From 4beff61db8c120d72246b8f66ce9f2a074fa5557 Mon Sep 17 00:00:00 2001 From: Christopher Hobbs Date: Wed, 27 Feb 2013 16:31:42 -0800 Subject: [PATCH] Push SRL 5 code as a starting point --- AUTHORS.txt | 11 + COPYING.txt | 674 ++++ README.md => README.txt | 0 SRL.simba | 229 ++ SRL/core/SRLlog.simba | 145 + SRL/core/amount.simba | 742 +++++ SRL/core/animation.simba | 435 +++ SRL/core/antiban.simba | 1615 +++++++++ SRL/core/antirandoms/abyss.simba | 80 + SRL/core/antirandoms/antirandoms.simba | 527 +++ SRL/core/antirandoms/beekeeper.simba | 269 ++ SRL/core/antirandoms/capnarnav.simba | 259 ++ SRL/core/antirandoms/certers.simba | 293 ++ SRL/core/antirandoms/common.simba | 333 ++ SRL/core/antirandoms/demon.simba | 274 ++ SRL/core/antirandoms/evilbob.simba | 441 +++ SRL/core/antirandoms/forester.simba | 344 ++ SRL/core/antirandoms/frog.simba | 423 +++ SRL/core/antirandoms/leo.simba | 41 + SRL/core/antirandoms/maze.simba | 412 +++ SRL/core/antirandoms/mime.simba | 435 +++ SRL/core/antirandoms/molly.simba | 860 +++++ SRL/core/antirandoms/mordaut.simba | 1526 +++++++++ SRL/core/antirandoms/pillory.simba | 349 ++ SRL/core/antirandoms/pinball.simba | 295 ++ SRL/core/antirandoms/prisonpete.simba | 44 + SRL/core/antirandoms/quiz.simba | 394 +++ SRL/core/antirandoms/randomtool.simba | 283 ++ SRL/core/antirandoms/rewards.simba | 370 +++ SRL/core/antirandoms/sandwich.simba | 134 + SRL/core/autocolor.simba | 360 ++ SRL/core/bank.simba | 2287 +++++++++++++ SRL/core/bitmaps.simba | 841 +++++ SRL/core/cautorespond.simba | 28 + SRL/core/chat.simba | 915 ++++++ SRL/core/color.simba | 593 ++++ SRL/core/flag.simba | 517 +++ SRL/core/gametab.simba | 4157 ++++++++++++++++++++++++ SRL/core/globals.simba | 851 +++++ SRL/core/globalstats.simba | 443 +++ SRL/core/inventory.simba | 1127 +++++++ SRL/core/login.simba | 1350 ++++++++ SRL/core/mapwalk.simba | 1507 +++++++++ SRL/core/math.simba | 1597 +++++++++ SRL/core/mouse.simba | 811 +++++ SRL/core/object.simba | 638 ++++ SRL/core/players.simba | 266 ++ SRL/core/rc.simba | 319 ++ SRL/core/simba.simba | 487 +++ SRL/core/symbol.simba | 1072 ++++++ SRL/core/text.simba | 1349 ++++++++ SRL/core/timing.simba | 981 ++++++ SRL/core/worldswitcher.simba | 783 +++++ SRL/misc/SmartGraphics.simba | 558 ++++ SRL/misc/SmartParams.simba | 425 +++ SRL/misc/arrayloader.simba | 344 ++ SRL/misc/buysell.simba | 338 ++ SRL/misc/debug.simba | 227 ++ SRL/misc/doorprofiles.simba | 299 ++ SRL/misc/draynorcolorfinder.simba | 303 ++ SRL/misc/dungeonwalk.simba | 169 + SRL/misc/findxp.simba | 1085 +++++++ SRL/misc/fontupdater.simba | 106 + SRL/misc/friends.simba | 318 ++ SRL/misc/grandexchange.simba | 647 ++++ SRL/misc/newautocolor.simba | 419 +++ SRL/misc/online.simba | 219 ++ SRL/misc/paintsmart.simba | 888 +++++ SRL/misc/path.simba | 204 ++ SRL/misc/quickchat.simba | 136 + SRL/misc/remote.simba | 159 + SRL/misc/reports.simba | 485 +++ SRL/misc/smart.simba | 167 + SRL/misc/smartcolors.simba | 638 ++++ SRL/misc/trade.simba | 413 +++ SRL/misc/users.simba | 1808 +++++++++++ SRL/misc/wizzyplugin.simba | 290 ++ SRL/misc/worlds.ini | 957 ++++++ SRL/skill/agility.simba | 40 + SRL/skill/construction.simba | 14 + SRL/skill/cooking.simba | 47 + SRL/skill/crafting.simba | 42 + SRL/skill/farming.simba | 14 + SRL/skill/fighting.simba | 252 ++ SRL/skill/firemaking.simba | 116 + SRL/skill/fishing.simba | 261 ++ SRL/skill/fletching.simba | 14 + SRL/skill/herblore.simba | 14 + SRL/skill/hunting.simba | 14 + SRL/skill/magic.simba | 1103 +++++++ SRL/skill/mining.simba | 795 +++++ SRL/skill/prayer.simba | 346 ++ SRL/skill/ranging.simba | 126 + SRL/skill/runecrafting.simba | 151 + SRL/skill/slayer.simba | 14 + SRL/skill/smithing.simba | 298 ++ SRL/skill/thieving.simba | 14 + SRL/skill/woodcutting.simba | 146 + SRLLape.simba | 87 + doc/DocPlaceHolder | 0 plugins/irokiplugin.lpi | 84 + plugins/irokiplugin.lpr | 2321 +++++++++++++ plugins/skyplugin.lpi | 72 + plugins/skyplugin.lpr | 1800 ++++++++++ tools/autocoloraid(ACA).exe | Bin 0 -> 313856 bytes 105 files changed, 55303 insertions(+) create mode 100644 AUTHORS.txt create mode 100644 COPYING.txt rename README.md => README.txt (100%) create mode 100644 SRL.simba create mode 100644 SRL/core/SRLlog.simba create mode 100644 SRL/core/amount.simba create mode 100644 SRL/core/animation.simba create mode 100644 SRL/core/antiban.simba create mode 100644 SRL/core/antirandoms/abyss.simba create mode 100644 SRL/core/antirandoms/antirandoms.simba create mode 100644 SRL/core/antirandoms/beekeeper.simba create mode 100644 SRL/core/antirandoms/capnarnav.simba create mode 100644 SRL/core/antirandoms/certers.simba create mode 100644 SRL/core/antirandoms/common.simba create mode 100644 SRL/core/antirandoms/demon.simba create mode 100644 SRL/core/antirandoms/evilbob.simba create mode 100644 SRL/core/antirandoms/forester.simba create mode 100644 SRL/core/antirandoms/frog.simba create mode 100644 SRL/core/antirandoms/leo.simba create mode 100644 SRL/core/antirandoms/maze.simba create mode 100644 SRL/core/antirandoms/mime.simba create mode 100644 SRL/core/antirandoms/molly.simba create mode 100644 SRL/core/antirandoms/mordaut.simba create mode 100644 SRL/core/antirandoms/pillory.simba create mode 100644 SRL/core/antirandoms/pinball.simba create mode 100644 SRL/core/antirandoms/prisonpete.simba create mode 100644 SRL/core/antirandoms/quiz.simba create mode 100644 SRL/core/antirandoms/randomtool.simba create mode 100644 SRL/core/antirandoms/rewards.simba create mode 100644 SRL/core/antirandoms/sandwich.simba create mode 100644 SRL/core/autocolor.simba create mode 100644 SRL/core/bank.simba create mode 100644 SRL/core/bitmaps.simba create mode 100644 SRL/core/cautorespond.simba create mode 100644 SRL/core/chat.simba create mode 100644 SRL/core/color.simba create mode 100644 SRL/core/flag.simba create mode 100644 SRL/core/gametab.simba create mode 100644 SRL/core/globals.simba create mode 100644 SRL/core/globalstats.simba create mode 100644 SRL/core/inventory.simba create mode 100644 SRL/core/login.simba create mode 100644 SRL/core/mapwalk.simba create mode 100644 SRL/core/math.simba create mode 100644 SRL/core/mouse.simba create mode 100644 SRL/core/object.simba create mode 100644 SRL/core/players.simba create mode 100644 SRL/core/rc.simba create mode 100644 SRL/core/simba.simba create mode 100644 SRL/core/symbol.simba create mode 100644 SRL/core/text.simba create mode 100644 SRL/core/timing.simba create mode 100644 SRL/core/worldswitcher.simba create mode 100644 SRL/misc/SmartGraphics.simba create mode 100644 SRL/misc/SmartParams.simba create mode 100644 SRL/misc/arrayloader.simba create mode 100644 SRL/misc/buysell.simba create mode 100644 SRL/misc/debug.simba create mode 100644 SRL/misc/doorprofiles.simba create mode 100644 SRL/misc/draynorcolorfinder.simba create mode 100644 SRL/misc/dungeonwalk.simba create mode 100644 SRL/misc/findxp.simba create mode 100644 SRL/misc/fontupdater.simba create mode 100644 SRL/misc/friends.simba create mode 100644 SRL/misc/grandexchange.simba create mode 100644 SRL/misc/newautocolor.simba create mode 100644 SRL/misc/online.simba create mode 100644 SRL/misc/paintsmart.simba create mode 100644 SRL/misc/path.simba create mode 100644 SRL/misc/quickchat.simba create mode 100644 SRL/misc/remote.simba create mode 100644 SRL/misc/reports.simba create mode 100644 SRL/misc/smart.simba create mode 100644 SRL/misc/smartcolors.simba create mode 100644 SRL/misc/trade.simba create mode 100644 SRL/misc/users.simba create mode 100644 SRL/misc/wizzyplugin.simba create mode 100644 SRL/misc/worlds.ini create mode 100644 SRL/skill/agility.simba create mode 100644 SRL/skill/construction.simba create mode 100644 SRL/skill/cooking.simba create mode 100644 SRL/skill/crafting.simba create mode 100644 SRL/skill/farming.simba create mode 100644 SRL/skill/fighting.simba create mode 100644 SRL/skill/firemaking.simba create mode 100644 SRL/skill/fishing.simba create mode 100644 SRL/skill/fletching.simba create mode 100644 SRL/skill/herblore.simba create mode 100644 SRL/skill/hunting.simba create mode 100644 SRL/skill/magic.simba create mode 100644 SRL/skill/mining.simba create mode 100644 SRL/skill/prayer.simba create mode 100644 SRL/skill/ranging.simba create mode 100644 SRL/skill/runecrafting.simba create mode 100644 SRL/skill/slayer.simba create mode 100644 SRL/skill/smithing.simba create mode 100644 SRL/skill/thieving.simba create mode 100644 SRL/skill/woodcutting.simba create mode 100644 SRLLape.simba create mode 100644 doc/DocPlaceHolder create mode 100644 plugins/irokiplugin.lpi create mode 100644 plugins/irokiplugin.lpr create mode 100644 plugins/skyplugin.lpi create mode 100644 plugins/skyplugin.lpr create mode 100644 tools/autocoloraid(ACA).exe diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 0000000..3efd872 --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1,11 @@ +Benjamin Land +Cohen Adair +Kevin Brightwell +Mark Janse +Merlijn Wajer +Niels AD +Axel Schmidt Selmer-Anderssen +Colby Nagle +Chris Hobbs +David Mendes +Nathan Hartung diff --git a/COPYING.txt b/COPYING.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.txt similarity index 100% rename from README.md rename to README.txt diff --git a/SRL.simba b/SRL.simba new file mode 100644 index 0000000..69a22c3 --- /dev/null +++ b/SRL.simba @@ -0,0 +1,229 @@ +//----------------------------------------------------------------------------// +//-- SRL Resource Library --// +//----------------------------------------------------------------------------// +//-- by: Azeroth, Bebe, BenLand100, benleegt, Boreas, c0de, Cheesehunk --// +//-- Coh3n, dakota, Dankness, driger1592, EvilChicken!, Flyboy, --// +//-- Freddy1990, Hobbit, IceFire908, inferno, Kernel Klink, Knightstreak, --// +//-- Krazy_Meerkat, Krichevskoy, Liquid, Lorax, lordsaturn, Mad Cow, --// +//-- marpis, Markus, masquerader, mastaraymond, moparisthebest, --// +//-- Mutant Squirrle, n3ss3s, N1ke, Naum, Nava2, NCDS, nielsie95, --// +//-- phantombmx, pups, Pyro, RAM, Rasta Magician, realrune, Renax, Ron, --// +//-- RsN, SKy Scripter, solemn wishes, Spky, SRL, Starblaster100, --// +//-- Stupid3ooo,Sumilion, tarajunky, The Claw, The_Rs_Monkey, TRiLeZ, --// +//-- Wizzup?, WT-Fakawi, XxKanexX, Yakman, YoHoJo, ZephyrsFury, _ChArMz, --// +//-- --// +//-- ....... and the SRL Community. --// +//----------------------------------------------------------------------------// + +//----------------------------------------------------------------------------// +//-- SRL Level 1 Includes --// +//-- --// +//-- Low Level SCAR Math, Mouse Movement and Color routines. --// +//----------------------------------------------------------------------------// + +// For development: +//{$DEFINE CompileSRL} + +{$DEFINE SRL5} + +{$IFDEF Lape} +{$include SRLLape.simba} +{$ENDIF} + +{$IFDEF SMART8} + {$IFNDEF SMART} + {$DEFINE SMART} + {$ENDIF} +{$ENDIF} + +{$IFDEF SMART} +{$IFNDEF SRL_SMART} + {$IFDEF SIMBAMAJOR980} + {$I SRL/SRL/Misc/Smart.Simba} + {$ELSE} + Procedure ActivateClient; {$IFDEF LAPE}override;{$ENDIF} begin end; + {$ENDIF} +{$ENDIF} +{$ENDIF} + +//{$include SRL/SRL/core/defines.simba} +{$ifdef Simba} +{$i SRL/SRL/core/simba.simba} +{$endif} +{$include SRL/SRL/core/globals.simba} +{$include SRL/SRL/core/math.simba} +{$include SRL/SRL/core/mouse.simba} +{$include SRL/SRL/core/color.simba} +{$include SRL/SRL/core/players.simba} + +//----------------------------------------------------------------------------// +//-- SRL Level 2 Includes --// +//-- --// +//-- Interface and OCR routines. --// +//----------------------------------------------------------------------------// + +{$include SRL/SRL/core/text.simba} +{$include SRL/SRL/core/timing.simba} +{$include SRL/SRL/core/SRLlog.simba} +{$include SRL/SRL/core/chat.simba} +{$include SRL/SRL/core/bitmaps.simba} +{$include SRL/SRL/core/amount.simba} +{$include SRL/SRL/core/gametab.simba} + +//----------------------------------------------------------------------------// +//-- SRL Level 3 Includes --// +//-- --// +//-- MapWalking, AntiRandoms, Objects, Bank, Symbol and many more... --// +//----------------------------------------------------------------------------// + +{$include SRL/SRL/core/animation.simba} +{$include SRL/SRL/core/flag.simba} +{$include SRL/SRL/core/worldswitcher.simba} +{$include SRL/SRL/core/login.simba} +{$include SRL/SRL/core/autocolor.simba} +{$include SRL/SRL/core/mapwalk.simba} +{$include SRL/SRL/core/object.simba} +{$include SRL/SRL/core/inventory.simba} +{$include SRL/SRL/core/bank.simba} +{$include SRL/SRL/core/symbol.simba} +{$include SRL/SRL/core/rc.simba} +{$include SRL/SRL/core/cautorespond.simba} +{$include SRL/SRL/core/antiban.simba} +{$include SRL/SRL/core/globalstats.simba} + +{$include SRL/SRL/core/antirandoms/antirandoms.simba} + +{$IFDEF LoadExtraFonts} +{$include SRL/SRL/misc/fontupdater.simba} +{$ENDIF} + +{$IFNDEF SIMBAMAJOR980} +{$IFDEF SMART} + {$IFNDEF SRL_SMART} + {$include SRL/SRL/misc/SmartParams.Simba} + {$ENDIF} +{$ENDIF} +{$ENDIF} + +{$DEFINE SRL_OPENDEV} +{******************************************************************************* +procedure FreeSRL; +by: SRL Dev Team +Description: Tries to free all the variables it allocated during runtime. +*******************************************************************************} +procedure FreeSRL; +begin + FreeSRLBitmaps; + FreeSRLFonts; +end; + +{******************************************************************************* +procedure SetupSRL; +by: SRL Dev Team +Last Edit: 22 June 2010 -- Nava2 +Description: Sets up all variables needed to run SRL. +*******************************************************************************} + +procedure SetupSRL; +var + t: Integer; +begin + {$IFNDEF SMART} + {$IFDEF SIMBA} + if (not IsTargetValid) then + srl_Warn('SetUpSRL', 'Target client is not valid! ' + + 'Drag the crosshairs over the target client.', warn_Terminate); + {$ENDIF} + {$ENDIF} + SetupBoxes; //Sets up box variables in globals.simba + t := GetTimeRunning; + MouseSpeed := 15; + {$IFDEF UseLaptopMouse}LMouse_MissChance := 75;{$ENDIF} + CheckHPFirst := True; + Reincarnate := False; + TalkAfterRandoms := False; + RoadColor := 0; + WaterColor := 0; + BankColor := 0; + + // these need to be removed eventually (no longer used) + SRL_OnFindRandomCall := nil; + LampSkill := 'mining'; + + //SetUpSRLReport; + LoadCosineArrays; + SymbolAccuracy:= 0.8; + LoadSRLBitMaps; + LoadSRLFonts; + {$IFNDEF SRL_RANDOMS_TEST} + _SetRandoms(); + {$ENDIF} + SetupSRLAutoResponder; + SRL_RandomScreenShot := False; + UseFindMod := True; + LogoutOnMod := True; + UseFindTrade := True; + UseAutoResponder := True; + GraphicsSet := False; + AllowPVP := False; + SRL_DisableIPLog := false; + SRL_SavePath := includePath + 'SRL/logs/'; + SRL_StartTime := theDate(DATE_MONTH)+' at '+theTime; + WarnSensitivity := -2; + SetupAutoColors; + +{$IFDEF LoadExtraFonts} + srl_UpdateFonts(srl_FontsUp2date); +{$ENDIF} + + AddOnTerminate('FreeSRL'); + SetSupressExceptions(true); + Writeln ('SRL Compiled in '+ IntToStr(GetTimeRunning - t) + ' msec'); + + {$IFDEF SRL_SMART} + {$IFDEF SIMBAMAJOR980} + if (Smart_Server = 0) then + begin + Smart_Server := RandomWorld(Smart_Members, False); + Smart_Signed := True; + Smart_SuperDetail := False; + end; + Writeln('SMART Initialized.' + #10 + 'Loaded: Server ' + IntToStr(Smart_Server) + ', Members: ' + BoolToStr(Smart_Members) + + ', Signed: ' + BoolToStr(Smart_Signed) + ', Super Detail: ' + BoolToStr(Smart_SuperDetail) + '.'); + SmartSetupEx(Smart_Server, Smart_Members, Smart_Signed, Smart_SuperDetail); + SetTargetArray(SmartImageArray, 765, 553); + {$ELSE} + SetupSmart(Smart_ForceNew); + if (SRL_SixHourFix) then + SRL_Procs[srl_OnRSUpdate] := @SixHourFix; + {$ENDIF} + + repeat + {$IFNDEF SIMBAMAJOR980} + {$IFDEF SMART} + If Smart_FixSpeed then + FixSmartSpeed; + {$ENDIF} + {$ENDIF} + Wait(100); + if (GetTimeRunning - t) > 120000 then + Break; + until(RSReady); + {$ENDIF} + + SetupGauss; + SRL_ResetNavBar; + Proc_WorldSwitcherEnabled +end; + +{$ifdef CompileSRL} +begin + SetupSRL; +end. +{$endif} + +{$ifdef LAPE} +begin + SetupSRL; +end. +{$endif} diff --git a/SRL/core/SRLlog.simba b/SRL/core/SRLlog.simba new file mode 100644 index 0000000..2b06edf --- /dev/null +++ b/SRL/core/SRLlog.simba @@ -0,0 +1,145 @@ +(* + +SRL Debug Log +============= + +Routines that write to the SRL log file. + +.. contents:: + +*) + +var + SRL_SavePath: string; // the path to save log files + SRL_StartTime: string; // the time the script starts (used to name log file) + SRL_DisableLogging: boolean; // gives the scripter the option to disable + +(* +TakeScreen +~~~~~~~~~~ + +.. code-block:: pascal + + procedure TakeScreen(Reason: string); + +Sets up Box variables + +.. note:: + + by Mutant, Squirrle, Yakman, & Harry + Last Modified: Feb. 16th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + TakeScreen('Prison Pete'); + +*) +procedure TakeScreen(Reason: string); +begin + if (not DirectoryExists(SRL_SavePath)) then + ForceDirectories(SRL_SavePath); + + try + if FileExists(SRL_SavePath + reason + ' ' + Players[CurrentPlayer].Name + '.png') then + SaveScreenshot(SRL_SavePath + reason + ' ' + Players[CurrentPlayer].Name + ' ' + TimeRunning + '.png') + else + SaveScreenshot(SRL_SavePath + reason + ' ' + Players[CurrentPlayer].Name + '.png'); + + WriteLn('Screenshot of: ' + reason + ' ' + TimeRunning); + except + Writeln('Failed to save screenshot of: ' + reason); + end +end; + +(* +OpenSRLLogFile +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function OpenSRLLogFile(): integer; + +Creates the SRL log file. + +.. note:: + + by Coh3n + Last Modified: Feb. 20th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + OpenSRLLogFile(); + +*) +function OpenSRLLogFile(): integer; +var + fileName: string; +begin + if (SRL_DisableLogging) then + exit; + + if (not directoryExists(SRL_SavePath)) then + forceDirectories(SRL_SavePath); + + // make sure it's a valid file name (Windows) + fileName := 'SRL log ('+SRL_StartTime+').txt'; + fileName := replace(fileName, '/', '-'); + fileName := replace(fileName, ':', ' '); + fileName := SRL_SavePath + fileName; + + try + if (fileExists(fileName)) then + result := appendFile(fileName) + else + result := createFile(fileName); + except + writeln('OpenSRLLogFile: '+exceptionToString(exceptionType, exceptionParam)); + end; +end; + +(* +AddToSRLLog +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure AddToSRLLog(s : string); + +Writes the string 's' to the SRL log file. + +.. note:: + + by Markus + Last Modified: Feb. 20th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + AddToSRLLoc('Adding to SRL log file!'); + +*) +procedure AddToSRLLog(s: string); +var + tmpFile: integer; +begin + writeln(s); + + if (SRL_DisableLogging) then + exit; + + tmpFile := openSRLLogFile(); + + if (tmpFile >= 0) then + try + writeFileString(tmpFile, '['+msToTime(getTimeRunning(), TIME_BARE)+']: '+s+#13+#10); + except + SRL_Warn('AddToSRLLog', 'Could not write to logfile: '+exceptionToString(exceptionType, exceptionParam), WARN_ALLVERSIONS); + finally + closeFile(tmpFile); + end; +end; diff --git a/SRL/core/amount.simba b/SRL/core/amount.simba new file mode 100644 index 0000000..f7bcde1 --- /dev/null +++ b/SRL/core/amount.simba @@ -0,0 +1,742 @@ +(* +Amount +====== + +The Amount include contains all kinds of functions to get the amount of items. +Items can be in your bank or in your inventory. + +.. contents:: + + +*) + +function DepositScreen: Boolean; forward; + +(* +TradeScreen +~~~~~~~~~~~ + +.. code-block:: pascal + + function TradeScreen: Integer; + +Returns 1 if the first trade screen is open, 2 if the second, and 0 if neither +is open. + +.. note:: + + Author: ZephyrsFury + Last Modified: 12/7/11 by Legoace + +Example: + +.. code-block:: pascal + + if (TradeScreen > 0) then + writeln('Trade screen is open!'); +*) +function TradeScreen: Integer; +begin + for Result := 2 downto 1 do + case Result of + 2: if (CountColor(16776960, 127, 32, 373, 51) > 20) then Break; + 1: if (CountColor(2070783, 150, 12, 350, 28) > 20) then Break; + end; +end; + +(* +ShopScreen +~~~~~~~~~~ + +.. code-block:: pascal + + Function ShopScreen : Boolean; + +Returns true if the shop screen is open. + +.. note:: + + Author: ZephyrsFury + Last Modified: Unknown by NCDS + +Example: + +.. code-block:: pascal + + if (ShopScreen) then + writeln('Shop screen is open!'); +*) +Function ShopScreen : Boolean; +Begin + Result := FindTextTPA(2070783, 10, 58, 303, 85, 317, 'Right', StatChars, Nothing); +End; + +(* +FindItemEx +~~~~~~~~~~ + +.. code-block:: pascal + + function FindItemEx(var x, y: Integer; IdentType: string; Ident: Integer; Area: TBox; Tol: TIntegerArray): Boolean; + +Finds an item in a specified box (Area). Returns its coordinates (x, y). +Valid IdentTypes are: + + - 'bmp', 'mask', 'color', 'dtm' + +The Tol variable is: + + Tol[0] : Color Tolerance; + Tol[1] : Contour Tolerance or minimum Colors to Find to be True. + +.. note:: + + Author: Nava2 + Last Modified: 13 Jan 2011 by Nava2 + +Example: + +.. code-block:: pascal + + var + x, y: Integer; + b: TBox; + begin + b:= IntToBox(MIX1, MIY1, MIX2, MIY2); + if (FindItemEx(x,y, 'bmp, the_bmp, b, [4])) then + Mouse(x, y, 5, 5, true); + end; +*) +function FindItemEx(var x, y: Integer; IdentType: string; Ident: Integer; Area: TBox; Tol: TIntegerArray): Boolean; +var + Pts: TPointArray; +begin + Result := False; + SetLength(Tol, 2); + case Lowercase(IdentType) of + 'bitmap mask', 'bmpmask', 'bmp mask', 'mask': Result := FindBitmapMaskTolerance(Ident, x, y, Area.x1, Area.y1, Area.x2, Area.y2, Tol[0], Tol[1]); + 'bitmap', 'bmp': Result := FindBitmapToleranceIn(Ident, x, y, Area.x1, Area.y1, Area.x2, Area.y2, Tol[0]); + 'dtm': Result := FindDTM(Ident, x, y, Area.x1, Area.y1, Area.x2, Area.y2); + 'colour', 'color': + begin + FindColorsTolerance(Pts, Ident, Area.x1, Area.y1, Area.x2, Area.y2, Tol[0]); + if Tol[1] < 1 then Tol[1] := 1; + Result := Length(Pts) >= Tol[1]; + if Result then + MiddleTPAEx(Pts, x, y); + end; + else + SRL_Warn('FindItem', 'Invalid identifier input as IdentType.', -1); + end; +end; + +(* +FindItem +~~~~~~~~ + +.. code-block:: pascal + + function FindItem(var x, y: Integer; IdentType: string; Ident: Integer; x1, y1, x2, y2: Integer; Tol: TIntegerArray): Boolean; + +This function is exactly the same as FindItemEx except it takes integer +coordinates (x1, y1, x2, y2) rather than an TBox. + +.. note:: + + Author: Nava2 + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + var + x, y: Integer; + begin + if (FindItem(x,y, 'bmp, the_bmp, MIX1, MIY1, MIX2, MIY2, [4])) then + Mouse(x, y, 5, 5, true); + end; +*) +function FindItem(var x, y: Integer; IdentType: string; Ident: Integer; x1, y1, x2, y2: Integer; Tol: TIntegerArray): Boolean; +begin + Result := FindItemEx(x, y, IdentType, Ident, IntToBox(x1, y1, x2, y2), Tol); +end; + +(* +GetAmountBox +~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetAmountBox(box: TBox): integer; + +Returns the amount of an item at in the box 'box'. Returns approximate values +for 'K' and 'M'. + +.. note:: + + Author: Zeph, N1ke & Narcle + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + var + i: Integer; + begin + i := GetAmountBox(InvBox(1)); // Gets the amount in inventory slot 1 + Writeln('Amount = '+toStr(i)); + end; +*) +function GetAmountBox(box: TBox): integer; +var + Col: TIntegerArray; + X, Y, I: Integer; + B: TBox; + TPA: TPointArray; + S: String; +begin + Result := 0; + + If Not FindColor(X, Y, srl_outline_black, box.x1, box.y1, box.x2, box.y2) then + Exit; + Inc(Result); + Col := [65535, 65278, 16777215, 8453888]; + + For I := 0 to High(Col) do + If FindColor(X, Y, Col[I], box.x1, box.y1, box.x2, box.y2)then + begin + FindColors(TPA, Col[i], box.x1, box.y1, box.x2, box.y2); + B := GetTPABounds(TPA); + //SMART_DrawBoxEx(False, b, clYellow); + B := IntToBox(b.x1-2, b.y1-2, b.x2+2, b.y2+2); + S := GetTextAtExWrap(b.x1, b.y1, b.x2, b.y2, 0, 1, 1, Col[i], 0, StatChars); + Result := StrToIntDef(GetNumbers(S), 1); + Case I of + 2: Result := Result * 1000; + 3: Result := Result * 1000000; + end; + Exit; + end; +end; + +(* +GetAmount +~~~~~~~~~ + +.. code-block:: pascal + + function GetAmount(x, y: integer): integer; + +Returns the amount of an item at inventory coordinates (x, y). + +.. note:: + + Author: Coh3n + +Example: + +.. code-block:: pascal + + var + amount, x, y: integer; + + begin + if (findDTM(x, y, dtm_Hatchet, MIX1, MIY1, MIX2, MIY2)) then + begin + amount := GetAmount(x, y); + writeln('amount: '+toStr(amount)); + end; + end; +*) +function InvBox(i: integer): TBox; forward; +function CoordsToItem(x, y: integer): integer; forward; +function GetAmount(x, y: integer): integer; +begin + result := getAmountBox(invBox(coordsToItem(x, y))); +end; + +(* +AreaInfo +~~~~~~~~ + +.. code-block:: pascal + + procedure AreaInfo(area: String; var startx, starty, rowsize, colsize, colnumber, rownumber: Integer); + +Returns information on certain interfaces. Valid interfaces (area): + + - 'inv' + - 'inventory' + - 'trade' + - 'your trade' + - 'bank' + - 'shop' + - 'deposit box' + +.. note:: + + Author: masquerader + +Example: + +.. code-block:: pascal + + var + info: array[0..5] of integer; + begin + AreaInfo('inv', info[0], info[1], info[2], info[3], info[4], info[5]); + end; +*) +procedure AreaInfo(area: string; var startx, starty, rowsize, colsize, colnumber, rownumber: Integer); +begin + case LowerCase(area) of + 'inv', 'inventory': begin + startx := 560; + starty := 212; + + rowsize := 36; + colsize := 42; + + colnumber := 4; + rownumber := 7; + end; + 'shop': begin + startx := 63; + starty := 97; + + rowsize := 55; + colsize := 39; + + colnumber := 10; + rownumber := 4; //? + end; + 'bank': begin + startx := 35; + starty := 91; + + rowsize := 44; + colsize := 44; + + colnumber := 10; + rownumber := 5; + end; + 'deposit box': begin + startx := 97; + starty := 60; + + rowsize := 48; + colsize := 50; + + colnumber := 7; + rownumber := 4; + end; + 'trade': begin + startx := 310; + starty := 75; + + rowsize := 32; + colsize := 49; + + colnumber := 4; + rownumber := 7; + end; + 'your trade': begin + startx := 24; + starty := 75; + + rowsize := 32; + colsize := 49; + + colnumber := 4; + rownumber := 7; + end; + else srl_Warn('AreaInfo', Area + ' is an invalid option', warn_AllVersions); + end; +end; + +(* +CheckArea +~~~~~~~~~ + +.. code-block:: pascal + + function CheckArea(area: String): Boolean; + +Checks if the given area is opened. + +.. note:: + + Author: masquerader + Last Modified: Unknown by EvilChicken + +Example: + +.. code-block:: pascal + + if (CheckArea('shop')) then + WriteLn('Shop is open!'); +*) +function CheckArea(area: string): Boolean; +begin + Result := false; + case LowerCase(area) of + 'inv', 'inventory': begin + Result := (BankScreen) or (ShopScreen) or (TradeScreen > 0); + if (not(Result)) then Result := GameTab(tab_Inv); + end; + 'shop': Result := ShopScreen; + 'bank': Result := BankScreen; + 'deposit box': Result := DepositScreen; + 'trade', 'your trade': Result := (TradeScreen > 0); + else + srl_Warn('CheckArea', Area + ' is an invalid option.', warn_AllVersions); + end; + if (Result = False) then + WriteLn('PROBLEM: ' + area + ' interface not open'); +end; + +(* +ItemCoordinates +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ItemCoordinates(Area, ItemType: string; Item, Tol: TIntegerArray): TPointArray; + +Returns a TPA with the positions of all occurances of the item. +Parameters: + + Area: 'inv', 'shop', 'bank', 'trade', 'your trade'. + ItemType: DTM, Color, BitmapMask, Bitmap + Item: name/value of your dtm/bmp/color/bmpmask. + + Tol: + 'dtm' - [] (dtm's can't have tolerance). + 'bmp' - [BMPTol]. + 'color' - [COLOUR Tol, Minimum Colour Count]. + 'bmpmask' - [BMPTol, ContourTol]. + +.. note:: + + Author: masquerader + Last Modified: Unknown by ZephyrsFury + +Example: + +.. code-block:: pascal + + if (Length(ItemCoordinates('inv', 'dtm', dtm_Hatchet, []) > 0) then + Writeln('Hatchet found!'); +*) +function ItemCoordinates(Area, ItemType: string; Item: Integer; Tol: TIntegerArray): TPointArray; +var + startx, starty, rowsize, colsize, colnumber, rownumber, col, row: Integer; + x1, y1, x2, y2: Integer; + itemx, itemy, L: Integer; +begin + if (CheckArea(area)) then + begin + AreaInfo(area, startx, starty, rowsize, colsize, colnumber, rownumber); + SetLength(Result, RowNumber * ColNumber); + for row := 0 to rownumber - 1 do + for col := 0 to colnumber - 1 do + begin + x1 := startx + col * colsize; + y1 := starty + row * rowsize; + x2 := x1 + colsize; + y2 := y1 + rowsize; + if FindItem(Itemx, Itemy, ItemType, Item, x1, y1, x2, y2, Tol) then + begin + Result[L].x := ItemX; + Result[L].y := ItemY; + Inc(L); + end; + end; + end; + SetLength(Result, L); +end; + +(* +CountItemsIn +~~~~~~~~~~~~ + +.. code-block:: pascal + + function CountItemsIn(Area, ItemType: string; Item: Integer; Tol: TIntegerArray): Integer; + +Counts the number of items found within the Area (does not count stacks). +Parameters are exactly the same as ItemCoordinates. + +.. note:: + + Author: masquerader + Last Modified: Unknown by ZephyrsFury + +Example: + +.. code-block:: pascal + + var + itemsFound: integer; + begin + itemsFound := CountItemsIn('inv', 'dtm', dtm_Ore, []); + writeln('Ore found: ' + toStr(itemsFound)); + end; +*) +function CountItemsIn(area, ItemType: string; Item: Integer; Tol: TIntegerArray): Integer; +begin + Result := Length(ItemCoordinates(Area, ItemType, Item, Tol)); +end; + +(* +CountItemsArea +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function CountItemsArea(area: string): Integer; + +Counts the number of items (no matter which item) found in the given area. Looks +for the black outline color. + +.. note:: + + Author: masquerader + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + var + itemsFound: integer; + begin + itemsFound := CountItemsArea('inv'); + writeln('Items found: '+toStr(itemsFound)); + end; +*) +function CountItemsArea(area: string): Integer; +begin + Result := CountItemsIn(area, 'colour', srl_outline_black, [0, 1]); +end; + +(* +ItemAmount +~~~~~~~~~~ + +.. code-block:: pascal + + function ItemAmount(area, ItemType: string; Item: Integer; Tol: TIntegerArray): Integer; + +Counts the number of items found within the Area (counts stacks). +Parameters are exactly the same as ItemCoordinates. + +.. note:: + + Author: masquerader + Last Modified: Unknown by ZephyrsFury + +Example: + +.. code-block:: pascal + + var + itemsFound: integer; + begin + itemsFound := ItemAmount('inv', 'dtm', dtm_Ore, []); + writeln('Ore found: '+toStr(itemsFound)); + end; +*) +function ItemAmount(area, ItemType: string; Item: Integer; Tol: TIntegerArray): Integer; +var + startX, startY, rowSize, colSize, colNumber, rowNumber: integer; + Coords: TPointArray; + i, h: Integer; +begin + Result := 0; + AreaInfo(area, startX, startY, rowSize, colSize, colNumber, rowNumber); + Coords := ItemCoordinates(Area, ItemType, Item, Tol); + h := High(Coords); + for i := 0 to h do + Result := Result + GetAmountBox(IntToBox(Coords[i].x - floor(rowSize / 2), + Coords[i].y - floor(colSize / 2), + Coords[i].x + floor(rowSize / 2), + Coords[i].y + floor(colSize / 4))); +end; + +(* +FindCoins +~~~~~~~~~ + +.. code-block:: pascal + + function FindCoins(var X, Y: Integer; Area: string): Boolean; + +Returns true if coins are found in the given area (Area). If found, stores their +coordinates in X, Y. + +.. note:: + + Author: ZephyrsFury + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + var + x, y: integer; + begin + if (FindCoins(x, y, 'inv')) then + WriteLn('Coins found: '+toStr(GetAmount(x, y))); + end; +*) +function FindCoins(var X, Y: Integer; Area: string): Boolean; +var + B: TBox; + CTS, I, J, H, L: Integer; + Pts, tPts: TPointArray; + ATPA: T2DPointArray; + V: array [0..1] of TVariantArray; +begin + case Lowercase(Area) of + 'inv', 'inventory': B := IntToBox(MIX1, MIY1, MIX2, MIY2); + 'bank': B := IntToBox(MBx1, MBy1, MBx2, MBy2); + 'trade': B := IntToBox(323, 73, 509, 302); + 'your trade': B := IntToBox(9, 73, 196, 302); + end; + V[0] := [1606307, 4, 0.09, 1.32]; //Darker colour (top of coins) + V[1] := [2209251, 8, 0.04, 1.08]; //Lighter colour (rest of the coins) + CTS := GetColorToleranceSpeed; + ColorToleranceSpeed(2); + SetLength(tPts, 0); + try + for I := 0 to 1 do + begin + SetColorSpeed2Modifiers(V[I][2], V[I][3]); + FindColorsTolerance(Pts, V[I][0], B.X1, B.Y1, B.X2, B.Y2, V[I][1]); + if (Length(Pts) < 10) then Exit; + ATPA := SplitTPAEx(Pts, 10, 10); + h := High(ATPA); + L := High(tPts) + 1; + SetLength(tPts, L + h + 1); + for J := 0 to H do + tPts[L + j] := MiddleTPA(ATPA[J]); + end; + ATPA := SplitTPAEx(tPts, 20, 20); + H := High(ATPA); + for I := 0 to H do + if (High(ATPA[I]) = 1) then + Break; + if (I > H) then Exit; + Result := True; + MiddleTPAEx(ATPA[I], X, Y); + finally + ColorToleranceSpeed(CTS); + SetColorSpeed2Modifiers(0.2, 0.2); + end; +end; + +(* +CoinAmount +~~~~~~~~~~ + +.. code-block:: pascal + + function CoinAmount(Area: string): Integer; + +Returns the amount of coins found in the given area. + +.. note:: + + Author: ZephyrsFury + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + WriteLn('Coins found: '+toStr(CoinAmount('inv'))); +*) +function CoinAmount(Area: string): Integer; +var + X, Y: Integer; +begin + if (FindCoins(X, Y, Area)) then + Result := GetAmount(X, Y); +end; + +(* +RuneAmount +~~~~~~~~~~ + +.. code-block:: pascal + + function RuneAmount(area, runetype: String): Integer; + +Returns the amount of a certain rune in the specified area. + +.. note:: + + Author: masquerader + Last Modified: Unknown by ZephyrsFury + +Example: + +.. code-block:: pascal + + WriteLn('Air runes found: '+toStr(RuneAmount('inv', 'air'))); +*) +function RuneAmount(Area, RuneType: string): Integer; +var + RuneBmp, II: Integer; + RuneNames: TStringArray; +begin + RuneNames := ['air', 'mind', 'water', 'fire', 'earth', 'law', 'nature', 'chaos', 'death', 'body', 'cosmic', 'soul', 'blood']; + if (InStrArrEx(Lowercase(RuneType), RuneNames, II)) then + begin + RuneBmp := srl_GetBitmap(18 + II); + Result := ItemAmount(Area, 'bmp', RuneBmp, [20]); + FreeBitmap(RuneBmp); + end else + srl_Warn('RuneAmount', 'Invalid RuneType: ''' + RuneType + '''', warn_AllVersions); +end; + +(* +ShopSwitchTab +~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure ShopSwitchTab(Name: string); + +Switches the shop tab to the one you want, only moves mouse if neccessary. +Valid arguments are: + + - ShopSwitchTab('main') + - ShopSwitchTab('player') + +.. note:: + + Author: Rasta Magician & ZephyrsFury + Last Modified: Unknown by ZephyrsFury + +Example: + +.. code-block:: pascal + + ShopSwitchTab('main'); + +*) +procedure ShopSwitchTab(Name: string); +begin + if (not(InStrArr(Name, ['main', 'player'], False))) then + begin + srl_Warn('ShopSwitchTab', 'Name: ' + Name + ' is not a valid tab.', warn_AllVersions); + Exit; + end; + if (ShopScreen) then + FindTextTpa(1930687, 0, 50, 65, 225, 83, Capitalize(Name), SmallChars, ClickLeft); +end; diff --git a/SRL/core/animation.simba b/SRL/core/animation.simba new file mode 100644 index 0000000..07df35e --- /dev/null +++ b/SRL/core/animation.simba @@ -0,0 +1,435 @@ +(* +Animation +========= + + +.. contents:: + + +*) + +(* +PixelShiftMulti +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function PixelShiftMulti(B: TBoxArray; T: Integer): TIntegerArray; + +Calculates how many pixels change in boxes B during time T. + +.. note:: + + Author: marpis + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + PixelShiftArray := PixelShiftMulti(box, 5000); +*) +function PixelShiftMulti(B: TBoxArray; T: Integer): TIntegerArray; +Var + L, I: Integer; + BMP, BMP2: TIntegerArray; +begin + L := Length(B); + SetLength(BMP, L); + SetLength(BMP2, L); + SetLength(Result, L); + + for I := 0 to (L - 1) do + BMP[I] := BitmapFromClient(B[i].x1,B[i].y1,B[i].x2,B[i].y2); + Wait(T); + for I := 0 to (L - 1) do + BMP2[I] := BitmapFromClient(B[i].x1,B[i].y1,B[i].x2,B[i].y2); + for i := 0 to (L - 1) do + result[i] := CalculatePixelShift(BMP[i],BMP2[i],IntToBox(0,0,(b[i].x2 - b[i].x1),(b[i].y2-b[i].y1))); + for I := 0 to (L - 1) do + begin + FreeBitmap(BMP[I]); + FreeBitmap(BMP2[I]); + end; +end; + +(* +PixelShift +~~~~~~~~~~ + +.. code-block:: pascal + + function PixelShift(B: TBox; T: Integer): Integer; + +Calculates how many pixels change in boxes B during time T. + +.. note:: + + Author: marpis + Last Modified: Nov. 29, 2009 + +Example: + +.. code-block:: pascal + + Result := (PixelShift(box, 5000) > 2000); +*) +function PixelShift(B: TBox; Time: Integer): Integer; +var + TIA: TIntegerArray; +begin + TIA := PixelShiftMulti([B], Time); + Result := TIA[0]; +end; + +(* +AveragePixelShift +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function AveragePixelShift(B: TBox; waitPerloop, maxTime: Integer): Integer; + +Gets the average pixel shift every 'waitPerLoop' ms over the time 'maxTime' + +.. note:: + + Author: Coh3n + Last Modified: Mar. 31st, 2011 + +Example: + +.. code-block:: pascal + + Result := (AveragePixelShift(box, 500, 5000) > 2000); +*) +function AveragePixelShift(b: TBox; waitPerLoop, maxTime: integer): integer; +var + t: integer; + shifts: TIntegerArray; +begin + t := (getSystemTime + maxTime); + + while (getSystemTime < t) do + begin + setLength(shifts, length(shifts)+1); + shifts[high(shifts)] := pixelShift(b, waitPerLoop); + end; + + result := averageTIA(shifts); +end; + +(* +ReturnGridColorsInBox +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ReturnGridColorsInBox(Box : TBox): T2DIntegerArray; + +Returns a 2D color array from the pixels contained by Box. + +.. note:: + + Author: m34tcode + Last Modified: 4/7/2012 +*) +function ReturnGridColorsInBox (Box : TBox) : T2DIntegerArray; +var + x,y : Integer; +begin + SetArrayLength(Result,box.X2-box.X1); + for x := 0 to box.X2-box.X1-1 do + begin + SetArrayLength(Result[x],box.Y2-box.Y1); + for y := 0 to box.Y2-box.Y1-1 do + begin + Result[x][y] := GetColor(x+box.X1,y+box.Y1); + end; + end; +end; + +(* +ValidatePixels +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure ValidatePixels(Box : TBox; OrigCols : T2DIntegerArray; BoolArr : array of TBoolArray; Tolerance : Integer); + +Checks for which pixels, in OrigCols, have changed +beyond the specified tolerance, since the last check + +.. note:: + + Author: m34tcode + Last Modified: 4/7/2012 +*) +procedure ValidatePixels(Box : TBox; OrigCols : T2DIntegerArray; BoolArr : array of TBoolArray; Tolerance : Integer); +var + X,Y : Integer; + NewCols : T2DIntegerArray; +begin + NewCols := ReturnGridColorsInBox(Box); + for X := 0 to Box.X2 - Box.X1-1 do + for Y := 0 to Box.Y2 - Box.Y1-1 do + begin + if not BoolArr[x][y] then + continue; + boolArr[x][y] := SimilarColors(origCols[x][y],NewCols[x][y],Tolerance); + end; +end; + +(* +InitBoolArr +~~~~~~~~~~~ + +.. code-block:: pascal + + function InitBoolArr(Width,Height : Integer): array of TBoolArray; + +Initializes a 2D boolean array, of dimensions Width x Height to True; + +.. note:: + + Author: m34tcode + Last Modified: 4/7/2012 +*) +function InitBoolArr(Width,Height : Integer) : array of TBoolArray; +var x,y : Integer; +begin + SetArrayLength(Result,Width); + for x := 0 to Width-1 do + begin + SetArrayLength(Result[x],Height); + for Y := 0 to Height-1 do + begin + Result[x][y] := True; + end; + end; +end; + +(* +CountBools +~~~~~~~~~~ + +.. code-block:: pascal + + function CountBools(BoolArr : Array of TBoolArray; CountTrues : Boolean) : Integer; + +Counts all boolean values in the array, equal to CountTrue + +.. note:: + + Author: m34tcode + Last Modified: 4/7/2012 +*) +function CountBools(BoolArr : Array of TBoolArray; CountTrues : Boolean) : Integer; +var + X,Y,W,H,C : Integer; +begin + W := GetArrayLength(BoolArr); + H := GetArrayLength(BoolArr[0]); + For X := 0 to W-1 do + for Y := 0 to H-2 do + if BoolArr[X][Y] = CountTrues then + Inc(C); + Result := C; +end; + +(* +PixelShiftOT +~~~~~~~~~~~~ + +.. code-block:: pascal + + function PixelShiftOT(Box : TBox; ShiftInterval, Repetitions, Tolerance : Integer) : Integer; + +Returns an integer equal to the number of pixels, + within Box, that changed more than tolerance, + in the time specified by ShiftInterval * Repetitions + +.. note:: + + Author: m34tcode + Last Modified: 4/7/2012 + +Example: + +.. code-block:: pascal + + PixelCount := PixelShiftOT(IntToBox(10,10,20,20), 500, 4, 10); +*) +function PixelShiftOT(Box : TBox; ShiftInterval, Repetitions, Tolerance : Integer) : Integer; +var + I : Integer; + T,TT : LongInt; + OrigColArr : T2DIntegerArray; + BoolArr : array of TBoolArray; +begin + OrigColArr := ReturnGridColorsInBox(Box); + BoolArr := initBoolArr(Box.X2-Box.X1,Box.Y2-Box.Y1); + MarkTime(T); + MarkTime(TT); + for I := 0 to Repetitions-1 do + begin + if (TimeFromMark(T) > (Repetitions*ShiftInterval)) then + begin + srl_Warn('CalcNonStaticPixelCount','Completed only ' + IntToStr(I) + ' of ' + + IntToStr(Repetitions) + '. Try increasing the interval',1); + break; + end; + MarkTime(TT); + wait(Max(0,ShiftInterval-TimeFromMark(TT))); + ValidatePixels(Box,OrigColArr,BoolArr,Tolerance); + end; + Result := CountBools(BoolArr,False); +end; + +(* +AnimatingMulti +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function AnimatingMulti(B: TBoxArray; Time, MinCount: Integer): TBooleanArray; + +Finds constant animation in boxes B during time T. If PixelShift in box is +smaller than MinCount, it's considered not animating. + +.. note:: + + Author: marpis + Last Modified: Nov. 29, 2009 + +Example: + +.. code-block:: pascal + + boolArray := AnimatingMulti(boxArray, 5000, 2000); + for i := 0 to High(boolArray) do + isAnimating := boolArray[i]; +*) +function AnimatingMulti(B: TBoxArray; Time, MinCount: Integer): TBooleanArray; +var + Shifts: TIntegerArray; + TT, I, H: Integer; +begin + TT := GetSystemTime + Time; + H := High(B); + SetLength(Result, H + 1); + for I := 0 to H do + Result[I] := True; + while (GetSystemTime < TT) do + begin + Shifts := PixelShiftMulti(B, 50); + for I := 0 to H do + if (Shifts[I] <= MinCount) then + Result[I] := False; + end; +end; + +(* +Animating +~~~~~~~~~ + +.. code-block:: pascal + + function Animating(B: TBox; Time, MinCount: Integer): Boolean; + +Finds constant animation in boxes B during time T. If PixelShift in box is +smaller than MinCount, it's considered not animating. + +.. note:: + + Author: marpis + Last Modified: Nov. 29, 2009 + +Example: + +.. code-block:: pascal + + playerAnimating := Animating(box, 5000, 2000); +*) +function Animating(B: TBox; Time, MinCount: Integer): Boolean; +var + TBA: TBooleanArray; +begin + TBA := AnimatingMulti([B], Time, MinCount); + Result := TBA[0]; +end; + +(* +IsMoving +~~~~~~~~ + +.. code-block:: pascal + + function IsMoving: Boolean; + +Results true if character is moving. + +.. note:: + + Author: marpis + Last Modified: Nov. 29, 2009 + +Example: + +.. code-block:: pascal + + PlayerMoving := IsMoving; +*) + +function IsMoving: Boolean; +begin + Result := PixelShift(IntToBox(MMCX-30, MMCY-30, MMCX+30, MMCY+30), 500) > 200; +end; + +function Flag: Boolean; forward; + +(* +WaitNotMoving +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitNotMoving(WaitFlag: Boolean): Boolean; + +Waits until you arent moving, WaitFlag boolean is there because if you clicked +in an area that isnt walkable the flag will not disappear. Includes a timeout +of 20 seconds for safety. + +.. note:: + + Author: Ollybest + +Example: + +.. code-block:: pascal + + if WaitNotMoving(true) then + writeln('Our player has stopped moving!'); + +*) +function WaitNotMoving(WaitFlag: Boolean): Boolean; +var + T: Integer; +begin + Result := False; + if not (LoggedIn) then + Exit; + + MarkTime(T); + if (WaitFlag) then + Flag; + + repeat + Wait(RandomRange(50, 100)); + if not (IsMoving) then + begin + Result := True; + Exit; + end; + until (TimeFromMark(T) > 20000); +end; diff --git a/SRL/core/antiban.simba b/SRL/core/antiban.simba new file mode 100644 index 0000000..ca3ff2a --- /dev/null +++ b/SRL/core/antiban.simba @@ -0,0 +1,1615 @@ +(* +AntiBan +======= + +The Antiban include contains functions to help eliminate bans. + +.. contents:: + +*) + +(* +LeaveDangerZone +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function LeaveDangerZone: Boolean; + +Handles the 'danger zone' message users get when their total level is < 60 + +.. note:: + + Author: Coh3n + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if LeaveDangerZone then + ContinueWalking; +*) +function LeaveDangerZone: Boolean; +var + t: Integer; +begin + if (FindNPCChatText('erous', Nothing)) then // Only if total level < 60 + begin + ClickContinue(True, True); + + t := GetSystemTime + 5000; + while (GetSystemTime < t) do + begin + Wait(500 + Random(300)); + if (FindNPCChatText('eave', ClickLeft)) then + begin + Result := True; + Break; + end; + end; + end; +end; + +(* +RandomRClick +~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure RandomRClick + +Performs random right click to stay active. + +.. note:: + + Author: phantombmx/EvilChicken!, idea by Naum + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + RandomRClick; +*) +procedure RandomRClick; +var + I: TBooleanArray; + II, M, R: Byte; + Inv: Boolean; +begin + if (not LoggedIn) then exit; + M := MouseSpeed; + MouseSpeed := 7 + Random(25); + Inv := (GetCurrentTab = tab_Inv); + if (Inv) then Inv := ((not InvEmpty) and (Random(3) > 0)); + if (not Inv) then + MouseBox(MSX1, MSY1, MIX2, MIY2, mouse_right) + else + begin + SetLength(I, 28); + for II := 0 to 27 do + I[II] := ExistsItem(II + 1); + + R := RandomRange(1, 28); + while (not I[R - 1]) do + R := RandomRange(1, 28); + InvMouse(R, mouse_right); + end; + Inv := False; + if (Random(3) > 0) then + Inv := ChooseOption('xamine'); + if (not Inv) then ChooseOption('ancel'); + MouseSpeed := M; +end; + +(* +HoverSkill +~~~~~~~~~~ + +.. code-block:: pascal + + procedure HoverSkill(Skill: variant; Click: Boolean); + +Hovers mouse over selected skill to "check exp" Click = True will Click Skill +and Click = False will 'Hover'. Won't "check" skills where your level is 1. + +.. note:: + + Author: Dankness/Cheesehunk/Ron/Raymond/ZephyrsFury + Last Modified: December 09 by Coh3n + +Example: + +.. code-block:: pascal + + HoverSkill(skill_Atack, False); +*) +procedure HoverSkill(Skill: variant; Click: Boolean); +var + TP: TPoint; + Skills: TStringArray; + TheSkill: string; +begin + if(not(GameTab(tab_Stats))) then exit; + + if VariantIsInteger(Skill) then + begin + + if Skill >= 0 then + TP := SkillToCoords(Skill) + else + repeat + Skill := RandomRange(skill_Attack, skill_Summoning); + TP := SkillToCoords(Skill); + until(GetSkillLevel(TheSkill) > 1) + + end else begin + if(Lowercase(Skill) <> 'random')then + TP := SkillToCoords(Skill) + else + repeat + Skills := ['attack','defence','strength','hitpoints','mining','smithing','woodcutting','firemaking','magic', + 'fletching','hunter', 'summoning','fishing','construction','herblore','agility','thieving','crafting', + 'ranged','slayer','farming', 'prayer', 'runecrafting', 'cooking', 'dungeoneering']; + TheSkill := Skills[Random(Length(Skills))]; + TP := SkillToCoords(TheSkill); + until (TP.x > 0) and (GetSkillLevel(TheSkill) > 1); + + end; + + if(Click)then + begin + Mouse(TP.X, TP.Y, 10, 10, mouse_left); + Wait(3000+Random(3000)); + CloseWindow; + end else begin + MMouse(TP.x, TP.y, 10, 10); + Wait(1000 + Random(500)); + end; +end; + +(* +PickUpMouse +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure PickUpMouse; + +Acts just like you picked your mouse off the pad... +then sets it back down. + +.. note:: + + Author: dark_sniper + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + PickUpMouse; +*) +procedure PickUpMouse; +var + cx, cy, XX, YY: Integer; +begin + if(not(LoggedIn))then + exit; + GetMousePos(cx, cy); + XX := cx; + YY := cy; + if(Random(2) = 0)then + MMouse(cx - 3 - Random(5), cy - 8 - Random(17), 0, 0) + else + MMouse(cx + 3, cy - 8 - Random(17), 5, 0); + Wait(1131 + Random(358)); + if(Random(2) = 0)then + MMouse(XX + 3, YY + 8, 5, 9) + else + MMouse(XX - 3 - Random(5), YY + 8, 0, 9); +end; + +(* +SetScreenMouse +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function SetScreenMouse(Direction, CameraAngle: Variant): Boolean; + +Aligns RS to specified direction and camera angle using the middle mouse button. + - Direction: 'n', 's', 'e', 'w' or any degree angle. Accepts 'random' + and 'rand', or '' for no movement. + - CamerAngle: any number from 1 to 10 (1 = lowest angle), or '1', '10'. + Accepts '' for no movement. + +.. note:: + + by Home & euphemism + +Example: + +.. code-block:: pascal + +*) +const + _DEG_TO_PX = 2.838; + _SM_X_AXIS = 511; +function SetScreenMouse(Direction, CameraAngle: Variant): Boolean; +var + ii: Integer; + i, DirectionDeg, StartAngle, Fraction: Extended; + AngleStep, DirFalseSet, FractionInt, NumOfSteps, WaitTime, TempMouse, YStart, + OffX, X, XChange1, XChange2, Y, YChange1, YChange2: Integer; + Left, SetCamera, SetDirection, TopOfScreen: Boolean; +begin + SetCamera := True; + SetDirection := True; + + for ii := 0 to 2 do + begin + Result := False; + StartAngle := rs_GetCompassAngleDegrees; + DirFalseSet := 0; + + if (StartAngle < 0) or (not LoggedIn) then + Exit; + + if VariantIsNumber(Direction) then + DirectionDeg := FixD(Direction + 0.0) + else if VariantIsString(Direction) then + begin + i := StrToFloatDef(Direction,-1337); + if i = -1337 then + begin + case LowerCase(Direction) of + 'n': DirectionDeg := 0; + 'w': DirectionDeg := 270; + 's': DirectionDeg := 180; + 'e': DirectionDeg := 90; + 'random', 'rand': DirectionDeg := RandomRange(0, 360); + '' : SetDirection := False; + end; + end else + DirectionDeg := FixD(i); + end; + + if VariantIsString(CameraAngle) then + begin + if CameraAngle = '' then + SetCamera := False + else + CameraAngle := StrToInt(CameraAngle); + end; + + i := 0.0; + + if ((not SetDirection) and (not SetCamera)) then + begin + Result := True; + Exit + end; + + if (((MinE(Abs(StartAngle - DirectionDeg), + MinE(Abs(StartAngle - (DirectionDeg + 360)), + Abs((StartAngle + 360) - DirectionDeg)))) <= 3.0) and (SetCamera)) then + begin + SetDirection := False; + end; + + if (((MinE(Abs(StartAngle - DirectionDeg), + MinE(Abs(StartAngle - (DirectionDeg + 360)), + Abs((StartAngle + 360) - DirectionDeg)))) <= 3.0) and (not SetCamera)) then + begin + Result := True; + Exit; + end; + + if SetDirection then + begin + Left := (Round((360 - StartAngle) + DirectionDeg) + mod 360 <= Round((StartAngle + 360) - DirectionDeg) mod 360); + WaitTime := RandomRange(30, 90); + + if Left then + begin + DirectionDeg := 360 + DirectionDeg - StartAngle; + OffX := - 5; + end else + begin + DirectionDeg := 360 - DirectionDeg + StartAngle; + OffX := 5; + end; + + end else + Left := RBool; + + TempMouse := MouseSpeed; + + if MouseSpeed > 14 then + MouseSpeed := RandomRange(14, 15); + + if not SetDirection then + Fraction := 1 + else + Fraction := DirectionDeg * _DEG_TO_PX / _SM_X_AXIS + - Floor(DirectionDeg * _DEG_TO_PX / _SM_X_AXIS); + + if Fraction > 0 then + begin + FractionInt := Round(MSX2 * Fraction); + + if SetDirection then + begin + XChange1 := RandomRange(0, FractionInt); + XChange2 := FractionInt - XChange1; + DirFalseSet := 0; + end else + begin + DirFalseSet := RandomRange(7, 511); + XChange1 := DirFalseSet; + XChange2 := 0; + OffX := 0; + end; + + NumOfSteps := 10; + AngleStep := Ceil((278 / NumOfSteps)); + TopOfScreen := RBool; + + if SetCamera then + begin + CameraAngle := NumOfSteps - CameraAngle; + if TopOfScreen then + begin + YStart := RandomRange(MSY1, MSY1 + 55); + YChange1 := YStart + RandomRange(278, 280); + YChange2 := (CameraAngle * AngleStep) * -1; + end else + begin + YStart := RandomRange(MSY2, MSY2 - 55); + YChange1 := YStart - RandomRange(278, 280); + YChange2 := ((NumOfSteps - CameraAngle) * AngleStep); + end; + end else + begin + YStart := RandomRange(10, 330); + YChange1 := YStart; + YChange2 := 0; + end; + + GetMousePos(X, Y); + + if ii <> 0 then + MMouse(X, Y, 0, 0) + else + if not Left then + begin + if not ii <> 0 then + MMouse(MSX2 - DirFalseSet, YStart, 0, 0) + else + MMouse(MSX2, Y, 0, 0); + end else + begin + if not ii <> 0 then + MMouse(MSX1 + DirFalseSet, YStart, 0, 0) + else + MMouse(MSX1, Y, 0, 0); + end; + + GetMousePos(X, Y); + HoldMouse(X, Y, mouse_Middle); + Wait(WaitTime); + + if ((ii = 0) and (SetCamera))then + begin + if not Left then + begin + MMouse(MSX2 - XChange1, YChange1, 0, 0); + Wait(WaitTime); + GetMousePos(X, Y); + ReleaseMouse(X, Y, mouse_Middle); + Wait(WaitTime); + HoldMouse(MSX2 - XChange1, Y, mouse_Middle); + MMouse(((MSX2 - XChange1) - XChange2 + OffX), Y + YChange2, 0, 0); + end else + begin + MMouse(MSX1 + XChange1, YChange1, 0, 0); + Wait(WaitTime); + GetMousePos(X, Y); + ReleaseMouse(X, Y, mouse_Middle); + Wait(WaitTime); + HoldMouse(MSX1 + XChange1, Y, mouse_Middle); + MMouse(((MSX1 + XChange1) + XChange2 + OffX), Y + YChange2, 0, 0); + end; + end else + if not Left then + MMouse(X - (FractionInt + 5), Y, 0, 0) + else + MMouse(X + (FractionInt - 5), Y, 0, 0); + + Wait(WaitTime); + GetMousePos(X, Y); + ReleaseMouse(X, Y, mouse_Middle); + Wait(WaitTime); + end; + + SetCamera := False; + end; + + MouseSpeed := TempMouse; +end; + +(* +MissMouse +~~~~~~~~~ + +.. code-block:: pascal + + procedure MissMouse(eX, eY: Integer); + +Human-like miss-and-correct mouse movement. + +.. note:: + + Author: Flight + Last Modified: 30 Dec. 2011 + +Example: + +.. code-block:: pascal + + RandomMovement; +*) +procedure MissMouse(eX, eY: Integer); +var + randSpeed: extended; + X,Y,A,Dist,MP: integer; +begin + A := MouseSpeed; + GetMousePos(X, Y); + Dist := Distance(X, Y, eX, eY); + MP := Round(Dist/150); + if MP < 0 then + MP := 1; + + randSpeed := (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0; + MMouse(RandomRange(eX-(A*MP), eX+(A*MP)), RandomRange(eY-(A*MP), eY+(A*MP)), 0, 0); + GetMousePos(X, Y); + MMouse(eX, eY, 0, 0); + MouseSpeed := A; +end; + +(* +MultiMouse +~~~~~~~~~~ + +.. code-block:: pascal + + function MultiMouse(x, y, chance, maxClicks: integer; red: boolean): boolean; + +Will simulate "spam" clicking on the point x, y. Will do it a random amount +between 1 and 'maxClicks'. Will click once no matter what, then has a percent +'chance' of clicking again after that. Will not exceed 'maxClicks'. if 'red' +then will return true if the red X appears after clicking an object, else will +return true after clicking. + +.. note:: + + | Author: Coh3n + | Last Updated: 21 July 2011 by Coh3n + +Example: + +.. code-block:: pascal + + if (waitUptext('ree', 200)) then + MSI_MultiMouse(x, y, 35, 5, true); +*) +function MultiMouse(x, y, chance, maxClicks: integer; red: boolean): boolean; +var + clicks: integer; +begin + repeat + inc(clicks); + mouse(x, y, 0, 0, true); + + if (red) then + result := didRedClick + else + result := true; + + if (random(100) > chance) or (not result) then + break; + until(clicks >= maxClicks); +end; + +(* +RandomMovement +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure RandomMovement; + +Presses random arrow keys and moves the mouse. Able to press 2 keys simultaneously. + +.. note:: + + Author: Krazy_Meerkat + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + RandomMovement; +*) +procedure RandomMovement; +var + Keys: TIntegerArray; + I: Integer; + Deg: Extended; +begin + if(not(LoggedIn))then exit; + Keys := [VK_RIGHT, VK_LEFT]; + I := Random(2); + if (Random(2) = I) then + begin + ActivateClient; + Deg := RS_GetCompassAngleDegrees; + Wait(100 + random(50)); + KeyDown(Keys[I]); + Wait(500 + random(1000)); + KeyUp(Keys[I]); + Wait(500 + random(1000)); + MakeCompass(Deg); + end else + if (Random(3) = 0) then + SleepAndMoveMouse(1000 + random(200)); +end; + +(* +CompassMovement +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function CompassMovement(MinMovement, MaxMovement: Integer; Return: Boolean): Boolean; + +Rotates the compass somewhere between MinMovement and MaxMovement. Will return +to original angle if Return is set to true. + +.. note:: + + Author: Nebula + Last Modified: Mar. 6th, 2011 by Nebula + +Example: + +.. code-block:: pascal + + CompassMovement(10, 30, true); +*) +function CompassMovement(MinMovement, MaxMovement: Integer; Return: Boolean): Boolean; +var + StartAngle, Movement : Integer; +begin + Result := False; + StartAngle := round(rs_GetCompassAngleDegrees()); + case Random(2) of + 0: Movement := RandomRange(-MinMovement, -MaxMovement); + 1: Movement := RandomRange(MinMovement, MaxMovement); + end; + MakeCompass(StartAngle + Movement); + if (Return = true) then + begin + wait(RandomRange(100,350)); + MakeCompass(StartAngle); + end; + Result := true; +end; + +(* +BoredHuman +~~~~~~~~~~ + +.. code-block:: pascal + + procedure BoredHuman; + +Performs 5-15 times: + * Rotates the cam, + * Moves the mouse around MainScreen, + * If it finds IsUpText('option'), it will Chooseoption('Examine'); + +.. note:: + + Author: WT-Fakawi, small edit by Harry + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + BoredHuman; +*) +procedure BoredHuman; +var + i, x, y: Integer; + Deg: Variant; +begin + if not LoggedIn then exit; + Deg := rs_GetCompassAngleDegrees; + for i := 1 to (3 + Random(11)) do + begin + MMouse(Random(MSX2), Random(MSY2), 0, 0); + if IsUpText('opti') then + begin + GetMousePos(x, y); + Mouse(x, y, 0, 0, mouse_right); + ChooseOption('Examine'); + end; + case Random(6) of + 0: SendArrowWait(((Random(2) * 2) + 1), 1000 + Random(200)); + 1: SendArrowWait(((Random(2) * 2)), 1000 + Random(200)); + 2: SendArrowWait(((Random(2) * 2) + 1), 200 + Random(200)); + 3: SendArrowWait(((Random(2) * 2)), 200 + Random(200)); + 4: SendArrowWait(((Random(2) * 2) + 1), 20 + Random(20)); + 5: SendArrowWait(((Random(2) * 2)), 20 + Random(20)); + end; + end; + if (Deg <> 0) then + MakeCompass(Round(Deg)) + else + MakeCompass('N'); + SendArrowWait(0, 750 + Random(500)); +end; + +(* +ExamineInv +~~~~~~~~~~ + +.. code-block:: pascal + + procedure ExamineInv; + +Chooses a random item in the inventory to examine. + +.. note:: + + Author: R1ch + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + ExamineInv; +*) +procedure ExamineInv; +var + InvSpots: array of Byte; + I, L: Byte; +begin + if (InvEmpty) then exit; + for I := 1 to 28 do + if ExistsItem(I) then + begin + SetLength(InvSpots, Length(InvSpots) + 1); + InvSpots[L] := I; + Inc(L); + end; + MouseItem(InvSpots[Random(Length(InvSpots))], mouse_right); + if (not WaitOption('xamine', 375)) then + if (Random(2) = 0) then + WaitOption('ancel', 375); +end; + +(* +RandomAngle +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure RandomAngle(HowToEnd: Variant); + +Randomly changes the angle of the compass. Finishes depending on + + HowToEnd: + 1, 'up', True = Highest angle + 2, 'down', False = Lowest angle + + Put '' to leave it as it is. + +.. note:: + + Author: R1ch + +Example: + +.. code-block:: pascal + + RandomAngle(1); +*) +procedure RandomAngle(HowToEnd: Variant); +var + Key: Byte; + B: Integer; +begin + B:= random(2); + if (B = 0) then + Key:= 38 + else + Key:= 40; + SetAngle(B); + Wait(RandomRange(500, 1000)); + KeyDown(Key); + Wait(RandomRange(500, 1100)); + KeyUp(Key); + Wait(RandomRange(500, 1000)); + case (HowToEnd) of + SRL_ANGLE_LOW, 'down', False : SetAngle(SRL_ANGLE_LOW); + SRL_ANGLE_HIGH, 'up', True : SetAngle(SRL_ANGLE_HIGH); + end; +end; + +(* +AdjustMouseSpeed +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure AdjustMouseSpeed(Amount, MinMS, MaxMS: Integer); + +Randomly changes the mousespeed by the amount (+/-) within the min and max +mousespeed limit. + +.. note:: + + Author: Ollybest + +Example: + +.. code-block:: pascal + + AdjustMouseSpeed(3, 10, 20); + +*) +procedure AdjustMouseSpeed(Amount, MinMS, MaxMS: Integer); +var + MS, NewMS: Integer; +begin + MS := MouseSpeed; + NewMS := RandomRange(MS - Amount, MS + Amount); + + // setting the mousespeed to the max/min limit if needed + if NewMS > MaxMS then + NewMS := MaxMS; + if NewMS < MinMS then + NewMS := MinMS; + + if InRange(NewMS, MinMS, MaxMS) then + MouseSpeed := NewMS +end; + +(* +RandomFKeys +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure RandomFKeys(Return: Boolean) + +Randomly changes tabs using fkeys to simulate a human pressing fkeys quickly. +Will return to the original tab if Return is set to true. + +.. note:: + + Author: Ollybest + +Example: + +.. code-block:: pascal + + RandomFKeys(True); + +*) +procedure RandomFKeys(Return: Boolean); +var + t, r, i: integer; + Tabs: TIntegerArray; +begin + if not (LoggedIn) then + exit; + + t := GetCurrentTab; + r := RandomRange(1, 6); + Tabs := [tab_Combat, tab_Inv, tab_Equip, tab_Prayer, tab_Magic]; + for i := 0 to r do + FTab(Tabs[Random(Length(Tabs))]); + + // not all tabs can be f keyed + if (Return) then + if InIntArray(Tabs, t) then + FTab(t) + else + GameTab(t); +end; + +(* +RandomTab +~~~~~~~~~ + +.. code-block:: pascal + + procedure RandomTab; + +Switches to a random gametab, more of a 50% chance of switching to a more +used tab. Will return to the original tab if Return is set to true. + +.. note:: + + Author: Ollybest + +Example: + +.. code-block:: pascal + + RandomTab(True); + +*) +procedure RandomTab(Return: Boolean); +var + AllTabs, T: Integer; + TIA: TIntegerArray; +begin + if not (LoggedIn) then + exit; + + T := GetCurrentTab; + // every tab + AllTabs := RandomRange(21, 37); + // more commanly used tabs + TIA := [23, 25, 26, 30, 28]; + + if (RBool) then + GameTab(AllTabs) + else + GameTab(TIA[Random(Length(TIA))]); + + if (Return) then + GameTab(T); +end; + +(* +HoverOnlineFriend +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure HoverOnlineFriend; + +Hovers a random online friend (if any are online) + +.. note:: + + Author: Ollybest + +Example: + +.. code-block:: pascal + + HoverOnlineFriend; + +*) +procedure HoverOnlineFriend; +var + x, y, i, S, L, clOffline, t: Integer; + OnlineSlots: TIntegerArray; + Slots: TBoxArray; + TPA: TPointArray; + B: TBox; +begin + if not (LoggedIn) then + Exit; + + // color of offline friend - could change oneday + clOffline := 4087005; + t := GetCurrentTab; + Gametab(Tab_Friends); + + // scrolling back to the top if needed + if GetColor(728, 311 - 50) <> 3646433 then + begin + if FindColorsTolerance(TPA, 3845615, 723, 306-50, 734, 478-50, 6) then + B := GetTPABounds(TPA) + else //failsafe incase color oneday changes + Exit; + DragMouseTBox(B, IntToBox(724, 280-50, 734, 304-50)); + end; + + //possible slots + Slots := Grid(1, 13, 166, 9, 5, 15, Point(633, 305 - 50)); + + for i := 0 to High(Slots) do + if not FindColor(X, Y, clOffline, Slots[i].X1, Slots[i].Y1, Slots[i].X2, Slots[i].Y2) then + begin + SetLength(OnlineSlots, Length(OnlineSlots) + 1); + OnlineSlots[L] := i; + Inc(L); + end; + + if Length(OnlineSlots) < 1 then + Exit; + + S := OnlineSlots[Random(Length(OnlineSlots))]; + MMouse(RandomRange(Slots[S].X1, Slots[S].X2), + RandomRange(Slots[S].Y1, Slots[S].Y2), 0, 0); + + if (RBool) then + if WaitUpText('essage', 200 + Random (100)) then + begin + ClickMouse2(Mouse_Right); + WaitOption('ancel', 400 + Random(100)); + end; + Wait(RandomRange(300, 900)); + GameTab(t); +end; + +(* +HoverMovingObject +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure HoverMovingObject; + +Splits the screen up into boxes and hovers the one with the most pixel shift in. + +.. note:: + + Author: Ollybest + +Example: + +.. code-block:: pascal + + HoverMovingObject; + +*) +procedure HoverMovingObject; +var + TBA: TBoxArray; + TIA: TIntegerArray; + i, L: Integer; + Rows: Integer; + ATPA, ATPA2: T2DPointArray; + Player, TPA: TPointArray; +begin + if not (LoggedIn) then + Exit; + + // if actionbar is open we dont need track it + if (IsActionBarOpen) then + Rows := 13 + else + Rows := 16; + + TBA := Grid(27, Rows, 19, 20, 19, 20, Point(13, 14)); + TIA := PixelShiftMulti(TBA, 100 + Random(100)); + TPAFromBoxWrap(IntToBox(232, 194 - 50, 289, 254 - 50), Player); + + for i := 0 to High(TBA) do + if TIA[i] > 5 then + begin + Inc(L); + SetArrayLength(ATPA, L + 1); + TPAFromBoxWrap(TBA[i], ATPA[L]); + end; + + MergeATPAWrap(ATPA, TPA); + ClearTPAFromTPAWrap(TPA, Player, TPA); + SplitTPAExWrap(TPA, 1, 1, ATPA2); + SortATPASize(ATPA2, True); + + if Length(ATPA2) > 1 then + begin + MouseTBox(GetTPABounds(ATPA2[0]), Mouse_Move); + if (RBool) then + if WaitUpTextMulti(['option', 'tion'], 100 + Random(100)) then + WaitOptionMulti(['xamine', 'ancel'], 100 + Random(100)); + end; +end; + +(* +MMouseOffClient +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure MMouseOffClient(Direction: String); + +Moves the mouse off the client in the set direction. + - Vaild Directions: 'top', 'bottom', 'left', 'right' or accepts 'random' + and 'rand' for a random direction. + +.. note:: + + Author: Ollybest + +Example: + +.. code-block:: pascal + + MMouseOffClient('top'); + +*) +procedure MMouseOffClient(Direction: String); +var + B: TBoxArray; + P: TPoint; + i, W, H: Integer; +begin + GetClientDimensions(W, H); + SetArrayLength(B, 4); + B[0] := IntToBox(-300, -300, W, 0); //top + B[1] := IntToBox(0, H, W, H +300); //bottom + B[2] := IntToBox(0-300, 0, 0, H); //left + B[3] := IntToBox(W, 0, W +300, H); //right + + case Lowercase(Direction) of + 'top': i := 0; + 'bottom': i := 1; + 'left': i := 2; + 'right': i := 3; + 'rand', 'random': i := Random(4); + else + srl_Warn('MMouseOffClient', 'Invaild direction!', warn_AllVersions); + end; + + P := Point(RandomRange(B[i].X1, B[i].X2), RandomRange(B[i].Y1, B[i].Y2)); + MMouse(P.X, P.Y, 0, 0); +end; + +(* +SmallRandomMouse +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SmallRandomMouse; + +Randomly moves the mouse in a max radius of 80 of its current postion, has alot +of gravity and wind so it can simulate a human flicking/spiraling the mouse. + +.. note:: + + Author: Flight (edit to work with SRL5 by Ollybest) + +Example: + +.. code-block:: pascal + + SmallRandomMouse; + +*) +procedure SmallRandomMouse; +var + RandSpeed: Extended; + x, y, rx, ry, FS, W, H: Integer; +begin + GetClientDimensions(W, H); + FS := MouseSpeed; + MouseSpeed := RandomRange(7, 10); + RandSpeed := (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0; + GetMousePos(x, y); + + rx := RandomRange(x-80, x+80); + ry := RandomRange(y-80, y+80); + + //make sure mouse stays on ms + if rx < MSX1 then + rx := MSX1 + 1; + if ry < MSY1 then + ry := MSY1 + 1; + if rx > W then + rx := W - 1; + if ry > H then + ry := H - 1; + + WindMouse(x, y, rx, ry, 30, 55, (10.0/randSpeed), (12.0/randSpeed), (10.0*randSpeed), (10.0*randSpeed)); + MouseSpeed := FS; +end; + +(* +DragRandomInvSlot +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DragRandomInvSlot; + +Moves an item in your invent to another free slot, if your script relys on +static inv slots its suggested not to use. + +.. note:: + + Author: Ollybest + +Example: + +.. code-block:: pascal + + DragRandomInvSlot; + +*) +procedure DragRandomInvSlot; +var + i, FullL, EmptyL: integer; + FullSlots, EmptySlots: TIntegerArray; +begin + if (not (LoggedIn)) or (InvFull) or (InvEmpty) then + Exit; + + // collecting full and empty inv slots + for i := 1 to 28 do + if ExistsItem(i) then + begin + SetLength(FullSlots, Length(FullSlots) + 1); + FullSlots[FullL] := i; + Inc(FullL); + end else + begin + SetLength(EmptySlots, Length(EmptySlots) + 1); + EmptySlots[EmptyL] := i; + Inc(EmptyL); + end; + + if Length(FullSlots) and Length(EmptySlots) > 0 then + DragMouseTBox(InvBox(FullSlots[Random(Length(FullSlots))]), + InvBox(EmptySlots[Random(Length(EmptySlots))])); + +end; + +(* +LevelUpEx + +.. code-block:: pascal + + function LevelUpEx(ClickCont, ClickSkill: Boolean): Boolean; + +Returns true if the player has gained a level. If ClickCont is set to true it +will click the continue button in the chat box. If ClickSkill is set to true, +it will click the skill and exit the window. + +.. note:: + + Author: Flight + +Example: + +.. code-block:: pascal + + if (LevelUpEx(false, true)) then + inc(Players[CurrentPlayer].Integers[10]); +*) +function LevelUpEx(ClickCont, ClickSkill: Boolean): Boolean; +var + i: Integer; + Skills: TStringArray; +begin + if (FindNPCChatText('gratu', Nothing) or FindBlackChatMessage('just adva')) then + begin + ClickContinue(ClickCont, True); + + if (ClickSkill) then + begin + Wait(RandomRange(50, 110)); + + Skills := [ + 'Attack', 'Defence', 'Strength', 'Constitution', 'Mining', 'Smithing', + 'Woodcutting', 'Firemaking', 'Magic', 'Fletching', 'Hunting', 'Summoning', + 'Fishing', 'Construction', 'Herblore', 'Agility', 'Thieving', 'Crafting', + 'Ranged', 'Slayer', 'Farming', 'Prayer', 'Runecrafting', 'Cooking', + 'Dungeoneering' + ]; + + for i := 0 to High(Skills) do + if IsChatBoxTextBetween(Skills[i], clMessage, 1, 8) then + if IsChatBoxTextBetween('Constitution', clMessage, 1, 8) then + HoverSkill('HitPoints', True) + else + HoverSkill(Skills[i], True); + end; + + Result := True; + WriteLn(Players[CurrentPlayer].Name + ' leveled up!'); + end; +end; + +(* +LevelUp +~~~~~~~ + +.. code-block:: pascal + + function LevelUp: Boolean; + +Returns true if the player has gained a level. Will click the "click to +continue" button in the chat box. + +.. note:: + + Author: Flight + +Example: + +.. code-block:: pascal + + if (LevelUp) then + inc(Players[CurrentPlayer].Integers[10]); +*) +function LevelUp: Boolean; +begin + Result := LevelUpEx(True, False); +end; + +(* +FindMod +~~~~~~~ + +.. code-block:: pascal + + function FindMod: Boolean; + +Results true if a mod is found talking in the chat box. Will logout and wait +if LogoutOnMod (global boolean) is set to true. + +.. note:: + + Author: Stupid3ooo + +Example: + +.. code-block:: pascal + + FindMod(); +*) +function FindMod: Boolean; +var + tX, tY: Integer; +begin + if (not UseFindMod) or (not LoggedIn) then + exit; + + if (not SRLBitmapsLoaded) then + LoadSRLBitMaps; + + if (FindColorTolerance(tX, tY, 14737632, MCX1, MCY1, MCX1 + 40, MCY2, 15)) or + (FindColorTolerance(tX, tY, 589815, MCX1, MCY1, MCX1 + 40, MCY2, 15)) then + if (FindBitmapToleranceIn(bmpMod, tX, tY, MCX1, MCY1, MCX1 + 40, MCY2, 15)) or + (FindBitmapToleranceIn(bmpAdmin, tx, ty, MCX1, MCY1, MCX1 + 40, MCY2, 15)) then + begin + Result := True; + + if SRL_HasProc(srl_OnFindMod) then + SRL_Procs[srl_OnFindMod](); + + if (LogoutOnMod) then + begin + Writeln('******** FOUND MOD ********'); + Writeln('Logging out, waiting 1-2 minutes until mod leaves'); + + WaitFunc(@ExitToLobby, 500, 1500); + Wait(60000 + Random(60000)); + LoginPlayer; + end; + end; +end; + +(* +FindDead +~~~~~~~~ + +.. code-block:: pascal + + function FindDead: Boolean; + +Logs out and sets the current player to false if they are found dead. Will not +logout if Reincarnate (global boolean) is set to true. + +.. note:: + + Author: Stupid3ooo and Cazax + +Example: + +.. code-block:: pascal + + FindDead(); +*) +function FindDead: Boolean; +begin + Result := False; + if FindTextTPA(0, 0, MCX1, MCY1, MCX2, MCY2, 'dear', SmallChars, Nothing) then + if FindTextTPA(0, 0, MCX1, MCY1, MCX2, MCY2, 'dead', SmallChars, Nothing) then + begin + Result := True; + + if SRL_HasProc(srl_OnFindDead) then + SRL_Procs[srl_OnFindDead](); + + if (Reincarnate) then + exit; + + LogOut; + Players[CurrentPlayer].Rand := 'Dead'; + Players[CurrentPlayer].Active := False; + end; +end; + +(* +FindDwarvenPopup +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindDwarvenPopup: Boolean; + +A simple functinds and closes the "please buy RS Members" popup that happens +when you reach lvl 10 in any skill. + +.. note:: + + Author: Harry + +Example: + +.. code-block:: pascal + + FindDwarvenPopup(); +*) +function FindDwarvenPopup: Boolean; +begin + Result := False; + // Parts of red X, checked in two different spots to reduce false-positives + if (GetColor(485, 40) = 2569093) then + if (GetColor(488, 40) = 11189720) then + begin + Result := True; + + // Box around the X, to close it. + MouseBox(482, 35, 492, 44, mouse_left); + Wait(1000+Random(3000)); + end; +end; + +(* +ExitSquealOfFortune +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ExitSquealOfFortune(): boolean; + +Finds and exits the annoying Squeal of Fortune pop up. + +.. note:: + + Author: Coh3n & Ashaman88 + Last Modified: July 28th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + ExitSquealOfFortune(); +*) +function ExitSquealOfFortune(): boolean; +var + w, h, x, y, xs, ys, xe, ye, tmpCTS,SquealDTM: integer; +begin + if (SRL_ExitedSquealOfFortune) then + exit; + + SquealDTM := DTMFromString('mbQAAAHicY2VgYNjOzMCwEIirgLgSiBuB2JiRgUELiGWB2BCIrYH4/1kXhku1MQyLrxcyfPz0iSHA2Z2BH6gfHTNiwWAAAHx8DXE='); + + tmpCTS := getColorToleranceSpeed(); + setColorToleranceSpeed(1); + + getClientDimensions(w, h); + + // green color of the goblin thing + if (findColorTolerance(x, y, 7457955, 1, 1, w - 1, h - 1, 15)) then + begin + // to avoid out of bounds warnings + xs := x-70; + if (xs < 0) then + xs := 1; + + ys := (y - 70); + if (ys < 0) then + ys := 1; + + xe := (x + 130); + if (xe > w) then + xe := (w - 1); + + ye := (y + 70); + if (ye > h) then + ye := (h - 1); + + // gold color in the X + if (findDTM(SquealDTM,x,y,xs,ys,xe,ye)) then + begin + mouse(x, y, 3, 3, mouse_Move); + + if (waitUptextMulti(['Select', 'elect', 'lect'], 300)) then + begin + getMousePos(x, y); + mouse(x, y, 0, 0, mouse_Left); + result := true; + SRL_ExitedSquealOfFortune := true; + end; + end; + end; + FreeDTM(SquealDTM); + setColorToleranceSpeed(tmpCTS); +end; + + (* +FindSpinTicketObj +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindSpinTicketObj(var x,y : Integer): Boolean; + +Find spin ticket object. + +.. note:: + + Author: Kyle Undefined + Last Modified: Feb. 1st 2013 by slushpuppy + + +Example: + +.. code-block:: pascal + + FindSpinTicketObj(x,y); +*) +function FindSpinTicketObj(var x,y : Integer): Boolean; +var + oneFreeSpin : Integer; +begin + oneFreeSpin := DTMFromString('mrAAAAHic42BgYMhlYmBIBuJyIC4F4hQgLgPiaiAuAeInQDWvgfg+ED8D4vdQDBK/BcS9BloMHXHWYMzLwwMUYULB/EASH2ZCw4xoGAYA/y4OqA=='); + + Result := FindDTM(oneFreeSpin, x, y, MIX1, MIY1, MIX2, MIY2); + FreeDTM(oneFreeSpin); +end; +(* +FindSpinTicket +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindSpinTicket(): Boolean; + +Finds and exits the annoying Squeal of Fortune pop up. + +.. note:: + + Author: Kyle Undefined + Last Modified: Apr. 3rd, 2012 by Coh3n + Feb. 1st 2013 by slushpuppy + +Example: + +.. code-block:: pascal + + FindSpinTicket(); +*) +function FindSpinTicket(): Boolean; +var + x, y: Integer; +begin + if FindSpinTicketObj(x,y) then + begin + Mouse(x, y, 5, 5, mouse_Move); + + if (WaitUptext('laim', 300)) then + begin + ClickMouse2(mouse_Left); + Wait(RandomRange(100, 200)); + Result := True; + end; + end; +end; + +(* +FindAndDestroySpinTicket +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindAndDestroySpinTicket: Boolean; + +Finds and destroys any sof spin tickets. + +.. note:: + + Author: Kyle Undefined + Last Modified: Feb. 1st 2013 by slushpuppy + +Example: + +.. code-block:: pascal + + FindAndDestroySpinTicket(); +*) +function FindAndDestroySpinTicket(): Boolean; +var + x, y: Integer; +begin + if FindSpinTicketObj(x,y) then + begin + Mouse(x, y, 5, 5, mouse_Move); + + if (WaitUptext('laim', 300)) then + begin + ClickMouse2(mouse_Right); + Wait(RandomRange(100, 200)); + ChooseOption('estroy'); + Wait(RandomRange(1000, 1400)); + FindNPCChatTextMulti(['All', 'Yes'], ClickLeft); + Result := True; + end; + end; +end; + +(* +CloseAdWindow +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function CloseAdWindow(): Boolean; + +Finds and exits the wicked hood and dwarven army axe pop up ads. + +.. note:: + + Author: litoris + Last Modified: September 2nd, 2012 by litoris + +Example: + +.. code-block:: pascal + + CloseAdWindow(); +*) +function CloseAdWindow(): Boolean; +var +Cross, x, y: Integer; +begin + Cross := BitmapFromString(10, 9, 'meJzT1jbX0HDWzp6jYxipqOwNRDI' + + 'yXkoq3lKRfSIiKjo6FiCpDX+0pj/QMshQUgqVVE4AsoEikpG9ioqW' + + 'QF0QLpBUMKvRmgFiq02+yyHiJCVlLy3tpaiSDhGEILUpd3nEAtnYj' + + 'GVkDYEKpKSCRLVL4LJi2iU8PE4cnMYiIlpCwpbCUpFA9Zh6ublVOE' + + 'WdIFJAEqgLygbaK2zNzCwlGdkHVS8eCDQQSEIUAN3MyMgNUcApYg0' + + '0CoKAbKAUE5MQAMPoVvw='); + if FindBitmapTolerancein(Cross, x, y, MSCX, MSY1, MSX2, MSCY, 5) then + begin + MMouse(x, y, 2, 2); + if (WaitUptext('lose', 300)) then + begin + ClickMouse2(mouse_Left); + Wait(RandomRange(100, 200)); + Result := True; + end; + end; + FreeBitmap(Cross); +end; diff --git a/SRL/core/antirandoms/abyss.simba b/SRL/core/antirandoms/abyss.simba new file mode 100644 index 0000000..4d1cdf2 --- /dev/null +++ b/SRL/core/antirandoms/abyss.simba @@ -0,0 +1,80 @@ +(* +Abyss +===== + +The Abyss file stores the routines to solve the abyss (Lost and Found) random +event. Since the appendages are very difficult to differentiate with one +another, this solver walks to the north one and clicks it until it's the right +one or the maximum tries (defined in Abyss_Solve) has been reached. + +*) + +(** + * Author: Coh3n + * Description: Detects if a player is in the Abyss random. + *) +function Abyss_Detect(): boolean; +var + x, y: integer; +begin + if (tabExists(TAB_MAGIC)) then + exit; + + // redish color on the minimap; only searches top half because the Mime audience color is similar and only appears in the bottom of the minimap + if (findColorTolerance(x, y, 3619450, MMCX-10, MMCY-10, MMCX+10, MMCY, 15)) then + result := (countColorTolerance(clBlack, MMX1, MMY1, MMX2, MMY2, 15) > 1000); +end; + +(** + * Author: Coh3n + * Description: Sets up the screen/player to solve the random. + *) +procedure Abyss_Setup(); +begin + if (not loggedIn()) then + exit; + + clickNorth(SRL_ANGLE_HIGH); + mouse(MMCX, MMY1 + 60, 3, 3, true); // walks north, clicks the same appendage + wait(2000 + random(500)); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Solves the random by clicking the same appendage over and over + * again. There's a 25% chance of getting it right each click. + *) +function Abyss_Solve(): boolean; +var + dtmStick, t: integer; +begin + if (not loggedIn()) then + exit; + + Abyss_Setup(); + dtmStick := DTMFromString('mrAAAAHic42BgYNBhZGCQAWJbIFYEYnMgFgNiJyDWBuIqoJp8IM4D4jogrgHiLiBuh+JQVSmGMntThlgjLYZIdRkw34WPi8GdH4glxRj4gWrwYUYCGAYAeSYKcw=='); + + repeat + Inc(t); + + if (clickDTMRotatedIn(dtmStick, MSX1, MSY1, MSX2, 200, -Pi/4, Pi/4, Pi/30, ['erate'], mouse_Left)) then + begin + addToSRLLog('Abyss_Solve: Clicked Appendage'); + wait(2000 + random(1000)); + end; + + if (FindNPCChatText('ologise', Nothing)) then + begin + clickContinue(true, true); + result := true; + end else + result := tabExists(TAB_MAGIC); + + until(result or (t > 25)); + + freeDTM(dtmStick); + + if (not result) then + addToSRLLog('Abyss_Solve: Abyss solver exceeded maximum tries'); +end; + diff --git a/SRL/core/antirandoms/antirandoms.simba b/SRL/core/antirandoms/antirandoms.simba new file mode 100644 index 0000000..328d769 --- /dev/null +++ b/SRL/core/antirandoms/antirandoms.simba @@ -0,0 +1,527 @@ +(* +Antirandoms +=========== + +The 'master' SRL randoms file. The 4 "core" functions (solverandoms, +FindAllrandoms, FindNormalRandoms, and FindNonInventoryRandoms) shouldn't ever +need to be updated if a new random event is added to the game, or a current one +is removed. For a description of how each solver works, see the top of that +solver's simba file. + +*) + +// include all the solver files +{$include_once common.simba} +{$include_once rewards.simba} +{$include_once demon.simba} +{$include_once maze.simba} +{$include_once evilbob.simba} +{$include_once mordaut.simba} +{$include_once certers.simba} +{$include_once mime.simba} +{$include_once abyss.simba} +{$include_once frog.simba} +{$include_once pinball.simba} +{$include_once sandwich.simba} +{$include_once pillory.simba} +{$include_once capnarnav.simba} +{$include_once quiz.simba} +{$include_once leo.simba} +{$include_once prisonpete.simba} +{$include_once forester.simba} +{$include_once molly.simba} +{$include_once beekeeper.simba} + +// represent the elements of the SRL_Randoms array +const + SRL_RANDOMS_COUNT = 0; + SRL_RAND_DEMON = 0; + SRL_RAND_MAZE = 1; + SRL_RAND_EVILBOB = 2; + SRL_RAND_MORDAUT = 3; + SRL_RAND_CERTERS = 4; + SRL_RAND_MIME = 5; + SRL_RAND_ABYSS = 6; + SRL_RAND_FROG = 7; + SRL_RAND_PINBALL = 8; + SRL_RAND_SANDWICH = 9; + SRL_RAND_PILLORY = 10; + SRL_RAND_ARNAV = 11; + SRL_RAND_QUIZ = 12; + SRL_RAND_LEO = 13; + SRL_RAND_PETE = 14; + SRL_RAND_FORESTER = 15; + SRL_RAND_BEEKEEPER = 16; + SRL_RAND_MOLLY = 17; + SRL_RAND_REWARDS = 18; + +type + TRandom = record + name: string; + solve, detect: function(): boolean; + solved, failed: integer; // for SRL stats/randoms report + isInvRandom, hasRewardBox, disabled: boolean; + end; + +var + SRL_Randoms: array[0..(SRL_RANDOMS_COUNT - 1)] of TRandom; + SRL_RandomsSet, SRL_DisableRandoms, SRL_RandomScreenShot: boolean; + +// needs to be included after variables are declared +{$include_once randomtool.simba} + +(* +SRLRandomsReport +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function SRLRandomsReport(): boolean; + +Prints a random events progress report for the current script. + +.. note:: + + Author: Coh3n + Last Modified: Jan. 22nd, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + SRLRandomsReport(); +*) +procedure SRLRandomsReport(); +var + i: integer; +begin + writeln('|====================================|'); + writeln('| ~ SRL ~ |'); + writeln('| Randoms Report |'); + writeln('|────────────────────────────────────|'); + writeln('| |'); + + for i := 0 to high(SRL_Randoms) do + begin + if (SRL_Randoms[i].name = '') then + continue; + + if (SRL_Randoms[i].solved > 0) then + writeln('| '+padR(SRL_Randoms[i].name + +' Solved', 22)+' ~ '+padR(toStr(SRL_Randoms[i].solved), 7)+'|'); + + if (SRL_Randoms[i].failed > 0) then + writeln('| '+padR(SRL_Randoms[i].name + +' Failed', 22)+' ~ '+padR(toStr(SRL_Randoms[i].failed), 7)+'|'); + end; + + writeln('| |'); + writeln('|────────────────────────────────────|'); + writeln('|====================================|'); +end; + +(** + * Author: Coh3n + * Description: Sets the SRL_Randoms global array. + *) +procedure _SetRandoms(); +var + i: integer; +begin + SRL_RandomsSet := true; + exit; + if (SRL_RandomsSet) then + exit; + + with SRL_Randoms[SRL_RAND_DEMON] do + begin + name := 'Drill Demon'; + solve := @DD_Solve; + detect := @DD_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_MAZE] do + begin + name := 'Maze'; + solve := @Maze_Solve; + detect := @Maze_Detect; + isInvRandom := false; + hasRewardBox := false; + end; + + with SRL_Randoms[SRL_RAND_EVILBOB] do + begin + name := 'Evil Bob'; + solve := @EB_Solve; + detect := @EB_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_MORDAUT] do + begin + name := 'Mordaut'; + solve := @MD_Solve; + detect := @MD_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_CERTERS] do + begin + name := 'Certers'; + solve := @CT_Solve; + detect := @CT_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_MIME] do + begin + name := 'Mime'; + solve := @Mime_Solve; + detect := @Mime_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_ABYSS] do + begin + name := 'Abyss'; + solve := @Abyss_Solve; + detect := @Abyss_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_FROG] do + begin + name := 'Frog'; + solve := @Frog_Solve; + detect := @Frog_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_PINBALL] do + begin + name := 'Pinball'; + solve := @PB_Solve; + detect := @PB_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_SANDWICH] do + begin + name := 'Sandwich Lady'; + solve := @SL_Solve; + detect := @SL_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_PILLORY] do + begin + name := 'Pillory (Cage)'; + solve := @PL_Solve; + detect := @PL_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_ARNAV] do + begin + name := 'Cap''n Arnav'; + solve := @CA_Solve; + detect := @CA_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_QUIZ] do + begin + name := 'Quiz Master'; + solve := @Quiz_Solve; + detect := @Quiz_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_LEO] do + begin + name := 'Leo'; + solve := @Leo_Solve; + detect := @Leo_Detect; + isInvRandom := false; + hasRewardBox := true; + disabled := true; + end; + + with SRL_Randoms[SRL_RAND_PETE] do + begin + name := 'Prison Pete'; + solve := @PP_Solve; + detect := @PP_Detect; + isInvRandom := false; + hasRewardBox := true; + disabled := true; + end; + + with SRL_Randoms[SRL_RAND_FORESTER] do + begin + name := 'Freaky Forester'; + solve := @FF_Solve; + detect := @FF_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_BEEKEEPER] do + begin + name := 'Beekeeper'; + solve := @BK_Solve; + detect := @BK_Detect; + isInvRandom := false; + hasRewardBox := true; + end; + + with SRL_Randoms[SRL_RAND_MOLLY] do + begin + name := 'Molly'; + solve := @Molly_Solve; + detect := @Molly_Detect; + isInvRandom := false; + hasRewardBox := true; + disabled := false; + end; + + with SRL_Randoms[SRL_RAND_REWARDS] do + begin + name := 'Rewards'; + solve := @RD_Solve; + detect := @RD_Detect; + isInvRandom := true; + hasRewardBox := true; + end; + + // disable all randoms if set to + + if (SRL_DisableRandoms) then + begin + addToSRLLog('**** WARNING: Disabling random event solvers'); + + for i := 0 to high(SRL_Randoms) do + SRL_Randoms[i].disabled := true; + end; + + SRL_RandomsSet := true; +end; + +(** + * Author: Coh3n + * Description: Detects and solves the random of index 'rand' in the SRL_Randoms + * array. Returns true if a random is found, not necessarily if it is solved. + * Manually returns true if the random was solved by hand using SRL's Random + * tool. + *) +function _SolveRandom(rand: integer; var manually: boolean): boolean; +var + solved: boolean; + oldCompass: extended; +begin + if (not loggedIn) then + exit; + + if ({$IFDEF Lape}@{$ENDIF}SRL_Randoms[rand].detect <> nil) and (SRL_Randoms[rand].detect()) then + begin + addToSRLLog('***** Found Random: '+SRL_Randoms[rand].name+' *****'); + players[currentPlayer].rand := SRL_Randoms[rand].name; + result := true; + + if SRL_HasProc(SRL_OnFindRandom) then + SRL_Procs[SRL_OnFindRandom](); + + // see if the script is using SRL's random tool + if (RT_UseRandomTool) then + if (RT_Execute()) then + begin + addToSRLLog('***** Solved Random Manually: '+SRL_Randoms[rand].name+' *****'); + manually := true; + exit; + end; + + // only take a screenshot if needed + if ((SRL_RandomScreenShot) and (not SRL_Randoms[rand].isInvRandom)) then + takeScreen(SRL_Randoms[rand].name); + + // sometimes it gets in the way of objects we need to find + toggleMoneyPouch(false); + exitSquealOfFortune(); + + // if solver isn't disabled, solve it + if (not SRL_Randoms[rand].disabled) then + begin + oldCompass := rs_GetCompassAngleDegrees(); + + if ({$IFDEF Lape}@{$ENDIF}SRL_Randoms[rand].solve <> nil) and (SRL_Randoms[rand].solve()) then + begin + addToSRLLog('***** Solved Random: '+SRL_Randoms[rand].name+' *****'); + players[currentPlayer].rand := ''; + inc(SRL_Randoms[rand].solved); + solved := true; + end; + + makeCompass(oldCompass); // restore the compass to its original angle + + end else + addToSRLLog(SRL_Randoms[rand].name+' solver currently disabled'); + + if (not solved) then + begin + addToSRLLog('***** Failed Random: '+SRL_Randoms[rand].name+' *****'); + + // solver didn't fail, it's disabled + if (not SRL_Randoms[rand].disabled) then + inc(SRL_Randoms[rand].failed); + + // set player to false and logout if the solver failed or is disabled + players[currentPlayer].active := false; + result := false; + logout(); + end; + end; +end; + +(** + * Author: Coh3n + * Description: Finds and solves all the randoms. Checks inventory if checkInv + * is set to true. This function should only be called in FindNormalRandoms and + * FindNonInventoryRandoms. + *) +function _Callback_SolveRandom: Boolean; +var + b: Boolean; +begin + Result := _SolveRandom(SRL_RAND_REWARDS, b); +end; + +function _FindAllRandoms(checkInv: boolean): boolean; +var + i: integer; + manually: boolean; +begin + // no tabs exists if bank is open; could throw false positives + if (not loggedIn()) or (bankScreen()) then + exit; + + if (not SRL_RandomsSet) then + _SetRandoms(); + + // handle the GE update message + if (findNPCChatText('exchan', nothing)) then + clickContinue(true, true); + + for i := 0 to high(SRL_Randoms) do + begin + if ((SRL_Randoms[i].isInvRandom) and (not checkInv)) then + continue; + + if (_SolveRandom(i, manually)) then + begin + // if the random was solved by hand, break out of the loop + if (manually) then + begin + result := true; + break; + end; + + // solve reward box if a non inventory random was just solved + if (loggedIn()) then // if solver failed, player would be logged out + if (not SRL_Randoms[i].isInvRandom) then + begin + // reward box doesn't exist if inventory is full/some randoms don't have reward box + result := (invFull() or (not SRL_Randoms[i].hasRewardBox)); + + if (not result) then + begin + if (waitFunc(@_Callback_SolveRandom, 50, 5000)) then + _SolveRandom(SRL_RAND_REWARDS, manually); // check if we chose another reward + end; + end; + + result := true; + end; + + // don't want to keep looking for randoms if one was already detected, but failed + if ((result) or (not loggedIn())) then + break; + end; + + findDead(); + findMod(); + findDwarvenPopup(); + exitSquealOfFortune(); + closeAdWindow(); + if checkInv then + findSpinTicket(); + + if SRL_HasProc(SRL_OnRandomCall) then + SRL_Procs[SRL_OnRandomCall](); +end; + +(* +FindNormalRandoms +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindNormalRandoms(): boolean; + +Finds and solves Runescape's random events. Returns true if an event was +solved. + +.. note:: + + Author: Coh3n + Last Modified: Jan. 22nd, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + FindNormalRandoms(); +*) +function FindNormalRandoms(): boolean; +begin + result := _FindAllrandoms(true); +end; + +(* +FindNonInventoryRandoms +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindNonInventoryRandoms(): boolean; + +Finds and solves all Runescape's non inventory random events (i.e. the ones that +teleport the player somewhere else). Returns true if an event was solved. + +.. note:: + + Author: Coh3n + Last Modified: Jan. 22nd, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + FindNonInventoryRandoms(); +*) +function FindNonInventoryRandoms(): boolean; +begin + result := _FindAllRandoms(false); +end; diff --git a/SRL/core/antirandoms/beekeeper.simba b/SRL/core/antirandoms/beekeeper.simba new file mode 100644 index 0000000..faeae3a --- /dev/null +++ b/SRL/core/antirandoms/beekeeper.simba @@ -0,0 +1,269 @@ +(* +Beekeeper +========= + +Stores all the routines to solve the Beekeeper random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +This solver uses pixel shifting to determine which hive piece goes where. + +*) + +type + TBeePiece = record + name: string; + minPixelShift, maxPixelShift: integer; + dragPoint: TPoint; + end; + TBeePieceArray = array of TBeePiece; + +const + BK_PIECE_COUNT = 4; + BK_PIECE_LID = 0; + BK_PIECE_UPPER = 1; + BK_PIECE_LOWER = 2; + BK_PIECE_LEGS = 3; + +const + _NPC_BEEKEEPER = '888l8808!'; + +(** + * Author: + * Description: Detects if a player is in the '' random. + *) +function BK_Detect(): boolean; +begin + if (not tabExists(TAB_MAGIC)) then + result := (getNPCChatName() = _NPC_BEEKEEPER); +end; + +(** + * Author: Coh3n + * Description: Returns an array of all the hive pieces. + *) +function BK_GetPieces(): TBeePieceArray; +begin + setLength(result, BK_PIECE_COUNT); + + with result[BK_PIECE_LID] do + begin + name := 'Lid'; + minPixelShift := 2950; + maxPixelShift := 3500; + dragPoint := point(260, 45); + end; + + with result[BK_PIECE_UPPER] do + begin + name := 'Upper Middle'; + minPixelShift := 2000; + maxPixelShift := 2400; + dragPoint := point(260, 100); + end; + + with result[BK_PIECE_LOWER] do + begin + name := 'Lower Middle'; + minPixelShift := 2420; + maxPixelShift := 2550; + dragPoint := point(260, 150); + end; + + with result[BK_PIECE_LEGS] do + begin + name := 'Legs'; + minPixelShift := 2600; + maxPixelShift := 2820; + dragPoint := point(260, 200); + end; +end; +(** + * Author: Coh3n + * Description: Returns a TBox of the piece slot, 'slot'. + *) +function BK_PieceBox(slot: integer): TBox; +begin + result := gridBox(slot, 1, 4, 100, 50, 100, 50, point(77, 53)); +end; + +(** + * Author: Coh3n + * Description: Returns true if the puzzle screen is open. + *) +function BK_Screen(): boolean; +var + x, y: integer; +begin + // the color of the text + result := findColorTolerance(x, y, 2071039, 363, 36, 493, 137, 10); +end; + +(** + * Author: Coh3n + * Description: Gets the pixel shift in slot 'slot'. + *) +function BK_ScanPiece(slot: integer): integer; +begin + addToSRLLog('BK_ScanPiece: Scanning slot '+toStr(slot)); + result := averagePixelShift(BK_PieceBox(slot), 1000, 5000); +end; + +(** + * Author: Coh3n + * Description: Goes through conversations with the Beekeeper. + *) +function BK_TalkTo(): boolean; +var + t: integer; +begin + t := (getSystemTime + 10000); + + // keep clicking continue until the puzzle screen appears + while (getSystemTime < t) and (not result) do + begin + clickContinue(true, true); + + // appears if failed or exited screen + if (findNPCChatText('let', nothing)) then + typeByte(VK_2); + + result := BK_Screen(); + wait(100 + random(200)); + end; + + if (not result) then + addToSRLLog('BK_TalkTo: Failed to talk to the Beekeeper'); +end; + +(** + * Author: Coh3n + * Description: Identifies and drags each piece to the proper slots. + *) +function BK_BuildHive(pieces: TBeePieceArray): boolean; +var + i, j, t, numDone, tmpShift: integer; + p: TPoint; + compareShifts: boolean; + slotDone: array[1..4] of boolean; + pieceDone: TBooleanArray; +begin + if (not loggedIn()) and (not BK_Screen()) then + exit; + + t := (getSystemTime + (5 * 60000)); + setLength(pieceDone, length(pieces)); + + repeat + for i := 1 to 4 do // 4 piece slots + begin + if (slotDone[i]) then // skip slots already done + continue; + + // no point in scanning if there's only one piece left + if (numDone <> 3) then + tmpShift := BK_ScanPiece(i) + else + tmpShift := 1001; // to statisfy the next if statement + + // in case a dragging failed during last attempt + if (tmpShift < 1000) then + begin + addToSRLLog('BK_BuildHive: No piece in slot '+toStr(i)); + slotDone[i] := true; + break; + end; + + addToSRLLog('BK_BuildHive: Piece shift = '+toStr(tmpShift)+' in slot '+toStr(i)); + + for j := 0 to high(pieces) do + begin + if (pieceDone[j]) then // skip pieces already done + continue; + + // if there's only one item left, drag it to the last slot + if (numDone <> 3) then + compareShifts := inRange(tmpShift, pieces[j].minPixelShift, pieces[j].maxPixelShift) + else + compareShifts := true; + + if (compareShifts) then + begin + addToSRLLog('BK_BuildHive: Found '+pieces[j].name+' in slot '+toStr(i)); + + p := middleBox(BK_PieceBox(i)); + dragMouse(p.x, p.y, 15, 15, pieces[j].dragPoint.x, pieces[j].dragPoint.y, 5, 5); + + // set variables to optimize speed + compareShifts := false; + pieceDone[j] := true; + slotDone[i] := true; + inc(numDone); + break; + end; + end; + end; + + // if there are no pieces left to drag, we must be done + for i := low(slotDone) to high(slotDone) do + if (not slotDone[i]) then + break + else + result := (i = high(slotDone)); + + if (not result) then + result := (numDone = 4); + + wait(200 + random(300)); + + until(result or (getSystemTime > t)); + + if (result) then + begin + addToSRLLog('BK_BuildHive: Finished dragging pieces'); + mouse(277, 280, 10, 5, mouse_Left); // click the BUILD button + end else + addToSRLLog('BK_BuildHive: Solver timed out'); +end; + +(** + * Author: Coh3n + * Description: Solves the random. + *) +function BK_Solve(): boolean; +var + fails: integer; + pieces: TBeePieceArray; +begin + if (not loggedIn()) then + exit; + + pieces := BK_GetPieces(); + + repeat + if (BK_TalkTo()) then + if (BK_BuildHive(pieces)) then + if (waitNPCTalking(_NPC_BEEKEEPER, 5000)) then + if (findNPCChatText('No', nothing)) then // if it wasn't solved right + begin + addToSRLLog('BK_Solve: Failed to solve properly'); + inc(fails); + end else begin + doConversation('', false); + result := waitTabExists(TAB_MAGIC, 8000); + end; + + result := tabExists(TAB_MAGIC); // just in case + + until(result or (fails >= 6) or (not loggedIn())); // Beekeeper gives a maximum of 6 tries + + if (fails >= 6) then + begin + addToSRLLog('BK_Solve: Failed too many times'); + result := false; + exit; + end; + + if (result) then + addToSRLLog('BK_Solve: Solved Beekeeper'); +end; diff --git a/SRL/core/antirandoms/capnarnav.simba b/SRL/core/antirandoms/capnarnav.simba new file mode 100644 index 0000000..66c099c --- /dev/null +++ b/SRL/core/antirandoms/capnarnav.simba @@ -0,0 +1,259 @@ +(* +Cap'n Arnav +=========== + +Stores all the routines to solve the Cap'n Arnav random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +This solver uses DTMs to determine which items are in the middle of the puzzle. +It will keep rotating the items until the one we're looking for is found in the +center slot. + +*) + +const + CA_NAME_ARNAV = 'C50!04!05u'; + + DTM_CA_COUNT = 4; + DTM_CA_RING = 0; + DTM_CA_BAR = 1; + DTM_CA_COINS = 2; + DTM_CA_BOWL = 3; + +(** + * Author: Coh3n + * Description: Returns true if player is in the random. + *) +function CA_Detect(): boolean; +begin + if ((not tabExists(TAB_MAGIC)) and (not tabExists(TAB_INV))) then + if (countColorTolerance(9931907, MMX1, MMY1, MMX2, MMY2, 15) > 1000) then // water color + if (inRange(countDots('npc'), 3, 5)) then + result := tabExists(TAB_MUSIC); +end; + +(** + * Author: DemiseScythe + * Description: Loads the item's DTMs. + *) +function CA_GetDTMs(): TIntegerArray; +begin + setLength(result, DTM_CA_COUNT); + + result[DTM_CA_RING] := DTMFromString('m6wAAAHic42ZgYLgMxKeB+CgUXwLi60D8CIgfAPFDIL4CxDeBeDEQzwLiOUC8EojXAvFGIF4BxPOAeBoQzwDiKUC8e+1Uhrd3lBg+X1JmOLNPlqGrXIThzhl5hhNrZBmeXVVkyI3jZ7i1R56hv0aEgR+onljMSAJGAgC5kiIz'); + result[DTM_CA_BAR] := DTMFromString('m6wAAAHic42ZgYOBhQABeKBYHYgkglgRiKSR5MSCWBmI+INaEirEAsQAQy0LFtKHiVZGCDNm+/AwpnnwMvWkiDMXBAgxNcUIM/ekiDLMLxBiWV4ozlIYIMMS58DLwA9UTixmBmIlIjAQAHY4MWg=='); + result[DTM_CA_COINS] := DTMFromString('mAAEAAHic42FgYOBjgABGIOYGYn4gVgFiNSCWBWJhqDgzELNB+RxIekBsSSAWgOqVAmJFKC0KxL+uKzOcXCvD8Py4IsPvm8oMDw8pMFzfKcfw45oyw7crygxvzygy7FsiDVbz8oQi2AxSMMgNTCRgZAAAn4IXqw=='); + result[DTM_CA_BOWL] := DTMFromString('mAAEAAHiclcs/CoIAAEbxzz3oIAUVJVkg9HfRK0lzQ9YQFE1SBEJQ4SYNQksnUAk8hXSB3ujqg9/4GpJGhjTEAB10YcLGEg4WmMBCwHPAFkecccMdEZ644oQ1knCs9DXVN5kpvlgK930Fm558r6Xdqq3Pw1bxnqvMHP1yV02eOoyaqv0BVbQe0g=='); +end; + +(** + * Author: Coh3n + * Description: Returns true if the lock screen is open. + *) +function CA_LockScreen(): boolean; +var + x, y: integer; +begin + // looks for the text in the top right of the lcok screen + result := findText(x, y, 'lick', smallChars, MSCX, MSY1, MSX2, MSCY); +end; + +(** + * Author: Coh3n + * Description: Returns a TBox of the slot 'slot' for the lock grid. Top left + * is slot 1. + *) +function CA_LockBox(slot: integer): TBox; +begin + result := gridBox(slot, 3, 3, 90, 82, 90, 82, point(127, 79)); +end; + +(** + * Author: Coh3n + * Description: Returns a TBox of the slot 'slot' for the top arrows. + *) +function CA_ArrowBox(slot: integer): TBox; +begin + result := gridBox(slot, 3, 1, 45, 30, 88, 0, point(125, 25)); +end; + +(** + * Author: Coh3n + * Description: Talks to Cap'n Arnav and returns true when the lock screen is + * open. + *) +function CA_TalkToArnav(): boolean; +var + dtmArnav, t: integer; +begin + if (not loggedIn() and (not CA_LockScreen)) then + exit; + + addToSRLLog('CA_TalkToArnav: Talking to Cap''n Arnav'); + dtmArnav := DTMFromString('mggAAAHicY2NgYGhiZGCoAeIWIG4H4kYgbgXip0C5V1D8GIjvAfF9IK6tzmEoz3Ri8DDXYPDWF2PYOz2TYWFDJIMkUA4bZsSBIQAAPqYQBQ=='); + + if (clickDTMRotatedIn(dtmArnav, MSCX+50, MSY1, MSX2, MSY2, -Pi/4, Pi/4, Pi/30, ['rnav'], mouse_Left) or waitNPCTalking(CA_NAME_ARNAV, 1000)) then + begin + if (waitNPCTalking(CA_NAME_ARNAV, 4000)) then + begin + t := (getSystemTime + 20000); + + while ((getSystemTime < t) and (not CA_LockScreen())) do + begin + doConversation('', false); + + if (findNPCChatText('ready', nothing)) then + begin + typeSend('2'); + addToSRLLog('CA_TalkToArnav: Clicked chat box text'); + wait(500 + random(500)); + end; + end; + end; + + end else + addToSRLLog('CA_TalkToArnav: Didn''t click Arnav DTM'); + + result := CA_LockScreen(); + freeDTM(dtmArnav); +end; + +(** + * Author: nielsie95 & Coh3n + * Description: Returns which item is needed to open the chest. + *) +function CA_GetTarget(): integer; +var + tpa: TPointArray; + s: TStringArray; +begin + if ((not loggedIn()) or (not CA_LockScreen())) then + exit; + + addToSRLLog('CA_GetTarget: Identifying chest target'); + + // the black color of the text shadow + findColorsTolerance(tpa, 1119769, 7, 150, 80, 185, 15); + + case length(tpa) of + 116: result := DTM_CA_RING; // set to DTM constant to easily access the correct DTM + 84 : result := DTM_CA_BAR; + 108: result := DTM_CA_BOWL; + 102: result := DTM_CA_COINS; + + else + writeLn('CA_GetTarget: Could not get Arnav target'); + end; + + s := ['Ring', 'Bar', 'Coins', 'Bowl']; + addToSRLLog('CA_GetTarget: Found target: '+s[result]); +end; + +(** + * Author: DemiseScythe & Coh3n + * Description: Returns true if the chest has been unlocked. + *) +function CA_FixLock(DTMs: TIntegerArray): boolean; +var + i, t, t2, target, x, y: integer; + b: TBox; + aFound: extended; + colDone: array[1..3] of boolean; +begin + if ((not loggedIn()) or (not CA_LockScreen())) then + exit; + + addToSRLLog('CA_FixLock: Fixing lock'); + target := CA_GetTarget(); + + for i := 1 to 3 do // arrows 1, 2, and 3 + begin + t := (getSystemTime + (2 * 60000)); + + repeat + b := CA_LockBox(i + 3); // slots 4, 5, and 6 + t2 := (getSystemTime + 5000); // time to ID item in each column before rotating + + // try to find the target DTM + while (getSystemTime < t2) do + begin + if (findDTMRotatedAlternating(DTMs[target], x, y, b.x1, b.y1, b.x2, b.y2, -Pi, Pi, Pi/30, aFound)) then + begin + addToSRLLog('CA_FixLock: Found target in slot '+toStr(i)); + colDone[i] := true; + break; + end; + + wait(50 + random(50)); + end; + + if (colDone[i]) then // continue with the for loop + break; + + // rotate the item if needed + b := CA_ArrowBox(i); + mouseBox(b.x1, b.y1, b.x2, b.y2, mouse_Left); + wait(500 + random(500)); + + until(colDone[i] or (getSystemTime > t)); + + result := (colDone[1] and colDone[2] and colDone[3]); + end; + + if (result) then + begin + mouse(440, 250, 20, 10, mouse_Left); // click the unlock button + + // have to make sure we did it right + result := false; + if (waitNPCTalking(CA_NAME_ARNAV, 3000)) then + result := findNPCChatText('hanks', nothing); + end; + + if (result) then + addToSRLLog('CA_FixLock: Fixed lock') + else + addToSRLLog('CA_FixLock: Didn''t fix lock'); +end; + +(** + * Author: + * Description: Solves the random. + *) +function CA_Solve(): boolean; +var + t, tries, dtmPortal: integer; + DTMs: TIntegerArray; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + (6 * 60000)); + DTMs := CA_GetDTMs(); + dtmPortal := DTMFromString('mbQAAAHicY2VgYPgHxOyMDAz/gfQPIGYFsoOBtB8QewGxPxBHAPGuB/0M+19OAWMQe8eHXgZ+oDg6BmpnYELDYAAAF5wP7g=='); + clickNorth(SRL_ANGLE_HIGH); + + repeat + if (not CA_LockScreen) then + CA_TalkToArnav() + else + if (CA_FixLock(DTMs)) then + begin + if (clickPortal(dtmPortal)) then + result := waitTabExists(TAB_MAGIC, 10000); + end else + inc(tries); + + until(result or (tries >= 5) or (getSystemTime > t)); // 5 failed we fail the random + + if (not result) and (getSystemTime > t) then + addToSRLLog('CA_Solve: Cap''n Arnav solver timed out') + else + if (not result) and (tries >= 5) then + addToSRLLog('CA_Solve: Cap''n Arnav failed after 5 tries'); + + freeDTM(dtmPortal); + freeDTMs(DTMs); +end; + diff --git a/SRL/core/antirandoms/certers.simba b/SRL/core/antirandoms/certers.simba new file mode 100644 index 0000000..c15f568 --- /dev/null +++ b/SRL/core/antirandoms/certers.simba @@ -0,0 +1,293 @@ +(* +Certers +======= + +Stores all the routines to solve the Certers random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +This solver uses multiple DTMs to identify each item. If an item can't be +identified right away, it will rotate the item and loop through the items again. + +*) + +const + CT_ITEM_COUNT = 9; + CT_ITEM_BOWL = 0; + CT_ITEM_SHEARS = 1; + CT_ITEM_RING = 2; + CT_ITEM_SWORD = 3; + CT_ITEM_BATTLEAXE = 4; + CT_ITEM_SHIELD = 5; + CT_ITEM_SPADE = 6; + CT_ITEM_HELMET = 7; + CT_ITEM_FISH = 8; + +type + TCTItem = record + name, text: string; // name and text to click + DTMs: TIntegerArray; + end; + TCTItemArray = array of TCTItem; + +(** + * Author: DemiseScythe + * Description: Detects if a player is in the Certers random. + *) +function CT_Detect(): boolean; +var + s: string; +begin + if (tabExists(TAB_MAGIC)) then + exit; + + s := getNPCChatname(); + result := (s = 'Dll8g' {Miles/Niles}) or (s = 'Gll8g' {Giles}); +end; + +(** + * Author: Coh3n, DTMs by DemiseScythe + * Updated by: [J]ustin - Bowl DTM - 9/06/2012 + * Description: Returns a TCTItemArray of all the Certer items. + *) +function CT_GetItems(): TCTItemArray; +begin + //setLength(result, CT_ITEM_COUNT); + setLength(result, 9); + + with result[CT_ITEM_BOWL] do + begin + name := 'Bowl'; + text := lowercase(name); + DTMs := [ + DTMFromString('mAAEAAHic42FgYGBiZGBgBuKfDBCaD4i/ANmvgFgGyBYG4k9AtiBU3TUg+ywQXwXiuwwQ/kkgfgDEj4H4FBC/A+IPQPwRiAsy5BhyU2UZijLlGIqz5MD88lx5hvx0WQY7Z3GGhBhphsRYGQYHV3EG/wBJBn6gHlIwI8gPJGBkAADRtRm0'), + DTMFromString('mlwAAAHicY2dgYJBggABmIJYCYgMg1gFicSAWAmIuIFYBYn0gloPyQaA0T5GhpkSJIStNnsHLX5rByVOSITZWliEvS4GBHyiPCzMCMRMODAUAmFgH6Q=='), + DTMFromString('mrAAAAHic42BgYLBkZmAIB+JkIM4AYg8gjgTiCCC2AuIHjAwMh4D4FBC/BOIvQPwNiO8A8QsgDrBUY2iL12WYVOrL0JnrxTC13J+hO1mPoTpch8HTWIWBC2gHPsxIAMMAAPvdEnw='), + DTMFromString('mwQAAAHic42RgYPBmZmAwAWIZIFYGYkMgdgNiPyD2AGJtID7IyMBwCIjPA/F1IH4CxKeAeDcQXwbiG0AcbqPM0BqrydAQqcGQ7q7KkOGhyqArK8OQ663GEGKlxBBmrcTABbSPEGYkAsMBADNLENU=') + ]; + end; + + with result[CT_ITEM_SHEARS] do + begin + name := 'Shears'; + text := lowercase(name); + DTMs := [ + DTMFromString('mPwEAAHic42dgYOBgZGBgBWIRIBYAYm4g5gdiUSBmAGI2IP4JZDIB6d9A+gcQfwXil0D8Coi/QOkPUDZIzXcgfg7ED6D4JhBfBuJjQHwNiC8CcVqyK0NDVTBDYa4XQ1SkHUNmmhtYDERnpLgxuLgaMgT4WzC4uRsz+PkYMCTHWTKEBpkwZKfaMvAD9ZOLQd5iIhOjAQCPQCJj'), + DTMFromString('mVAEAAHicE2BgYPgPxD+A+DMQ/4LyPwDxayB+D8RfoeJvgfglEHMxMjAwAjEPELMD8WWg2HUgvgvED4D4BhA/har/CDXnORA/BOIXQLwfiE8B8VEgPgvECXGODGWFfgx5WZ4MwcFWDH5+5gy1Ja4M7bVeDKkJVgzhIaYMnh56DIVZDgz5mQ4M5UX+DI3VIQwZqW4MmWnuDPxAMyjBQC8wMFGA0QEAfj0reg==') + ]; + end; + + with result[CT_ITEM_RING] do + begin + name := 'Ring'; + text := lowercase(name); + DTMs := [ + DTMFromString('mVAEAAHicE2BgYPgDxD+A+DsQMzKCCAgbxgfJg8R+AikmIP0Xqp4Ryn4BxI+B+DWUfgPEnxkg6n8B8Tcg/gLEd4D4NhBfhOJLQHwaiBOirRjSk2wZinOdGDw99BnCQ80YqopdGSZ0xDLkZ3sz5Gc6gtWkJFgzeHsZMAQGWDF0N0cxmFvqMNja6zPwA82gBIO8zEQBRgcA6YwpHQ=='), + DTMFromString('mFQEAAHic42VgYGBjZGBgBmI+IGYFYk4g/g8U/wXFIDYnVF4QiHmB+A5Q7BkQPwXi11B8C4gvAfFJID4MxIeA+DgQnwPiG0BcX+rG0NcaxbBqbhZDeooVQ3NNKENuqh1Daa4jQ3WhM0NThTtDXYkrWCw/3Q7M5wfqIxUDncfARCJGAQD5FyAT'), + DTMFromString('mrAAAAHic42BgYDjEycBwFoiPA/EBIN4DxDuA+CCUbcnIwKAGxIpQWg+ITaB8VSDevDSWoTzPgKG3wZIhNU6DoSBDl2FSqw1DfpoOWJwLaAc+zEgAwwAA2mURbw=='), + DTMFromString('m6wAAAHic42ZgYDjBycBwGIjPAfF1ID7LiRAD4d1AfACI9wCxMSMDgwwQKwKxDhDbALEDEFsCsT0QawCxIVS+udGGob7agKEwX5MhK0eeYUKvM0Nbiy1DT6cDQ0GBJkNbozFDfp4mQ0ezCQMX0B3EYkYSMBIAAAyrGGs=') + ]; + end; + + with result[CT_ITEM_SWORD] do + begin + name := 'Sword'; + text := lowercase(name); + DTMs := [ + DTMFromString('mPwEAAHic42dgYPgNxD+h9Fcg/g/l/4CK/YDy/0H5IPk/QMzIyMBwA0g/AeLXQPwBiD8D8Scg/o6k5gKQPgnEB4F4JxBvAOJVQNxUGcxQWeTHUJbnw1BX7MKQn2bLUJHnwDCpI4ahuzGCoSTLnqG62I+htymCoaU6mGFqdyxDR30YWI4fqJ9czEQBRgMABzot8Q=='), + DTMFromString('mAAEAAHic42FgYPgFxb+xsEH0DyD+gyT3EUqzMjIw8AOxKBC/BPLvAfEVID4DxKeA+AgQ7wNiL3dDBl9PY4bkWAcwrir0YUhPdGLwcDVgyEx0ZqgvcmII8zdgiAi2ZPD31GHgB+ohBQOtZ2AiASMDADBgH6M=') + ]; + end; + + with result[CT_ITEM_BATTLEAXE] do + begin + name := 'BattleAxe'; + text := lowercase(name); + DTMs := [ + DTMFromString('mJgIAAHick2JgYOBnZGAQBGJRIBYGYglGiBgXEPMAMRsQcwIxMxAzAPEfBgj+BsRfgfgzlAbpEQJiEagZUkAsB2WDxF4A1TwE4jtAfA2IzwPxRyD+BMQ/gPgfA8SO70D6N1T8FRC/hqr7CcT/gZiFEUKzQd3zCyrGCXV3VYknQ2WxB0NxnhtDeZEHQ2GOK5iuLfMCy9VXeDNUl3oxlJcEMXQ0xzAUFwQwZGd6M+Tn+DJUl4cwVJWFMNRWhDJM7klkaKgJZ+hujWUoKw4CqyvM82dorIkAY36Qn+mAQd5kogPGDQCBfztn'), + DTMFromString('mJgIAAHicvdA/S4JRHMXxUwgRKQU2hCj4HkKTECIcSkJFUVSeEkX6I4kU5FKTb6ctSFBSVEiMlnBobeoFFC3aEH59uGurFz7cy7mH34XrkbS2JDmxYWxiBQ6swgW3yee24DO7B3548cesX0yNH3zjCxO8Yox3fOATz3hCFy100MQ9HvBo8p7pDdE3vQFe0Db3I7zhOBeyZVIB5TNBpRLbKp/s6qwUlpXd0eX5oazcnupXcTVu07qrJ+1z5fRApUJE1YuoapWoCta+3Z3n8VhIN7WY7bp6pHIxonXeWgS+VssL8P+aAXLdOcY=') + ]; + end; + + with result[CT_ITEM_SHIELD] do + begin + name := 'Shield'; + text := lowercase(name); + DTMs := [ + DTMFromString('mfgEAAHicE2JgYPgAxC+A+DsQ/wXiz0B8B4ivAvElIL4IxKeB+D5UDScjA4MEEAswQtiCjBA9N4D4GhBfAOKbQPwUiK8A8RkgPgDE94D4DdS+o0B8GyoGMv8UVP17IJ5Q5s4wsdyDYXqtF8OkCg+GvlI3MD2j1huMu4pcGRqzHBnKEmzAfJDa6hRbuJ7KZBuGllwnBn6gWdTAQO8xMFEBYwIAOLkzag=='), + DTMFromString('mVAEAAHicE2BgYBBjZGAQAmIZIFYGYh0gtgJieyBWAmIRIOYFYnYg5gDiP0A9n4D4GxB/BOKjQHwYiA8B8UEgPgLEx4H4FBCfhGKYmhNQ+cNQ8dNAPKXMn2FSiR/DgpZkhkWtQNyWAhYriXZk6Mn3YWjN9ASLgeS787wZegt8GMrjnBkKojwY0gKsGfiBZlCCgV5iYKIAowMAy0onqA==') + ]; + end; + + with result[CT_ITEM_SPADE] do + begin + name := 'Spade'; + text := lowercase(name); + DTMs := [ + DTMFromString('mJgIAAHick2JgYOAFYj4gFgFiMSifDYiZgZgDiAWhYjAMA6xQdSCaBYi5oFgYqkcSiKWAWBpqtgQQu0KxPRDbQtmOULYNEJsAsQ4Qq0LtAunjAWIhJDuZoPYwQt3HjGQvCHf2BzBUN9gyNLc7MmQXmzFU1NowVNXbMtQ22TG0dDgyZBaaguVBYiB6+pxIsrAI1H20xoxQP9Ma4wYAphgrGg=='), + DTMFromString('m5wEAAHictdBBSwJRFIbhb1wL7XKhEK2mzBBHSGnhPhhCGaLRURxERv2PLmtVooFBZCJZJLrITT/A13GINi298HAPl8t3DichaYU5pnjDM4Z4wBgTPGKET3zjB4YhxXGIFJI4wglOcWzs8mZR5iteoh7v+MAXFlhj+efPOOq3nWGAe/Rxh6dovkanKC8o6MbP/6q1L1RpWGFdsk3Zbja8t/zepZx6RuVqWhXvTLVWVtduWs0gJ79rhW9Xjqnb5rkOyN8X1qLYnvxzNkLsNe8='), + DTMFromString('m6wAAAHic42ZgYChjZmDIAuISIK4F4nwgrgPidiCeBsQTgXgWEC8C4meMDAyPgPg7EH8D4tdA/BeIuZkYGLSB2BiILYHYDIgjXa0YXE30wTjZzwFMR7lbMwTbGzHEeZgxRLmaMmQGWYNpLqA7iMWMJGAkAACJ+RWu'), + DTMFromString('m1gAAAHic42JgYPjFyMDwDYjZmBgYeID4D5D9BoglgGw9IJYCYnUgjgaKeQGxCxCHAnEWEMcDsRoQSwExHxTPrk1gmFefyNCYFgimYbgxxYOhM9uboSnVA8zmAtpNDGYkEiMAAP4jFNc=') + ]; + end; + + with result[CT_ITEM_HELMET] do + begin + name := 'Helmet'; + text := lowercase(name); + DTMs := [ + DTMFromString('mkwEAAHicE2ZgYGBkZGBgA2J2IOYGYiZGhNg/oPwfBogYiP0DiD8CMQuQLwTE/4FsVqg+QSC+CuTfAOLLQHwTiG8B8T0oBsmdB+ILQHwaSc0zIL4CxMeB+BgQnwLic0BcVmTKUJQlz5CTKstQlqfAkJ8hxzBzoidDf4czQ2ayDENKvBRDeqIMw+QeV4ZpfW4MnU32DBUlZmD19aXKDKsWBDGsnB8IluMHmkctzAgKDyphLAAATHotqg=='), + DTMFromString('mqAEAAHicE2FgYGBnhGBuIGYEYgYg/g+kvgPxV6g8BxCLALEoEPMBMQ8QC0LFJKHif4BqWYD0AyD9GIjvAfE1IH4ExG+h9Ecg/gLE/4D4DhA/BOI3QPwLKv4KygfZ+xSIPwBxfoY5g5uDEIO1OT9Db5MHw6xef4baEnuG9loXhowkY4ZwfwkGf3dRhto8FYaNi2LA8lWFtgxTO30Y1s6LAuO5EwIZ+ls8GcrybBj4gWZSE4OCjImKGBsAAK6vMEA='), + DTMFromString('mAAEAAHic42FgYPgFxB+A+B0QMzIyMDAD8R8g+y8QvwViNiCfgxFCcwHxe6DYCyB+zABhPwXiR0D8E4i/Q815BsTfgPgTEFekuDNMq4tgaC8KYCiK0mFoTDNgmNEYxdBW6A/GG6alM6ybmsYwtzWaYWlvIgM/UA8pGOgkBiYSMDIAAA0EIiY=') + ]; + end; + + with result[CT_ITEM_FISH] do + begin + name := 'Fish'; + text := lowercase(name); + DTMs := [ + DTMFromString('m1gAAAHic42JgYGDiZGB4ysHAcAKIlwHxGiC+B8SPgPgrEP8HYl6gGj9GBgZXIDYBYltGCD8SiNOBOBaIw4E4BIjdQtQZ7P2UGZLyrBki0kwZ4nMsGcKT9Rg8I3QYsorNGNKLbcGYC2g3MZiRSIwAAFSFFBo='), + DTMFromString('mwQAAAHic42RgYFjPwcBwBYi/Q/FtIL4OxGug4g+AOJGRgcEYiNWB2AqIA4A4G4hzgTgCiH1A/Mokhqp6D4bKWneGju4Ahp5uF4bZc6IZpk2PYOjrdWPo7HRh4ALaRwgzEoHhAACqKhdS') + ]; + end; + +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Sets up to solve random. + *) +procedure CT_Setup(); +begin + if (not loggedIn()) then + exit; + + clickNorth(SRL_ANGLE_HIGH); +end; + +(** + * Author: Coh3n + * Description: Clicks the "Change spin" button 'clicks' times. + *) +procedure CT_ChangeSpin(clicks: integer); +var + i, x, y: integer; +begin + if (not loggedIn()) then + exit; + + mouse(364, 162, 5, 5, mouse_Move); + if (waitUptextMulti(['ange', 'nge', 'spin', 'pin'], 200)) then + begin + getMousePos(x, y); + + for i := 1 to clicks do + mouse(x, y, 0, 0, mouse_Left); + end; +end; + +(** + * Author: Coh3n + * Description: Identifies the item, waits for a mazimum of 30 seconds. + *) +function CT_IdentifyItem(items: TCTItemArray): integer; +var + i, j, t, t2, x, y: integer; + aFound: extended; +begin + if (not loggedIn()) then + exit; + + result := -1; + t := (getSystemTime + 60000); + addToSRLLog('CT_IdentifyItem: Identifying item...'); + markTime(t2); + + // loops through DTMs while item is rotating on screen + repeat + for i := 0 to high(items) do + for j := 0 to high(items[i].DTMs) do + // look in the box where the item is rotating + if (findDTMRotatedAlternating(items[i].DTMs[j], x, y, 145, 150, 370, 295, -Pi, Pi, Pi/30, aFound)) then + begin + addToSRLLog('CT_IdentifyItem: Found item ~ '+items[i].name); + result := i; + exit; + end; + + // change the spin every 15000 + if (timeFromMark(t2) >= 15000) then + begin + addToSRLLog('CT_IdentifyItem: Didn''t ID item, changing spin...'); + CT_ChangeSpin(randomRange(5, 10)); + markTime(t2); + end; + + until(getSystemTime > t); + + if (result = -1) then + addToSRLLog('CT_IdentifyItem: Didn''t identify item'); +end; + +(** + * Author: Coh3n + * Description: Clicks the correct item's text. + *) +function CT_SelectItem(item: TCTItem): boolean; +begin + if (clickText(item.text, charsNPC, 75, 40, 240, 180, mouse_Left)) then + begin + addToSRLLog('CT_SelectItem: Clicked item text'); + result := true; + end else + addToSRLLog('CT_SelectItem: Didn''t click text; may have ID''d wrong item'); +end; + +(** + * Author: Coh3n + * Description: Solves the random event, returns true when the portal is + * clicked. + *) +function CT_Solve(): boolean; +var + dtmPortal, i, t: integer; + items: TCTItemArray; +begin + if (not loggedIn()) then + exit; + + CT_Setup(); + dtmPortal := DTMFromString('mbQAAAHicY2VgYHjGyMDwCIjvAfEnIH4HxJuB4quAeBsQrwPiPUA8YWsSw8RtSQzTdqYytC2OZujeGM/ADxRHx4xYMBgAAJveEIE='); + items := CT_GetItems(); + t := (getSystemTime + (3 * 60000)); // maximum 3 minutes + + repeat + if (findNPCChatTextMulti(['ortal', 'atch'], nothing)) then + if (clickPortal(dtmPortal)) then + begin + result := waitTabExists(TAB_MAGIC, 8000); + break; + end; + + if (not areTalking) then + begin + i := CT_IdentifyItem(items); + + if (i <> -1) then + if (CT_SelectItem(items[i])) then + wait(2000 + random(500)); + + end else + clickContinue(true, true); // in case there are extra messages (GE) or we get one wrong + + until(getSystemTime > t); + + freeDTM(dtmPortal); + for i := 0 to high(items) do + freeDTMs(items[i].DTMs); + + if (not result) then + addToSRLLog('CT_Solve: Certers solver timed out'); +end; + diff --git a/SRL/core/antirandoms/common.simba b/SRL/core/antirandoms/common.simba new file mode 100644 index 0000000..b3f805c --- /dev/null +++ b/SRL/core/antirandoms/common.simba @@ -0,0 +1,333 @@ +(* +Common +====== + +The common randoms file stores any functions or procedures that are used +several random event solvers. + +*) + +const + SRL_NPC_OLDMAN = 'Dygt8!loqgGlgD50'; // chat name for Mysterious Old Man + +(** + * Author: Wizzup? & Coh3n + * Description: Type used to identify rotating items. Example, Quiz & Mordaut. + *) +type + TRotateObject = record + name, use: string; + count, width, height, totalCount: integer; + coverPercent: extended; + end; + TRotateObjectArray = array of TRotateObject; + +(* +ScanRotateObject +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ScanRotateObject(cols, tols: TIntegerArray; area: TBox; splitDist, tries: integer): TRotateObject; + +Returns a TRotateObject type depending on parameters given: + * cols: The colors you DO NOT want to find (calls InverseColors) + * tols: The tolerance on the colors in 'cols' + * area: The area to gather data (i.e. area of the rotating item) + * splitDist: The splitTPA distance (larger for larger items) + * tries: How many times to call returnTPAExceptColors before declaring result fields + +.. note:: + + Author: Wizzup? & Coh3n + Last Modified: Feb. 13th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + // MD_SmallBox is in mordaut.simba + item := getRotateObject([4410947, 5003083], [10, 10], MD_SmallBox(i), 25, 30); +*) +//{$i srl/srl/misc/debug.simba} +function ScanRotateObject(cols, tols: TIntegerArray; area: TBox; splitDist, tries: integer): TRotateObject; +var + i: integer; + bounds: TBox; + tmpTPA: TPointArray; + tmpATPA: T2DPointArray; + tmpObj: TRotateObject; +begin + for i := 1 to tries do + begin + tmpTPA := returnTPAExceptColors(cols, tols, area); + //debugTPA(tmpTPA, ''); + bounds := getTPABounds(tmpTPA); + + tmpATPA := splitTPA(tmpTPA, splitDist); + sortATPASize(tmpATPA, true); + + if (length(tmpATPA) <> 0) then + tmpTPA := tmpATPA[0] + else + setLength(tmpTPA, 0); + + // keep increasing the properties so we can find the average later + tmpObj.count := (tmpObj.count + length(tmpTPA)); + tmpObj.width := (tmpObj.width + (bounds.x2 - bounds.x1)); + tmpObj.height := (tmpObj.height + (bounds.y2 - bounds.y1)); + tmpObj.totalCount := (tmpObj.totalCount + ((bounds.x2 - bounds.x1) * (bounds.y2 - bounds.y1))); + end; + + // get the average and set the result + result.count := (tmpObj.count div tries); + result.width := (tmpObj.width div tries); + result.height := (tmpObj.height div tries); + result.totalCount := (tmpObj.totalCount div tries); + + if (result.totalCount > 0) then // to prevent math runtime errors + result.coverPercent := ((result.count / extended(result.totalCount)) * 100.0); +end; + +(* +DebugRotateObject +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DebugRotateObject(obj: TRotateObject; name, use: string); + +Prints 'obj' to the debug box in a format so it can be easily inserted into a +case statement. + +.. note:: + + Author: Coh3n + Last Modified: Feb. 13th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + // MD_SmallBox is in mordaut.simba + debugRotateObject(getRotateObject([4410947, 5003083], [10, 10], MD_SmallBox(i), 25, 30), 'Test', 'Nothing'); +*) +procedure DebugRotateObject(obj: TRotateObject; name, use: string); +begin + addToSRLLog('with result do'); + addToSRLLog('begin'); + addToSRLLog(' name := '''+capitalize(name)+''';'); + addToSRLLog(' use := '''+capitalize(use)+''';'); + addToSRLLog(' count := '+toStr(obj.count)+';'); + addToSRLLog(' width := '+toStr(obj.width)+';'); + addToSRLLog(' height := '+toStr(obj.height)+';'); + addToSRLLog(' totalCount := '+toStr(obj.totalCount)+';'); + addToSRLLog(' coverPercent := '+toStr(obj.coverPercent)+';'); + addToSRLLog('end;'); +end; + +(* +GetTROAUse +~~~~~~~~~~ + +.. code-block:: pascal + + function GetTROAUse(objs: TRotateObjectArray): string; + +Returns the most common use in a TRotateObjectArray. Used to more accurately +identify puzzles like Quiz and Mordaut. + +.. note:: + + Author: Coh3n & Wizzup? + Last Modified: Mar. 13th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + commonUse := GetTROAUse(objs); +*) +function GetTROAUse(objs: TRotateObjectArray): string; +var + i, j, count: integer; + found: boolean; + useCounts: TIntegerArray; + useNames: TStringArray; +begin + // loops through each object and records and counts their 'uses' + for i := 0 to high(objs) do + begin + for j := 0 to high(useNames) do + if (lowercase(objs[i].use) = lowercase(useNames[j])) then + begin + found := true; + break; + end; + + if (found) then + useCounts[j] := useCounts[j] + 1 + else begin + setLength(useNames, length(useNames) + 1); + setLength(useCounts, length(useCounts) + 1); + + useNames[high(useNames)] := objs[i].use; + useCounts[high(useCounts)] := 1; + end; + + found := false; + end; + + j := -1; + count := -1; + + // gets the highest use count + for i := 0 to high(useCounts) do + if (useCounts[i] > count) then + begin + count := useCounts[i]; + j := i; + end; + + if (j <> -1) then + result := useNames[j] + else + addToSRLLog('GetTROAUse: Couldn''t find a use'); + + addToSRLLog('GetTROAUse: UseNames - '+toStr(useNames)); + addToSRLLog('GetTROAUse: UseCounts - '+toStr(useCounts)); + addToSRLLog('GetTROAUse: Result - '+result); +end; + +(* +ClickDTMRotatedIn +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClickDTMRotatedIn(DTM, x1, y1, x2, y2: integer; sAngle, eAngle, aStep: extended; uptext: TStringArray; action: integer): boolean; + +Returns true if 'DTM' is found and clicked. + * DTM: The DTM identifier + * x1, y1, x2, y2: The area to search for the DTM + * sAngle: The starting angle to search + * eAngle: The ending angle to search + * aStep: Rotate 'aStep' degrees each search + * uptext: Will click no matter what if uptext is set to [] + * action: The mouse action + +.. note:: + + Author: Coh3n + Last Modified: Jan. 22nd, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + ClickDTMRotatedIn(DTM, MSBox, -Pi, Pi, Pi/30, [], mouse_Left); +*) +function ClickDTMRotatedIn(DTM, x1, y1, x2, y2: integer; sAngle, eAngle, aStep: extended; uptext: TStringArray; action: integer): boolean; +var + x, y: integer; + aFound: extended; +begin + if (findDTMRotatedAlternating(DTM, x, y, x1, y1, x2, y2, sAngle, eAngle, aStep, aFound)) then + begin + mmouse(x, y, 3, 3); + if ((length(uptext) = 0) or waitUptextMulti(uptext, 300)) then + begin + getmousePos(x, y); + mouse(x, y, 0, 0, action); + result := true; + end; + end; +end; + +var + _Callback_ClickPortal_DTM: Integer; +function _Callback_ClickPortal: Boolean; +begin + Result := ClickDTMRotatedIn(_Callback_ClickPortal_DTM, MSX1, MSY1, MSX2, MSY2, -Pi, Pi, Pi/30, ['ortal'], mouse_Left); +end; + +(* +ClickPortal +~~~~~~~~~~~ + +.. code-block:: pascal + + function ClickPortal(dtmPortal: integer): boolean; + +Calls ClickDTMRotatedIn on 'dtmPortal'. Debugs portal information depending on +whether the function is successful or not. Function also checks for the +"dropped items" warning. + +.. note:: + + Author: Coh3n + Last Modified: Jan. 22nd, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + result := exitPortal(dtmCerterPortal); +*) +function ClickPortal(dtmPortal: integer): boolean; +var + t: integer; +begin + if (not loggedIn()) then + exit; + + _Callback_ClickPortal_DTM := dtmPortal; + addToSRLLog('ClickPortal: Exiting random'); + + if (waitFunc(@_Callback_ClickPortal, 50, 5000)) then + begin + t := (getSystemTime + 5000); + while (getSystemTime < t) do + begin + // in case we had to drop items + if (clickText('valuables', smallChars, MSX1, MSY1, MSX2, MSY2, mouse_Left)) then + break; + + wait(50 + random(50)); + end; + + result := true; + addToSRLLog('ClickPortal: Clicked portal'); + end else + addToSRLLog('ClickPortal: Didn''t find portal DTM'); +end; + +(* +FreeDTMs +~~~~~~~~ + +.. code-block:: pascal + + procedure FreeDTMs(DTMs: TIntegerArray); + +Frees the dtms 'DTMs'. Used to avoid repeating code. + +.. note:: + + Author: Coh3n + Last Modified: Feb. 08, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + FreeDTMs(DTMs); +*) +procedure FreeDTMs(DTMs: TIntegerArray); +var + i: integer; +begin + for i := 0 to high(DTMs) do + freeDTM(DTMs[i]); +end; + diff --git a/SRL/core/antirandoms/demon.simba b/SRL/core/antirandoms/demon.simba new file mode 100644 index 0000000..474fe98 --- /dev/null +++ b/SRL/core/antirandoms/demon.simba @@ -0,0 +1,274 @@ +(* +Drill Demon +=========== + +Stores all the routines to solve the Drill Demon random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +This solver uses DTMs of the signs to determine which mat to exercise on. It +also uses relocating DTMs in case the sign we're looking for doesn't appear on +the main screen. + +*) + +// the demon's name that appears when he's talking +const + DD_NPC_DEMON = 'B8!q850t85Ol80'; + +// these constants represent elements in an array, so do not change the values +const + DTM_DD_EXERCISE_COUNT = 4; + DTM_DD_JOG = 0; + DTM_DD_SITUP = 1; + DTM_DD_PUSHUP = 2; + DTM_DD_STARJUMP = 3; + + DTM_DD_RELOCATE_COUNT = 3; + DTM_DD_RIGHT = 0; + DTM_DD_LEFT = 1; + DTM_DD_CENTER = 2; + +(** + * Author: DemiseScythe & Coh3n + * Description: Returns true if player is in the Drill Demon random. + *) +function DD_Detect(): boolean; +begin + result := (getNPCChatName() = DD_NPC_DEMON) and (not tabExists(TAB_MAGIC)); +end; + +(** + * Author: Coh3n, DTMs by DemiseScythe + * Description: Returns the four DTMs of the exercise signs. + *) +function DD_ExerciseDTMs(): TIntegerArray; +begin + setLength(result, DTM_DD_EXERCISE_COUNT); + + // The signs + result[DTM_DD_JOG] := DTMFromString('mrAAAAHic42BgYNjFyMCwBYpB7L1AfBSIVwPxciAuAKrJBOISKA3iFwNxDpROK4lkKG5JBWMQG4Sd0izhmB+oBh9mJIBhAABkYhKt'); + result[DTM_DD_SITUP] := DTMFromString('mggAAAHicY2NgYDgCxKeA+DwQ7wfijUB8BYiLgTgHiAuBuASIs4C4FIRb01CwQ4oFGPMD5bBhRhwYAgALjQ7j'); + result[DTM_DD_PUSHUP] := DTMFromString('mlwAAAHicY2dgYNjNyMCwGYhXAfEpID4DxAeAeDUQFwHl84C4FIiLgTgLCZe3Z6BgpzRLMM4oi2bgB8rjwox4MBQAALfyETE='); + result[DTM_DD_STARJUMP] := DTMFromString('mbQAAAHicY2VgYHBkZGCwAmJXIA4AYmMgzgeKZwFxGRAXQnF5ewYcO6VZgjE/UBwdM2LBYAAAhp8Jww=='); +end; + +(** + * Author: Coh3n, DTMs by DemiseScythe + * Description: Returns the three DTMs used to relocate inside the random. + *) +function DD_RelocateDTMs(): TIntegerArray; +begin + setLength(result, DTM_DD_RELOCATE_COUNT); + + // Used to relocate inside the fence + result[DTM_DD_RIGHT] := DTMFromString('mbQAAAHicY2VgYDAE4iwgngDEz4E4AYjPA3E+EBcCcS4QvwFi7yAVBsc0Czj2DOJm4AeKo2NGLBgMAMJeCdQ='); + result[DTM_DD_LEFT] := DTMFromString('mbQAAAHicY2VgYDjPyMAgAsQ5QDwJiOcA8S2geA4Q5wFxARB/BmKfYBUGpzRLOLZp0WDgB4qjY0YsGAwA3gcKPQ=='); + result[DTM_DD_CENTER] := DTMFromString('mbQAAAHicY2VgYNgJxM+AeBIQMzMyMMQC6fNAnAfEBUD8EohfAbFPsAqDU5olGHsESjBYN2kw8APF0TEjFgwGAP5iCoM='); +end; + +(** + * Author: DemiseScythe & Coh3n + * Description: Sets up the screen to solve the random. + *) +procedure DD_Setup(); +begin + if (not loggedIn()) then + exit; + + clickNorth(SRL_ANGLE_LOW); // Takes care of MakeCompass & SetAngle + if (findNPCChatText('minute', Nothing)) then + clickToContinue; +end; + +(** + * Author: DemiseScythe & Coh3n + * Description: Checks the NPC chat and finds which exercise we must do. Then + * it finds the sign and uses its coords to click the mat. The wait is just + * large enough to make it wait until it has walked, performed the exercise, + * and ready to return to the center of the fence. + *) +function DD_DoExercise(DTMs: TIntegerArray): boolean; +var + i, x, y: integer; + texts: TStringArray; + aFound: extended; +begin + if (not loggedIn()) then + exit; + + texts := ['jog', 'sit', 'push', 'star']; + + if (length(texts) <> length(DTMs)) then + begin + addToSRLLog('DD_DoExercise: Invalid DTMs or texts array'); + exit; + end; + + // There should not be any out of range errors here as all arrays should be the same length + for i := 0 to high(texts) do + if (findNPCChatText(texts[i], nothing)) then + if (findDTMRotated(DTMs[i], x, y, MSX1, MSY1, MSX2, MSY2, -Pi/12, Pi/12, Pi/30, aFound)) then + begin + addToSRLLog('DD_DoExercise: '+capitalize(texts[i])); + mouse(x, (y + 100), 3, 3, true); + + if (waitNPCTalking(DD_NPC_DEMON, 10000)) then + begin + wait(2000 + random(500)); + result := true; + break; + end; + end else + addToSRLLog('DD_Exercise: Didn''t find exercise DTM: '+capitalize(texts[i])); +end; + +(** + * Author: Coh3n + * Description: Returns a TBox of the exercise area on the minimap. It finds the + * distance from the player to each side of the exercise area. Saves the + * distance and points in arrays. It then uses those arrays to calculate the + * top left and bottom right corners of the exercise area. + *) +function DD_GetExerciseArea(var exerciseArea: TBox): boolean; +var + i, c, t, w, h, distFound: integer; + dist: array[0..3] of integer; + area: array[0..3] of TBox; + tpa: array[0..3] of TPoint; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + 15000); + + repeat + inc(c); + + // search areas for each direction (only one pixel at a time) + area[0] := intToBox(MMCX, MMCY - 1 - c, MMCX, MMCY - 1 - c); // north + area[1] := intToBox(MMCX + 1 + c, MMCY, MMCX + 1 + c, MMCY); // east + area[2] := intToBox(MMCX, MMCY + 1 + c, MMCX, MMCY + 1 + c); // south + area[3] := intToBox(MMCX - 1 - c, MMCY, MMCX - 1 - c, MMCY); // west + + // loop through each area (i.e. direction) to get the distance from the player to the fence on the MM + for i := 0 to high(area) do + if (dist[i] = 0) then + // the white color of the fence + if (findColorTolerance(tpa[i].x, tpa[i].y, 15068652, area[i].x1, area[i].y1, area[i].x2, area[i].y2, 25)) then + begin + dist[i] := distance(tpa[i].x, tpa[i].y, MMCX, MMCY); + inc(distFound); + end; + + // if all 4 distances are found + if (distFound = 4) then + begin + // calculate the top left and bottom right of the exercise box + exerciseArea.x1 := tpa[3].x; + exerciseArea.y1 := tpa[3].y - dist[0]; + exerciseArea.x2 := tpa[1].x; + exerciseArea.y2 := tpa[1].y + dist[2]; + + //SMART_DrawBoxEx(true, exerciseArea, clGreen); + + w := (exerciseArea.x2 - exerciseArea.x1); + h := (exerciseArea.y2 - exerciseArea.y1); + //writeln('w: '+toStr(w)+', h: '+toStr(h)); + + // sometimes the Drill Demon is standing right inline with the player, causing the next white line to be found on the edge of the MM + result := (inRange(38, w - 2, w + 2) and inRange(20, h - 2, h + 2)); + end; + + until(result or (getSystemTime > t)); +end; + +(** + * Author: DemiseScythe & Coh3n + * Description: Relocates the player to the center of the exercise area. + *) +function DD_Relocate(DTMs: TIntegerArray): boolean; +var + i: integer; + exerciseArea: TBox; + p: TPoint; +begin + if (not loggedIn()) then + exit; + + for i := 0 to high(DTMs) do + if (clickDTMRotatedIn(DTMs[i], MSX1, MSY1, MSX2, MSY2, -Pi, Pi, Pi/30, ['alk'], mouse_Left)) then + begin + result := true; + break; + end; + + if (not result) then + begin + addToSRLLog('DD_Relocate: Didn''t find any relocate DTMs, using area detection'); + + if (DD_GetExerciseArea(exerciseArea)) then + begin + p := middleBox(exerciseArea); + mouse(p.x, p.y + 5, 2, 2, mouse_Left); + result := true; + end; + end; + + if (result) then + begin + addToSRLLog('DD_Relocate: Walking to Center!'); + flag(); + wait(1000 + random(100)); + end else + addToSRLLog('DD_Relocate: Failed to relocate'); +end; + +(** + * Author: DemiseScythe & Coh3n + * Description: Solves the Drill Demon random event. + *) +function DD_Solve(): boolean; +var + t: integer; + exerciseDTMs, relocateDTMs: TIntegerArray; +begin + DD_Setup(); + + exerciseDTMs := DD_ExerciseDTMs(); + relocateDTMs := DD_RelocateDTMs(); + + repeat + inc(t); // tries counter + + // checks if we have sucessfully completed the Demon's requests + if (findNPCChatText('actual', nothing)) then + begin + clickContinue(true, true); + + if (waitTabExists(TAB_MAGIC, 10000)) then + begin + result := true; + break; + end; + + end else begin + doConversation('', false); // GE message or if we get exercise wrong + + if (not DD_DoExercise(exerciseDTMs)) then + DD_Relocate(relocateDTMs); + end; + + // just in case ;) + result := tabExists(TAB_MAGIC); + + until(result or (not loggedIn()) or (t > 30)); + + // free the DTMs + freeDTMs(exerciseDTMs); + freeDTMs(relocateDTMs); + + if (not result) then + addToSRLLog('DD_Solve: Drill Demon exceeded maximum tries'); +end; + diff --git a/SRL/core/antirandoms/evilbob.simba b/SRL/core/antirandoms/evilbob.simba new file mode 100644 index 0000000..f084340 --- /dev/null +++ b/SRL/core/antirandoms/evilbob.simba @@ -0,0 +1,441 @@ +(* +Evil Bob +======== + +Stores all the routines to solve the Evil Bob random. + +This solver uses DTMs to determine which fishing spot to fish at. + +*) + +const + DTM_EB_COUNT = 14; + DTM_EB_NET_GROUND = 0; + DTM_EB_NET_INV = 1; + DTM_EB_POT = 2; + DTM_EB_FISH_COOKED = 3; + DTM_EB_FISH_RAW = 4; + DTM_EB_BOB = 5; + DTM_EB_SLAVE = 6; + DTM_EB_STATUE_NORTH = 7; + DTM_EB_STATUE_SOUTH = 8; + DTM_EB_STATUE_EAST = 9; + DTM_EB_STATUE_WEST = 10; + DTM_EB_FISHSPOT = 11; + DTM_EB_CENTER = 12; + DTM_EB_PORTAL = 13; + +var + EB_DTMs: array[0..(DTM_EB_COUNT - 1)] of integer; + +(** + * Author: DemiseScythe & Coh3n + * Description: Returns true if player is in the random. + *) +function EB_Detect(): boolean; +begin + if (countColorTolerance(9931907, MMX1, MMY1, MMX2, MMY2, 15) > 6000) then // the water color + if (countColorTolerance(10995923, MMX1, MMY1, MMX2, MMY2, 15) > 3000) then // the sand color + if (inRange(countDots('red'), 3, 7)) then + if (inRange(countDots('yellow'), 1, 2)) then + result := tabExists(TAB_PRAYER); +end; + +(** + * Author: Coh3n, DTMs by DemiseScythe + * Description: Sets the EB_DTMs array. + *) +procedure EB_SetDTMs(); +var + i: integer; +begin + EB_DTMs[DTM_EB_NET_GROUND] := DTMFromString('mggAAAHicY2NgYOAAYgEGCACxOYGYF4i5gJgdKsYAFeMBYgM1GYZzR+dhYH6gHDbMiANDAAApXgw2'); + EB_DTMs[DTM_EB_NET_INV] := DTMFromString('mwQAAAHic42RgYHBgYmCwBGJzILYDYjcg9gdiPyB2AWIfIN7OyMBwEIh3AvEGIN4IZR8C4uNAfBKIvay0gaYx4cX8DIQBIxEYDgCVcgn6'); + EB_DTMs[DTM_EB_POT] := DTMFromString('mwQAAAHic42RgYBBjZGCQBGJ+IOYCYnYgFgFiRSBmAGJtIE4GMrOBOAuIE4E4A4jzoPwcKN1aX8ewVEqFYZk0BEtISjCIS0gwSElLMyQkpjLER0cx8APVEcKMRGA4AACDdQxK'); + EB_DTMs[DTM_EB_FISH_COOKED] := DTMFromString('mwQAAAHic42RgYLBnYmBwBGJbILYBYjsgdgViDyD2AWJfIH4OVPcEiB8yQNivofRjIH4ApbO99RhkLE4zBFkqg9kNcbYMuT76DFH26gy+ZooMsQ4aDPxAdYQwIxEYDgAsOBLV'); + EB_DTMs[DTM_EB_FISH_RAW] := DTMFromString('mrAAAAHic42BgYHBgYmBwBGI7ILYHYlcg9gRiHyD2A+LnQDVPgPgxEL9igPAfAfF9qJhs2Q0GGcsLDBKJmxjkqx8yyJXfZhCPW8sgGjqHQTJlBwM/UA0+zEgAwwAAVtET5Q=='); + EB_DTMs[DTM_EB_BOB] := DTMFromString('mlwAAAHicY2dgYLgHxPeB+A6UfgDEd6HiE4C4F4i7gbgDiCcD8RQgng7EJkZGYGxjZcmgo6XFICMtzWBlbs5gb2PDwA+Ux4UZ8WAoAAAu4Q6J'); + EB_DTMs[DTM_EB_SLAVE] := DTMFromString('mQwAAAHicY2aAAGYkmhHKrs5RZWgp0WCozFJh4AfyYRgkzwTFQAAAdKQDcA=='); + EB_DTMs[DTM_EB_STATUE_NORTH] := DTMFromString('mAAEAAHic42FgYHBgZGCwB2IbIHaFskHYCYgtgNgKKu4JxAFAvAWoZycDhN4OxBuAeDUQL4bi9UC8GYpBcpsnmzHsnW3J8PqgO8PcRn2GQ/OtGE4vtwWLb5pkxnBzkyPD/rmWDBdW2zMcX2zDwA/UQwpmJBEjAwD7vB91'); + EB_DTMs[DTM_EB_STATUE_SOUTH] := DTMFromString('mPwEAAHic42dgYBBkZGDgBmIBKM0FxMJALMIIkROFioOwNBBLQcXFgHg9UP8uIN4DxIeB+DQUHwLiFUC8HIhnAvEiIJ4NxEuAeD4QLwDipmwNhqUdxgwdBVoM6SHyDMu7jBkWtRoxtORqMKzrNwXj7mJthopkVYaZdfoM5UkqYPaqHhMGfqB+cjEjBRgNAACAhx5Y'); + EB_DTMs[DTM_EB_STATUE_EAST] := DTMFromString('mVAEAAHicpcw7CsJgEIXR6wp0LaKdGIyFbsxO3IAoGHwGAz4Lm6BgI0iKiCREFDvBVfgl/JVtBg4zMHemJClBjJeZH7jjhhBPRAjMLvU2N2luhT0OxhE+POzgYooZxhhhiAH6cDplLXtVRWs7c3ZqcrsVBQtL8cbWdW4p2Tb18VsKvUaWuUzq+p7aWS/yI49CTv/1A6QHNIs='); + EB_DTMs[DTM_EB_STATUE_WEST] := DTMFromString('m6wAAAHic42ZgYLgPxI+A+B4Q3wXi50D8DEnsKRA/BOInQHwViG9B8WMgvgLE54H4LBCfAeKTQHwMiPeC6MW2DOkh8gwz6/QZZjcYMJQnqTDUZagzLGgxZNg5w5JheZcxw5FFNgzzmw0Z+IHqicWMJGAkAADn6CG2'); + EB_DTMs[DTM_EB_FISHSPOT] := DTMFromString('mWAAAAHicY2FgYFAFYhUg1gRieSDmZ2Rg4ARiASAWBOLazkUMC5euhGN+kBokzIiGQQAAkaEIiA=='); + EB_DTMs[DTM_EB_CENTER] := DTMFromString('mbQAAAHicY2VgYChhYmDIAuJuIO4H4nQgtgGKawKxOhC7A7EPEB/b08bglCTLoBQhDMYgNj9QHB0zYsFgAABcVgiC'); + EB_DTMs[DTM_EB_PORTAL] := DTMFromString('mKgEAAHic42NgYNgJxLuAeBMQrwfiDVCxg0C8FoiPAfEOIF4NxBuhckeAeCUQLwTiJUC8HKp3I1R8B5K564B4PhDPhapdsNQfJ27q0ILj/YfKUDA/UC85mJFMjAoAKusqzA=='); + + for i := 0 to high(EB_DTMs) do + setDTMName(EB_DTMs[i], 'Evil Bob '+toStr(i)); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Initial setup to solve the random. + *) +procedure EB_Setup(); +begin + if (not loggedIn()) then + exit; + + clickNorth(SRL_ANGLE_HIGH); + EB_SetDTMs(); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Walks to the fishing nets and picks one up. + *) +function EB_GetNet(): boolean; +var + x, y, r, t: integer; +begin + if (not loggedIn()) then + exit; + + addToSRLLog('EB_GetNet: Getting fishing net'); + + result := waitFindDTM(x, y, EB_DTMs[DTM_EB_NET_INV], 200); // may already have a net + + if (not result) then + begin + // walk to the red dots on the SE part of the island + TPAWalk(721128, 30, 5, -5, point(MMX2, MMY2)); + wait(2000 + random(500)); + + // drop items if needed + if (InvCount > 26) then + begin + addToSRLLog('Dropping items'); + + t := (getSystemTime + 5000); + repeat + r := randomRange(10, 16); // random slots, probably not important items + if (ExistsItem(r)) then + begin + DropItem(r); + wait(1000 + random(500)); + end; + until((InvCount <= 26) or (getSystemTime > t)); + end; + + // pick up net off the ground + if (clickDTMRotatedIn(EB_DTMs[DTM_EB_NET_GROUND], MSX1, MSY1, MSX2, MSY2, -Pi/4, Pi/4, Pi/30, ['ake', 'net'], mouse_Left)) then + begin + if (didRedClick) then + begin + result := waitFindDTM(x, y, EB_DTMs[DTM_EB_NET_INV], 5000); // look for net in inventory + + if (not result) then + addToSRLLog('DB_GetNet: Didn''t find DTM_EB_NET_INV'); + end; + end else + addToSRLLog('EB_GetNet: Didn''t click DTM_EB_NET_GROUND'); + end; + + if (result) then + addToSRLLog('EB_GetNet: Got fishing net'); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Returns true if player relocated to the center of the island. + *) +function EB_WalkToCenter(): boolean; +var + x, y: integer; + aFound: extended; +begin + addToSRLLog('EB_WalkToCenter: Walking to the center of the island'); + + if (findDTMRotatedAlternating(EB_DTMs[DTM_EB_CENTER], x, y, MMX1, MMY1, MMX2, MMY2, -Pi/4, Pi/4, Pi/30, aFound)) then + begin + if (Distance(x, y, MMCX, MMCY) > 10) then // may already be at center + begin + mouse(x, y, 3, 3, true); + wait(1500 + random(300)); + Flag; + end else + addToSRLLog('EB_WalkToCenter: Already at center'); + + result := true; + end else begin + addToSRLLog('EB_WalkToCenter: Didn''t find DTM_EB_CENTER'); + result := TPAWalk(63717, 50, randomRange(-5, 5), randomRange(-5, 5), point(MMCX, MMCY)); + end; + + if (result) then + addToSRLLog('EB_WalkToCenter: At center'); +end; + +function _Callback_EB_TalkToSlave: Boolean; +begin + Result := clickDTMRotatedIn(EB_DTMs[DTM_EB_SLAVE], MSX1, MSY1, MSX2, MSY2, -Pi/4, Pi/4, Pi/30, ['ervant'], mouse_Left); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Talks to slave to start cut scene. + *) +function EB_TalkToSlave(): boolean; +var + i: integer; +begin + if (not loggedIn()) then + exit; + + addToSRLLog('EB_TalkToSlave: Talking to the Slave'); + + if (waitFunc(@_Callback_EB_TalkToSlave, 50, 5000)) then + begin + if (findNPCChatTextMulti(['fallen', 'quick'], nothing)) then + begin + result := true; + exit; + end; + + if (waitFunc(@areTalking, 50, 4000)) then + for i := 1 to 4 do // click through 4 dialogs + begin + clickContinue(true, true); + wait(300 + random(200)); + result := true; + end; + end else + addToSRLLog('Didn''t find DTM_EB_SLAVE'); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Returns the statue we need to fish at. + *) +function EB_GetStatue(): string; +var + i, x, y, t: integer; + DTMs: TIntegerArray; + results: TStringArray; + aFound: extended; +begin + if (not loggedIn()) then + exit; + + addToSRLLog('EB_GetStatue: Identifying statue'); + + result := ''; + t := (getSystemTime + 20000); + + results := [ 'north', 'east', 'south', 'west' ]; + DTMs := [ DTM_EB_STATUE_NORTH, DTM_EB_STATUE_EAST, + DTM_EB_STATUE_SOUTH, DTM_EB_STATUE_WEST ]; + + // loop through statue DTMs trying to find the correct one + repeat + for i := 0 to high(DTMs) do + if (findDTMRotatedAlternating(EB_DTMs[DTMs[i]], x, y, MSX1, MSY1, MSX2, MSY2, -Pi/4, Pi/4, Pi/30, aFound)) then + begin + result := results[i]; + break; + end; + until((result <> '') or (getSystemTime > t)); + + if (result <> '') then + addToSRLLog('DB_GetStatue: Found statue '''+result+'''') + else + addToSRLLog('DB_GetStatue: Didn''t identify statue'); + + wait(1500 + random(500)); + clickContinue(true, true); // need to do this whether or not it fails +end; + +function _Callback_EB_GetFish: Boolean; +begin + Result := clickDTMRotatedIn(EB_DTMs[DTM_EB_FISHSPOT], MSX1, MSY1, MSX2, MSY2, -Pi, Pi, Pi/30, ['ishing'], mouse_Left); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Relocates to center, walks to fishing spots and returns true + * when cooked fish is found. + *) +function EB_GetFish(Direction: string): boolean; +var + x, y: integer; +begin + if (not loggedIn()) then + exit; + + addToSRLLog('EB_GetFish: Getting fish'); + + // may already have fish + result := waitFindDTM(x, y, EB_DTMs[DTM_EB_FISH_COOKED], 200) or + waitFindDTM(x, y, EB_DTMs[DTM_EB_FISH_RAW], 200); + + EB_WalkToCenter(); // make sure we're at the center of the island + + if (not result) then + begin + case Direction of // sand color + 'north': TPAWalk(10864595, 15, 10, 10, point(MMCX, MMY1)); + 'east': TPAWalk(10864595, 15, 0, 0, point(MMX2, MMCY)); + 'south': TPAWalk(10864595, 15, 0, -5, point(MMCX, MMY2)); + 'west': TPAWalk(10864595, 15, 5, 0, point(MMX1, MMCY)); + end; + + wait(1500 + random(500)); + + if (waitFunc(@_Callback_EB_GetFish, 50, 5000)) then + begin + if (didRedClick) then + if (waitFindDTM(x, y, EB_DTMs[DTM_EB_FISH_COOKED], 10000)) then // wait to find cooked fish + result := true + else + addToSRLLog('EB_GetFish: Didn''t find DTM_EB_FISH_COOKED'); + end else + addToSRLLog('EB_GetFish: Didn''t click DTM_EB_FISHSPOT'); + end; + + if (result) then + addToSRLLog('EB_GetFish: Got fish') +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Uses the cooked fish on the uncooking pot. + *) +function EB_Uncook(): boolean; +var + x, y: integer; +begin + if (not loggedIn()) then + exit; + + addToSRLLog('EB_Uncook: Uncooking the fish'); + result := waitFindDTM(x, y, EB_DTMs[DTM_EB_FISH_RAW], 200); // may already have uncooked the fish + + EB_WalkToCenter(); + + if (not result) then + begin + // click the cooked fish + if (findDTM(EB_DTMs[DTM_EB_FISH_COOKED], x, y, MIX1, MIY1, MIX2, MIY2)) then + begin + mouse(x, y, 5, 5, mouse_Left); + + // use the fish on the uncooking pot + if (clickDTMRotatedIn(EB_DTMs[DTM_EB_POT], MSX1, MSY1, MSX2, MSY2, -Pi, Pi, Pi/30, ['ncook'], mouse_Left)) then + begin + // wait for the fish to be uncooked + if (waitFindDTM(x, y, EB_DTMs[DTM_EB_FISH_RAW], 5000)) then + result := true + else + addToSRLLog('EB_Uncook: Didn''t find DTM_EB_FISH_RAW') + end else + addToSRLLog('EB_Uncook: Didn''t click DTM_EB_POT'); + end else + addToSRLLog('EB_Uncook: Didn''t find DTM_EB_FISH_COOKED'); + end; + + if (result) then + addToSRLLog('EB_Uncook: Uncooked the fish'); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Feeds Bob the raw fish. + *) +function EB_FeedBob(): boolean; +var + x, y: integer; +begin + if (not loggedIn()) then + exit; + + addToSRLLog('EB_FeedBob: Feeding Bob'); + + if (findDTM(EB_DTMs[DTM_EB_FISH_RAW], x, y, MIX1, MIY1, MIX2, MIY2)) then + begin + mouse(x, y, 5, 5, mouse_Left); + + if (clickDTMRotatedIn(EB_DTMs[DTM_EB_BOB], MSX1, MSY1, MSX2 - 200, MSY2, -Pi, Pi, Pi/30, ['vil', 'ob'], mouse_Left)) then + begin + wait(1500 + random(500)); + + if (DoConversation('nap', false)) then + begin + result := true; + addToSRLLog('EB_FeedBob: Fed Bob'); + end; + + end else + addToSRLLog('EB_FeedBob: Didn''t find DTM_EB_BOB'); + end else + addToSRLLog('EB_FeedBob: Didn''t find DTM_EB_FISH_RAW'); +end; + +(** + * Author: Coh3n + * Description: Solves the Evil Bob random event. + *) +function EB_Solve(): boolean; +var + t: integer; + statue: string; +begin + t := (getSystemTime + (5 * 60000)); // maximum 5 minutes + + EB_Setup(); + + repeat + if (EB_GetNet()) then + begin + EB_WalkToCenter(); + wait(1000 + random(500)); + + if ((statue <> '') or (EB_TalkToSlave())) then // don't talk to the slave if the statue is already ID'd + begin + // in case we've already finished + if (findNPCChatTextMulti(['fallen', 'quick'], nothing)) then + begin + addToSRLLog('Already finished feeding Bob'); + + if (clickPortal(EB_DTMs[DTM_EB_PORTAL])) then + if (waitTabExists(TAB_MAGIC, 25000)) then + begin + result := true; + break; + end; + end; + + if (statue = '') then // may have already ID'd the statue + statue := EB_GetStatue(); + + if (statue <> '') then + repeat // since statue was found, keep trying to do the rest + if (EB_GetFish(statue)) then + begin + EB_WalkToCenter(); + + if (EB_Uncook()) then + if (EB_FeedBob()) then + begin + if (clickPortal(EB_DTMs[DTM_EB_PORTAL])) then + result := WaitTabExists(TAB_MAGIC, 25000) + else begin + freeDTMs(EB_DTMs); + exit; + end; + end else begin + statue := ''; + break; // wrong fish (or need another), starting over + end; + end; + until(result or (getSystemTime > t)); + end; + end; + until(result or (getSystemTime > t)); + + freeDTMs(EB_DTMs); + + if (not result) then + addToSRLLog('EB_Solve: Evil Bob solver has failed or timed out'); +end; + diff --git a/SRL/core/antirandoms/forester.simba b/SRL/core/antirandoms/forester.simba new file mode 100644 index 0000000..7b3ba05 --- /dev/null +++ b/SRL/core/antirandoms/forester.simba @@ -0,0 +1,344 @@ +(* +Freaky Forester +=============== + +Stores all the routines to solve the Forester random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +This solver uses very specific TPA calculations to determine how many tails +each pheasant has. It finds the color if the tip of the tail and uses how many +colors are found to determine how many tails there are. + +*) + +// colors gathered using ACA +const + _PHEASANT_TAIL_COLOR = 9412006; // white tail tip + _PHEASANT_TAIL_TOL = 5; + + _PHEASANT_COLOR = 2705758; // brown of pheasant body + _PHEASANT_TOL = 7; + + _NPC_FORESTER = '8!85ly8o!8gt8!'; + +(** + * Author: Coh3n + * Description: Detects if a player is in the random. + * Updated on 02/06/2012 - [J]ustin (Thanks J J for the report) + *) +function FF_Detect(): boolean; +begin + if (not (tabExists(TAB_MAGIC))) then + if (tabExists(TAB_FRIENDS)) then // Removed false detection when shop window open + if (length(getMinimapDots('npc')) >= 12) then //Possible 10 NPCS at Yanille (14+ NPCS at random event) + // forest color + result := (countColorTolerance(2513745, MMX1, MMY1, MMX2, MMY2, 20) > 5000); +end; + +(** + * Author: Sumilion & Coh3n + * Description: Finds and attacks the pheasant with number of 'numOfTails'. + *) +function FF_WalkToCenter(): boolean; +var + arP: TPointArray; + tmpCTS: integer; + p: TPoint; +begin + if (not loggedIn()) then + exit; + + tmpCTS := getColorToleranceSpeed(); + setColorToleranceSpeed(0); + + addToSRLLog('FF_WalkToCenter: Walking to the center area'); + + // the yellow of the NPC dots + if (findColorsTolerance(arP, 195836, MMX1, MMY1, MMX2, MMY2, 25)) then + begin + p := middleTPA(arP); + mouse(p.x, p.y, 5, 5, mouse_Left); + flag(); + wait(1500 + random(500)); + result := true; + end; + + setColorToleranceSpeed(tmpCTS); +end; + +(** + * Author: Coh3n + * Description: Returns true if player talks to Freaky Forester. + *) +function FF_TalkTo(): boolean; +var + dtmForester: integer; +begin + if (not loggedIn()) then + exit; + + dtmForester := DTMFromString('mWAAAAHicY2FgYHABYlcg9oLiNiDugtL9QHzt/FmGSb3dDF/fvmI4uGsHAz9QDBkzAjETEgYBAH3DDKU='); + + if (clickDTMRotatedIn(dtmForester, MSX1, MSY1, MSX2, MSY2, -Pi/4, Pi/4, Pi/30, ['orester'], mouse_Left)) then + result := waitNPCTalking(_NPC_FORESTER, 5000) + else + addToSRLLog('FF_TalkTo: Failed to click Forester'); + + freeDTM(dtmForester); + + if (result) then + addToSRLLog('FF_TalkTo: Talking to Forester') +end; + +(** + * Author: Coh3n + * Description: Gets the pheasant required to kill. Returns the number of tails; + * 0 if we need to exit through portal, and -1 if nothing was found. + *) +function FF_GetPheasant(): integer; +var + t, i: integer; + options: TStringArray; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + 15000); + options := ['portal', 'one', 'two', 'three', 'four']; + result := -1; + + // goes through the conversation, looking for the pheasant we have to kill + while ((areTalking) and (result = -1) and (getSystemTime < t)) do + begin + for i := 0 to high(options) do + if (findNPCChatText(' '+options[i], nothing)) then + begin + wait(1500 + random(500)); + result := i; + break; + end; + + wait(500 + random(300)); + clickContinue(true, true); + end; + + // simply for debugging purposes + case result of + 1..4: addToSRLLog('FF_GetPheasant: Need to kill the '+toStr(result)+' tailed pheasant'); + 0: addToSRLLog('FF_GetPheasant: Need to exit through portal'); + -1: addToSRLLog('FF_GetPheasant: Failed to get pheasant'); + end; +end; + +(** + * Author: TRiLeZ & Coh3n + * Description: Finds and attacks the pheasant with number of 'numOfTails'. + *) +function FF_KillPheasant(numOfTails: integer): boolean; +var + tpaTail: TPointArray; + atpaPheasant, atpaTails: T2DPointArray; + areaCheck, countCheck: boolean; + b: TBox; + i, x, y, t, area, tmpMouseSpeed, tmpCTS, tmpCount, dtmPheasant: Integer; +begin + if (not loggedIn()) then + exit; + + tmpMouseSpeed := mouseSpeed; + tmpCTS := getColorToleranceSpeed(); + + mouseSpeed := 35; // since the pheasants move so much + setColorToleranceSpeed(3); + + // move closer to all the pheasants + mouse(450, 175, 50, 50, mouse_Right); + waitOption('alk', 300); + + // need to make room for a raw pheasant + if (invFull()) then + dropItem(randomRange(12, 16)); + + t := (getSystemTime + (2 * 60000)); + + repeat + // find the pheasants numOfTails + if (findColorsTolerance(tpaTail, _PHEASANT_TAIL_COLOR, MSX1+20, MSY1+20, MSX2-20, MSY2-20, _PHEASANT_TAIL_TOL)) then + begin + atpaPheasant := TPAtoATPA(tpaTail, 25); + sortATPASize(atpaPheasant, (numOfTails = 3) or (numOfTails = 4)); // sort largest first if looking for 3 or 4 tails + + // loop through each pheasant found, searching for the right one + for i := 0 to high(atpaPheasant) do + begin + b := getTPABounds(atpaPheasant[i]); + area := (b.x2 - b.x1) * (b.y2 - b.y1); + + // tpa area is larger depending on the tail being looked for + case numOfTails of + 1: areaCheck := inRange(area, 0, 4); + 2: areaCheck := inRange(area, 2, 12); + 3: areaCheck := inRange(area, 36, 62); + 4: areaCheck := inRange(area, 80, 160); + end; + + // continue if area isn't correct + if (not areaCheck) then + continue; + + tpaTail := atpaPheasant[i]; + atpaTails := TPAtoATPA(tpaTail, 3); // each tail is a separate tpa + + if (numOfTails = length(atpaTails)) then + begin + // counts the colors + tmpCount := countColorTolerance(_PHEASANT_COLOR, b.x1 - 5, b.y1 - 5, b.x2 + 5, b.y2 + 5, _PHEASANT_TOL); + + // checks to make sure there are the right amount of pheasant colors + case numOfTails of + 1: countCheck := inRange(tmpCount, 4, 9); + 2: countCheck := inRange(tmpCount, 10, 18); + 3: countCheck := inRange(tmpCount, 30, 56); + 4: countCheck := inRange(tmpCount, 70, 200); + end; + + if (not countCheck) then + continue; + + middleTPAEx(atpaPheasant[i], x, y); + mouse(x, y, 5, 5, mouse_Right); + + if (waitOption('ttack', 500)) then + begin + addToSRLLog('FF_KillPheasant: Attacking pheasant'); + result := true; + break; + end; + end; + end; + + end else begin + addToSRLLog('FF_KillPheasant: Failed to find tail color'); + wait(200 + random(300)); + end; + + until(result or (getSystemTime > t) or (not loggedIn())); + + mouseSpeed := tmpMouseSpeed; + setColorToleranceSpeed(tmpCTS); + + // wait for the raw pheasant to appear in inventory + if (result) then + begin + result := false; + dtmPheasant := DTMFromString('mlwAAAHicY2dgYDjMzMBwEogvAfEpID4OxLuAeC8Q9zMyMLQCcTcQTwHiBiCeBsTtQFzpIwXUzYQV8wNJXJgRD4YCAOxXCrU='); + + if (waitFindDTM(x, y, dtmPheasant, 8000)) then + begin + addToSRLLog('FF_KillPheasant: Pheasant found in inventory'); + result := true; + end; + + freeDTM(dtmPheasant); + end; +end; + +(** + * Author: Coh3n + * Description: Returns the raw pheasant to the Freaky Forester. + *) +function FF_ReturnPheasant(): boolean; +var + tries: integer; +begin + if (not loggedIn()) then + exit; + + repeat + inc(tries); + + if (FF_TalkTo()) then + result := (FF_GetPheasant() = 0) // if portal text is found + else + FF_WalkToCenter(); + + wait(200 + random(300)); + until(result or (tries >= 10)); +end; + +(** + * Author: Coh3n + * Description: Exits the random. + *) +function FF_Exit(): boolean; +var + tries, dtmPortal: integer; +begin + if (not loggedIn()) then + exit; + + dtmPortal := DTMFromString('mQwAAAHicY2ZgYOhkZGCoB+IpQFwN5JcCcTMQx+YbMtTPcwNjfiAfhoHKGJigGAgAJ7gHCw=='); + + repeat + inc(tries); + + addToSRLLog('FF_Exit: Walking to portal'); + TPAWalk(2115909, 15, 0, 0, point(665, 85)); // color of the grass + flag(); + + if (clickPortal(dtmPortal)) then + begin + result := true; + break; + end; + + wait(200 + random(300)); + until(tries >= 10); + + if (not result) then + addToSRLLog('FF_Exit: Couldn''t exit Forester'); + + freeDTM(dtmPortal); +end; + +(** + * Author: Coh3n + * Description: Solves the random. + *) +function FF_Solve(): boolean; +var + t, pheasant: integer; + done: boolean; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + (5 * 60000)); // maximum 5 minutes + clickNorth(SRL_ANGLE_HIGH); + + repeat + if (FF_TalkTo()) then + begin + pheasant := FF_GetPheasant(); + + // see if we need to kill a pheasant or exit through portal + if (pheasant > 0) then + begin + if (FF_KillPheasant(pheasant)) then + done := FF_ReturnPheasant(); + end else + done := (pheasant = 0); // if we're free to leave + end else + FF_WalkToCenter(); + + if (done) then + if (FF_Exit()) then + result := waitTabExists(TAB_MAGIC, 10000); + + until(result or (getSystemTime > t)); + + if (not result) then + addToSRLLog('FF_Solve: Forester solver timed out'); +end; + diff --git a/SRL/core/antirandoms/frog.simba b/SRL/core/antirandoms/frog.simba new file mode 100644 index 0000000..6fa8572 --- /dev/null +++ b/SRL/core/antirandoms/frog.simba @@ -0,0 +1,423 @@ +(* +Frog +==== + +Stores all the routines to solve the Frog random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +This solver uses a DTM of a frog with a crown to find the royal (Prince or +Princess) frog. + +*) + +var + RoyalPos: TPointArray; + +const + FROG_NAME_HERALD = '8!oqB8!5lg'; + FROG_NAME_PRINCESS = '8!oqo!l0o8gg'; + FROG_NAME_PRINCE = '8!oqo!l0o8'; + + FROG_DTM_ROYAL = 0; + FROG_DTM_CENTER = 1; // big cave center + +(** + * Author: Coh3n + * Description: Loads the 'DTM'. + *) +function Frog_GetDTM(DTM: integer): integer; +begin + case DTM of + FROG_DTM_ROYAL : result := DTMFromString('mlwAAAHicY2dgYGBlgAAeKM0FxGxAzALEnFA+J1SMGaoGRMvEyjJIRcgwyKUqMMinKzD8vefD8PCYC5jmB8rjwoxAzIQDQwEAwHgJcQ=='); + FROG_DTM_CENTER : result := DTMFromString('mlwAAAHicY2dgYKhmYmAoAOJcIC4D4jYg7oJieaC8DhDLATE/EEsBsToQmwJxaJAJg4OOGENARTaDb0kGmO9TlAYW44eqx4YZgZgJB4YCADVaCxw='); + end; +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Sets up to solve the Frog random. + *) +procedure Frog_Setup(); +begin + if (not LoggedIn()) then + exit; + + // Setting the mousespeed higher to avoid misclicking on the quickly moving frogs + MouseSpeed := 30; + clickNorth(SRL_ANGLE_HIGH); + doConversation('', false); +end; + +(** + * Author: Coh3n + * Description: Returns true if the a royal frog is talking. + *) +function Frog_RoyalTalking(): boolean; +var + name: string; +begin + name := getNPCChatName(); + result := ((name = FROG_NAME_PRINCESS) or (name = FROG_NAME_PRINCE)); +end; + +(** + * Author: Coh3n + * Description: Returns true if the Frog Herald is talking. + *) +function Frog_HeraldTalking(): boolean; +begin + result := (getNPCChatName = FROG_NAME_HERALD); +end; + +(** + * Author: DemiseScythe + * Description: Returns true if player is in the Frog random. + *) +function Frog_Detect(): boolean; +var + name: String; + frogDTM, frogX, frogY: Integer; + +begin + if not (tabExists(TAB_MAGIC)) then + begin + name := getNPCChatName(); + case name of + FROG_NAME_HERALD: begin result := true; exit; end; + FROG_NAME_PRINCESS:begin result := true; exit; end; + FROG_NAME_PRINCE: begin result := true; exit; end; + end; + + frogDTM := DTMFromString('mWAAAAHicY2FgYEhnZWAoBuIkIE4D4mlMDAzTgXgiEM8DYr50AQbRGfEMAqXCDALlwgxcQD3ImBENgwAAnKIHDg=='); + if (FindDTM(frogDTM, frogX, frogY, MSX1, MSY1, MSX2, MSY2)) then + result := true; + end; +end; + +(** + * Author: Coh3n + * Description: Waits for the a frog the be talking (called after clicking + * frog). + *) +function Frog_WaitChat(waitTime: integer): boolean; +var + t: integer; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + waitTime); + + while (getSystemTime < t) do + begin + // checks to see if we're talking to the Royal Frog + if (Frog_RoyalTalking()) then + begin + addToSRLLog('Frog_WaitChat: Talking to the Royal Frog'); + result := true; + break; + end; + + // if we're talkin to the Herald, we clicked the wrong frog + if (Frog_HeraldTalking()) then + begin + addToSRLLog('Frog_WaitChat: Clicked wrong frog'); + clickContinue(true, true); + break; + end; + + wait(200 + random(100)); + end; +end; + +(** + * Author: Coh3n + * Description: Returns true when the player is talking to the Royal Frog. + *) +function Frog_ClickRoyal(): boolean; +var + dtmRoyal, i, x, y: integer; + dtmPoints: TPointArray; + aFound: T2DextendedArray; +begin + if (not loggedIn()) then + exit; + + if (Frog_RoyalTalking()) then + begin + addToSRLLog('Frog_ClickRoyal: Already talking to the Royal Frog'); + result := true; + exit; + end; + + dtmRoyal := Frog_GetDTM(FROG_DTM_ROYAL); + + // it's possible more than one DTM can be found (multiple frogs) + if (findDTMsRotatedAlternating(dtmRoyal, dtmPoints, MSX1, MSY1, MSX2, MSY2, -Pi/4, Pi/4, Pi/30, aFound)) then + begin + filterTPADist(dtmPoints, 35); + sortTPAFrom(dtmPoints, point(MSCX, MSCY)); // sort from closest to the player + + // loop through each DTM that was found + for i := 0 to high(dtmPoints) do + begin + x := dtmPoints[i].x; + y := dtmPoints[i].y; + + mmouse(x, y, 3, 3); + + // added the '/' so we don't click the 'Frog Herald' + if (waitUptextMulti(['Frog /', 'rog /'], 300)) then + begin + addToSRLLog('Frog_ClickRoyal: Clicked a frog'); + + getmousePos(x, y); + mouse(x, y, 0, 0, mouse_Left); + + if (Frog_WaitChat(10000)) then // wait for frog's name + begin + result := true; + break; + end; + end; + end; + end; + + freeDTM(dtmRoyal); +end; + +(** + * Author: Coh3n + * Description: Returns true if Frog's text is found that indicated we're in + * the big cave. Finishes the conversation. + *) +function Frog_InBigCave(): boolean; +begin + if (FindNPCChatText('gnore', Nothing) or (FindNPCChatText('pologise', Nothing))) then + begin + addToSRLLog('Frog_InBigCave: Failed to click Ro, we are in the big cave'); + DoConversation('', false); + result := true; + end; +end; + +(** + * Author: Marpis & Coh3n + * Description: Walks to an area specified by 'Where' in the cave. + *) +function Frog_WalkCave(center: Tpoint; where: integer): boolean; +begin + if (not loggedIn()) then + exit; + + addToSRLLog('Frog_WalkCave: Relocating in cave'); + + case Where of + 0, 2, 4: mouse(center.x, center.y + 50, 2, 2, mouse_Left); // south + 1: mouse(center.x + 40, center.y, 2, 2, mouse_Left); // east + 3: mouse(center.x - 40, center.y, 2, 2, mouse_Left); // west + 5: mouse(center.x, center.y, 2, 2, mouse_Left); // center + end; + + if (flag) then + begin + result := true; + wait(1500 + random(500)); + end; +end; + +(** + * Author: Coh3n + * Description: Goes through the conversation with the Royal Frog in the big + * cave. + *) +function Frog_TalkCave(): boolean; +var + t: integer; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + 30000); + + repeat + findNPCChatText('lease', clickLeft); + clickContinue(true, true); + result := tabExists(TAB_MAGIC); + until(result or (getSystemTime > t)); + + if (not result) then + addToSRLLog('Frog_TalkCave: Failed to go through conversation with Royal Frog'); +end; + +(** + * Author: Coh3n + * Description: Solves the big cave part of the random event. + *) +function Frog_SolveCave(): boolean; +var + t, x, y, tries, dtmCenter: integer; + aFound: extended; +begin + if (not loggedIn()) then + exit; + + addToSRLLog('Frog_SolveCave: Solving frog big cave'); + t := (getSystemTime + (5 * 60000)); + dtmCenter := Frog_GetDTM(FROG_DTM_CENTER); + + repeat + if (Frog_ClickRoyal()) then + begin + result := Frog_TalkCave(); + break; + end; + + if (findDTMRotatedAlternating(dtmCenter, x, y, MMX1, MMY1, MMX2, MMY2, -Pi/4, Pi/4, Pi/30, aFound)) then + Frog_WalkCave(point(x, y), tries) + else + addToSRLLog('Frog_SolveCave: Didn''t find DTM_FROG_CENTER'); + + Inc(tries); + + // reset so it'll still walk + if (tries > 5) then + tries := 0; + until(getSystemTime > t); + + if (not result) then + addToSRLLog('Frog_SolveCave: Failed to solve big frog cave'); + + freeDTM(dtmCenter); +end; + +(** + * Author: J J + * Description: Returns a TPA with the possible Queen locations + *) +function RoyalLoc: Boolean; +var + i, Red, Yellow: Integer; + GreenFrog: TPointArray; + GreenFrogSplit, GoodFrogSplit: T2DPointArray; + SearchBox: TBoxArray; + +begin + // Finding the frogs by using their green color + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(0.14, 0.53); + if FindColorsSpiralTolerance(MSCX, MSCY, GreenFrog, 3576607, MSX1, MSY1, MSX2, MSY2, 24) then + begin + SplitTPAExWrap(GreenFrog, 5, 5, GreenFrogSplit); + SortATPASize(GreenFrogSplit, True); + + // Sorting out the boxes that are frogs + for i:=0 to high(GreenFrogSplit) do + if Length(GreenFrogSplit[i]) > 100 then + begin + SetLength(GoodFrogSplit, Length(GoodFrogSplit)+1); + GoodFrogSplit[Length(GoodFrogSplit)-1] := GreenFrogSplit[i]; + end; + + // Checking for yellow & red colors in each box + SetLength(SearchBox, Length(GoodFrogSplit)); + for i:=0 to high(GoodFrogSplit) do + begin + SearchBox[i] := IntToBox(GetTPABounds(GoodFrogSplit[i]).X1-5, GetTPABounds(GoodFrogSplit[i]).Y1-5, GetTPABounds(GoodFrogSplit[i]).X2+5, GetTPABounds(GoodFrogSplit[i]).Y2+5); + SetColorSpeed2Modifiers(0.15, 1.21); + Red := CountColorTolerance(1984209, SearchBox[i].X1, SearchBox[i].Y1, SearchBox[i].X2, SearchBox[i].Y2, 19); + SetColorSpeed2Modifiers(0.09, 1.28); + Yellow := CountColorTolerance(2012628, SearchBox[i].X1, SearchBox[i].Y1, SearchBox[i].X2, SearchBox[i].Y2, 18); + + if (Red < 20) and (Yellow > 25) then + begin + SetLength(RoyalPos, Length(RoyalPos)+1); + RoyalPos[Length(RoyalPos)-1] := Point((SearchBox[i].X1+SearchBox[i].X2) div 2, (SearchBox[i].Y1+SearchBox[i].Y2) div 2); + end; + end; + end; + + // The result + if (Length(RoyalPos) > 0) then + Result := True; +end; + +(** + * Author: J J + * Description: Returns true when the player is talking to the Royal Frog. + * Credits to [J]ustin for pointing out a mistake with the break placement! + *) +function TalkToRoyal: Boolean; +var + i: Integer; + +begin + if (RoyalLoc) then + begin + for i:=0 to high(RoyalPos) do + begin + MMouse(RoyalPos[i].X, RoyalPos[i].Y, RandomRange(-2, 2), RandomRange(-2, 2)); + if WaitUpTextMulti(['rog /', 'Frog /'], 100) then + begin + case Random(7) of + 0..4: ClickMouse2(1); + 5..6: begin + ClickMouse2(0); + WaitOptionMulti(['alk'], 500); + end; + end; + FFlag(0); + repeat + Wait(50 + Random(50)); + until not(IsMoving); + Wait(1000 + Random(1000)); + if (Frog_RoyalTalking()) then + begin + Result := True; + break; + end; + end; + end; + end; +end; + +(** + * Author: Coh3n + * Description: Solves the Frog random event, returns false if player + * had to go through the big cave because RS still teleports you. + *) +function Frog_Solve(): boolean; +var + t: integer; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + (10 * 60000)); // 5 minutes max + Frog_Setup(); + + repeat + if TalkToRoyal then // returns true if Royal Frog is talking + // may have clicked wrong frogs, need to solve large cave + if (not Frog_InBigCave()) then + begin + doConversation('', false); + wait(3000 + random(500)); // wait for the kiss to finish + clickContinue(true, true); + result := waitTabExists(TAB_MAGIC, 10000); + end else + if (Frog_SolveCave()) then // still get teleported after big cave + begin + addToSRLLog('Frog_Solve: Solved frog big cave, but failed random'); + waitTabExists(TAB_MAGIC, 5000); + break; + end; + until(result or (getSystemTime > t)); + + // Setting back the normal mousespeed + MouseSpeed := 15; + + if (not result) then + addToSRLLog('Frog_Solve: Frog solver failed or timed out'); +end; \ No newline at end of file diff --git a/SRL/core/antirandoms/leo.simba b/SRL/core/antirandoms/leo.simba new file mode 100644 index 0000000..6b7ca88 --- /dev/null +++ b/SRL/core/antirandoms/leo.simba @@ -0,0 +1,41 @@ +(* +Leo the Gravedigger +=================== + +Stores all the routines to solve the Leo random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +*) + +(** + * Author: + * Description: Detects if a player is in the Leo random. + *) +function Leo_Detect(): boolean; +begin + result := (getNPCChatName() = 'l8o'); +end; + +(** + * Author: + * Description: Solves the random. + *) +function Leo_Solve(): boolean; +var + t: integer; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + (5 * 60000)); // maximum 5 minutes + doConversation('', false); + + repeat + + until(result or (getSystemTime > t)); + + if (not result) then + addToSRLLog('Leo_Solve: '' solver timed out'); +end; + diff --git a/SRL/core/antirandoms/maze.simba b/SRL/core/antirandoms/maze.simba new file mode 100644 index 0000000..7d47771 --- /dev/null +++ b/SRL/core/antirandoms/maze.simba @@ -0,0 +1,412 @@ +(* +Maze +==== + +The Maze file stores the routines to solve the maze random event. + +This solver uses black minimap color counts in specific areas to determine which +path to solve. It uses specific minimap corrdinate clicking to walk to each +door, and uses simple TPA work to find and click each door. + +*) + +type + TMazePath = record + name: string; + area: TBox; // area to search for black on MM + minCount, maxCount: integer; // range for lenght of black found on MM + + // [x, y, compassAngle] if compassAngle = '', it won't look for the door (some rooms need to walk further) + // compass angle should be so you can see the DARK side of the door + path: array of TVariantArray; + end; + TMazePathArray = array of TMazePath; + +const + MAZE_PATH_COUNT = 5; + MAZE_PATH_SW = 0; + MAZE_PATH_NE = 1; + MAZE_PATH_SE = 2; + MAZE_PATH_NW = 3; + MAZE_PATH_COMMON = 4; + +(** + * Author: DemiseScythe & Coh3n + * Description: Returns true if player is in the random. + *) +function Maze_Detect(): boolean; +begin + // WARNING: sometimes magic tab exists, sometimes it doesn't + + if (getNPCChatName() = SRL_NPC_OLDMAN) then + // the red maze walls on the minimap + result := (countColorTolerance(197614, MMX1, MMY1, MMX2, MMY2, 15) > 1000); +end; + +(** + * Author: DemiseScythe & Coh3n + * Description: Returns an array of all the different maze paths. + *) +function Maze_GetPaths(): TMazePathArray; +begin + setLength(result, MAZE_PATH_COUNT); + + with result[MAZE_PATH_NE] do + begin + name := 'North East'; + area := intToBox(668, 60, 687, 73); + minCount := 100; + maxCount := 1200; + + path := [[630, 86, 's'], [672, 94, 's'], [676, 83, 's'], [609, 78, 's'], + [645, 78, 's'], [581, 77, 's'], [670, 80, 's'], [604, 49, 'w'], + [608, 94, 's'], [575, 81, 'w'], [611, 128, 's'], [583, 78, 's']]; + end; + + with result[MAZE_PATH_SE] do + begin + name := 'South East'; + area := intToBox(MMCX, MMCY, MMX2, MMY2); + minCount := 800; + maxCount := 3400; + + path := [[580, 82, 's'], [698, 79, 's'], [560, 81, ''], [637, 116, 'w'], + [676, 81, 'w'], [648, 82, 'w'], [574, 83, 'w'], [690, 83, ''], + [643, 90, 'w'], [663, 86, 'w'], [645, 95, 's'], [561, 94, 'w'], + [662, 83, 'w'], [657, 97, 's']]; + end; + + with result[MAZE_PATH_SW] do + begin + name := 'South West'; + area := intToBox(MMX1, MMCY, MMCX, MMY2); + minCount := 3500; + maxCount := 9999; + + path := [[576, 81, 's'], [674, 33, 'w'], [676, 90, 'w'], [578, 93, 'w'], + [605, 91, 'w'], [593, 76, 's'], [583, 86, 's'], [650, 93, 's'], + [639, 143, 'w'], [660, 77, 'w'], [645, 58, 's'], [640, 47, 'w'], + [612, 137, 's'], [583, 78, 's']]; + end; + + with result[MAZE_PATH_NW] do + begin + name := 'North West'; + area := intToBox(551, 78, 610, 110); + minCount := 1000; + maxCount := 2000; + + path := [[586, 82, 'w'], [658, 78, 'w'], [602, 97, 's'], [590, 76, 's'], + [642, 80, 's'], [594, 73, 'w'], [604, 89, 'w'], [578, 89, 'w'], + [612, 90, 'w'], [584, 79, 's'], [628, 152, ''], [638, 92, 's'], + [583, 78, 's']]; + end; + + // the end of each path is commone throughout + with result[MAZE_PATH_COMMON] do + begin + name := 'Common'; + path := [[614, 100, 'w'], [662, 83, 's'], [627, 51, 's'], [637, 89, 'w']]; + end; +end; + +(** + * Author: Naum & Coh3n + * Description: Returns the path for the current player. + *) +function Maze_DetectPath(paths: TMazePathArray; var resultPath: TMazePath): boolean; +var + i, tmpCount: integer; +begin + if (not loggedIn()) then + exit; + + clickNorth(SRL_ANGLE_HIGH); // REQUIRED! + + for i := 0 to high(paths) do + with paths[i] do + begin + // so it doesn't look for MAZE_PATH_COMMON spawn (doesn't exist) + if (i = MAZE_PATH_COMMON) then + continue; + + tmpCount := countColorTolerance(clBlack, area.x1, area.y1, area.x2, area.y2, 50); + + if (inRange(tmpCount, minCount, maxCount)) then + begin + addToSRLLog('Maze_DetectPath: Found path - '+name); + resultPath := paths[i]; + result := true; + break; + end; + end; +end; + +(** + * Author: Coh3n + * Description: Examines the old man to remove last chat line text. Used as a + * failsafe in case the script accidentially clicks a wall. + *) +function Maze_ExamineOldMan(): boolean; +var + t, dtmMan: integer; + chatPrevious: string; +begin + if (not loggedIn()) then + exit; + + dtmMan := DTMFromString('mQwAAAHicY2ZgYLgBxJeA+DoQTwPiGUC8GIh5VbQYuGQUGXiU1Bn4gXwYZgRiJigGAgAO2gV/'); + chatPrevious := getBlackChatMessage(); // get the chat line text + t := (getSystemTime + 5000); + + if clickDTMRotatedIn(dtmMan, MSCX - 70, MSCY - 70, MSCX + 70, MSCY + 70, -Pi/4, Pi/4, Pi/30, ['ster'], mouse_Right) then + begin + if (waitOption('xamin', 300)) then + while (getSystemTime < t) do + begin + // wait for the chat text to change + if (getBlackChatMessage() <> chatPrevious) then + begin + result := true; + break; + end; + + wait(200); + end; + + end else + addToSRLLog('Maze_ExamineOldMan: Failed to click Old Man DTM'); + + freeDTM(dtmMan); +end; + +(** + * Author: Coh3n & Naum + * Description: Returns true if any doors are found. Returns their points in + * doorPts. + *) +//{$i srl/srl/misc/paintsmart.simba} +function Maze_FindDoors(var doorPts: TPointArray): boolean; +var + tpa: TPointArray; + atpa: T2DPointArray; + i, c, tmpCTS: integer; +begin + if (not loggedIn()) then + exit; + + tmpCTS := getColorToleranceSpeed(); + setColorToleranceSpeed(3); + + // the darker door color & smaller main screen box + findColorsTolerance(tpa, 4342341, MSX1+100, MSY1+75, MSX2-100, MSY2-75, 5); + //SMART_DrawDots(tpa); + //SMART_ClearCanvas(); + + setColorToleranceSpeed(tmpCTS); + + // make sure the door is found + if (length(tpa) <= 0) then + begin + addToSRLLog('Maze_FindDoor: Failed to find maze door color'); + exit; + end; + + // split the colors into boxes + atpa := splitTPA(tpa, 1); + setLength(doorPts, length(atpa)); + + // loop through all the boxes, filtering out wall points + for i := 0 to high(atpa) do + begin + // if there aren't enough points, it's probably a wall point + if (length(atpa[i]) < 220) then + continue; + + //SMART_DrawBoxEx(false, getTPABounds(atpa[i]), clRed); + doorPts[c] := middleTPA(atpa[i]); + inc(c); + end; + + setLength(doorPts, c); // gets rid of the empty elements + sortTPAFrom(doorPts, point(MSCX, MSCY)); // sort from the player + + result := (c > 0); + + addToSRLLog('Maze_FindDoors: Found '+toStr(c)+' possible doors'); +end; + +(** + * Author: Coh3n + * Description: Clicks a maze door. + *) +function Maze_ClickDoor(): boolean; +var + i, x, y, t, c: integer; + doorPts: TPointArray; + s: string; + b: TBox; +begin + if (not loggedIn()) then + exit; + + if (Maze_FindDoors(doorPts)) then + for i := 0 to high(doorPts) do + begin + // small box to spiral the mouse + b := intToBox(doorPts[i].x - 20, doorPts[i].y - 20, doorPts[i].x + 20, doorPts[i].y + 20); + + // sometimes the uptext doesn't show when moused on the door + if (spiralMouseMulti(x, y, b.x1, b.y1, b.x2, b.y2, ['pen', 'all'], 5, 8)) then + begin + mouse(x, y, 5, 5, mouse_Right); + addToSRLLog('Maze_ClickDoor: Clicked door'); + + // in case it clicks in between the door bars + if (not waitOption('pen', 300)) then + begin + mouse(x + random(6), y, 5, 5, mouse_Right); + if (not waitOption('pen', 300)) then + continue; + end; + + flag(); + + t := (getSystemTime + 5000); + while (isMoving() and (getSystemTime < t)) do + wait(50); + + // failsafe to make sure we didn't click a wall + s := getBlackChatMessage(); + if ((pos('reach', s) > 0) or (pos('open', s) > 0)) then + begin + addToSRLLog('Maze_ClickDoor: Accidentially clicked the wall'); + + // get rid of the "bad" chat text, tries 3 times + for c := 1 to 3 do + if (Maze_ExamineOldMan()) then + begin + addToSRLLog('Maze_ClickDoor: Examined Old Man'); + break; + end; + + continue; + end else + result := true; + + break; + end; + + wait(300 + random(200)); + end; + + if (not result) then + addToSRLLog('Maze_ClickDoor: Failed to click maze door'); +end; + +(** + * Author: DemiseScythe & Coh3n + * Description: Walks the path. + *) +function Maze_WalkPath(path: TMazePath): boolean; +var + i, t: integer; + doorClicked: boolean; +begin + if (not loggedIn()) then + exit; + + addToSRLLog('Maze_WalkPath: Walking '+path.name+' path'); + + for i := 0 to high(path.path) do + begin + if (path.path[i][2] <> '') then + makeCompass(path.path[i][2]); + + mouse(path.path[i][0], path.path[i][1], 2, 2, mouse_Left); + flag(); + wait(1500 + random(500)); + doorClicked := false; + + // if we want to look for the door (some rooms have more than one walking point) + if (path.path[i][2] <> '') then + begin + // in a loop in case we misclick the door + repeat + inc(t); + + if (Maze_ClickDoor()) then + begin + addToSRLLog('Maze_WalkPath: Finished room '+toStr(i)); + result := (i = high(path.path)); + doorClicked := true; + t := 0; + break; + end; + + until(t >= 10); // maximum 10 click door calls + + if (not doorClicked) then + begin + addToSRLLog('Maze_WalkPath: Failed to solve room '+toStr(i)); + result := false; + break; + end; + end; + end; + + if (result) then + addToSRLLog('Maze_WalkPath: Finished path '+path.name) + else + addToSRLLog('Maze_WalkPath: Didn''t finish path '+path.name); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Touches the shrine in the middle of the maze. + *) +function Maze_TouchShrine(): boolean; +var + dtmShrine, t: integer; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + 5000); + dtmShrine := DTMFromString('mggAAAHicY2NgYPgDxD+B+DcQfwJiDkYGhr9A+ggQnwHiy0B8AIgPAvE+IO5obmIwNjRgyEpLZcjLyGAIDw5mqC4rY+AHymHDjDgwBAAAz2UQ6Q=='); + + // in a loop to make sure we don't misclick + repeat + if (clickDTMRotatedIn(dtmShrine, 220, 175, 285, 225, -Pi/4, Pi/4, Pi/60, ['ouch'], mouse_Left)) then + result := (not didYellowClick()); + + wait(100 + random(300)); + until(result or (getSystemTime > t)); + + freeDTM(dtmShrine); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Solves the Maze random event. + *) +function Maze_Solve(): boolean; +var + paths: TMazePathArray; + path: TMazePath; +begin + if (not loggedIn()) then + exit; + + paths := Maze_GetPaths(); + + if (Maze_DetectPath(paths, path)) then + begin + if (Maze_WalkPath(path)) then + if (Maze_WalkPath(paths[MAZE_PATH_COMMON])) then + if (Maze_TouchShrine()) then + result := waitTabExists(TAB_MAGIC, 15000); + end else + addToSRLLog('Maze_Solve: Didn''t detect maze path'); +end; + diff --git a/SRL/core/antirandoms/mime.simba b/SRL/core/antirandoms/mime.simba new file mode 100644 index 0000000..d414192 --- /dev/null +++ b/SRL/core/antirandoms/mime.simba @@ -0,0 +1,435 @@ +(* +Mime +==== + +The Mime file stores the routines to solve the mime random event. + +This solver uses pixel shifting to determine which emote the mime is performing. +To compensate for the spotlight, it will get the total pixel shift in a large +box around the mime, and the pixel shift in a small box around the mime. It +then calculates the percentage of the small shift in the big shift. Lastly, +it compares the stored emotes (Mime_GetEmotes) with the scanned emote, resulting +a certain score. If the score is high enough, it's found the right emote. + +*) + +const + MIME_EMOTE_COUNT = 8; + MIME_EMOTE_THINK = 0; + MIME_EMOTE_BOX = 1; + MIME_EMOTE_WALL = 2; + MIME_EMOTE_DANCE = 3; + MIME_EMOTE_CRY = 4; + MIME_EMOTE_CLIMB = 5; + MIME_EMOTE_LEAN = 6; + MIME_EMOTE_LAUGH = 7; + +(** + * Stores a Mime emote's properties. See Mime_ScanMime for more details. + *) +type + TMimeEmote = record + name: string; + shiftSmall: integer; // total pixel shift in a small box around Mime + shiftBig: integer; // total pixel shift in a big box around Mime + shiftPercent: extended; // percent of small shift in large + textTPACount: integer; + end; + TMimeEmoteArray = array of TMimeEmote; + +(** + * Author: Coh3n & NCDS + * Description: Returns true if player is in the random. + *) +function Mime_Detect(): boolean; +var + i: integer; +begin + if (not loggedIn()) then + exit; + + for i := TAB_COMBAT to TAB_OBJECTIVES do + if (tabExists(i)) then + exit; + + // the ligher red on the minimap + result := (countColorTolerance(592960, MMX1, MMY1, MMX2, MMY2, 20) > 500) and + (not tabExists(TAB_EMOTES)); +end; + +(** + * Author: Coh3n + * Description: Returns a TMimeEmoteArray of all the Mime's emotes. + *) +function Mime_GetEmotes(): TMimeEmoteArray; +begin + setLength(result, MIME_EMOTE_COUNT); + + with result[MIME_EMOTE_THINK] do + begin + name := 'Think'; + shiftSmall := 10000; + shiftBig := 13000; + shiftPercent := 84.0; + textTPACount := 87; + end; + + with result[MIME_EMOTE_BOX] do + begin + name := 'Glass Box'; + shiftSmall := 14800; + shiftBig := 20500; + shiftPercent := 70.0; + textTPACount := 139; + end; + + with result[MIME_EMOTE_WALL] do + begin + name := 'Glass Wall'; + shiftSmall := 5500; + shiftBig := 6500; + shiftPercent := 95.0; + textTPACount := 155; + end; + + with result[MIME_EMOTE_DANCE] do + begin + name := 'Dance'; + shiftSmall := 19000; + shiftBig := 35000; + shiftPercent := 55.0; + textTPACount := 96; + end; + + with result[MIME_EMOTE_CRY] do + begin + name := 'Cry'; + shiftSmall := 10000; + shiftBig := 11500; + shiftPercent := 85.0; + textTPACount := 54; + end; + + with result[MIME_EMOTE_CLIMB] do + begin + name := 'Climb Rope'; + shiftSmall := 17000; + shiftBig := 28000; + shiftPercent := 60.0; + textTPACount := 168; + end; + + with result[MIME_EMOTE_LEAN] do + begin + name := 'Lean on Air'; + shiftSmall := 10000; + shiftBig := 15000; + shiftPercent := 84.0; + textTPACount := 148; + end; + + with result[MIME_EMOTE_LAUGH] do + begin + name := 'Laugh'; + shiftSmall := 9500; + shiftBig := 12600; + shiftPercent := 76.0; + textTPACount := 101; + end; +end; + +(** + * Author: Coh3n + * Description: Prints the 'emote' to the debug box. + *) +procedure Mime_DebugEmote(emote: TMimeEmote); +begin + addToSRLLog('Name: '+emote.name); + addToSRLLog('ShiftSmall: '+toStr(emote.shiftSmall)); + addToSRLLog('ShiftBig: '+toStr(emote.shiftBig)); + addToSRLLog('ShiftPercent: '+toStr(emote.shiftPercent)); +end; + +(** + * Author: Coh3n + * Description: Sets up the screen to solve the random. + *) +procedure Mime_Setup(); +begin + if (not loggedIn()) then + exit; + + clickNorth(SRL_ANGLE_LOW); // REQUIRED. Data was gathered at this angle + doConversation('', false); // get past GE messages + + // click front of stage & move the mouse away from chat box so text can be recognized + mouse(250, 300, 10, 10, mouse_Left); + mouse(MCX2 + 30 + random(100), 170, 100, 100, mouse_Move); +end; + +(** + * Author: Coh3n + * Description: Returns true if the Mime is performing an Emote. While the + * Mime is performing, there's always the same black text in the chat box. + *) +function Mime_IsPerforming(): boolean; +begin + result := (countColorTolerance(clBlack, MCX1, MCY1, MCX2, MCY2, 0) = 683); +end; + +(** + * Author: Coh3n + * Description: Returns the total pixel shifting over the specified scanning + * time. The results from this are in Mime_GetEmotes, so if scanning constants + * change, the records may need to change as well. + *) +const + _MIME_SCAN_TIME = 3000; // time to scan for pixel shifting + _MIME_SCAN_AFTER = 1500; // wait time AFTER perfomance starts (i.e. Mime_IsPerforming returns true); lessens the affect of the spotlight + _MIME_SCAN_DIV = 15; // determines pixel shift interval + +function Mime_ScanMime(): TMimeEmote; +var + t: integer; + shiftBoxes: TBoxArray; + tmpShifts: TIntegerArray; +begin + wait(_MIME_SCAN_AFTER); // wait until after the spotlight appears + + t := (getSystemTime + _MIME_SCAN_TIME); + + shiftBoxes := [ intToBox(400, 20, 510, 210), // box around the entire Mime + intToBox(440, 82, 510, 145) ]; // box around the upper body of the mime + + // get the total pixel shift over the total scanning time + while (getSystemTime < t) do + begin + tmpShifts := pixelShiftMulti(shiftBoxes, _MIME_SCAN_TIME div _MIME_SCAN_DIV); + result.shiftBig := result.shiftBig + tmpShifts[0]; + result.shiftSmall := result.shiftSmall + tmpShifts[1]; + end; + + result.shiftPercent := (result.shiftSmall / extended(result.shiftBig)) * 100; + + // waits for performance to be over + t := (getSystemTime + 5000); + while (Mime_IsPerforming() and (getSystemTime < t)) do + wait(50 + random(25)); +end; + +(** + * Author: Coh3n + * Description: Returns the corresponding Mime's emote constant (see top). Uses + * Wizzup?'s scoring system to decide which emote was found. + *) +function Mime_IdentifyEmote(emotes: TMimeEmoteArray): integer; +var + i, maxScore, maxIndex: integer; + tmpEmote: TMimeEmote; + scores: TIntegerArray; +begin + if (not loggedIn()) then + exit; + + result := -1; + setLength(scores, length(emotes)); + + // wait for the performance to start before scanning + if (waitFunc(@Mime_IsPerforming, 50, 10000)) then + begin + addToSRLLog('Mime_IdentifyEmote: Identifying emote'); + tmpEmote := Mime_ScanMime(); + + {$IFDEF DEBUG_MIME} + tmpEmote.name := 'Scanned Emote'; + Mime_DebugEmote(tmpEmote); + {$ENDIF} + end; + + // loop through emotes to see which fits + for i := 0 to high(emotes) do + begin + // checks if big/small shifts are in range of emotes[i] + if (inRange(tmpEmote.shiftSmall, emotes[i].shiftSmall - 1500, emotes[i].shiftSmall + 1500)) then + scores[i] := scores[i] + 6; + + if (inRange(tmpEmote.shiftBig, emotes[i].shiftBig - 1500, emotes[i].shiftBig + 1500)) then + scores[i] := scores[i] + 6; + + // check if pixel shifting is in range of min/max + if (inRange(tmpEmote.shiftBig + tmpEmote.shiftSmall div 2, emotes[i].shiftSmall, emotes[i].shiftBig)) then + scores[i] := scores[i] + 4; + + // in range of emote's shiftPercet +/- 3% + if (scores[i] <> 0) then + if (tmpEmote.shiftPercent = emotes[i].shiftPercent) then + scores[i] := scores[i] + 15 + else + if ((tmpEmote.shiftPercent > (emotes[i].shiftPercent - 3)) and (tmpEmote.shiftPercent < (emotes[i].shiftPercent + 3))) then + scores[i] := scores[i] + 9; + end; + + // get the highest score, set result + maxScore := -1; + maxIndex := -1; + for i := 0 to high(scores) do + if (scores[i] > maxScore) then + begin + maxScore := scores[i]; + maxIndex := i; + end; + + // didn't ID if score is too low + if (maxScore > 0) then + result := maxIndex; + + if (result <> -1) then + addToSRLLog('Mime_IdentifyEmote: Found emote '+emotes[result].name+' with a score of '+toStr(maxScore)) + else + addToSRLLog('Mime_IdentifyEmote: Didn''t identify emote'); +end; + +(** + * Author: Coh3n + * Description: Returns a TBox of the 'Text' slot. Starts at 1 and goes across + * the chat box. + *) +function Mime_TextBox(slot: integer): TBox; +begin + result := gridBox(slot, 4, 2, 90, 20, 90, 40, point(100, 397)); +end; + +(** + * Author: Coh3n + * Description: Returns the tpa length of the text color for 'text'. See + * Mime_TextBox. + *) +function Mime_GetTextTPA(text: integer): integer; +var + tpa: TPointArray; + b: TBox; +begin + if (not loggedIn()) then + exit; + + b := Mime_TextBox(text); + + // the colour of the main text (not shadow) + if (findColorsTolerance(tpa, 11174789, b.x1, b.y1, b.x2, b.y2, 10)) then + result := length(tpa); + + //addToSRLLog('slot: '+toStr(text)+' length: '+toStr(result)); +end; + +(** + * Author: Coh3n + * Description: Clicks the text in the chat box for the 'Emote'. + *) +function Mime_ClickText(emote: TMimeEmote): boolean; +var + i, len: integer; + p: TPoint; +begin + if (not loggedIn()) then + exit; + + // loop through each "text box" in the chat box to find the correct text + for i := 1 to 8 do + begin + len := Mime_GetTextTPA(i); + + // +/- tolerance on TPA count just in case + if (inRange(len, emote.textTPACount - 3, emote.textTPACount + 3)) then + begin + addToSRLLog('Mime_ClickText: Clicked text '+emote.name); + p := middleBox(Mime_TextBox(i)); + mouse(p.x, p.y, 10, 3, mouse_Left); + wait(1500 + random(500)); + + // move the mouse away from text so text color can be found later + mmouse(MCX2 + 30 + random(30), 170, 50, 50); + result := true; + break; + end; + end; + + if (not result) then + addToSRLLog('Mime_ClickText: Unable to click text - '+emote.name); +end; + +(** + * Author: Coh3n + * Description: Identifies and performs the Mime's emote. + *) +function Mime_DoEmote(emotes: TMimeEmoteArray): boolean; +var + i, t: integer; +begin + if (not loggedIn()) then + exit; + + i := Mime_IdentifyEmote(emotes); + if (i <> -1) then + begin + t := (getSystemTime + 5000); + while (getSystemTime < t) do + if (Mime_ClickText(emotes[i])) then + begin + result := true; + break; + end; + end; +end; + +(** + * Author: Coh3n + * Description: Solves the random. + *) +function Mime_Solve(): boolean; +var + t: integer; + emotes: TMimeEmoteArray; +begin + if (not loggedIn()) then + exit; + + Mime_Setup(); + emotes := Mime_GetEmotes(); + + // perform emotes until finished or tries is exceeded + repeat + Inc(t); + Mime_DoEmote(emotes); + result := (not Mime_Detect() and (loggedIn())); + until(result or (t > 30)); + + if (not result) then + addToSRLLog('Mime_Solve: Mime solver exceeded maximum tries'); +end; + +(** + * Author: Coh3n + * Description: Used to gather data for the emote records. + *) +procedure Mime_GatherData(times: integer); +var + i: integer; + tmpEmote: TMimeEmote; +begin + for i := 1 to times do + begin + // need to reset so properties are accurate + tmpEmote.shiftSmall := 0; + tmpEmote.shiftBig := 0; + tmpEmote.shiftPercent := 0; + + if (waitFunc(@Mime_IsPerforming, 50, 10000)) then + begin + tmpEmote.name := toStr(i); + tmpEmote := Mime_ScanMime(); + + Mime_DebugEmote(tmpEmote); + end; + end; +end; + diff --git a/SRL/core/antirandoms/molly.simba b/SRL/core/antirandoms/molly.simba new file mode 100644 index 0000000..21d2346 --- /dev/null +++ b/SRL/core/antirandoms/molly.simba @@ -0,0 +1,860 @@ +(* +Molly +===== + +Stores all the routines to solve the Molly random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +Remaked on 25/06/2012 by J J +Development blog (includes resources): http://villavu.com/forum/showthread.php?t=83175 +This should be working now :) + +*) + +var + HookBox, PreviousBox, MollyTime, MaxMollyTime, FalseMolly: Integer; + MollyHair: String; + CorrectMolly: Boolean; + +(** + * Author: Coh3n and/or [J]ustin? + * Description: Detects if a player is in the random. + *) +function Molly_Detect(): boolean; +begin + if (not tabExists(TAB_MAGIC)) then + if (areTalking()) then + if (countColorTolerance(clBlack, MMCX-30, MMCY-30, MMCX+30, MMCY+30, 20) = 3721) then + result := (getNPCChatName <> SRL_NPC_OLDMAN); +end; + +{******************************************************************************* +procedure TalkToMolly; +by: J J +Description: Talks to Molly at start +*******************************************************************************} +procedure TalkToMolly; +var + FloorColors, MollyColors: TPointArray; + SearchBox: TBox; + MollySplit: T2DPointArray; + P: TPoint; + +begin + AddToSRLLog('Trying to click on Molly'); + SearchBox := IntToBox(60, 215, 125, 265); + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(0.17, 0.54); + if FindColorsSpiralTolerance(260, 200, FloorColors, 4215386, SearchBox.X1, SearchBox.Y1, SearchBox.X2, SearchBox.Y2, 8) then + begin + MollyColors := TPAFromBox(SearchBox); + MollyColors := ClearTPAFromTPA(MollyColors, FloorColors); + SplitTPAExWrap(MollyColors, 1, 1, MollySplit); + SortATPASize(MollySplit, True); + if Length(MollySplit[0]) > 20 then + begin + P := MiddleTPA(MollySplit[0]); + MMouse(P.X, P.Y, RandomRange(-2, 2), RandomRange(-2, 2)); + Wait(50 + Random(100)); + ClickMouse2(1); + AddToSRLLog('Succesfully clicked on Molly'); + end; + end; +end; + +{******************************************************************************* +procedure MollyTalk; +by: J J +Description: Handles the conversations with Molly +*******************************************************************************} +procedure MollyTalk; +begin + if AreTalking then + begin + AddToSRLLog('We are talking, finishing conversation'); + repeat + if not(ClickContinue(True, True)) then + TypeSendEx('1', False); + Wait(750 + Random(750)); + until not(AreTalking); + end; +end; + +{******************************************************************************* +procedure GrabMollyHairColor; +by: J J +Description: Returns molly's hair color by using the hair color while in chat +*******************************************************************************} +procedure GrabMollyHairColor; +var + HairColor, Tol, i: Integer; + HairColorExtended, Lowest: Extended; + HairColors: TIntegerArray; + Speed2Modifiers, HairDefinedColors: TExtendedArray; + +begin + HairColors := GetColors(TPAFromBox(IntToBox(48, 375, 67, 396))); + HairColor := GetBestColor(HairColors, 2, Tol, Speed2Modifiers); + + // Dark brown, dark blond, light brown, red, lightblond \\ + HairDefinedColors := [2178123, 3103606, 3954284, 2441835, 2843007]; + HairColorExtended := HairColor; + Lowest := HairDefinedColors[0]+1; + for i:=0 to 4 do + begin + if Abs(HairColor-HairDefinedColors[i]) < Lowest then + begin + Lowest := Abs(HairColor-HairDefinedColors[i]); + case i of + 0: MollyHair := 'DarkBrown'; + 1: MollyHair := 'DarkBlond'; + 2: MollyHair := 'LightBrown'; + 3: MollyHair := 'Red'; + 4: MollyHair := 'LightBlond'; + end; + end; + end; + AddToSRLLog('Molly''s hair color: '+MollyHair+''); +end; + +{******************************************************************************* +procedure OpenMollyDoor(Where: String); +by: J J +Description: Opens the door in the Molly random event + Uses the brown colors of the door +*******************************************************************************} +procedure OpenMollyDoor(Where: String); +var + N: Integer; + P: TPoint; + Door: TPointArray; + DoorSplit: T2DPointArray; + Searchbox: Array of TBox; + Hue, Sat: Array of Extended; + Col, Tol: Array of Integer; + +begin + AddToSRLLog('Attempting to open the door'); + + case Where of + 'begin': N := 0; + 'end': N := 1; + end; + + SearchBox := [IntToBox(380, 80, 480, 180), IntToBox(10, 70, 90, 180)]; + Col := [7115939, 6063508]; + Tol := [5, 11]; + Hue := [0.35, 0.17]; + Sat := [0.77, 0.34]; + + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(Hue[N], Sat[N]); + if FindColorsSpiralTolerance(MSCX, MSCY, Door, Col[N], SearchBox[N].X1, SearchBox[N].Y1, SearchBox[N].X2, SearchBox[N].Y2, Tol[N]) then + begin + SplitTPAExWrap(Door, 3, 3, DoorSplit); + SortATPASize(DoorSplit, True); + if Length(DoorSplit[0]) > 10 then + begin + P := MiddleTPA(DoorSplit[0]); + MMouse(P.x, P.y, RandomRange(-5, 5), RandomRange(-5, 5)); + Wait(RandomRange(50, 150)); + case Random(7) of + 0..4: ClickMouse2(1); + 5..6: begin + ClickMouse2(0); + WaitOptionMulti(['pen', 'Open'], 1000); + end; + end; + AddToSRLLog('Clicked on the door'); + end; + end; +end; + +{******************************************************************************* +procedure UseControls; +by: J J +Description: Opens the control panel in the Molly random event + Uses the wooden parts of the control panel +*******************************************************************************} +procedure UseControls; +var + P: TPoint; + Controls: TPointArray; + ControlsSplit: T2DPointArray; + +begin + AddToSRLLog('Attempting to use the control panels'); + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(0.32, 1.67); + if FindColorsSpiralTolerance(MSCX, MSCY, Controls, 3366960, MSX1, 80, MSX2, 280, 4) then + begin + SplitTPAExWrap(Controls, 2, 2, ControlsSplit); + SortATPASize(ControlsSplit, True); + if Length(ControlsSplit[0]) > 2 then + begin + P := MiddleTPA(ControlsSplit[0]); + MMouse(P.x, P.y, RandomRange(-5, 5), RandomRange(-5, 5)); + Wait(RandomRange(50, 150)); + case Random(7) of + 0..4: ClickMouse2(1); + 5..6: begin + ClickMouse2(0); + WaitOptionMulti(['ontrol', 'Use', 'panel'], 1000); + end; + end; + AddToSRLLog('Clicked on the control panels'); + end; + end; +end; + +{******************************************************************************* +function HookPosition: String; +by: J J +Description: Returns the angle of the hook by using the fence to calculate + the perspective. +*******************************************************************************} +function HookPosition: String; +var + X, Y, i, NormalDTM, TwoLeftDTM, OneLeftDTM, OneRightDTM, TwoRightDTM: Integer; + DTMArray: Array of Integer; + +begin + NormalDTM := DTMFromString('mlwAAAHicY2dgYGBiZGBQBtKaQHwXyH4IxCuA7AQgfQFInwfiR1B8EYld4qzC0OytyZBoIQfGWbaKDHn2SmA2P1AeF2bCg6EAAOTUDx0='); + TwoLeftDTM := DTMFromString('mlwAAAHicY2dgYMhlZWA4zMLAcBSIfwKxCRsDgz4QvwGK/wbK3wTiV1DMz8jAIA/EPECcaiXPkGWryJBoIceQbCnPkG6jAGaDxPlBanFgJjwYCgC16Q3z'); + OneLeftDTM := DTMFromString('mlwAAAHicY2dgYKhkZWA4xMLAcASI/wGxPRsDgzUQ/wSK/wHKPwfib0D8EYgZGBkYhIGYFYiTLeUZ0m0UGBIt5FDYqVbyDPxApbgwEx4MBQDPBg4e'); + OneRightDTM := DTMFromString('mlwAAAHicY2dgYOhnZWBwZmNgsAXibhYGhglAzA8UYwXyfwDl7wHxJyBmZmRgEAdiJiB+B+QnWsgxtPtpMcSbyzKkWsmDaZBYsqU8Az9QHhdmwoOhAACpYAwC'); + TwoRightDTM := DTMFromString('mlwAAAHicY2dgYIhhZWBgZ2NgYAHi80D2NBYGhplAfA+IfwPlbwHxSyB+AcS8jAwMCkDMA8SpVvIM6TYKDIkWcmB2lq0inM0PVIsLM+HBUAAAI+IM+Q=='); + + DTMArray := [NormalDTM, TwoLeftDTM, OneLeftDTM, OneRightDTM, TwoRightDTM]; + + for i:=0 to 4 do + begin + if FindDTM(DTMArray[i], X, Y, MSX1, MSY1, MSX2, MSY2) then + begin + case i of + 0: Result := 'Normal'; + 1: Result := 'TwoLeft'; + 2: Result := 'OneLeft'; + 3: Result := 'OneRight'; + 4: Result := 'TwoRight'; + end; + Break; + end; + end; + + FreeDTMs([NormalDTM, TwoLeftDTM, OneLeftDTM, OneRightDTM, TwoRightDTM]); +end; + +{******************************************************************************* +function NormalHook: Integer; +by: J J +Description: Finds the position of the hook if it is positioned in a normal + perspective. It returns an integer which resembles a position + on this map: http://img841.imageshack.us/img841/4879/tilesystem.png +*******************************************************************************} +function NormalHook: Integer; +var + i, x, CountedColors, Highest: Integer; + Row: Array[0..6] of Array[0..9] of TBox; + X1, Y1, X2, Y2, Multiplier: Array of Integer; + +begin + X1 := [66, 83, 97, 109, 120, 129, 137, 144, 150, 156]; + Y1 := [210, 178, 152, 130, 112, 95, 81, 68, 57, 47]; + X2 := [100, 121, 132, 141, 148, 156, 162, 167, 173, 177]; + Y2 := [234, 199, 171, 145, 124, 106, 90, 77, 64, 53]; + Multiplier := [58, 52, 48, 45, 41, 39, 36, 34, 32, 31]; + + for i:=0 to 6 do + begin + for x:=0 to 9 do + begin + Row[i][x] := IntToBox(X1[x] + (i * Multiplier[x]), Y1[x], X2[x] + (i * Multiplier[x]), Y2[x]); + CountedColors := CountColorTolerance(2373117, Row[i][x].X1, Row[i][x].Y1, Row[i][x].X2, Row[i][x].Y2, 5); + if CountedColors > Highest then + begin + Highest := CountedColors; + Result := (20 + (10 * i) + x); + AddToSRLLog('The hook is in box '+ToStr(Result)+''); + end; + end; + end; +end; + +{******************************************************************************* +function TwoLeftHook: Integer; +by: J J +Description: Finds the position of the hook if it is positioned in the two left + perspective. It returns an integer which resembles a position + on this map: http://img841.imageshack.us/img841/4879/tilesystem.png +*******************************************************************************} +function TwoLeftHook: Integer; +var + i, CountedColors, Highest: Integer; + Box: Array[0..9] of TBox; + X1, Y1, X2, Y2: Array of Integer; + +begin + X1 := [76, 105, 128, 147, 164, 178, 191, 203, 213, 222]; + Y1 := [184, 158, 137, 119, 103, 89, 77, 65, 55, 46]; + X2 := [112, 138, 157, 174, 189, 202, 214, 224, 233, 242]; + Y2 := [208, 177, 153, 133, 115, 99, 86, 74, 63, 53]; + + for i:=0 to 9 do + begin + Box[i] := IntToBox(X1[i], Y1[i], X2[i], Y2[i]); + CountedColors := CountColorTolerance(2373117, Box[i].X1, Box[i].Y1, Box[i].X2, Box[i].Y2, 5); + if CountedColors > Highest then + begin + Highest := CountedColors; + Result := i; + AddToSRLLog('The hook is in box '+ToStr(Result)+''); + end; + end; +end; + +{******************************************************************************* +function OneLeftHook: Integer; +by: J J +Description: Finds the position of the hook if it is positioned in the one left + perspective. It returns an integer which resembles a position + on this map: http://img841.imageshack.us/img841/4879/tilesystem.png +*******************************************************************************} +function OneLeftHook: Integer; +var + i, CountedColors, Highest: Integer; + Box: Array[0..9] of TBox; + X1, Y1, X2, Y2: Array of Integer; + +begin + X1 := [71, 94, 112, 128, 142, 154, 164, 174, 182, 190]; + Y1 := [196, 167, 143, 123, 106, 90, 77, 65, 54, 45]; + X2 := [108, 128, 144, 157, 168, 180, 188, 197, 203, 210]; + Y2 := [222, 187, 160, 138, 118, 101, 86, 73, 62, 51]; + + for i:=0 to 9 do + begin + Box[i] := IntToBox(X1[i], Y1[i], X2[i], Y2[i]); + CountedColors := CountColorTolerance(2373117, Box[i].X1, Box[i].Y1, Box[i].X2, Box[i].Y2, 5); + if CountedColors > Highest then + begin + Highest := CountedColors; + Result := (10 + i); + AddToSRLLog('The hook is in box '+ToStr(Result)+''); + end; + end; +end; + +{******************************************************************************* +function TwoRightHook: Integer; +by: J J +Description: Finds the position of the hook if it is positioned in the two right + perspective. It returns an integer which resembles a position + on this map: http://img841.imageshack.us/img841/4879/tilesystem.png +*******************************************************************************} +function TwoRightHook: Integer; +var + i, CountedColors, Highest: Integer; + Box: Array[0..7] of TBox; + X1, Y1, X2, Y2: Array of Integer; + +begin + X1 := [420, 380, 360, 343, 328, 316, 304, 294]; + Y1 := [182, 158, 137, 119, 103, 89, 77, 66]; + X2 := [445, 413, 390, 371, 354, 339, 327, 315]; + Y2 := [210, 177, 153, 133, 115, 99, 86, 74]; + + for i:=0 to 7 do + begin + Box[i] := IntToBox(X1[i], Y1[i], X2[i], Y2[i]); + CountedColors := CountColorTolerance(2373117, Box[i].X1, Box[i].Y1, Box[i].X2, Box[i].Y2, 5); + if CountedColors > Highest then + begin + Highest := CountedColors; + Result := (100 + i); + AddToSRLLog('The hook is in box '+ToStr(Result)+''); + end; + end; +end; + +{******************************************************************************* +function OneRightHook: Integer; +by: J J +Description: Finds the position of the hook if it is positioned in the one right + perspective. It returns an integer which resembles a position + on this map: http://img841.imageshack.us/img841/4879/tilesystem.png +*******************************************************************************} +function OneRightHook: Integer; +var + i, CountedColors, Highest: Integer; + Box: Array[0..7] of TBox; + X1, Y1, X2, Y2: Array of Integer; + +begin + X1 := [422, 389, 373, 360, 349, 338, 329, 321]; + Y1 := [196, 167, 144, 123, 106, 91, 77, 65]; + X2 := [448, 424, 405, 390, 376, 364, 353, 344]; + Y2 := [222, 187, 160, 138, 118, 101, 86, 73]; + + for i:=0 to 7 do + begin + Box[i] := IntToBox(X1[i], Y1[i], X2[i], Y2[i]); + CountedColors := CountColorTolerance(2373117, Box[i].X1, Box[i].Y1, Box[i].X2, Box[i].Y2, 5); + if CountedColors > Highest then + begin + Highest := CountedColors; + Result := (90 + i); + AddToSRLLog('The hook is in box '+ToStr(Result)+''); + end; + end; +end; + +{******************************************************************************* +function MoveHook(Box: Integer): Boolean; +by: J J +Description: Moves the hook to a box number you input. The box number resembles + a position this map: http://img841.imageshack.us/img841/4879/tilesystem.png +*******************************************************************************} +function MoveHook(Box: Integer): Boolean; +var + H, V, X, Y, BoxRow, HookBoxRow, Horizontal, Vertical, BoxSpot, HookBoxSpot: Integer; + +begin + if Box = -1 then + begin + Wait(2000 + Random(2000)); + AddToSRLLog('Not moving the hook because the box is false!'); + Exit; + end; + + if not(Box = HookBox) then + begin + // Horizontal movement + BoxRow := (Box div 10); + HookBoxRow := (HookBox div 10); + AddToSRLLog('BoxRow : '+IntToStr(BoxRow)+', HookBoxRow: '+IntToStr(HookBoxRow)+''); + + if not(BoxRow = HookBoxRow) then + begin + if (BoxRow > HookBoxRow) then + begin + Horizontal := (BoxRow - HookBoxRow); + AddToSRLLog('Move Right '+IntToStr(Horizontal)+' times'); + repeat + Inc(H); + if (H > 1) then + begin + GetMousePos(X, Y); + MMouse(X, Y, RandomRange(-2, 2), RandomRange(-2, 2)); + ClickMouse2(1); + end else + begin + MouseBox(700, 325, 720, 340, 1); + end; + Wait(75 + Random(25)); + until(H >= Horizontal); + end else + begin + Horizontal := (HookBoxRow - BoxRow); + AddToSRLLog('Move left '+IntToStr(Horizontal)+' times'); + repeat + Inc(H); + if (H > 1) then + begin + GetMousePos(X, Y); + MMouse(X, Y, RandomRange(-2, 2), RandomRange(-2, 2)); + ClickMouse2(1); + end else + begin + MouseBox(570, 325, 590, 340, 1); + end; + Wait(75 + Random(25)); + until(H >= Horizontal); + end; + end else + begin + AddToSRLLog('We are at the correct row already!'); + end; + + // Vertical movement + HookBoxSpot := (HookBox - (HookBoxRow * 10)); + BoxSpot := (Box - (BoxRow * 10)); + AddToSRLLog('HookBoxspot: '+IntToStr(HookBoxSpot)+''); + AddToSRLLog('Boxspot: '+IntToStr(BoxSpot)+''); + + if not(BoxSpot = HookBoxSpot) then + begin + if (BoxSpot > HookBoxSpot) then + begin + Vertical := (BoxSpot - HookBoxSpot); + AddToSRLLog('Move up '+IntToStr(Vertical)+' times'); + repeat + Inc(V); + if (V > 1) then + begin + GetMousePos(X, Y); + MMouse(X, Y, RandomRange(-2, 2), RandomRange(-2, 2)); + ClickMouse2(1); + end else + begin + MouseBox(635, 265, 650, 280, 1); + end; + Wait(75 + Random(25)); + until(V >= Vertical); + end else + begin + Vertical := (HookBoxSpot - BoxSpot); + AddToSRLLog('Move down '+IntToStr(Vertical)+' times'); + repeat + Inc(V); + if (V > 1) then + begin + GetMousePos(X, Y); + MMouse(X, Y, RandomRange(-2, 2), RandomRange(-2, 2)); + ClickMouse2(1); + end else + begin + MouseBox(635, 385, 650, 405, 1); + end; + Wait(75 + Random(25)); + until(V >= Vertical); + end; + end else + begin + AddToSRLLog('We are at the correct spot already!'); + end; + end else + begin + AddToSRLLog('We are at the correct spot and row!'); + Result := True; + end; + Wait(600 + Random(200)); +end; + +{******************************************************************************* +function MollyLocation: TPoint; +by: J J +Description: Returns a TPoint of the location of the correct Molly's boots + This TPoint can be used in the Mollybox function to convert it + to a box number +*******************************************************************************} +function MollyLocation: TPoint; +var + X, Y, Q, i: Integer; + P, T: TPoint; + Hair, Boots: TPointArray; + HairSplit, BootsSplit: T2DPointArray; + SearchBox: TBox; + Col, Tol: Array of Integer; + Hue, Sat: Array of Extended; + +begin + case MollyHair of + 'LightBrown': Q := 0; + 'DarkBrown': Q := 1; + 'LightBlond': Q := 2; + 'DarkBlond': Q := 3; + 'Red': Q := 4; + end; + + Col := [3161416, 1517614, 3658722, 3573399, 2710186]; + Tol := [14, 10, 10, 20, 17]; + Hue := [0.13, 0.21, 0.15, 0.08, 0.11]; + Sat := [0.08, 0.64, 2.31, 0.49, 0.59]; + + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(Hue[Q], Sat[Q]); + if FindColorsSpiralTolerance(X, Y, Hair, Col[Q], MSX1, MSY1, MSX2, 200, Tol[Q]) then + begin + if (Length(Hair) > 10)then + begin + SplitTPAExWrap(Hair, 1, 1, HairSplit); + SortATPASize(HairSplit, True); + for i:=0 to high(HairSplit) do + begin + if (Length(HairSplit[i]) > 10) and (Length(HairSplit[i]) < 100) then + begin + P := MiddleTPA(HairSplit[i]); + SearchBox := IntToBox(P.X-6, P.Y+2, P.X+6, P.Y+8); + SetColorSpeed2Modifiers(0.09, 0.85); + if FindColorSpiralTolerance(X, Y, 4555446, SearchBox.X1, SearchBox.Y1, SearchBox.X2, SearchBox.Y2, 21) then + begin + AddToSRLLog('Potential Molly has been found at: '+IntToStr(P.X)+', '+IntToStr(P.Y)+''); + SetColorSpeed2Modifiers(0.40, 0.68); + if FindColorsSpiralTolerance(X, Y, Boots, 2176834, SearchBox.X1-5, SearchBox.Y1+40, SearchBox.X2+5, SearchBox.Y2+70, 11) then + begin + SplitTPAExWrap(Boots, 2, 2, BootsSplit); + SortATPASize(BootsSplit, True); + T := Point(MiddleTPA(Boots).X, GetTPABounds(BootsSplit[0]).Y2); + AddToSRLLog('Detected boots, correct Molly has been found at '+IntToStr(T.X)+', '+IntToStr(T.Y)+''); + Result := T; + Break; + end; + end; + end; + end; + end; + end; +end; + +{******************************************************************************* +function MollyBox(MollyTPoint: TPoint): Integer; +by: J J +Description: Returns an integer which resembles the position of Molly on this + grid: http://img841.imageshack.us/img841/4879/tilesystem.png + It uses the FindHair function to get the position of Molly. +*******************************************************************************} +function MollyBox(MollyPosition: TPoint): Integer; +var + X, i, k: Integer; + YI, YII, Col, Tol, XSplit, YSplit, X1, Y1, X2, Y2, Multiplier, Height: Array of Integer; + Hue, Sat: Array of Extended; + Row: Array[0..10] of Array[0..9] of TBox; + +begin + YI := [47, 45, 46, 51, 54]; + YII := [237, 241, 250, 241, 250]; + Hue := [0.12, 0.58]; + Sat := [2.77, 0.99]; + Col := [2240266, 3702093]; + Tol := [5, 10]; + XSplit := [6, 8]; + YSplit := [6, 8]; + + case HookPosition of + 'Normal': begin + X := 0; + X1 := [61, 78, 92, 104, 114, 124, 132, 139, 146, 151]; + Y1 := [210, 178, 152, 130, 112, 95, 81, 68, 57, 47]; + X2 := [110, 126, 137, 146, 153, 160, 166, 171, 177, 180]; + Y2 := [234, 199, 171, 145, 124, 106, 90, 77, 64, 53]; + Multiplier := [58, 52, 48, 45, 41, 39, 36, 34, 32, 31]; + for i:=0 to 10 do + begin + for k:=0 to 9 do + begin + case i of + 0: Row[i][k] := IntToBox(X1[k] + (-2 * Multiplier[k]), Y1[k], X2[k] + (-2 * Multiplier[k]), Y2[k]); + 1: Row[i][k] := IntToBox(X1[k] + (-1 * Multiplier[k]), Y1[k], X2[k] + (-1 * Multiplier[k]), Y2[k]); + 2..10: Row[i][k] := IntToBox(X1[k] + ((i-2) * Multiplier[k]), Y1[k], X2[k] + ((i-2) * Multiplier[k]), Y2[k]); + end; + if PointInBox(MollyPosition, IntToBox(Row[i][k].X1, Row[i][k].Y1, Row[i][k].X2, Row[i][k].Y2)) then + begin + Result := ((10 * i) + k); + PreviousBox := Result; + AddToSRLLog('Molly is in box: '+IntToStr(Result)+''); + Exit; + end; + end; + end; + end; + 'OneLeft': begin + X := 1; + X1 := [69, 89, 105, 118, 140, 151, 162, 172, 180, 186]; + Y1 := [194, 167, 143, 123, 104, 90, 77, 66, 54, 43]; + X2 := [118, 133, 144, 156, 169, 180, 188, 197, 204, 211]; + Y2 := [224, 187, 160, 140, 117, 101, 86, 75, 64, 52]; + Multiplier := [62, 56, 52, 48, 38, 36, 34, 33, 32, 31]; + Height := [4, 3, 3, 3, 2, 2, 2, 1, 1, 1]; + for i:=0 to 10 do + begin + for k:=0 to 9 do + begin + case i of + 0: Row[i][k] := IntToBox(X1[k] + (-1 * Multiplier[k]), Y1[k] + (Height[k]*i), X2[k] + (-1 * Multiplier[k]), Y2[k] + (Height[k]*i)); + 1: Row[i][k] := IntToBox(X1[k] + (0 * Multiplier[k]), Y1[k] + (Height[k]*i), X2[k] + (0 * Multiplier[k]), Y2[k] + (Height[k]*i)); + 2..10: Row[i][k] := IntToBox(X1[k] + ((i-1) * Multiplier[k]), Y1[k] + (Height[k]*i), X2[k] + ((i-1) * Multiplier[k]), Y2[k] + (Height[k]*i)); + end; + if PointInBox(MollyPosition, IntToBox(Row[i][k].X1, Row[i][k].Y1, Row[i][k].X2, Row[i][k].Y2)) then + begin + Result := ((10 * i) + k); + PreviousBox := Result; + AddToSRLLog('Molly is in box: '+IntToStr(Result)+''); + Exit; + end; + end; + end; + end; + 'TwoLeft': begin + X := 2; + X1 := [66, 96, 116, 135, 152, 170, 183, 195, 206, 215]; + Y1 := [184, 158, 135, 118, 101, 90, 77, 66, 55, 46]; + X2 := [122, 146, 162, 178, 192, 205, 217, 225, 235, 245]; + Y2 := [210, 181, 153, 135, 116, 102, 87, 75, 63, 53]; + Multiplier := [62, 56, 52, 48, 44, 41, 38, 35, 33, 31]; + Height := [8, 7, 7, 6, 6, 5, 5, 5, 4, 3]; + for i:=0 to 10 do + begin + for k:=0 to 9 do + begin + Row[i][k] := IntToBox(X1[k] + (i * Multiplier[k]), Y1[k] + (Height[k]*i), X2[k] + (i * Multiplier[k]), Y2[k] + (Height[k]*i)); + if PointInBox(MollyPosition, IntToBox(Row[i][k].X1, Row[i][k].Y1, Row[i][k].X2, Row[i][k].Y2)) then + begin + Result := ((10 * i) + k); + PreviousBox := Result; + AddToSRLLog('Molly is in box: '+IntToStr(Result)+''); + Exit; + end; + end; + end; + end; + 'OneRight': begin + X := 3; + X1 := [420, 386, 371, 360, 349, 338, 329, 321, 318, 310]; + Y1 := [196, 167, 144, 123, 106, 89, 78, 64, 52, 40]; + X2 := [470, 431, 412, 396, 378, 366, 355, 345, 339, 331]; + Y2 := [222, 187, 160, 138, 118, 102, 88, 75, 60, 49]; + Multiplier := [62, 56, 52, 48, 44, 41, 38, 35, 34, 32]; + Height := [4, 4, 3, 3, 3, 3, 2, 2, 2, 2]; + for i:=0 to 10 do + begin + for k:=0 to 9 do + begin + case i of + 0: Row[i][k] := IntToBox(X1[k] + (1 * Multiplier[k]), Y1[k] + (Height[k]*i), X2[k] + (1 * Multiplier[k]), Y2[k] + (Height[k]*i)); + 1: Row[i][k] := IntToBox(X1[k] + (0 * Multiplier[k]), Y1[k] + (Height[k]*i), X2[k] + (0 * Multiplier[k]), Y2[k] + (Height[k]*i)); + 2..10: Row[i][k] := IntToBox(X1[k] + ((-i+1) * Multiplier[k]), Y1[k] + (Height[k]*i), X2[k] + ((-i+1) * Multiplier[k]), Y2[k] + (Height[k]*i)); + end; + if PointInBox(MollyPosition, IntToBox(Row[i][k].X1, Row[i][k].Y1, Row[i][k].X2, Row[i][k].Y2)) then + begin + Result := 100 - ((10 * i) - k); + PreviousBox := Result; + AddToSRLLog('Molly is in box: '+IntToStr(Result)+''); + Exit; + end; + end; + end; + end; + 'TwoRight': begin + X := 4; + X1 := [395, 373, 358, 341, 323, 311, 299, 290, 284, 277]; + Y1 := [182, 158, 137, 119, 103, 89, 79, 66, 52, 41]; + X2 := [447, 415, 394, 373, 359, 342, 331, 321, 311, 301]; + Y2 := [210, 177, 153, 132, 115, 99, 86, 74, 63, 54]; + Multiplier := [54, 45, 36, 34, 40, 38, 36, 33, 33, 33]; + Height := [8, 6, 4, 4, 4, 4, 4, 4, 4, 3]; + for i:=0 to 10 do + begin + for k:=0 to 9 do + begin + Row[i][k] := IntToBox(X1[k] + (-i * Multiplier[k]), Y1[k] + (Height[k]*i), X2[k] + (-i * Multiplier[k]), Y2[k] + (Height[k]*i)); + if PointInBox(MollyPosition, IntToBox(Row[i][k].X1, Row[i][k].Y1, Row[i][k].X2, Row[i][k].Y2)) then + begin + Result := 100 - ((10 * i) - k); + PreviousBox := Result; + AddToSRLLog('Molly is in box: '+IntToStr(Result)+''); + Exit; + end; + end; + end; + end; + end; + // It only reaches this far if Molly isn't in a box.. If the box is -1 then it won't move the hook! + AddToSRLLog('Not able to detect Molly''s position, waiting a while..'); + Result := -1; +end; + +{******************************************************************************* +function CatchedMolly: Boolean; +by: J J +Description: Checks if the correct Molly has been catched +*******************************************************************************} +function CatchedMolly: Boolean; +var + PossibleTexts: Array of String; + i, j: Integer; + +begin + if FindChatBoxText('innoc', 8, clBlack) then + begin + Wait(12000 + Random(6000)); + Inc(FalseMolly); + Result := False; + end; + + PossibleTexts := ['ongratulations', 'ongrat', 'tions', 'evil', 'twin']; + for i:=0 to high(PossibleTexts) do + begin + for j:=1 to 8 do + begin + if FindChatBoxText(PossibleTexts[i], j, clBlack) then + begin + CorrectMolly := True; + Result := True; + Break; + end; + end; + end; + + ClickContinue(True, True); +end; + +{******************************************************************************* +function Molly_Solve(): Boolean; +by: J J +Description: Handles the Molly random event +*******************************************************************************} +(** + * Author: + * Description: Solves the random. + *) +function Molly_Solve(): Boolean; +begin + ClickNorth(SRL_Angle_High); + MarkTime(MaxMollyTime); // Max 10 mins + MarkTime(MollyTime); + + repeat + // Gets from the starting room to the control panel + OpenMollyDoor('begin'); + Wait(4000 + Random(1500)); + GrabMollyHairColor; + MollyTalk; + Wait(3000 + Random(1000)); + UseControls; + Wait(5000 + Random(2000)); + + // Handles the grabbing of Molly + repeat + repeat + MouseSpeed := 30; + case HookPosition of + 'Normal': Hookbox := NormalHook; + 'TwoLeft': Hookbox := TwoLeftHook; + 'OneLeft': Hookbox := OneLeftHook; + 'TwoRight': Hookbox := TwoRightHook; + 'OneRight': Hookbox := OneRightHook; + end; + until(MoveHook(MollyBox(MollyLocation))); + MouseSpeed := 100; + Mousebox(694, 420, 707, 434, 1); + Wait(3000 + Random(1000)); + until(CatchedMolly); + Wait(16000 + Random(4000)); + MouseSpeed := 15; + + // Handles the talking to Molly to finish + MollyTalk; + OpenMollyDoor('end'); + Wait(6000 + Random(2000)); + TalkToMolly; + Wait(3000 + Random(1000)); + MollyTalk; + + AddToSRLLog('Molly completed in: '+MsToTime(TimeFromMark(MollyTime), Time_Formal)+''); + AddToSRLLog('Molly had the following hair color: '+MollyHair+''); + AddToSRLLog('Innocent civilians caught: '+IntToStr(FalseMolly)+''); + + if CorrectMolly then + Result := True; + until (Result) or (TimeFromMark(MaxMollyTime) > 600000); + if (TimeFromMark(MaxMollyTime) < 600000) then + begin + Result := True; + end else + begin + AddToSRLLog('Molly solve took longer than 10 minutes, logging out'); + LogOut; + end; +end; diff --git a/SRL/core/antirandoms/mordaut.simba b/SRL/core/antirandoms/mordaut.simba new file mode 100644 index 0000000..b3d959d --- /dev/null +++ b/SRL/core/antirandoms/mordaut.simba @@ -0,0 +1,1526 @@ +(* +Mordaut +======= + +Stores all the routines to solve the Mordaut random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +This solver uses a "score" system to determine which item is the odd one out. +A rotating object is determined using the TRotateObject type and +DebugRotateObject method both found in common.simba. Each object is declared +in MD_GetObject and is compared to a scanned object in each of the slots +depending on the puzzle that needs to be solved. + +The puzzles are stored in separate arrays (big and small). The big puzzles are +the ones where you have to match 3 items to the wording on the right. The small +puzzles are the ones you have to click the item that comes next in the sequence. + +*) + +type + TMDBigPuzzle = record + name: string; + idText: TStringArray; + objs: TRotateObjectArray; + end; + TMDBigPuzzleArray = array of TMDBigPuzzle; + +const + MD_NPC_MORDAUT = 'D!!Do!g5qt'; + + // new data for MD_GetObject will need to be gathered if these are to change + MD_ACCURACY = 50; // gets the average of MD_ACCURACY times to ID objects + MD_OBJ_SIZE = 25; // split TPA into this size of box + MD_MIN_SCORE = 25; // minimum score for an object to be ID'd + +const + MD_OBJECT_COUNT = 62; + MD_OBJ_SCIMITAR = 0; + MD_OBJ_LONGSWORD = 1; + MD_OBJ_BATTLEAXE = 2; + MD_OBJ_MACE = 3; + MD_OBJ_TEA = 4; + MD_OBJ_BEER = 5; + MD_OBJ_MARTINI = 6; + MD_OBJ_VODKA = 7; + MD_OBJ_PICKAXE = 8; + MD_OBJ_ORE = 9; + MD_OBJ_HAMMER = 10; + MD_OBJ_BAR = 11; + MD_OBJ_PLATEBODY = 12; + MD_OBJ_SHORTBOW = 13; + MD_OBJ_ARROWS = 14; + MD_OBJ_CROSSBOW = 15; + MD_OBJ_LONGBOW = 16; + MD_OBJ_FROG = 17; + MD_OBJ_THIEF = 18; + MD_OBJ_MIME = 19; + MD_OBJ_NECKLACE = 20; + MD_OBJ_TIARA = 21; + MD_OBJ_SYMBOL = 22; + MD_OBJ_RING = 23; + MD_OBJ_LONG = 24; + MD_OBJ_FULLHELM = 25; + MD_OBJ_KITE = 26; + MD_OBJ_PLATE = 27; + MD_OBJ_CAVALIER = 28; + MD_OBJ_PIRATE = 29; + MD_OBJ_JESTER = 30; + MD_OBJ_LOGS = 31; + MD_OBJ_TINDERBOX = 32; + MD_OBJ_LAMP = 33; + MD_OBJ_CANDLE = 34; + MD_OBJ_RAKE = 35; + MD_OBJ_WATERCAN = 36; + MD_OBJ_SPADE = 37; + MD_OBJ_TROWEL = 38; + MD_OBJ_SQUARE = 39; + MD_OBJ_WOODEN = 40; + MD_OBJ_KITESHIELD = 41; + MD_OBJ_SHRIMP = 42; + MD_OBJ_SARDINE = 43; + MD_OBJ_MACKEREL = 44; + MD_OBJ_SWORDFISH = 45; + MD_OBJ_TROUT = 46; + MD_OBJ_BOOTS = 47; + MD_OBJ_BOOTS_2 = 48; + MD_OBJ_HOOK = 49; + MD_OBJ_EYEPATCH = 50; + MD_OBJ_RUNE = 51; + MD_OBJ_STAFF = 52; + MD_OBJ_HARPOON = 53; + MD_OBJ_CHEFHAT = 54; + MD_OBJ_APRON = 55; + MD_OBJ_BREAD = 56; + MD_OBJ_CAKE = 57; + MD_OBJ_BANANA = 58; + MD_OBJ_STRAWBERRY = 59; + MD_OBJ_PINEAPPLE = 60; + MD_OBJ_GRAPES = 61; + +const + MD_PUZZLE_BIG_COUNT = 10; + MD_PUZZLE_BIG_DRINK = 0; + MD_PUZZLE_BIG_PIRATE = 1; + MD_PUZZLE_BIG_JEWEL = 2; + MD_PUZZLE_BIG_RANGE = 3; + MD_PUZZLE_BIG_FIRE = 4; + MD_PUZZLE_BIG_MELEE = 5; + MD_PUZZLE_BIG_MAGIC = 6; + MD_PUZZLE_BIG_DISGUISE = 7; + MD_PUZZLE_BIG_HAT = 8; + MD_PUZZLE_BIG_FISH = 9; + +var + // stores the background colors and tolerances of the small and big puzzles + MD_ExColSmall, MD_ExColBig, MD_ExTolSmall, MD_ExTolBig: TIntegerArray; + +(** + * Author: Coh3n + * Description: Declares global variables. Used so it can be easily updated. + *) +procedure MD_DeclareGlobals(); +begin + // background colors of the small puzzle + MD_ExColSmall := [4674119, 5265999]; + MD_ExTolSmall := [17, 17]; + + // background colors of the big puzzle + MD_ExColBig := [13423575, 12897741]; + MD_ExTolBig := [25, 25]; +end; + +(** + * Author: DemiseScythe & Coh3n + * Description: Returns true if player is in the random. + *) +function MD_Detect(): boolean; +begin + result := (getNPCChatName() = MD_NPC_MORDAUT) and (not tabExists(TAB_MAGIC)); +end; + +(** + * Author: Coh3n + * Description: Stores all the Mordaut object properties. Data gathered using + * MD_DebugSmall/BigPuzzle. + *) +function MD_GetObject(obj: integer): TRotateObject; +begin + case obj of + MD_OBJ_SCIMITAR: + with result do + begin + name := 'Scimitar'; + use := 'Weapon'; + count := 280; + width := 41; + height := 25; + totalCount := 951; + coverPercent := 29.0; + end; + + MD_OBJ_LONGSWORD: + with result do + begin + name := 'Longsword'; + use := 'Weapon'; + count := 107; + width := 34; + height := 23; + totalCount := 670; + coverPercent := 16.0; + end; + + MD_OBJ_BATTLEAXE: + with result do + begin + name := 'Battleaxe'; + use := 'Weapon'; + count := 218; + width := 31; + height := 19; + totalCount := 591; + coverPercent := 37.0; + end; + + MD_OBJ_MACE: + with result do + begin + name := 'Mace'; + use := 'Weapon'; + count := 205; + width := 31; + height := 23; + totalCount := 700; + coverPercent := 28.0; + end; + + MD_OBJ_TEA: + with result do + begin + name := 'Tea'; + use := 'Drink'; + count := 885; + width := 33; + height := 33; + totalCount := 1134; + coverPercent := 75.0; + end; + + MD_OBJ_BEER: + with result do + begin + name := 'Beer'; + use := 'Drink'; + count := 588; + width := 26; + height := 28; + totalCount := 751; + coverPercent := 75.0; + end; + + MD_OBJ_MARTINI: + with result do + begin + name := 'Martini'; + use := 'Drink'; + count := 435; + width := 20; + height := 32; + totalCount := 680; + coverPercent := 63.0; + end; + + MD_OBJ_VODKA: + with result do + begin + name := 'Vodka'; + use := 'Drink'; + count := 350; + width := 14; + height := 28; + totalCount := 424; + coverPercent := 83.0; + end; + + MD_OBJ_PICKAXE: + with result do + begin + name := 'Pickaxe'; + use := 'Smithing'; + count := 230; + width := 45; + height := 30; + totalCount := 1380; + coverPercent := 16.0; + end; + + MD_OBJ_ORE: + with result do + begin + name := 'Ore'; + use := 'Smithing'; + count := 591; + width := 38; + height := 26; + totalCount := 1053; + coverPercent := 56.0; + end; + + MD_OBJ_HAMMER: + with result do + begin + name := 'Hammer'; + use := 'Smithing'; + count := 269; + width := 30; + height := 21; + totalCount := 600; + coverPercent := 44.0; + end; + + MD_OBJ_BAR: + with result do + begin + name := 'Bar'; + use := 'Smithing'; + count := 627; + width := 33; + height := 25; + totalCount := 867; + coverPercent := 72.0; + end; + + MD_OBJ_PLATEBODY: + with result do + begin + name := 'Platebody'; + use := 'Smithing'; + count := 750; + width := 36; + height := 28; + totalCount := 1039; + coverPercent := 70.0; + end; + + MD_OBJ_SHORTBOW: + with result do + begin + name := 'Shortbow'; + use := 'Range'; + count := 288; + width := 40; + height := 25; + totalCount := 870; + coverPercent := 33.0; + end; + + MD_OBJ_ARROWS: + with result do + begin + name := 'Arrows'; + use := 'Range'; + count := 232; + width := 42; + height := 27; + totalCount := 975; + coverPercent := 24.0; + end; + + MD_OBJ_CROSSBOW: + with result do + begin + name := 'Crossbow'; + use := 'Range'; + count := 247; + width := 34; + height := 24; + totalCount := 847; + coverPercent := 29.0; + end; + + MD_OBJ_LONGBOW: + with result do + begin + name := 'Longbow'; + use := 'Range'; + count := 161; + width := 34; + height := 21; + totalCount := 664; + coverPercent := 24.0; + end; + + MD_OBJ_FROG: + with result do + begin + name := 'Frog Mask'; + use := 'Disguise'; + count := 850; + width := 34; + height := 30; + totalCount := 1055; + coverPercent := 81.0; + end; + + MD_OBJ_MIME: + with result do + begin + name := 'Mime Mask'; + use := 'Disguise'; + count := 728; + width := 33; + height := 27; + totalCount := 919; + coverPercent := 79.0; + end; + + MD_OBJ_NECKLACE: + with result do + begin + name := 'Necklace'; + use := 'Jewelery'; + count := 219; + width := 29; + height := 19; + totalCount := 567; + coverPercent := 38.0; + end; + + MD_OBJ_TIARA: + with result do + begin + name := 'Tiara'; + use := 'Jewelery'; + count := 202; + width := 32; + height := 23; + totalCount := 758; + coverPercent := 26.0; + end; + + MD_OBJ_SYMBOL: + with result do + begin + name := 'Holy Symbol'; + use := 'Jewelery'; + count := 306; + width := 40; + height := 25; + totalCount := 970; + coverPercent := 32.0; + end; + + MD_OBJ_RING: + with result do + begin + name := 'Ring'; + use := 'Jewelery'; + count := 245; + width := 24; + height := 18; + totalCount := 452; + coverPercent := 55.0; + end; + + MD_OBJ_LONG: // same item is used for more than one puzzle (different use) + begin + result := MD_GetObject(MD_OBJ_LONGSWORD); + result.name := 'Long'; + result.use := 'Combat'; + end; + + MD_OBJ_FULLHELM: + with result do + begin + name := 'Full Helm'; + use := 'Combat'; + count := 468; + width := 27; + height := 28; + totalCount := 760; + coverPercent := 61.0; + end; + + MD_OBJ_KITE: + with result do + begin + name := 'Kite'; + use := 'Combat'; + count := 640; + width := 37; + height := 24; + totalCount := 953; + coverPercent := 68.0; + end; + + MD_OBJ_PLATE: + begin + result := MD_GetObject(MD_OBJ_PLATEBODY); + result.name := 'Platebody'; + result.use := 'Combat'; + end; + + MD_OBJ_THIEF: + with result do + begin + name := 'Thief Mask'; + use := 'Hat'; + count := 560; + width := 34; + height := 28; + totalCount := 944; + coverPercent := 59.0; + end; + + MD_OBJ_JESTER: + with result do + begin + name := 'Jester Hat'; + use := 'Hat'; + count := 416; + width := 31; + height := 24; + totalCount := 747; + coverPercent := 56.0; + end; + + MD_OBJ_PIRATE: + with result do + begin + name := 'Pirate Hat'; + use := 'Hat'; + count := 696; + width := 35; + height := 27; + totalCount := 970; + coverPercent := 72.0; + end; + + MD_OBJ_CAVALIER: + with result do + begin + name := 'Cavalier Hat'; + use := 'Hat'; + count := 584; + width := 35; + height := 23; + totalCount := 817; + coverPercent := 71.0; + end; + + MD_OBJ_LOGS: + with result do + begin + name := 'Logs'; + use := 'Fire'; + count := 820; + width := 37; + height := 32; + totalCount := 1242; + coverPercent := 65.0; + end; + + MD_OBJ_TINDERBOX: + with result do + begin + name := 'Tinderbox'; + use := 'Fire'; + count := 1485; + width := 42; + height := 44; + totalCount := 1878; + coverPercent := 79.0; + end; + + MD_OBJ_LAMP: + with result do + begin + name := 'Lamp'; + use := 'Fire'; + count := 425; + width := 23; + height := 27; + totalCount := 640; + coverPercent := 66.0; + end; + + MD_OBJ_CANDLE: + with result do + begin + name := 'Candle'; + use := 'Fire'; + count := 0; + width := 0; + height := 0; + totalCount := 0; + coverPercent := 0.0; + end; + + MD_OBJ_RAKE: + with result do + begin + name := 'Rake'; + use := 'Farming'; + count := 222; + width := 50; + height := 32; + totalCount := 1459; + coverPercent := 15.0; + end; + + MD_OBJ_WATERCAN: + with result do + begin + name := 'Watering Can'; + use := 'Farming'; + count := 625; + width := 30; + height := 35; + totalCount := 1072; + coverPercent := 58.0; + end; + + MD_OBJ_SPADE: + with result do + begin + name := 'Spade'; + use := 'Farming'; + count := 338; + width := 44; + height := 30; + totalCount := 1203; + coverPercent := 28.0; + end; + + MD_OBJ_TROWEL: + with result do + begin + name := 'Trowel'; + use := 'Farming'; + count := 275; + width := 31; + height := 21; + totalCount := 650; + coverPercent := 44.0; + end; + + MD_OBJ_SQUARE: + with result do + begin + name := 'Square Shield'; + use := 'Shield'; + count := 600; + width := 37; + height := 25; + totalCount := 900; + coverPercent := 65.0; + end; + + MD_OBJ_WOODEN: + with result do + begin + name := 'Wooden Shield'; + use := 'Shield'; + count := 498; + width := 32; + height := 23; + totalCount := 750; + coverPercent := 66.0; + end; + + MD_OBJ_KITESHIELD: + begin + result := MD_GetObject(MD_OBJ_KITE); + result.name := 'Kiteshield'; + result.use := 'Shield'; + end; + + MD_OBJ_SHRIMP: + with result do + begin + name := 'Shrimp'; + use := 'Fish'; + count := 262; + width := 37; + height := 24; + totalCount := 914; + coverPercent := 29.0; + end; + + MD_OBJ_SARDINE: + with result do + begin + name := 'Sardine'; + use := 'Fish'; + count := 121; + width := 22; + height := 15; + totalCount := 320; + coverPercent := 38.0; + end; + + MD_OBJ_MACKEREL: + with result do + begin + name := 'Mackerel'; + use := 'Fish'; + count := 238; + width := 31; + height := 18; + totalCount := 599; + coverPercent := 40.0; + end; + + MD_OBJ_SWORDFISH: + with result do + begin + name := 'Swordfish'; + use := 'Fish'; + count := 218; + width := 37; + height := 23; + totalCount := 836; + coverPercent := 26.0; + end; + + MD_OBJ_BOOTS: + with result do + begin + name := 'Boots'; + use := 'Boots'; + count := 587; + width := 30; + height := 28; + totalCount := 900; + coverPercent := 67.0; + end; + + MD_OBJ_BOOTS_2: + with result do + begin + name := 'Boots 2'; + use := 'Boots'; + count := 520; + width := 31; + height := 29; + totalCount := 930; + coverPercent := 55.0; + end; + + MD_OBJ_EYEPATCH: + with result do + begin + name := 'Eye Patch'; + use := 'Pirate'; + count := 255; + width := 32; + height := 20; + totalCount := 630; + coverPercent := 40.0; + end; + + MD_OBJ_HOOK: + with result do + begin + name := 'Pirate Hook'; + use := 'Pirate'; + count := 224; + width := 32; + height := 23; + totalCount := 706; + coverPercent := 32.0; + end; + + MD_OBJ_RUNE: + with result do + begin + name := 'Rune'; + use := 'Magic'; + count := 800; + width := 35; + height := 29; + totalCount := 1040; + coverPercent := 75.0; + end; + + MD_OBJ_STAFF: + with result do + begin + name := 'Staff'; + use := 'Magic'; + count := 96; + width := 39; + height := 26; + totalCount := 878; + coverPercent := 11.0; + end; + + MD_OBJ_HARPOON: + with result do + begin + name := 'Harpoon'; + use := 'Fish'; + count := 194; + width := 35; + height := 23; + totalCount := 738; + coverPercent := 24.0; + end; + + MD_OBJ_TROUT: + with result do + begin + name := 'Trout'; + use := 'Fish'; + count := 320; + width := 32; + height := 23; + totalCount := 700; + coverPercent := 45.0; + end; + + MD_OBJ_CHEFHAT: + with result do + begin + name := 'Chef''s Hat'; + use := 'Cook'; + count := 645; + width := 36; + height := 25; + totalCount := 942; + coverPercent := 68.0; + end; + + MD_OBJ_APRON: + with result do + begin + name := 'Apron'; + use := 'Cook'; + count := 340; + width := 31; + height := 20; + totalCount := 637; + coverPercent := 53.0; + end; + + MD_OBJ_BREAD: + with result do + begin + name := 'Bread'; + use := 'Cook'; + count := 535; + width := 30; + height := 22; + totalCount := 676; + coverPercent := 78.0; + end; + + MD_OBJ_CAKE: + with result do + begin + name := 'Cake'; + use := 'Cook'; + count := 975; + width := 35; + height := 31; + totalCount := 1110; + coverPercent := 88.0; + end; + + MD_OBJ_BANANA: + with result do + begin + name := 'Banana'; + use := 'Fruit'; + count := 399; + width := 34; + height := 24; + totalCount := 799; + coverPercent := 50.0; + end; + + MD_OBJ_STRAWBERRY: + with result do + begin + name := 'Strawberry'; + use := 'Fruit'; + count := 379; + width := 20; + height := 24; + totalCount := 510; + coverPercent := 74.0; + end; + + MD_OBJ_PINEAPPLE: + with result do + begin + name := 'Pineapple'; + use := 'Fruit'; + count := 600; + width := 33; + height := 33; + totalCount := 1098; + coverPercent := 55.0; + end; + + MD_OBJ_GRAPES: + with result do + begin + name := 'Grapes'; + use := 'Shield'; + count := 190; + width := 23; + height := 15; + totalCount := 351; + coverPercent := 54.0; + end; + + else + addToSRLLog('MD_GetObject: Invalid object '+toStr(obj)); + end; +end; + +(** + * Author: Coh3n + * Description: results the DTMs to detect which "big" puzzle to solve. + *) +function MD_GetBigPuzzles(): TMDBigPuzzleArray; +begin + setLength(result, MD_PUZZLE_BIG_COUNT); + + with result[MD_PUZZLE_BIG_DRINK] do + begin + name := 'Big Puzzle: Drinks'; + idText := ['thirst', 'dehydrate']; + objs := [MD_GetObject(MD_OBJ_TEA), MD_GetObject(MD_OBJ_BEER), + MD_GetObject(MD_OBJ_MARTINI)]; + end; + + with result[MD_PUZZLE_BIG_MAGIC] do + begin + name := 'Big Puzzle: Magic'; + idText := ['stic', 'wizard']; + objs := [MD_GetObject(MD_OBJ_STAFF), MD_GetObject(MD_OBJ_RUNE), + MD_GetObject(MD_OBJ_RUNE)]; + end; + + with result[MD_PUZZLE_BIG_DISGUISE] do + begin + name := 'Big Puzzle: Disguise'; + idText := ['face', 'mask', 'disg', 'hidden']; + objs := [MD_GetObject(MD_OBJ_FROG), MD_GetObject(MD_OBJ_THIEF), + MD_GetObject(MD_OBJ_MIME)]; + end; + + with result[MD_PUZZLE_BIG_MELEE] do + begin + name := 'Big Puzzle: Melee'; + idText := ['sword', 'weapon', 'melee']; + objs := [MD_GetObject(MD_OBJ_LONGSWORD), MD_GetObject(MD_OBJ_SCIMITAR), + MD_GetObject(MD_OBJ_BATTLEAXE)]; + end; + + with result[MD_PUZZLE_BIG_HAT] do + begin + name := 'Big Puzzle: Hat'; + idText := ['hat', 'cap', 'head', 'tip', 'hink']; + objs := [MD_GetObject(MD_OBJ_CAVALIER), MD_GetObject(MD_OBJ_JESTER), + MD_GetObject(MD_OBJ_PIRATE)]; + end; + + with result[MD_PUZZLE_BIG_FIRE] do + begin + name := 'Big Puzzle: Fire'; + idText := ['arks', 'fire', 'nitin', 'brain', 'star']; + objs := [MD_GetObject(MD_OBJ_LOGS), MD_GetObject(MD_OBJ_TINDERBOX), + MD_GetObject(MD_OBJ_LAMP)]; + end; + + with result[MD_PUZZLE_BIG_PIRATE] do + begin + name := 'Big Puzzle: Pirate'; + idText := ['pirate', 'tis', 'Yarr']; + objs := [MD_GetObject(MD_OBJ_HOOK), MD_GetObject(MD_OBJ_PIRATE), + MD_GetObject(MD_OBJ_EYEPATCH)]; + end; + + with result[MD_PUZZLE_BIG_RANGE] do + begin + name := 'Big Puzzle: Range'; + idText := ['archery', 'arrow']; + objs := [MD_GetObject(MD_OBJ_LONGBOW), MD_GetObject(MD_OBJ_ARROWS), + MD_GetObject(MD_OBJ_CROSSBOW)]; + end; + + with result[MD_PUZZLE_BIG_FISH] do + begin + name := 'Big Puzzle: Fish'; + idText := ['ishy', 'water', 'ish', 'eel like a']; + objs := [MD_GetObject(MD_OBJ_TROUT), MD_GetObject(MD_OBJ_HARPOON), + MD_GetObject(MD_OBJ_TROUT)]; + end; + + with result[MD_PUZZLE_BIG_JEWEL] do + begin + name := 'Big Puzzle: Jewelery'; + idText := ['ineries', 'ecio', 'ewell']; + objs := [MD_GetObject(MD_OBJ_SYMBOL), MD_GetObject(MD_OBJ_RING), + MD_GetObject(MD_OBJ_NECKLACE)]; + end; +end; + +(** + * Author: Coh3n + * Description: Returns all the possible small puzzles to solve. The string + * value MUST be the same as the 'use' field for the corresponding objects. + *) +function MD_GetSmallPuzzles(): TStringArray; +begin + setLength(result, 15); + + result[0] := 'Weapon'; + result[1] := 'Smithing'; + result[2] := 'Range'; + result[3] := 'Jewelery'; + result[4] := 'Combat'; + result[5] := 'Drink'; + result[6] := 'Hat'; + result[7] := 'Farming'; + result[8] := 'Shield'; + result[9] := 'Fish'; + result[10] := 'Boots'; + result[11] := 'Magic'; + result[12] := 'Cook'; + result[13] := 'Fruit'; + result[14] := 'Fire'; +end; + +(** + * Author: Coh3n + * Description: Returns the score of obj1 compared to obj2. The higher the + * score the more likely the objects are the same. + *) +function MD_CompareObjects(obj1, obj2: TRotateObject): integer; +begin + // best score is currently 40 + result := 0; + + if (inRange(obj1.count, obj2.count - 10, obj2.count + 10)) then + result := result + 3; + + if (obj1.width = obj2.width) then + result := result + 12 + else + if (inRange(obj1.width, obj2.width - 2, obj2.width + 2)) then + result := result + 6; + + if (obj1.height = obj2.height) then + result := result + 12 + else + if (inRange(obj1.height, obj2.height - 2, obj2.height + 2)) then + result := result + 6; + + if (inRange(obj1.totalCount, obj2.totalCount - 75, obj2.totalCount + 75)) then + result := result + 5; + + if ((obj1.coverPercent > obj2.coverPercent - 3) and (obj1.coverPercent < obj2.coverPercent + 3)) then + result := result + 8; +end; + +(** + * Author: Coh3n + * Description: Returns the Mordaut object that best (has the highest score) + * matches 'scanObj'. + *) +function MD_IDObject(scanObj: TRotateObject): TRotateObjectArray; +var + i, c, tmpScore: integer; + tmpObj: TRotateObject; +begin + setLength(result, MD_OBJECT_COUNT); + + // loop through all the objects to find which one best matches the scanned object + for i := 0 to (MD_OBJECT_COUNT - 1) do + begin + tmpObj := MD_GetObject(i); + tmpScore := MD_CompareObjects(tmpObj, scanObj); + + //writeln('tmpObj('+tmpObj.name+') vs. scanObj(): score - '+toStr(tmpScore)); + + // set the highest score as result + if (tmpScore > MD_MIN_SCORE) then + begin + //addToSRLLog('MD_IDObject: One match is '+tmpObj.name+' with a score of '+toStr(tmpScore)); + result[c] := tmpObj; + inc(c); + end; + end; + + setLength(result, c); +end; + +(** + * Author: Coh3n + * Description: Returns a TBox of the big puzzle item slot 'Slot'. Top left + * is slot 1, botton right is slot 15. + *) +function MD_BigBox(slot: integer): TBox; +begin + result := gridBox(slot, 5, 3, 60, 80, 67, 91, point(71, 73)); +end; + +(** + * Author: Coh3n + * Description: Returns a TBox of the small puzzle item slot 'Slot'. Top left + * is slot 1, botton right is slot 8. + *) +function MD_SmallBox(slot: integer): TBox; +begin + result := gridBox(slot, 4, 2, 95, 80, 95, 150, point(110, 100)); +end; + +(** + * Author: Nava2 + * Description: Returns true if the big puzzle screen is open. + *) +function MD_BigScreen(): boolean; +var + dtmThumb, x, y: integer; +begin + dtmThumb := DTMFromString('78DA63E4646060E063400187BBD3184480342310FF0702466E208309558D083333030B540D08300A619A83A146002488AA86879911550D1B901025A006E4161E5435E2DC2C286A00ACBB06F0'); + result := findDTM(dtmThumb, x, y, MSX1, MSY1, MSX2, MSY2); + freeDTM(dtmThumb); +end; + +(** + * Author: Nava2 + * Description: Returns true if the small puzzle screen is open. + *) +function MD_SmallScreen(): boolean; +begin + // counts black pixels of the text shadow in the middle of the MS + result := (countColor(clBlack, 165, 142, 357, 183) = 322); +end; + +(** + * Author: Coh3n + * Description: Returns the object scanned in 'slot' for the big puzzle. + *) +function MD_ScanBigObject(slot: integer): TRotateObject; +begin + result := scanRotateObject( + MD_ExColBig, MD_ExTolBig, MD_BigBox(slot), MD_OBJ_SIZE, MD_ACCURACY); +end; + +(** + * Author: Coh3n + * Description: Returns the object scanned in 'slot' for the small puzzle. + *) +function MD_ScanSmallObject(slot: integer): TRotateObject; +begin + result := scanRotateObject( + MD_ExColSmall, MD_ExTolSmall, MD_SmallBox(slot), MD_OBJ_SIZE, MD_ACCURACY); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Returns which small puzzle we have to solve. + *) +function MD_IDSmallPuzzle(puzzles: TStringArray): integer; +var + i, j: integer; + tmpObjs, posObjs: TRotateObjectArray; + commonUse: string; +begin + if (not loggedIn()) or (not MD_SmallScreen()) then + exit; + + addToSRLLog('MD_IDSmallPuzzle: Identifying puzzle'); + result := -1; + + addToSRLLog('MD_IDSmallPuzzle: Scanning objects...'); + + // get the possible objects that could be one the top part of the puzzle + for i := 1 to 3 do // item slots 1-3 + begin + tmpObjs := MD_IDObject(MD_ScanSmallObject(i)); + + for j := 0 to high(tmpObjs) do + begin + setLength(posObjs, length(posObjs) + 1); + posObjs[high(posObjs)] := tmpObjs[j]; + end; + end; + + addToSRLLog('MD_IDSmallPuzzle: Objects scanned'); + + // get's the most common use found in the possible objects + commonUse := getTROAUse(posObjs); + addToSRLLog('MD_IDSmallPuzzle: Most common use - '+commonUse); + + // loop through the puzzles, checking which has the proper use + for i := 0 to high(puzzles) do + if (commonUse = puzzles[i]) then + begin + result := i; + break; + end; + + if (result <> -1) then + addToSRLLog('MD_IDSmallPuzzle: Found Small Puzzle '+puzzles[result]) + else + addToSRLLog('MD_IDSmallPuzzle: Didn''t ID puzzle'); + + // to make sure the player doesn't log out + if (getCurrentTab() = TAB_FRIENDS) then + gameTab(TAB_CLAN) + else + gameTab(TAB_FRIENDS); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Solves the small puzzle (calls MD_GetSmallPuzzle). + *) +function MD_SolveSmallPuzzle(puzzle: string): boolean; +var + i, j, t: integer; + posObjs: TRotateObjectArray; +begin + if (not loggedIn()) then + exit; + + addToSRLLog('MD_SolveSmallPuzzle: Solving...'); + + repeat + inc(t); + + for i := 5 to 8 do // object slots 5-8 (bottom half) + begin + posObjs := MD_IdObject(MD_ScanSmallObject(i)); + + for j := 0 to high(posObjs) do + if (lowercase(posObjs[j].use) = lowercase(puzzle)) then + begin + addToSRLLog('MD_SolveSmallPuzzle: Found bottom object in slot '+toStr(i)); + + // needs specific coords because you can't click anywhere on the item + mouse(108 + (100 * (i - 5)), 235, 3, 3, mouse_Left); + result := waitNPCTalking(MD_NPC_MORDAUT, 4000); + break; + end; + + if (result) then + break; + end; + + if (not result) then + addToSRLLog('MD_SolveSmallPuzzle: Didn''t find bottom objects, try '+toStr(t)); + + until(result or (t >= 3)); // maximum tries + + if (result) then + addToSRLLog('MD_SolveSmallPuzzle: Solved Small Puzzle '+puzzle) +end; + +(** + * Author: Coh3n + * Description: Identifies which of the big puzzles we have to solve. + *) +function MD_IDBigPuzzle(puzzles: TMDBigPuzzleArray): integer; +var + i, j, h: integer; + tpa, m: TPointArray; +begin + if (not loggedIn()) then + exit; + + result := -1; + findColorsTolerance(tpa, 13290961, 373, 60, 473, 160, 25); + + // loops through the possible texts in each puzzle in the 'puzzles' array + for i := 0 to high(puzzles) do + for j := 0 to high(puzzles[i].idText) do + // the text on the right size of the puzzle + if (findTPAInTPA(loadTextTPA(puzzles[i].idText[j], smallCharsNS, h), tpa, m)) then + begin + addToSRLLog('MD_GetBigPuzzle: Found '+puzzles[i].name); + result := i; + exit; + end; + + addToSRLLog('MD_GetBigPuzzle: Failed to identify big puzzle'); +end; + +(** + * Author: Coh3n + * Description: Returns true if the swords appear in 'slot'. Checks to see if + * that slot has already been clicked. + *) +function MD_FindSwords(slot: integer): boolean; +var + x, y, dtmSwords: integer; + b: TBox; +begin + if (not loggedIn()) then + exit; + + dtmSwords := DTMFromString('mbQAAAHicY2VgYPgLxD+AmImRgeELkGYF0i1AuguIO4G4BoonTJzI8O+sJxjLKciDMT9QHB0zYsFgAAB8JQxr'); + b := MD_BigBox(slot); + + if (findDTM(dtmSwords, x, y, b.x1, b.y1, b.x1 + 50, b.y1 + 50)) then + begin + addToSRLLog('MD_FindSwords: Slot has already been clicked'); + result := true; + end; + + freeDTM(dtmSwords); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Solves the big 'puzzle'. Constants at the top of the file. Will + * randomly choose slots to scan, then remove that slot from an array. Will + * check every slot before starting over. Starts over a set number of tries. + *) +function MD_SolveBigPuzzle(puzzle: TMDBigPuzzle): boolean; +var + i, clicks, slotsLen, time, index, t: integer; + objFound: TBooleanArray; + slots: TIntegerArray; + tmpObj: TRotateObject; + p: TPoint; +begin + markTime(time); + + if ((not loggedIn()) or (not MD_BigScreen())) then + exit; + + addToSRLLog('MD_SolveBigPuzzle: Solving...'); + setLength(objFound, length(puzzle.objs)); + + // scan the entire puzzle a maximum of 5 times + for t := 1 to 5 do + begin + slots := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + slotsLen := length(slots); + + addToSRLLog('MD_SolveBigPuzzle: Scanning for objects (try '+toStr(t)+')...'); + + // randomly chooses a slot to look for the objects + repeat + index := random(length(slots)); + + if (not MD_FindSwords(slots[index])) then // if that slot has already been clicked + begin + p := middleBox(MD_BigBox(slots[index])); + + tmpObj := MD_ScanBigObject(slots[index]); + for i := 0 to high(puzzle.objs) do + begin + if (objFound[i]) then // don't want to look for the same object twice + continue; + + if (MD_CompareObjects(tmpObj, puzzle.objs[i]) >= MD_MIN_SCORE) then + begin + addToSRLLog('MD_SolveBigPuzzle: Found '+puzzle.objs[i].name+' in slot '+toStr(slots[index])); + mouse(p.x, p.y, 20, 30, mouse_Left); + objFound[i] := true; + inc(clicks); + break; + end; + end; + + end else + if (t = 1) then // in case it's retrying + inc(clicks); + + // remove the index so we don't search the same box twice + deleteValueInIntArray(slots, index); + + result := (clicks >= 3); // only need to click 3 times + + until((length(slots) <= 0) or result); + + if (result) then + break; + end; + + if (result) then + begin + addToSRLLog('MD_SolveBigPuzzle: Solved in '+toStr(timeFromMark(time))+'ms'); + wait(500 + random(500)); + mouse(429, 270, 7, 7, mouse_Left); // click the thumb + wait(800 + random(500)); + end else + addToSRLLog('MD_SolveBigPuzzle: Didn''t solve '+puzzle.name); +end; + +(** + * Author: Coh3n & Nava2 + * Description: Exits the classroom. + *) +function MD_Exit(): boolean; +var + doorColor, x, y: integer; + txt, doorDirection, doorType: string; + p: TPoint; + a: extended; +begin + txt := getTextAtExWrap(142, 395, 500, 419, 1, 6, 2, clBlack, 50, upChars); + + // get the door's direction + doorDirection := lowercase(trim(between('in the ', ' of', txt))); + case doorDirection of + 'south-west' : begin p := point(MMX1, MMY2); a := 270; end; + 'north' : begin p := point(MMCX, MMY1); a := 0; end; + 'north-west' : begin p := point(MMX1, MMY1); a := 270; end; + 'south-east' : begin p := point(MMX2, MMY2); a := 90; end; + + else begin + addtoSRLLog('MD_Exit: Failed to get door direction'); + exit; + end; + end; + + // get the door's color + doorType := lowercase(trim(between(' the ', ' door', txt))); + case doorType of + 'purple circle' : doorColor := 14754001; + 'red cross' : doorColor := 1318539; + 'green square' : doorColor := 3927642; + 'blue star' : doorColor := 6115385; + + else begin + addtoSRLLog('MD_Exit: Failed to get door color'); + exit; + end; + end; + + addToSRLLog('MD_Exit: Need to exit through '+doorDirection+', '+doorType+' door'); + makeCompass('n'); + + // walk to the proper door + if (TPAWalk(clRed, 50, 0, 0, p)) then + begin + makeCompass(a); + wait(1500 + random(500)); + + // find and click the door + if (findColorTolerance(x, y, doorColor, MSX1, MSY1, MSX2, MSY2, 15)) then + begin + mouse(x, y, 5, 5, mouse_Move); + + if (waitUptext('oor', 300)) then + begin + addToSRLLog('MD_Exit: Clicking door'); + getMousePos(x, y); + mouse(x, y, 0, 0, mouse_Left); + + if (didRedClick()) then + result := waitTabExists(TAB_MAGIC, 8000); + end; + end; + end; +end; + +// debugs each rotating item in the Mordaut small puzzle +procedure MD_DebugPuzzle(slots: TIntegerArray; names: TStringArray; use: string; big: boolean); +var + i: integer; +begin + MD_DeclareGlobals(); + + for i := 0 to high(slots) do + if (big) then + debugRotateObject(MD_ScanBigObject(slots[i]), names[i], use) + else + debugRotateObject(MD_ScanSmallObject(slots[i]), names[i], use); +end; + +(** + * Author: Coh3n + * Description: Solves the random. + *) +const + _MD_MAX = 6; // maximum puzzle tries + +function MD_Solve(): boolean; +var + t, puz, incorrect, correct: integer; + bigPuzzles: TMDBigPuzzleArray; + smallPuzzles: TStringArray; + solved: boolean; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + (15 * 60000)); + + MD_DeclareGlobals(); + clickNorth(SRL_ANGLE_HIGH); + + bigPuzzles := MD_GetBigPuzzles(); + smallPuzzles := MD_GetSmallPuzzles(); + + repeat + // solve the big puzzle + if (MD_BigScreen()) then + begin + puz := MD_IDBigPuzzle(bigPuzzles); + + if (puz <> -1) then + solved := MD_SolveBigPuzzle(bigPuzzles[puz]) + else + break; + end; + + // solve the small puzzle + if (MD_SmallScreen()) then + begin + puz := MD_IDSmallPuzzle(smallPuzzles); + + if (puz <> -1) then + solved := MD_SolveSmallPuzzle(smallPuzzles[puz]); + end; + + // wait for Mordaut to start talking, otherwise puzzle wasn't solved + if (solved) then + begin + solved := false; + mouseBox(MIX1, MIY1, MIX2, MIY2, mouse_Move); // move away from MS to get a more accurate scan + + if (waitNPCTalking(MD_NPC_MORDAUT, 3000)) then + if (findNPCChatTextMulti(['No', 'WRONG'], nothing)) then + begin + addToSRLLog('MD_Solve: Incorrectly solved puzzle'); + inc(incorrect); + end else + inc(correct); + end; + + // to bring up the next puzzle or show the solver is done + if (doConversation('exit', false)) then + if (MD_Exit()) then + begin + if (incorrect > 3) then + addToSRLLog('MD_Solve: Exited Mordaut, but too many incorrect puzzles') + else + result := true; + end else begin + addToSRLLog('MD_Solve: Failed to exit classroom'); + break; + end; + + // checks if we've been trying to solve for too long + if ((getSystemTime > t) and (not result)) then + begin + addToSRLLog('MD_Solve: Mordaut solver timed out'); + break; + end; + + until(result); +end; + diff --git a/SRL/core/antirandoms/pillory.simba b/SRL/core/antirandoms/pillory.simba new file mode 100644 index 0000000..e38c0a4 --- /dev/null +++ b/SRL/core/antirandoms/pillory.simba @@ -0,0 +1,349 @@ +(* +Pillory +======= + +Stores all the routines to solve the Pillory random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +This solver uses very specific color density checks to determine the shape of +the lock and which key to use. + +*) + +(** + * Author: nielsie95 + * Description: Checks if the lock screen is visible. + *) +function PL_LockScreen(): boolean; +begin + result := (loggedIn() and (getColor(502, 22) = 0)); +end; + +(** + * Author: nielsie95 & Coh3n + * Description: Returns true if the locks have been opened. + *) +function PL_DoneLocks(): boolean; +begin + if (not PL_LockScreen) then + if (findNPCChatText('spinning lock', nothing)) then + if (clickContinue(true, true)) then + begin + result := true; + wait(2000 + random(1000)); + end; +end; + +(** + * Author: Wanted + * Description: Returns true if in the Pillory random. + *) +function PL_Detect(): boolean; +var + tpa: TPointArray; +begin + if (not tabExists(TAB_MAGIC)) and (tabExists(TAB_FRIENDS)) then + begin + // red doors of the cages + findColorsTolerance(tpa, 237, MMCX - 15, MMCY - 15, MMCX + 15, MMCY + 15, 17); + result := ((inRange(length(tpa), 3, 18)) and (PL_LockScreen())); + end; +end; + +(** + * Author: Wanted & Coh3n + * Description: Clicks the cage to open the lock screen. + *) +function PL_ClickCage(): boolean; +var + x, y: integer; +begin + if (not loggedIn()) then + exit; + + result := PL_LockScreen(); + + if (not result) then + // click around the center of the main screen (where cage lock is) + if (spiralMouse(x, y, MSCX - 20, MSCY - 20, MSCX + 20, MSCY - 20, 'age', 30, 8)) then + begin + getMousePos(x, y); + mouse(x, y, 0, 0, mouse_Left); + + if (waitFunc(@PL_LockScreen, 50, 5000)) then + begin + addToSRLLog('PL_ClickCage: Opened lock screen'); + result := true; + end; + end; +end; + +(** + * Author: Coh3n + * Description: Returns a tpa of the lock color found in 'area'. + *) +function PL_GetLockTPA(area: TBox): TPointArray; +begin + setColorToleranceSpeed(2); + setToleranceSpeed2Modifiers(0.26, 0.55); + + // the color on the inside of the lock, and the face of the keys + findColorsTolerance(result, 1121831, area.x1, area.y1, area.x2, area.y2, 4); + + setColorToleranceSpeed(1); + setToleranceSpeed2Modifiers(0.2, 0.2); +end; + +(** + * Author: nielsie95 + * Description: Returns a color density of the four corners of 'bounds'. + *) +function PL_GetDensities(bounds: TBox): TIntegerArray; +var + i: integer; + b: TBox; +begin + setLength(result, 4); + + for i := 0 to high(result) do + begin + b := bounds; + + b.x2 := (bounds.x1 + bounds.x2) shr 1; + b.y2 := (bounds.y1 + bounds.y2) shr 1; + + case i of + 1: begin + b.x1 := b.x2; + b.x2 := bounds.x2; + end; + + 2: begin + b.y1 := b.y2; + b.y2 := bounds.y2; + end; + + 3: begin + b.x1 := b.x2; + b.x2 := bounds.x2; + b.y1 := b.y2; + b.y2 := bounds.y2; + end; + end; + + result[i] := length(PL_GetLockTPA(b)); + end; + + quickSort(result); +end; + +(** + * Author: nielsie95, Wanted, & Coh3n + * Description: Returns the type of lock that needs to be opened. + *) +function PL_GetLock(): string; +var + densities: TIntegerArray; + tpa: TPointArray; + bounds: TBox; + l, t: integer; + e: extended; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + 8000); // 8 seconds to identify lock + + while ((getSystemTime < t) and (PL_LockScreen())) do + begin + wait(randomRange(50, 75)); + + // box around the spinning lock + tpa := PL_GetLockTPA(intToBox(40, 40, 180, 180)); + l := length(tpa); + + // if not enough colors are found, search again + if (l < 300) then + continue; + + // if more than 1100 colors are found, it has to be a circle + if (l > 1100) then + begin + result := 'circle'; + break; + end; + + bounds := getTPAbounds(tpa); + + if (((bounds.x2 - bounds.x1) < 24) and ((bounds.y2 - bounds.y2) < 24)) then + continue; + + densities := PL_GetDensities(bounds); + + if (((densities[3] - densities[0]) > 150) and (l > 350)) then + begin + result := 'triangle'; + break; + end; + + e := maxE(bounds.x2 - bounds.x1, bounds.y2 - bounds.y1) / minE(bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + + if ((((densities[3] - densities[0]) < 35) and (l > 600)) or + (((densities[3] - densities[0]) < 75) and (l > 750) and (l < 900))) and + (e < 1.3) then + begin + result := 'square'; + break; + end; + end; + + if (result = '') then + result := 'rombus'; + + addToSRLLog('PL_GetLock: Identified lock - '+capitalize(result)) +end; + +(** + * Author: nielsie95, Wanted, & Coh3n + * Description: Returns the type of key in 'slot', starting at 0. + *) +function PL_GetKey(slot: integer): string; +var + tpa: TPointArray; + l, e, t: integer; + bounds: TBox; + densities: TIntegerArray; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + 8000); + l := 0; + + while ((getSystemTime < t) and (PL_LockScreen())) do + begin + wait(60 + random(40)); + + // search box depends on which 'slot' the key is in + tpa := PL_GetLockTPA(intToBox(190 + (slot * 95), 180, 235 + (slot * 95), 260)); + + if (length(tpa) < l) or (length(tpa) < 230) then + continue; + + l := length(tpa); + bounds := getTPABounds(tpa); + + if ((bounds.x2 - bounds.x1) < 18) and ((bounds.y2 - bounds.y1) < 18) then + continue; + + e := (bounds.x2 - bounds.x1) - (bounds.y2 - bounds.y1); + + if (l > 400) and (l < 600) and (e < -5) then + begin + result := 'rombus'; + break; + end; + + if (iAbs(e) <= 3) then + if (l > 600) then + begin + result := 'square'; + break; + end else + if (l > 375) then + begin + result := 'circle'; + break; + end; + + densities := PL_GetDensities(bounds); + + if (l < 350) and ((densities[3] - densities[0]) > 50) then + begin + result := 'triangle'; + break; + end; + end; + + if (result <> '') then + addToSRLLog('PL_GetKey: Identified key - '+capitalize(result)) + else + addToSRLLog('PL_GetKey: Didn''t identify key in slot '+toStr(slot)); +end; + +(** + * Author: Coh3n + * Description: Solves the Pillory random. + *) +const + _PL_MAX_FAILS = 3; // maximum fails in a row + +function PL_Solve(): boolean; +var + i, t, wrongKey: integer; + lock: string; + keyFound: boolean; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + (2 * 60000)); // maximum 2 minutes + clickNorth(SRL_ANGLE_HIGH); + + if (not PL_ClickCage()) then + begin + addToSRLLog('PL_Solve: Didn''t click cage lock'); + exit; + end; + + repeat + keyFound := false; + + // open the lock screen if it's not already open + if (not PL_LockScreen()) then + PL_ClickCage(); + + lock := PL_GetLock(); + + if (lock <> '') then + begin + for i := 0 to 2 do // there's only 3 keys for each puzzle + if (PL_GetKey(i) = lock) then + begin + addToSRLLog('PL_Solve: Found matching key'); + + // specific coords because only a certain part is "clickable" + mouse(208 + (94 * i), 225, 4, 4, mouse_Left); + wait(2000 + random(1000)); + wrongKey := 0; + keyFound := true; + break; + end; + + // if the matching key wasn't found, exit window so a new lock can be ID'd + if ((i = 2) and (not keyFound)) then + begin + addToSRLLog('PL_Solve: Failed to find matching key, resetting...'); + closeWindow(); + i := -1; // used to differentiate between a failed/successful attempt + end; + end; + + if (not PL_LockScreen()) then + if (findNPCChatText('not', nothing)) then + inc(wrongKey) + else + if (i <> -1) then + result := waitTabExists(TAB_MAGIC, 10000); + + wait(1500 + random(500)); + until(result or (getSystemTime > t) or (wrongKey = _PL_MAX_FAILS)); + + if (not result) then + if (wrongKey = _PL_MAX_FAILS) then + addToSRLLog('PL_Solve: Picked wrong key too many times in a row') + else + addToSRLLog('PL_Solve: Pillory solver timed out'); +end; + diff --git a/SRL/core/antirandoms/pinball.simba b/SRL/core/antirandoms/pinball.simba new file mode 100644 index 0000000..75a28b0 --- /dev/null +++ b/SRL/core/antirandoms/pinball.simba @@ -0,0 +1,295 @@ +(* +Pinball +======= + +Stores all the routines to solve the Pinball random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +This solver uses findGapsTPA to determine which post to click. + +*) + +//{$DEFINE PB_DEBUG} + +const + PB_SCORE_10 = 60; // the tpa length of when the score is 10 + +(** + * Author: Coh3n + * Description: Detects if a player is in the Pinball random. + *) +function PB_Detect(): boolean; +begin + // makes sure friends tab exists and magic doesn't + if ((not tabExists(TAB_MAGIC)) and (tabExists(TAB_FRIENDS))) then + if (getNPCChatName() = SRL_NPC_OLDMAN) then + if (findNPCChatTextMulti(['10', 'flashing', 'pillars'], nothing)) then + result := (countColor(clBlack, MMCX-20, MMCY-20, MMCX+20, MMCY+20) = 1681); +end; + +(** + * Author: Coh3n + * Description: Returns the length of a tpa found of the yellow color of the + * score at the top of the main screen. + *) +function PB_GetScore(): integer; +var + tpa: TPointArray; +begin + // yellow color of the score + if (findColorsTolerance(tpa, 381907, 280, 15, 315, 50, 30)) then + result := length(tpa); +end; + +(** + * Author: SKy Scripter, NCDS, & Coh3n + * Description: Returns true if a flashing pillar is found. Sets coordinates + * to x, y. + *) +const + _PB_FILL_COLOR = 10; + _PB_MIN_LENGTH = 20; + +function PB_ScanPost(var x, y: integer): boolean; +var + tpa: TPointArray; + pillarCols: array of integer; + ATPA, pillarGaps: T2DPointArray; + oldTarget, tmpCTS, bmp, i, j, c: integer; + hue, sat, lum: extended; + tmpBox: TBox; +begin + result := false; + bmp := -1; + + try + tmpCTS := getColorToleranceSpeed; + setColorToleranceSpeed(3); + + // the green of the spinning pillars + findColorsTolerance(tpa, 8708721, MSX1, MMY1, MSX2, MSY2, 5); + + setColorToleranceSpeed(tmpCTS); + + // if colors aren't found, exit + if (length(tpa) < _PB_MIN_LENGTH) then + exit; + + bmp := createBitmap(MSX2 + 5, MSY2 + 5); // creats a bitmap of the MS + fastDrawClear(bmp, _PB_FILL_COLOR); // fill it with a distinct color + + c := 0; + pillarCols := getColors(tpa); + + // draws a rectangle on the bitmap of the colors that are light enough + for i := 0 to high(tpa) do + begin + colorToHSL(pillarCols[i], hue, sat, lum); + + if (lum > 50.0) then + begin + tmpBox := intToBox(max(0, tpa[i].x - 1), max(0, tpa[i].y - 1), tpa[i].x + 1, tpa[i].y + 1); + rectangleBitmap(bmp, tmpBox, clRed); + inc(c); + end; + end; + + if (c > _PB_MIN_LENGTH) then + begin + floodFillBitmap(bmp, point(5, 5), _PB_FILL_COLOR, clBlack); + + oldTarget := getImageTarget(); + setTargetBitmap(bmp); + + findColors(tpa, _PB_FILL_COLOR, 0, 0, MSX2 - 5, MSY2 - 5); + + setImageTarget(oldTarget); // reset target to RS client + + if (length(tpa) > 10) then + begin + ATPA := TPAtoATPA(tpa, 60); + sortATPASize(ATPA, true); + + for i := 0 to high(ATPA) do + begin + pillarGaps := findGapsTPA(ATPA[i], 10); + + for j := 0 to high(pillarGaps) do + if (length(pillarGaps[j]) > 2) then + begin + middleTPAEx(ATPA[i], x, y); + result := true; + break; + end; + + if (result) then + break; + end; + end; + end; + + {$IFDEF PB_DEBUG} + displayDebugImgWindow(MSX2, MSY2); + drawBitmapDebugImg(bmp); + {$ENDIF} + + finally + if (bmp <> -1) then + freeBitmap(bmp); + end; + + if (result) then + addToSRLLog('PB_ScanPost: Found post'); +end; + +(** + * Author: Coh3n + * Description: Returns true if player clicks a post and the score changes. + *) +function PB_TagPost(): boolean; +var + t, x, y, oldScore: integer; +begin + if (not loggedIn()) then + exit; + + oldScore := PB_GetScore(); + + if (PB_ScanPost(x, y)) then + begin + Mouse(x, y, 5, 5, mouse_Right); + + if (WaitOptionMulti(['ag', 'g P'], 618)) then + begin + t := (getSystemTime + 6000); + while (getSystemTime < t) do + begin + if (PB_GetScore() <> oldScore) then + begin + addToSRLLog('PB_TagPost: Tagged post'); + result := true; + break; + end; + + wait(300 + random(200)); + end; + end else + MMouse(x, y - 25, 8, 8); + end; +end; + +(** + * Author: DemiseScythe & Coh3n + * Description: Uses mainscreen walking to exit the random. + * Updated: Added a backup to the exit as it can sometimes miss it. - [J]ustin - 03/08/2012 + *) +function PB_Exit(): boolean; +var + x, y, t, i: integer; + tpa, tpa_Exit: TPointArray; + ATPA: T2DPointArray; +begin + if (not loggedIn()) then + exit; + addToSRLLog('PB_Exit: Exiting cave'); + t := (getSystemTime + 20000); + clickNorth(SRL_ANGLE_HIGH); + repeat + // the green path color + if (findColorsTolerance(tpa, 9283213, MSX1, MMCY, MSX2, MSY2, 15)) then + if (length(tpa) > 0) then + begin + sortTPAFrom(tpa, point(MSCX, MSY2)); // center of the bottom of the MS + x := tpa[0].x; + y := tpa[0].y - 20; // so it's actually on the MS + + mouse(x, y, 5, 5, mouse_Move); + + // check for the proper uptexts + if (waitUptextMulti(['Walk', 'alk', 'here', 'ere'], 200)) then + begin + getMousePos(x, y); + mouse(x, y, 0, 0, mouse_Left); + end + else if (waitUptextMulti(['Exit', 'xit', 'Cave', 'ave'], 200)) then + begin + getMousePos(x, y); + mouse(x, y, 0, 0, mouse_Left); + + if (waitTabExists(TAB_MAGIC, 8000)) then + begin + result := true; + break; + end; + end; + end; + result := tabExists(TAB_MAGIC); // just in case + wait(2000 + random(300)); + until ((getSystemTime > t) or (result)); + if (result) then + addToSRLLog('PB_Exit: Clicked exit cave') + else + begin + addToSRLLog('PB_Exit: Took to long to find exit... Looking for backup'); + t := (getSystemTime + 20000); + repeat + if (FindColorsTolerance(tpa_Exit, 10390671, MSX1, MSY1, MSX2, MSY2, 10)) then + ATPA := TPAToATPAEx(tpa_Exit, 70, 5); + if (length(ATPA) > 0) then + begin + SortATPASize(ATPA, True); + for i := 0 to High(ATPA) do + begin + MiddleTPAEx(ATPA[i], x, y); + mouse(x, y, 5, 5, mouse_Move); + if (waitUptextMulti(['Exit', 'xit', 'Cave', 'ave'], 200)) then + begin + getMousePos(x, y); + mouse(x, y, 0, 0, mouse_Left); + if (waitTabExists(TAB_MAGIC, 8000)) then + begin + result := true; + break; + end; + end; + end; + end; + result := tabExists(TAB_MAGIC); + wait(2000 + random(300)); + until ((getSystemTime > t) or (result)); + if (result) then + addToSRLLog('PB_Exit: Clicked exit cave with backup') + else + addToSRLLog('PB_Exit: Failed to exit') + end; +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Solves the Pinball random. + *) +function PB_Solve(): boolean; +var + t: integer; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + (15 * 60000)); // maximum 15 minutes + doConversation('', false); + + repeat + if (PB_GetScore = PB_SCORE_10) then // length of "Score: 10" + begin + if (PB_Exit()) then + begin + result := true; + break; + end; + end else + PB_TagPost(); + + wait(500 + random(200)); + until(result or (getSystemTime > t)); +end; diff --git a/SRL/core/antirandoms/prisonpete.simba b/SRL/core/antirandoms/prisonpete.simba new file mode 100644 index 0000000..b0613c5 --- /dev/null +++ b/SRL/core/antirandoms/prisonpete.simba @@ -0,0 +1,44 @@ +(* +Prison Pete +=========== + +Stores all the routines to solve the Prison Pete random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +*) + +(** + * Author: Coh3n + * Description: Detects if a player is in the random. + *) +function PP_Detect(): boolean; +begin + if (not tabExists(TAB_MAGIC)) then + if (countColorTolerance(14409956, MMX1, MMY1, MMX2, MMY2, 10) > 700) then // white tiles + if (countColorTolerance(6713450, MMX1, MMY1, MMX2, MMY2, 10) > 300) then // grey tiles + result := (countColorTolerance(clWhite, MMX1, MMY1, MMX2, MMY2, 50) > 500); // walls +end; + +(** + * Author: + * Description: Solves the random. + *) +function PP_Solve(): boolean; +var + t: integer; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + (5 * 60000)); // maximum 5 minutes + doConversation('', false); + + repeat + + until(result or (getSystemTime > t)); + + if (not result) then + addToSRLLog('PP_Solve: '' solver timed out'); +end; + diff --git a/SRL/core/antirandoms/quiz.simba b/SRL/core/antirandoms/quiz.simba new file mode 100644 index 0000000..779641a --- /dev/null +++ b/SRL/core/antirandoms/quiz.simba @@ -0,0 +1,394 @@ +(* +Quiz +==== + +Stores all the routines to solve the Quiz random. None of these routines +should be used throughout scripts. They only need to be called in SRL's random +detection methods. + +This solver uses a "score" system to determine which item is the odd one out. +A rotating object is determined using the TRotateObject type and +DebugRotateObject method both found in common.simba. Each quiz item is declared +in Quiz_LoadItems and is compared to a scanned object in each of the item slots. +It then compares the scanned item with the stored item to determine which item +is the odd one out. + +*) + +const + _QUIZ_ACCURACY = 250; // number of tries to scan object - Updated 5/06/2012 - [J]ustin + _QUIZ_NPC = 'GqlzD5gt8!'; // Quiz Master's name + +var + Quiz_Items: TRotateObjectArray; + +(** + * Author: DemiseScythe + * Description: Detects if a player is in the Quiz random. + *) +function Quiz_Detect(): boolean; +begin + result := (getNPCChatName = _QUIZ_NPC) and (not tabExists(TAB_MAGIC)); +end; + +(** + * Author: Coh3n + * Description: Returns true if the "Pick the odd one out." screen is in the + * chat box. + *) +function Quiz_QuestionScreen(): boolean; +begin + // the yellow color of the text + result := (getColor(302, 384) = 65535); +end; + +(** + * Author: Coh3n + * Description: Returns a box around the item slot, 'slot'. + *) +function Quiz_ItemBox(slot: integer): TBox; +begin + result := gridBox(slot, 3, 1, 80, 37, 176, 0, point(84, 433)); +end; + +(** + * Author: Wizzup? + * Description: Loads all the quiz items into the Quiz_Items array. + *) +procedure Quiz_LoadItems(); +begin + setLength(Quiz_Items, 20); + + with Quiz_Items[0] do + begin + name := 'Trout Fish Big'; + use := 'Edible'; + count := 191; + width := 25; + height := 16; + totalCount := 370; + coverPercent := 50.0; + end; + + with Quiz_Items[1] do + begin + name := 'Trout Fish Small'; + use := 'Edible'; + count := 123; + width := 19; + height := 13; + totalCount := 228; + coverPercent := 52.0; + end; + + with Quiz_Items[2] do + begin + name := 'Tuna Fish Big'; + use := 'Edible'; + count := 255; + width := 24; + height := 16; + totalCount := 401; + coverPercent := 61.0; + end; + + with Quiz_Items[3] do + begin + name := 'Tuna Fish Small'; + use := 'Edible'; + count := 166; + width := 19; + height := 13; + totalCount := 254; + coverPercent := 63.0; + end; + + with Quiz_Items[4] do + begin + name := 'Necklace Small'; + use := 'Jewelry'; + count := 91; + width := 18; + height := 11; + totalCount := 170; + coverPercent := 47.0; + end; + + with Quiz_Items[5] do + begin + name := 'Necklace Big'; + use := 'Jewelry'; + count := 137; + width := 22; + height := 14; + totalCount := 308; + coverPercent := 46.0; + end; + + with Quiz_Items[6] do + begin + name := 'Ring Small'; + use := 'Jewelry'; + count := 112; + width := 14; + height := 11; + totalCount := 154; + coverPercent := 72.0; + end; + + with Quiz_Items[7] do + begin + name := 'Ring Big'; + use := 'Jewelry'; + count := 172; + width := 17; + height := 14; + totalCount := 243; + coverPercent := 70; + end; + + with Quiz_Items[8] do + begin + name := 'Shield Small'; + use := 'Armour'; + count := 95; + width := 14; + height := 8; + totalCount := 122; + coverPercent := 76.0; + end; + + with Quiz_Items[9] do + begin + name := 'Shield Big'; + use := 'Armour'; + count := 147; + width := 17; + height := 11; + totalCount := 201; + coverPercent := 71.0; + end; + + with Quiz_Items[10] do + begin + name := 'Spade'; + use := 'Tool'; + count := 75; + width := 21; + height := 15; + totalCount := 253; + coverPercent := 29.5; + end; + + with Quiz_Items[11] do + begin + name := 'Sword Small'; + use := 'Weapon'; + count := 42; + width := 18; + height := 11; + totalCount := 176; + coverPercent := 25.0; + end; + + with Quiz_Items[12] do + begin + name := 'Sword Big'; + use := 'Weapon'; + count := 65; + width := 23; + height := 14; + totalCount := 278; + coverPercent := 23.0; + end; + + with Quiz_Items[13] do + begin + name := 'Shears Small'; + use := 'Tool'; + count := 142; + width := 21; + height := 13; + totalCount := 270; + coverPercent := 50.0; + end; + + with Quiz_Items[14] do + begin + name := 'Shears Big'; + use := 'Tool'; + count := 219; + width := 27; + height := 14; + totalCount := 408; + coverPercent := 53.0; + end; + + with Quiz_Items[16] do + begin + name := 'BattleAxe Big'; + use := 'Weapon'; + count := 119; + width := 23; + height := 14; + totalCount := 317; + coverPercent := 38.0; + end; + + with Quiz_Items[17] do + begin + name := 'BattleAxe Small'; + use := 'Weapon'; + count := 78; + width := 18; + height := 11; + totalCount := 200; + coverPercent := 40.0; + end; + + with Quiz_Items[18] do + begin + name := 'Helmet Small'; + use := 'Weapon'; + count := 279; + width := 17; + height := 18; + totalCount := 322; + coverPercent := 85.5; + end; + + with Quiz_Items[19] do + begin + name := 'Helmet Big'; + use := 'Weapon'; + count := 428; + width := 22; + height := 22; + totalCount := 508; + coverPercent := 83.5; + end; +end; + +(** + * Author: Wizzup? + * Description: Scans and returns the item in 'slot'. + *) +function Quiz_ScanItem(slot: integer): TRotateObject; +var + i, maxScore, maxIndex: integer; + obj: TRotateObject; + scores: TintegerArray; +begin + // the colors of the blue background and border of the items + obj := scanRotateObject([7807248, 11040367], [35, 35], Quiz_ItemBox(slot), 5, _QUIZ_ACCURACY); + + setLength(scores, length(Quiz_Items)); + + // loop through fields, scoring each item + for i := 0 to high(Quiz_Items) do + begin + if (Quiz_Items[i].width = obj.width) and (Quiz_Items[i].height = obj.height) then + scores[i] := scores[i] + 5 + else + if inRange(obj.width, Quiz_Items[i].width - 3, Quiz_Items[i].width + 3) and inRange(obj.height, Quiz_Items[i].height - 3, Quiz_Items[i].height + 3) then + scores[i] := scores[i] + 3; + + if inRange(obj.count, Quiz_Items[i].count - 10, Quiz_Items[i].count + 10) then + scores[i] := scores[i] + 2; + + if inRange(obj.totalCount, Quiz_Items[i].totalCount - 15, Quiz_Items[i].totalCount + 15) then + scores[i] := scores[i] + 2; + + if (obj.coverPercent > Quiz_Items[i].coverPercent - 3) and (obj.coverPercent < Quiz_Items[i].coverPercent + 3) then + scores[i] := scores[i] + 2; + end; + + // get the item with the highest score + maxScore := -1; + maxIndex := -1; + for i := 0 to high(scores) do + if (scores[i] > maxScore) then + begin + maxScore := scores[i]; + maxIndex := i; + end; + + addToSRLLog('Quiz_ScanItem: '+Quiz_Items[maxIndex].name + ', with a score of ' + intToStr(scores[maxIndex])); + + result.name := Quiz_Items[maxIndex].name; + result.use := Quiz_Items[maxIndex].use; +end; + +(** + * Author: Wizzup? + * Description: Solves a quiz question. + *) +function Quiz_SolveQuestion(): boolean; +var + i: integer; + tmpObjs: array[0..2] of TRotateObject; + commonUse: string; + p: TPoint; +begin + // scan each item slots for the rotating objects + for i := 0 to 2 do + tmpObjs[i] := Quiz_ScanItem(i + 1); + + commonUse := GetTROAUse(tmpObjs); + + // sets i to the correct item slot so it can be clicked + if (commonUse <> '') then + begin + for i := 0 to 2 do + if (tmpObjs[i].use <> commonUse) then + begin + addToSRLLog('Quiz_SolveQuestion: We need to pick ' + tmpObjs[i].name + ' at slot ' + toStr(i + 1)); + break; + end; + + // for some reason i gets increased to 3 if the loop's condition isn't met; means failed to ID items properly, so we're going to guess + if (i >= 3) then + i := random(3); + + p := middleBox(Quiz_ItemBox(i + 1)); + mouse(p.x, p.y, 20, 10, mouse_Left); + + wait(500 + random(500)); + mouse(MIX1, MIY1, 50, 50, mouse_Move); // move away from chat box to get accurate scan + result := true; + end else + addToSRLLog('Quiz_SolveQuestion: Didn''t properly ID items'); +end; + +(** + * Author: + * Description: Solves the random. + *) +function Quiz_Solve(): boolean; +var + t: integer; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + (10 * 60000)); // maximum 10 minutes + Quiz_LoadItems(); + + repeat + if (Quiz_QuestionScreen()) then + if (Quiz_SolveQuestion()) then + if (waitNPCTalking(_QUIZ_NPC, 4000)) then + if (findNPCChatText('RIGHT', nothing)) then + addToSRLLog('Quiz_Solve: Answered question right') + else + addToSRLLog('Quiz_Solve: Answered question wrong'); + + clickContinue(true, true); // to go through all the dialogue + result := tabExists(TAB_MAGIC); + + until(result or (getSystemTime > t)); + + if (not result) then + addToSRLLog('Quiz_Solve: Quiz solver timed out'); +end; + diff --git a/SRL/core/antirandoms/randomtool.simba b/SRL/core/antirandoms/randomtool.simba new file mode 100644 index 0000000..b81852d --- /dev/null +++ b/SRL/core/antirandoms/randomtool.simba @@ -0,0 +1,283 @@ +(* +SRL Random Tool +=============== + +The SRL random tool is an optional tool for scripters that allows the user to +decide whether they want the script to solve a random, or if they want to use +SRL's solvers. It's useful if a player encounters a disabled random, or an +enabled random that isn't working properly. + +The SRL Random Tool was originally developed by N1ke! and was cleaned up and +updated by Coh3n on March 6th, 2012. + +*) + +var + RT_WaitTimeOut, RT_CountMS, RT_FKeyFinish: integer; + RT_SelfSolve, RT_UseRandomTool: boolean; + RT_SoundPath: string; + +const + RT_LABEL_COUNT = 4; + RT_LABEL_TITLE = 0; + RT_LABEL_RAND = 1; + RT_LABEL_PLAYER = 2; + RT_LABEL_TIMEOUT = 3; + + RT_BUTTON_COUNT = 2; + RT_BUTTON_SELF = 0; + RT_BUTTON_SRL = 1; + +{$IFNDEF Lape} +var + RT_Form: TForm; + + RT_Labels: array[0..(RT_LABEL_COUNT - 1)] of TLabel; + RT_Buttons: array[0..(RT_BUTTON_COUNT - 1)] of TButton; + RT_UseBox: TCheckBox; + + RT_Timer_UntilClose, RT_Timer_Countdown: TTimer; +{$ENDIF} + +function RT_GetRandomByName(name: string): integer; +var + i: integer; +begin + result := -1; + + for i := 0 to high(SRL_Randoms) do + if (SRL_Randoms[i].name = name) then + begin + result := i; + break; + end; +end; + +{$IFNDEF Lape} +procedure RT_OnClick(sender: TObject); +begin + case sender of + RT_Buttons[RT_BUTTON_SELF]: + begin + RT_SelfSolve := true; + showMessage('Hit OK, then press F'+toStr(RT_FKeyFinish)+' when you have solved the random.'); + RT_Form.ModalResult := mrOk; + end; + + RT_Buttons[RT_BUTTON_SRL]: + RT_Form.ModalResult := mrOk; + end; +end; + +procedure RT_OnTimer(sender: TObject); +begin + case sender of + RT_Timer_UntilClose: + RT_Form.ModalResult := mrOk; + + RT_Timer_CountDown: + begin + inc(RT_CountMS); + RT_Labels[RT_LABEL_TIMEOUT].caption := + 'Timeout in: ' + msToTime(RT_WaitTimeOut - (RT_CountMS * 1000), 1); + end; + end; +end; + +procedure RT_OnClose(sender: TObject; var action: TCloseAction); +begin + case sender of + RT_Form: + RT_UseRandomTool := (not RT_UseBox.checked); + end; +end; +{$ENDIF} + +procedure RT_Init(); +var + i, randIndex: integer; + tmpArr: TStringArray; +begin + {$IFNDEF Lape} + RT_Form := TForm.create(nil); + with RT_Form do + begin + caption := 'SRL Random Tool'; + setBounds(0, 0, 200, 210); + position := poScreenCenter; + formStyle := fsStayOnTop; + borderStyle := bsSingle; + borderIcons := [biSystemMenu]; + onClose := @RT_OnClose; + end; + + RT_Labels[RT_LABEL_TITLE] := TLabel.create(RT_Form); + with RT_Labels[RT_LABEL_TITLE] do + begin + parent := RT_Form; + top := 5; + width := 140; + height := 15; + left := (parent.width / 2) - (width / 2); + font.size := 15; + font.style := [fsBold]; + caption := 'Random Found!'; + end; + + tmpArr := ['Random: ' + players[currentPlayer].rand, + 'Player: ' + players[currentPlayer].name, + 'Timeout in: ' + msToTime(RT_WaitTimeOut, 1)]; + + for i := 1 to 3 do + begin + RT_Labels[i] := TLabel.create(RT_Form); + with RT_Labels[i] do + begin + parent := RT_Form; + top := 30 + (i * 17); + width := 100; + height := 13; + left := 20; + caption := tmpArr[i - 1]; + end; + end; + + tmpArr := ['Solve it yourself', 'Let SRL solve it']; + + for i := 0 to high(RT_Buttons) do + begin + RT_Buttons[i] := TButton.Create(RT_Form); + with RT_Buttons[i] do + begin + parent := RT_Form; + width := 130; + height := 28; + left := (parent.width / 2) - (width / 2); + top := 110 + (i * 30); + caption := tmpArr[i]; + font.height := -11; + onClick := @RT_OnClick; + end; + end; + + // if the solver is disabled, disable the "Solve SRL" button + randIndex := RT_GetRandomByName(players[currentPlayer].rand); + if (randIndex <> -1) then + RT_Buttons[RT_BUTTON_SRL].enabled := (not SRL_Randoms[randIndex].disabled); + + RT_Timer_UntilClose := TTimer.create(RT_Form); + with RT_Timer_UntilClose do + begin + interval := RT_WaitTimeOut; + enabled := true; + onTimer := @RT_OnTimer; + end; + + RT_Timer_Countdown := TTimer.create(RT_Form); + with RT_Timer_Countdown do + begin + interval := 1000; + enabled := true; + onTimer := @RT_OnTimer; + end; + + RT_UseBox := TCheckBox.create(RT_Form); + with RT_UseBox do + begin + parent := RT_Form; + left := 8; + width := 200; + height := 13; + top := parent.height - height - 10; + caption := ' Stop using SRL''s RandomTool?'; + end; + + RT_Form.showModal; + {$ENDIF} +end; + +procedure RT_Reset(); +begin + RT_CountMS := 0; + RT_SelfSolve := false; +end; + +procedure RT_SafeCall(proc: string); +var + v: TVariantArray; +begin + setLength(v, 0); + threadSafeCall(proc, v); +end; + +procedure RT_Free(); +begin + {$IFNDEF Lape} + RT_Timer_Countdown.enabled := false; + RT_Timer_UntilClose.enabled := false; + RT_Form.free(); + {$ENDIF} +end; + +function RT_Execute(): boolean; +{$IFDEF Lape} +var + t: Integer; +{$ENDIF} +begin + playSound(RT_SoundPath); + + {$IFDEF Lape} + WriteLn('SRL Random Tool: ', Players[CurrentPlayer].Rand); + WriteLn('Press F', RT_FKeyFinish, ' to solve by hand (timeout in ', msToTime(RT_WaitTimeOut, 1), ')'); + + t := GetTickCount() + RT_WaitTimeOut; + while (GetTickCount() < t) do + if (not isKeyDown(VK_F1 + RT_FKeyFinish - 1)) then + Wait(1000) + else + begin + RT_SelfSolve := True; + Break; + end; + + if RT_SelfSolve then + WriteLn('Start solving! Press F', RT_FKeyFinish, ' when ready.') + else + WriteLn('No intervention, let SRL handle the random..'); + {$ELSE} + try + RT_SafeCall('RT_Init'); + except + writeln(exceptionToString(exceptionType, exceptionParam)); + finally + RT_SafeCall('RT_Free'); + end; + {$ENDIF} + + // return true if user is solving by hand (will exit _FindAllRandoms) + if (RT_SelfSolve) then + begin + result := true; + + while (not isKeyDown(VK_F1 + RT_FKeyFinish - 1)) do + wait(1); + end; + + RT_Reset(); +end; + +procedure SetupRandomTool(timeOutWait, FKeyFinish: integer; soundPath: string); +begin + if (not inRange(FKeyFinish, 1, 12)) then + begin + writeln('SetupRandomTool: Invalid FKeyFinish, using F1'); + RT_FKeyFinish := 1; + end else + RT_FKeyFinish := FKeyFinish; + + RT_WaitTimeOut := timeOutWait; + RT_SoundPath := soundPath; + RT_UseRandomTool := true; +end; + diff --git a/SRL/core/antirandoms/rewards.simba b/SRL/core/antirandoms/rewards.simba new file mode 100644 index 0000000..8df034d --- /dev/null +++ b/SRL/core/antirandoms/rewards.simba @@ -0,0 +1,370 @@ +(* +Rewards +======= + +Stores all the routines to solving reward/inventory random events. + +*) + +const + DTM_REWARD_COUNT = 4; + DTM_REWARD_BOX = 0; + DTM_REWARD_MYSTERY = 1; + DTM_REWARD_LAMP = 2; + DTM_REWARD_BOOK = 3; + +function RD_GetDTMs(): TIntegerArray; +begin + setLength(result, DTM_REWARD_COUNT); + + result[DTM_REWARD_BOX] := DTMFromString('mlwAAAHicY2dgYMhmYmBIA+IsIC4A4lIonQzEz4Hy94H4OhDfA+JHQPwWiN8AcQqfI0OnhTDDRg9JhnZzYYYMPhcwH4T5gfK4MCMeDAUADmYPew=='); + result[DTM_REWARD_MYSTERY] := DTMFromString('mlwAAAHicY2dgYMhhYmBIBeJcIC4G4hIgzgTiFCCeycjAMAGIe4F4EhDPAeIlQDwPiGdHigJ1MzHMtBNlmBIqwtBsJgTmTw0TZeBngAB+JAzjM+LBUAAA3YEMSA=='); + result[DTM_REWARD_LAMP] := DTMFromString('mggAAAHicY2NgYMhhYmDIAOIyIK4A4kIgTgPip0C5B0D8kAHCfgXEz4F46hRRIMkExn29ImB6zSoJBn4GBOBHohlxYAgAACyDDBw='); + result[DTM_REWARD_BOOK] := DTMFromString('mrAAAAHic42BgYHBiYmCwBmIfIPYCYlcmiJglFD8CqrkFxHeA+BkQvwDiD0D8FsovyM5mCDGTZPA2EGcwVxZk8DMUZ/DT4WIIN5cCs/mBavBhRgIYBgCtoQ8M'); +end; + +(** + * Author: Coh3n + * Description: Returns true if one of the reward DTMs are found. + * Updated: 5/06/2012 - [J]ustin + *) +function RD_Detect(): boolean; +var + i, x, y: integer; + DTMs: TIntegerArray; +begin + if ((not loggedIn()) or (not gameTab(TAB_INV))) then + exit; + + DTMs := RD_GetDTMs(); + + // loop through reward DTMs + for i := 0 to high(DTMs) do + if (findDTM(DTMs[i], x, y, MIX1, MIY1, MIX2, MIY2)) then + begin + result := true; + break; + end; + + freeDTMs(DTMs); +end; + +(** + * Author: Coh3n + * Description: Solves the Mystery Box (at coords x, y) inventory random. + *) +function RD_SolveMystery(x, y: integer): boolean; +begin + addToSRLLog('RD_SolveMystery: Found mystery box'); + + mmouse(x, y, 5, 5); + if (waitUptext('pen', 200)) then + begin + result := true; + GetmousePos(x, y); + mouse(x, y, 0, 0, mouse_Left); + wait(randomRange(1200, 1800)); // 2-3 game ticks to stop the random repeating + addToSRLLog('RD_SolveMystery: Clicked mystery box'); + end; +end; + +(** + * Author: Coh3n + * Description: Solves XP rewards (at coords x, y) with 'uptext'. + *) +function RD_SolveXP(x, y: integer; uptext: string): boolean; +var + slot, skill: integer; + b: TBox; +begin + mmouse(x, y, 3, 3); + if (waitUptext(uptext, 300)) then + begin + getmousePos(x, y); + mouse(x, y, 0, 0, mouse_Left); + addToSRLLog('RD_SolveXP: Clicked XP reward'); + + // the color of the background (i.e. scroll color) + if (not waitFindColor(x, y, 10803447, MSX1, MSY1, MSX2, MSY2, 5, 5000)) then + begin + addToSRLLog('RD_SolveXP: XP reward didn''t open'); + exit; + end; + + // in case of runtime out of range + if (length(players) <= 0) then + skill := SKILL_MINING + else + skill := players[currentPlayer].lampSkill; + + // slot returned by gridBox below + case skill of + SKILL_ATTACK : slot := 1; + SKILL_DEFENCE : slot := 15; + SKILL_STRENGTH : slot := 8; + SKILL_HITPointS, SKILL_HP : slot := 22; + SKILL_RANGE : slot := 9; + SKILL_PRAYER : slot := 16; + SKILL_MAGIC : slot := 2; + SKILL_COOKING : slot := 24; + SKILL_WOODCUTTING : slot := 4; + SKILL_FLETCHING : slot := 6; + SKILL_FISHING : slot := 17; + SKILL_FIREMAKING : slot := 11; + SKILL_CRAFTING : slot := 18; + SKILL_SMITHING : slot := 10; + SKILL_MINING : slot := 3; + SKILL_HERBLORE : slot := 12; + SKILL_AGILITY : slot := 5; + SKILL_THIEVING : slot := 7; + SKILL_SLAYER : slot := 13; + SKILL_FARMING : slot := 19; + SKILL_RUNECRAFTING : slot := 25; + SKILL_HUNTER : slot := 20; + SKILL_CONSTRUCTION : slot := 14; + SKILL_SUMMONING : slot := 21; + SKILL_DUNGEONEERING : slot := 23; + + else + slot := 3; // Mining + end; + + b := gridBox(slot, 7, 4, 40, 40, 65, 57, point(64, 104)); + mouseBox(b.x1, b.y1, b.x2, b.y2, mouse_Left); // click skill + + wait(500 + random(500)); + mouse(387, 263, 20, 5, mouse_Left); // click confirm + + addToSRLLog('RD_SolveXP: Solved experience reward'); + wait(2000 + random(500)); + clickContinue(true, true); + result := true; + end; +end; + +(** + * Author: Coh3n + * Description: Solves the Gene Lamp (at coords x, y) inventory random. + *) +function RD_SolveLamp(x, y: integer): boolean; +begin + addToSRLLog('RD_SolveLamp: Found experience lamp'); + result := RD_SolveXP(x, y, 'amp'); +end; + +(** + * Author: Coh3n + * Description: Solves the Book of Knowledge (at coords x, y) inventory random. + *) +function RD_SolveBook(x, y: integer): boolean; +begin + addToSRLLog('RD_SolveBook: Found Book of Knowledge'); + result := RD_SolveXP(x, y, 'ook'); +end; + +(** + * Author: Coh3n + * Description: Returns true if the reward box screen is open. + *) +const + _RD_TEXT_COLOR = 2070783; + _RD_TEXT_TOL = 10; + +function RD_BoxScreen(): boolean; +begin + // box around the text + result := findTextTPA(_RD_TEXT_COLOR, _RD_TEXT_TOL, 189, 31, 328, 51, 'hoose', upCharsEx, nothing); +end; + +(** + * Author: Coh3n & Nava2 + * Description: Finds and clicks the reward box option 'opt' in box 'slot'. + * Starts grid at 'gridStart'. Also clicks the confirm button. See RD_SolveBox. + *) +function RD_ClickBoxOption(opt: string; slot: integer; gridStart: TPoint): boolean; +var + x, y, t: integer; + b: TBox; +begin + // grid starts at different points if we need to scroll + b := gridBox(slot, 2, 3, 159, 63, 167, 71, gridStart); + + // if found box option + if (findTextTPA(_RD_TEXT_COLOR, _RD_TEXT_TOL, b.x1, b.y1, b.x2, b.y2, opt, upCharsEx, nothing)) then + begin + addToSRLLog('RD_ClickBoxOption: Found box option '+opt); + mouseBox(b.x1, b.y1, b.x2, b.y2, mouse_Left); + + // box around the confirm choice box + if (waitFindColor(x, y, _RD_TEXT_COLOR, 394, 163, 470, 207, _RD_TEXT_TOL, 4000)) then + begin + mouse(x, y, 10, 10, mouse_Left); + t := (getSystemTime + 5000); + + // wait for the box screen to disappear + while ((not result) and (getSystemTime < t)) do + begin + wait(50 + random(50)); + result := (not RD_BoxScreen()); + end; + end; + end; +end; + +(** + * Author: Coh3n + * Description: Returns true if the scroll bar is ready to scroll down, false + * if ready to scroll up. + *) +function RD_ScrollDown(): boolean; +var + x, y: integer; +begin + // the dark scroll bar color at the bottom of the scroll bar + result := findColorTolerance(x, y, 1909544, 373, 293, 379, 299, 10); +end; + +(** + * Author: Coh3n + * Description: Scrolls up or down in the reward screen. + *) +procedure RD_BoxScroll(); +var + x, y, t: integer; + scrollDown: boolean; +begin + if (not (RD_BoxScreen())) then + exit; + + scrollDown := RD_ScrollDown(); + + // mouse the top or bottom arrow + mmouse(377, 70 + (Ord(scrollDown) * 240), 4, 4); + wait(100 + random(100)); + + wait(100 + random(100)); + getMousePos(x, y); + t := (getSystemTime + 5000); + + holdMouse(x, y, mouse_Left); + while (getSystemTime < t) do + begin + // break if opposite of scrollDown (i.e. done scrolling) + if ((RD_ScrollDown() = (not scrollDown))) then + break; + + wait(50 + random(25)); + end; + releaseMouse(x, y, mouse_Left); +end; + +(** + * Author: Coh3n + * Description: Solves the Reward Box (at coords x, y) inventory random. + *) +function RD_SolveBox(x, y: integer): boolean; +var + i, slot: integer; + boxRewards: TStringArray; + tmpReward: string; +begin + addToSRLLog('RD_SolveBox: Found reward box'); + + mmouse(x, y, 5, 5); + if (waitUptextMulti(['andom', 'event', 'ift', 'pen'], 300)) then + begin + getMousePos(x, y); + mouse(x, y, 0, 0, mouse_Left); + + if (not waitFunc(@RD_BoxScreen, 50, 5000)) then + begin + addToSRLLog('RD_SolveBox: Reward box didn''t open'); + exit; + end; + + // avoid out of range from scripter error + if (length(players) > 0) then + boxRewards := players[currentPlayer].boxRewards; + + for i := 0 to (high(boxRewards) + 1) do + begin + // if no rewards were found, get the default + if (i = (high(boxRewards) + 1)) then + tmpReward := 'box' + else + tmpReward := boxRewards[i]; + + // loop through each slot, looking for the first reward choice + for slot := 1 to 6 do + if (RD_ClickBoxOption(tmpReward, slot, point(114, 101))) then + begin + result := true; + exit; + end; + + // if not found, scroll if possible + if (getColor(385, 70) = 592137) then // scroll bar exists + begin + RD_BoxScroll(); // scroll down + + for slot := 1 to 6 do + if (RD_ClickBoxOption(tmpReward, slot, point(110, 133))) then + begin + result := true; + exit; + end; + + RD_BoxScroll(); // scroll back up + end; + end; + end; +end; + +(** + * Author: Coh3n + * Description: Loops through the rewards DTMs. If one is found, calls the + * corresponding solve function. Returns true if solved. + * Now checks uptext before dropping the item and points the user to report false positives. + *) +function RD_Solve(): boolean; +var + i, x, y: integer; + DTMs: TIntegerArray; +begin + if (not loggedIn()) then + exit; + + DTMs := RD_GetDTMs(); + + for i := 0 to high(DTMs) do + if (findDTM(DTMs[i], x, y, MIX1, MIY1, MIX2, MIY2)) then + begin + case i of + DTM_REWARD_BOX : result := RD_SolveBox(x, y); + DTM_REWARD_MYSTERY : result := RD_SolveMystery(x, y); + DTM_REWARD_LAMP : result := RD_SolveLamp(x, y); + DTM_REWARD_BOOK : result := RD_SolveBook(x, y); + end; + + if (not result) then + begin + addToSRLLog('RD_Solve: Didn''t solve reward'); + MouseItem(coordsToItem(x, y), mouse_Move); + if (WaitUpTextMulti(['andom', 'event', 'ift', 'pen', 'amp', 'ook'], 618 + Random(200))) then + begin + addToSRLLog('RD_Solve: Dropping item as a failsafe'); + ClickMouse2(mouse_Right); + WaitOption('rop', 200+Random(800)); + end else + begin + addToSRLLog('RD_Solve: Falsely identified item: ' + GetUpText); + addToSRLLog('RD_Solve: Please report this at: http://villavu.com/forum/showthread.php?t=72956'); + end; + result := true; + end; + + break; + end; + + freeDTMs(DTMs); +end; diff --git a/SRL/core/antirandoms/sandwich.simba b/SRL/core/antirandoms/sandwich.simba new file mode 100644 index 0000000..16ba397 --- /dev/null +++ b/SRL/core/antirandoms/sandwich.simba @@ -0,0 +1,134 @@ +(* +Sandwich Lady +============= + +Stores all the routines to solve the Sandwich Lady random. None of these +routines should be used throughout scripts. They only need to be called in +SRL's random detection methods. + +This solver uses text recognition to determine which food to click, then uses +DTM finding to click the required food. + +*) + +const + DTM_SL_COUNT = 7; + DTM_SL_DONUT = 0; + DTM_SL_BAGUETTE = 1; + DTM_SL_SQUARE = 2; + DTM_SL_TRIANGLE = 3; + DTM_SL_ROLL = 4; + DTM_SL_PIE = 5; + DTM_SL_CHOCOLATE = 6; + +(** + * Author: DemiseScythe + * Description: Detects if a player is in the Sandwich Lady random. + *) +function SL_Detect(): boolean; +begin + result := (getNPCChatName = 'B50gwlo6l5gy') and (not tabExists(TAB_MAGIC)); +end; + +(** + * Author: DemiseScythe + * Description: Loads all needed DTMs to an integer array. + * Updated Pie DTM - [J]ustin - 24/05/2012 + *) +function SL_GetDTMs(): TIntegerArray; +begin + setLength(result, DTM_SL_COUNT); + + result[DTM_SL_DONUT] := DTMFromString('mrAAAAHic42BgYGiH4kYgrgDiPCAuBOJqIG4D4mtAfAGITwLxKSC+CMR3gPgREN8F6ckxZajJN2coyzJhaCyxZIgP0wKL5SQagMX5gWrwYUYCGAYApHMTqQ=='); + result[DTM_SL_BAGUETTE] := DTMFromString('mAAEAAHic42FgYNjCyMCwHYg3Q+kdQLwbiPcC8QYg3grEG4F4DRCvB+KHQD13gPgmEF8F4hNAfBqIjwDxUyB+CcTvgfgHEP8H4sUTYhiqMswY0sJ1GRb2RTMUJRoztBZaM6ydkcjQVeXHsH5WEkNNpjnD5KZghq0L0hj4gXpIwYwkYmQAALnFI/k='); + result[DTM_SL_SQUARE] := DTMFromString('mFQEAAHic42VgYDBkZGAwB2JbIDYCYl0gVgRiaSDWgIpZAbEDELsAsR0QTwDqawPiWiBuhtKtQDwViGcA8VwgXgxlg9R2A7GvizYYH+iRgbMJYX6gPlIxIxkYBQAAPBoU8Q=='); + result[DTM_SL_TRIANGLE] := DTMFromString('mwQAAAHic42RgYGBiZWD4zsLA8BeIuYFsaSBWA2JZIOYCYlYg7mFkYCgH4gIgLgXiCiCuAuIWIO4H4ilA7Oeiw9BT48+woDeKYV53JMOcrgiG2R3hDDnxtgyeDpoMNqZKDPxA+whhRiIwHAAAiHwSIA=='); + result[DTM_SL_ROLL] := DTMFromString('mAAEAAHic42FgYNgGxDuBeCMQr4TSK6Bi+4F4LxAfAOKjQHwciOcA8QQgXgzE84G4D4inAPFyIJ4KxHOh+hcA8QwQXS/OMLNKjGFCsShDZ64Iw7w6cYYVbRIMk0pEwexZ1WIMzZnCDH2FIgzLWiUY+IF6SMGMJGJkAABm7x6B'); + result[DTM_SL_PIE] := DTMFromString('mggAAAHicY2NgYNBiZGCQhWI1INYDYnMgnsgAwT1A3A2le4HY0c6OwcTQkEFPR4fBzMQEzPf38WEQAsphw4w4MAQAAMbbCNs='); + result[DTM_SL_CHOCOLATE] := DTMFromString('m6wAAAHic42ZgYIhgZGAIA+JMIHYH4mggjgHiBCAOAeIAII4D4kAgvgtUfwKILwLxCyD+AMRPgfg2EF8F4vtAfA6IXwFxiqU8GAfpSzKUuagyZNgogHGatQJDooUcWC7SWAbM5weqJxYzkoCRAABzRBYf'); +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Finds and clicks the correct food. + *) +function SL_ClickFood(DTMs: TIntegerArray): boolean; +var + i, t: integer; + foods: TStringArray; +begin + if (not loggedIn()) then + exit; + + foods := ['doughnut', 'baguette', 'square', 'triangle', 'roll', 'pie', 'chocolate']; + + // to avoid out of range errors + if (length(foods) <> length(DTMs)) then + begin + addToSRLLog('SL_ClickFood: Invalid foods or DTMs array'); + exit; + end; + + for i := 0 to high(foods) do + // the color of the text that tells you which food to take + if (findTextTPA(2070783, 15, MSX1, MSY1, MSX2, MSY2, foods[i], upCharsEx, nothing)) then + begin + addToSRLLog('SL_ClickFood: Need to click '+capitalize(foods[i])); + + t := (getSystemTime + 5000); + while ((not result) and (getSystemTime < t)) do + begin + if (clickDTMRotatedIn(DTMs[i], MSX1, MSY1, MSX2, MSY2, -Pi, Pi, Pi/30, ['hoose'], mouse_Left)) then + begin + addToSRLLog('SL_ClickFood: Clicked '+capitalize(foods[i])); + result := true; + end; + + wait(200 + random(300)); + end; + + break; + end; +end; + +(** + * Author: Coh3n & DemiseScythe + * Description: Solves the random. + *) +function SL_Solve(): boolean; +var + t, dtmPortal: integer; + DTMs: TIntegerArray; +begin + if (not loggedIn()) then + exit; + + t := (getSystemTime + (5 * 60000)); // maximum 5 minutes + dtmPortal := DTMFromString('mggAAAHicY2NgYNBjZGDQBmJVINYAYhMgtgDibUC5tUC8GYh3Q/FGIJ5zsp5h7qkGhvlnmhhmH61lmHagkmHmsRoGfqAcNsyIA0MAAArzEPs='); + DTMs := SL_GetDTMs(); + clickNorth(SRL_ANGLE_HIGH); + + repeat + if (findNPCChatTextMulti(['exit', 'ight'], nothing)) then + if (clickPortal(dtmPortal)) then + begin + result := true; + break; + end; + + if (not areTalking) then + begin + if (SL_ClickFood(DTMs)) then + wait(2000 + random(500)); + end else + clickContinue(true, true); // in case there are extra messages (GE) or we get one wrong + + until(result or (getSystemTime > t)); + + if (not result) then + addToSRLLog('SL_Solve: Sandwich Lady solver timed out'); + + freeDTM(dtmPortal); + freeDTMs(DTMs); +end; + diff --git a/SRL/core/autocolor.simba b/SRL/core/autocolor.simba new file mode 100644 index 0000000..206f704 --- /dev/null +++ b/SRL/core/autocolor.simba @@ -0,0 +1,360 @@ +(* +AutoColor +========= + +Auto color finding routines. + +.. contents:: + +*) +//-----------------------------------------------------------------// +//-- SRL Resource Library --// +//-- AutoColorFinding Routines --// +//-----------------------------------------------------------------// +// * procedure SetupAutoColors; +// * function LoadColorArray(Which: Integer): TIntegerArray; +// * function LoadAutoColor(which: Integer; var theAC: TAutoColorInfo): Boolean; +// * function AutoColorEx(which: Integer): TAutoColorInfo; +// * function AutoColor(which: Integer): Integer; +//-----------------------------------------------------------------// + +{ const AutoColor Constants; + Description: Constants representing the different types of AutoColors } +const + srl_AutoColorCount = 14; + srl_VarrockRoadColor = 0; + srl_LumbridgeRoadColor = 1; + srl_FaladorRoadColor = 2; + srl_AlKharidRoadColor = 3; + srl_DarkDirtRoadColor = 4; + srl_LightDirtRoadColor = 5; + srl_SandColor = 6; + srl_WaterColor = 7; + srl_SwampWaterColor = 8; + srl_LadderColor = 9; + srl_RockColor = 10; + srl_MineRockColor = 11; + srl_TreeColor = 12; + srl_BlackColor = 13; + +(* +SetupAutoColors +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SetupAutoColors; + +Need to initialize the global vars Which store information + +.. note:: + + Author: Nava2 + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + SetupAutoColors; +*) +procedure SetupAutoColors; +begin + setLength(acArr, srl_AutoColorCount); + setLength(isACLoaded, srl_AutoColorCount); +end; + +(* +LoadColorArray +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function LoadColorArray(Which: Integer): TIntegerArray; + +Returns a color array depending on the parameter Which. + +.. note:: + + Author: Coh3n + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + colArray := LoadColorArray(srl_VarrockRoadColor); +*) +function LoadColorArray(Which: Integer): TIntegerArray; +begin + case Which of + srl_VarrockRoadColor: + Result := [ 8620683, 8752269, 8489097, 8291717, 8160131, 8357511, 8818318, + 8949648, 8816777, 8422019, 8947853, 8555145, 8094342, 8686479, + 9013897, 8947848, 8487296, 9145489, 8947337, 9013386, 9013388, + 8355458, 8487043, 7960700 ]; + + srl_LumbridgeRoadColor: + Result := [ 7963536, 7568520, 6318195, 7832206, 8161171, 7634570, 8095122, + 7305605, 7766156, 7107969, 8095891, 7964305, 6977152, 7569290, + 7437960, 7832975, 8357520, 8226190, 8160140, 7106937, 8489106, + 7435903, 7702922, 7373956, 6847355, 6252912, 6186862, 7701377, + 8161929, 7964549, 7832963, 8359564, 7306361, 7503741 ]; + + srl_FaladorRoadColor: + Result := [ 7569029, 7306114, 7437443, 6976892, 6647670, 6450290, 6318704, + 6121068, 6581876, 7635079, 6910842, 7108478, 7240064, 5726310, + 5265501, 7831939, 7305081, 7173751, 8029318, 6844529, 7504518, + 7043967, 6583669, 7569021, 7700351, 8095623, 8226953, 6975865, + 6778229 ]; + + srl_AlKharidRoadColor: + Result := [ 6195595, 6327438, 6063495, 6525074, 6590868, 6656917, 6459024, + 6261644, 6327187, 6261137, 6129293, 6458773, 5931658, 6656666, + 6853530, 6852759, 6457486, 6789533 ]; + + srl_DarkDirtRoadColor: + Result := [ 1853017, 1786966, 1786452, 1918811, 1654093, 2049630, 2049116, + 2114904, 2115418 ]; + + srl_LightDirtRoadColor: + Result := [ 6784402, 7047575, 6652302, 6586508, 6520459, 6455952, 6390158, + 6653845, 6192778, 6060678, 6456974, 6720403, 6589073, 6127750, + 6586772, 6652566, 6784666, 6257293, 6326163, 6589592, 6655386, + 6261136, 5799813, 6063501, 6260882, 5865353, 6458011 ]; + + srl_SandColor: + Result := [ 8367041, 8103355, 8368321, 8566214, 6859196, 6133416, 6727353, + 7188934, 8829900, 8696521, 8630728, 6395825, 6857148, 6659512, + 6263724, 6988992, 5737886, 5605787, 4814213, 5409429, 5541273, + 5607323, 8435903, 8501953, 7124673, 5937826, 6927036, 8633796, + 8304060, 9224908, 7314081, 5869721 ]; + + srl_WaterColor: + Result := [ 10524303, 9603459, 10064009, 9142909, 8748408, 8617079, + 10655889, 10721682, 11180175, 10851211, 10127746, 10655624, + 10261123, 10063744, 10719630, 10588045, 9338236, 10327945, + 10262151, 10130566, 9670272, 8682096, 10917513, 11114892 ]; + + srl_SwampWaterColor: + Result := [ 6121029, 6515785, 6647370, 6384199, 6187848, 5858628, 5793600, + 6122820, 6252619, 5923399, 6121034, 6123596, 5728584, 5597509, + 5463361, 5331776, 5595720, 6450502, 6055490, 6122571, 5793351, + 6123082, 5728070, 6189387, 5794631, 6383946, 6054726 ]; + + srl_LadderColor: + Result := [ 405597, 207703, 405078, 470616, 601431, 404825, 339287, 338262, + 404569, 470108, 208989, 274010, 338780, 601175, 272982, 208733, + 536151, 272730, 208215, 339037, 405596, 601944, 207958, 601949, + 405852, 340822, 798806, 143195, 403800, 404566 ]; + + { The color of the rocks found on the Minimap. This also works with the + GRAY mine rocks. } + srl_RockColor: + Result := [ 5725020, 4474183, 3685438, 2829872, 5987671, 4736834, 3948089, + 4539973, 5855580, 3815998, 4604743 ]; + + { The REDish color of the rocks in a mine on the minimap. Use srl_RockColor + for the GRAY mine rocks. } + srl_MineRockColor: + Result := [ 3100807, 2573687, 2573941, 3101061, 2177633, 2706292, 3233412, + 2309984, 2770298, 3297418, 2373990, 2509689, 3036809, 2971525, + 2444405, 2048097, 2971271, 2444151, 2047843 ]; + + srl_TreeColor: + Result := [ 2121284, 1463332, 1527603, 1333281, 1267488, 1202468, 999966 ]; + + srl_BlackColor: + Result := [ 460550, 460033, 459776, 458757, 395015, 329476, 328454, 328194, + 263170, 262145, 197895, 197120, 132096, 131075, 198151, + 1792, 1539, 1286, 1030]; + + else + srl_Warn('AutoColor', + 'Index ''' + IntToStr(Which) + ''' is not a valid SRL AutoColor.', + warn_AllVersions); + end; +end; + +(* +LoadAutoColor +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function LoadAutoColor(which: Integer; var theAC: TAutoColorInfo): Boolean; + +Finds the color on the minimap depending on the parameter which. + +.. note:: + + Author: Nava2 & Coh3n + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + foundColor := LoadAutoColor(srl_VarrockRoadColor, var_AutoColor); +*) +function LoadAutoColor(which: Integer; var theAC: TAutoColorInfo): Boolean; +var + X, Y, Z: Extended; + R, G, B: Integer; + foundCols, newCols: TIntegerArray; + functTime, curCTS, h, i, c: Integer; + validPts, t: TPointArray; +begin + functTime := GetTimeRunning; + + if (not LoggedIn) then + Exit; + + if (not InRange(which, 0, (srl_AutoColorCount - 1))) then + begin; + srl_Warn('LoadAutoColor', 'Index ''' + IntToStr(which) + ''' is not a valid AutoColor. ', warn_AllVersions); + Exit; + end; + + acArr[which] := CreateAutoColorInfo(LoadColorArray(which)); + //srl_warn('LoadAutoColor', 'Rough AutoColor = ' + IntToStr(acArr[which].Color) + ' ', warn_AllVersions); + with acArr[which] do + begin + curCTS := GetColorToleranceSpeed; + ColorToleranceSpeed(2); + { + Find the colours which match the TAutoColorInfo and filter out points that + are not part of the minimap using RemoveDistTPointArray + } + SetColorSpeed2Modifiers(hueMod, satMod); + FindColorsTolerance(t, color, MMX1, MMY1, MMX2, MMY2, lumTol); + validPts := RemoveDistTPointArray(MMCX, MMCY, (MMX2 - MMCX), t, True); + //debugTPA(validPts, ''); + + SetColorSpeed2Modifiers(0.2, 0.2); + ColorToleranceSpeed(curCTS); + + { + This is because the ladder color is much more specific and all that is + required is to check if it's on the minimap + } + if (which = srl_LadderColor) and (Length(validPts) > 0) then + begin + Result := true; + theAC := acArr[which]; + srl_Warn('LoadAutoColor', 'Function Successful: Found Color = ' + IntToStr(theAC.Color) + ' ', warn_AllVersions); + Exit; + end; + + if (Length(validPts) = 0) then + begin + srl_Warn('LoadAutoColor', 'Length(t) = 0 ', warn_AllVersions); + Exit; + end; + + foundCols := GetColors(validPts); + ClearSameIntegers(foundCols); + { + Cycle through the colors found on the minimap, creating a new array based + on their RGB/XYZ ranges + } + h := High(foundCols); + SetLength(newCols, h + 1); + for i := 0 to h do + begin + ColorToRGB(foundCols[i], R, G, B); + + if (R >= MinR) and (R <= MaxR) and (G >= MinG) and (G <= MaxG) and + (B >= MinB) and (B <= MaxB) then + begin + ColorToXYZ(foundCols[i], X, Y, Z); + + if (X >= MinX) and (X <= MaxX) and (Y >= MinY) and (Y <= MaxY) and + (Z >= MinZ) and (Z <= MaxZ) then + begin + newCols[c] := foundCols[i]; + Inc(c); + end; + end; + end; + + Dec(c); + SetLength(newCols, c); + + if (Length(newCols) > 0) then + begin + acArr[which] := CreateAutoColorInfo(newCols); + theAC := acArr[which]; + result := True; + srl_Warn('LoadAutoColor', 'Function Successful: Found Color = ' + IntToStr(theAC.Color) + ' ', warn_AllVersions); + end else + srl_Warn('LoadAutoColor', 'Couldn''t Find Color Index ' + IntToStr(which) + ', using rough color ', warn_AllVersions); + end; + + //srl_Warn('LoadAutoColor', 'Took: ' + IntToStr(GetTimeRunning - functTime) + 'ms ', warn_AllVersions); +end; + +(* +AutoColorEx +~~~~~~~~~~~ + +.. code-block:: pascal + + function AutoColorEx(i: Integer): TAutoColorInfo; + +Check the isACLoaded boolean for the asked AC, if true, we know the + AutoColorInfo has been loaded, and we will not do it again. + Otherwise, load the initial TAutoColorInfo from the stored array of + colours. + +.. note:: + + Author: Nava2 & Coh3n + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + var_AutoColor := AutoColorEx(srl_VarrockRoadColor); +*) +function AutoColorEx(which: Integer): TAutoColorInfo; +begin + if isACLoaded[which] then + result := acArr[which] + else + begin + if (LoadAutoColor(which, result)) then + begin + acArr[which] := result; + isACLoaded[which] := True; + end else + result := acArr[which]; + end; +end; + +(* +AutoColor +~~~~~~~~~ + +.. code-block:: pascal + + function AutoColor(i: Integer): Integer; + +Returns the correct color based on the autocolor constant + +.. note:: + + Author: Coh3n + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + Color := AutoColor(srl_VarrockRoadColor); +*) +function AutoColor(which: Integer): Integer; +begin + Result := AutoColorEx(which).Color; +end; diff --git a/SRL/core/bank.simba b/SRL/core/bank.simba new file mode 100644 index 0000000..b1c1728 --- /dev/null +++ b/SRL/core/bank.simba @@ -0,0 +1,2287 @@ +(* +Bank +==== + +The Bank include contains Bank finders, and all banking routines. + +Normal Banks: +'feb' = Falador East Bank +'fwb' = Falador West Bank +'veb' = Varrock East Bank +'vwb' = Varrock West Bank +'geb' = Varrock GE Bank +'db' = Draynor Bank +'akb' = Al-Kharid Bank +'eb' = Edgeville Bank +'ctb' = Catherby bank +'clt' = Camelot bank +'nab' = North Ardougne bank +'sab' = South Ardougne bank +'ynb' = Yanille bank +'ngb' = North gnome bank +'sgb' = South gnome bank +'wgb' = Warrior guild bank +'fgb' = Fishing guild bank + +Special Bank: +SRL_BANK_SW = Soul Wars chest +SRL_BANK_CW = Castle Wars chest +SRL_BANK_B = Burthrope chest (outside warriors guild) +SRL_BANK_GG = Gamer's Grotto (north of Falador) +SRL_BANK_SP = Shantay Pass chest + +.. contents:: + +*) + +const + Bank_FE = 'feb'; // (Falador East Bank) + Bank_FW = 'fwb'; // (Falador West Bank) + Bank_VE = 'veb'; // (Varrock East Bank) + Bank_VW = 'vwb'; // (Varrock West Bank) + Bank_GE = 'geb'; // (Varrock GE Bank) + Bank_DR = 'db' ; // (Draynor Bank) + Bank_AK = 'akb'; // (Al-Kharid Bank) + Bank_EV = 'eb' ; // (Edgeville Bank) + Bank_CT = 'ctb'; // (Catherby bank) + Bank_CM = 'clt'; // (Camelot bank) + Bank_NA = 'nab'; // (North Ardougne bank) + Bank_SA = 'sab'; // (South Ardougne bank) + Bank_YN = 'ynb'; // (Yanille bank) + Bank_NG = 'ngb'; // (North gnome bank) + Bank_SG = 'sgb'; // (South gnome bank) + Bank_WG = 'wgb'; // (Warrior guild bank) + Bank_FG = 'fgb'; // (Fishing guild bank) + + SRL_BANK_SW = 20; // Soul Wars chest + SRL_BANK_CW = 21; // Castle Wars chest + SRL_BANK_B = 22; // Burthrope chest (outside warriors guild) + SRL_BANK_GG = 23; // Gamer's Grotto (north of Falador) + SRL_BANK_SP = 24; // Shantay Pass chest + +(* +BankScreen +~~~~~~~~~~ + +.. code-block:: pascal + + function BankScreen: Boolean; + +Finds Bankscreen. Returns true if Found. + +.. note:: + + Author: SRL Dev Team + Last Modified: Feb. 14th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + BankOpen := BankScreen; +*) +function BankScreen: Boolean; +begin + result := findTextTPA(4106994, 20, 20, 22, 400, 45, 'Bank', upCharsEx, nothing); +end; + +(* +DepositScreen +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function DepositScreen: Boolean; + +Returns true if deposit screen is Found. + +.. note:: + + Author: Shuttleu + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + BankOpen := (not DepositScreen); +*) +function DepositScreen: Boolean; +var + X, Y: Integer; +begin + Result := FindText(x, y, 'Deposit Box', UpCharsEx, 92, 29, 396, 54); +end; + +(* +PinScreen +~~~~~~~~~ + +.. code-block:: pascal + + function PinScreen: Boolean; + +Finds Pin Screen. Returns true if Found. + +.. note:: + + Author: Naum + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if PinScreen then + InPin(); +*) +function PinScreen : Boolean; +begin + Result := FindTextTPA(2070783, 0, 105, 62, 150, 75, 'Please', UpCharsEx, Nothing); +end; + +(* +ClosePinScreen +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClosePinScreen: Boolean; + +Results true is PinScreen is not open. + +.. note:: + + Author: SRL + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if PinScreen then + Result := ClosePinScreen; +*) +function ClosePinScreen: Boolean; +var + Timer : Integer; +begin + Result := False; + Timer := GetSystemTime + 10000; + while PinScreen do + begin + if Timer > GetSystemTime then + Break; + MouseBox(332, 258, 489, 281, mouse_left); + Wait(500); + end; + Result := not PinScreen; +end; + +(* +InPin +~~~~~ + +.. code-block:: pascal + + function Inpin(Pin: string): Boolean; + +Enters bank pin. Will try 3 times, returns true if bank is opened. + +.. note:: + + Author: ZephyrsFury and Nava2 + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if PinScreen then + InPin('1234'); +*) +function InPin(Pin: string): Boolean; +var + Tx, Ty, X, Y, H, I, J, Tries, ColorCount : Integer; + Boxes: array of TBox; +begin + Result := False; + if not PinScreen then Exit; + + if (GetNumbers(Pin) <> Pin) then + begin + srl_Warn('InPin', '''' + Pin + ''' is not a valid Pin', warn_AllVersions); + Exit; + end; + if (Length(Pin) <> 4) then + begin + srl_Warn('InPin', 'Pin must be 4 digits long', warn_AllVersions); + Exit; + end; + + Boxes := [IntToBox(37, 107, 100, 170), IntToBox(127, 107, 190, 170), IntToBox(217, 107, 280, 170), IntToBox(307, 107, 370, 170), + IntToBox(37, 179, 100, 242), IntToBox(127, 179, 190, 242), IntToBox(217, 179, 280, 242), + IntToBox(37, 251, 100, 314), IntToBox(127, 251, 190, 314), IntToBox(217, 251, 280, 314)]; + + while PinScreen do + begin + for I := 1 to 4 do + begin + if not PinScreen then Break; + + ColorCount := CountColorTolerance(clWhite, 150, 80, 380, 100, 10); + // Counts the "Now click the NUM_X digit.". This is used later on. + + GetMousePos(X, Y); + if (FindText(Tx, Ty, Pin[I], UpCharsEx, 30, 100, 383, 319)) then + begin + H := High(Boxes); + for J := 0 to H do + if IntInBox(Tx, Ty, Boxes[J]) then + begin + with Boxes[J] do + if PinScreen then + MouseBox(x1, y1, x2, y2, mouse_left); + Break; + end; + end else + begin + H := High(Boxes); + for J := 0 to H do + if IntInBox(X, Y, Boxes[J]) then + begin + with Boxes[J] do + if PinScreen then + MouseBox(x1, y1, x2, y2, mouse_left); + Break; + end; + end; + + Wait(100); + while (CountColorTolerance(clWhite, 150, 80, 380, 100, 10) = ColorCount) do + Wait(500); + + Wait(RandomRange(300, 600)); + + if BankScreen or not PinScreen then + begin + Result := True; + Exit; + end; + end; + + WaitFunc(@BankScreen, 50, 300); + + ClickContinue(True, True); + while not FindColor(Tx, Ty, 0, 7, 460, 69, 474) do + begin + Wait(500); + if not LoggedIn then + Exit; + end; + Inc(Tries); + + if Tries > 2 then + begin + srl_Warn('InPin', '''' + Pin + ''' is not the correct Pin', warn_AllVersions); + ClosePinScreen; + Exit; + end; + + end; + Result := BankScreen; +end; + +(* +MSTPointToBankPoint +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function MSTPointToBankPoint(P: TPoint): TPoint; + +Converts a point on the Mainscreen to the point in the Bank. + +.. note:: + + Author: Wizzup + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + ItemSlot := MSTPointToBankPoint(Point); +*) +function MSTPointToBankPoint(MSP: TPoint): TPoint; +begin + Result.X := (MSP.X - 38) div 44; + Result.Y := (MSP.Y - 90) div 45; +end; + +(* +BankPointToBankIndex +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function BankPointToBankIndex(P: TPoint): Integer; + +Converts a Bank Point (Row,Col) to Bank Index (spot in bank). (0, 0) = 1 + +.. note:: + + Author: Wizzup? + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + BankSlot := BankPointToBankIndex(itemPoint); +*) +function BankPointToBankIndex(P: TPoint): Integer; +begin + Result := P.Y * 10 + P.X + 1; +end; + +(* +BankIndexToBankPoint +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function BankIndexToBankPoint(ind: Integer): TPoint; + +Converts the Bank Index (spot in bank) to a Bank Point (Row,Col). 1 = (0, 0) + +.. note:: + + Author: Wizzup? + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + BankPoint := BankIndexToBankPoint(index); +*) +function BankIndexToBankPoint(Index: Integer): TPoint; +begin + Index := Index - 1; + Result := Point((Index mod 10), Floor(Index div 10)); +end; + +(* +BankIndexToMSPoint +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function BankIndexToMSPoint(Index: Integer): TPoint; + +Converts the Bank Index (spot in bank) to a Mainscreen TPoint of the Index. (Top Left) + +.. note:: + + Author: Wizzup? + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + msPoint := BankIndexToMSPoint(index); +*) +function BankIndexToMSPoint(Index: Integer): TPoint; +begin + Index := Index - 1; + Result := Point(38 + (Index mod 10) * 44, 90 + Floor(Index div 10) * 45); +end; + +(* +BankIndexToMSBox +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function BankIndexToMSBox(Ind: Integer): TBox; + +Converts the Bank Index (spot in bank) to a Mainscreen TBox of the Index. + +.. note:: + + Author: Wizzup? + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + msBox := BankIndexToMSBox(index); +*) +function BankIndexToMSBox(Index: Integer): TBox; +var + P: TPoint; +begin + P := BankIndexToMSPoint(Index); + Result.X1 := P.X; + Result.Y1 := P.Y; + Result.X2 := Result.X1 + 31; + Result.Y2 := Result.Y1 + 32; +end; + +(* +GetBankItemAmount +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetBankIndexItemAmount(const Index: Integer): Integer; + +Returns the amount of an item in the bank at bank index, Index. + +.. note:: + + Author: Daniel + Last Modified: Jan. 03, 2012 by Daniel + +Example: + +.. code-block:: pascal + + amt := GetBankIndexItemAmount(13); +*) +function GetBankIndexItemAmount(const Index: Integer): Integer; +begin + Result := getAmountBox(BankIndexToMSBox(Index)); +end; + +(* +GetBankItemAmount +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetBankItemAmount(const Row, Col: Integer): Integer; + +Returns the amount of an item in the bank at bank screen coordinates (Row, Col). + +.. note:: + + Author: Daniel + Last Modified: Jan. 03, 2012 by Daniel + +Example: + +.. code-block:: pascal + + amt := GetBankItemAmount(0, 5); +*) +function GetBankItemAmount(const Row, Col: Integer): Integer; +begin + Result := GetBankIndexItemAmount(BankPointToBankIndex(Point(Row, Col))); +end; + +(* +GetMSBankItemAmount +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetMSBankItemAmount(const x, y: Integer): Integer; + +Returns the amount of an item in the bank at main screen coordinates x, y. + +.. note:: + + Author: Daniel + Last Modified: Jan. 03, 2012 by Daniel + +Example: + +.. code-block:: pascal + + amt := GetMSBankItemAmount(250, 100); +*) +function GetMSBankItemAmount(const x, y: Integer): Integer; +begin + Result := GetBankIndexItemAmount(BankPointToBankIndex(MSTPointToBankPoint(Point(x, y)))); +end; + +(* +DepositItemBox +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function DepositItemBox(Item: Integer): TBox; + +Returns a TBox surround Item (1 to 28) in the Deposit Box screen. + +.. note:: + + Author: ZephyrsFury + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + currentItem := DepositItemBox(itemSlot); +*) +function DepositItemBox(Item: Integer): TBox; +begin + Result.X1 := 97 + (Item - 1) mod 7 * 48; + Result.Y1 := 60 + (Item - 1) div 7 * 50; + Result.X2 := Result.X1 + 48; + Result.Y2 := Result.Y1 + 50; +end; + +(* +FixBank +~~~~~~~ + +.. code-block:: pascal + + procedure FixBank; + +Scrolls the bank screen up. + +.. note:: + + Author: lordsaturn, Nava2, IceFire908 & Bixby Sayz + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + FixBank; +*) +procedure FixBank; +var + Timer : Integer; +begin + if (SimilarColors(GetColor(481, 110), 723981, 20)) then + if (BankScreen) then + if (not (SimilarColors(GetColor(489, 101), 1316634, 5))) then + begin + Timer := GetTimeRunning + 5000; + MouseBox(482, 101, 488, 111, mouse_left); + while ((not (SimilarColors(GetColor(489, 101), 1316634, 5))) and (GetTimeRunning < Timer)) do + Wait(50 + Random(50)); + Wait(RandomRange(100, 200)); + end; +end; + +(* +FixBankTab +~~~~~~~~~~ + +.. code-block:: pascal + + procedure FixBankTab; + +Fixes the BankTab to 'View All' + +.. note:: + + Author: Wizzup? + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if FixBankTab then + SearchForItem; +*) +function FixBankTab: Boolean; +var + activeTPA, notactiveTPA: TPointArray; + T: Integer; +begin + Result := False; + FindColorsTolerance(activeTPA, 2896954, 25, 45, 70, 80, 5); + FindColorsTolerance(notactiveTPA, 2437688, 25, 45, 70, 80, 5); + + if Length(activeTPA) > Length(notactiveTPA) then + begin + Result := True; + Exit; + end; + + Mouse(40, 60, 10, 10, mouse_left); + T := GetSystemTime; + while Length(activeTPA) <= Length(notactiveTPA) do + begin + FindColorsTolerance(activeTPA, 2896954, 25, 45, 70, 80, 5); + FindColorsTolerance(notactiveTPA, 2437688, 25, 45, 70, 80, 5); + Wait(500); + if ((GetSystemTime - T) div 1500) mod 2 = 0 then + Mouse(40, 60, 10, 10, mouse_left); + if GetSystemTime - T > 10000 then + Exit; + end; +end; + +(* +CurrentBankTab +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function CurrentBankTab: Integer; + +Returns Current Bank Tab selected + +.. note:: + + Author: Narcle + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + curTab := GetCurrentBankTab; +*) +function CurrentBankTab: Integer; +begin + Result := -1; + if not BankScreen then + Exit; + for Result := 1 to 9 do + if GetColor(40 + 48 * (Result - 1), 83) = 2831161 then //Left of the bottom boundary of the tab + Exit; + Result := 0; +end; + +(* +ExistsBankTab +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ExistsBankTab(T: Integer): Boolean; + +Returns true if Bank Tab Exists + +.. note:: + + Author: Narcle + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if ExistsBankTab(2) then + BankTab(2); +*) +function ExistsBankTab(T: Integer): Boolean; +var + x, y: integer; +begin + Result := False; + if not BankScreen then + begin + srl_Warn('ExistsBankTab', 'Bank not open.', warn_AllVersions); + Exit; + end; + if (not(InRange(T, 1, 9))) then + begin + srl_Warn('ExistsBankTab', 'Bank Tab: ' + IntToStr(T) + ' is not possible (1..9) only.', warn_AllVersions); + Exit; + end; + if T = 1 then + Result := true; + + if FindColor(x, y, srl_outline_black, 27+(T-1)*48, 51, 70+(T-1)*48, 81) then + Result := true; +end; + +(* +BankTab +~~~~~~~ + +.. code-block:: pascal + + function BankTab(T: Integer): Boolean; + +If Bank Tab is there will switch to it. + +.. note:: + + Author: Narcle + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if ExistsBankTab(2) then + BankTab(2); +*) +function BankTab(T: Integer): Boolean; +begin + result := false; + if not BankScreen then + Exit; + + if T = CurrentBankTab then + Begin + Result := true; + Exit; + end; + + if not ExistsBankTab(T) then + srl_Warn('BankTab', 'Bank Tab '+inttostr(T) +' does not Exist.', warn_AllVersions) + else + Mouse(48 * T, 57, 10, 10, mouse_left); + + Result := T = CurrentBankTab; +end; + +(* +SearchBank +~~~~~~~~~~ + +.. code-block:: pascal + + procedure SearchBank(Item: string); + +Searches for Item in your bank. + +.. note:: + + Author: ZephyrsFury + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + SearchBank('air rune'); + if FindDTM(..) then +*) +procedure SearchBank(Item: string); +var + T, II: Integer; +begin + if (not(BankScreen)) then Exit; + for II := 0 to 2 do + begin + FixBankTab; + Mouse(75, 300, 20, 10, mouse_left); + T := GetSystemTime; + while (BankScreen) and (GetSystemTime - T < 5000) do + begin + Wait(500 + Random(500)); + if (FindTextTpa(0, 0, 350, 392, 399, 410, 'search', UpCharsEx, Nothing)) then + begin + TypeSend(Item); + Exit; + end; + end; + Wait(500 + Random(500)); + end; +end; + +(* +MouseBankSlot +~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure MouseBankSlot(BankSlot, Action: integer); + +.. note:: + + by Fwd Motion + Last Modified: Feb. 09, 2012 by Fwd Motion + +Example: + +.. code-block:: pascal + + MouseBankSlot(1, mouse_Right); + if (WaitOption('ithdraw-All', 500)) then + Writeln('Withdrew item'); +*) +procedure MouseBankSlot(BankSlot, Action: integer); +var + BankBox: TBox; + X, Y: Integer; +begin + BankBox := BankIndexToMSBox(BankSlot); + GetMousePos(X, Y); + if (not PointInBox(Point(X, Y), BankBox)) then + MouseBox(BankBox.X1, BankBox.Y1, BankBox.X2, BankBox.Y2, Action); +end; + +(* +QuickDeposit +~~~~~~~~~~~~ + +.. code-block:: pascal + + function QuickDeposit(Which: Integer): Boolean; + +Uses the quick deposit buttons in the bottom right of the bank. Valid +arguments for 'Which' are: + * SRL_DEPOSIT_ALL + * SRL_DEPOSIT_COINS + * SRL_DEPOSIT_EQUIPMENT + * SRL_DEPOSIT_FOLLOWER + +.. note:: + + Author: ZephyrsFury & Quickmarch & Shuttleu + Last Modified: January 08, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + QuickDeposit(SRL_DEPOSIT_COINS); +*) +const + SRL_DEPOSIT_ALL = 0; + SRL_DEPOSIT_COINS = 1; + SRL_DEPOSIT_EQUIPMENT = 2; + SRL_DEPOSIT_FOLLOWER = 3; + +procedure QuickDeposit(Which: Integer); +var + StartX: Integer; +begin + if (BankScreen) or (DepositScreen) then + begin + case Which of + SRL_DEPOSIT_ALL: StartX := 362; + SRL_DEPOSIT_EQUIPMENT: StartX := 395; + SRL_DEPOSIT_FOLLOWER: StartX := 431; + SRL_DEPOSIT_COINS: StartX := 467; + + else + SRL_Warn('QuickDeposit', 'Invalid deposit method ', WARN_ALLVERSIONS); + end; + + Mouse(StartX - 58 * Ord(DepositScreen), 303 - 29 * Ord(DepositScreen), 15, 10, True); + Wait(200 + Random(300)); + end; +end; + +(* +DepositAll +~~~~~~~~~~ + +.. code-block:: pascal + + function DepositAll: Boolean; + +Deposits all items in your inventory. + +.. note:: + + Author: Shuttleu + Last Modified: January 08, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + DepositAll(); +*) +function DepositAll: Boolean; +begin + if (InvEmpty) then + begin + Result := True; + Exit; + end; + + QuickDeposit(SRL_DEPOSIT_ALL); + Result := WaitFunc(@InvEmpty, 50, 3000); +end; + +(* +Deposit +~~~~~~~ + +.. code-block:: pascal + + Procedure Deposit(SlotFrom, SlotTo: Integer; vType: Variant); + + Deposits from Slot to ToSlot. + vType True = Deposit All. vType False = Deposit one by one. + Any integer is deposit with Deposit X. (except for 5 and 10) + +.. note:: + + Author: WT-Fakawi/PPLSUQBAWLZ/Stupid3ooo/Town + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + Deposit(1, 28, True); +*) +procedure Deposit(SlotFrom, SlotTo: Integer; vType: Variant); +var + DepositX, BScreen, DScreen: Boolean; + All: Variant; + I, T, x, y: Integer; + B: TBox; +begin + BScreen := BankScreen; + if (not(BScreen)) then + DScreen := DepositScreen; + if not (BScreen or DScreen) then + Exit; + if vType = 2 then + srl_Warn('Deposit', '2 now means store per 2, not ''All''', 15); + DepositX := False; + if VariantIsInteger(vType) then + begin + DepositX := not InIntArray([1, 5, 10], vType); + All := vType <> 1; + end + else if VariantIsBoolean(vType) then + All := vType; + if (SlotFrom = 1) and (SlotTo = 28) and (All = true) then + if DepositAll then + exit; + for I := SlotFrom to SlotTo do + begin + if (BScreen) then + begin + If Not ExistsItem(I) Then + Continue; + if (not All) then + MouseItem(I, mouse_left) + else + MouseItem(I, mouse_right); + end else + begin + B := DepositItemBox(I); + if (not(FindColor(X, Y, srl_outline_black, B.X1, B.Y1, B.X2, B.Y2))) then + Continue; + if (not All) then + Mouse((B.X1 + B.X2) shr 1, (B.Y1 + B.Y2) shr 1, 0, 0, mouse_left) + else + Mouse((B.X1 + B.X2) shr 1, (B.Y1 + B.Y2) shr 1, 0, 0, mouse_right); + end; + if DepositX then + begin + WaitOptionMulti(['Deposit-X', 'Deposit'], 200); + T := GetSystemTime; + while (not FindColor(x, y, 8388608, MCX1, MCY1, MCX2, MCY2)) and (GetSystemTime - T < 3000) do + Wait(100); + TypeSend(vType); + end else if VariantIsInteger(vType) then + WaitOptionMulti(['Deposit-' + IntToStr(Integer(vType)), 'Deposit'], 200) + else + if not WaitOptionMulti(['Deposit-All', 'All'], 200) then + ChooseOptionMulti(['Deposit' , 'osit']); + T := GetSystemTime; + Wait(RandomRange(200, 300)); + repeat + if (BScreen) then + if (not(ExistsItem(I))) then Break; + if (DScreen) then + if (not(FindColor(X, Y, srl_outline_black, B.X1, B.Y1, B.X2, B.Y2))) then Break; + Wait(50); + until(GetSystemTime - T > 2000); + end; +end; + +(* +WithdrawEx +~~~~~~~~~~ + +.. code-block:: pascal + + function WithdrawEx(Col, Row, Amount: Integer; Uptexts: TStringArray): Boolean; + +Withdraws Amount at Column/Row. + +.. note:: + + Author: Starblaster100, Town, Wizzup? and Narcle, small fixes by r!ch!e & EvilChicken! + Last Modified: riwu (19 Jan 2013) + +Example: + +.. code-block:: pascal + + WithdrawEx(1, 3, 28, ['ron ore', 'ore', 'on or']); +*) +function WithdrawEx(Col, Row, Amount: Integer; Uptexts: TStringArray): Boolean; +var + BBox: TBox; + X, Y: Integer; +begin + Result := False; + FixBank; + + BBox := BankIndexToMSBox(BankPointToBankIndex(Point(Col, Row))); + GetMousePos(X, Y); + if (not PointInBox(Point(X, Y), BBox)) then + MouseBox(BBox.X1 + 5, BBox.Y1 + 5, BBox.X2 - 5, BBox.Y2 - 5, mouse_move); + + if (Length(Uptexts) > 0) then + if (not WaitUptextMulti(Uptexts, 500)) then + Exit; + + if (Amount = 1) then + ClickMouse2(mouse_left) + else + ClickMouse2(mouse_right); + if (Amount = 1) then + begin + Result := True; + Wait(RandomRange(250, 550)); + Exit; + end; + + if (Amount = -1) then + begin + if (WaitOptionMultiEx(['Withdraw-All but', 'l b'], 'All', Nothing, 300)) then + Result := ChooseOptionMulti(['Withdraw-All but', 'l b']); + end else + if (Amount = 0) then + begin + if (WaitOptionMultiEx(['Withdraw-All', 'w-A'], 'All', Nothing, 300)) then + Result := ChooseOptionMulti(['Withdraw-All', 'w-A']); + end else + if (WaitOptionMultiEx(['Withdraw-' + IntToStr(Amount) + ' ', 'w-' + IntToStr(Amount) + ' '], 'All', Nothing, 300)) then + Result := ChooseOptionMulti(['Withdraw-' + IntToStr(Amount) + ' ', 'w-' + IntToStr(Amount) + ' ']); + + if (not (Result)) and (Amount > 0) then + begin + if (not OptionsExist(['Withdraw', 'ithdraw', 'draw'], False)) then + MouseBox(BBox.X1 + 5, BBox.Y1 + 5, BBox.X2 - 5, BBox.Y2 - 5, mouse_right); + + if WaitOptionMulti(['Withdraw-X', 'w-X'], 500) then + begin + X := GetSystemTime + 10000; + while (X >= GetSystemTime) and (not (InRange(CountColor(0, 250, 396, 307, 410), 155, 165))) do + Wait(50); + Wait(RandomRange(75, 400)); + TypeSend(IntToStr(Amount)); + Result := True; + end; + end; +end; + +(* +Withdraw +~~~~~~~~ + +.. code-block:: pascal + + function Withdraw(Col, Row, Amount: Integer): Boolean; + +Withdraws Amount at Column/Row. Column/Row start at 0. Columns are left/right - Rows are up/down. + +.. note:: + + Author: Starblaster100, Town, Wizzup? and Narcle + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + Withdraw(0, 0, 28) withdraws 28 of the item in the upper-left most bank slot. +*) +function Withdraw(col, row, Amount: Integer): Boolean; +begin + Result := WithdrawEx(Col, Row, Amount,[]); +end; + +(* +WithdrawItemEx +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WithdrawItemEx(Ident: integer; IdentType: string; var Index: integer; + Amount: integer; UpText: String; Tol: TIntegerArray): boolean; + +Withdraws an item from the bank by using "Ident" with tol[0] +as color tolerance, tol[1] as contour tolerance in case of bmp +masks, or the count of colors for TPA item finding. +Valid IdentTypes are all in FindItem. + +Index: + + The Bank Index where the item is found, must be a variable. + Speeds up future withdraws. + +Amount: + + Amount to withdraw from bank. + +UpText: + + The UpText which the function checks for. + +.. note:: + + Author: Nava2 + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if WithdrawItemEx(theColor, 'color', itemSlot, 27, 'ew log', [3]) then + CloseBank; +*) +function WithdrawItemEx(Ident: integer; IdentType: string; var Index: integer; Amount: integer; UpText: string; Tol: TIntegerArray): Boolean; +var + x, y: integer; + BPoint: TPoint; + BankBox: TBox; + Found: Boolean; + t: TPointArray; +label + Start; +begin + Result := False; + if not BankScreen then Exit; + FixBank; + + if (Index = 0) then + begin + Start: + for Index := 1 to 50 do + begin + if FindItemEx(x, y, IdentType, Ident, BankIndexToMSBox(Index), Tol) then + begin + MMouse(x, y, 4, 4); + if WaitUpText(UpText, 300) then + begin + Writeln('Found Item at Bank Slot ' + IntToStr(Index) + '.'); + Found := True; + Break; + end else + Writeln('Found Incorrect Item, Moving to new Bank Spot.'); + end; + end; + end else + begin + BankBox := BankIndexToMSBox(Index); + FindColors(t, srl_outline_black, BankBox.x1, BankBox.y1, BankBox.x2, BankBox.y2); + BankBox := GetTPABounds(t); + MouseBox(BankBox.x1, BankBox.y1, BankBox.x2, BankBox.y2, mouse_move); + if WaitUpText(UpText, 300) then + Found := true + else + begin + Writeln('Item Moved from Bank Slot ' + IntToStr(Index) + ', checking bank again.'); + goto Start; + end; + end; + Wait(RandomRange(200, 350)); + if Found then + begin + BPoint := BankIndexToBankPoint(Index); + //Writeln(IntToStr(BPoint.x) + ', ' + IntToStr(BPoint.y)); + Withdraw(BPoint.x, BPoint.y, Amount); + Result := True; + end else + begin + Index := 0; + SRL_Warn('WithdrawItem', 'Could not Find ' + IdentType + ' in Bank. [Uptext: ' + UpText + ']', Warn_AllVersions); + end; +end; + +(* +WithdrawItem +~~~~~~~~~~~~ + +.. code-block:: pascal + + function WithdrawItem(Ident: integer; IdentType: string; Amount: integer; + UpText: TStringArray; Tol: TIntegerArray): boolean; + +Withdraws an item using WithdrawItemEx, but removes the Index check. + +.. note:: + + Author: Nava2 + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if WithdrawItem(theColor, 'color', 27, ['ew log', 'ew l'], [3]) then + CloseBank; +*) +function WithdrawItem(Ident: integer; IdentType: string; Amount: integer; UpText: String; Tol: TIntegerArray): boolean; +var + I : Integer; +begin + Result := WithdrawItemEx(Ident, IdentType, I, Amount, UpText, Tol); +end; + +(* +Notes +~~~~~ + +.. code-block:: pascal + + procedure Notes(SwitchOn: Boolean); + +Toggles note withdrawal on or off. + +.. note:: + + Author: lordsaturn, idea by R1ch + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + Notes(True); + Withdraw(Col, Row, 100); +*) +procedure Notes(SwitchOn: Boolean); +begin + if BankScreen then + if (getColor(225, 302) = 0) xor switchOn then + Mouse(228, 306, 10, 10, mouse_left); +end; + +(* +CloseBank +~~~~~~~~~ + +.. code-block:: pascal + + function CloseBank: Boolean; + +Closes the bank window - Tries twice before exiting + +.. note:: + + Author: Starblaster100 + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if Withdraw(Col, Row, 100) then + CloseBank; +*) +function CloseBank: Boolean; +var + i, Timer: Integer; +begin + Result := False; + if BankScreen then + begin + Timer := GetTimeRunning + 8000; + repeat + Mouse(483, 28, 10, 12, mouse_left); + for i := 0 to 30 do + begin + if not BankScreen then + begin + Result:= True; + Break; + end; + Wait(100); + end; + Wait(Random(100)); + until (GetTimeRunning > Timer) or Result; + end; +end; + +(* +OpenDepositBox +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function OpenDepositBox : Boolean; + +Opens the light deposit box (such as the boxes in edgeville). + +.. note:: + + Author: Ollybest + +Example: + +.. code-block:: pascal + + if (OpenDepositBox) then + DepositAll; +*) +function OpenDepositBox: Boolean; +var + i, CTS, c, Timeout: Integer; + TPA, TPA1, TPA2: TPointArray; + ATPA: T2DPointArray; + P: TPoint; +begin + Result := (DepositScreen); + if not (LoggedIn) or (Result) then + Exit; + + CTS := GetColorToleranceSpeed; + ColorToleranceSpeed(2); + Timeout := 5000 + Random(1000); + + // getting the dark edge + SetColorSpeed2Modifiers(0.22, 0.17); + FindColorsTolerance(TPA1, 4278092, MSX1, MSY1, MSX2, MSY2, 7); + // getting the light middle + SetColorSpeed2Modifiers(0.06, 0.76); + FindColorsTolerance(TPA2, 10006456, MSX1, MSY1, MSX2, MSY2, 14); + + SetColorSpeed2Modifiers(0.2, 0.2); + ColorToleranceSpeed(CTS); + + // combining and sorting + CombineTPAWrap(TPA1, TPA2, TPA); + SplitTPAWrap(TPA, 5, ATPA); + SortATPASize(ATPA, True); + + if Length(TPA) < 1 then + Exit; + + for i := 0 to High(ATPA) do + if Length(ATPA[i]) > 30 then + begin + P := MiddleTPA(ATPA[i]); + MMouse(P.X, P.Y, RandomRange( -5, 5), RandomRange( -5, 5)); + if WaitUpTextMulti(['Deposit Bank', 'deposit box', 'osit bo', 'eposit '], 400 + Random(100)) then + begin + ClickMouse2(True); + Flag; + MarkTime(c); + repeat + Wait(RandomRange(50, 100)); + until (DepositScreen) or (PinScreen) or (TimeFromMark(C) > Timeout); + Result := (DepositScreen) or (PinScreen); + if (Result) then + Exit; + end; + end; +end; + +(* +OpenBankQuiet +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function OpenBankQuiet(WhichBank: string): Boolean; + +Opens any given bank in the free world using +FindDeformedBitmapToleranceIn. Avoids strange mouse movements. Will cause +significant lag (approx. 1 second), but finds the bank with one click. + +Valid arguments are: +'feb' (Falador East Bank) +'fwb' (Falador West Bank) +'veb' (Varrock East Bank) +'vwb' (Varrock West Bank) +'db' (Draynor Bank) +'eb' (Edgeville Bank) +'akb' (Al-Kharid Bank) + +.. note:: + + Author: WT-Fakawi and modified by Ron + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if OpenBankQuiet('feb') then + Withdraw(...); +*) +function OpenBankQuiet(WhichBank: string): Boolean; +var + TheCounter, dx, dy, tol, Mark2, Mark3: Integer; + acc, accthres: Extended; +begin + result := false; + case WhichBank of + 'feb', 'fwb': TheCounter := BitmapFromString(1, 10, '6C583296897A948779948779736' + + 'C63A59E968C7F6F9686749B8A7685663E'); + // varrock west + 'vwb': TheCounter:= BitmapFromString(10, 1, 'A0997F504A49504A49504A495E4' + + 'F215E4F215E4F215E4F212C250EA0997F'); + // varrock east + 'veb': TheCounter := BitmapFromString(1, 10, '5E4D1589826D88806D88806D867' + + 'F6C9996907C7664847D648C836891876B'); + // draynor and this works too for alkharid + 'akb', 'db', 'eb': TheCounter:= BitmapFromString(12, 1, '584209735C29735C29735C29605' + + '85558504D60504D58504D58504D58504D58504D605855'); + else + begin + srl_Warn('OpenBankQuiet', 'Unknown bank: ' + WhichBank, warn_AllVersions); + Exit; + end; + end; + + MarkTime(Mark3); + tol := 1; + accthres := 0.6; + repeat + if (Length(Players) > 0) then + if (Players[CurrentPlayer].Pin <> '') then + InPin(Players[CurrentPlayer].Pin); + if BankScreen or PinScreen then + begin + Result := True; + FreeBitmap(TheCounter); + Exit; + end; + if WaitUpTextMulti(['ank', 'Bo', 'ot'], 1000) then + begin + GetMousePos(dx, dy); + Mouse(dx, dy, 0, 0, mouse_left); + MarkTime(Mark2); + repeat + Wait(10); + if TimeFromMark(Mark2) > 20000 then + begin + WriteLn('Couldn''t find the bank. Exiting'); + FreeBitmap(TheCounter); + Exit; + end; + until BankScreen or PinScreen; + if (Length(Players) > 0) then + if (Players[CurrentPlayer].Pin <> '') then + InPin(Players[CurrentPlayer].Pin); + Result := True; + FreeBitmap(TheCounter); + Exit; + end; + + FindDeformedBitmapToleranceIn(TheCounter, dx, dy, MSX1 + 50, MSY1 + 50, MSX2 + - 50, MSY2 - 50, tol, 4, True, acc); + if (acc >= accthres) then + begin + if (Length(Players) > 0) then + if (Players[CurrentPlayer].Pin <> '') then + InPin(Players[CurrentPlayer].Pin); + if BankScreen or PinScreen then + begin + Result := True; + FreeBitmap(TheCounter); + Exit; + end; + MMouse(dx, dy, 0, 0); + if WaitUptextMulti(['ank', 'Bo', 'ot'], 1000) then + begin + GetMousePos(dx, dy); + Mouse(dx, dy, 0, 0, mouse_left); + MarkTime(Mark2); + repeat + Wait(10); + if TimeFromMark(Mark2) > 20000 then + begin + WriteLn('Couldn''t find the bank. Exiting'); + FreeBitmap(TheCounter); + Exit; + end; + until BankScreen or PinScreen; + if (Length(Players) > 0) then + if (Players[CurrentPlayer].Pin <> '') then + InPin(Players[CurrentPlayer].Pin); + Result := True; + FreeBitmap(TheCounter); + Exit; + end; + end; + Wait(100); + tol := tol + 4; + if tol >= 20 then + begin + tol := 1; + accthres := accthres - 0.1; + if accthres < 0.2 then + begin + WriteLn('Couldn''t find the bank. Exiting'); + FreeBitmap(TheCounter); + Exit; + end; + end; + until TimeFromMark(Mark3) > 60000; + FreeBitmap(TheCounter); +end; + +(* +OpenBankGlass +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function OpenBankGlass(WhichBank: String; ChangeCompass, ChangeAngle: Boolean): Boolean; + +Opens the bank. +Valid arguments are: +'feb' (Falador East Bank) +'fwb' (Falador West Bank) +'veb' (Varrock East Bank) +'vwb' (Varrock West Bank) +'db' (Draynor Bank) +'akb' (Al-Kharid Bank) +'eb' (Edgeville Bank) +'ctb' (Catherby bank) +'clt' (Camelot bank) +'nab' (North Ardougne bank) +'sab' (South Ardougne bank) +'ynb' (Yanille bank) +'ngb' (North gnome bank) +'sgb' (South gnome bank) +'wgb' (Warrior guild bank) +'fgb' (Fishing guild bank) + +.. note:: + + Author: Wizzup? and modified by Ron + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if OpenBankGlass('feb', True, False) then + Withdraw(...); +*) +function OpenBankGlass(WhichBank: string; ChangeCompass, ChangeAngle: Boolean): Boolean; +var + OBC: TPoint; + c, Speed, Col: Integer; +begin + result := false; + Speed := GetColorToleranceSpeed; + ColorToleranceSpeed(2); + if ChangeAngle then SetAngle(SRL_ANGLE_HIGH); + if ChangeCompass then + begin + c := Random(2); + case WhichBank of + 'feb', 'fwb', 'veb', 'ctb', 'clt', 'nab': if c = 0 then MakeCompass('N') else MakeCompass('S'); + 'akb', 'db', 'eb', 'vwb', 'sab', 'ynb', 'sgb', 'wgb', 'fgb': if c = 0 then MakeCompass('E') else MakeCompass('W'); + 'ngb': if c = 0 then MakeCompass(45) else MakeCompass(225); + end; + end; + Col := 10070458; + If (WhichBank = 'nab') or (WhichBank = 'sab')then + Col := 8095371; + if FindColorSpiralTolerance(OBC.x, OBC.y, Col, MSX1, MSY1, MSX2, MSY2, 10) then + begin + if WaitUpTextMulti(['nk', 'bo', 'ot'], 1000) then + begin + Mouse(OBC.x, OBC.y, 0, 0, mouse_left); + FFlag(0); + Wait(2000 + Random(500)); + if (Length(Players) > 0) then + if (Players[CurrentPlayer].Pin <> '') then + InPin(Players[CurrentPlayer].Pin); + Result := (BankScreen) or (PinScreen); + end; + end else + if FindObj(OBC.x, OBC.y, 'ank', 10070458, 20) then + begin + Mouse(OBC.x, OBC.y, 0, 0, mouse_left); + FFlag(0); + Wait(2000 + Random(500)); + if (Length(Players) > 0) then + if (Players[CurrentPlayer].Pin <> '') then + InPin(Players[CurrentPlayer].Pin); + Result := (BankScreen) or (PinScreen); + end; + ColorToleranceSpeed(Speed); +end; + +(* +OpenBankFast +~~~~~~~~~~~~ + +.. code-block:: pascal + + function OpenBankFast(Location: String): Boolean; + +Opens the bank. +Valid arguments are: +'feb', 'falador east bank' +'fwb', 'falador west bank' +'veb', 'varrock east bank' +'vwb', 'varrock west bank' +'db' , 'draynor bank' +'akb', 'al-kharid bank' +'eb' (Edgeville Bank) +'ctb', 'catherby bank' +'clt', 'camelot bank' +'nab', 'north ardougne bank' +'sab', 'south ardougne bank' +'ynb', 'yanille bank' +'ngb', 'north gnome bank' +'sgb', 'south gnome bank' +'wgb', 'warrior guild bank' +'fgb', 'fishing guild bank' +'tavb', 'taverly bank' + +.. note:: + + Author: Wizzup? and Nielsie95 + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if OpenBankFast('feb') then + Withdraw(...); +*) +function OpenBankFast(Location: String): Boolean; +var + bo, i, l, c, z: Integer; + Info: TVariantArray; + Booths: TPointArray; + ABooths: T2DPointArray; + UpText: TStringArray; + B: TBox; +begin + result := false; + if (not LoggedIn) then + Exit; + if BankScreen or PinScreen then + begin + Result := True; + Exit; + end; + UpText := ['Bank booth', 'ank boo']; + + case LowerCase(Location) of { Sort X Sort Y Color Tol Hue Sat Count SplitTPA? W H } + 'cg', 'cooking guild': Info := [MSCX, MSCY, 5666708, 17, 0.06, 0.77, 100, False, 10, 10]; + 'akb', 'al kharid': Info := [MSCX - 50, MSCY, 5002594, 20, 0.02, 0.61, 100, False, 10, 10]; // Fixed 1/5, #40 + 'lb', 'lumbridge': Info := [MSCX, MSCY - 50, 6780805, 10, 0.19, 0.27, 100, False, 10, 10]; // Fixed 12/7, #40 + 'veb', 'varrock east': Info := [MSCX, MSCY + 50, 3037545, 5, 0.41, 1.32, 100, False, 10, 10]; // Fixed 12/7, #40 + 'vwb', 'varrock west': Info := [MSCX, MSCY, 3037545, 5, 0.41, 1.32, 100, False, 10, 10]; // Fixed 12/7, #40 + 'feb', 'falador east': Info := [MSCX, MSCY + 50, 5008519, 10, 0.22, 0.67, 100, False, 10, 10]; // Fixed 12/7, #40 + 'fwb', 'falador west': Info := [MSCX, MSCY + 50, 5074569, 15, 0.22, 0.67, 50, False, 10, 10]; // Fixed 12/7, #40 + 'db', 'draynor': begin UpText := ['ount', 'unte', 'oun', 'unter']; + Info := [MSCX - 50, MSCY, 5136741, 5, 0.73, 0.49, 15, False, 10, 10]; // Fixed 12/7, #40 + end; + 'eb', 'edgeville bank': Info := [MSCX + 20, MSCY, 3561835, 20, 0.32, 0.61, 50, False, 10, 10]; // Fixed 12/7, #40 + 'ctb', 'catherby bank': Info := [MSCX, MSCY, 3239049, 8, 0.20, 0.20, 100, False, 10, 10]; + 'clt', 'camelot bank': Info := [MSCX, MSCY, 7636882, 5, 0.20, 0.20, 100, False, 10, 10]; + 'nab', 'north ardougne bank': Info := [MSCX, MSCY, 4084572, 5, 0.20, 0.20, 100, False, 10, 10]; + 'sab', 'south ardougne bank': Info := [MSCX, MSCY, 4084572, 5, 0.20, 0.20, 100, False, 10, 10]; + 'ynb', 'yanille bank': Info := [MSCX, MSCY, 3239049, 7, 0.20, 0.20, 100, False, 10, 10]; + 'ngb', 'north gnome bank': Info := [MSCX, MSCY, 3239049, 7, 0.20, 0.20, 100, False, 10, 10]; + 'sgb', 'south gnome bank': Info := [MSCX, MSCY, 3239049, 7, 0.20, 0.20, 100, False, 10, 10]; + 'wgb', 'warrior guild bank': Info := [MSCX, MSCY, 2578286, 7, 0.20, 0.20, 100, False, 10, 10]; + 'fgb', 'fishing guild bank': Info := [MSCX, MSCY, 2908796, 10, 0.20, 0.20, 100, False, 10, 10]; + 'tavb', 'taverly bank': begin UpText := ['ount','unte','oun','unter']; + Info := [MSCX, MSCY, 3556433, 7, 0.20, 0.20, 100, False, 10, 10]; + end; + else + begin + srl_Warn('OpenBankFast', 'Unknown bank: '+Location, warn_AllVersions); + Exit; + end; + end; + + MakeCompass('n'); + z := GetColorToleranceSpeed; + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(Info[4], Info[5]); + + FindColorsSpiralTolerance(Info[0], Info[1], Booths, Info[2], MSX1, MSY1, MSX2, MSY2, Info[3]); + ColorToleranceSpeed(z); + SetColorSpeed2Modifiers(0.2, 0.2); + + { Split to ATPA. } + if Info[7] then + ABooths := SplitTPA(Booths, 1) + else + ABooths := TPAtoATPA(Booths, 10); + + Booths := []; + + { Go through ATPA. } + l := GetArrayLength(ABooths) -1; + for i := 0 to l do + begin + { Too few pixels. } + if (Length(ABooths[i]) < Info[6]) then + Continue; + + { Too small TPA bounds. } + B := GetTPABounds(ABooths[i]); + If ((B.X2 - B.X1) < Info[8]) Or ((B.Y2 - B.Y1) < Info[9]) Then + Continue; + + Inc(bo); + SetArrayLength(Booths, bo); + Booths[bo-1] := MiddleTPA(ABooths[i]); + + end; + + SortTPAFrom(Booths, Point(Info[0], Info[1])); + + l := GetArrayLength(Booths) -1; + for i := 0 to l do + begin + + MMouse(Booths[i].X, Booths[i].Y, 3, 3); + if WaitUpTextMulti(UpText, 1000) Then + begin + GetMousePos(Booths[i].X, Booths[i].Y); + Mouse(Booths[i].X, Booths[i].Y, 0, 0, mouse_left); + FFLag(0); + MarkTime(c); + repeat + Wait(100); + until (BankScreen) or (PinScreen) or (TimeFromMark(c) > 10000); + Wait(Random(300)); + if (HowManyPlayers > 0) then + if (Players[CurrentPlayer].Pin <> '') then + InPin(Players[CurrentPlayer].Pin); + Result := (BankScreen) or (PinScreen); + if (Result) then Exit; + end; + end; +end; + +(* +OpenBankNPCEx +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function OpenBankNPCEx(Color: String): Boolean; + +Opens the bank by using the NPC banker. + +Vaild colors are: +'blue' - most bankers.. edgeville, varrock etc. +'green' - al-kharid. +'gray', 'grey' - ardougne. + +.. note:: + + Author: Ollybest (Heavily copyied home's function) + +Example: + +.. code-block:: pascal + + if (OpenBankNPCEx('green') then + Withdraw(...); + +*) +function OpenBankNPCEx(Color: String): Boolean; +var + NPCBox: TBox; + Colors, NPCArray: TPointArray; + ATPA: T2DPointArray; + MSNPC, NPCPoint: TPoint; + CTS, C, II, I, TimeOut: Integer; + Info: TVariantArray; +begin + Result := False; + if not (LoggedIn) then + Exit; + Result := (BankScreen) or (PinScreen); + if (Result) then + Exit; + + case Lowercase(Color) of { Color Tol Hue Sat } + 'blue': Info := [4336177, 15, 0.16, 0.66]; + 'green': Info := [1988959, 17, 0.11, 1.52]; + 'gray', 'grey': Info := [5855838, 8, 0.42, 0.11]; + else + begin + srl_Warn('OpenBankNPCEx', 'Unknown banker color: '+ Color, warn_AllVersions); + Exit; + end; + end; + + TimeOut := 5000 + Random(1200); + NPCArray := GetMinimapDots('NPC'); + + If Length(NPCArray) < 1 then + Exit; + + SortTPAFrom(NPCArray, Point(MMCX, MMCY)); + for I := 0 to High(NPCArray) do + begin + NPCPoint := MMToMS(NPCArray[I]) + If (NPCPoint.x = -1) and (NPCPoint.y = -1) then + Continue; + with NPCPoint do + NPCBox := IntToBox(Max(X - 40, MSX1), Max(Y - 40, MSY1), Min(X + 40, MSX2), Min(Y + 40, MSY2)); + + If PixelShift(NPCBox, 150) > 500 then + Continue; + + CTS := GetColorToleranceSpeed; + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(Info[2], Info[3]); + FindColorsTolerance(Colors, Info[0], NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, Info[1]); + SetColorSpeed2Modifiers(0.2, 0.2); + ColorToleranceSpeed(CTS); + + TPAtoATPAExWrap(Colors, 15, 25, ATPA); + SortATPASize(ATPA, True); + + for II := 0 to High(ATPA) do + begin + MSNPC := MiddleTPA(ATPA[II]); + MMouse(MSNPC.X, MSNPC.Y, RandomRange(-3, 3), RandomRange(-3, 3)); + If WaitUpTextMulti(['ooth', 'anker', '-to Banker', 'Bank'], 400 + Random(100)) then + begin + ClickMouse2(False); + If WaitOptionMulti(['Bank B', 'nk B', 'ank Banker'], 600 + Random(200)) then + MarkTime(c); + Flag; + repeat + Wait(RandomRange(50, 100)); + until (BankScreen) or (PinScreen) or (TimeFromMark(C) > TimeOut); + if not (AllPlayersInactive) then + if (Players[CurrentPlayer].Pin <> '') then + InPin(Players[CurrentPlayer].Pin); + Result := (BankScreen) or (PinScreen); + If (Result) then + Exit; + end; + end; + end; +end; + +(* +OpenBankNPC +~~~~~~~~~~~ + +.. code-block:: pascal + + function OpenBankNPC: Boolean; + +Attempts to open the *blue* NPC banker. +(used as a wrapper to prevent breaking script) + +.. note:: + + Author: Ollybest. + +Example: + +.. code-block:: pascal + + if (OpenBankNPC) then + Withdraw(...); +*) +function OpenBankNPC: Boolean; +begin + Result := OpenBankNPCEx('blue'); +end; + +(* +OpenBankChestEdge +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function OpenBankChestEdge(Location: String): Boolean; + +Opens the bank. Valid arguments are: + * SRL_BANK_SW (Soul Wars Bank) + * SRL_BANK_CW (Castle Wars Bank) + * SRL_BANK_B (Burthrope) + * SRL_BANK_GG (Gamer's Grotto) + * SRL_BANK_SP (Shantay Pass) + +.. note:: + + Author: -daazndagger- + Last Modified: Jan 27th, 2013 + +Example: + +.. code-block:: pascal + + if OpenBankChestEdge(SRL_BANK_SW) then + Withdraw(...); +*) +function OpenBankChestEdge(Location: Integer): Boolean; +var + bo, i, l, c, z: Integer; + Info: TVariantArray; + Chests: TPointArray; + AChests: T2DPointArray; + UpText, ChooseOp: TStringArray; + B: TBox; +begin + result := false; + if (not LoggedIn) then + Exit; + if BankScreen or PinScreen then + begin + Result := True; + Exit; + end; + if Location = SRL_BANK_SP then + begin + UpText := ['Shantay', 'chest', 'tay che']; + ChooseOp := ['Open', 'pen Sh']; + end else + begin + UpText := ['Bank', 'chest', 'nk che']; + ChooseOp := ['Use', 'se']; + end; + { 0 1 2 3 4 5 6 7 8 9 10 } + case Location of { Sort X Sort Y Color Tol Hue Sat Count SplitTPA? W H Compass} + SRL_BANK_SW : Info := [MSCX , MSCY, 10198185, 21, 0.08, 0.25, 50, True , 10, 10, 'w']; + SRL_BANK_CW : Info := [MSCX , MSCY, 10198185, 21, 0.08, 0.25, 50, True , 10, 10, 'n']; + SRL_BANK_B : Info := [MSCX , MSCY, 10198185, 21, 0.08, 0.25, 50, True , 10, 10, 'n']; + SRL_BANK_GG : Info := [MSCX , MSCY, 5921630, 9 , 0.47, 0.08, 50, True , 10, 10, 'n']; + SRL_BANK_SP : Info := [MSCX , MSCY, 6715270, 4 , 0.19, 0.29, 50, True , 10, 10, 'n']; + + else + begin + srl_Warn('OpenBankChestEdge', 'Unknown bank: '+IntToStr(Location), warn_AllVersions); //will output loc as int (no longer string) + Exit; + end; + end; + + MakeCompass(Info[10]); + //SetAngle(SRL_ANGLE_HIGH); //?? + z := GetColorToleranceSpeed; + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(Info[4], Info[5]); + + FindColorsSpiralTolerance(Info[0], Info[1], Chests, Info[2], MSX1, MSY1, MSX2, MSY2, Info[3]); + ColorToleranceSpeed(z); + SetColorSpeed2Modifiers(0.2, 0.2); + + { Split to ATPA. } + if Info[7] then + AChests := SplitTPA(Chests, 3) + else + AChests := TPAtoATPA(Chests, 10); + + Chests := []; + + { Go through ATPA. } + l := GetArrayLength(AChests) -1; + for i := 0 to l do + begin + { Too few pixels. } + if (Length(AChests[i]) < Info[6]) then + Continue; + + { Too small TPA bounds. } + B := GetTPABounds(AChests[i]); + If ((B.X2 - B.X1) < Info[8]) Or ((B.Y2 - B.Y1) < Info[9]) Then + Continue; + + Inc(bo); + SetArrayLength(Chests, bo); + Chests[bo-1] := MiddleBox(GetTPABounds(AChests[i])); + + end; + + SortTPAFrom(Chests, Point(Info[0], Info[1])); + + l := GetArrayLength(Chests) -1; + for i := 0 to l do + begin + + MMouse(Chests[i].X, Chests[i].Y, 3, 3); + if WaitUpTextMulti(UpText, 1000) Then + begin + GetMousePos(Chests[i].X, Chests[i].Y); + Case Random(9) of + 0..7: Mouse(Chests[i].X, Chests[i].Y, 0, 0, mouse_left); + 8: begin + Mouse(Chests[i].X, Chests[i].Y, 0, 0, mouse_right); + if not WaitOptionMulti(ChooseOp, 1000) then Exit; + end; + end; + FFLag(0); + MarkTime(c); + repeat + Wait(100); + until (BankScreen) or (PinScreen) or (TimeFromMark(c) > 10000); + Wait(Random(300)); + if (HowManyPlayers > 0) then + if (Players[CurrentPlayer].Pin <> '') then + InPin(Players[CurrentPlayer].Pin); + Result := (BankScreen) or (PinScreen); + if (Result) then Exit; + end; + end; +end; + +(* +OpenBankChest +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function OpenBankChest(WhichBank): Boolean; + +Opens the bank. Valid arguments are: + * SRL_BANK_SW (Soul Wars Bank) + * SRL_BANK_CW (Castle Wars Bank) + * SRL_BANK_B (Burthrope) + +.. note:: + + Author: SRL Dev Team + Last Modified: 18/01/2012 + +Example: + +.. code-block:: pascal + + if OpenBankChest(SRL_BANK_SW) then + Withdraw(...); +*) +function OpenBankChest(WhichBank: Integer): Boolean; +begin + result := false; + if BankScreen or PinScreen then + begin + Result := True; + Exit; + end; + + Result := OpenBankChestEdge(WhichBank); + +end; + +(* +OpenBank +~~~~~~~~ + +.. code-block:: pascal + + function OpenBank(WhichBank: String, ChangeCompass, ChangeAngle: Boolean): Boolean; + +Opens the bank if possible. +Valid arguments are: +'feb' (Falador East Bank) +'fwb' (Falador West Bank) +'veb' (Varrock East Bank) +'vwb' (Varrock West Bank) +'db' (Draynor Bank) +'akb' (Al-Kharid Bank) +'eb' (Edgeville Bank) +'lb' (Lumbridge Bank) +'ctb' (Catherby bank) +'clt' (Camelot bank) +'nab' (North Ardougne bank) +'sab' (South Ardougne bank) +'ynb' (Yanille bank) +'ngb' (North gnome bank) +'sgb' (South gnome bank) +'wgb' (Warrior guild bank) +'fgb' (Fishing guild bank) + +.. note:: + + Author: SRL Dev Team + Last Modified: January 31st, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + if OpenBank('feb', False, True) then + Withdraw(...); +*) +function OpenBank(WhichBank: variant; ChangeCompass, ChangeAngle: Boolean): Boolean; +var + I: Integer; +begin + result := false; + if BankScreen then + begin + Result := True; + Exit; + end; + + if VariantIsInteger(WhichBank) then + if (OpenBankChest(WhichBank)) then + begin + Result := true; + Exit; + end; + + for I := 0 to 3 do + begin + case I of + 0: Result := OpenBankFast(WhichBank); + 1: Result := OpenBankGlass(WhichBank, ChangeCompass, ChangeAngle); + 2: Result := OpenBankQuiet(WhichBank); + 3: Result := OpenBankNPC; + end; + + if Result then + Exit; + end; +end; + +(* +FindBank +~~~~~~~~ + +.. code-block:: pascal + + function FindBank(TheBank: String): Boolean; + +Valid arguments are: +'feb' (Falador East Bank) +'fwb' (Falador West Bank) +'veb' (Varrock East Bank) +'vwb' (Varrock West Bank) +'db' (Draynor Bank) +'akb' (Al-Kharid Bank) +'ctb' (Catherby bank) +'clt' (Camelot bank) +'nab' (North Ardougne bank) +'sab' (South Ardougne bank) +'ynb' (Yanille bank) +'ngb' (North gnome bank) +'sgb' (South gnome bank) +'fgb' (Fishing guild bank) + +.. note:: + + Author: WT-Fakawi and modified by Ron + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + if FindBank('feb') then + Withdraw(...); +*) +function FindBank(TheBank: string): Boolean; +var + bx, by, TheDTM: Integer; + WhichAngle: Extended; +begin + result := false; + TheBank := LowerCase(TheBank); + case TheBank of + 'feb': TheDTM := DTMFromString('78DA63AC67626088634001FFFFFD63F80FA41' + + '9416C2060AC01AA4987C83141D5FCF9C3C4C0055503028CAD44A8' + + 'E924AC0600131E11B5'); + 'fwb': TheDTM := DTMFromString('78DA636C676260086540038C0CFFC12403C37' + + 'F206004A98986C8304155FCF9C3C4C0055503D6D14C849A6EC26A' + + '009F5A0EA1'); + 'db': TheDTM := DTMFromString('78DA632C6162608866400181DEDE0CFF81342' + + '310FF0702C62CA09A4454357FFE30313043D58000584D1C116AC2' + + 'F0AB0100EC370F0C'); + 'veb': TheDTM := DTMFromString('78DA63EC61626008624001FFFFFD63F80FA41' + + '9416C2060EC00AA8982C83141D5FCF9C3C4C0055503028C138850' + + 'D343580D00122211A9'); + 'vwb': TheDTM := DTMFromString('78DA63EC606260B066C000FF819811440301E' + + '354A01A3B88381354FECF1F260611A81A1000AB3125428D2E7E35' + + '0087F80E5E'); + 'akb': TheDTM := DTMFromString('78DA636C606260F06140019D9D710CFF81342' + + '310FF0702C652A01A37881C1354CD9F3F4C0C5C5035200056E345' + + '841A3FFC6A002A3B0F97'); + + 'ctb': TheDTM := DTMFromString('78DA63CC63626008624001478F1E65F80FA41' + + '981F83F1030A602D578A0AAF9F387898119AA060418F388505344' + + '849A32C26A00FE5D12EE'); + 'clt': TheDTM := DTMFromString('78DA63CC67626008604001E78E1F67F80FA41' + + '981F83F10306601D5B8A2AAF9F387898119AA060418CB88505345' + + '849A3AC26A000B52130B'); + 'nab': TheDTM := DTMFromString('78DA63AC61626008654001135A8B19FE03694' + + '620FE0F048C454035B1A86AFEFC61626086AA0101C66A22D47400' + + 'D5C4E057030045F20FE7'); + 'sab': TheDTM := DTMFromString('78DA632C656260086040017DCD850CFF81342' + + '310FF0702C63AA09A6454357FFE30313043D58000584D180135F5' + + '40359EF8D500003F560FC7'); + 'ynb': TheDTM := DTMFromString('78DA632C60626008654001E78E1F67F80FA41' + + '981F83F10305601D5F8A2AAF9F387898119AA0604182B31CDC1AA' + + '260ABF1A009CFB108C'); + 'ngb': TheDTM := DTMFromString('78DA632C66626008654001FFFFFF67F80FA41' + + '921ECFF8CB94035B1A86AFEFC61626086AA0101C632C26A00AD6D' + + '0E64'); + 'sgb': TheDTM := DTMFromString('78DA632C606260086640038C0CFFC12403C37' + + 'F20604C05AA894255F1E70F130333540D5807484D18116AFCF0AB' + + '01006D100DF4'); + + 'fgb': TheDTM := DTMFromString('78DA632C626260F0654001F5311E0CFF81342' + + '310FF0702C64CA01A1754357FFE30313043D58000588D27116A02' + + '8950138A5F0D0041A911BD'); + 'eb' : TheDTM := DTMFromString('78DA63E4666060E0614001EF2F2832FC07D28' + + 'C40FC1F0818E5800C7154355FBF426846289F51124848A3AAF9F3' + + '8709558D0490504255F3EF9F20A6395AF8D500008FCC0FE1'); + else + begin + srl_Warn('FindBank', 'Invalid bank name', warn_Warning); + Exit; + end; + end; + if FindDtmRotated(TheDTM, bx, by, MMX1, MMY1, MMX2, MMY2, Radians(-30), Radians(30), 0.05, WhichAngle) then + begin + Mouse(bx, by, 0, 0, mouse_left); + FFlag(0); + Wait(300+Random(400)); + Result := OpenBank(TheBank, False, False); + end; + FreeDTM(TheDTM); +end; + +(* +WithdrawFromPouch +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WithdrawFromPouch(Amount :Integer) :Boolean; + +Withdraws amount from pouch. + +.. note :: + + by Home + +*) +function WithdrawFromPouch(Amount :Integer) :Boolean; +var + T :Integer; +begin + Result := False; + MouseBox(528, 94, 533, 107, mouse_Right); + If WaitOption('draw', 500) then + begin + T := GetSystemTime + 10000; + repeat + wait(50); + InPin(Players[CurrentPlayer].Pin); + until (T <= GetSystemTime) or (InRange(CountColor(0, 250, 396, 307, 410), 160, 175)); + Wait(RandomRange(75, 400)); + TypeSend(IntToStr(Amount)); + Result := True; + end; +end; diff --git a/SRL/core/bitmaps.simba b/SRL/core/bitmaps.simba new file mode 100644 index 0000000..5889f90 --- /dev/null +++ b/SRL/core/bitmaps.simba @@ -0,0 +1,841 @@ +(* +Bitmaps +======= + +The Bitmap include contains Bitmap of most common objects. + +.. contents:: + +*) + + +//-----------------------------------------------------------------// +//-- SRL Resource Library --// +//-- » SRL Bitmap Routines --// +//-----------------------------------------------------------------// +// * function srl_GetBitmap(ID: Integer): Integer; // * by the SRL community +// * procedure srl_LoadBitmaps(IDs: TIntegerArray); // * by Nielsie95 +// * procedure srl_LoadBitmapRange(StartID, EndID: Integer); // * by Nielsie95 +// * procedure srl_FreeBitmapEx(which: integer); // * by Rasta Magician +// * procedure srl_FreeBitmapArray(bmpArr: TIntegerArray); // * by EvilChicken! +// * procedure srl_FreeBitmaps; // * by Nielsie95 +// * procedure srl_FreeBitmapRange(StartID, EndID: Integer); // * by EvilChicken! + +const + srl_BitmapCount = 111; + +{var srl_Bitmaps: array[0..107] of Integer; + Description: Holds all the loaded SRL bitmaps.} +var + srl_Bitmaps: array[0..(srl_BitmapCount - 1)] of Integer; + +{var srl_BitmapSet: array[0..107] of Boolean; + Description: Array to specify if a certain bitmap is loaded or not.} + +var + srl_BitmapSet: array[0..(srl_BitmapCount - 1)] of Boolean; + +{ + READ ME + When calling a SRL Bitmap, it is better to use srl_GetBitmap(bmp_Ore_Iron) + rather than srl_GetBitmap(1) as the numbers are subject to change, + while bmp_something will always work. +} + +{ + Dev Note + The next Bitmap to be added = srl_BitmapCount; Don't forget to add + 1 to the count afterwards! +} + +const + bmp_Ore_Clay = 0; + bmp_Ore_Iron = 1; + bmp_Ore_Copper = 2; + bmp_Ore_Tin = 3; + bmp_Ore_Coal = 4; + bmp_Ore_Silver = 5; + bmp_Ore_Gold = 6; + bmp_Ore_Mithril = 7; + bmp_Ore_Adamant = 8; + bmp_Ore_Runite = 9; + + bmp_Bar_Bronze = 10; + bmp_Bar_Iron = 11; + bmp_Bar_Steel = 12; + bmp_Bar_Silver = 13; + bmp_Bar_Gold = 14; + bmp_Bar_Mithril = 15; + bmp_Bar_Adamant = 16; + bmp_Bar_Runite = 17; + + bmp_Rune_Air = 18; + bmp_Rune_Mind = 19; + bmp_Rune_Water = 20; + bmp_Rune_Fire = 21; + bmp_Rune_Earth = 22; + bmp_Rune_Law = 23; + bmp_Rune_Nature = 24; + bmp_Rune_Chaos = 25; + bmp_Rune_Death = 26; + bmp_Rune_Body = 27; + bmp_Rune_Cosmic = 28; + bmp_Rune_Soul = 29; + bmp_Rune_Blood = 30; + + bmp_Talis_Air = 31; + bmp_Talis_Mind = 32; + bmp_Talis_Water = 33; + bmp_Talis_Fire = 34; + bmp_Talis_Earth = 35; + bmp_Talis_Law = 36; + bmp_Talis_Nature = 37; + bmp_Talis_Chaos = 38; + bmp_Talis_Death = 39; + bmp_Talis_Body = 40; + bmp_Talis_Cosmic = 41; + + bmp_FishGear_SmallNet = 42; + bmp_FishGear_Rod = 43; + bmp_FishGear_FlyRod = 44; + bmp_FishGear_Cage = 45; + bmp_FishGear_Harpoon = 46; + + bmp_Axe_Bronze = 47; + bmp_Axe_Iron = 48; + bmp_Axe_Steel = 49; + bmp_Axe_Black = 50; + bmp_Axe_Mithril = 51; + bmp_Axe_Adamant = 52; + bmp_Axe_Rune = 53; + bmp_Axe_Dragon = 54; + bmp_Axe_Adze = 110; + + bmp_TinderBox = 55; + bmp_Log_Normal = 56; + bmp_Log_Oak = 57; + bmp_Log_Willow = 58; + bmp_Log_Maple = 59; + bmp_Log_Yew = 60; + + bmp_Pick_Bronze = 61; + bmp_Pick_Iron = 62; + bmp_Pick_Steel = 63; + bmp_Pick_Mithril = 64; + bmp_Pick_Adamant = 65; + bmp_Pick_Rune = 66; + + bmp_Bow_CrossBow = 67; + bmp_Bow_Short_Normal = 68; + bmp_Bow_Short_Oak = 69; + bmp_Bow_Short_Willow = 70; + bmp_Bow_Short_Maple = 71; + bmp_Bow_Long_Normal = 72; + bmp_Bow_Long_Oak = 73; + bmp_Bow_Long_Willow = 74; + bmp_Bow_Long_Maple = 75; + + bmp_Food_Cooked_Meat = 76; + bmp_Food_Cooked_Chicken = 77; + bmp_Food_Cooked_Shrimps = 78; + bmp_Food_Cooked_Anchovies = 79; + bmp_Food_Cooked_Tuna = 80; + bmp_Food_Cooked_Trout = 81; + bmp_Food_Cooked_Pike = 82; + bmp_Food_Cooked_Salmon = 83; + bmp_Food_Cooked_Lobster = 84; + bmp_Food_Cooked_Swordfish = 85; + + bmp_Food_Raw_Meat = 86; + bmp_Food_Raw_Chicken = 87; + bmp_Food_Raw_Shrimps = 88; + bmp_Food_Raw_Anchovies = 89; + bmp_Food_Raw_Tuna = 90; + bmp_Food_Raw_Trout = 91; + bmp_Food_Raw_Pike = 92; + bmp_Food_Raw_Salmon = 93; + bmp_Food_Raw_Lobster = 94; + bmp_Food_Raw_Swordfish = 95; + + bmp_Bucket_Empty = 96; + bmp_Bucket_Water = 97; + + bmp_Bones_Normal = 98; + bmp_Bones_Big = 99; + + bmp_Uncut_Sapphire = 100; + bmp_Uncut_Emerald = 101; + bmp_Uncut_Ruby = 102; + bmp_Uncut_Diamond = 103; + + bmp_Cut_Sapphire = 104; + bmp_Cut_Emerald = 105; + bmp_Cut_Ruby = 106; + bmp_Cut_Diamond = 107; + + bmp_GE = 108; + + bmp_Ring_Ruby = 109; + + +(* +srl_GetBitmap +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function srl_GetBitmap(ID: Integer): Integer; + +Returns the bitmap identified by ID. + +.. note:: + + Author: SRL Community + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + FindBitmap(srl_GetBitmap(bmp_Ore_Iron), x, y) +*) +function srl_GetBitmap(ID: Integer): Integer; +begin + Result := -1; + if (ID < 0) or (ID > srl_BitmapCount - 1) then + begin + WriteLn('srl_GetBitmap: Unknown bitmap, id: '+IntToStr(ID)); + Exit; + end; + if srl_BitmapSet[ID] then + begin + //WriteLn('Returning already loaded bitmap: '+IntToStr(ID)); + Result := srl_Bitmaps[ID]; + Exit; + end; + + + //WriteLn('Loading new bitmap: '+IntToStr(ID)); + case ID of + bmp_Ore_Iron : + Result := BitmapFromString(7, 3, 'beNpTkNCTFjGUFTN' + //Iron_Ore [10-12-09] + 'XkLBRkQYiSyVJIBsoYiIvDmQjCwJFgCSKIAAisglL'); + bmp_Ore_Copper: + Result := BitmapFromString(7, 3, 'beNrLspwZob8swWR' + //Copper_Ore [10-12-09] + 'rpsWBfJujRbaHC21351gtjDVan2oGZJwotgMKHiqw2ZVtBVS2Ic0c' + + 'yACqAQoC1e8AAH4THIg='); + bmp_Ore_Tin: + Result := BitmapFromString(7, 3, 'beNpLTg4PDo6NjMx' + //Tin_Ore [10-12-09] + 'ITs7LzCzIzgaSWamp0eHhibGxQAZQBC4IVJYSHw8XzElPzwAAEYYY' + + '5g=='); + bmp_Ore_Coal: + Result := BitmapFromString(7, 3, 'beNpTlZGTE1dSklJ' + //Coal_Ore [10-12-09] + 'VldHQkAciIAOIkEXwCQIAC50IfA=='); + bmp_Ore_Silver : + Result := BitmapFromString(7, 3, 'beNrrmlBYWFZVVd/' + //Silver_Ore [10-12-09] + 'W1tPfP3XSpJkTJkzv7p5UVlbT2Nje2TUBKAJEQCkgu6amsbm5E8gA' + + 'qoEKAgAyUiIM'); + bmp_Ore_Gold: + Result := BitmapFromString(7, 3, 'beNrrk5pUIrqgXnx' + //Gold_Ore [10-12-09] + '9t+SuKdJ7p0vvniq9dYLUrGqxFW0Sm/ul9s8ACQKlgGygslXtIEGg' + + 'CBDtmCy9CQB2/Bwz'); + bmp_Ore_Mithril: + Result := BitmapFromString(7, 3, 'beNozD9LRcTQ09DQ' + //Mithril_Ore [10-12-09] + '1C7CwDLGyCgeS5uZB+vpuJia+QAZQBC4IVIYuCADpFQ+E'); + bmp_Ore_Adamant: + Result := BitmapFromString(7, 3, 'beNpzsTayNDKzN7N' + //Adamant_Ore [10-12-09] + '2sbb3tIcgWzdbExsTC0dLIANZEKgMTdAaAOgFD28='); + bmp_Ore_Runite: + Result := BitmapFromString(7, 3, 'beNoLCDdzdLPx8HU' + //Runite_Ore [10-12-09] + 'OCHcLifYIiwWSLkGRVm7e9j5BQAZQBC5o6xXg6BeCLOgMAF6iEzw=' + + ''); + + + + bmp_Bar_Bronze: + Result := BitmapFromString(6, 6, 'beNqzUbbRlYajABt' + //Bronze_Bar [10-12-09] + 'lIELjApGSJD8EUSQCABMEErQ='); + bmp_Bar_Iron: + Result := BitmapFromString(6, 6, 'beNoLDHS0s0NGIYG' + //Iron_Bar [10-12-09] + 'BqsrKyFyICByRLwIARD8Xlg=='); + bmp_Bar_Steel: + Result := BitmapFromString(6, 6, 'beNqrqUmJj0dGjTU' + //Steel_Bar [10-12-09] + '1aFxkEQgXiCzNzSGIBBEAEFkpjw=='); + bmp_Bar_Silver: + Result := BitmapFromString(6, 6, 'beNqrqUmJj0dGjTU' + //Silver_Bar [10-12-09] + '1aFxkEQgXiCzNzSGIBBEAEFkpjw=='); + bmp_Bar_Gold: + Result := BitmapFromString(6, 6, 'beNpbIbe4SRw/urx' + //Gold_Bar [10-12-09] + 'CLtaLF5kLEYEjYkUAFiwozg=='); + bmp_Bar_Mithril: + Result := BitmapFromString(6, 6, 'beNpzSjQy9oYjR6d' + //Mithril_Bar [10-12-09] + 'EIELjApGsrDYEUSQCAGhIGLE='); + bmp_Bar_Adamant: + Result := BitmapFromString(6, 6, 'beNoL8bRwtIQjzxB' + //Adamant_Bar [10-12-09] + 'PIELjApGCqgIEUSQCAHRMGOE='); + bmp_Bar_Runite: + Result := BitmapFromString(6, 6, 'beNpLyLD1CoCjgIQ' + //Runite_Bar [10-12-09] + 'MIELjApGKth4EUSQCAKRXHlY='); + + //all runes updated 4th Sept 2010 + bmp_Rune_Air: + Result := BitmapFromString(10, 7, 'beNpNjtsKgCAQRD9VpKuZ3RMRM6' + + 'Jf3Nf+pYWJJfBh3Dk7s0TbOD5EeHHfIM4Yr5TufEzWLs5hGNYVIoc' + + 'AYDBGdv08S0jynpm+acT9hwBoi0JcboHgYwDgy0xXVf8QaSmVqrUW' + + 'iy/5Kl4kjYgB'); + bmp_Rune_Mind: + Result := BitmapFromString(9, 6, 'beNorLSkrLDQ344CguoqK+qoqCLu5r' + + 'rYkPx8uVVVaUlNWBmE31tQUZGcX5eYCFQC1VxQXA2UhUkDteZmZQF' + + 'm4AqAs3HAgmZOeDlEANxmI4CYjI6jJAKr+MqI='); + bmp_Rune_Water: + Result := BitmapFromString(7, 7, 'beNqTmpOVmpqTnp6XmVmQnS0mN' + + 'QeC0hITM5KTIVJwwZT4eKA4EMFFgCg+OjopNhZZBIhiIyOBCE0wMj' + + 'Q0OjwcqB5ZMDw4GCgOVIwQBwDlRC5D'); + bmp_Rune_Fire: + Result := BitmapFromString(11, 5, 'beNpljFsKgCAURHfhv2u0IsQSMc3U' + + 'XkZE0GKbEPwJDpczl2EoMVKOSk1aBzM8lGzepxiOeT7X9dq3OyU8d' + + 'd/lGhy1aO3iHJqIaOJKzoESAv4fxOV1JZoGksmDJWZaxoqXtY8XIR' + + 'pFYQ=='); + bmp_Rune_Earth: + Result := BitmapFromString(11, 3, 'beNqrqCjIzi7KzS3Jzy8rLKwo' + + 'Lo624UVDeZmZQDVoyqpKS2rKyuoqKuqrqrJSU3PS09GUIdQAAFx4J' + + '64='); + bmp_Rune_Law: + Result := BitmapFromString(10, 4, 'beNpTuSavAkIl+fllhYVARlVpCR' + + 'DVlJVBxCGoIDu7KDcXyACqqSguBipAls3LzAQqgKgBmgNUABFPS0z' + + 'MSE7OSk3NSU+HGwIxQR4AlTMw6A=='); + bmp_Rune_Nature: + Result := BitmapFromString(8, 4, 'beNrLzc1KTc1JTxeqEwWiguxs' + + 'IFmSn19RXJyWmJiRnAwRz8vMBJJFubllhYUp8fFAKYg4RCNQHKglP' + + 'joaKAURB5oJMa0IADkkIHo='); + bmp_Rune_Chaos: + Result := BitmapFromString(10, 5, 'beNqbI39tjvzdK1eAyNyMA0JCGEAE' + + 'lILLYiI0WT5eXjyyWPViKoCKAwDh9WkK'); + bmp_Rune_Death: Result := BitmapFromString(12, 9, 'beNptjt0KgCAMRp8zRIQIQvrP' + + 'EhFLJKIX7LZ3abAYMYRzM3a27zNmGQY7Tc4Y4LlvIoVw7NsZ45XS2' + + 'DRz14H5F4DoPWpArzVqzAnW7s6hCSNq9BCj/bqQRofMZPWItq7RZK' + + 'GllJVS2RMKlUWhhGBb1i37AfmKvQ6hy5E='); + bmp_Rune_Body: + Result := BitmapFromString(14, 5, 'beNpdjtkJgDAQBSvQCvywtRDiF' + + 'e8jhLAagohtWZoPFoII8/V2WIZo1DpNEmCmyS6L21Yy5rDWO8f7ee' + + 'yX93cIfV3z8pVBHANRlj+gLUvI/HnuunUY4LMTn7NZSdkoBR8n+DH' + + 'mV4KGQggAn4UY88sOLxqsRU0='); + bmp_Rune_Cosmic: + Result := BitmapFromString(10, 7, 'beNq7In/tCgjVlJXVVVTUV1U11tQ0' + + '19VCBJFRVWkJXA2mLJEKIGqwygJRRXExpoKC7GwgKsrNLcnPBypAl' + + 'spKTc1JT8/LzIQogIoDACTZcOk='); + bmp_Rune_Soul: + Result := BitmapFromString(18, 5, 'beNrr6Z4w6TocFeXmluTnlxUWVhQX' + + 'V5WWAFFNWVldRQWyms7m5gldXcgiWPUCNSLLtjc2TurpxtSFH7XW1' + + '0/u7cUqlZeZiV9XbGQkplROejoujUBdkwAjiKIY'); + bmp_Rune_Blood: + BitmapFromString(6, 12, 'beNpdylsKgCAQheE99Ni+IkQkKszu' + + 'ZZmIRG29U8IUwf9yvpk42q09nDu9R0ccIau1W1e/mfv0iJmmgGGiu' + + 'euWYYCTjE0TkKRXKiBJXZatlHCSKs8RTVQI8Z1IMPYTnqYZ519hSY' + + 'K3Fy9o6kKo'); + + + bmp_Talis_Air: Result := BitmapFromString(8, 8, 'z78DA4D90491244210843' + //Air talisman + 'AFE4C010964EDCFF484D7F5CE8ABB22C0D9068040374680D9A8CC' + + '0A44A9D7BF6D97930059D56B009A47A940391235B5C10BCFAC512' + + '3039391732327435B57CCD3DABEEB9F1E4716BBF29609D3A50F4B' + + 'F3E575739A507C487D7DB0D0B2D10DDBAAE376811CF2CAF32BD59' + + '430822B1EBC9FB37D19DF5254A6FA318078A1D93062ACADBF34D9' + + '45566701C8B801877D6417C5CE6BAFF4CB2228FB2B3FF00D6A856' + + '88'); + bmp_Talis_Mind: Result := BitmapFromString(8, 8, 'z78DA75904B0EC4200C4' + //Mind talisman + '3AF04251F670914EE7FA4F1342C2A8D266F6BCB7642108077AFE4' + + 'B24EC22AB9746827429A4C720BC447B151C5CD96DDB60DE4D1376' + + '9528A4E35A2B2656B919040F320D31B795CA9FC9702F5E11DC5BF' + + 'F7B43AFA618D882E66640AB46ACD3EA7D57225F0623BB7A4F7AD8' + + '90B1470F1F675BAA5EB6751EA7B09258E1B131D15251BBE17BD5D' + + '11D8586118E8276B818F3BAEFCB3D8E41ED7ADFB03A3AE53DB'); + bmp_Talis_Water: Result := BitmapFromString(8, 8, 'z78DA75D04712C3300C' + //Water talisman + '03C02FA9B08047D5FF3F2988E58333196BAFE400620802F0E6998' + + 'A350ACB54B46B23A12A83A640DC972B992D9BB60DF49C1F6AA4B2' + + '656B929040F5A0E195DEB61E2950EFDE90FCFBAE5669668159B74' + + 'AA28B1927059A3563A090F964C6D5EDCCBF6D4581137CFB3ADD7E' + + 'E6FFBAB5144A8EC9A4868C741ABEFD28021B2B0C1DEDCE5AE0E1E' + + 'EAD7367B1C166AE5BF7071F0F5449'); + bmp_Talis_Fire: Result := BitmapFromString(8, 8, 'z78DA8D90490AC4300C0' + //Fire talisman + '4BF643B5A5A4779FBFF9322221F6618064281D1A14C4B6D0403D4' + + 'B5064D3C30A941E3CE1E5070D108268154977220B26442AA97F9E' + + '50F968069D3E64246864B4D2DCDE36F81E0CCCFAF9C3305AC5DFD' + + 'D3FFF732B872C5400BDEF8CF6ED6A0C10B3F77F3621C286624FD3' + + '8D9435E943D98616399A0C34FD6421497779D9E49867451DEBC6F' + + '735F54C5'); + bmp_Talis_Earth: Result := BitmapFromString(8, 8, 'z78DA75904B0EC43008' + //Earth talisman + '43AF940F60B34CD270FF230D52BB48A58E9EC402616C70A19318A' + + '849B391B8D5A4E9D49148D265259750800D4DCCB65DAADD0BBFAA' + + '84841671717678B2D0D1FFCE1F2E544C8CBBFF4A35ADDB7B03B56' + + 'AE56263FBB7F9A55A6A6ADE888408EC8FF93026C70746714DC02B' + + '9D062BCB9DF0BCE854B933B8DD38391EAFCD7CDCA3BA2F125B990' + + 'C1A1A3FFD2E52E3'); + bmp_Talis_Law: Result := BitmapFromString(8, 8, 'z78DA7D8F310EC3300C03' + //Law talisman + 'BFC42291C98E59F8FF27D58AEC3440DC420007FB0EA2049A6E6EC' + + '809850381DD7DB4A30F33376FAEECA406EB05FFB088E673F8C75A' + + 'F1B9E5DECAC174BE16FCC2D1BB93CC1BB0B24E6658C50BD4E4EBB' + + '7B2BADD5F2ADF9004A537760DFEC74545167DEDCA86F32E4CABF8' + + '0F8395533F'); + bmp_Talis_Nature: Result := BitmapFromString(8, 8, 'z78DA7D904B12C3200' + //Nature talisman + 'C43AF4400CBF21208DCFF48554216ED745ADEE08D7F92A332486F' + + '7E888C86964E0CFD6CDD9AA8A2D421CECAEA3EDD0430716281227' + + '0885D3F0C863D6147160F31BC881F5D1FF5E6DD1B935FEF56F59E' + + 'FD8E1CCC027E6AC7D6464F58DB0B3A8AA836A5ECD616992A90E3E' + + '5734FF8EFA8A530E1BC36351E4C5BE12F47115C9C0176B667D7A4' + + '0EF774ED3B570C29735BB65E288F5580'); + bmp_Talis_Chaos: Result := BitmapFromString(8, 8, 'z78DA7590490E433108' + //Chaos talisman + '43AF9401B05966F8B9FF918A94BFA0AACA93D860848D0B9DE4626' + + '383D963DBDC6AD074EA0824E8B2822D14D0B0B15EE5311A67A154' + + 'C95D558E1C2DE2E2ECF060A1A3BF1A8E3DD6973E5DA16262B020E' + + 'A4E83A8772BED2AB56ABDCEAFAB5F27B7E72CDE88803878FEEAD3' + + '0746710DC01D97062B4B4E94FF70B7DC79F878BC25D4C9DB4D848' + + '11A882D9B063D7A3E27C4541A'); + bmp_Talis_Death: Result := BitmapFromString(8, 8, 'z78DA8D903912433108' + //Death talisman + '43AFE46F10C225DEEE7FA490E4172E924C7833342C42B8B133AC5' + + 'B4D0481881535AE33ABCA4CB684B86D7B06B1B1ACC0E167679925' + + '4AA869492EE9D2A916F661E737159A0DEBDF7A005D3A1326AE552' + + 'B1785F27BF339E5CAC6F6CF3D101DDA9B3A93E04EA5C1CABB6AD3' + + 'D2E6F9073454541F7E7971E7E4786B79219297AFFBCFC0C40075E' + + 'B7E00C70F571C'); + bmp_Talis_Body: Result := BitmapFromString(8, 8, 'z78DA7D90510AC430084' + //Body talisman + '4AF94B4EA8C9F264DEE7FA4B5D88FC22EEB0311E2E818173A8940' + + '4F0E8BC4AD27870E8D2E1D217ACA4C2EA1000B9A982DBB6C1B935' + + '7BF4EB54465CBD6262ECE130EAF39957FA842459F572A06820D77' + + 'BC5D0D3B13D1953B6A0BB56B7F4F2E6F59DFF1CAA5AA1E3F8884D' + + '858E5EDFF45D15C13F0E264B0B395434C9CC997CA9D9BCB8D83F1' + + 'EC5ACC8F7B547591D8CC7BA05BF7078F8E53A4'); + bmp_Talis_Cosmic: Result := BitmapFromString(8, 8, 'z78DA7590498E05210' + //Cosmis talisman + 'C43AFC490C159068ADCFF483F2A508B5AB49E940D3676620403D4' + + 'B5264D5C7C148F4AF7E44E337908A4BA94139125CF7E15939A341' + + 'EEC3C5912A6A0E0424686AEA676FF2621486E9733F14901EBD04F' + + '87DDCAC9FB5F9F9D02AE5C31D1D03E7A6891F82412AFF4BC2E6B4' + + '8416E1CBA8EFEDDE8BF6E5E8C13C593498E8AB21BEAD49EBC77B8' + + '5D66082C130CF8C95AC8C31DD7BE33C99421CAC1F1030D395553'); + + + + bmp_FishGear_SmallNet: Result := BitmapFromString(9, 9, 'beNo9jAsLgkAQhPUv9EB8IGp32eW' + //small net | 14 may 2009 + 'dj0g5rgxNykKo/v+vaWQjGJbZ2W/Hsm96r1UCWZZNevcHzL4WptzC' + + 'fK7z2shEsoAAxYI6i7tj+uqq0WRzwgOa3npB74DLNPSd5aCz6VJi5' + + 'vz3vovd0ai5UzEwaeQ+Tmo08nnO0UkMAf9m5G3Fh0ZAtdrQ6W4kYb' + + 'rgKJnaAl4knmQ+AX0jAODEQgchTOStrC8oaB35'); + + bmp_FishGear_Rod: Result := BitmapFromString(9, 7, 'beNrz4gn29XV3crIyM7PT4mBgYAS' + // fishing rod | 14 may 2009 + 'iskj+CGfuYHtuMVFRoJSdlaW+jg5EKiuAz9OcE8iICArycnV1tLUB' + + 'qoFoiXXjAeoCsqNDQ3w9PIwN9OFa/Ky5gIyqGIHY8PAAby+IOJCb5' + + 'MUD1AVRE2zJDXdAXjAf0HaIGqCZfmZcEPG6eIE0X16gLoiWJAD1kR' + + '+/'); + + + bmp_FishGear_FlyRod: Result := BitmapFromString(8, 2, 'beNpjYIwICnJ3cmJgYGxKEswL5ot' + //fly fishing rod | 14 may 2009 + 'w5gayDRQUfD08IOJlkfxJXjwQcQYA4NgIiw=='); + + bmp_FishGear_Cage: Result := BitmapFromString(11, 13, 'beNp9kMEKgmAQhO9l' + // lobster cage | 14 may 2009 + '9jZBhyAMKy1TtNIIITxIWkkIXbz24g18HiJSGH5md4adf9cxd5NBN' + + 'B2CZNYinRsgWxg9Eujq58sR6JFKx1TZJQnV1jwf9n8l1HfTJGFI+S' + + 'OhCpHnVXkuUvvjb1xOJwzBxn0WV5E0jnWQIsvoKxri2nZ9K8nSNZh' + + 'GCVlZ1utxFzkGvq7BNKL18n8M6mhfphGtl70weOu1DHCi270+AGOC' + + 'kg=='); + + bmp_FishGear_Harpoon: Result := BitmapFromString(12, 11, 'beNpdjm0LwWAYhfmmvP4Ev' + //harpoon | 14 may 2009 + '0A0X1BMtJZayduIsVYm1DAawhDzVhL5wY7uepI6H552rl334eMi/4' + + '3L5V5Nza1l7RcLZ72+7rbzkdHXNAQVMYQhy8n4bG8A9FS121YojCE' + + 'MADD8rjYa9VJJazWRXwAnNrOZoesAmtUKmdktPO6Hw8M5msMB5Ios' + + 'lyUJH6PhMCLwHN7P8+l1ubxvN63gg5wkBMAAhg0eFAPpiAcGLCGGr' + + 'hTySWLMWrCc8bINTMLG2J2QIvhY9QfkUjFUmJHnPL9+bECFkESX/P' + + 'Wc928k2mwiIqbj4gf1xl5S'); + + // Updated to 8/9/2010 \\ + bmp_Axe_Bronze: Result := BitmapFromString(2, 5, 'meJxjYmBgYmCQ0rXhFYqU1LaEkDxC' + + 'YRAEAC7lA84='); + bmp_Axe_Iron: Result := BitmapFromString(2, 5, 'meJxjYmBgYmCwsbHnFYq0tLSBkDxC' + + 'YRAEADlGBGQ='); + bmp_Axe_Steel: Result := BitmapFromString(3, 3, 'meJxjYmBgAqP4+OTY2EReoUggGR0d' + + 'D2QAADcHBWM='); + bmp_Axe_Black: Result := BitmapFromString(2, 5, 'meJxjYmBgYmDg5eXjFYqEkzxCYRAE' + + 'AB3LAsk='); + bmp_Axe_Mithril: Result := BitmapFromString(3, 3, 'meJxjYmBgAiNvYyNPQ0NeoUgg6aav' + + 'D2QAACQhA6E='); + bmp_Axe_Adamant: Result := BitmapFromString(2, 5, 'meJxjYmBgYmAwszfjFYo0sTGBkDxC' + + 'YRAEADcjBEQ='); + bmp_Axe_Rune: Result := BitmapFromString(2, 5, 'meJxjYmBgYmDw9bDmFYr0drWCkDxC' + + 'YRAEAD7SBLU='); + bmp_Axe_Dragon: Result := BitmapFromString(2, 5, 'meJxzD6hnYmDwCm72DmnlE0n0CW3n' + + 'FYnnE03jFY7lE00GAHQiBxQ='); + bmp_Axe_Adze:Result := BitmapFromString(9, 9, 'beNqzM3azNYIgBgZGCJLlZFdVV' + //Azde Inferno Axe + 'gIy4OKtmopAZC/Mb29rBeQKCgpCxBs1FMpV5YqVZf0khIG6kKXq1O' + + 'WB4hkKUvGyEhBxIAAyfp9VB2rJV5IBajHm54FIeTqYABlvDshCjGr' + + 'PFciJ4IVIedgZAxl3t0hvnCA2u04Y4kKIaRCpQ/MkgFJwQYg4EEHM' + + 'RFYMRQASJSec'); + + + bmp_TinderBox: Result := BitmapFromString(6, 6, 'beNpz4F44bSoQzZs8aUZf' + //TinderBox + '7+TOjjgH7sXTpwPR/ClTZvX3A7lwEaAyCBcuAkRwEcIIABweKJI='); + bmp_Log_Normal: Result := BitmapFromString(6, 6, 'beNoLN6lLtISgxmRrIlF1nAVc' + //Normal Log + 'V0WMeVG4SX6oUZSrZqyHdqKXTqqvHhBlBOjDGdlBhkAFRQA4pCTw'); + bmp_Log_Oak: Result := BitmapFromString(6, 6, 'beNpLtu7NcUBD/XmOuBBQtj3DtjE' + //Oak Log + 'ZpKsry74l1aYu0bIixrwo3ATOyA4yBKL8UCMguzTKFChYHWcBlG0E' + + 'ABT7KQA='); + bmp_Log_Willow: Result := BitmapFromString(6, 6, 'beNpzkspJsQ3zlUNG+Wl2QIQ' + //Willow Log + 'mgqYmM9E6yFMWgqxNRYEIyHCwFENGMaEmnk5SCAQACP0arQ=='); + bmp_Log_Maple: Result := BitmapFromString(5, 10, 'beNqLi8sS58uT4CuT4l+W' + //Maple Log + 'Hb86LylNjBcoUizJDxRZkZuYJMoDRBBulbRAhDB3rAgPUD1QBKg+R' + + 'IgbKAIxYW1BMpANFIFo31iUxsDACERAA4Ead5RnQbhA2ToZgX3Vub' + + 'Hh4QmRkUkx0alxcekJCRAuVAQA3gcmog=='); + bmp_Log_Yew: Result := BitmapFromString(6, 6, 'beNqz54pz4yYJRTpzhdpzQRgQdoA' + //Yew Log + 'Np7cFp4MBu5sJBxAB2UAEFERmA1EoAAH/Fnk='); + + + bmp_Pick_Bronze: Result := BitmapFromString(4, 6, 'meJyzy+zxbVqr5him4RINRAaB2UE9' + + 'u8KnHGViYDAOLzaLrrTP7gOypXRtpPXt5IydgWxhBW0JTTNJbUsgm' + + '19SEYIA72QQQg=='); + bmp_Pick_Iron: Result := BitmapFromString(4, 6, 'meJzr7Z28eMlqNccwDZfo8PDooqLy' + + 'DRt27Nx5iImBoaCgtKysurOzH8i2sbGzs3N0dnYDsnV09MzNLS0tb' + + 'YBsfklFCAIA2E4VLg=='); + bmp_Pick_Steel: Result := BitmapFromString(4, 6, 'meJzr7p64cdMuNccwDZfo6Oj4vPzi' + + '/ftPnDx1mYmBoaysura2edKkGUB2bGxicnJ6ZmYukO3u7h0SGgFUD' + + 'GTzSypCEAA3bhhT'); + bmp_Pick_Mithril: Result := BitmapFromString(4, 6, 'meJwrjY5aUVig5him4RLtpq8fZG+/' + + 'tapyX2M9EwNDhItLrId7bmgIkO1haOBrYhxkbg5km6mqOOvqAkWAb' + + 'H5JRQgCAPRgELk='); + bmp_Pick_Adamant: Result := BitmapFromString(4, 6, 'meJxLL0/vmt+l5him4RKtb6bvHuQ+' + + 'ZfWUuVvnMDEwuPq7eoZ4hiWHAdlmdmYWjha2bjZAtoaehqGloYmNC' + + 'ZDNL6kIQQATZBE6'); + bmp_Pick_Rune: Result := BitmapFromString(4, 6, 'meJwrzAxfMa1AzTFMwyXazdEsOtB2' + + '66LKfavrmRgYEsMdU6NdyrMDgGx/L9sQP8eIIBcg28Zcz8PZwtfdG' + + 'sjml1SEIAA/HBKu'); + + bmp_Bow_CrossBow: Result := BitmapFromString(6, 5, 'beNorDWsuj4CgUA8DK0MFA0' + //CrossBow + '1pBgbGhhyP2iy3SG8jO1NlIBeI8uPs0sIs4wNNgWqA3Jxom+Rgc6A' + + 'CPyedxtKwuuJQoBTQBC97LYiWRgBeYxdg'); + bmp_Bow_Short_Normal: Result := BitmapFromString(5, 6, 'beNpjYMxNTWFgYEx35Qm' + //Normal Shortbow + '15AIyIAiZW+zHm+TEHWDGSZALZAM1RtpwgbgAJEYMuw=='); + bmp_Bow_Short_Oak: Result := BitmapFromString(5, 6, 'beNpjYMxNTWFgYGzK5M8O5' + //Oak Shortbow + 'wUyIAiZO7lCsC4NwZ1QCuKmB/PAuVXJfBAukA3UWBzLC+ICAMbvEP' + + 'w='); + bmp_Bow_Short_Willow: Result := BitmapFromString(5, 6, 'beNpjYMxNTWFgYCwv1E' + //Willow Shortbow + 'qKUQIyIAiZ295gUJKrCee21OoDuXGRinBuQZYGhAtkAzVmJquCuAD' + + '7BxJv'); + bmp_Bow_Short_Maple: Result := BitmapFromString(5, 6, 'beNpjYMxNTWFgYGzKS8+' + //Maple Shortbow + 'KCgEyIKghJxXOnVhVXJeVnBERBOH2VxZWZySlhgZAuL3lBZVpCcnB' + + 'fhApoMaihCgQFwCSBRZv'); + bmp_Bow_Long_Normal: Result := BitmapFromString(3, 5, 'beNoL4GNgYKwL5QeSyIw' + //Normal Longbow + '4e+6qYL7c1BQguzwApCY/Pb0cAItWB2w='); + bmp_Bow_Long_Oak: Result := BitmapFromString(3, 5, 'beNqrEGRgYFzQJAwkgWhuA5' + //Oak Longbow + 'RRnsA3q1YoNzUFyJ5eJQQk89PTJwMAtokJLQ=='); + bmp_Bow_Long_Willow: Result := BitmapFromString(3, 5, 'beNprMGBgYJzcbQIkgWh' + //Willow Longbow + 'ChzGEkZuu1ttqlJuaAmR3NRsCyfz09HYAyIoJyw=='); + bmp_Bow_Long_Maple: Result := BitmapFromString(3, 5, 'beNqrLGRgYJzbWgMkgWhm' + //Maple Longbow + 'YyWEUZIUA2TnpqYA2ZNrSoBkfnp6PwDx+wtt'); + + + + bmp_Food_Cooked_Meat: Result := BitmapFromString(16, 4, 'beNrzNK/24qME9YY5ICM02fYgO' + //Cooked Meat + '5LU1/la4VePrKUrxL4CAG1uOqY='); + bmp_Food_Cooked_Chicken: Result := BitmapFromString(7, 6, 'beNpz42NgYEy24Slx' + //Cooked Chicken + '4yv34Kv25i9w4QVygYLp9jxAbr0vP0QQKOKjx5ntyAsUafYXgAvGW' + + '3IDGUARIAKaAGQHGnIBTQCy2wIRgkDTIAb2hglCtANtLAEA2Uodkg' + + '=='); + bmp_Food_Cooked_Shrimps: Result := BitmapFromString(5, 6, 'beNpjYGRgQEFXJ0pd' + //Cooked Shrimps + 'LYCi2YHCXR6CvV4gVGDN66PB2ewqAET1zvzpZjyBWlwltnxA8WwL3' + + 'ngj7lBdLhSjAFtZEY0='); + bmp_Food_Cooked_Anchovies: Result := BitmapFromString(5, 6, 'beNpjYGRgQEHhCbM' + //Cooked Anchovies + 'KK1ZAUFB4ladvrrd/PhBZ20doaNm4eqYDkbN7irlVoLauva1jNFDc' + + '0ibUyNRb18AZxSgAqlITnw=='); + bmp_Food_Cooked_Tuna: Result := BitmapFromString(6, 6, 'beNorLWjMSqvLSClNiIU' + //Cooked Tuna + 'jCDc7IrQmLakqJRGI2vOzW/MygVyILJABFIEINudkABGQ3VOcD0Sd' + + 'hblwNrMcCxD1lRZAEQC2dS0+'); + bmp_Food_Cooked_Trout: Result := BitmapFromString(6, 7, 'beNpjYPS0sQp2cYrwdI' + //Cooke Trout + 'vz9U4M8E0LCQSyo709gOzkIP/siNDiuGigFJCdFxVemhBbnhRfk5Y' + + 'EYVelJNZlpDRmpbXnZwMFgYzmnIzWvMye4vwZtRVABlAcyJ5QVjSr' + + 'vmpeUy2EPaWqFMhd0FLPAAA4fzKj'); + bmp_Food_Cooked_Pike: Result := BitmapFromString(6, 6, 'beNpjYAzO9QzL944q9Y+' + //Cooked Pike + 'rCkpuDM/ujoso8gWyU1sic3vjCyYlFU1JgbCBjJLpqeWzM+qW5EEY' + + 'lXOzahblNq4o7NtRA2QAxeuXFbSsKQFypxxobF5VBGS3byjv31U79' + + 'VAzAwDhYjLo'); + bmp_Food_Cooked_Salmon: Result := BitmapFromString(6, 6, 'beNpjYJxoKDjdWGieq' + //Cooked Salmon + 'fASc5EN1qJ77MVnm4DYm23E9juIH3WSOOUiCWEfd5Y46yp5yV3qvr' + + 'c0UPCCm+RVD6lbntJPfGV+hMjd8JS66yX9yEf6lb/M7xD53ynWQHE' + + 'g+12A7O8I9d8ZjgwAEyYpag=='); + bmp_Food_Cooked_Lobster: Result := BitmapFromString(6, 6, 'beNqLFd2WILY/VfxS' + //Cooked Lobster + 'vtSTChkgYmBgRBb51igHFNmZCBJJN+OBKICLiAoLwxFEZZu7wBQ/o' + + 'YWhwquiRIHcLg/B6QEg7tpo0Q0AZhkgFw=='); + bmp_Food_Cooked_Swordfish: Result := BitmapFromString(6, 6, 'beNorWZPvX1oWUlM' + //Cooked Swordfish + 'd3tgU05njWxRpH9efOn1i+kwg2RbfWxvZku6Zu7R03dyCZVOz5vam' + + 'TAEKVoTWLyxaBRScX7hicsZsoGBLXDeQvbhkDVBwZcWmmbmLupMmM' + + 'TAwQtDy8g1AwcUA+4QyqA=='); + + + + bmp_Food_Raw_Meat: Result := BitmapFromString(6, 6, 'beNpbMH+eojAa2rtlM6kiO9ev' + //Uncooked Meat + 'A4ogC25avgxNyxoATJwnrQ=='); + bmp_Food_Raw_Chicken: Result := BitmapFromString(6, 6, 'beNqbOnltd+eSlqYZVRXTKso39v' + //Uncooked Chicken + 'UcXb50x5RJ63u7l7U2z6uvBbJPrlt7YP68PTNnbJs8cXVXx8GF84+' + + 'vXnlo8UKIIFABkH1s5XKgRojgvtmzgGqAXLjg/rlzgCp3AQAyD0Ta'); + bmp_Food_Raw_Shrimps: Result := BitmapFromString(5, 6, 'beNpjYGRgQEEntq6' + //Uncooked Shrimps + '+urDl2uI2IJpbFNGXHjAhM3BydnBxsKO/pU5bok9LvFdjrGeWr02w' + + 'jV5ZqBNQPNffNsHNLMzOAMUoAMXOGRE='); + bmp_Food_Raw_Anchovies: Result := BitmapFromString(5, 6, 'beNpjYGRgQEGtrSumTVsEQdnZJYmJ' + //Uncooked Anchovies + 'mcnJ2ampuf7+oSYmFtHRSUAUERHv4eFrbm4NFPT1DfbyCrB3cLWys' + + 'kMxCgBC+RaW'); + bmp_Food_Raw_Tuna: Result := BitmapFromString(6, 6, 'beNrbuWP57NlLZ82c2de3aNo0CI' + //Uncooked Tuna + 'Jwe5qaVs2bt3LuHKCCTcuXrVu0ECg1vbcHyFizYP7O9euAaNua1Vt' + + 'Xrdy8YgWQvX/rViDavXEDnM0sxwJEB7Zvh6CDAFeXQxc='); + bmp_Food_Raw_Trout: Result := BitmapFromString(6, 6, 'beNpjYKwpKW4oL2+r' + //Uncooked Trout + 'relpapre27Ng6pSW6moIe9G0actnz141b97Mvr4lM2YAGesWLdy4d' + + 'MnujRuAjE3Ll21dtXLH2rX7t249f+IEkAEU37tl8+Fduy6cOnn94s' + + 'UD27cD2cf37794+vSNS5cYAE5gRKA='); + bmp_Food_Raw_Pike: Result := BitmapFromString(6, 6, 'beNpjYPRP9g9MCwzNDo0siIwvj0' + //Uncooked Pike + '9rTAvODAayE6sSM5ozMluzcjtzIWwgI78nv6CvsGJGJZBRNKGoZFJ' + + 'J6ZSymjk1bSvbgQygeNWs6voF9UBuz8ZeoDiQ3bSkqWN1R9/mPgYA' + + 'pjMxzQ=='); + bmp_Food_Raw_Salmon: Result := BitmapFromString(6, 6, 'beNpjYKzwdakLcG8J' + //Uncooked Salmon + '8eoM950cGzw3JaIxyBPInhofMj81aklGzIrseAh7WVbc6tyE9fnJu' + + '8oygYJr85I2FqZsK0nbV5l9vqV0S1HqjtKMPRVZh2vyLraWXelrBI' + + 'oD2cfrCi61V16d2MIAABAOM8M='); + bmp_Food_Raw_Lobster: Result := BitmapFromString(6, 6, 'beNpzli1zlq11l+/wVZoSorowWo' + //Uncooked Lobster + 'OBgREi4qwmCBQBcoGoylUOKCIqLAxHS2I1geLhhqLxZhLp1lL59tL' + + 'I3GJHGSAK0hdJtpDMtpUGsoFmlgEA7aQW+g=='); + bmp_Food_Raw_Swordfish: Result := BitmapFromString(6, 6, 'beNpbfGli+szp2fPnFixbWrquO' + //Uncooked SwordFish + '2lSYUD5juZDe1qPAcm11dvmF65oi+89s/Ty0Rln93Wd2NZ4YHXllt' + + 'l5S07MuwAUPDbr3N6O45vq96ys2ARkQwTPr752cOKpjbW7GBgYIej' + + 's8itAwdMAElVAsw=='); + + + + bmp_Bucket_Empty: Result := BitmapFromString(6, 6, 'beNrLs03ylgCiOA9xIIpyFUuOi' + //Empty Bucket + 'UETCXMShXMhImnxcWgiWclJFtp8Rmo8QKStyAVEhZmZeSHSyKgdAO' + + '2EG5o='); + bmp_Bucket_Water: Result := BitmapFromString(6, 6, 'beNrLs62smkkQ2er' + //Bucket of water + 'zW2jzGanxAJG2IhcQ5YVIo6G6dMvGTOuWHJv2PNuuAvveYoeKJPPq' + + 'FAuEOAAStSgC'); + + + + bmp_Bones_Normal: Result := BitmapFromString(5, 5, 'beNpjYGRgAKEbly71t7' + //Normal Bones + 'YCGWeOHrl19eqGJUvS4uOA3KN795w6fLiutKStpmZqV1d5fv78KVO' + + 'AUkBGR13t3s2bc1NTISYwAAC6Yh+e'); + bmp_Bones_Big: Result := BitmapFromString(6, 6, 'beNpjYLx6/nx/a2tLVdWMv' + //Big Bones + 't7V8+fPnzLl1OHD8yZPYmBghKDpPd2bVyxfu3ABkH322LFj+/Yd2L' + + '5t57p1m5YtWzVv7sJpU4EagSbkpqYmRkVFBQeH+vv5e3m6OzlB0LL' + + 'Zs4Da923dwgAASxQz+w=='); + + + + bmp_Uncut_Sapphire: Result := BitmapFromString(6, 6, 'beNoTyOMTqoAjQbHJXLzRELaASBeU' + //Uncut Sapphire + 'IdoH4cJFwKgaP+LmT0Tj8gAApDsVnw=='); + bmp_Uncut_Emerald: Result := BitmapFromString(6, 6, 'beNrL5OctFIQjgS4Rr' + //Uncut Emerald + 'kheCJu/SRjKaBfhLRbkbxEGIiCDSMQVzYvG5QEAb5UUXA=='); + bmp_Uncut_Ruby: Result := BitmapFromString(6, 6, 'beNoT4koW4YGjSgk+X35OCLtInB' + //Uncut Ruby + 'fCKBPng3DhIkCUJkoABQhwonGjAfq6Erg='); + bmp_Uncut_Diamond: Result := BitmapFromString(6, 6, 'beNprbZk+aRIc7dy0q' + //Uncut Diamond + 'Tw/H8Jet3w5hLFl7dqZkydvWLECiIAMKJoyBT+qKy1F4/YAAI4EPw' + + 'U='); + + + + bmp_Cut_Sapphire: Result := BitmapFromString(6, 6, 'beNoTKu3omI2Mpk7bgM' + //Cut Sapphire + 'zlFyoFIjQuXATOhYggc7EgANgkJpk='); + bmp_Cut_Emerald: Result := BitmapFromString(6, 6, 'beNrLFbTZo4mMpm6eiMzlyxUEIj' + //Cut Emerald + 'QuXATOhYggc7EgAFXLHbk='); + bmp_Cut_Ruby: Result := BitmapFromString(6, 6, 'beNoT5VlclI+M1k/vR+YmiPIAERo' + //Cut Ruby + 'XLgLnQkSQuVgQANj/IqY='); + bmp_Cut_Diamond: Result := BitmapFromString(6, 7, 'beNqrr1uxdCky2r1jMzK3vb4' + //Cut Diamond + 'OiNC4cBE4FyKCzCUKAQBys0a9'); + + bmp_Ring_Ruby: Result := BitmapFromString(2, 6, 'beNpbIr5BVRSIbulKA' + // ruby ring. 14 Jun 2009 + 'VGAG+dxTYnpLUL5iby39ksBGb/vWe8BAO0FDjM='); + + bmp_GE: Result := BitmapFromString(5, 15, 'beNpbW7q1mOH5Wobnexn+/38PZ' + //Used in GE Functions + 'FgaSrRYQlGQpSZ1ZaudOCCyUZYMaLLVTootbpoQ2WJLxfdri9/vav' + + 'm+d873Y3O/n9v4fW8PkHtvIwhdm1P8fmv1ymwnoBXZXoZTkp2uTUk' + + 'Gcu/1RQF1/T/Wc29S8vOl2ffmgMjnAECCbl0='); + + end; + srl_Bitmaps[ID] := Result; + srl_BitmapSet[ID] := True; +end; + +(* +srl_LoadBitmaps +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure srl_LoadBitmaps(IDs: TIntegerArray); + +Preloads bitmaps identified by ID in the srl bitmaparray. + +.. note:: + + Author: Nielsie95 + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + srl_LoadBitmaps(bmpArray); +*) +procedure srl_LoadBitmaps(IDs: TIntegerArray); +var + i, h: Integer; +begin + h := High(IDs); + for i := 0 to h do + if (not srl_BitmapSet[IDs[i]]) then + srl_GetBitmap(IDs[i]); +end; + +(* +srl_LoadBitmapRange +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure srl_LoadBitmapRange(StartID, EndID: Integer); + +Preloads bitmaps identified by ID in range StartID to EndID + +.. note:: + + Author: Nielsie95 + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + srl_LoadBitmapRange(bmp_Uncut_Emerald, bmp_Uncut_Diamond); +*) +procedure srl_LoadBitmapRange(StartID, EndID: Integer); +var + I: Integer; +begin + if (StartID > EndID) then + srl_Warn('srl_LoadBitmapRange', 'EndID is greater than StartID!', warn_AllVersions); + for I := StartID to EndID do + if (not srl_BitmapSet[I]) then + srl_GetBitmap(I); +end; + +(* +srl_FreeBitmapEx +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure srl_FreeBitmapEx(which: integer); + +Frees SRL bitmap which + +.. note:: + + Author: Rasta Magician + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + srl_FreeBitmapEx(bmp_Uncut_Emerald); +*) +procedure srl_FreeBitmapEx(which: integer); +begin + try + FreeBitmap(srl_Bitmaps[which]); + srl_BitmapSet[which] := False; + except end; +end; + +(* +srl_FreeBitmapArray +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure srl_FreeBitmapArray(bmpArr: TIntegerArray); + +Frees an array of assigned SRL bitmaps determined by bmpArr. + +.. note:: + + Author: EvilChicken! + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + srl_FreeBitmapArray([bmp_Uncut_Emerald, bmp_Uncut_Ruby]); +*) +procedure srl_FreeBitmapArray(bmpArr: TIntegerArray); +var + I, Lo, Hi: Integer; +begin + Lo := Low(bmpArr); + Hi := High(bmpArr); + for I := Lo to Hi do + srl_FreeBitmapEx(I); +end; + +(* +srl_FreeBitmaps +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure srl_FreeBitmaps; + +Frees all SRL bitmaps + +.. note:: + + Author: Nielsie95, edited by Rasta Magician + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + srl_FreeBitmaps; +*) +procedure srl_FreeBitmaps; +var + i: Integer; +begin + for i := 0 to (srl_BitmapCount - 1) do + srl_FreeBitmapEx(i); +end; + +(* +srl_FreeBitmapRange +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure srl_FreeBitmapRange(StartID, EndID: Integer); + +Frees all SRL bitmaps with IDs ranging from StartID to EndID. + +.. note:: + + Author: EvilChicken! + Last Modified: Unknown + +Example: + +.. code-block:: pascal + + srl_FreeBitmapRange(bmp_Uncut_Emerald, bmp_Uncut_Diamond); +*) +procedure srl_FreeBitmapRange(StartID, EndID: Integer); +var + I: Integer; +begin + if (StartID > EndID) then + srl_Warn('srl_FreeBitmapRange', 'EndID is greater than StartID!', warn_AllVersions); + for I := StartID to EndID do + srl_FreeBitmapEx(I); +end; diff --git a/SRL/core/cautorespond.simba b/SRL/core/cautorespond.simba new file mode 100644 index 0000000..03795dc --- /dev/null +++ b/SRL/core/cautorespond.simba @@ -0,0 +1,28 @@ +//-----------------------------------------------------------------// +//-- SRL Resource Library --// +//-- » AutoRespond Routines --// +//-----------------------------------------------------------------// +// * procedure SetupSRLAutoResponder; // by ??? +// * function Respond: Boolean; // by ??? + +var + UseAutoResponder: Boolean; + +{******************************************************************************* +procedure SetupSRLAutoResponder; +By: ??? +Description: +*******************************************************************************} +procedure SetupSRLAutoResponder; +begin +end; + +{******************************************************************************* +function Respond: Boolean; +By: ??? +Description: +*******************************************************************************} +function Respond: Boolean; +begin + Result := False; +end; diff --git a/SRL/core/chat.simba b/SRL/core/chat.simba new file mode 100644 index 0000000..d720a95 --- /dev/null +++ b/SRL/core/chat.simba @@ -0,0 +1,915 @@ +(* +Chat +==== + +The Chat include contains all chat-related functions + +.. contents:: + +*) + +const + CHAT_GAME = 0; + CHAT_PUBLIC = 1; + CHAT_PRIVATE = 2; + CHAT_FRIENDS = 3; + CHAT_CLAN = 4; + CHAT_TRADE = 5; + CHAT_ASSIST = 6; + +(* +.. code-block:: pascal + + const + CHAT_GAME = 0; + CHAT_PUBLIC = 1; + CHAT_PRIVATE = 2; + CHAT_CLAN = 3; + CHAT_TRADE = 4; + CHAT_ASSIST = 5; +*) + +(* +SetChat +~~~~~~~ + +.. code-block:: pascal + + function SetChat(state: string; chat: Integer): Boolean; + +Sets Chat to desired state +Game Public Private Clan Trade Assist +0 1 2 3 4 5 + + +.. note:: + + by Wizzup?, WT-Fakawi, Starblaster100, N1ke! & Coh3n + +Example: + +.. code-block:: pascal + + +*) +function SetChat(state: string; chat: Integer): Boolean; +var + x, y, mx, Color: Integer; +begin + result := false; + mx := 90 + (chat * 55); + + if (not InRange(chat, CHAT_GAME, CHAT_ASSIST)) then + begin + srl_Warn('SetChat', 'chat(' + IntToStr(chat) + ') does not exist.', warn_AllVersions); + Exit; + end; + + case Lowercase(State) of + 'on', 'all': Color := 65280; + 'off': Color := 255; + 'hide': Color := 16776960; + 'friends', 'filter': Color := 65535; + else + srl_Warn('SetChat', state + ' does not exist.', warn_AllVersions); + end; + + if (not FindColor(x, y, Color, mx - 10, 486, mx + 10, 502)) then + begin + Mouse(mx, 496, 4, 4, mouse_right); + Wait(RandomRange(50, 150)); + + if (Lowercase(State) = 'off') then + begin + case chat of + CHAT_PUBLIC, CHAT_ASSIST: Mouse(mx, 496 - 33, 8, 3, mouse_left); + CHAT_PRIVATE..CHAT_TRADE: Mouse(mx, 496 - 20, 8, 3, mouse_left); + end; + + Wait(RandomRange(50, 150)); + Result := FindColor(x, y, Color, mx - 10, 486, mx + 10, 502); + end else + Result := WaitOption(Capitalize(State), 300); + end; +end; + +(* +SetAllChats +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SetAllChats(Game, Pub, Priv, Clan, Trade, Assist: string); + +Sets all the chats to a particular state in one simple procedure. +Leave the parameter as '' if you wish to leave the chat as it is. + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + + SetAlChats('all', 'Hide', '', 'Off', '', 'Friend'); + +*) +procedure SetAllChats(Game, Pub, Priv, Friends, Clan, Trade, Assist: string); +var + States: TStringArray; + II: Integer; +begin + if (not(LoggedIn)) then Exit; + States := [Game, Pub, Priv, Friends, Clan, Trade, Assist]; + for II := 0 to 6 do + begin + if (States[II] = '') then Continue; + SetChat(States[II], II); + end +end; + +(* +ChatsOff +~~~~~~~~ + +.. code-block:: pascal + + procedure ChatsOff; + + +Sets all Chats to off. + +.. note:: + + by Starblaster100 + +Example: + +.. code-block:: pascal + + + +*) +procedure ChatsOff; +var + i: Integer; +begin + for i := 1 to 6 do + SetChat('off', i); +end; + + +(* +ChatWait +~~~~~~~~ + +.. code-block:: pascal + + procedure ChatWait; + +Waits while there's Please Wait in the chatbox. + +.. note:: + + by Nielsie95 + +Example: + +.. code-block:: pascal + + + +*) +procedure ChatWait; +begin + Wait(400 + Random(500)); +end; + +(* +ClickContinueEx +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClickContinueEx(Click, Wait: Boolean): Boolean; + + +Returns true if the blue 'Click To Continue' text in the chat box is found. +If will click if Click = True, calls ChatWait if Wait = True. + +.. note:: + + by _ChArMz & Narcle (Original by EvilChicken!) + +Example: + +.. code-block:: pascal + + + +*) +function ClickContinueEx(Click, Wait: Boolean): Boolean; +var + bTxt, wTxt, SearchTPA, TextTPA, Matches : TPointArray; + Search2D : T2DPointArray; + b : TBox; + Height, i, x, y : Integer; +begin + Result := false; + FindColorsTolerance(bTxt, 8388608, MCX1, MCY1, MCX2, MCY2, 10); + FindColorsTolerance(wTxt, 16777215, MCX1, MCY1, MCX2, MCY2, 10); + + SearchTPA := CombineTPA(bTxt, wTxt); + if Length(SearchTPA) < 1 then + Exit; + + Search2D := SplitTPAEx(SearchTPA, 20, 2); + + TextTPA := LoadTextTPA('here to conti', NPCChars, Height); + for i := 0 to High(Search2D) do + begin + Result := FindTextTPAinTPA(Height, TextTPA, Search2D[i], Matches); + if Result and Click then + begin + b := GetTPABounds(Search2D[i]); + GetMousePos(x, y); + if PointInBox(Point(x, y), b) then + Mouse(x, y, 2, 1, true) + else + with b do + Mouse(RandomRange(x1, x2), RandomRange(y1 + 2, y2 - 2), 2, 1, true); + if Wait then + ChatWait; + end; + if Result then + Break; + end; +end; + +(* +ClickContinue +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClickContinue(SpaceBar, DoWait: Boolean): Boolean; + + +Returns true if the green button in the chat box is found. +It will SpaceBar if true otherwise will mouse it. If DoWait = true +will wait until color count changes. + +.. note:: + + by _ChArMz & Narcle (Original by EvilChicken!) + +Example: + +.. code-block:: pascal + + + +*) +Function ClickContinue(SpaceBar, DoWait: Boolean): Boolean; +var + TPA: TPointArray; + i, C, T: integer; + B: TBox; + ATPA: T2DPointArray; +begin + if ClickContinueEx(SpaceBar, DoWait) then + begin + Result := true; + Exit; + end; + C := GetColorToleranceSpeed; + SetColorToleranceSpeed(1); + FindColorsTolerance(TPA, 11776948, MCX1, MCY1, MCX2, MCY2, 15);//color is constant atm + SetColorToleranceSpeed(C); + if Length(TPA) < 1 then + Exit; + ATPA := SplitTPA(TPA, 2); + for i := 0 to High(ATPA) do + begin + B := GetTPABounds(ATPA[i]); + if InRange(B.x2-B.x1, 58, 72) then + if (CountColorTolerance(1203763, B.x1-5, B.y1+1, B.x2+5, B.y1+15, 37) > 50) then + begin + C := CountColor(0, MCX1, MCY1, MCX2, MCY2); + if SpaceBar then + TypeByte(VK_SPACE) + else + Mouse(B.x1, B.y1, (B.x2-B.x1), 8, true); + Result := True; + T := GetSystemTime + 10000; + if DoWait then + while (C = CountColor(0, MCX1, MCY1, MCX2, MCY2)) and (GetSystemTime < T) do + Wait(50+random(50)); + Exit; + end; + end; +end; + +(* +ClickToContinue +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClickToContinue: Boolean; + +Click the blue 'Click To Continue' text in the chat box. + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + + + +*) +function ClickToContinue: Boolean; +begin + Result := ClickContinue(True, False); +end; + +(* +TextCoords +~~~~~~~~~~ + +.. code-block:: pascal + + Function TextCoords(textn: Integer): TPoint; + +Returns x, y for text. (1 to 8) + +.. note:: + + by Wizzup? + +Example: + +.. code-block:: pascal + + + +*) +function TextCoords(textn: Integer): TPoint; +begin + Result.X := 10; + Result.Y := 346 + (14 * (textn - 1)); +end; + +(* +GetChatBoxText +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetChatBoxText(Line, TextCol: Integer): string; + +Gets text on the line Line with colour TextCol. +(Line 1 is the top, Line 8 is the bottom line). +Colours: + + - clMessage/clBlack - Black text messages ("Oh Dear you are dead", etc). + - clChat/clBlue - Chat messages from you and other players. + - clTrade/clPurple - Colour of trade request text. + - clFriend - Colour of friend and clan chat. + +Works with other colours too. + + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + + +*) +function GetChatBoxText(Line, TextCol: Integer): string; +var + P: TPoint; + cArr: TPointArray; + B: TBox; +begin + Result := ''; + P := TextCoords(Line); + if (FindColorsTolerance(cArr, TextCol, MCX1, P.y, MCX2, P.y + 13, 0)) then + begin + B := GetTPABounds(cArr); + result := Trim(GetTextAtExWrap(b.x1-1,p.y,B.x2+1,p.y+13,0,5,2,TextCol,0,SmallChars)); + end; +end; + +(* +FindChatBoxText +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindChatBoxText(Text: string; Line: Integer; TextCol: Integer): Boolean; + +Searches for Text on Line with colour TextCol. True if found. + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + + + +*) +function FindChatBoxText(Text: string; Line: Integer; TextCol: Integer): Boolean; +begin + Result := (Pos(Text, GetChatBoxText(Line, TextCol)) > 0); +end; + +(* +IsChatBoxTextBetween +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function IsChatBoxTextBetween(Text: string; TextCol, StartLine, EndLine: Integer): Boolean; + +Returns true if Text with colour TextCol is found anywhere in the chat box. + + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + + +*) +function IsChatBoxTextBetween(Text: string; TextCol, StartLine, EndLine: Integer): Boolean; +var + II: Integer; +begin + Result := True; + for II := Max(StartLine, EndLine) downto Min(StartLine, EndLine) do + if (FindChatBoxText(Text, II, TextCol)) then + Exit; + Result := False; +end; + +(* +IsChatBoxTextAnyLine +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function IsChatBoxTextAnyLine(Text: string; TextCol: Integer): Boolean; + +Returns true if Text with colour TextCol is found anywhere in the chat box. + + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + +*) +function IsChatBoxTextAnyLine(Text: string; TextCol: Integer): Boolean; +begin + Result := IsChatBoxTextBetween(Text, TextCol, 1, 8); +end; + +(* +ChatBoxTextArray +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ChatBoxTextArray(TextCol: Integer): TStringArray; + + Gets and return a TStringArray with the contents of each line + with the colour TextCol (see GetChatBoxText for list of colours). + + Gets and return a TStringArray with the contents of each line + with the colour TextCol (see GetChatBoxText for list of colours). + - Line 1 is Result[1] + - Line 2 is Result[2] + - Line 3 is Result[3] + - Line 4 is Result[4] + - Line 5 is Result[5] + - Line 6 is Result[6] + - Line 7 is Result[7] + - Line 8 is Result[8] + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + + +*) +function ChatBoxTextArray(TextCol: Integer): TStringArray; +var + II: Integer; +begin + SetLength(Result, 9); + for II := 8 downto 1 do + Result[II] := GetChatBoxText(II, TextCol); +end; + +(* +GetBlackChatMessage +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetBlackChatMessage: String; + +Gets text with color 0 in last chat line. + +.. note:: + + by Wizzup? + +Example: + +.. code-block:: pascal + +*) +function GetBlackChatMessage: string; +begin + Result := GetChatBoxText(8, clMessage); +end; + +(* +FindBlackChatMessage +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindBlackChatMessage(ChatMsg: String): Boolean; + +Returns True if text with color 0 in last chat line is found. + +.. note:: + + by Wizzup? + +Example: + +.. code-block:: pascal + + +*) +function FindBlackChatMessage(ChatMsg: string): Boolean; +begin + Result := (Pos(ChatMsg, GetChatBoxText(8, clMessage)) > 0); +end; + +(* +LastChatter +~~~~~~~~~~~ + +.. code-block:: pascal + + function LastChatter(var name: String): Boolean; + +Returns name and true if a person was talking, or false and the text + +.. note:: + + by masquerader + +Example: + +.. code-block:: pascal + + +*) +function LastChatter(var name: string): Boolean; +var + i: Integer; +begin + Result := False; + Name := LowerCase(GetBlackChatMessage); + i := Pos(':', name); + if (i <> 0) then + begin + Delete(Name, i, i); + Result := True; + end; +end; + +(* +GetLastChatText +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetLastChatText(var chat: String): Boolean; + +Returns true if blue chat text was found + +.. note:: + + by masquerader / Wizzup? + +Example: + +.. code-block:: pascal + + +*) +function GetLastChatText(var chat: string): Boolean; +begin + Chat := GetChatBoxText(8, clChat); + Result := (Chat <> ''); +end; + +(* +InChat +~~~~~~ + +.. code-block:: pascal + + function InChat(Text: String): Boolean; + +Grabs Last Chat Line and performs checks on occurence of text + + +.. note:: + + by WT-Fakawi + +Example: + +.. code-block:: pascal + + +*) +function InChat(Text: string): Boolean; +var + s: string; +begin + if (not (GetLastChatText(s))) then + LastChatter(s); + + Result := (Pos(LowerCase(Text), Lowercase(s)) > 0); +end; + +(* +FixChat +~~~~~~~ + +.. code-block:: pascal + + procedure FixChat; + +Scrolls ChatText scrollbar down. + +.. note:: + + by WT-Fakawi + +Example: + +.. code-block:: pascal + + +*) +procedure FixChat; +var + ScrollX, ScrollY: Integer; +begin + ScrollX := 507 + Random(8); + ScrollY := 451 + Random(8); + if (GetColor(505, 439) = 2041131) then + begin + MMouse(ScrollX, ScrollY, 0, 0); + HoldMouse(ScrollX, ScrollY, mouse_left); + while (GetColor(505, 439) = 2041131) do + Wait(10 + random(15)); + Wait(50+random(50)); + ReleaseMouse(ScrollX, ScrollY, mouse_left); + Wait(100+random(50)); + end; +end; + + +(* +SaveToChatLog +~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SaveToChatLog; + +Saves chat to log file. + +.. note:: + + by WT-Fakawi & masquerader + +Example: + +.. code-block:: pascal + + +*) +procedure SaveToChatLog; +begin + FixChat; + OldLine := TheLine; + + if(LastChatter(TheName))then + begin + GetLastChatText(TheLine); + TheLine:=' '+TheLine+' '; + if OldLine <> TheLine then + try AddToSRLLog(TheName+':'+TheLine); except end; + end else + begin + TheLine:=TheName; + if OldLine <> TheLine then + try AddToSRLLog(TheLine); except end; + end; +end; + +(* +ColorEffectAdd +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ColorEffectAdd(Color, Effect: Boolean): string; + +Returns a RS chat effect based on 'Color' and 'Effect' booleans. + +.. note:: + + by NiCbaZ + +Example: + +.. code-block:: pascal + + +*) +function ColorEffectAdd(Color, Effect: Boolean): string; +var + Str : TStringArray; + +begin + Result := ''; + Str := ['flash1:', 'flash2:', 'flash3:', 'glow1:', 'glow2:', 'glow3:', 'red:', + 'green:', 'cyan:', 'purple:', 'white:', 'scroll:', 'shake:', 'slide:', + 'wave:', 'wave2:']; + if Color then + Result := Str[Random(11)]; + if Effect then + Result := Result + Str[11 + Random(5)]; +end; + +(* +GetNPCChatName +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetNPCChatName(): string; + +Gets the name of the random event NPC from the top of the chat box. The proper +font doesn't exist yet, so it returns a random string of characters. + +.. note:: + + Author: DemiseSythe + Last Modified: Jan. 22nd, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + writeln(getNPCChatName()); +*) +function GetNPCChatName(): string; +begin + result := getTextAtExWrap(152, 345, 366, 370, 0, 50, 30, 7913190, 15, NPCChars); +end; + +(* +AreTalking +~~~~~~~~~~ + +.. code-block:: pascal + + function AreTalking(): boolean; + +Returns true if player is talking to an NPC. + +.. note:: + + Author: Wizzup? + Last Modified: Jan. 22nd, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + while (areTalking()) do + clickContinue(true, true); +*) +function AreTalking(): boolean; +begin + result := (getNPCChatName <> ''); +end; + +(* +DoConversation +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function DoConversation(resultText: string; clickresult: boolean): boolean; + +Goes through the initial dialog of a random. Will keep clicking to continue +until the conversation's 'resultText' is found. Will click to continue when +'resultText' is found if 'clickresult' is set to true. Set 'resultText' to '' +to click continue until conversation is over. + +.. note:: + + Author: Coh3n + Last Modified: Jan. 22nd, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + if (DoConversation('thank', true)) then + writeln('Finished conversation'); +*) +function DoConversation(resultText: string; clickResult: boolean): boolean; +var + t: integer; +begin + while (t < 25) do // max of 25 "click to continue's" + begin + if (resultText <> '') then + if (findNPCChatText(resultText, nothing)) then + begin + if (clickResult) then + clickContinue(true, true); + + result := true; + break; + end; + + // break if there's no more conversation + if (not clickContinue(true, true)) then + break; + + wait(100 + random(200)); + inc(t); + end; +end; + +(* +PlayerChatActive +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function PlayerChatActive: Boolean; + +Return true if player chat is active. + +.. note:: + + by riwu + +Example: + +.. code-block:: pascal + +*) +function PlayerChatActive: Boolean; +begin + Result:= not FindChatBoxText('Press Enter to Chat', 9, clBlack); +end; diff --git a/SRL/core/color.simba b/SRL/core/color.simba new file mode 100644 index 0000000..f0ad77f --- /dev/null +++ b/SRL/core/color.simba @@ -0,0 +1,593 @@ +(* +Color +===== + +The Color include contains all Colorfinding routines. + +.. contents:: + +.. note:: + + Remove?: + - FindDeformed + - DTMRotated + - GetColorsBox? + +*) + +(* +FindDeformed +~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindDeformed(var Xoff, Yoff: Integer; BMP, a, b, c, d: Integer): Boolean; + +Finds Bitmap in Box a,b,c,d. Returns coords in ObjX and ObjY. +Uses Deformed Bitmap. FindDeformed will gradually lower Tol and reduce Accuracy. +Functon can cause severe Lag when using bitmaps bigger then 16 pixels. Works but Lags. +Useful for MM-clicking. For ObjectFinding use FindObjectDeformed. + + +.. note:: + + by WT-Fakawi + +Example: + +.. code-block:: pascal + + +*) +function FindDeformed(var Xoff, Yoff: Integer; BMP, a, b, c, d: Integer): + Boolean; +var + acc, ref: Extended; + XT, YT, times, tol: Integer; +begin + result := false; + ref := 0.9; + tol := 0; + for times := 1 to 50 do + begin + FindDeformedBitmapToleranceIn(BMP, XT, YT, a, b, c, d, tol, 2, True, acc); + if (acc >= ref) then + begin + Xoff := XT; + YOff := YT; + Result := True; + Exit; + end; + if (Times mod 5 = 0) then + begin + ref := ref - 0.1; + tol := tol + 10; + end; + Wait(1); + end; +end; + +(* +FindColorsPie +~~~~~~~~~~~~~ + +.. code-block:: pascal + + + function FindColorsPie(var Points: TPointArray; Color, Tol: Integer; StartD, + EndD, MinR, MaxR: Extended; x1, y1, x2, y2, Mx, My: Integer): Boolean; + +Finds all Colors with tolerance in the Pie, defined by x1, y1, x2, y2, Mx, My, +StartDegree, EndDegree, MinRadius and MaxRadius. + +.. note:: + + by Wizzup?, edit by EvilChicken! + +Example: + +.. code-block:: pascal + + +*) +function FindColorsPie(var Points: TPointArray; Color, Tol: Integer; StartD, + EndD, MinR, MaxR: Extended; x1, y1, x2, y2, Mx, My: Integer): Boolean; +begin + Result := FindColorsTolerance(Points, Color, x1, y1, x2, y2, Tol); + if (Result) then + FilterPointsPie(Points, StartD, EndD, MinR, MaxR, Mx, My); +end; + +(* +DTMRotated +~~~~~~~~~~ + +.. code-block:: pascal + + function DTMRotated(DTM: Integer; var x, y: Integer; x1, y1, x2, y2: Integer): Boolean; + +First looks for a DTM without rotation, then increases the amount +of rotation around 0 gradually until it finds the DTM. A bit like the +ProgressiveTol Bitmap Engines. + +.. note:: + + by Yakman + +Example: + +.. code-block:: pascal + + +*) +function DTMRotated(DTM: Integer; var x, y: Integer; x1, y1, x2, y2: Integer): Boolean; +var + t, s, AngleFound: Extended; +begin + result := false; + if (FindDTM(DTM, x, y, x1, y1, x2, y2)) then + begin + Result := True; + Exit; + end; + repeat + s := 0.3; + repeat + if (FindDTMRotated(DTM, x, y, x1, y1, x2, y2, 0 - t, 0 + t, s, AngleFound)) then + begin + Result := True; + Exit; + end; + s := s - 0.1; + until (s <= 0.1); + t := t + (Pi / 20); + until (t >= Pi / 3); +end; + +(* +GetColorsBox +~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetColorsBox(x1, y1, x2, y2: Integer; ClearSameColors: Boolean): TIntegerArray; + +Returns an array of all colors within box ((x1, y1), (x2, y2)). +If ClearSameColors is set to True, all duplicate colors will be deleted. + +.. note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + + +*) +function GetColorsBox(x1, y1, x2, y2: Integer; ClearSameColors: Boolean): TIntegerArray; +begin + Result := GetColors(TPAFromBox(IntToBox(x1, y1, x2, y2))); + if (ClearSameColors) then + ClearSameIntegers(Result); +end; + +(* +PercentColorMMEx +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function PercentColorMMEx(Color, Tol, StartRadial, EndRadial, StartRadius, EndRadius: Integer): integer; + +Returns the percentage of colour on the minimap section defined by +StartRadial, EndRadial, StartRadius, and EndRadius. + + +.. note:: + + by Richard, and Nava2 + +Example: + +.. code-block:: pascal + + +*) +function PercentColorMMEx(Color, Tol, StartRadial, EndRadial, StartRadius, EndRadius: Integer): integer; +var + TPA: TPointArray; +begin + FindColorsTolerance(TPA, Color, MMX1, MMY1, MMX2, MMY2, Tol); + FilterPointsPie(TPA, StartRadial, EndRadial, StartRadius, EndRadius, MMCX, MMCY); + Result := ceil((Length(TPA) * 100) / ((Pi * (EndRadius * EndRadius)) * ((EndRadial - StartRadial) / 360.0)-((Pi * (StartRadius * StartRadius)) * ((EndRadial - StartRadial) / 360.0)))); +end; + +(* +PercentColorMM +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function PercentColorMM(Color, Tol: Integer): Integer; + +Returns the percent of a colour on the whole minimap. + + +.. note:: + + by Richard + +Example: + +.. code-block:: pascal + + +*) +function PercentColorMM(Color, Tol: Integer): Integer; +begin + Result := PercentColorMMEx(Color, Tol, 0, 360, 0, 76); +end; + +function LoggedIn: Boolean; forward; + +(* +FindMMColorsTolerance +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindMMColorsTolerance(var Points: TPointArray; Color, Tol: Integer): Boolean; + + +Finds all colors within "Tol" tolerance in the minimap circle and if +successful, returns a TPointArray containing them, sorted from MMCX, MMCY. + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + + +*) +function FindMMColorsSpiralTolerance(var Points: TPointArray; Color, Tol: Integer): Boolean; +begin + FindColorsSpiralTolerance(MMCX, MMCY, Points, Color, MMX1, MMY1, MMX2, MMY2, Tol); + FilterPointsDist(Points,0,76,MMCX,MMCY); + Result := (Length(Points) > 0); +end; + +(* +ReturnTPAExceptColors +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ReturnTPAExceptColors(cols, tols: TIntegerArray; area: TBox): TPointArray; + +Returns a tpa of every point found in 'area' that DOES NOT a color in 'cols' +with tolerance 'tols'. Useful if you need a tpa of an object that is constantly +changing color, but has a constant background color. + +.. note:: + + Author: Coh3n + Last Modified: Jan. 26th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + iTPA := InverseColors([4410947, 5003083], [10, 10], IntToBox(MCX1, MCY1, MCX2, MCY2)); +*) +function ReturnTPAExceptColors(cols, tols: TIntegerArray; area: TBox): TPointArray; +var + i: integer; + tpa: TPointArray; + atpa: T2DpointArray; +begin + setLength(atpa, length(cols)); + for i := 0 to high(cols) do + findColorsTolerance(atpa[i], cols[i], area.x1, area.y1, area.x2, area.y2, tols[i]); + + tpa := mergeATPA(atpa); + clearDoubleTPA(tpa); + result := returnPointsNotInTPA(tpa, getTPABounds(tpa)); + + //debugTPA(result, ''); +end; + +(* +GetColorArrayInfo +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetColorArrayInfo(C: TIntegerArray; var BestColors, Tolerances: TIntegerArray; Speed2Mods: TExtendedArray; var RGB: array of TIntegerArray; var HSL, XYZ: array of TExtendedArray): array of array of TExtendedArray; + +Takes an array of colours and outputs a multitude of information + - BestColors + - An array of the best color to find per CTS Speed, the + array index is relative to the CTS - 1. AKA BestColors[2] + returns the best color for ColorToleranceSpeed 3. + + - Tolerances + - An array of the necessary tolerance to find all of the + colours with array index is the CTS. Tolerances[1] = CTS 1. + - Speed2Mods + - [0]is Hue modifier, [1] is Saturation. + RGB, HSL, XYZ: Arrays which hold the RGB, HSL, and XYZ values respectively. + - The Result + - The result array is divided like so + - Result[CTS][Div][MMA] + - CTS + - The colour tolerance speed - 1. 0 and 1 are combined since they both use RGB. + - Div + - The division, for exampe HSL, H is index 0, S is index 1, and L is index 2. + - MMA + - The last values are the Minimum, Maximum, and average of the colors. + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + + +*) +function GetColorArrayInfo(C: array of Integer; var BestColors, Tolerances: TIntegerArray; var Speed2Mods: TExtendedArray; var rRGB: T2DIntegerArray; var rHSL, rXYZ: T2DExtendedArray): T3DExtendedArray; +var + i, ii, h: Integer; + tE: array of TExtendedArray; +begin + h := Length(c); + + SetLength(rRGB, h); + SetLength(rHSL, h); + SetLength(rXYZ, h); + SetLength(Tolerances, 3); + SetLength(Speed2Mods, 2); + SetLength(BestColors, 3); + SetLength(Result, 3); + Dec(h); + for i := 0 to h do + begin + SetLength(rRGB[i], 3); + SetLength(rHSL[i], 3); + SetLength(rXYZ[i], 3); + end; + SetLength(tE, 3); + for i := 0 to 2 do + begin + SetLength(Result[i], 3); + SetLength(tE[i], 3); + for ii := 0 to 2 do + SetLength(Result[i][ii], 3); + end; + + for i := 0 to 2 do + for ii := 0 to 2 do + begin + Result[i][ii][0] := 300; + Result[i][ii][1] := 0; + end; + + Dec(h); + for i := 0 to h do + begin + ColorToRGB(C[i], rRGB[i][0], rRGB[i][1], rRGB[i][2]); + ColorToHSL(C[i], rHSL[i][0], rHSL[i][1], rHSL[i][2]); + ColorToXYZ(C[i], rXYZ[i][0], rXYZ[i][1], rXYZ[i][2]); + for ii := 0 to 2 do + begin + // Calculates the Min and Max of the RGB, HSL, and XYZ + Result[0][ii][0] := Min(rRGB[i][ii], Round(Result[0][ii][0])); + Result[0][ii][1] := Max(rRGB[i][ii], Round(Result[0][ii][1])); + Result[1][ii][0] := MinE(rHSL[i][ii], Result[1][ii][0]); + Result[1][ii][1] := MaxE(rHSL[i][ii], Result[1][ii][1]); + Result[2][ii][0] := MinE(rXYZ[i][ii], Result[2][ii][0]); + Result[2][ii][1] := MaxE(rXYZ[i][ii], Result[2][ii][1]); + + // Totals the Values of color values for later avg. + Result[0][ii][2] := (Result[0][ii][2]) + (rRGB[i][ii]); + Result[1][ii][2] := (Result[1][ii][2]) + (rHSL[i][ii]); + Result[2][ii][2] := (Result[2][ii][2]) + (rXYZ[i][ii]); + end; + end; + + // Calculate the Geometric Average of the Ranges to create best colour. + Inc(h); + for i := 0 to 2 do + for ii := 0 to 2 do + Result[i][ii][2] := Result[i][ii][2] / h; + + for i := 0 to 2 do + Result[0][i][2] := Round(Result[0][i][2]); + + // Get Tolerances for each ColorSpeedTolerance, 3 is unknown so is skipped. + for i := 0 to 2 do + Tolerances[0] := Max(Tolerances[0], iAbs(Round(Result[0][i][1] - Result[0][i][0]))); + + Tolerances[1] := Ceil(sqrt(sqr(Result[0][0][0] - Result[0][0][1]) + sqr(Result[0][1][0] - Result[0][1][1]) + + sqr(Result[0][2][0] - Result[0][2][1]))); + + Tolerances[2] := Ceil(abs(Result[1][2][0] - Result[1][2][1])); + for i := 0 to 1 do + try + Speed2Mods[i] := (abs(Result[1][i][0] - Result[0][i][1]) / Tolerances[2]); + except Speed2Mods[i] := 0.0; end; + + + // Create best colour based on ranges. + BestColors[0] := RGBToColor(Round(Result[0][0][2]), Round(Result[0][1][2]), Round(Result[0][2][2])); + BestColors[1] := HSLToColor(Result[1][0][2], Result[1][1][2], Result[1][2][2]); + BestColors[2] := XYZToColor(Result[2][0][2], Result[2][1][2], Result[2][2][2]); +end; + +(* +GetBestColor +~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetBestColor(Colors: TIntegerArray; CTS: Integer; var Tol: Integer; var Speed2Modifiers: TExtendedArray): Integer; + +Gets the best colour to find as well as the tolerance and modifiers +based on which CTS you input. + + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + + +*) +function GetBestColor(Colors: TIntegerArray; CTS: Integer; var Tol: Integer; var Speed2Modifiers: TExtendedArray): Integer; +var + RGB: T2DIntegerArray; + HSL, XYZ: T2DExtendedArray; + BestColours, Tols: TIntegerArray; +begin + ClearSameIntegers(Colors); + GetColorArrayInfo(Colors, BestColours, Tols, Speed2Modifiers, RGB, HSL, XYZ); + if CTS <> 3 then Tol := Tols[CTS] else Writeln('ColorSpeed3Tolerance not supported.'); + if CTS <> 2 then Speed2Modifiers := []; + if CTS = 0 then CTS := 1; + Result := BestColours[CTS - 1]; +end; + +(* +CreateAutoColorInfo +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function CreateAutoColorInfo(Colors: TIntegerArray): TAutoColorInfo; + +Creates a TAutoColorInfo from the inputted array of colors. + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + + +*) +function CreateAutoColorInfo(Colors: TIntegerArray): TAutoColorInfo; +var + RGB: T2DIntegerArray; + HSL, XYZ: T2DExtendedArray; + Mods: TExtendedArray; + BestColours, Tols: TIntegerArray; + EInfo: T3DExtendedArray; +begin + EInfo := GetColorArrayInfo(Colors, BestColours, Tols, Mods, RGB, HSL, XYZ); + + with Result do + begin + Color := BestColours[1]; + HueMod := Mods[0]; + SatMod := Mods[1]; + LumTol := Tols[2]; + MinR := Round(EInfo[0][0][0]); MaxR := Round(EInfo[0][0][1]); + MinG := Round(EInfo[0][1][0]); MaxG := Round(EInfo[0][1][1]); + MinB := Round(EInfo[0][2][0]); MaxB := Round(EInfo[0][2][1]); + + MinX := EInfo[2][0][0]; MaxX := EInfo[2][0][1]; + MinY := EInfo[2][1][0]; MaxY := EInfo[2][1][1]; + MinZ := EInfo[2][2][0]; MaxZ := EInfo[2][2][1]; + end; +end; + +(* +SRL_GetBlackBackground +~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function SRL_GetBlackBackground: integer; + +Autocolours the black background colour. Returns -1 if not found. + +.. note:: + + Author: ZephyrsFury + Last Modified: Unknown/March 08, 2012 + +Example: + +.. code-block:: pascal + + blackColour := SRL_GetBlackBackground; +*) +function SRL_GetBlackBackground: Integer; +var + CTS, I, H, C, Count, MaxC: Integer; + TPA: TPointArray; + Cols: TIntegerArray; +begin + Result := -1; + if (not(LoggedIn)) then Exit; + CTS := GetColorToleranceSpeed; + + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(100, 100); + FindColorsTolerance(TPA, clBlack, MMX1, MMY1, MMX2, MMY2, 3); + SetColorSpeed2Modifiers(0.2, 0.2); + ColorToleranceSpeed(CTS); + if (Length(TPA) < 1) then Exit; + + Cols := GetColors(TPA); + ClearSameIntegers(Cols); + + H := High(Cols); + for I := 0 to H do + begin + C := Cols[I]; + Count := CountColor(C, MMX1, MMY1, MMX2, MMY2); + if (CountColor(C, MMX1, MMY1, MMX2, MMY2) > MaxC) then + begin + Result := C; + MaxC := Count; + end; + end; + +end; + +(* +PercentBlackMM +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function PercentBlackMM: integer; + +Returns the percentage of the minimap which is black. + +.. note:: + + Author: NaumanAkhlaQ + Last Modified: Unknown/March 08, 2012 + +Example: + +.. code-block:: pascal + + blackPercent := PercentBlackMM; +*) +function PercentBlackMM: Integer; +begin + Result := PercentColorMM(SRL_GetBlackBackground, 0); +end; diff --git a/SRL/core/flag.simba b/SRL/core/flag.simba new file mode 100644 index 0000000..20c3c39 --- /dev/null +++ b/SRL/core/flag.simba @@ -0,0 +1,517 @@ +(* +Minimap +======= + +The Minimap include contains all igeneral Minimap related functions + +.. contents:: + +*) + +(* +rs_GetCompassAngleRadians +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function rs_GetCompassAngleRadians: Extended; + +Returns the compass angle in radians. + +.. note:: + + by Narcle & Flight + +Example: + +.. code-block:: pascal + +*) +Function rs_GetCompassAngleRadians: Extended; +var + TPA: TPointArray; + T: TPoint; + B: TBox; +begin + B := IntToBox(524, 5, 562, 43); + with B do + FindColorsSpiralTolerance(T.x, T.y, TPA, 65536, x1, y1, x2, y2, 0); + if Length(TPA) < 1 then + Exit; + T := MiddleTPA(TPA); + Result := ArcTan2(-(T.Y - 24), T.X - 543) + Radians(90); + Result := fixRad(Result - Pi); +end; + +(* +rs_GetCompassAngleDegrees +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function rs_GetCompassAngleDegrees: Extended; + +Returns the compass angle in degrees. + +.. note:: + + by Wizzup? + +Example: + +.. code-block:: pascal + +*) +function rs_GetCompassAngleDegrees: Extended; +begin + Result := Degrees(rs_GetCompassAngleRadians()); +end; + + +(* +rs_OnMinimap +~~~~~~~~~~~~ + +.. code-block:: pascal + + function rs_OnMinimap(x, y: Integer): Boolean; + +Checks wether the specified point is on the minimap. + +.. note:: + + by Raymond + +Example: + +.. code-block:: pascal + +*) +function rs_OnMinimap(x, y: Integer): Boolean; +begin + Result := InCircle(x, y, MMCX, MMCY, 75); +end; + +(* +FindFlag +~~~~~~~~ + +.. code-block:: pascal + + function FindFlag(var X, Y: Integer): Boolean; + +Returns true if the flag is found on the minimap. + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + + if (FindFlag(x, y)) then + begin + writeln('Flag found'); + mouse(x, y, 3, 3, true); + end; +*) +Function FindFlag(var X, Y: integer): Boolean; +begin + Result := False; + if FindBitmapToleranceIn(bmpFlag, X, Y, MMX1, MMY1, MMX2, MMY2, 75) then + begin + Result := True; + X := X+7; + Y := Y+14; + end; +end; + +(* +FindFlag2 +~~~~~~~~~ + +.. code-block:: pascal + + function FindFlag2(var X, Y: Integer): Boolean; + +Returns true if the flag is found on the minimap. + +.. note:: + + by Home + +Example: + +.. code-block:: pascal + + if (FindFlag2(x, y)) then + begin + writeln('Flag found'); + mouse(x, y, 3, 3, true); + end; +*) +function FindFlag2(var X, Y: Integer): Boolean; +var + KMTarget, ITarget, I, Hi, Map, W, H, t: Integer; + TPA: TPointArray; +begin + Result := False; + Map := BitmapFromString(MMX2 - MMX1, MMY2 - MMY1, ''); + CopyClientToBitmap(Map, MMX1, MMY1, MMX2, MMY2); + KMTarget := GetKeyMouseTarget; + ITarget := GetImageTarget; + SetTargetBitmap(Map); + GetBitmapSize(Map, W, H); + FindColors(TPA, 65536, 0, 0, W - 1, H -1); + FilterPointsDist(TPA, 0, 75.5, W div 2, H div 2); + Hi := Length(TPA); + for I := 0 to Hi - 1 do + if ((FastGetPixel(Map, TPA[I].X - 1, TPA[I].Y - 1) - FastGetPixel(Map, TPA[I].X, TPA[I].Y - 1)) = 6381921) then + begin + Result := True; + X := TPA[I].X + MMX1; + Y := TPA[I].Y + MMY1; + Break; + end; + + t := GetImageTarget; + SetKeyMouseTarget(KMTarget); + SetImageTarget(ITarget); + FreeTarget(t); + FreeBitmap(Map); +end; +(* +FlagPresent +~~~~~~~~~~~ + +.. code-block:: pascal + + function FlagPresent: Boolean; + +T/F depending on flag exist. + + +.. note:: + + by weequ + +Example: + +.. code-block:: pascal + + +*) +function FlagPresent: Boolean; +var + X, Y: Integer; +begin + Result := FindFlag(X, Y) or FindFlag2(X, Y); +end; + +(* +FlagDistance +~~~~~~~~~~~~ + +.. code-block:: pascal + + function FlagDistance: Integer; + +Returns distance in pixels your char dot is from flag on mini-map + + +.. note:: + + by weequ + +Example: + +.. code-block:: pascal + + +*) +function FlagDistance: Integer; +var + X, Y: Integer; +begin + Result := -1; + if (FindFlag(X, Y)) or (FindFlag2(X, Y)) then + Result := Distance(MMCX, MMCY, X, Y); +end; + +(* +WalkingToFlag +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WalkingToFlag(WaitTime: Integer): Boolean; + +Checks if your charachter is moving; stores current FlagDistance to a variable, +waits "WaitTime" ms and then checks the FlagDistance again. +If it differs from the Distance stored in the variable, function returns true. + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + + +*) +function WalkingToFlag(WaitTime: Integer): Boolean; +var + FirstDistance: Integer; +begin + Result := False; + if (not FlagPresent) then exit; + FirstDistance := FlagDistance; + Wait(WaitTime); + Result := (FirstDistance <> FlagDistance); +end; + +function RoadColorChecker: Boolean; Forward; + +(* +FlagEx +~~~~~~ + +.. code-block:: pascal + + function FlagEx(Dist: Integer; RoadColorCheck: Boolean): Boolean; + +Waits until Flag is within "Distance" distance. + +.. note:: + + by Wizzup? / WT-Fakawi / ZephyrsFury / N1ke! / weequ + +Example: + +.. code-block:: pascal + + +*) +function FlagEx(Dist: Integer; RoadColorCheck: Boolean): Boolean; +var + Tx, Ty, M, D1, D2: Integer; +begin + Wait(randomRange(400, 600)); + Result := False; + M := GetSystemTime; + repeat + if (not FindFlag(Tx, Ty)) and (not FindFlag2(Tx, Ty)) then + begin + Result := true; + Exit; + end; + D1 := Distance(Tx, Ty, MMCX, MMCY); + if (D1 <= Dist) then + begin + Result := True; + Exit; + end; + if (D1 > Dist+12) then + wait(450+random(70)) + else + wait(50+random(50)); + if (RoadColorCheck) then + RoadColorChecker; + if (GetColor(6, 6) <> 13092807) then // border of the loading message + if (GetSystemTime - M > 5000) then + begin + if (D1 = D2) then Exit; + D2 := D1; + M := GetSystemTime; + end; + if SRL_HasProc(SRL_AntiBan) then + SRL_Procs[SRL_AntiBan](); + until not LoggedIn; +end; + +(* +MouseFlagEx +~~~~~~~~~~~ + +.. code-block:: pascal + + function MouseFlagEx(X, Y, rX, rY, Xmod, Ymod, FlagDist: Integer; CheckForFlag, CheckForRoadColor: Boolean): Boolean; + +MouseFlag, MFF & MFNF combined into one procedure. +X, Y is the point you want to click, rX, rY are randomness modifiers. +Xmod and Ymod is the adjustment for each click without finding a flag. +FlagDist is how close you want to be (in pixels) to the flag before exiting. +CheckForFlag = True if you want to exit the function if a flag is present. (MFF) +CheckForRoadColor = True if you want to call RoadColorChecked while FlagPresent. + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + + +*) +function MouseFlagEx(X, Y, rX, rY, Xmod, Ymod, FlagDist: Integer; + CheckForFlag, CheckForRoadColor: Boolean): Boolean; +var + I: Integer; + P: TPoint; +begin + Result := False; + if (FlagPresent) then + if (CheckForFlag) or (FlagDistance <= FlagDist) then exit; + + P := Point(X - Xmod, Y - Ymod); + Xmod := Max(Xmod, 3); + Ymod := Max(Ymod, 3); + + for I := 0 to 4 do + begin + IncEx(P.X, Xmod + Random(rX)); + IncEx(P.Y, Ymod + Random(rY)); + if not rs_OnMiniMap(P.X, P.Y) then Continue; + Mouse(P.X, P.Y, 0, 0, mouse_left); + Result := WaitFunc(@FlagPresent, 50, 3000); + if (Result) then break; + end; + if (FlagDist > -1) then + FlagEx(FlagDist, CheckForRoadColor); +end; + +(* +MFF +~~~ + +.. code-block:: pascal + + function MFF(X, Y, Xmod, Ymod: Integer): Boolean; + + +If the flag is not present it will click at (ax, ay) increasing by +(xmod, ymod) 5 times or until the flag appears. + + +.. note:: + + by EvilChicken! from an original idea by WT-Fakawi + +Example: + +.. code-block:: pascal + + +*) +function MFF(X, Y, Xmod, Ymod: Integer): Boolean; +begin + Result := MouseFlagEx(X, Y, 3, 3, Xmod, Ymod, -1, True, False); +end; + +(* +MFNF +~~~~ + +.. code-block:: pascal + + Function MFNF(ax, ay, xmod, ymod: Integer):Boolean; + +Like MFF except it will click even if the flag is present when the + +.. note:: + + by EvilChicken! from an original idea by WT-Fakawi + +Example: + +.. code-block:: pascal + + +*) +function MFNF(X, Y, Xmod, Ymod: Integer): Boolean; +begin + Result := MouseFlagEx(X, Y, 3, 3, Xmod, Ymod, -1, False, False); +end; + +(* +FFlag +~~~~~ + +.. code-block:: pascal + + function FFlag(Dist: Integer): Boolean; + +Waits until Flag is within "Distance" distance. + + +.. note:: + + by Wizzup? / WT-Fakawi / ZephyrsFury + +Example: + +.. code-block:: pascal + + +*) +function FFlag(Dist: Integer): Boolean; +begin + Result := FlagEx(Dist, False); +end; + +(* +Flag +~~~~ + +.. code-block:: pascal + + function Flag: Boolean; + +Waits while flag exists. + + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + + +*) + +function Flag: Boolean; +begin + Result := FlagEx(0, False); +end; + +(* +MouseFlag +~~~~~~~~~ + +.. code-block:: pascal + + procedure MouseFlag(X, Y, rX, rY, FlagDist: Integer); + +Mouse and Flag combined into one easy procedure. + + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + + +*) + +function MouseFlag(X, Y, rX, rY, FlagDist: Integer): Boolean; +begin + Result := MouseFlagEx(X, Y, rX, rY, 0, 0, FlagDist, False, False); +end; diff --git a/SRL/core/gametab.simba b/SRL/core/gametab.simba new file mode 100644 index 0000000..d5779ef --- /dev/null +++ b/SRL/core/gametab.simba @@ -0,0 +1,4157 @@ +(* +Gametab +======= + +This Include contains all Gametab Routines. + +.. contents:: + +*) + +type + TSMSetting = (Stereo, Mono, NoChange); + +{ const LobbyTab Constants; + Description: Constants representing lobbytab numbers. } + +const + L_PlayerInfo = 1; + L_WorldSelect = 2; + L_FriendsList = 3; + L_FriendsChat = 4; + L_ClanChat = 5; + L_Options = 6; + +(* + +Ability Book and Action Bar +--------------------------- + +Ability Book and Action Bar related functions + +*) + +(* +ActiveMainAbilityTab +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ActiveMainAbilityTab(): Integer; + +Returns which of the four main Ability Book tabs is currently active. + +.. note:: + + by euphemism + +*) +function ActiveMainAbilityTab(): Integer; +var + TabColor: Integer; + TabColorArray: TIntegerArray; +begin + SetLength(TabColorArray, 4); + TabColorArray := [1996449, 2315049, 7225628, 2370692]; + TabColor := GetColor(551, 282); + for Result := 0 to 3 do + if (TabColor = TabColorArray[Result]) then + Exit; +end; + +(* +ActiveSubAbilityTab +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ActiveSubAbilityTab(): Integer; + +Returns which of the sub-tabs beneath the active main tab is currently active. + +.. note:: + + by euphemism + +*) +function ActiveSubAbilityTab(): Integer; +var + H, S, L: Extended; + XVals: TIntegerArray; +begin + SetLength(XVals, 4); + XVals := [555, 601, 648, 695]; + if (ActiveMainAbilityTab = 0) then + XVals[1] := 602; + for Result := 0 to 3 do + begin + ColorToHSL(GetColor(XVals[Result], 262), H, S, L); + if (L > 10) then + Exit; + end; +end; + +(* +SetAbilityBook +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function SetAbilityBook(Tab: Integer): Boolean; + +Takes a sub-tab constant (see globals.simba), and changes the main tab and +sub-tabs of the Ability Book as necessary to make the target sub-tab +the active sub-tab. Returns true if successful. + +.. note:: + + by euphemism + +*) +function SetAbilityBook(Tab: Integer): Boolean; +var + ActiveMain, I, TabCompare, TimeOut, X, Y: Integer; + CompareFunc: Function(): Integer; + BoxCoords, TabLocations, TabLoop: T2DIntegerArray; +begin + if (not GameTab(TAB_MAGIC)) then + Exit; + SetLength(TabLocations, 4); + TabLocations[0] := [AB_ATTACK, AB_STRENGTH]; //First dimension is main tab, second dimension is sub tab position. + TabLocations[1] := [AB_RANGED]; + TabLocations[2] := [AB_ABILITIES, AB_COMBAT_SPELLS, AB_TELEPORT_SPELLS, AB_SKILLING_SPELLS]; + TabLocations[3] := [AB_DEFENSE, AB_CONSTITUTION]; + SetLength(BoxCoords, 2); + BoxCoords[0] := [548, 205, 594, 237, 47]; //Main tab size and spacing + BoxCoords[1] := [557, 248, 586, 277, 46]; //Sub tab size and spacing + for X := 0 to 3 do //Converts tab constant into X Y pair, where X is the main tab, and Y is the sub tab. + begin + for Y := 0 to High(TabLocations[X]) do + begin + if (TabLocations[X][Y] = Tab) then + begin + Result := True; + Break; + end; + end; + if (Result) then + Break; + end; + ActiveMain := ActiveMainAbilityTab; //Stores the current active main tab to reduce redundancy. + SetLength(TabLoop, 2); + TabLoop[0] := [ActiveMain, X]; //Holds the active main tab, and the target main tab. + TabLoop[1] := [ActiveSubAbilityTab, Y]; //Holds the active sub tab to 0, and the target sub tab. + Result := ((TabLoop[0][0] = TabLoop[0][1]) and (TabLoop[1][0] = TabLoop[1][1])); + if (Result) then + Exit; + Wait(Random(300)); + for I := 0 to 1 do //This loop sets the main tab and sub tab to to the target tab. + begin + if (I = 1) then + TabLoop[i][0] := ActiveSubAbilityTab; //Updates the stored active sub tab to account for switching the main tab. + if (TabLoop[i][0] <> TabLoop[i][1]) then + begin + MouseBox((BoxCoords[i][0] + (BoxCoords[i][4] * TabLoop[i][1])), BoxCoords[i][1], (BoxCoords[i][2] + (BoxCoords[i][4] * TabLoop[i][1])), BoxCoords[i][3], MOUSE_LEFT); //Clicks the target tab. + TimeOut := (GetSystemTime + RandomRange(800, 1200)); //Sets timeout fail-safe. + if (I = 0) then //Points the CompareFunc function to check either the active main tab or sub tab based on the value of the looping variable. + CompareFunc := @ActiveMainAbilityTab + else + CompareFunc := @ActiveSubAbilityTab; + while ((GetSystemTime < TimeOut) and (CompareFunc() <> TabLoop[i][1])) do //Fail-safe and state check for the tab. + Wait(16); + end; + if (I = 0) then //Sets the TabCompare variable to either the active main tab or active sub tab based on the value of the looping variable. + TabCompare := ActiveMainAbilityTab + else + TabCompare := ActiveSubAbilityTab; + Result := (TabCompare <> TabLoop[i][1]); //If the tab failed to change to the target tab, function returns false and exit. + if (Result) then + Exit; + if (I = 0) then //Determines whether to wait between setting the main tab and sub tab, or to check the final result. + Wait(400 + Random(300)) + else + Result := ((ActiveMainAbilityTab = TabLoop[0][1]) and (ActiveSubAbilityTab = TabLoop[1][1])); + end; +end; + +(* +GetAbilityLocation +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure GetAbilityLocation(AbilityConstant: Integer; out SubTab, PositionUnderTab: Integer); + +Returns the sub-tab (Through SubTab of the Ability Book that the Ability +(AbilityConstant) is under, and then the position of the ability within the +SubTab (Through PositionUnderTab). + +.. note:: + + by euphemism + Last modified: Jan. 31st, 2013 by euphemism + +Example: + +.. code-block:: pascal + + GetAbilityLocation(AB_SURGE, SubTab, PositionUnderTab); + //SubTab would contain 3 (AB_ABILITIES), as that is the constant for the + //Abilities sub-tab, and PositionUnderTab would contain 7, as that is the + //position of the ability within the sub-tab. +*) +procedure GetAbilityLocation(AbilityConstant: Integer; out SubTab, PositionUnderTab: Integer); +var + AbilityTabs: TIntegerArray; +begin + AbilityTabs := [AB_ATTACK, AB_STRENGTH, AB_RANGED, AB_ABILITIES, AB_DEFENCE, AB_CONSTITUTION]; + SubTab := AbilityTabs[(AbilityConstant - 13) div 12]; + PositionUnderTab := ((AbilityConstant - 12) - (((AbilityConstant - 13) div 12) * 12)); +end; + +(* +AbilitySlotToBox +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function AbilitySlotToBox(Slot: Integer): TBox; + +Returns a TBox around the specified Ability Book slot. Currently does not work +with the standard combat spells tab, as they are aligned to a different grid +than the rest of the Ability Book. + +.. note:: + + by euphemism + Last modified: Dec. 21st, 2012 by euphemism + +Example: + +.. code-block:: pascal + + SlotBox := AbilitySlotToBox(AB_SURGE); + MouseBox(SlotBox.x1, SlotBox.y1, SlotBox.x2, SlotBox.y2, mouse_Left); +*) +function AbilitySlotToBox(Slot: Integer): TBox; +begin + if not InRange(Slot, 1, 20) then + begin + srl_Warn('AbilitySlotToBox', 'Slot must be within 1-20!', warn_AllVersions); + Exit; + end; + with Result do + begin + X1 := 561 + ((((Slot + 3) mod 4)) * 44); + Y1 := 290 + ((((Slot - 1) div 4)) * 36); + X2 := X1 + 29; + Y2 := Y1 + 29; + end; +end; + +(* +IsActionBarOpen +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function IsActionBarOpen(): Boolean; + +Results True if the Action Bar is showing. + +.. note:: + + by euphemism + +*) +function IsActionBarOpen(): Boolean; +var + Color: Integer; +begin + Color := GetColor(45, 283); + Result := ((Color = 2697663) or (Color = 15790330)); +end; + +(* +ToggleActionBar +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ToggleActionBar(Open: Boolean): Boolean; + +Opens or closes the Action Bar, true if had to toggle. + +.. note:: + by euphemism, modelled after ToggleXPBarEx by Narcle & IceFire908 + +*) +function ToggleActionBar(Open: Boolean): Boolean; +var + T: Integer; +begin + if (Open xor IsActionBarOpen()) then + begin + if Open then + MouseBox(499, 326, 516, 338, mouse_Left) + else + MouseBox(499, 264, 516, 277, mouse_Left); + T := GetSystemTime + 300; + repeat + wait(RandomRange(10, 30)); + Result := (Open = IsActionBarOpen()); + until Result or (GetSystemTime > t); + end else + Result := true; +end; + +(* +ActionBarSlotToBox +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ActionBarSlotToBox(Slot: Integer): TBox; + + Returns the TBox (30 x 30) of the action bar at position Slot. + +.. note:: + + by Slushpuppy + +Example: + +.. code-block:: pascal + + ActionBarSlotToBox(1); + +*) +function ActionBarSlotToBox(Slot: Integer): TBox; +begin + if InRange(Slot, 1, 12) then + begin + with Result do + begin + X1 := 47 + (Slot - 1) * 36; + Y1 := 347 - SRL_NAVBAR_INGAME_Y; + X2 := X1 + 29; + Y2 := 376 - SRL_NAVBAR_INGAME_Y; + end; + end else + srl_Warn('ActionBarSlotToBox', 'Slot must be within 1-12!', warn_AllVersions); +end; + +(* +ActionBarSlotEmpty +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ActionBarSlotEmpty(Slot: Integer): Boolean; + +Results True if the specified Action Bar slot is empty. + +.. note:: + + by euphemism + Last modified: Dec. 21st, 2012 by euphemism + +Example: + +.. code-block:: pascal + + if (not ActionBarSlotEmpty(4)) then + ClearActionBarSlot(4); +*) +function ActionBarSlotEmpty(Slot: Integer): Boolean; +var + MidPoint: TPoint; +begin + ToggleActionBar(True); + MidPoint := MiddleBox(ActionBarSlotToBox(Slot)); + Result := (GetColor(MidPoint.x, MidPoint.y) = 59); +end; + +(* +GetAbilityCooldown +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetAbilityCooldown(ActionBarSlotOrAbilityConstant: Integer): Integer; + +Returns a number, 0-100 (or -1 in the case that it fails to get the cooldown) +indicating the percentage complete of the cooldown of the specified ability, +ActionBarSlotOrAbilityConstant. Passing 1-12 will check the ability in the +coordinating Action Bar slot, and passing an ability constant, such as AB_SURGE, +will open the Ability Book and check there for the ability's cooldown. + +.. note:: + + by euphemism + Last modified: Jan. 31st, 2013 by euphemism + +Example: + +.. code-block:: pascal + + + if (GetAbilityCooldown(AB_SURGE) = 100) then + WriteLn('Ability is ready to use.'); + + while (GetAbilityCooldown(AB_SURGE) < 100) do + WriteLn('Ability cooldown is ' + IntToStr(GetAbilityCooldown(AB_SURGE)) + '% complete.'); +*) +function GetAbilityCooldown(ActionBarSlotOrAbilityConstant: Integer): Integer; +var + ColorFix, ClientBitmap, I, Len, PositionUnderTab, SubTab, SumTotal, x1, y1, x2, y2, W, H: Integer; + MidPoint: TPoint; + AbilitySlot: TBox; + PointCircle, Line, TPA: TPointArray; +begin + Result := - 1; + case (ActionBarSlotOrAbilityConstant) of + 1..12: AbilitySlot := ActionBarSlotToBox(ActionBarSlotOrAbilityConstant); + AB_SLICE..AB_SINGLE_WAY_WILDERNESS: + begin + GetAbilityLocation(ActionBarSlotOrAbilityConstant, SubTab, PositionUnderTab); + if (not SetAbilityBook(SubTab)) then + Exit; + AbilitySlot := AbilitySlotToBox(PositionUnderTab); + end; + end; + try + ClientBitmap := BitmapFromClient(AbilitySlot.x1, AbilitySlot.y1, AbilitySlot.x2, AbilitySlot.y2); + SetBitmapName(ClientBitmap, 'CooldownBitmap'); + x1 := 0; + y1 := 0; + x2 := AbilitySlot.x2 - AbilitySlot.x1; + y2 := AbilitySlot.y2 - AbilitySlot.y1; + W := x2 + 1; + H := y2 + 1; + if (InRange(ActionBarSlotOrAbilityConstant, 1, 12)) then + begin + FindColors(TPA, 3111603, AbilitySlot.x1 + 2, AbilitySlot.y1 + 19, AbilitySlot.x1 + 8, AbilitySlot.y1 + 26); + OffsetTPA(TPA, IntToPoint( - AbilitySlot.x1, - AbilitySlot.y1)); + for I := 0 to High(TPA) do + FastSetPixel(ClientBitmap, TPA[i].x, TPA[i].y, 0); + end; + GetMufasaBitmap(ClientBitmap).Brightness(GetMufasaBitmap(ClientBitmap), 100); + GetMufasaBitmap(ClientBitmap).Posterize(GetMufasaBitmap(ClientBitmap), 60); + GetMufasaBitmap(ClientBitmap).Contrast(GetMufasaBitmap(ClientBitmap), 30); + GetMufasaBitmap(ClientBitmap).Desaturate(GetMufasaBitmap(ClientBitmap)); + MidPoint := IntToPoint(15, 14); + TPAFromCircleWrap(MidPoint.x, MidPoint.y, 14, PointCircle); + SortCircleWise(PointCircle, MidPoint.x, MidPoint.y, 359, False, True); + Len := Length(PointCircle); + for I := 0 to (Len - 1) do + begin + if (InRange(I, 0, 38)) then + MidPoint := IntToPoint(14, 15) + else + MidPoint := IntToPoint(15, 14); + tmp_TPAFromLineWrap(Midpoint.x, MidPoint.y, PointCircle[i].x, PointCircle[i].y, Line) SortTPAFrom(Line, MidPoint); + InvertTPA(Line); + if (I = 0) then + SetLength(Line, 7) + else + SetLength(Line, Length(Line) - 4); + SumTotal := 0; + SumTotal := SumIntegerArray(FastGetPixels(ClientBitmap, Line)); + if (SumTotal <> 0) then + begin + Result := Ceil((Round(FixD(Degrees(ArcTan2(PointCircle[i].x - MidPoint.x - 1, - (PointCircle[i].y - MidPoint.y))))) / 360.0) * 100) + 1; + if (Result = 99) then + begin + ColorFix := GetColor(AbilitySlot.x1 + 14, AbilitySlot.y1 + 2); + if ((ColorFix = 6706) or (ColorFix = 1710617)) then + Result := 100; + end; + Break; + end + else if (I = (Len - 1)) then + Result := 0; + end; + finally + FreeBitmap(ClientBitmap); + end; +end; + +(* +UseAbility +~~~~~~~~~~ + +.. code-block:: pascal + + function UseAbility(ActionBarSlotOrAbilityConstant: Integer): Boolean; + +If the ability is ready to use, the function will click the ability and return +true or false depending on if the cooldown of the ability begins. Passing 1-12 +will use the ability in the coordinating Action Bar slot, and passing an ability +constant, such as AB_SURGE, will open the Ability Book and use the ability there. + +.. note:: + + by euphemism + Last modified: Jan. 31st, 2013 by euphemism + +Example: + +.. code-block:: pascal + + + if (not UseAbility(3)) then + WriteLn('Was unable to use ability in Action Bar slot 3.'); +*) +function UseAbility(ActionBarSlotOrAbilityConstant: Integer): Boolean; +var + PositionUnderTab, SubTab, TimeMarker: Integer; + AbilitySlot: TBox; +begin + Result := False; + case (ActionBarSlotOrAbilityConstant) of + 1..12: + begin + AbilitySlot := ActionBarSlotToBox(ActionBarSlotOrAbilityConstant); + if (ActionBarSlotEmpty(ActionBarSlotOrAbilityConstant)) then + Exit; + end; + AB_SLICE..AB_SINGLE_WAY_WILDERNESS: + begin + GetAbilityLocation(ActionBarSlotOrAbilityConstant, SubTab, PositionUnderTab); + if (not SetAbilityBook(SubTab)) then + Exit; + AbilitySlot := AbilitySlotToBox(PositionUnderTab); + end; + end; + if (not (GetAbilityCoolDown(ActionBarSlotOrAbilityConstant) = 100)) then + Exit; + MouseTBox(AbilitySlot, mouse_left); + TimeMarker := GetSystemTime + RandomRange(800, 1204); + repeat + Result := (GetAbilityCoolDown(ActionBarSlotOrAbilityConstant) <> 100); + until ((Result) or (GetSystemTime > TimeMarker)); +end; + +(* +AbilityInSlot +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function AbilityInSlot(AbilityConstant, ActionBarSlot: Integer): Boolean; + +Opens up the Ability Book where the ability, AbilityConstant, is located, and +checks to see if the ability is in the specified Action Bar slot, ActionBarSlot. +This function doesn't really have a use except for within the following functions. + +.. note:: + + by euphemism + Last modified: Jan. 31st, 2013 by euphemism +*) +function AbilityInSlot(AbilityConstant, ActionBarSlot: Integer): Boolean; +var + bmp, PositionUnderTab, SubTab, X, Y: Integer; + Acc: Extended; + Colors: TIntegerArray; + TPA: TPointArray; + AbilitySlot, ActionSlot: TBox; + +begin + Result := False; + GetAbilityLocation(AbilityConstant, SubTab, PositionUnderTab); + if (not SetAbilityBook(SubTab)) then + Exit; + AbilitySlot := AbilitySlotToBox(PositionUnderTab); + ActionSlot := ActionBarSlotToBox(ActionBarSlot); + TPAFromBoxWrap(IntToBox(AbilitySlot.x1 + 8, AbilitySlot.y1 + 7, AbilitySlot.x2 - 7, AbilitySlot.y2 - 8), TPA); + FilterPointsPie(TPA, 0, ((GetAbilityCoolDown(AbilityConstant) * 360) / 100) - 1, 0, 7, AbilitySlot.x1 + 15, AbilitySlot.y1 + 14); + GetColorsWrap(TPA, Colors); + OffsetTPA(TPA, IntToPoint(- (AbilitySlot.x1 + 8), - (AbilitySlot.y1 + 7))); + try + Bmp := BitmapFromString(15, 15, ''); + FastSetPixels(bmp, TPA, Colors); + Result := FindDeformedBitmapToleranceIn(Bmp, X, Y, ActionSlot.x1 + 8, ActionSlot.y1 + 7, ActionSlot.x2 - 7, ActionSlot.y2 - 8, 0, 0, False, Acc); + finally + FreeBitmap(Bmp); + end; +end; + +(* +GetAdrenalinePercent +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetAdrenalinePercent : Integer; + +Gets percent(0-100) of adrenaline in the action bar. Function returns -1 if actionbar is not active + + +.. note:: + + by Slushpuppy + +Example: + +.. code-block:: pascal + + GetAdrenalinePercent; + +*) +function GetAdrenalinePercent(): Integer; +var + BarX1,BarX2,BarY1,BarY2 : Integer; + tpa : TPointArray; + box : TBox; +begin + Result := -1; + if isActionBarOpen then + begin + Result := 100; + BarY1 := 334 - SRL_NAVBAR_INGAME_Y; + BarY2 := 337- SRL_NAVBAR_INGAME_Y; + BarX1 := 49 - SRL_NAVBAR_INGAME_X; + BarX2 := 469 - SRL_NAVBAR_INGAME_X; + if FindColorsTolerance(tpa,1776411,BarX1,BarY1,BarX2,BarY2,15) then + begin + box := GetTPABounds(tpa); + Result := Floor(100 - ((BarX2 - box.X1)*1.0 / (BarX2-BarX1) * 1.0) * 100); + end; + end; +end; + +(* +IsActionBarLocked +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function IsActionBarLocked(): Boolean; + +Results True if the Action Bar is locked. + +.. note:: + + by euphemism + Last modified: Dec. 21st, 2012 by euphemism + +Example: + +.. code-block:: pascal + + if (IsActionBarLocked()) then + ToggleActionBarLock(False); +*) +function IsActionBarLocked(): Boolean; +var + Color: Integer; +begin + Color := GetColor(19, 296); + Result := ((Color = 5145251) or (Color = 8846590)); +end; + +(* +ToggleActionBarLock +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ToggleActionBarLock(Lock: Boolean): Boolean; + +Locks or unlocks the Action Bar, true if had to toggle. + +.. note:: + by euphemism, modelled after ToggleXPBarEx by Narcle & IceFire908 + Last modified: Dec. 21st, 2012 by euphemism + +Example: + +.. code-block:: pascal + + if (IsActionBarLocked()) then + ToggleActionBarLock(False); +*) +function ToggleActionBarLock(Lock: Boolean): Boolean; +var + T: Integer; +begin + if (Lock xor IsActionBarLocked()) then + begin + MouseBox(10, 285, 34, 308, mouse_Left); + T := GetSystemTime + RandomRange(1900, 2300); + repeat + wait(RandomRange(10, 30)); + Result := (Lock = IsActionBarLocked()); + until Result or (GetSystemTime > T); + end else + Result := true; +end; + +(* +ActionBarEmpty +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ActionBarEmpty(): Boolean; + +Results True if the entire Action Bar slot is empty. + +.. note:: + + by euphemism + Last modified: Dec. 21st, 2012 by euphemism + +Example: + +.. code-block:: pascal + + if (ActionBarEmpty()) then + Writeln('Action Bar is empty and ready to receive abilities.'); +*) +function ActionBarEmpty(): Boolean; +var + I: Integer; +begin + Result:= False; + for I:= 1 to 12 do + if (not ActionBarSlotEmpty(I)) then + Exit; + Result:= True; +end; + +(* +ClearActionBarSlot +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClearActionBarSlot(Slot: Integer): Boolean; + +Results True if the specified Action Bar slot is successfully cleared. + +.. note:: + + by euphemism + Last modified: Dec. 21st, 2012 by euphemism + +Example: + +.. code-block:: pascal + + if (ClearActionBarSlot(4)) then + Writeln('Action Bar Slot 4 is now empty.'); +*) +function ClearActionBarSlot(Slot: Integer): Boolean; +var + SlotBox: TBox; +begin + Result := ActionBarSlotEmpty(Slot); + if (Result) then + Exit; + if (isActionBarLocked()) then + ToggleActionBarLock(False); + Wait(RandomRange(314, 504)); + SlotBox := ActionBarSlotToBox(Slot); + DragMouse(SlotBox.x1, SlotBox.y1, 29, 27, 10, 310, 24, 23); + Wait(RandomRange(100, 300)); + Result := ActionBarSlotEmpty(Slot); +end; + +(* +ClearActionBar +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClearActionBar(): Boolean; + +Results True if the entire Action Bar is successfully cleared. + +.. note:: + + by euphemism + Last modified: Dec. 21st, 2012 by euphemism + +Example: + +.. code-block:: pascal + + if (ClearActionBar()) then + Writeln('Action Bar is empty and ready to add abilities/prayers/items'); +*) +function ClearActionBar(): Boolean; +var + TimeMarker: Integer; +begin + Result := ActionBarEmpty(); + if (Result) then + Exit; + MouseBox(10, 310, 34, 333, mouse_Right); + if (not WaitOptionMulti(['Clear', 'all', 'r-a', 'ear', 'ar'], RandomRange(1504, 2306))) then + Exit; + + TimeMarker:= GetSystemTime + RandomRange(1507, 2030); + repeat + Result := ActionBarEmpty(); + until (Result or (GetSystemTime > TimeMarker)); +end; + +(* +CurrentActionBar +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function CurrentActionBar(): Integer; + +Members can have five different Action Bars setup. Returns the number of the +active Action Bar. Returns -1 if it is unable to grab the text. + +.. note:: + + by euphemism + Last modified: Dec. 21st, 2012 by euphemism + +Example: + +.. code-block:: pascal + + if (CurrentActionBar() <> 1) then + SwitchActionBar(1, False); +*) +function CurrentActionBar(): Integer; +begin + Result := StrToIntDef(GetTextAtExWrap(495, 304, 501, 313, 0, 0, 0, 3111603, 0, 'UpChars'), -1); +end; + +(* +SwitchActionBar +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function SwitchActionBar(WhichBar: Integer; UseBindKey: Boolean): Boolean; + +Switch to action bar WhichBar, returns true on success. +Set and use ctrl bind key if UseBindKey, +otherwise click the arrows or right click to switch. + +.. note:: + + by riwu + +*) +function SwitchActionBar(WhichBar: Integer; UseBindKey: Boolean): Boolean; +var + currentBar, r, i, diff, tWait: Integer; + ClickForward: Boolean; + Keys: TIntegerArray; + Arg: TVariantArray; +begin + Result:= False; + + if Length(Players) > 0 then + if not Players[CurrentPlayer].Member then + begin + srl_Warn('SwitchBar', 'F2P cannot switch action bar!', warn_AllVersions); + Exit; + end; + + if not InRange(WhichBar, 1, 5) then + begin + srl_Warn('SwitchBar', 'WhichBar must be within 1-5!', warn_AllVersions); + Exit; + end; + + currentBar:= CurrentActionBar(); + Result:= (WhichBar = currentBar); + if Result then + Exit; + + if UseBindKey then + begin + if Length(Players) < 1 then + NumberOfPlayers(1); + + if not Players[CurrentPlayer].ActionBarSet then + begin + MouseBox(492, 300, 507, 314, mouse_Right); + if WaitOptionMulti(['Custo', 'mise', 'Modi', 'Key'], 618) then + begin + Arg:= ['press'] + WaitFuncEx('FindBlackChatMessage', Arg, RandomRange(10, 50), RandomRange(618, 777)); + TypeByte(VK_CONTROL); + wait(RandomRange(122, 244)); + Players[CurrentPlayer].ActionBarSet:= True; + end; + end; + + Keys:= [VK_CONTROL, VK_0 + WhichBar]; + for i:=0 to High(Keys) do + begin + KeyDown(Keys[i]); + wait(RandomRange(10, 200 - i * 100)); + end; + + r:= Random(2); + KeyUp(Keys[r]); + wait(Random(60)); + KeyUp(Keys[iAbs(r - 1)]); + end else + begin + diff:= iAbs(currentBar - WhichBar); + if InRange(diff, 2, 3) then + begin + MouseBox(492, 300, 507, 314, mouse_Right); + WaitOption(ToStr(WhichBar), 618); + end else + begin + ClickForward:= (currentBar < WhichBar) xor (diff > 2); + + if ClickForward then + MouseBox(493, 318, 502, 327, mouse_Left) + else + MouseBox(493, 288, 502, 297, mouse_Left) + end; + end; + + tWait:= GetSystemTime + RandomRange(3000, 4000); + while (tWait > GetSystemTime) do + begin + Result:= (WhichBar = CurrentActionBar); + if Result then + Exit; + end; +end; + +(* +ClickActionBarSlot +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClickActionBarSlot(Slot: Integer): Boolean; + +Clicks the specified Action Bar slot. If the specified Action Bar slot is empty +the function will return false. Otherwise, it clicks the slot and returns true. + +.. note:: + + by euphemism + Last modified: Jan. 31st, 2013 by euphemism +*) +function ClickActionBarSlot(Slot: Integer): Boolean; +var + SlotBox: TBox; +begin + Result := False; + if (ActionBarSlotEmpty(Slot)) then + Exit; + SlotBox := ActionBarSlotToBox(Slot); + MouseTBox(SlotBox, mouse_left); + Result := True; +end; + +(* +AddAbilityToActionBar +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function AddAbilityToActionBar(AbilityConstant, ActionBarSlot: Integer): Boolean; + +Adds the specified ability, AbilityConstant, from the Ability Book to the +specified slot, ActionBarSlot, of the Action Bar. Returns true on success. + +.. note:: + + by euphemism + Last modified: Jan. 31st, 2013 by euphemism + +Example: + +.. code-block:: pascal + + + if (AddAbilityToActionBar(AB_SURGE, 5)) then + WriteLn('Added the Surge ability to Action Bar slot 5.'); +*) +function AddAbilityToActionBar(AbilityConstant, ActionBarSlot: Integer): Boolean; +var + PositionUnderTab, SubTab, TimeMarker: Integer; + AbilitySlot, ActionSlot: TBox; +begin + Result := AbilityInSlot(AbilityConstant, ActionBarSlot); + if (Result) then + Exit; + GetAbilityLocation(AbilityConstant, SubTab, PositionUnderTab); + AbilitySlot := AbilitySlotToBox(PositionUnderTab); + ActionSlot := ActionBarSlotToBox(ActionBarSlot); + DragMouse(AbilitySlot.x1, AbilitySlot.y1, 29, 29, ActionSlot.x1, ActionSlot.y1, 28, 28); + TimeMarker := GetSystemTime + RandomRange(802, 1113); + repeat + Result := AbilityInSlot(AbilityConstant, ActionBarSlot); + Wait(12); + until ((Result) or (GetSystemTime > TimeMarker)); + TimeMarker := GetSystemTime + RandomRange(1004, 1516); + if (Result) then + repeat + if (GetColor(ActionSlot.x1 - 2, ActionSlot.y1 - 2) <> 13158600) then + Exit; + until (GetSystemTime > TimeMarker); +end; + +function ExistsItem(I: Integer): Boolean; forward; + +(* +AddItemToActionBar +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function AddItemToActionBar(InvSlot, ActionBarSlot: Integer): Boolean; + +Adds the item (if it exists) in the specified Inventory slot, InvSlot, to the +specified slot, ActionBarSlot, of the Action Bar. Returns true on success. + +.. note:: + + by euphemism + Last modified: Jan. 31st, 2013 by euphemism + +Example: + +.. code-block:: pascal + + + if (AddItemToActionBar(4, 5)) then + WriteLn('Added the item in Inventory slot 4 to Action Bar slot 5.'); +*) +function AddItemToActionBar(InvSlot, ActionBarSlot: Integer): Boolean; +var + bmp, I, Len, TimeMarker, X, Y: Integer; + acc: Extended; + InventoryBox, ActionSlot: TBox; + KeyBindTPA, TPA: TPointArray; +begin + Result := False; + if ((not GameTab(tab_Inv)) or (not ToggleActionBar(True))) then + Exit; + if (not ExistsItem(InvSlot)) then + Exit; + InventoryBox := InvBox(InvSlot); + InventoryBox.x2 := InventoryBox.x2 - 2; + InventoryBox.y2 := InventoryBox.y2 - 2; + ActionSlot := ActionBarSlotToBox(ActionBarSlot); + try + bmp := BitmapFromClient(InventoryBox.x1, InventoryBox.y1, InventoryBox.x2, InventoryBox.y2); + TPAFromBoxWrap(IntToBox(InventoryBox.x1 + 2, InventoryBox.y2 - 10, InventoryBox.x1 + 8, InventoryBox.y2 - 3), KeyBindTPA); + OffsetTPA(KeyBindTPA, IntToPoint(- InventoryBox.x1, - InventoryBox.y1)); + Len := Length(KeyBindTPA); + for I := 0 to (Len - 1) do + FastSetPixel(bmp, KeyBindTPA[i].x, KeyBindTPA[i].y, 0); + ColorToleranceSpeed(0); + FindColorsTolerance(TPA, 3292227, InventoryBox.x1, InventoryBox.y1, InventoryBox.x2, InventoryBox.y2, 8); + OffsetTPA(TPA, IntToPoint(- InventoryBox.x1, - InventoryBox.y1)); + Len := Length(TPA); + for I := 0 to (Len - 1) do + FastSetPixel(bmp, TPA[i].x, TPA[i].y, 0); + FindDeformedBitmapToleranceIn(bmp, X, Y, ActionSlot.x1, ActionSlot.y1 - 1, ActionSlot.x2, ActionSlot.y2, 35, 0, false, acc); + Result := (acc > 0.8); + if (Result) then + Exit; + DragMouse(InventoryBox.x1, InventoryBox.y1, 30, 30, ActionSlot.x1, ActionSlot.y1, 28, 28); + TimeMarker := GetSystemTime + RandomRange(802, 1113); + repeat + if (ExistsItem(InvSlot)) then + begin + FindDeformedBitmapToleranceIn(bmp, X, Y, ActionSlot.x1, ActionSlot.y1 - 1, ActionSlot.x2, ActionSlot.y2 + 1, 35, 0, False, Acc); + Result := (acc > 0.8); + end; + until ((Result) or (GetSystemTime > TimeMarker)); + finally + FreeBitmap(bmp); + end; +end; + +(* +GetKeyBind +~~~~~~~~~~ + +.. code-block:: pascal + + function GetKeyBind(Slot: Integer): String; + +Gets the key binded to the action bar at Slot. + +.. note:: + + by riwu + Last modified: 1 Jan 2012 by riwu + +*) +function GetKeyBind(Slot: Integer): String; +begin + if not InRange(Slot, 1, 12) then + begin + srl_Warn('GetKeyBind', 'Slot must be within 1-12!', warn_AllVersions); + Exit; + end; + + if not IsActionBarOpen then + if ToggleActionBar(True) then + srl_Warn('GetKeyBind', 'Action bar opened to grab text', warn_AllVersions) + else + begin + srl_Warn('GetKeyBind', 'Unable to open action bar', warn_AllVersions); + Exit; + end; + + Result:= GetTextAt(13 + 36 * Slot, 316, 0, 0, 0, 3111603, 0, 1, UpChars); +end; + +(* +Gametab Functions +----------------- + +*) + +(* +GetCurrentTab +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetCurrentTab: Integer; + +Returns current tab. + +.. note:: + + by Zephyrsfury + +Example: + +.. code-block:: pascal + + if (not tabExists(TAB_MAGIC)) then + writeln('We may be in a random event!'); + + +*) +function GetCurrentTab: Integer; +var + tP: TPoint; +begin + Result := -1; + if (not LoggedIn) then exit; + + for Result := 0 to (tab_LogOut - tab_Combat)-1 do + begin + tP.X := 535 + Result mod 8 * 30; + tP.Y := 169 + Result div 8 * 298; + if (GetColor(tP.X, tP.Y) = 3775717) then //Midpoint of the top boundary of the tab + Break; + end; + Result := Result + tab_Combat; + if BankScreen then + Result := tab_Inv; +end; + +(* +TabExists +~~~~~~~~~ + +.. code-block:: pascal + + function TabExists(tab: integer): boolean; + +Returns true if the gametab 'tab' exists. Tab constants can be found in +globals.simba. + +.. note:: + + by Zephyrsfury & Icefire908 + Last Modified: Mar. 7th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + if (not tabExists(TAB_MAGIC)) then + writeln('We may be in a random event!'); +*) +function TabExists(tab: integer): boolean; +var + b: TBox; + tmpCTS: integer; +begin + result := false; + if (not loggedIn) then + exit; + + if (not inRange(tab, TAB_COMBAT, TAB_LOGOUT)) then + begin + SRL_Warn('TabExists', 'Tab ' + toStr(Tab) + ' is not a valid tab number.', warn_AllVersions); + exit; + end; + + // requires CTS 1, may result in false negatives if CTS 2 + tmpCTS := getColorToleranceSpeed; + colorToleranceSpeed(1); + + if (tab = TAB_INV) then + if (bankScreen) then + begin + colorToleranceSpeed(tmpCTS); + result := true; + exit; + end; + + if (tab = TAB_LOGOUT) then + begin + result := (getColor(746, 0) = 0); //Top left of tab_LogOut + colorToleranceSpeed(tmpCTS); + exit; + end; + + // small boxes inside the tabs (hardly any of the background showing) + b := gridBox(tab - 20, 8, 2, 13, 18, 30, 300, point(536, 186)); + + // the color of the tab background + result := (countColorTolerance(5005422, b.x1, b.y1, b.x2, b.y2, 55) < 250); // actual count should be 266 + + colorToleranceSpeed(tmpCTS); +end; + +(* + +GameTab +~~~~~~~ + +.. code-block:: pascal + + function GameTab(Tab: Integer): Boolean; + +Returns True if the Tab exists. + +.. note:: + + by Zephyrsfury + +.. code-block:: pascal + + const + tab_Combat = 21; + tab_Stats = 22; + tab_Quest = 23; + tab_Diary = 24; + tab_Inv = 25; + tab_Equip = 26; + tab_Prayer = 27; + tab_Magic = 28; + tab_Objectives = 29; + tab_Friends = 30; + tab_Ignore = 31; + tab_Clan = 32; + tab_Options = 33; + tab_Emotes = 34; + tab_Music = 35; + tab_Notes = 36; + tab_LogOut = 37; + +.. note:: + Please use the constants and not the numbers! They may change any interface update. + + +Example: + +.. code-block:: pascal + +*) +function GameTab(Tab: Integer): Boolean; +var + tP: TPoint; + T, Tries: Integer; + +begin + if (not LoggedIn) then + Exit; + + Result := false; + if (not(InRange(Tab, Tab_Combat, Tab_LogOut))) then + begin + SRL_Warn('GameTab', 'Tab ' + IntToStr(Tab) + ' is not a valid tab number.', warn_AllVersions); + Exit; + end; + + Result := (GetCurrentTab = Tab); + if (Result) then exit; + + if (TabExists(Tab)) then + begin + tP := Point((Tab - 21) mod 8 * 30 + RandomRange(527, 545), + (Tab - 21) div 8 * 298 + RandomRange(177, 197)); + if (Tab = tab_LogOut) then + tP := Point(RandomRange(747, 760), RandomRange(3, 18)); + + Tries := 0; + while ((Tries < 3) and (not Result)) do + begin + Mouse(tP.X, tP.Y, 0, 0, mouse_left); + + T := GetSystemTime; + while (not Result) and (GetSystemTime - T < 2000) do + begin + Result := (GetCurrentTab = Tab); + Wait(100 + Random(100)); + end; + + Inc(Tries); + end; + + if (Result) then + Wait(250 + Random(300)); + + end else + SRL_Warn('GameTab', 'GameTab ' + IntToStr(Tab) + ' is not a valid tab number.', warn_Notice); +end; + +(* + +FTab +~~~~ + +.. code-block:: pascal + + function FTab(Tab: Integer): Boolean; + +Instead of clicking the Tab this uses the F keys to instantly switch to the tab. +Only works with Inv, Equip, Prayer, Magic and Combat tabs (F1-F5). +Returns True if the Tab exists. + +.. note:: + + by Narcle + Last Modified: 22/12/12 by riwu + +.. code-block:: pascal + + const + tab_Combat = 21; + tab_Inv = 25; + tab_Equip = 26; + tab_Prayer = 27; + tab_Magic = 28; + +.. note:: + Please use the constants and not the numbers! They may change any interface update. + + +Example: + +.. code-block:: pascal + +*) +function FTab(Tab: integer): boolean; +var + T, F: integer; +begin + if (GetCurrentTab = Tab) then + begin + result := true; + Exit; + end; + + Case Tab of + tab_Inv: F := 1; + tab_Equip: F := 2; + tab_Prayer: F := 3; + tab_Magic: F := 4; + tab_Combat: F := 5; + else + writeln('Tab '+inttostr(tab)+' isn''t a valid option.'); + end; + T := GetSystemTime + 618; + Repeat + TypeByte(111+F); + Wait(150+random(100)); + Result := GetCurrentTab = Tab; + until Result or (GetSystemTime > T); + + if not Result then //F keys sometimes doesn't work properly in EOC, may be a bug on Jagex's part though + Result:= GameTab(Tab); //nevertheless this is a good failsafe +end; + +(* + +Gametab 1 +--------- + +Gametab 1 related functions. +*) + +(* + +SetFightMode +~~~~~~~~~~~~ + +.. code-block:: pascal + + function SetFightMode(oFightMode: Integer): Boolean; + +Sets fight mode. Returns false if failed to set desired mode. + +.. note:: + + by Nielsie95 & Nava2, fixed by Quickmarch + +Example: + +.. code-block:: pascal + +*) +function SetFightMode(oFightMode: Integer): Boolean; +var + i, x, y: Integer; + b: TBox; + cmbBoxes: TBoxArray; +begin + Result := False; + if not(Loggedin)then Exit; + GameTab(tab_Combat); + Wait(200 + Random(100)); + + cmbBoxes := [IntToBox(575, 255, 630, 290), IntToBox(660, 255, 710, 290), + IntToBox(575, 310, 630, 345), IntToBox(660, 310, 710, 345)]; + b := cmbBoxes[oFightMode - 1]; + + if (oFightMode = 4) and (not FindColor(x, y, 2070783, 660, 310, 710, 345)) then + b := cmbBoxes[2]; + + i := 0; + while (i < 4) do + begin + Result := FindColorTolerance(x, y, 1323362, b.x1, b.y1, b.x2, b.y2, 2); + if (Result) then Exit; + MouseBox(b.x1, b.y1, b.x2, b.y2, mouse_left); + Wait(500 + Random(300)); + Inc(i); + end; +end; + +(* + +GetWeaponName +~~~~~~~~~~~~~ + +.. code-block:: pascal + + Function GetWeaponName: String; + +Returns the name of the weapon your currently using. + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + +*) +Function GetWeaponName: String; +begin + if GameTab(tab_Combat) then + Result := GetTextAtExWrap(584, 208, 734, 226, 0, 3, 4, 3907053, 0, UpChars); +end; + +(* + +GetWeaponData +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetWeaponData(var WArr: array of TStringArray): Boolean; + +Grabs weapon data and puts it into T2DStringArray. The data is the +information you get when you mouse over the attack styles of the weapon. This +then sets it into a array that can be used to set the fight mode of the weapon. +It even gets info like 'Crush' or 'Slash' can be useful if the NPC is weak to +that type of attack. + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + +*) +function GetWeaponData(var WArr: array of TStringArray): Boolean; +var + x, y, i, ii, H, L: integer; + TB: TBox; + TP: TPointArray; + T: TPoint; +begin + Result := False; + if (not LoggedIn) then + Exit; + if not GameTab(tab_Combat) then + Exit; + for i := 0 to 3 do + begin + T := Point(680-(i+1) mod 2*85, 270+2 mod (i+1)*28); + if CountColor(2070783, T.x - 27, T.y-18, T.x + 40, T.y + 22) > 10 then + Inc(L); + end; + SetArrayLength(WArr, L); + for I := 0 to L-1 do + begin + MMouse(680-(i+1) mod 2*85, 270+2 mod (i+1)*28, 12, 12); + wait(100+random(50)); + WaitFindColor(X, Y, 15133931, MIX1-10, MIY1-10, MIX2+10, MIY2+10, 0, 3000); + GetClientDimensions(TB.X2, TB.Y2); + TB := IntToBox(0, 0, TB.X2, TB.Y2); + FindColors(TP, 15133931, TB.X1, TB.Y1, TB.X2 - 1, TB.Y2 - 1); + if (Length(TP) < 1) then + Continue; + TB := GetTPABounds(TP); + H := ((TB.y2-TB.y1) div 17)-1; + SetArrayLength(WArr[i], H+1); + for ii := 0 to H do + begin + WArr[i][ii] := GetTextAtExWrap(TB.x1+1, TB.y1+2, TB.x2, TB.y1+18, 0, 3, 4, 4305653, 0, smallChars); + Debugln(WArr[i][ii]); + Result := (WArr[i][ii] <> ''); + IncEx(TB.Y1, 16); + end; + end; +end; + +(* + +SetWeaponMode +~~~~~~~~~~~~~ + +.. code-block:: pascal + + Function SetWeaponMode(Skill: string; WeaponData: array of TStringArray; SetIt: boolean): boolean; + +Sets Combat mode depending on WeaponData given. You can also +decide to SetIt which will set it to that particular skill or read it to see +if they are ranging, meleeing or using magic (with staff). + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + +*) +Function SetWeaponMode(Skill: string; WeaponData: array of TStringArray; SetIt: boolean): boolean; +var + i, ii: integer; +begin + for i := 0 to High(WeaponData) do + for ii := 0 to High(WeaponData[i]) do + if (Pos(Lowercase(skill), Lowercase(WeaponData[i][ii])) <> 0) then + begin + if SetIt then + Result := SetFightMode(i + 1) + else + Result := True; + Exit; + end; +end; + +(* + +SetCombatType +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function SetCombatType(Kind : string): Boolean; + +Sets Combat mode inputted into Kind, treat like UpText. + +.. note:: + + by Narcle & Nava2 + +Example: + +.. code-block:: pascal + +*) +function SetCombatType(Skill: string): Boolean; +var + WeapArr: array of TStringArray; +begin + if GetWeaponData(WeapArr) then + Result := SetWeaponMode(Skill, WeapArr, true) + else + Result := False; +end; + +(* + +GetCombatLevel +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetCombatLevel: Integer; + +Returns the players combat level. + +.. note:: + + by Nielsie95 & Narcle + Updated 26/11/2012 by riwu + +Example: + +.. code-block:: pascal + +*) +function GetCombatLevel: Integer; +begin + Result := -1; + if not FTab(tab_Combat) then + exit; + + Result := StrToIntDef(ExtractFromStr(GetTextAtExWrap(556, 316, 584, 333, 0, + 3, 4, 3111603, 0, UpChars), Numbers), -1); +end; + +(* + +HasTarget +~~~~~~~~~ + +.. code-block:: pascal + + function HasTarget: Boolean; + +Returns true if the player has a combat target currently. + +.. note:: + + by riwu + +Example: + +.. code-block:: pascal + +*) +function HasTarget: Boolean; +begin + Result := False; + if not FTab(tab_Combat) then + Exit; + + Result := not FindTextTPA(3111603, 0, 615, 220, 654, 229, 'Target', UpChars, nothing); +end; + +(* + +GetTargetCombatLevel +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetTargetCombatLevel: Integer; + +Returns the target combat level. + +.. note:: + + by riwu, modelled after GetCombatLevel by Nielsie95 & Narcle + +Example: + +.. code-block:: pascal + +*) +function GetTargetCombatLevel: Integer; +begin + Result := -1; + if not (FTab(tab_Combat) and HasTarget) then + begin + srl_Warn('GetTargetCombatLevel', 'Could not get target level', warn_AllVersions); + Exit; + end; + + Result := StrToIntDef(ExtractFromStr(GetTextAtExWrap(695, 208, 728, 223, 0, + 3, 4, 3111603, 0, UpChars), Numbers), -1); +end; + +(* +TargetHpPercent +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function TargetHpPercent: Integer; + + Returns the Hp Percent of the target. + +.. note:: + + by riwu + +Example: + +.. code-block:: pascal + +*) +function TargetHpPercent: Integer; +var + hpBar: TPointArray; + box: TBox; +begin + Result:= 0; + + if not FTab(tab_Combat) then + begin + srl_Warn('TargetHpPercent', 'Could not open combat tab', warn_AllVersions); + Exit; + end; + + if not HasTarget then + Exit; + + if FindColorsTolerance(hpBar, 2329176, 600, 237, 685, 242, 50) then + begin + box:= GetTPABounds(hpBar); + Result:= Round((box.X2 - box.X1 + 1) / 0.86); + end; +end; + +(* + +Retaliate +~~~~~~~~~ + +.. code-block:: pascal + + procedure Retaliate(RetTrue: Boolean); + +Set's Auto Retaliate ON of OFF. + +.. note:: + + by WT-Fakawi & n3ss3s, slight mod by EvilChicken! + Updated 26/11/2012 by riwu + +Example: + +.. code-block:: pascal + +*) +procedure Retaliate(RetTrue: Boolean); +begin + if not FTab(tab_Combat) then + Exit; + + if (RetTrue) xor FindTextTPA(3111603, 0, 558, 437, 682, 455, 'On', UpChars, nothing) then + MouseBox(558, 437, 682, 455, mouse_left); +end; + +(* + +Gametab 2 +--------- + +Gametab 2 related functions. + +*) + +//****************************************************************************// +// * GameTab 2 Related Functions. +//****************************************************************************// + +{ const Skill Constants; + Description: Constants representing player skills. } +{ consts in Players.scar ; Here is the list for easier access +const + SKILL_ATTACK = 0; + SKILL_DEFENCE = 1; + SKILL_STRENGTH = 2; + SKILL_HITPOINTS = 3; + SKILL_RANGE = 4; + SKILL_PRAYER = 5; + SKILL_MAGIC = 6; + SKILL_COOKING = 7; + SKILL_WOODCUTTING = 8; + SKILL_FLETCHING = 9; + SKILL_FISHING = 10; + SKILL_FIREMAKING = 11; + SKILL_CRAFTING = 12; + SKILL_SMITHING = 13; + SKILL_MINING = 14; + SKILL_HERBLORE = 15; + SKILL_AGILITY = 16; + SKILL_THIEVING = 17; + SKILL_SLAYER = 18; + SKILL_FARMING = 19; + SKILL_RUNECRAFTING = 20; + SKILL_HUNTER = 21; + SKILL_CONSTRUCTION = 22; + SKILL_SUMMONING = 23; + SKILL_DUNGEONEERING = 24; + SKILL_ALLCOMBAT = 25; + SKILL_EVERYSKILL = 26; + SKILL_NONE = 27; +} +(* + +SkillCoords +~~~~~~~~~~~ + +.. code-block:: pascal + + function SkillCoords(Row, Column: Integer): TPoint; + +Returns Coords of Skill's Row and Column (Used for GetSkill functions) + +.. note:: + + by NaumanAkhlaQ + +Example: + +.. code-block:: pascal + +*) +function SkillCoords(Row, Column : ShortInt): TPoint; +begin + Result := Point(576 + (62 * (Column - 1)), 213 + (28 * (Row - 1))); +end; + +(* + +SkillToCoords +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function SkillToCoords(Skill: Variant): TPoint; + +Turns skill string into TPoint. +If Scroll returns true then you must scroll down. + +.. note:: + + by Masquerader et. al. + +Example: + +.. code-block:: pascal + +*) +function SkillToCoords(Skill: Variant): TPoint; +var + SkillArr: TStringArray; + skNo: Integer; + SkillS: string; + SkillPT : TPoint; //Row/Column +begin + if (not LoggedIn) then exit; + + if VariantIsInteger(Skill) then + skNo := Skill + else + begin; + SkillS := Lowercase(Skill); + case Lowercase(SkillS) of + 'hp', 'constitution': SkillS := 'hitpoints'; + 'ranged': SkillS := 'range'; + 'hunter': SkillS := 'hunting'; + 'dung' : skillS := 'dungeoneering'; + end; + + SkillArr := ['attack', 'defence', 'strength', 'hitpoints', 'range', + 'prayer', 'magic', 'cooking', 'woodcutting', 'fletching', + 'fishing', 'firemaking', 'crafting', 'smithing', 'mining', + 'herblore', 'agility', 'thieving', 'slayer', 'farming', + 'runecrafting', 'hunting', 'construction', 'summoning', + 'dungeoneering']; + if (not InStrArrEx(SkillS, SkillArr, skNo)) then + begin + srl_Warn('SkillToCoords', + 'Invalid Skill Name/Number: ''' + string(Skill) + '''', + warn_AllVersions); + Exit; + end; + end; + case skNo of + Skill_Attack : SkillPT := Point(1,1); + Skill_Strength : SkillPT := Point(1,2); + Skill_Defence : SkillPT := Point(1,3); + Skill_Range : SkillPT := Point(1,4); + Skill_Prayer : SkillPT := Point(1,5); + Skill_Magic : SkillPT := Point(1,6); + Skill_RuneCrafting : SkillPT := Point(1,7); + Skill_Construction : SkillPT := Point(1,8); + Skill_Dungeoneering : SkillPT := Point(1,9); + Skill_Hitpoints : SkillPT := Point(2,1); + Skill_Agility : SkillPT := Point(2,2); + Skill_Herblore : SkillPT := Point(2,3); + Skill_Thieving : SkillPT := Point(2,4); + Skill_Crafting : SkillPT := Point(2,5); + Skill_Fletching : SkillPT := Point(2,6); + Skill_Slayer : SkillPT := Point(2,7); + Skill_Hunter : SkillPT := Point(2,8); + Skill_Mining : SkillPT := Point(3,1); + Skill_Smithing : SkillPT := Point(3,2); + Skill_Fishing : SkillPT := Point(3,3); + Skill_Cooking : SkillPT := Point(3,4); + Skill_FireMaking : SkillPT := Point(3,5); + Skill_WoodCutting : SkillPT := Point(3,6); + Skill_Farming : SkillPT := Point(3,7); + Skill_Summoning : SkillPT := Point(3,8); + else + begin + srl_Warn('SkillToCoords', 'Invalid Skill Number: ''' + inttostr(skNo) + '''', warn_AllVersions); + exit; + end; + end; + Result := SkillCoords(SkillPT.y,SkillPT.x); +end; + +(* +GetSkillInfo +~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetSkillInfo(Skill: Variant; Amount : Boolean): Integer; + +Gets the amount / level of a skill. +E.G. +0/15 +Amount = True will return 0. +Amount = False will return 15 (The actual level). +Returns -1 if the level couln't be grabbed succesfully + +.. note:: + + by Raymond + +Example: + +.. code-block:: pascal +*) +function GetSkillInfo(Skill: Variant; Amount : Boolean): Integer; +var + TP: TPoint; + Box : TBox; + TPA : TPointArray; + Cts : Integer; + +begin + Result := -1; + GameTab(tab_Stats); + TP := SkillToCoords(Skill); + if (not(Amount)) then + TP := Point(TP.x + 15,TP.y + 12); + CTS := GetColorToleranceSpeed; + ColorToleranceSpeed(0); + if not FindColors(TPA, 36095, TP.x - 2, TP.y - 2, TP.x + 15, TP.y + 15) then + begin + ColorToleranceSpeed(CTS); + exit; + end; + Box := GetTPABounds(TPA); + Result := StrToIntDef(GetNumbers(GetTextAtEx(Box.x1 - 2, Box.y1 -1, 100, + StatChars, False, True, 0, 3, 36095, 3, True, tr_Digits)), -1); + ColorToleranceSpeed(CTS); +end; + +(* +GetSkillLevel +~~~~~~~~~~~~~ + +.. code-block:: pascal + + Function GetSkillLevel(skill: Variant): Integer; + +Gets the max level for a particular skill. + +.. note:: + + by Raymond + +Example: + +.. code-block:: pascal +*) +function GetSkillLevel(Skill: Variant): Integer; +begin + Result := GetSkillInfo(Skill, False); +end; + +(* +IsRunOn +~~~~~~~ + +.. code-block:: pascal + + function IsRunOn: Boolean; + +Returns True if run button is on. + +.. note:: + + by Slushpuppy + +Example: + +.. code-block:: pascal +*) +function IsRunOn: Boolean; +begin + result := CountColorTolerance(3467501, 720, 117, 723, 119, 80) > 1; +end; + +(* +IsResting +~~~~~~~~~ + +.. code-block:: pascal + + function IsResting: Boolean; + +Returns True if you are currently resting. + +.. note:: + + by Sabzi + +Example: + +.. code-block:: pascal +*) +function IsResting: Boolean; +begin + result := (CountColorTolerance(3712343,707, 95,732, 122,10)>10); +end; + +(* +GetMMLevels +~~~~~~~~~~~ + +.. code-block:: pascal + + Function GetMMLevels(LevelType : String;var ColorSign : String): integer; + +Returns the level shown next to the minimap. +Colorsign returns the color of the text (Green,Yellow,Orange,Red). +Returns -1 if failed. + +.. note:: + + by Raymond / Wizzup / Sabzi / NCDS + +Example: + +.. code-block:: pascal + + Value := GetMMLevels( 'hp' ) ; // Will retrieve your Hit Points + Value := GetMMLevels( 'pray' ) ; // Will retrieve your Prayer Points + Value := GetMMLevels( 'run' ) ; // Will retrieve your Run energy + Value := GetMMLevels( 'summon' ) ; // Will retrieve your Summoning Points + +*) +function GetMMLevels(LevelType: string; var ColorSign: string): Integer; +var + Colors : TIntegerArray; + Signs: TStringArray; + P: TPointArray; + I: Integer; + B: TBox; +begin; + Result := -1; + ColorSign := ''; + case LowerCase(Leveltype) of + 'health', 'hp', 'hitpoints', 'constitution': B := IntToBox(719,27,745,43); + 'prayer', 'pray' : B := IntToBox(735,66,762,82); + 'run','energy' : B := IntToBox(735,103,762,122); + 'summon', 'summoning' : B := IntToBox(719,119,745,156); + else + begin; + srl_Warn('GetMMLevels', 'Invalid LevelType: ''' + LevelType + '', warn_AllVersions); + Exit; + end; + end; + Colors := [65280, 65535, 2070783, 255]; + Signs := ['Green', 'Yellow', 'Orange', 'Red']; + for I := 0 to 3 do + begin + With B do + FindColorsTolerance(P, Colors[i], x1, y1, x2, y2, 30); + if Length(P) < 1 then + Continue; + Result := StrToIntDef(GetNumbers(GetTextAtExWrap(B.X1, B.Y1, B.X2, B.Y2, 0, 4, 4, Colors[i], 20, statChars)), -1); + if (Result > -1) then + begin + ColorSign := Signs[i]; + Exit; + end; + end; +end; + +(* +GetXP +~~~~~ + +.. code-block:: pascal + + function GetXP(Skill: Variant): Integer; + +Returns current xp for a skill. Returns -1 if failed. + +.. note:: + + by Nielsie95 + +Example: + +.. code-block:: pascal +*) +function GetXP(skill: variant): integer; +var + b: TBox; + p: TPoint; + tpa: TPointArray; +begin + result := -1; + + if (not gameTab(TAB_STATS)) then + exit; + + p := skillToCoords(skill); + if (p.x < 1) then + exit; + + mmouse(p.x, p.y + 5, 12, 4); + wait(400 + random(200)); + + if (WaitFindColors(tpa, 15133931, MIX1, MIY1, MIX2, MIY2, 0, 3000)) then + begin + b := getTPABounds(tpa); + wait(400 + random(150)); + result := strToIntDef(getNumbers(getTextAt(b.x1 + 15, b.y1 + 15, 0, 1, 4, 4305653, 0, 75, smallChars)), -1); + end; +end; + +(* +XPTillNextLevel +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function XpTillNextLevel(Skill: Variant): Integer; + +Returns current xp until you level up in a skill. +Returns -1 if failed. + +.. note:: + + by Nielsie95 + +Example: + +.. code-block:: pascal +*) +function XPTillNextLevel(Skill: Variant): Integer; +var + TPA: TPointArray; + P: TPoint; + B: TBox; +begin + Result := -1; + if (not TabExists(tab_Stats)) then exit; + GameTab(tab_Stats); + if (GetCurrentTab <> tab_Stats) then exit; + P := SkillToCoords(Skill); + if (P.x < 1) then exit; + MMouse(P.x, P.y + 5, 12, 4); + wait(400 + random(200)); + if (not WaitFindColors(TPA, 15133931, MIX1, MIY1, MIX2, MIY2, 0, 4000)) then exit; + B := GetTPABounds(TPA); + Wait(200 + Random(150)); + Result := StrToIntDef(GetNumbers(GetTextAt(B.X1 + 15, B.Y1 + 45, 0, 1, 4, 4305653, 0, 75, SmallChars)), -1); +end; + +(* +HPPercent +~~~~~~~~~ + +.. code-block:: pascal + + function HpPercent: Integer; + +Returns Hp left as a percentage. +Does not switch tabs if Players[CurrentPlayer].Level[SKILL_HITPOINTS] (HP level) is set. +Returns -1 if failed. + +.. note:: + + by Wizzup? + +Example: + +.. code-block:: pascal +*) +function HPPercent: Integer; +var + ColorString: string; +begin + if (Players[CurrentPlayer].Level[SKILL_HITPOINTS] < 1) then + Players[CurrentPlayer].Level[SKILL_HITPOINTS] := Max(1, GetSkillInfo('hitpoints', False)); + + if (Players[CurrentPlayer].Level[SKILL_HITPOINTS] > 1) then + Result := Round(GetMMLevels('hp', ColorString) * 10 / Players[CurrentPlayer].Level[SKILL_HITPOINTS]) + else + Result := -1; +end; + +(* +GetAllLevels +~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure GetAllLevels; + +Sets all 25 skilllevels to Players.Level[0..24]: +Refer to the 'GameTab 2 Related Functions' above for the order. + +.. note:: + + by WT-Fakawi & ZephyrsFury + +Example: + +.. code-block:: pascal +*) +procedure GetAllLevels; +var + II: Integer; +begin + try + for II := 0 to High(Players[CurrentPlayer].Level) do + Players[CurrentPlayer].Level[II] := GetSkillLevel(II); + except + srl_Warn('GetAllLevels', 'CurrentPlayer not declared!', warn_AllVersions); + end; +end; + +(* +Gametab 4 +--------- + +Gametab 4 related functions + +*) + + +(* + +Gametab 5 +--------- + +Gametab 5 related functions + +*) + +(* +EquipmentCoords +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function EquipmentCoords(EquipSlot: Integer): TPoint; + +Returns X and Y of the coordinates of the specified equipment item + +.. note:: + + by RsN modded by WT-Fakawi and Nielsie95 + +Example: + +.. code-block:: pascal + +*) + +function EquipmentCoords(EquipSlot: Integer): TPoint; +begin + case EquipSlot of + 1: Result := Point(640, 225); + 2: Result := Point(600, 266); + 3: Result := Point(640, 266); + 4: Result := Point(684, 266); + 5: Result := Point(588, 304); + 6: Result := Point(644, 304); + 7: Result := Point(700, 304); + 8: Result := Point(642, 343); + 9: Result := Point(588, 384); + 10: Result := Point(643, 384); + 11: Result := Point(700, 384); + else + begin + result := Point(-1,-1); + srl_warn('EquipmentCoords','Invalid EquipSlot('+inttostr(EquipSlot)+') passed',warn_AllVersions); + end; + end; +end; + +(* +GetEquippedItemBounds +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetEquippedItemBounds(Which: String): TBox; + +Returns TBox of eqquipped item in which. + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + +*) +function GetEquippedItemBounds(Which: Variant): TBox; +var + P: TPoint; + I: Integer; +begin + Result := IntToBox(0, 0, 0, 0); + I := -1; + + if VariantIsString(Which) then + case Which of + 'helm', 'helmet' : + I := 1; + 'cape' : + I := 2; + 'amulet', 'neck', 'necklace' : + I := 3; + 'arrows', 'bolts' : + I := 4; + 'right hand', 'weapon' : + I := 5; + 'plate', 'chest', 'platebody' : + I := 6; + 'left hand', 'sheild', 'shield' : + I := 7; + 'legs', 'platelegs', 'skirt', 'plateskirt' : + I := 8; + 'gloves', 'gauntlets' : + I := 9; + 'boots': + I := 10; + 'ring' : + I := 11; + end + else if VariantIsInteger(Which) then + if (InRange(Which, 1, 11)) then + I := Which; + + if (I = -1) then + begin + SRL_Warn('GetEquiptItemBounds', 'Invalid entry (' + ToStr(Which) + ')', Warn_AllVersions); + Exit; + end; + + P := EquipmentCoords(I); + Result := IntToBox(P.x - 11, P.y - 11, P.x + 11, P.y + 11); +end; + +(* +MouseEquippedItem +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure MouseEquippedItem(Which : String; Left : Integer); + +Mouses Equipped item like MouseItem. + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + +*) +procedure MouseEquippedItem(Which: String; ClickType: Integer); +var + B : TBox; +begin + B := GetEquippedItemBounds(Which); + if (B.x1 = 0) and (B.x2 = 0) then Exit; + GameTab(tab_Equip); + MouseBox(B.x1, B.y1, B.x2, B.y2, ClickType); +end; + +(* +WearingItem +~~~~~~~~~~~ + +.. code-block:: pascal + + function WearingItem(i: Integer): Boolean; + +Results True if an item is equipped at equpiment slot defined by I. + +.. note:: + + by RsN + +Example: + +.. code-block:: pascal + +*) +function WearingItem(I: Integer): Boolean; +var + X, Y: Integer; + TP: TPoint; +begin + Result := false; + if (not InRange(I, 1, 11)) then + begin + srl_Warn('WearingItem', 'Equipment slot #' + IntToStr(I) + ' is not a valid equipment slot', warn_Warning); + Exit; + end; + if (not Gametab(tab_Equip)) then exit; + + TP := EquipmentCoords(I); + Result := FindColor(X, Y, srl_outline_black, TP.x - 8, TP.y - 8, TP.x + 8, TP.y + 8); +end; + +(* +TakeOff +~~~~~~~ + +.. code-block:: pascal + + procedure TakeOff(I: Integer); + +UnEquips Item specified in i. + +.. note:: + + by RsN + +Example: + +.. code-block:: pascal + +*) +procedure TakeOff(I: Integer); +var + TP: TPoint; +begin + TP := EquipmentCoords(I); + if (WearingItem(I)) then + begin + Mouse(TP.x, TP.y, 5, 5, mouse_left); + Wait(200 + Random(350)); + end; +end; + +(* +TakeOffAllExcept +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure TakeOffAllExcept(ExceptionSlots: TIntegerArray); + +Takes off equipped items defined by StripSlots. + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + +*) +procedure TakeOffAllExcept(ExceptionSlots: TIntegerArray); +var + I: Integer; +begin + for I := 1 to 11 do + if (not InIntArray(ExceptionSlots, I)) then + TakeOff(I); +end; + +(* +TakeOffAllItems +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure TakeOffAllItems; + +Takes off all equipped items. + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + +*) +procedure TakeOffAllItems; +begin + TakeOffAllExcept([]); +end; + +(* +CountEquippedItems +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function CountEquippedItems: Integer; + +Counts the amount of equipped items. Results "-1" if failed. + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + +*) +function CountEquippedItems: Integer; +var + I: Integer; +begin + Result := Ord(GameTab(tab_Equip)) - 2; + if (Result = -1) then exit; + + for I := 1 to 11 do + if WearingItem(I) then + Inc(Result); +end; + +(* +Gametab 6 +--------- + +Gametab 6 related functions + +*) + +(* +Gametab 7 +--------- + +Gametab 7 related functions + +*) + +(* +Gametab 8 +--------- + +Gametab 8 related functions + +*) + +(* +CurrentWorld +~~~~~~~~~~~~ + +.. code-block:: pascal + + function CurrentWorld: Integer; + +Returns current world from Friends Tab + +.. note:: + + by Home + +Example: + +.. code-block:: pascal + +*) +function CurrentWorld: Integer; +var + Box :TBox; + TPA :TPointArray; +begin + Result := - 1; + if (GetCurrentTab <> tab_Friends) then + begin + GameTab(tab_Friends); + Wait(250 + Random(500)); + end; + FindColors(TPA, 3381759, 601, 223, 703, 238); + Box := GetTPABounds(TPA); + Result := StrToIntDef(ExtractFromStr(GetTextAtExWrap(Box.X1, Box.Y1, Box.X2, Box.Y2, 0, 3, 4, 3381759, 0, UpChars), Numbers), - 1); + if (Result = - 1) then + srl_Warn('CurrentWorld', 'Could not get Player''s current world', Warn_AllVersions); +end; + +(* + +Gametab 9 +--------- + +Gametab 9 related functions + +*) + +(* +ObjectivePercent +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ObjectivePercent: Integer; + +Returns (Roughly) Objective Completion in Percent. +Results -1 if failed. + +.. note:: + + by r!ch!e + +Example: + +.. code-block:: pascal + +*) +function ObjectivePercent: Integer; +begin + Result := -1; + if (not GameTab(tab_Objectives)) then exit; + Result := Round(CountColor(42516, 596, 390, 690, 400) / 9.73); +end; + +(* +ObjectiveCoords +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ObjectiveCoords(ObjSlot: Integer): TPoint; + +Returns Coords of Random Objective Slot (ObjSlot : 1..6) + +.. note:: + + by r!ch!e & Naum + +Example: + +.. code-block:: pascal + +*) +function ObjectiveCoords(ObjectiveSlot: Byte): TPoint; +begin + if (not InRange(ObjectiveSlot, 1, 6)) then + begin + srl_Warn('ObjectiveCoords', 'Invalid Slot', Warn_AllVersions); + Exit; + end; + Result.y := Trunc(ObjectiveSlot / 2) + 1; + if (Result.y mod 2 = 0) then + Dec(Result.y); + Result.x := ObjectiveSlot mod 3; + if (Result.x = 0) then + Result.x := 3; + Result := Point(RandomRange(20 + 165 * (Result.x - 1), 160 + 165 * (Result.x - 1)), + RandomRange(50 + 65 * (Result.y - 1), 160 + 65 * (Result.y - 1))); +end; + +(* +HasObjective +~~~~~~~~~~~~ + +.. code-block:: pascal + + function HasObjective: Boolean; + +Returns True if an Objective is set. + +.. note:: + + by r!ch!e + +Example: + +.. code-block:: pascal + +*) +function HasObjective: Boolean; +begin + Result := False; + if (GameTab(tab_Objectives)) then + Result := (GetColor(582, 267) <> 3029570) + else + srl_Warn('HasObjective', 'Failed to open GameTab #' + + IntToStr(tab_Objectives), Warn_AllVersions); +end; + +(* +ClearObjective +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClearObjective: Boolean; + +Returns True if an Objective is Cleared, or no Objective Exists. + +.. note:: + + by r!ch!e + +Example: + +.. code-block:: pascal + +*) +function ClearObjective: Boolean; +begin + Result := HasObjective; + if (Result) then + MouseBox(559, 447, 724, 456, mouse_left) + else + srl_Warn('ClearObjective', 'No Objective to Clear', Warn_AllVersions); +end; + +(* +SetObjective +~~~~~~~~~~~~ + +.. code-block:: pascal + + function SetObjective(Skill: String; Level: Integer): Boolean; + +Sets Objective according to Skill and Level. +Returns True if Objective is set. + +.. note:: + + by r!ch!e + +Example: + +.. code-block:: pascal + +*) +function SetObjective(Skill: string; Level: Integer): Boolean; +var + TP: TPoint; +begin + Result := False; + if (not InRange(Level, 1, 99)) then + begin + srl_Warn('SetObjective', IntToStr(Level) + ' is not a valid level', Warn_AllVersions); + Exit; + end; + + if (not GameTab(tab_Stats)) then exit; + TP := SkillToCoords(Skill); + Mouse(TP.x, TP.y + 3, 2, 2, mouse_right); + WaitOption('bjec', 300 + Random(500)); + Wait(1000 + Random(250)); + if (FindTextTpa(clBlack, 0, 100, 390, 235, 410, 'Enter the skill', UpCharsEx, Nothing)) then + begin + Wait(1000 + Random(250)); + TypeSend(IntToStr(Level)); + Result := True; + end; +end; + +(* +SetRandomObjective +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function SetRandomObjective(ObjectiveSlot: Integer; KeepOld: Boolean): Boolean; + +Sets a Random Objective Slot (ObjSlot : 1..6). If an objective is +already set KeepOld determines if it is overwritten. +Returns True if Objective is set. + +.. note:: + + by r!ch!e + +Example: + +.. code-block:: pascal + +*) +function SetRandomObjective(ObjectiveSlot: Integer; KeepOld: Boolean): Boolean; +var + ObjP: TPoint; +begin + Result := False; + if not InRange(ObjectiveSlot, 1, 6) then + begin + srl_Warn('SetRandomObjective', 'Invalid Objective Slot', Warn_AllVersions); + Exit; + end; + + if (not GameTab(tab_Objectives)) then exit; + if (HasObjective) and (KeepOld) then exit; + + MouseBox(556, 422, 725, 432, mouse_left); + Wait(400 + Random(350)); + ObjP := ObjectiveCoords(ObjectiveSlot); + Mouse(ObjP.x, ObjP.y, 0, 0, mouse_left); + Result := HasObjective; +end; + +(* + +Gametab 10 +---------- + +Gametab 10 related functions + +*) + +(* + +Gametab 11 +---------- + +Gametab 11 related functions + +*) + +(* +SetRun +~~~~~~ + +.. code-block:: pascal + + function SetRun(Run: Boolean): Boolean; + +Sets Run on or off. + +.. note:: + + by Wizzup? & EvilChicken! + +Example: + +.. code-block:: pascal + +*) + +function SetRun(Run: Boolean): Boolean; +begin + Result := false; //Color near center of Run icon + if (((CountColorTolerance(3467501, 720, 117, 723, 119, 80) > 1) or (SimilarColors(GetColor(725, 111), 6740459, 10))) xor (Run)) then + begin + Mouse(715, 95, 10, 10, mouse_left); + Result := True; + end; +end; + +(* +RunEnergy +~~~~~~~~~ + +.. code-block:: pascal + + function RunEnergy(Min: Integer): Boolean; + +Toggles run if energy is greater or equal to MinEnergy. Results +true if energy is greater or equal to minimum. + +.. note:: + + by lordsaturn & NCDS + +Example: + +.. code-block:: pascal + +*) +function RunEnergy(Min: Integer): Boolean; +var + T, R: Integer; + s: String; +begin + T := GetSystemTime + 5000; + repeat + R := GetMMLevels('run', s); + Result := (R >= Min); + if (Result) then + begin + SetRun(True); + Exit; + end; + if (R > 0) then + Exit; + until (T > GetSystemTime); +end; + +(* +SetRest +~~~~~~~ + +.. code-block:: pascal + + function SetRest: Boolean; + +Turns Rest on. Result True if successful. + +.. note:: + + by ZephyrsFury, edited by NCDS + +Example: + +.. code-block:: pascal + +*) +function SetRest: Boolean; +begin + Result := False; + if (not(IsResting)) then + begin + Mouse(715, 95, 10, 10, mouse_right); + if (WaitOption('Rest', 300)) then + Result := WaitFunc(@IsResting, 100, 5000); + end; +end; + +(* +RestUntil +~~~~~~~~~ + +.. code-block:: pascal + + function RestUntil(Energy: Integer): Boolean; + +Rests until your Run energy is above Energy. Results True if successful. + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + +*) +function RestUntil(Energy: Integer): Boolean; +var + S: string; +begin + Result := (GetMMLevels('run', S) >= Energy); + if (Result) then exit; + SetRest; + while (GetMMLevels('run', S) < Energy) do + begin + Result := IsResting; + if (not(Result)) then exit; + if SRL_HasProc(srl_AntiBan) then + SRL_Procs[srl_AntiBan](); + Wait(100 + Random(50)); + end; +end; + +(* +RestUntilHP +~~~~~~~~~~~ + +.. code-block:: pascal + + function RestUntilHP(HPPerc: Integer): Boolean; + +Rests until your Run energy is above the given HP percentage. Results True if +successful. + +.. note:: + + by Mama + +Example: + +.. code-block:: pascal + +*) +function RestUntilHP(HPPerc: Integer): Boolean; +begin + Result := (HPPercent >= HPPerc); + if (Result) then exit; + SetRest; + while (HPPercent < HPPerc) do + begin + Result := IsResting; + if (not(Result)) then exit; + if SRL_HasProc(srl_AntiBan) then + SRL_Procs[srl_AntiBan](); + Wait(100 + Random(50)); + end; +end; + +Const + BrightnessColor = 9605778; + ScrollColor = 2106924; + ArrowOptions = 16645886; + BlueText = 14790912; + +(* +FixGraphics +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure FixGraphics; + +Fixes the Graphic Options if LoggedIn + +.. note:: + + by Naum & Rasta Magician + +Example: + +.. code-block:: pascal + +*) +procedure FixGraphics; +var + I, X, Y : Integer; + TPA : TPointArray; + ATPA : T2DPointArray; + TP : TPoint; + TB : TBox; +begin + if (not LoggedIn) then exit; + CloseWindow; + + if (not FindColor(x, y, ClBlack, 7, 460, 69, 474)) then {if you're in chat} + if (not ClickContinue(True, True)) then + begin + Mouse(MMCX, MMCY, 2, 2, mouse_left); + Wait(RandomRange(3000, 4000)); + end; + + i := 0; //failsafe opening clause + while (not FindTextTPA(ClWhite, 0, MSX1, MSY1, MSX2, MSY2, 'aphics', UpCharsEx, Nothing)) and (LoggedIn) do + begin + GameTab(tab_Options); + MouseBox(605, 258, 623, 277, mouse_left); + Wait(1000 + Random(500)); + Inc(i); + if (i > 3) then + begin + srl_Warn('SetGraphics', 'Could not open Graphics Options screen', warn_Warning); + CloseWindow; + Exit; + end; + end; + + If FindTextTPA(ClWhite, 0, MSX1, MSY1, MSX2, MSY2, 'aphics', UpCharsEx, Nothing) Then + Mouse(386, 172, 30, 10, mouse_left); + + if GetColor(255, 178) = BrightnessColor then + Mouse(255, 178, 2, 2, mouse_left); //Sets brightness + Wait(1000 + Random(400)); //waits for it + + FindColors(TPA, ArrowOptions, MSX1, MSY1, MSX2, MSY2); //finds drop down arrows + ATPA := SplitTPA(TPA, 5); //gets individual arrows + SortATPAFromFirstPoint(ATPA, Point(197, 89)); //sorts them + + for I := 0 to High(ATPA) do + begin + TP := MiddleTPA(ATPA[I]); + TB := IntToBox(TP.X - 60, TP.Y - 5, TP.X + 2, TP.Y + 5); + + if (CountColor(BlueText, TB.X1, TB.Y1, TB.X2, TB.Y2) > 5) then //if its not optimum + begin + Mouse(TP.X, TP.Y, 3, 3, mouse_left); + + GetMousePos(X, Y); + If IntInBox(X, Y, IntToBox(236, 308, 462, 587)) Then + if (CountColor(ClWhite, 201, 295, 226, 308) > 5) then //clicks the correct one + begin + MouseBox(201, 295, 226, 308, mouse_left); + Wait(900 + Random(100)); + end; + + If Not IntInBox(X, Y, IntToBox(236, 308, 462, 587)) Then + if (CountColor(ClWhite, TB.X1, TB.Y1 + 20, TB.X2, TB.Y2 + 15) > 5) then //clicks the correct one + begin + MouseBox(TB.X1, TB.Y1 + 20, TB.X2 - 15, TB.Y2 + 15, mouse_left); + Wait(900 + Random(100)); + end; + + end; + end; + CloseWindow; + CloseWindow; +end; + +(* +SetGraphics +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SetGraphics(Brightness: Integer; vl, rr, gd, td, id, fe, gt, cs: string); + +Sets graphic options through the Graphics Screen in GameTab 11. +Use: Enter the desired Setting for the desired Option. Leave as '' for no change + + +Parameter Option Setting +vl Visible Levels Current / All +rr Remove Roofs Always / Selectively +gd Ground Decoration Off / On +td Texture Detail Low / High +ia Idle Animations Few / Many +fe Flickering Effects Off / On +gt Ground Textures Few / Many +cs Character Shadows Off / On + +| 1 2 3 4 +| Brightness: <---o---o---o---o---> + +EG. SetGraphics(2, 'current', '', 'off', 'low', 'few', '', 'few', 'off'); +For Autoing: SetGraphics(4, 'current', 'always', 'off', 'low', 'few', 'off', 'few', 'off'); +OutDated since 02 Sep 09 + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + +*) +procedure SetGraphics(Brightness: Integer; vl, rr, gd, td, ia, fe, gt, cs: string); +var + Settings, PosSettings, OptionName, tArr: TStringArray; + TB: TBox; + II, Tx, Ty, Col, Where: Integer; + P: TPoint; +begin + if (not LoggedIn) then exit; + CloseWindow; + + if (not FindColor(Tx, Ty, 0, 7, 460, 69, 474)) then + if (not ClickContinue(True, True)) then + Mouse(MMCX, MMCY, 2, 2, mouse_left); + + II := 0; + while (not FindTextTPA(2070753, 0, MSX1, MSY1, MSX2, MSY2, 'Graphics Options', UpCharsEx, Nothing)) and (LoggedIn) do + begin + GameTab(tab_Options); + MouseBox(605, 258, 623, 277, mouse_left); + Wait(500 + Random(200)); + Inc(II); + if (II > 3) then + begin + srl_Warn('SetGraphics', 'Could not open Graphics Options screen', warn_Warning); + CloseWindow; + Exit; + end; + end; + + if (not InRange(Brightness, 0, 4)) then + srl_Warn('Login_SetGraphics', 'Brightness must be between 0 and 4', warn_AllVersions) + else + if (Brightness <> 0) then + begin + P := Point(140 + ((Brightness - 1) * 31), 185); + if (GetColor(P.x, P.y) = srl_outline_black) then + Mouse(P.x - 2, P.y - 2, 5, 5, mouse_left); + end; + + PosSettings := ['Current', 'All', 'Always', 'Selectively', 'Off', 'On', 'Low', + 'High', 'Few', 'Many', 'Off', 'On', 'Few', 'Many', 'Off', 'On']; + OptionName := ['Visible Levels', 'Remove Roofs', 'Ground Decoration', 'Texture Detail', + 'Idle Animations', 'Flickering Effects', 'Ground Textures', 'Character Shadows']; + Settings := [vl, rr, gd, td, ia, fe, gt, cs]; + + for II := 0 to High(Settings) do + begin + if (Settings[II] = '') then Continue; + + TB.x1 := 149 + ((II + 1) div 7) * 239; + TB.y1 := 173 + ((II + 1) mod 7) * 17; + TB.x2 := TB.x1 + 104; + TB.y2 := TB.y1 + 14; + + tArr := [PosSettings[II * 2], PosSettings[II * 2 + 1]]; + if (not(InStrArrEx(Capitalize(Settings[II]), tArr, Where))) then + begin + srl_Warn('SetGraphics', 'Setting: ' + Settings[II] + ' is not valid for Option: ' + OptionName[II], warn_AllVersions); + Continue; + end; + + Col := Where * 16777008 + 207; + if (FindColor(Tx, Ty, Col, TB.x1, TB.y1, TB.x2, TB.y2)) then Continue; + + Mouse(TB.x1 + 10, TB.y1 + 3, 10, 5, mouse_left); + Wait(50 + Random(100)); + + if (FindColor(Tx, Ty, Col , TB.x1, TB.y2 + 1, TB.x2, TB.y2 + 1 + 51)) then + begin + Mouse(Tx, Ty, 10, 5, mouse_left); + Wait(50 + Random(100)); + while (CountColor(16777215, 5, 5, 161, 35) > 100) do Wait(100 + Random(50)); + end else + Mouse(TB.x1 + 10, TB.y1 + 3, 10, 5, mouse_left); + end; + + Wait(500 + Random(500)); + CloseWindow; +end; + +(* +SetAudio +~~~~~~~~ + +.. code-block:: pascal + + procedure SetAudio(Volume, SFX, Area: Integer; SMSetting: (Stereo, Mono, NoChange) ); + +Sets audio options through the Audio screen in GameTab 11 +Use: Enter the desired Setting AS A POINT for the desired Option. Make option 0 +for no change. + +| 1 2 3 4 5 +| Volume, SFX, Area: <--o---o---o---o---o--> + +EG. SetAudio(1, 4, 0, Stereo); + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + +*) +procedure SetAudio(Volume, SFX, Area: Integer; SMSetting: TSMSetting); +var + Settings: TIntegerArray; + OptionName: TStringArray; + II, C, Tx, Ty: Integer; + P: TPoint; +begin + if (not LoggedIn) then exit; + + Settings := [Volume, SFX, Area]; + OptionName := ['Volume', 'SFX', 'Area']; + + C := 0; + CloseWindow; + if (not FindColor(Tx, Ty, 0, 7, 460, 69, 474)) then + if (not ClickContinue(True, True)) then + Mouse(MMCX, MMCY, 2, 2, mouse_left); + + while (not FindTextTPA(2070753, 0, MSX1, MSY1, MSX2, MSY2, 'Audio Options', UpCharsEx, Nothing)) and (LoggedIn) do + begin + GameTab(tab_Options); + MouseBox(654, 252, 677, 278, mouse_left); + Wait(500 + Random(200)); + Inc(C); + if (C > 3) then + begin + srl_Warn('SetAudio', 'Could not open Audio Options screen', warn_Warning); + CloseWindow; + Exit; + end; + end; + + for II := 0 to 2 do + begin + + if (not InRange(Settings[II], 0, 5)) then + begin + srl_Warn('SetAudio', IntToStr(Settings[II]) + ' is not a valid setting ' + + 'for: ' + OptionName[II] + '. Must be between 0 and 5', warn_AllVersions); + Continue; + end; + + if (Settings[II] = 0) then Continue; + + P.x := Round(201.0 + 25.5 * (Settings[II] - 1)); + P.y := Round(1.5 * II * II + 54.5 * II + 118.0); + if (GetColor(P.x, P.y) <> 16777215) then + Mouse(P.x - 6, P.y, 0, 5, mouse_left); + + Wait(10 + Random(10)); + end; + + if (GetColor(238, 268) = 181) and (SMSetting = Stereo) then + Mouse(302, 265, 7, 7, mouse_left) + else + if (GetColor(305, 268) = 181) and (SMSetting = Mono) then + Mouse(235, 265, 7, 7, mouse_left); + + Wait(500 + Random(500)); + CloseWindow; +end; + +(* +SetBar +~~~~~~ + +.. code-block:: pascal + + procedure SetBar(Brightness, Volume, SFX, Area: Integer); + +Sets each bar to the specific point. 1-4 for Brightness, 1-5 for +others. For no change in the value make the respective parameter 0. + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + +*) +procedure SetBar(Brightness, Volume, SFX, Area: Integer); +var + Settings: TIntegerArray; + Names: TStringArray; + II, K: Integer; +begin + Settings := [Brightness, Volume, SFX, Area]; + Names := ['Brightness', 'Volume', 'SFX', 'Area']; + for II := 0 to 3 do + begin + K := 5 - Integer(II = 0); + if (not InRange(Settings[II], 0, K)) then + begin + srl_Warn('SetBar', 'Setting: ' + IntToStr(Settings[II]) + ' is not valid for Bar: ' + Names[II] + '.', warn_AllVersions); + Settings[II] := 0; + end; + end; + SetGraphics(Settings[0], '', '', '', '', '', '', '', ''); + Wait(100 + Random(500)); + SetAudio(Settings[1], Settings[2], Settings[3], NoChange); +end; + +(* + +Gametab 12 +---------- + +Gametab 12 related functions + +*) + +(* +DoEmote +~~~~~~~ + +.. code-block:: pascal + + procedure DoEmote(EmoteNumber: Integer); + +Clicks on an emote specified by EmoteNumber (1 to 37) + +.. note:: + + by NaumanAkhlaQ + +Example: + +.. code-block:: pascal + +*) +procedure DoEmote(EmoteNumber: Integer); +var + I, X, Y, Row, Col: Integer; + +begin + if (not InRange(EmoteNumber, 1, 51)) then + begin + srl_Warn('DoEmote', 'Invalid EmoteNumber: ' + IntToStr(EmoteNumber) + ', Valid Emotes: 1..46', warn_AllVersions); + Exit; + end; + + if (GetCurrentTab <> tab_Emotes) then + begin + if (not GameTab(tab_Emotes)) then exit; + Wait(500 + Random(750)); + end; + + case EmoteNumber of + 01..20: if (GetColor(723, 226) = 2041131) then + Mouse(723, 226, 8, 4, mouse_left); + 21..40: if (GetColor(727, 364) = 1909544) then + Mouse(727, 354, 4, 1, mouse_left); + 41..51: if (GetColor(725, 438) = 1909544) then + Mouse(725, 438, 5, 5, mouse_left); + end; + Wait(300 + Random(200)); + if InRange(EmoteNumber, 21, 40) then + I := 20 + else + if InRange(EmoteNumber, 41, 51) then I := 28; + DecEx(EmoteNumber, I); + + Row := Trunc(EmoteNumber / 4) + 1; + if ((EmoteNumber mod 4) = 0) then Dec(Row); + Col := (EmoteNumber mod 4); + if (Col = 0) then Col := 4; + + X := 550 + (44 * (Col - 1)); + Y := 219 + (49 * (Row - 1)); + Mouse(X, Y, 26, 39, mouse_left); +end; + +(* +GetLobbyTab +~~~~~~~~~~~ + +.. code-block:: pascal + + function GetLobbyTab: Integer; + +Gets current lobby tab. + +.. note:: + + by Bionicle1800, NCDS + +Example: + +.. code-block:: pascal + +*) +function GetLobbyTab: Integer; +begin + for result := 1 to 6 do + if GetColor(63 + (result-1)*102, 32) = 11582147 then //Midpoint of the left boundary of the tab + Exit; + Result := -1; +end; + +(* +LobbyTab +~~~~~~~~ + +.. code-block:: pascal + + function LobbyTab(Tab: Integer): Boolean; + +Goes to the lobby tab specified by the integer 'Tab'. +Valid arguments are 1 through 5, as well as PlayerInfo, +WorldSelect, FriendsList, ClanChat and Options. + +.. note:: + + by Bionicle1800 + +Example: + +.. code-block:: pascal + +*) +function LobbyTab(Tab: Integer): Boolean; +begin + Result := false; + if not InRange(Tab, L_PlayerInfo, L_Options) then + begin + Srl_Warn('LobbyTab', 'Tab ' + IntToStr(Tab) + ' is not valid.', warn_AllVersions); + Exit; + end; + result := GetLobbyTab = Tab; + if result then + Exit; + if GetColor(63 + (Tab-1)*102, 32) = 8095117 then //Midpoint of the left boundary of the tab; this is the resultant color when the tab is active + begin + Mouse(63 + (Tab-1)*102, 32, 10, 6, mouse_left); + result := true; + end; +end; + +(* + +XP Counter +---------- + +XP Counter related functions + +*) + + (* +ToggleXPPopUp +~~~~~~~~~~~~~ + +.. code-block:: pascal + + Function ToggleXPPopUp(Disabled: Boolean): Boolean; + +Toggles the XP Pop-up to on/off that shows up on main screen. +This uses the chat messages to determine if its off or on. + ToggleXPPopUp(True) turns it off and returns True if successful + ToggleXPPopUp(False) turns it on and returns True if successful + +.. note:: + + by Narcle + +*) +Function ToggleXPPopUp(Disabled: Boolean): Boolean; +var + i: Integer; + TPA: TPointArray; + P: TPoint; + S: String; +begin + for i := 0 to 1 do + begin + TPA := TPAFromBox(IntToBox(521, 51, 546, 75)); + FilterPointsPie(TPA, 0, 360, 0, 12, 534, 63); + P := TPA[Random(Length(TPA))]; + Mouse(P.X, P.Y, 0, 0, mouse_right); + if WaitOptionMulti(['Pop', 'op', '-up'], 1000) then + begin + Wait(1500+Random(500)); + S := GetBlackChatMessage; + if Pos('disabled', S) > 0 then + Result := Disabled; + if Pos('enabled', S) > 0 then + Result := not Disabled; + if Result then + Break; + end; + end; + Writeln(S); +end; + +(* +ISXPBarOpenEx +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function IsXPBarOpen(CounterNum: integer): Boolean; + +Results True if the XP Bar is showing. Counter number 1 to 3 + +.. note:: + + by Narcle & IceFire908 + +*) + + +function IsXPBarOpenEx(CounterNum: integer): Boolean; +begin + Result := CountColor(14474460, 481, 10+(CounterNum-1)*22, 489, 22+(CounterNum-1)*22) > 6; +end; + + +(* +ISXPBarOpen +~~~~~~~~~~~ + +.. code-block:: pascal + + function IsXPBarOpen: Boolean; + +Results True if the XP Bar is showing. +Added for compatability + +.. note:: + + by Narcle & IceFire908 + +*) +function IsXPBarOpen: Boolean; +begin + Result := IsXPBarOpenEx(1); +end; + +(* +ToggleXPBarEx +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ToggleXPBarEx(Open: Boolean; CounterNum: integer): Boolean; + +Opens or closes the XP Bar, true if had to toggle. +Counter number 1 to 3 + +.. note:: + by Narcle & IceFire908 + +*) + +function ToggleXPBarEx(Open: Boolean; CounterNum: integer): Boolean; +var + TPA: TPointArray; + P: TPoint; + T: Integer; +begin + if Open xor IsXPBarOpenEx(CounterNum) then + begin + TPA := TPAFromBox(IntToBox(521, 51, 546, 75)); + FilterPointsPie(TPA, 0, 360, 0, 12, 534, 63); + P := TPA[Random(Length(TPA))]; + Mouse(P.X, P.Y, 0, 0, mouse_left); + T := GetSystemTime + 300; + repeat + wait(1); + Result := Open = IsXPBarOpenEx(CounterNum); + until Result or (GetSystemTime > t); + end else + Result := true; +end; + +(* +ToggleXPBar +~~~~~~~~~~~ + +.. code-block:: pascal + + function ToggleXPBar(Open: Boolean): Boolean; + +Opens or closes the XP Bar, true if had to toggle. + +.. note:: + by Narcle & IceFire908 + +*) +function ToggleXPBar(Open: Boolean): Boolean; +begin + Result := ToggleXPBarEx(Open, 1); +end; + +(* +GetXPBar +~~~~~~~~ + +.. code-block:: pascal + + function GetXPBar(CounterNum: integer): LongInt; + +Returns the number from your XP Bar. +Counter number 1 to 3 + +.. note:: + + by Narcle & IceFire908 edited by Ashaman88 +*) +Function GetXPBar(CounterNum: integer): LongInt; +var + TPA: TPointArray; + B: TBox; + S: String; + P: integer; +begin + Result:=-1; + if ToggleXPBarEx(true, CounterNum) then + begin + FindColorsTolerance(TPA, 14474460, 407, 10+(CounterNum-1)*22, 489, 24+(CounterNum-1)*22, 0); + B := GetTPABounds(TPA); + S := Replace(GetTextAtExWrap(B.x1, B.y1, B.x2, B.y2, 0, 1, 4, 14474460, 0, UpChars), ' ', ''); + P := Pos('x', S); + if P > 0 then + Result := StrToIntDef(ExtractFromStr(Copy(s, P, Length(S)), Numbers), 0) + else + Result := StrToIntDef(ExtractFromStr(S, Numbers), 0); + end; +end; + +(* +GetXPBarTotal +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetXPBarTotal: LongInt; + +Returns the number from your XP Bar. + +.. note:: + + by Narcle & IceFire908 +*) + +function GetXPBarTotal: LongInt; +begin + Result := GetXPBar(1); +end; + +(* +ResetXPTotal +~~~~~~~~~~~~ + +.. code-block:: pascal + + function ResetXPTotal: Boolean; + +Resets the XP Bar. + +.. note :: + + by Narcle & IceFire908 + +*) +function ResetXPTotal: Boolean; +var + TPA: TPointArray; + P: TPoint; +begin + TPA := TPAFromBox(IntToBox(521, 51, 546, 75)); + FilterPointsPie(TPA, 0, 360, 0, 12, 534, 63); + P := TPA[Random(Length(TPA))]; + Mouse(P.X, P.Y, 0, 0, mouse_right); + Result := WaitOptionMulti(['Res', 'ese', 'set'], 1000); +end; + + +(* + +MoneyPouch Tab +-------------- + +Money Pouch related functions + +*) + +(* +IsMoneyPouchOpen +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function IsMoneyPouchOpen: Boolean; + +Checks if money pouch is open. + +.. note :: + + by Home + +*) +function IsMoneyPouchOpen: Boolean; +var + Cols :TIntegerArray; + I :Integer; +begin + Cols := [65535, 16777215, 8453888]; + for I := 0 to 2 do + If CountColor(Cols[I],450, 90, 510, 109) > 10 then + Result := CountColor(Cols[I],450, 90, 510, 109) > 10; +end; + +(* +ToggleMoneyPouch +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + ToggleMoneyPouch(Open: Boolean): Boolean; + +Opens the money pouch if closed. + +.. note :: + + by Home + +*) +function ToggleMoneyPouch(Open: Boolean): Boolean; +begin + Result := IsMoneyPouchOpen <> Open; + if (not (Result)) then + Exit; + MouseBox(528, 94, 533, 107, mouse_Left); +end; + +(* +GetMoneyPouchAmount +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetMoneyPouchAmount: LongInt; + +Returns amount of coins in pouch. + +.. note :: + + by Home & Richard + +Example: + +.. code-block:: pascal + + amt := GetMoneyPouchAmount(); + +*) +function GetMoneyPouchAmount: Integer; +var + Previous: Boolean; + TPA: TPointArray; + B: TBox; + I :Integer; + Col :TIntegerArray; + Money :String; +begin + Previous := IsMoneyPouchOpen; + if (ToggleMoneyPouch(True)) then + WaitFunc(@IsMoneyPouchOpen, 10, 2750); + Col := [65535, 65278, 16777215, 8453888]; + for I := 0 to 3 do + if (FindColors(TPA, Col[I], 450, 90, 510, 109)) then + begin + B := GetTPABounds(TPA); + B := IntToBox(B.X1 - 2, B.Y1 - 2, B.X2 + 2, B.Y2 + 2); + Money := (GetTextAtEx(B.X1 - 1, B.Y1 - 1, 0, StatChars, False, False, 0, 2, Col[I], 5, False, tr_AllChars)); + Result := StrToIntDef(GetNumbers(Money), -1); + If Pos('K', Money) > 0 then + Result := Result * 1000; + If Pos('M', Money) > 0 then + Result := Result * 1000000; + break; + end; + if (not(Previous)) then + begin + Wait(RandomRange(500, 1500)); + ToggleMoneyPouch(Previous); + end; +end; + +(* +DepositToPouch +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function DepositToPouch :Boolean; + +Deposit's coins to pouch. + +.. note :: + + by Home + +*) +function DepositToPouch :Boolean; +var + MoneyPoint :TPoint; +begin + Result := False; + If FindCoins(MoneyPoint.X, MoneyPoint.Y, 'Inv') then + begin + MMouse(MoneyPoint.X, MoneyPoint.Y, 3, 3); + If WaitUpText('Coins', 500) then + begin + Mouse(MoneyPoint.X, MoneyPoint.Y, 0, 0, False); + Result := WaitOption('Add', 500); + end; + end; +end; + +(* +toolBeltScreen +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function toolBeltScreen : Boolean; + +Returns True if the Tool Belt screen is open + +.. note:: + + by Kyle Undefined + +Example: + +.. code-block:: pascal + +*) +function ToolBeltScreen() : Boolean; +begin + Result := (CountColorTolerance(1158880, 192, 18, 264, 33, 9) > 120); +end; + +(* +itemSlotFilled +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function itemSlotFilled : Boolean; + +Returns True if the current tool slot is filled + +.. note:: + + by Kyle Undefined + +Example: + +.. code-block:: pascal + +*) +function ItemSlotFilled() : Boolean; +var + TPA : TPointArray; + tmpCTS : Integer; +begin + tmpCTS := GetColorToleranceSpeed; + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(1.86, 0.06); + + FindColorsSpiralTolerance(MSCX, MSCY, TPA, 5855064, 211, 199, 298, 273, 9); + + ColorToleranceSpeed(tmpCTS); + SetColorSpeed2Modifiers(0.2, 0.2); + + Result := Length(TPA) > 0; +end; + +(* +openToolBelt +~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure toolBeltScreen; + +Opens the Tool Belt + +.. note:: + + by Kyle Undefined, edited by riwu. + +Example: + +.. code-block:: pascal + +*) +procedure OpenToolBelt(); +begin + GameTab(tab_Equip); + MouseBox(644, 416, 682, 450, mouse_Left); + Wait(RandomRange(250, 750)); +end; + +(* +setCategory +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure setCategory(Category : string); + +Sets the category of items to be shown + +.. note:: + + by Kyle Undefined + +Example: + +.. code-block:: pascal + +*) +procedure SetCategory(Category : string); +var + catBox : TBox; + TPA : TPointArray; + tmpCTS : Integer; +begin + case(LowerCase(Category))of + 'general' : catBox := IntToBox(161, 86, 188, 107); + 'fishing' : catBox := IntToBox(219, 86, 246, 104); + 'crafting' : catBox := IntToBox(275, 87, 305, 104); + 'farming' : catBox := IntToBox(332, 88, 359, 105); + end; + + tmpCTS := GetColorToleranceSpeed; + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(0.34, 0.80); + + FindColorsSpiralTolerance(MSCX, MSCY, TPA, 1810641, catBox.X1, catBox.Y1, catBox.X2, catBox.Y2, 9); + + ColorToleranceSpeed(tmpCTS); + SetColorSpeed2Modifiers(0.2, 0.2); + + if(not(Length(TPA) > 0))then + MouseBox(catBox.X1, catBox.Y1, catBox.X2, catBox.Y2, 1); +end; + +(* +checkToolBeltFor +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function checkToolBeltFor(Category, Tool : string) : Boolean; + +Returns True if the tool is in Tool Belt for the appropriate category + +.. note:: + + by Kyle Undefined + +Example: + +.. code-block:: pascal + +*) +function CheckToolBeltFor(Category, Tool : string) : Boolean; +var + I, catCount : Integer; +begin + if(not(toolBeltScreen()))then + openToolBelt(); + setCategory(Category); + + case(LowerCase(Category))of + 'general', 'crafting' : catCount := 13; + 'fishing' : catCount := 8; + 'farming' : catCount := 5; + end; + + for I := 1 to catCount do + begin + if(not(FindTextTpa(1158880, 9, 167, 146, 352, 161, Tool, SmallChars, Nothing)))then + begin + Mouse((375 + 397) div 2, (147 + 163) div 2, 1, 1, True); + Wait(RandomRange(250, 750)) + end else + Break; + end; + + Result := itemSlotFilled; + + Wait(RandomRange(250, 750)); + MouseBox(479, 20, 491, 29, mouse_Left); +end; + +(* +GetMusic +~~~~~~~~ + +.. code-block:: pascal + + function GetMusic: string; + +Gets the music that's currently playing. + +.. note:: + + by Nielsie95 and ZephyrsFury + +Example: + +.. code-block:: pascal + +*) +function GetMusic: string; +var + Pts: TPointArray; + B: TBox; +begin + if (GetCurrentTab <> tab_Music) then + begin + GameTab(tab_Music); + Wait(500 + Random(500)); + end; + if (FindColorsTolerance(Pts, 39401, 553, 242, 729, 264, 0)) then + begin + B := GetTPABounds(Pts); + Result := Trim(GetTextAtEx(B.X1 - 1, 245, 0, UpCharsEx, False, False, 0, 1, 39401, 50, False, tr_AllChars)); + end; +end; + +(* +CloseAllScreens +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function CloseAllScreens: boolean; + +Close BankScreen, DepositScreen, ShopScreen, ToolBeltScreen and the PinScreen. +Returns true if any of them is closed. + +.. note:: + + by Tickyy + +Example: + +.. code-block:: pascal + + CloseAllScreens(); + +*) +function PinScreen: boolean; forward; +function CloseAllScreens: boolean; +var + I: Integer; +begin + for I := 0 to 4 do + begin + case I of + 0: Result := BankScreen; + 1: Result := DepositScreen; + 2: Result := ShopScreen; + 3: Result := ToolBeltScreen; + 4: Result := PinScreen; + end; + + if Result then + if CloseWindow then + begin + Result := true; + Exit; + end else + Result := false; + end; +end; diff --git a/SRL/core/globals.simba b/SRL/core/globals.simba new file mode 100644 index 0000000..c4e763b --- /dev/null +++ b/SRL/core/globals.simba @@ -0,0 +1,851 @@ +(* +Globals +======= + + +.. contents:: + +*) + + +(* +SRL_NAVBAR_CONSTANTS +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SRL_NAVBAR_CONSTANTS; + + Navigation Bar Offsets at the top from the top of the client. (The Home, Support, Forums, Subscribe bar) + For Use With IgnoreBar or Any Bar Removal Functions. + +.. note:: + + by Brandon, Coh3n, Wizzup + +Example: + +.. code-block:: pascal + +*) +const + SRL_NAVBAR_LOGIN_X = 0; + SRL_NAVBAR_LOGIN_Y = 22; + SRL_NAVBAR_INGAME_X = 0; + SRL_NAVBAR_INGAME_Y = 50; + + + +type + TBooleanArray = array of Boolean; + +// used so ExitSquealOfFortune is only called once per login +var + SRL_ExitedSquealOfFortune: boolean; + +{ const SRLVersionNumber; + Description: Repository Version Number. } +const + SRLVersionNumber = 38; + +{ var TalkAfterRandoms: Boolean; + Description: Talk random phrases after randoms are detected/solved. } +var + TalkAfterRandoms: Boolean; + +{ var WorldSwitcherEnabled: Boolean; + Description: Enables world switching. } + +var + WorldSwitcherEnabled: Boolean; + +{ var FriendChars, LoginChars: Integer; + Description: Fonts used internally and for use in scripts. } +{$IFDEF LoadExtraFonts} +var + FriendChars, LoginChars: Integer; +{$ENDIF} + +{ var bmpAdmin, bmpMod, Lamp, BoxMask: Integer; + Description: Global Bitmaps. Need to be Global because of SCAR Memory leaks. } +var + bmpAdmin, bmpMod, bmpFlag, Lamp, BookOfKnowledge, SRL_NAVBAR_BITMAP, SRL_OPTIONS_BITMAP : Integer; //NavBar Added: Brandon. + +{ var RoadColor, WaterColor, BankColor: Integer; + Description: Three variables you will almost always use. :) } +var + RoadColor, WaterColor, BankColor: Integer; + +{ var LampSkill: String; + Description: Set Lamp skill. } +var + LampSkill: string; // no longer used + +var + SRL_DisableIPLog: boolean; + +{ const srl_outline_black + Description: Black Color outline} +const + srl_outline_black = 131072; + srl_outline_white = clWhite; + +{ const MMX1, MMY1, MMX2, MMY2; + Description: MiniMap Edge Points. } +const + MMX1 = 550; + MMY1 = 8; + MMX2 = 703; + MMY2 = 161; + +{ const MMCX, MMCY; + Description: MiniMap Centre Point. } +const + MMCX = 627; + MMCY = 85; + +{ const MSX1, MSY1, MSX2, MSY2; + Description: Main Screen EdgePoints. } +const + MSX1 = 4; + MSY1 = 4; + MSX2 = 515; + MSY2 = 337; + +{ const MSCX, MSCY; + Description: Main Screen Centre Points. } +const + MSCX = 259; + MSCY = 170; + +{ const MIX1, MIY1, MIX2, MIY2; + Description: Inventory EdgePoints. } +const + MIX1 = 547; + MIY1 = 202; + MIX2 = 737; + MIY2 = 466; + +{ const MICX, MICY; + Description: Inventory Centre Points. } +const + MICX = 642; + MICY = 334; + +{ const MCX1, MCY1, MCX2, MCY2; + Description: Chat Screen EdgePoints. } +const + MCX1 = 4; + MCY1 = 342; + MCX2 = 514; + MCY2 = 475; + +{ const MCCX, MCCY; + Description: Chat Screen Centre Points. } +const + MCCX = 250; + MCCY = 401; + +{ const MBX1, MBY1, MBX2, MBY2; + Description: BankScreen EdgePoints (where you click the items, does not include tabs). } +const + MBX1 = 26; + MBY1 = 84; + MBX2 = 480; + MBY2 = 292; + +{ const DBX1, DBY1, DBX2, DBY2; + Description: Deposit box edgepoints (only where the item appear) } +const + DBX1 = 91; + DBY1 = 57; + DBX2 = 443; + DBY2 = 262; + +{ const SRL_Procs Constants; + Description: Constants for SRL_Procs. } +const + srl_AntiBan = 0; // Your AntiBan procedure to be called during various SRL functions and procedures. (Flag, FFlag) + srl_OnFindMod = 1; // After a player or Jagex mod is detected talking in the chat box. + srl_OnFindDead = 2; // After the text 'Oh dear you are dead' is detected. + srl_OnFindFight = 3; // After detecting a fighting random. + srl_OnFindTrade = 4; // After the trade has been attempted (either success or failure). + srl_OnNextPlayer = 5; // While the players are logged out and before CurrentPlayer changes. + srl_OnSendStats = 6; // After SRL Script Stats are sent to the server. + srl_OnRandomCall = 7; // Called in FindNormalRandoms, FindInventoryRandoms, FindNonInventoryRandoms. (NOT ONLY WHEN RANDOMS ARE DETECTED). + srl_OnFindRandom = 8; // After a random event is detected. (FNR, FIR, FNIR, FT) + srl_OnLogOut = 9; // Just before the player is logged out. + srl_InNextPlayerLoop = 10; // During the infinite loop in NextPlayer when all players are inactive. + srl_OnCustomRC = 11; // When custom RC trigger has been given. + srl_OnExitToLobby = 12; // On exit to lobby + srl_OnLogIn = 13; // Right after player has successfully logged in. + srl_OnRSUpdate = 14; // Called in LoginPlayerToLob if RuneScape updates. + +{ var SRL_Procs: array [0..14] of procedure(); + Description: Varibles to store user-defined procs to be called in SRL. } +var + SRL_Procs: array [0..14] of procedure(); + SRL_OnFindRandomCall : function(var Cont : boolean) : boolean; // no longer used + +{ const Ability Constants; + Description: Constants representing sub-tabs and abilities in the ability book, + sorted by order of appearance.} +const + + //Sub-tabs + AB_ATTACK = 0; + AB_STRENGTH = 1; + AB_RANGED = 2; + AB_ABILITIES = 3; + AB_COMBAT_SPELLS = 4; + AB_TELEPORT_SPELLS = 5; + AB_SKILLING_SPELLS = 6; + AB_DEFENCE = 7; + AB_DEFENSE = 7; + AB_CONSTITUTION = 8; + + //Attack + AB_SLICE = 13; + AB_SLAUGHTER = 14; + AB_OVERPOWER = 15; + AB_HAVOC = 16; + AB_BACKHAND = 17; + AB_SMASH = 18; + AB_BARGE = 19; + AB_FLURRY = 20; + AB_SEVER = 21; + AB_HURRICANE = 22; + AB_MASSACRE = 23; + AB_METEOR_STRIKE = 24; + + //Strength + AB_KICK = 25; + AB_PUNISH = 26; + AB_DISMEMBER = 27; + AB_FURY = 28; + AB_DESTROY = 29; + AB_QUAKE = 30; + AB_BERSERK = 31; + AB_CLEAVE = 32; + AB_ASSAULT = 33; + AB_DECIMATE = 34; + AB_PULVERISE = 35; + AB_FRENZY = 36; + + //Ranged + AB_PIERCING_SHOT = 37; + AB_SNAP_SHOT = 38; + AB_DEADSHOT = 39; + AB_SNIPE = 40; + AB_BINDING_SHOT = 41; + AB_FRAGMENTATION_SHOT = 42; + AB_ESCAPE = 43; + AB_RAPID_FIRE = 44; + AB_RICOCHET = 45; + AB_BOMBARDMENT = 46; + AB_INCENDIARY_SHOT = 47; + AB_UNLOAD = 48; + + //Magic + AB_WRACK = 49; + AB_ASPHYXIATE = 50; + AB_OMNIPOWER = 51; + AB_DRAGON_BREATH = 52; + AB_IMPACT = 53; + AB_COMBUST = 54; + AB_SURGE = 55; + AB_DETONATE = 56; + AB_CHAIN = 57; + AB_WILD_MAGIC = 58; + AB_METAMORPHOSIS = 59; + AB_TSUNAMI = 60; + + //Defence + AB_ANTICIPATION = 61; + AB_BASH = 62; + AB_REVENGE = 63; + AB_PROVOKE = 64; + AB_IMMORTALITY = 65; + AB_FREEDOM = 66; + AB_REFLECT = 67; + AB_RESONANCE = 68; + AB_REJUVENATE = 69; + AB_DEBILITATE = 70; + AB_PREPARATION = 71; + AB_BARRICADE = 72; + + //Constitution + AB_REGENERATE = 73; + AB_MOMENTUM = 74; + AB_INCITE = 75; + AB_SINGLE_WAY_WILDERNESS = 76; + +{ const GameTab Constants; + Description: Constants representing gametab numbers. } +const + tab_Combat = 21; + tab_Diary = 22; + tab_Task = 22; + tab_Stats = 23; + tab_Quest = 24; + tab_Inv = 25; + tab_Equip = 26; + tab_Prayer = 27; + tab_Magic = 28; + tab_Objectives = 29; + tab_Friends = 30; + tab_Ignore = 30; + tab_FriendChat = 31; + tab_Clan = 32; + tab_Options = 33; + tab_Emotes = 34; + tab_Music = 35; + tab_Notes = 36; + tab_LogOut = 37; + +{ const Antirandoms Constants; + Description: Constants representing randoms index. } +const + rand_Count = 25; + + rand_Leo = 0; + rand_Forester = 1; + rand_Maze = 2; + rand_PrisonPete = 3; + rand_ScapeRune = 4; + rand_Demon = 5; + rand_Quiz = 6; + rand_Mordaut = 7; + rand_Molly = 8; + rand_Pinball = 9; + rand_Sandwich = 10; + rand_BeeKeeper = 11; + rand_Pillory = 12; + rand_CapnArnav = 13; + rand_Abyss = 14; + rand_Certer = 15; + rand_Mime = 16; + rand_Frog = 17; + + rand_Trade = 18; + rand_Mod = 19; + rand_Fight = 20; + rand_Lamp = 21; + rand_BirdNest = 22; + rand_Death = 23; + rand_RewardBox = 24; + +var + tmp_RandSolved: array[0..rand_Count-1] of Integer; + tmp_RandFailed: array[0..rand_Count-1] of integer; + +{ type TAutoColorInfo; + Description: Set of information that can be used in some functions. } +type + TAutoColorInfo = record + Name: string; + Color: Integer; + ColorArray: TIntegerArray; + MinCount: Integer; + MaxCount: Integer; + MaxDist: Integer; + MaxDistCenter: Integer; + UpText: string; + UpTextMulti: TStringArray; + HueMod, SatMod: Extended; + LumTol: Integer; + MinR, MaxR, MinG, MaxG, MinB, MaxB: Integer; + MinX, MaxX, MinY, MaxY, MinZ, MaxZ: Extended; +end; + +{ type fnct_ActionOptions; + Description: Action options. } +type + fnct_ActionOptions = (ClickRight,ClickLeft,ClickMiddle,Move,Nothing); + +var +{ var ACArr + Description: Stores the information needed for the autocolour functions } + acArr: array of TAutoColorInfo; + +{ var isACLoaded + Description: Boolean array to make sure that all TAutoColorInfos are loaded + prior to calling. Optimizes AutoColors significantly } + isACLoaded: array of Boolean; + +{ vars For Smart} +{$IFDEF SMART} +var + {$IFDEF SIMBAMAJOR980} + Smart_Server: Integer; + Smart_Members, Smart_Signed, Smart_SuperDetail: Boolean; + {$ELSE} + Smart_ForceNew: Boolean; + Smart_FixSpeed: Boolean; + SRL_SixHourFix: Boolean; + Smart_CurrentClient: Integer; + {$ENDIF} +{$ENDIF} + +{ var WarnSensitivity: Integer + Description: var for srl_Warn. } +var + WarnSensitivity: Integer; //-2 will show Warnings and above, -3 notices too. + +{ const srl_Warn Constants; + Description: Constants for srl_Warn. } +const + warn_AllVersions = 0; + warn_Terminate = -1; + warn_Warning = -2; + warn_Notice = -3; + warn_Debug = -4; + +{var SRLBitmapsLoaded : boolean; + Description: True if SRL bmps/DTMs are loaded} +var + SRLBitmapsLoaded : boolean; + +//****************************************************************************// +// * I tried to make these Bitmaps Local, but I got after a couple of hours +// * running scripts, CTB and DB handle errors. So sorry, declared them global +//****************************************************************************// + +(* +SRL_HasProc +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SRL_HasProc; + +Checks if userproc is defined at index. + +.. note:: + + by SRL Dev Team + +Example: + +.. code-block:: pascal + +*) +function SRL_HasProc(Index: Integer): Boolean; +begin + if (Index >= Low(SRL_Procs)) and (Index <= High(SRL_Procs)) then + Result := {$IFDEF LAPE}@{$ENDIF}SRL_Procs[Index] <> nil; +end; + +(* +LoadSRLBitmaps +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure LoadSRLBitMaps; + +Loads SRL Bitmaps into memory. + +.. note:: + + by SRL Dev Team + +Example: + +.. code-block:: pascal + +*) +procedure LoadSRLBitMaps; +begin + bmpMod := BitmapFromString(9, 6, 'beNqbPn0RWeDBgwdAkgEMkBnT' + + 'p0+HS6GR+KVwAgAGXFQr'); + bmpAdmin := BitmapFromString(9, 6, 'beNqbp/j9PwcZ6P//FiDJAA' + + 'bIjGvzFOFSaCR+KZwIALniVEk='); + bmpFlag := BitmapFromString(8, 15, 'meJxjYEAHIpr/F8yYgSkozPfE3ty' + + 'cGHGgIKY4RBBNHC6ILI4sAkYngOIwNhQJ8bUBBYEIyEBGQO37tm3D' + + 'dCcdxIGBhlUcCBgZGAA27Tt3'); + SetTransparentColor(bmpFlag, 0); + Lamp := DTMFromString('mggAAAHicY2NgYMhhYmDIAOIyIK4A4kIgTgPip0C5B0D8kAHCfgXEz4F46hRRIMkExn29ImB6zSoJBn4GBOBHohlxYAgAACyDDBw='); + BookOfKnowledge := DTMFromString('78DA63CC65626078C480028A7273183480342' + + '310FF0702C64CA09AAB0C6880094C3242798CE540FE2D026ACA80' + + 'FC1704D4E401F99F08A84900F2DF12509304E43FC0AF0600CF790' + + 'EC3'); + + SRL_NAVBAR_BITMAP := BitmapFromString(14, 8, 'meJyTlFeVkleVRELSihpAhCYoCVYmBZOFKtB0lNJ0lEQSRDZBBiYIUmycKGkYJY0kIoOqAMiWUlATVXcR0wkGIiFFG2TFaEhKxUhCN0RI1UNEwxuoGMhFMwrhHsMooBpJwxAIA6hLBsNqabNYUXVXIJLUCxRWtBRRspO1SAWyxbS8gVIQNRJGEUAkqukDRDLW6dIW6RIGYeL6odKW6aKaQGd4SOgFSBpHAhEA/ekzkg=='); + + SRL_OPTIONS_BITMAP := BitmapFromString(67, 19, 'meJy1VjFywzAM80M8aPT/5zymez+RXHXmMQAIUU3Ly+CQEAWQlOwxhJ3nGc/XdYHHWIadP9ZZVWWoPGCTYYUESlW0Q/Xx9f36VdFmqs5GGTM3jd9yYV/IcRxLZJ+nIRPkj9vCAxm4hvFQyZ8Jl2SahP3yrIKdy909/hdHzMOqwwgqeNimM57l7MFYRtQj2b8EmMmXlcwj9wqFkJkhZk+Cwzh5xgAfyA8ATs5azAixkJkkM2chUt1QA5yPYRWVBZlLgPOukEhVVXvcowsYk4GzSSHN0eIb1dBg5vB3N4OPbmmJQsleNzcy7f5QyLjPThyf3Fx4j4z32TaT40dakslX326hHuoGAyFxcKBx+fIZqrM5yhh5AwDG10EWodo9hIScbDkK6vL1lS1Hs8djPFIuBBWD3pVsfP9Ahg9t68PVg1kLdGq8X24dSlsad8HyCxDkGHXR0KqJ/9cgBgBVCctmAH0mfyXQM5cwf3w6x6rp7BuriIcntCCj4Q=='); + + SRLBitmapsLoaded := True; + SetBitmapName(bmpMod,'SRL - Mod bitmap'); + SetBitmapName(bmpAdmin,'SRL - Admin bitmap'); + SetBitmapName(bmpFlag, 'SRL - Flag bitmap'); + SetDTMName(Lamp,'SRL - Lamp bitmap'); + SetBitmapName(SRL_NAVBAR_BITMAP, 'SRL - NavBar Bitmap'); + SetBitmapName(SRL_OPTIONS_BITMAP, 'SRL - Options Bitmap'); +end; + +(* +FreeSRLBitmaps +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure FreeSRLBitMaps; + +Frees SRL Bitmaps from memory. + +.. note:: + + by Ron + +Example: + +.. code-block:: pascal + +*) +procedure FreeSRLBitmaps; +begin + if SRLBitmapsLoaded then + begin + FreeBitmap(bmpMod); + FreeBitmap(bmpAdmin); + FreeBitmap(bmpFlag); + FreeDTM(Lamp); + FreeDTM(BookOfKnowledge); + FreeBitmap(SRL_NAVBAR_BITMAP); + FreeBitmap(SRL_OPTIONS_BITMAP); + SRLBitmapsLoaded := False; + end; +end; + +(* +LoadSRLFonts +~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure LoadSRLFonts; + +Loads SRL Fonts into memory. + +.. note:: + + by Markus + +Example: + +.. code-block:: pascal + +*) +procedure LoadSRLFonts; +begin +{$IFDEF LoadExtraFonts} + FriendChars := LoadChars2(FontPath + 'FriendChars/'); + LoginChars := LoadChars2(FontPath + 'LoginChars/'); +{$ENDIF} +end; + +(* +FreeSRLFonts +~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure FreeSRLFonts; + +Frees SRL Fonts from memory. + +.. note:: + + by Markus + +Example: + +.. code-block:: pascal + +*) +procedure FreeSRLFonts; +begin +{$IFDEF LoadExtraFonts} + FreeChars2(FriendChars); + FreeChars2(LoginChars); +{$ENDIF} +end; + +(* +srl_Warn +~~~~~~~~ + +.. code-block:: pascal + + procedure srl_Warn(ProcName, ErrorMessage: String; wVersion: Integer); + +WriteLn's a warning message. + +.. note:: + + by SRL Dev Team + +Example: + +.. code-block:: pascal + + try + FindTree; + except + srl_Warn('FindTree', 'Through an error', warn_AllVersions); + end; + +*) +procedure srl_Warn(ProcName, ErrorMessage: String; wVersion: Integer); +begin + if (wVersion >= WarnSensitivity) then + if (wVersion <> warn_Debug) then + WriteLn('** Warning in ' + ProcName + ': ' + ErrorMessage + ' **') + else + WriteLn('Debugging ' + ProcName + ': ' + ErrorMessage); + if wVersion = warn_Terminate then + TerminateScript; +end; + +{ MainScreen, Minimap, Inventory, Chat, Bank boxes as TBox } +var + MSBox, MMBox, MIBox, MCBox, MBBox, MFBox: TBox; + +(* +SetupBoxes +~~~~~~~~~~ + +.. code-block:: pascal + + Procedure SetupBoxes; + +Sets up Box variables + +.. note:: + + by SRL Dev Team & MylesMadness + +Example: + +.. code-block:: pascal + +*) +Procedure SetupBoxes; +begin + MSBox := IntToBox(MSX1, MSY1, MSX2, MSY2); + MMBox := IntToBox(MMX1, MMY1, MMX2, MMY2); + MIBox := IntToBox(MIX1, MIY1, MIX2, MIY2); + MCBox := IntToBox(MCX1, MCY1, MCX2, MCY2); + MBBox := IntToBox(MBX1, MBY1, MBX2, MBY2); + MFBox := IntToBox(224, 114, 294, 150); +end; + + +{ const HP_BAR constants; + Global contants storing width, height and tolerance for HP bars. + Used in srl_InFight. } +const + HP_BAR_TOL = 3; + HP_BAR_WIDTH = 57; + HP_BAR_HEIGHT = 7; + HP_BAR_COLOR1 = 9728;//Green + HP_BAR_COLOR2 = 132923;//Red + +(* +GetFightBarTPA +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + Function GetFightBarTPA(SearchArea: TBox): TPointArray; + +Used in various fighting functions, including srl_InFight + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + + +*) +Function GetFightBarTPA(SearchArea: TBox): TPointArray; +var + T: TPoint; + H, I: integer; + Colors: TIntegerArray; + ATPA: T2DPointArray; +begin + Colors := [HP_BAR_COLOR1, HP_BAR_COLOR2]; + H := High(Colors); + SetArrayLength(ATPA, H+1); + T := point((MFBox.x2+MFBox.x1) div 2,(MFBox.y2+MFBox.y1) div 2); + for i := 0 to H do + with SearchArea do + FindColorsSpiralTolerance(T.x, T.y, ATPA[i], Colors[i], X1, Y1, X2, Y2, 2); + Result := MergeATPA(ATPA); +end; + +(* +srl_InFight +~~~~~~~~~~~ + +.. code-block:: pascal + + function srl_InFight: Boolean; + +Checks whether player currently is in a fight, using mainscreen +HP bar presence detection. Returns True if Player's HP bar is detected. +Idea for improvement: Also check using PixelShift(); to see whether Player +is performing fighting animations to further improve the certainty of results. + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + + while srl_InFight do + begin + CheckHP; + EatFood; + end; + +*) +Function srl_InFight: Boolean; +begin + Result := InRange(Length(GetFightBarTPA(MFBox)), 30, 240); +end; + + +(* +FoundBar +~~~~~~~~ + +.. code-block:: pascal + + Function FoundBar: Boolean; + + Returns True If The Bar Home-Support-Forums-Subscribe Bar is On Screen. + +.. note:: + + by: Brandon, edited by [J]ustin. + +Example: + +.. code-block:: pascal + +*) + +Function FoundBar: Boolean; +var + tempCTS, X, Y: Integer; +begin + tempCTS:= GetColorToleranceSpeed; + SetColorToleranceSpeed(1); + + Result := FindBitmapToleranceIn(SRL_NAVBAR_BITMAP, X, Y, 0, 0, 764, 50, 10); + + SetColorToleranceSpeed(tempCTS); +end; + +(* +SRL_DisableNavBar +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + Procedure SRL_DisableNavBar; + + Offsets the client by 50 pixels when logged in, 22 when not logged in. This is to ignore the navigation bar at the top. + +.. note:: + + by: Brandon. + +Example: + +.. code-block:: pascal + +*) + +Procedure SRL_DisableNavBar; +var + W, H: Integer; +begin + GetClientDimensions(W, H); + If (FoundBar) then + begin + ImageSetClientArea(SRL_NAVBAR_INGAME_X, SRL_NAVBAR_INGAME_Y, W, H); //H - Offset to remove black bar at the bottom. + MouseSetClientArea(SRL_NAVBAR_INGAME_X, SRL_NAVBAR_INGAME_Y, W, H); + end else + begin + ImageSetClientArea(SRL_NAVBAR_INGAME_X, SRL_NAVBAR_LOGIN_Y, W, H); + MouseSetClientArea(SRL_NAVBAR_INGAME_X, SRL_NAVBAR_LOGIN_Y, W, H); + end; +end; + +(* +SRL_EnableNavBar +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + Procedure SRL_EnableNavBar; + + Resets The Client Offsets To Normal! All functions will work as they were before the navigation bar. + This function does not ignore the navbar. + +.. note:: + + by: Brandon. + +Example: + +.. code-block:: pascal + +*) + +Procedure SRL_EnableNavBar; +begin + ImageResetClientArea; + MouseResetClientArea; +end; + +(* +SRL_ResetNavBar +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + Procedure SRL_ResetNavBar; + + No Longer Changes Target Pointer To The ScanLine After The Bar. + Sets the Client-Image/Mouse Offset to Ignore the NavBar. 50 Pixels In Height. + +.. note:: + + by: Brandon, Benland100. + +Example: + +.. code-block:: pascal + +*) + +Procedure SRL_ResetNavBar; +begin + SRL_EnableNavBar; + SRL_DisableNavBar; +end; + +procedure Proc_WorldSwitcherEnabled; +begin + WorldSwitcherEnabled := WorldSwitcherEnabled; +end; diff --git a/SRL/core/globalstats.simba b/SRL/core/globalstats.simba new file mode 100644 index 0000000..66e3673 --- /dev/null +++ b/SRL/core/globalstats.simba @@ -0,0 +1,443 @@ +(* + +Stats +===== + +The Stats include contains wrapper functions provided by the SRL Stats API. +The functions contained are meant for ease of use for implementation into +scripts. + +.. contents:: + +*) + +// behaves as entries in a dict. +type + TStats_Vars = record + Name: string; + Value: integer; + end; + +const + stats_ShowStatsDialog = 'stats_ShowStatsDialog'; // Name for the Setting that will be set + +var + stats_Vars: Array of TStats_Vars; + stats_UserName, stats_UserPass, stats_ScriptID: String; + stats_Timer: integer; + stats_RandNames: Array of String; + stats_RandSolved: Array of Integer; + stats_RandFailed: Array of Integer; + +{$IFNDEF LAPE} + stats_form: TForm; + stats_txtUser, stats_txtPass, stats_txtEmail: TEdit; + stats_btnRegister, stats_btnCancel: TButton; + stats_lblUser, stats_lblPass, stats_lblEmail: TLabel; + + +procedure stats_btnRegisterClick(Sender: TObject); +var + stats_Client: integer; + stats_PostData, stats_strError, stats_strSuccess: string; + stats_Success: boolean; +begin + // Check to make sure the user has filled in the Username and Password fields + if (Length(stats_txtUser.TEXT) = 0) OR (Length(stats_txtPass.TEXT) = 0) then + begin + MessageDlg('Error While Registering!', 'Please make sure you have entered a Username and Password into the appropriate fields.', mtError, [mbOk]); + end else + begin + try + stats_Client := InitializeHTTPClient(false, false); + + // Set Post Data + stats_PostData := 'user=' + stats_txtUser.TEXT + '&pass=' + stats_txtPass.TEXT; + if Length(stats_txtEmail.TEXT) > 0 then + stats_PostData := stats_PostData + '&mail=' + stats_txtEmail.TEXT; + + // Post data to STATS URL and receive response + stats_PostData := PostHTTPPage(stats_Client, 'http://stats.villavu.com/register', stats_PostData); + // Trim down the response to a bite size chunk + stats_PostData := Between('
', '', stats_PostData); + + // If there is an error, strip out just the error message(s) + // (I know the replacement of
  • with is silly, but I'm tired + // and this fits at the time) + stats_strError := Replace(Between('
      ', '
    ', stats_PostData), 'li', 'ERROR'); + // If successful, get the success response + stats_strSuccess := Between('

    ', '

    ', stats_PostData); + + // This next part is weird, I know, but it's the only way I could figure + // out how to show right message(s) + if Length(stats_strError) > 0 then + MessageDlg('Error While Registering!', stats_strError + '!', mtError, [mbOk]) + else if Length(stats_strSuccess) > 0 then + begin + MessageDlg('Registration Successful!', stats_strSuccess + ' You may find your account at: [url]http://stats.villavu.com[/url]' + Between('href="', '">', stats_PostData) + '. Please fill in the SRL Stats information in your script and run again, this script is now ending.', mtConfirmation, [mbOk]); + stats_Success := true; + end; + finally + FreeHTTPClient(stats_Client); + + if stats_Success then + stats_form.CLOSE; + end; + end; +end; + +procedure stats_btnCancelClick(Sender: TObject); +begin + stats_form.CLOSE; +end; + +procedure stats_formInit; +begin + stats_form := TForm.create(nil); + with stats_form do + begin + caption := 'Register for SRL Stats'; + setBounds(100, 100, 280, 130); + end; + + stats_lblUser := TLabel.Create(stats_form); + with stats_lblUser do + begin + parent := stats_form; + caption := 'Username: '; + top := 10; + left := 10; + end; + + stats_lblPass := TLabel.Create(stats_form); + with stats_lblPass do + begin + parent := stats_form; + caption := 'Password: '; + top := 40; + left := 10; + end; + + stats_lblEmail := TLabel.Create(stats_form); + with stats_lblEmail do + begin + parent := stats_form; + caption := 'Email (Opt): '; + top := 70; + left := 10; + end; + + stats_txtUser := TEdit.Create(stats_form); + with stats_txtUser do + begin + parent := stats_form; + setBounds(75, 7, 200, 25); + Hint := 'Limit of 20 characters.'; + ShowHint := true; + MaxLength := 20; + end; + + stats_txtPass := TEdit.Create(stats_form); + with stats_txtPass do + begin + parent := stats_form; + setBounds(75, 37, 200, 25); + Hint := 'Limit of 20 characters.'; + ShowHint := true; + MaxLength := 20; + PASSWORDCHAR := '*'; + end; + + stats_txtEmail := TEdit.Create(stats_form); + with stats_txtEmail do + begin + parent := stats_form; + setBounds(75, 67, 200, 25); + Hint := 'Limit of 40 characters, and also allows the characters email addresses can contain.'; + ShowHint := true; + MaxLength := 40; + end; + + stats_btnRegister := TButton.Create(stats_form); + with stats_btnRegister do + begin + parent := stats_form; + width := 100; + height := 25; + top := 100; + left := 10; + caption := 'Register'; + onClick := @stats_btnRegisterClick; + end; + + stats_btnCancel := TButton.Create(stats_form); + with stats_btnCancel do + begin + parent := stats_form; + width := 100; + height := 25; + top := 100; + left := 175; + caption := 'Cancel'; + onClick := @stats_btnCancelClick; + end; + + stats_form.showModal; +end; + +procedure stats_formSafeCall(proc: string); +var + stats_v: TVariantArray; +begin + setLength(stats_v, 0); + threadSafeCall(proc, stats_v); +end; + +procedure stats_formFree(); +begin + stats_form.free(); +end; +{$ENDIF} + + +(* +SetupSRLStats +~~~~~~~~~~~~~ + +.. code-block:: pascal + procedure SetupSRLStats(ScriptID: integer; UserName, UserPass: string); + +Initializes all variables necessary for SRL stats to function. Username and +password are *not* case sensitive. + +Example: +.. code-block:: pascal + SetupSRLStats(64, 'SRL-Developers', 'SRLSRLSRL'); +*) +procedure SetupSRLStats(ScriptID: integer; UserName, UserPass: string); +begin + stats_Timer := GetSystemTime; + stats_ScriptID := IntToStr(ScriptID); + stats_Username := UserName; + stats_UserPass := UserPass; + stats_RandNames := ['Leo', 'Forester', 'Maze', 'P. Pete', 'Evil Bob', + 'Demon', 'Quiz', 'Mordaut', 'Molly', 'Pinball', + 'Sandwich', 'Beekeeper', 'Pillory', 'Arnav', 'Abyss', + 'Certer', 'Mime', 'Frog', 'Trade', 'Mod', 'Fight', 'Lamp', + 'Bird Nest', 'Death', 'Reward Box']; + SetArrayLength(stats_RandSolved, Length(stats_RandNames)); + SetArrayLength(stats_RandFailed, Length(stats_RandNames)); + if ((stats_Username = '') AND (stats_UserPass = '')) AND (StrToBoolDef(GetSettingValue(stats_ShowStatsDialog), True)) then + begin + {$IFNDEF LAPE} + case MessageBox('No Stats account entered, would you like to set one up?', 'SRL Stats', mbYesNoCancel) of + mrYes: + try + stats_formSafeCall('stats_formInit'); + except + writeln(exceptionToString(exceptionType, exceptionParam)); + finally + stats_formSafeCall('stats_formFree'); + end; + + mrNo: + case MessageBox('Would you want to disable this dialog from showing again in the future? (Not Recommended)', 'Disable this dialog?', mbYesNoCancel) of + mrYes: SetSettingValue(stats_ShowStatsDialog, 'FALSE'); + end; + end; + {$ENDIF} + end; + + if (stats_username = '') then + begin + stats_Username := 'Anonymous'; + stats_UserPass := 'anon1337'; + end; +end; + +(* +stats_InitVariable +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + stats_InitVariable(VarName: String; InitValue: Integer); + +Helper method to clean up code in the include. Removes some repeating code +internally. + +.. WARNING:: + Use of this method outside of this include *may* lead to multiple variables + of the same name. It does **not** check to see if the variable is already + present. + +.. code-block:: pascal + stats_InitVariable('coal', 0); + +*) +procedure stats_InitVariable(VarName: String; InitValue: Integer); +var + len: Integer; +begin + len := Length(stats_Vars); + SetArrayLength(stats_Vars, len + 1); + stats_Vars[len].Name := LowerCase(VarName); + stats_Vars[len].Value := InitValue; +end; + + +(* +stats_SetVariable +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + stats_SetVariable(VarName: string; NewValue: Integer); + +Sets the passed variable to the new value regardless of old value. This method +behaves much like stats_InitVariable but checks for the variable present first. + +Example: +.. code-block:: pascal + stats_SetVariable('runite', 10) +*) +procedure stats_SetVariable(VarName: string; NewValue: Integer); +var + i, h: Integer; +begin + h := High(stats_Vars); + VarName := LowerCase(VarName); // set it to lowercase since not case sensitive + + if (h >= 0) then + for i := h downto 0 do + if (VarName = stats_Vars[i].Name) then + begin + stats_Vars[i].Value := NewValue; + Exit; + end; + + // the variable is not present already, thus make a new entry into the dict. + stats_InitVariable(VarName, NewValue); +end; + +(* +stats_IncVariable +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + procedure stats_IncVariable(VarName: string; Value: integer); + +Increments a variable by the value passed. + +Example: +.. code-block:: pascal + stats_IncVariable('cod', 69); + +*) +procedure stats_IncVariable(VarName: string; Value: integer); +var + i, h: Integer; +begin + h := High(stats_Vars); + VarName := LowerCase(VarName); // set it to lowercase since not case sensitive + + if (h >= 0) then + for i := h downto 0 do + if (VarName = stats_Vars[i].Name) then + begin + stats_Vars[i].Value := stats_Vars[i].Value + Value; + Exit; + end; + + // the variable is not present already, thus make a new entry into the dict. + stats_InitVariable(VarName, Value); +end; + + +(* +stats_Commit +~~~~~~~~~~~~ + +.. code-block:: pascal + function stats_Commit: Boolean; + +Sends all the information currently stored in the system to the server. Returns +true if commit was successful, displays error messages. One should note that the +stats variables are set to 0 on commit. + +Example: +.. code-block:: pascal + if (stats_Commit) then + WriteLn('We are success.'); + +*) +function stats_Commit: Boolean; +var + SRLClient, Worked, i, ExtraTime, Increment: integer; + S: String; +begin + ExtraTime := GetSystemTime - stats_Timer; + Worked := ExtraTime div 60000; + // Exit if 5 minutes of time has not passed since last commit. + if Worked < 5 then Exit; + ExtraTime := ExtraTime - (Worked*60000); + + stats_Timer := GetSystemTime - ExtraTime; + {$IFDEF Simba} + SRLClient := InitializeHTTPClientWrap(False); + {$ELSE} + SRLClient := InitializeHTTPClient(False, False); + {$ENDIF} + ClearPostData(SRLClient); + + AddPostVariable(SRLClient, 'user', stats_UserName); + AddPostVariable(SRLClient, 'password', stats_UserPass); + AddPostVariable(SRLClient, 'script', stats_ScriptID); + AddPostVariable(SRLClient, 'time', IntToStr(Worked)); + + for i := rand_Leo to rand_Frog do + begin + // Update solved stats. + Increment := tmp_RandSolved[i] - stats_RandSolved[i]; + if (Increment > 0) then + begin + stats_IncVariable(stats_RandNames[i] + ' (Solved)', Increment); + stats_RandSolved[i] := tmp_RandSolved[i]; + end; + // Update unsolved stats. + Increment := tmp_RandFailed[i] - stats_RandFailed[i]; + if (Increment > 0) then + begin + stats_IncVariable(stats_RandNames[i] + ' (Unsolved)', Increment); + tmp_RandFailed[i] := stats_RandFailed[i]; + end; + end; + + if (Length(stats_Vars) > 0) then + for i := High(stats_Vars) downto 0 do + with stats_Vars[i] do + begin + if (Value <= 0) then + Continue; + + AddPostVariable(SRLClient, Name, ToStr(Min(Value, 20000))); //Commit Value capped at 20000 + Value := 0;//Clear for next commit + end; + + S := PostHTTPPageEx(SRLClient, 'http://stats.villavu.com/api/commit'); + FreeHTTPClient(SRLClient); + Result := False; + {$IFDEF Simba} + case StrToIntDef(ExtractFromStr(S, Numbers), -1) of + {$ELSE} + case StrToIntDef(GetNumbers(S), -1) of + {$ENDIF} + 100: Result := True; // successful commit. + 110: Writeln('SRL_Stats: Incorrect user and/or password'); + 120: Writeln('SRL_Stats: Incorrect script ID'); + 130: Writeln('SRL_Stats: Invalid time'); + 140: Writeln('SRL_Stats: Variable does not exist'); + 150: Writeln('SRL_Stats: Wrong info for variable'); + 160: Writeln('SRL_Stats: Internal server error'); + else + Writeln('SRL_Stats: No POST return'); + end; +end; diff --git a/SRL/core/inventory.simba b/SRL/core/inventory.simba new file mode 100644 index 0000000..cc5ad59 --- /dev/null +++ b/SRL/core/inventory.simba @@ -0,0 +1,1127 @@ +(* +Inventory +========= + +The Inventory include contains all inventory-related functions. + +.. contents:: + +*) + +{ type TInvenItem; + Description: Holds data regarding an inventory item } +type + TInvenItem = record + Width, Height : Integer; // the width and height of the item + Count : Integer; // the count of the item + ItemBox : TBox; // the exact box around the item + CenterPoint: TPoint; // the center point inside the item + ExistsItem : Boolean; // to define the item Exists + end; + TInvenItemArr = array of TInvenItem; + +(* +GetInven +~~~~~~~~ + +.. code-block:: pascal + + function GetInven(Inven: Integer): TInvenItem; + +Returns The Width, Height, Count, ItemBox and CenterPoint of the given Item Slot. + +.. note:: + + by SKy Scripter + +Example: + +.. code-block:: pascal + + invItem := GetInven(InvSlot); + MMouse(invItem.centerPoint.x, invItem.centerPoint.y, 2, 2); + +*) +function GetInven(Inven: Integer): TInvenItem; +var + Slot, Row, Ix, Iy, I, Cx, Cy: Integer; + P: TPointArray; + MinP, MaxP: TPoint; +begin + GameTab(tab_Inv); + Inven := Inven - 1; + Slot := Inven mod 4; + Row := Inven div 4; + IX := 560 + (Slot * 42); + IY := 210 + (Row * 36); + FindColorsTolerance(P, srl_outline_black, IX, IY, IX + 41, IY + 35, 0); + Result.Count := Length(P); + if (Result.Count = 0) then Exit; + Result.ExistsItem := True; + MinP := P[0]; + MaxP := P[Result.Count-1]; + Cx := P[0].x + P[Result.Count-1].x; + Cy := P[0].y + P[Result.Count-1].y; + for I := 1 to Result.Count - 2 do + begin + if (P[i].x < MinP.x) then MinP.x := P[i].x; + if (P[i].y < MinP.y) then MinP.y := P[i].y; + if (P[i].x > MaxP.x) then MaxP.x := P[i].x; + if (P[i].y > MaxP.y) then MaxP.y := P[i].y; + Cx := Cx + P[i].x; + Cy := Cy + P[i].y; + end; + Cx := Cx div Result.Count; + Cy := Cy div Result.Count; + Result.CenterPoint := Point(Cx, Cy); + Result.Width := MaxP.x - MinP.x; + Result.Height := MaxP.y - MinP.y; + Result.ItemBox := PointToBox(MinP, MaxP); +end; + +(* +GetInventoryArray +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetInventoryArray : array of TInvenItem; + +Returns The Width, Height, Count, ItemBox and CenterPoint in array [0..27] of +all Items in the inventory. + +.. note:: + + by SKy Scripter + +Example: + +.. code-block:: pascal + + invItems := GetInventoryArray); + for i := 3 to 7 do + MMouse(invItems[i].centerPoint.x, invItems[i].centerPoint.y, 2, 2); + +*) +function GetInventoryArray : TInvenItemArr; +var + I: Byte; +begin + SetArrayLength(Result, 28); + for I := 0 to 27 do + Result[I] := GetInven(i + 1); +end; + +(* +InvBox +~~~~~~ + +.. code-block:: pascal + + Function InvBox(i :Integer): TBox; + +Returns TBox of surrounding Inventory SlotBox +1-2-3-4 +5-6-7-8 +etc. + +.. note:: + + by Boreas + Last Modified: by Ogre July 15th 2009. + +Example: + +.. code-block:: pascal + + iBox := InvBox; + MMouse(randomRange(iBox.x1, iBox.x2), randomRange(iBox.y1, iBox.y2), 0, 0); + +*) +function InvBox(I :Integer): TBox; +var + Slot1, Slot6: TBox; +begin + if not InRange(I, 1, 28) then + begin + Result := IntToBox(-1,-1,-1,-1); + srl_Warn('InvBox', 'Incorrect index: ' + IntToStr(i), warn_AllVersions); + Exit; + end; + Slot1 := IntToBox(563, 213, 594, 244); + Slot6 := IntToBox(605, 249, 31415, 92653); + Result.x1 := Slot1.X1 + ((((i + 3) mod 4)) * (Slot6.X1 - Slot1.X1)); + Result.y1 := Slot1.Y1 + ((((i - 1) div 4)) * (Slot6.Y1 - Slot1.Y1)); + Result.x2 := Result.x1 + (Slot1.X2 - Slot1.X1); + Result.y2 := Result.y1 + (Slot1.Y2 - Slot1.Y1); +end; + +(* +ItemCoords +~~~~~~~~~~ + +.. code-block:: pascal + + function ItemCoords(i: Integer): TPoint; + +Returns X and Y of Specified Inventory Slot + +.. note:: + + by RsN + +Example: + +.. code-block:: pascal + + Coords := itemCoords(3); + MMouse(Coords.x, Coords.y, 2, 2); + +*) +function ItemCoords(i: Integer): TPoint; +var + Box: TBox; +begin + Box := InvBox(i); + Result.X := (Box.X1 + Box.X2) Shr 1; + Result.Y := (Box.Y1 + Box.Y2) Shr 1; +end; + +(* +CoordsToItem +~~~~~~~~~~~~ + +.. code-block:: pascal + + function CoordsToItem(X, Y: Integer): Integer; + +Returns which Inventory slot the X and Y coords are in. If the +coords are between slots (or not in the inventory area at all) it will return 0. + +.. note:: + + by Boreas and BraK + +Example: + +.. code-block:: pascal + + Writeln('Item found in slot '+IntToStr(CoordsToItem(point.x, point.y))); + +*) +function CoordsToItem(X, Y: Integer): Integer; +begin + if not PointInBox(Point(X, Y), IntToBox(MIX1, MIY1, MIX2, MIY2)) then + exit; + for Result := 1 to 28 do + if PointInBox(Point(X, Y), InvBox(result)) then + exit; + Result := 0; +end; + +(* +GetInvItemBounds +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetInvItemBounds(InvSpot: Integer; var T: TBox): Boolean; + +If item exists, returns TBox of the item, else returns the normal InvBox. + +.. note:: + + by Wizzup? + +Example: + +.. code-block:: pascal + + for i := 1 to 7 do + if GetInvItemBounds(i, iBox) then + Writeln('Item found in slot '+IntToStr(i)); + +*) +function GetInvItemBounds(InvSpot: Integer; var T: TBox): Boolean; +var + TPA: TPointArray; +begin + GameTab(tab_inv); + if (not FindColors(TPA, srl_outline_black, T.x1, T.y1, T.x2, T.y2)) then //No shortcut elevation + begin + Result := False; + T := InvBox(InvSpot); + Exit; + end; + Result := True; + T := GetTPABounds(TPA); +end; + +(* +ExistsItem +~~~~~~~~~~ + +.. code-block:: pascal + + function ExistsItem(i: Integer): Boolean; + +Checks if item in inventory at specified position exists + +.. note:: + + by WT-Fakawi + +Example: + +.. code-block:: pascal + + for i := 1 to 28 do + if ExistsItem(i) then + Inc(Count); + +*) +function ExistsItem(I: Integer): Boolean; +var + X, Y: Integer; + TB: TBox; +begin + GameTab(tab_Inv); + TB := InvBox(I); + Result := FindColor(x, y, srl_outline_black, TB.x1, TB.y1, TB.x2, TB.y2); +end; + +(* +ExistsItemDTM +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ExistsItemDTM(dtm: Integer; var x, y: Integer): Boolean; + +Checks if the dtm is in the inventory. Returns the item's coordinates. + +.. note:: + + by NCDS + +Example: + +.. code-block:: pascal + + if ExistsItemDTM(OreDTM, x, y) then + MMouse(x, y, 3, 3); + +*) +function ExistsItemDTM(dtm: Integer; var x, y: Integer): Boolean; +begin + Gametab(tab_Inv); + Wait(300 + Random(300)); + Result := FindDTM(dtm, x, y, MIx1, MIy1, MIx2, MIy2); +end; + +(* +InvMouse +~~~~~~~~ + +.. code-block:: pascal + + function InvMouse(InvSlot, Action: Byte) : boolean; + +A combined MouseItem & MMouseItem, will hopefully replace both +procedures one day. Usage is like SRL's MouseBox, Action determines what to do: + + - 1: Leftclick + - 2: Rightclick + - 3: Move mouse to item + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + + if InvMouse(1, rightClick) then + WaitOption('eposit', 500); + +*) +function InvMouse(InvSlot, Action: Byte) : boolean; +var + TB: TBox; + CurrPT : TPoint; +begin + result := false; + if (not InRange(Action, 0, 3)) then + begin + srl_Warn('InvMouse', 'Action #' + IntToStr(Action) + ' is not a valid action', warn_AllVersions); + Exit; + end; + if (not InRange(InvSlot, 1, 28)) then + begin + srl_Warn('InvMouse', 'Inventory slot #' + IntToStr(InvSlot) + ' is not a valid slot', warn_AllVersions); + Exit; + end; + GameTab(tab_inv); + Result := true; + TB := InvBox(InvSlot); + GetMousePos(CurrPT.x,CurrPT.y); + if PointInBox(CurrPT,TB) then + MouseBox(Max(CurrPT.x-random(2),TB.x1),Max(CurrPT.y-random(2),TB.y1), + Min(CurrPT.x+random(2),TB.x2),Min(CurrPT.y+random(2),TB.y2),Action) //LOL Pro-human much! + else + MouseBox(TB.X1, TB.Y1, TB.X2, TB.Y2, Action); +end; + +(* +MMouseItem +~~~~~~~~~~ + +.. code-block:: pascal + + procedure MMouseItem(i: Integer); + +Moves mouse to specified inventory spot. + +.. note:: + + by WT-Fakawi/EvilChicken! + +Example: + +.. code-block:: pascal + + MMouseItem(1); + +*) +procedure MMouseItem(I: Integer); +begin + if (ExistsItem(I)) then + InvMouse(I, mouse_move); +end; + +(* +MouseItem +~~~~~~~~~ + +.. code-block:: pascal + + procedure MouseItem(i: Byte; Left: Boolean); + +Moves Mouse to inv spot then clicks left or right. + +.. note:: + + by WT-Fakawi/EvilChicken! edit by Naum + +Example: + +.. code-block:: pascal + + MouseItem(1, true); + +*) +procedure MouseItem(I: Integer; button: Integer); +begin + if (ExistsItem(I)) then + InvMouse(i, button); +end; + +(* +DragItem +~~~~~~~~ + +.. code-block:: pascal + + procedure DragItem(Inv1, Inv2: Integer); + +Drags Item from first position Inv1 to Inv2 (Inventory Slots) + +.. note:: + + by Naum + +Example: + +.. code-block:: pascal + + DragItem(1, 3); + +*) +procedure DragItem(Inv1, Inv2: Integer); +var + InvAr: array [0..1] of TBox; +begin + InvAr[0] := InvBox(Inv1); + InvAr[1] := InvBox(Inv2); + DragMouse(InvAr[0].x1, InvAr[0].y1, InvAr[0].x2 - InvAr[0].x1, InvAr[0].y2 - InvAr[0].y1, + InvAr[1].x1, InvAr[1].y1, InvAr[1].x2 - InvAr[1].x1, InvAr[1].y2 - InvAr[1].y1); +end; + +(* +InvCount +~~~~~~~~ + +.. code-block:: pascal + + function InvCount: Integer; + +Returns amount of items in your inventory + +.. note:: + + by RsN + +Example: + +.. code-block:: pascal + + totalCount := InvCount; + +*) +function InvCount: Integer; +var + I: Integer; +begin + Result := 0; + GameTab(tab_inv); + for I := 1 to 28 do + if (ExistsItem(I)) then + Inc(Result); +end; + +(* +InvEmpty +~~~~~~~~ + +.. code-block:: pascal + + function InvEmpty: Boolean; + +Returns True if inventory is empty + +.. note:: + + by WT-Fakawi + +Example: + +.. code-block:: pascal + + if InvEmpty then + CloseBank; + +*) +function InvEmpty: Boolean; +var + X, Y: Integer; +begin + GameTab(tab_Inv); + Result := (not FindColor(X, Y, srl_outline_black, MIX1, MIY1, MIX2, MIY2)); +end; + +(* +InvFull +~~~~~~~ + +.. code-block:: pascal + + function InvFull: Boolean; + +Returns True if inventory is full + +.. note:: + + by n3ss3s + +Example: + +.. code-block:: pascal + + if InvFull then + walkToBank; + +*) +function InvFull: Boolean; +Var + i : integer; +begin + GameTab(Tab_Inv); + Result := True; + + for i := 1 to 28 do + if (not ExistsItem(i)) then + begin + Result := False; + exit; + end; +end; + +(* +CountItems +~~~~~~~~~~ + +.. code-block:: pascal + + function CountItems(ItemType: string; Identifier: Integer; tol: TIntegerArray): Integer; + +Counts Items in the inventory: + + - ItemType: 'dtm', 'bitmap', 'bitmap mask', 'color' + - Item: name/value of your dtm/bmp/color/bmpmask. + - Tol: + + * 'dtm' - [] (dtm's can't have tolerance). + * 'bmp' - [BMPTol]. + * 'color' - [COLOUR Tol, Colour Count]. + * 'bmpmask' - [BMPTol, ContourTol]. + +.. note:: + + by WT-Fakawi / Sumilion + +Example: + +.. code-block:: pascal + + numbOfItems := CountItems('dtm', TheDTM, []); + +*) +function CountItems(ItemType: string; Identifier: Integer; tol: TIntegerArray): Integer; +begin + GameTab(tab_Inv); + Result := CountItemsIn('inv', ItemType, Identifier, Tol) +end; + +(* +ClickAllItemsExcept +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClickAllItemsExcept(ItemType: String; Identifier: Integer; option: string; SlotIgnores: TIntegerArray; waitnum: Integer; tol: TIntegerArray):Integer; + +Performs "option" popup menu action on all items with: + + - ItemType: 'dtm', 'bitmap', 'bitmap mask', 'color' + - Identifier: name/value of your dtm/bmp/color/bmpmask. + - Tol: + + * 'dtm' - [] (dtm's can't have tolerance). + * 'bmp' - [BMPTol]. + * 'color' - [COLOUR Tol, Colour Count]. + * 'bmpmask' - [BMPTol, ContourTol]. + + Will not click items in slots SlotIgnores + +.. note:: + + by WT-Fakawi / Sumilion & Nava2 + +Example: + +.. code-block:: pascal + + ClickAllItemsExcept('dtm', theDTM, 'eposit', [1, 4, 5], 200, []); + +*) +function ClickAllItemsExcept(ItemType: String; Identifier: Integer; option: string; SlotIgnores: TIntegerArray; waitnum: Integer; tol: TIntegerArray):Integer; +var + arr: TIntegerArray; + I, X, Y: Integer; + TB: Tbox; +begin + GameTab(tab_Inv); + Result := 0; + arr :=[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]; + for i := 1 to 28 - 4 do + Swap(arr[RandomRange(i - 1, i + 4)], arr[RandomRange(i - 1, i + 4)] ); + SetLength(Tol, 2); + for i := 0 to 27 do + begin + if InIntArray(SlotIgnores, arr[i] + 1) then Continue; + TB := InvBox(arr[i]); + if ExistsItem(arr[i]) then + try + if not FindItemEx(x, y, ItemType, Identifier, TB, Tol) then Continue; + if (Option <> '') then + begin + MouseItem(arr[i], mouse_right); + WaitOption(Option, waitnum); + Inc(Result); + end + else + MouseItem(arr[i], mouse_Left); + Wait(waitnum); + except end; + end; +end; + +(* +ClickAllItems +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClickAllItems(ItemType: String; Identifier: Integer; option: string; waitnum: Integer; tol: TIntegerArray):Integer; + +See ClickAllItemsExcept, this doesn't ignore any slots. + +.. note:: + + by WT-Fakawi / Sumilion & Nava2 + +Example: + +.. code-block:: pascal + + ClickAllItemsExcept('dtm', theDTM, 'eposit', 200, []); + +*) +function ClickAllItems(ItemType: String; Identifier: Integer; option: string; waitnum: Integer; tol: TIntegerArray):Integer; +begin + Result := ClickAllItemsExcept(ItemType, Identifier, option, [], waitnum, tol); +end; + +(* +DropItem +~~~~~~~~ + +.. code-block:: pascal + + procedure DropItem(i: Integer); + +Drops item at given position (1-28) + +.. note:: + + by Lorax + +Example: + +.. code-block:: pascal + + DropItem(3); + +*) +function DropItem(i: Integer): Boolean; +begin + Result := False; + if ExistsItem(i) then + begin + MouseItem(i, mouse_Right); + if (WaitOptionEx('rop', 'action', ClickLeft, 250)) then + begin + Result := True; + Wait(RandomRange(50, 200)); + end; + end; +end; + +(* +DropArray +~~~~~~~~~ + +.. code-block:: pascal + + procedure DropArray(InvSlots: TIntegerArray); + +Drops item positioned equivalent to numbers in "InvSlots" array. +Example: "DropArray([2, 4, 9, 12]);" would drop items in InvSlot 2, 4, 9 and 12. + +.. note:: + + by Lorax/EvilChicken!, Tickyy for idea. + +Example: + +.. code-block:: pascal + + DropArray([2, 3, 6]); + +*) +procedure DropArray(InvSlots: TIntegerArray); +var + I, Len: Integer; +begin + Len := Length(InvSlots); + for I := 1 to Len - 4 do + Swap(InvSlots[RandomRange(I - 1, I + 4)], InvSlots[RandomRange(I - 1, I + 4)]); + for I := 0 to Len - 1 do + DropItem(InvSlots[I]); +end; + +const + dp_UpToDown = 1; + dp_Snake = 2; + dp_Random = 3; + +(* +DropPattern +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DropPattern(Which: Integer); + +Drops all items in inventory according to pattern which. + +.. note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + + DropPattern(dp_Snake); + +*) +procedure DropPattern(Which: Integer); +var + Col, A, I: Integer; + Arr: TIntegerArray; + Turn: Boolean; +begin + SetLength(Arr, 28); + A := 0; + if (Which = 0) then + Which := Random(2) + 1; //ignores complete randomness, unless scripter chooses to use it + srl_warn('DropPattern','Dropping by pattern: ' + IntToStr(Which),warn_Debug); + case which of + dp_UpToDown: + for Col := 1 to 4 do + if InIntArray([2, 4], Col) then + begin + for i := 6 Downto 0 do + begin + Arr[a] := Col + i*4; + Inc(a); + end; + end else + for i := 0 to 6 do + begin + Arr[a] := Col + i*4; + Inc(a); + end; + dp_Snake: + repeat + if (not Turn) then + begin + for i:= 1 to 4 do + Arr[a + I - 1] := A + I; + IncEx(a, 4); + Turn := True; + end else begin + for I := 4 Downto 1 do + Arr[a-i+4] := a + i; + IncEx(a, 4); + Turn := false; + end; + until (a >= 28); + dp_Random: + begin + DropArray([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]); + Exit; + end; + end; + if Random(2) = 1 then + InvertTIA(Arr); + Gametab(tab_inv); + for i:= 0 to 27 do + DropItem(Arr[i]); +end; + +(* +DropAll +~~~~~~~ + +.. code-block:: pascal + + procedure DropAll; + +Drops all items in inventory. + +.. note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + + DropAll; + +*) +procedure DropAll; +var i: integer; +begin + for i:= 0 to 2 do + begin + DropPattern(Random(2) + 1); + if InvCount = 0 then + break; + end; +end; + +(* +DropAllExcept +~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DropAllExcept(IgnoreInvSlots: TIntegerArray); + +Drops everything in inventory. Ignores slots specified by DontDrop array. + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + + DropAllExcept([1, 3, 5, 6]); + +*) +procedure DropAllExcept(DontDrop: TIntegerArray); +var + inv, i, h: Integer; +begin + h := high(DontDrop); + for i := 0 to h do + { Set the bit associated with the DontDrop Array } + inv := inv or (1 shl DontDrop[i]); + for i := 1 to 28 do + { Check the bit at i, and if its high, then we dont drop. } + if (((inv shr i) and 1) = 0) then + DropItem(i); +end; + +(* +DropItemsByIdentifier +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DropItemsByIdentifier(ItemType: string; Identifier: Integer; Tol: TIntegerArray); + +See description of ClickAllItemsExcept. + +.. note:: + + by EvilChicken! Fixed by Coh3n + +Example: + +.. code-block:: pascal + + DropItemsByIdentifier('dtm', tehDTM, []); + +*) +procedure DropItemsByIdentifier(ItemType: string; Identifier: Integer; Tol: TIntegerArray); +begin + ClickAllItems(ItemType, Identifier, 'rop', 250, Tol); +end; + +(* +ArrangeInv +~~~~~~~~~~ + +.. code-block:: pascal + + procedure ArrangeInv; + +Arrange's inventory in an orderly fashion. + +.. note:: + + by Cheesehunk + +Example: + +.. code-block:: pascal + + ArrangeInv; + +*) +procedure ArrangeInv; +var + InvSpace, i, c, OpenSpace: Integer; + InvSpotFull: array[1..28] of Boolean; +begin + InvSpace := InvCount; + if (InvSpace <= 0) or (InvSpace >= 28) then + Exit; + for i := 1 to 28 do + InvSpotFull[i] := ExistsItem(i); + for i := 1 to 28 do + if InvSpotFull[i] then + for c := 1 to 28 do + if not ExistsItem(c) then + begin + OpenSpace := c; + if (i > 1) and (c < i) then + begin + DragItem(i, c); + Break; + end; + end; +end; + +(* +CountItemsBlackLine +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function CountItemsBlackLine(Count, Tol: Integer): Integer; + +Returns the number of items in inventory with Count amount of +blackline points and Tol tolerance in the amount of points. + +.. note:: + + by n3ss3s, fixed by Bobzilla69 + +Example: + +.. code-block:: pascal + + CountItemsBlackLine(260, 2); + +*) +function CountItemsBlackLine(Count, Tol: Integer): Integer; +var + I, B: Integer; + Search:TBox; +begin + GameTab(tab_Inv); + result := 0; + for i:=1 to 28 do + begin + Search:= InvBox(i); + B:= CountColor(SRL_OUTLINE_BLACK, Search.X1, Search.Y1, Search.X2, Search.Y2 ); + if InRange(B, Count - Tol, Count + Tol) then + Inc(Result); + end; +end; + +(* +ClickAllItemsBlackLine +~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ClickAllItemsBlackLine(Count, Tol: Integer; Option: string): Integer; + +Finds all items in inventory with blackline points amount of Count +with Tol tolerance, and returns the amount of items could choose the +option Option to. Waits the WaitT amount of millisecs between items, with +WaitR randomness of milliseconds. + +.. note:: + + by n3ss3s + +Example: + +.. code-block:: pascal + + ClickAllItemsBlackLine(260, 2, 'rop'); + +*) +function ClickAllItemsBlackLine(Count, Tol, WaitT, WaitR: Integer; Option: String): Integer; +var + TPA: TPointArray; + X, Y, Z, H: Integer; + TPAA: T2DPointArray; +begin + GameTab(tab_Inv); + result := 0; + FindColorsTolerance(TPA, srl_outline_black, MIX1, MIY1, MIX2, MIY2, 0); + TPAA := TPAToATPAEx(TPA, 42, 36); + H := High(TPAA); + for z := 0 to H do + if InRange(GetArrayLength(TPAA[z]), Count - Tol, Count + Tol) then + begin + MiddleTPAEx(TPAA[z], X, Y); + Mouse(X, Y, 2, 2, mouse_Right); + if WaitOption(Option, 300) then + begin + Inc(Result); + Wait(WaitT + Random(WaitR)); + end; + end; +end; + +(* +ItemsActivated +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ItemActivated(Slot: Integer): Boolean; + +Checks if item in specified inventory slot has a white outline. +Returns True if the item has a white outline, otherwise returns false. + +.. note:: + + by marpis + +Example: + +.. code-block:: pascal + + Result := ItemActivated(4); + +*) +function ItemActivated(Slot: Integer): Boolean; +var + X, Y: Integer; + TB: TBox; +begin + result := false; + if not GameTab(tab_Inv) then + exit; + TB := InvBox(Slot); + Result := FindColor(x, y, srl_outline_white, TB.x1, TB.y1, TB.x2, TB.y2); +end; + +(* +ActivatedItem +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ActivatedItem : integer; + +Returns the selected item in invetory (if any), else returns -1. + +.. note:: + + by mastaraymond + +Example: + +.. code-block:: pascal + + item := ActivatedItem; + +*) +function ActivatedItem : integer; +var + i : integer; +begin; + result := -1; + for i := 1 to 28 do + if ItemActivated(i) then + begin + result := i; + exit; + end; +end; diff --git a/SRL/core/login.simba b/SRL/core/login.simba new file mode 100644 index 0000000..ad2698c --- /dev/null +++ b/SRL/core/login.simba @@ -0,0 +1,1350 @@ +(* +Login +===== + +The Login include contains all the functions to succesfully log you in and out +of the game and/or the lobby. + +.. contents:: + +*) + + +const + SM_Color = 8115338; + +{ var SRL_Logs: Integer; + var RandomPlayer, GraphicsSet: Boolean; + Description: Variables needed for some login functions. } +var + SRL_Logs: Integer; + RandomPlayer, GraphicsSet, AllowPVP: Boolean; + +procedure NextPlayer(Active: Boolean); forward; +procedure RandomNextPlayer(Active: Boolean); forward; + +const + UBx1 = 279; // Username tBox - in use now + UBy1 = 180; + UBx2 = 486; + UBy2 = 190; + + PBx1 = 279; // Password tBox - in use now + PBy1 = 225; + PBx2 = 486; + PBy2 = 240; + + GBx1 = 230; // greeting box in final screen + GBy1 = 330; + GBx2 = 660; + GBy2 = 400; + + WDx1 = 88; // window box (to enter game) "click here to play" + WDy1 = 450; + WDx2 = 545; + WDy2 = 473; + + WHITE_TEXT = 16777215; // white text color + MESSAGE_BOX = 11452366; // The "helpful message" box color + INFO_BOX = 7428416; // Blue information box color + LOGIN_COLOR = 6865381; // Login button color + ERROR_BOX = 2044518; // Error box (comes up on incorrect pw/un or banned acc + +const //GetScreen + LOGIN_TA_X1 = 210; //Text check area + LOGIN_TA_Y1 = 54; + LOGIN_TA_X2 = 556; + LOGIN_TA_Y2 = 228; + + LOGIN_TEXTCOLOUR = 12378347; //Colour of text + + + +(* +LobbyScreen +~~~~~~~~~~~ + +.. code-block:: pascal + + function LobbyScreen: Boolean; + +Returns true if we are at the Lobby Screen + +.. note:: + + by IceFire908 & Bionicle1800 + +Example: + +.. code-block:: pascal + + // wait for the Lobby Screen to appear! + while (not LobbyScreen) do + Wait(100 + Random(400)); + +*) +function LobbyScreen: Boolean; +begin + Result := InRange(GetLobbyTab, L_PlayerInfo, L_Options); +end; + +(* +TakeIPScreen +~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure TakeIPScreen(); + +Saves a screenshot of the last logged in IP address to the SRL logs folder. + +.. note:: + + by Harry & Coh3n + +Example: + +.. code-block:: pascal + + TakeIPScreen(); +*) +procedure TakeIPScreen(); +var + tmpPath: string; +begin + if ((not lobbyScreen()) or (SRL_DisableIPLog)) then + exit; + + tmpPath := SRL_SavePath; + SRL_SavePath := tmpPath + 'IPLogs/'; // so TakeScreen saves to the right directory + + takeScreen('IP Log'); + + SRL_SavePath := tmpPath; // reset +end; + +(* +RSReady +~~~~~~~ + +.. code-block:: pascal + + function RSReady: Boolean; + +Returns true if we are ready to auto (on loginscreen or logged in). +Useful for waiting until RS has fully loaded. + +.. note:: + + by ZephyrsFury - Edited by [J]ustin + +Example: + +.. code-block:: pascal + + while (not RSReady) do + SleepAndMoveMouse(100 + Random(500)); + +*) +function RSReady: Boolean; +var + x, y: Integer; +begin + Result := (LoggedIn) or (LobbyScreen); + if (not Result) then + begin + ImageResetClientArea; + Result := (GetColor(745, 17) = 16645629) or FoundBar; // X button in top right && Navigation Bar. + SRL_ResetNavBar; + end; + if (GetColor(755, 43) = 16645629) then // X button on resizeable client + begin + WriteLn('You are using the "Resizeable" screen option in RS.'); + WriteLn('Changing to "Fixed" screen option.'); + Mouse(735, 44, 2, 2, mouse_Left); + Wait(600 + Random(800)); + if FindBitMapToleranceIn(SRL_OPTIONS_BITMAP, x, y, 130, 40, 640, 265, 5) then + begin + Mouse(200, 270, 5, 5, mouse_Left); //Fixed button + Wait(1200 + Random(1200)); //Wait while the screen changes + Mouse(621, 71, 3, 3, mouse_Left); //Close the Options interface + Wait(600 + Random(240)); + end + else + begin + WriteLn('Unable to find Options Screen.'); + WriteLn('Please manually change to "Fixed" screeb size'); + TerminateScript; + end; + end; + if (FindBitMapToleranceIn(SRL_OPTIONS_BITMAP, x, y, 130, 40, 640, 265, 5)) then + begin + Writeln('Failed to close Options Interface. Please report on Villavu Forum'); + TerminateScript; //Failsafe if we fail to close the Interface for some reason + end; +end; + +(* +Login_SetAudio +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure Login_SetAudio(Volume, SFX, Area: Integer; SMSetting: TSMSetting); + +Sets audio options through the login screen. +Use: Enter the desired Setting for the desired Option. Make option 0 for no change. + +.. note:: + + by ZephyrsFury, fixed by Markus + +Example: + +.. code-block:: pascal + + Login_SetAudio(1, 5, 2, NoChange); + +*) +procedure Login_SetAudio(Volume, SFX, Area: Integer; SMSetting: TSMSetting); +var + II, Tx, Ty, T, AudioMask,x,y: Integer; + Pts: TIntegerArray; +begin + if (LoggedIn) then Exit; + AudioMask := BitmapFromString(28, 3, 'beNrLyMAKGBgYJ85Y' + //gfx slice but too lazy + 'dOfmw4VrdgPZaFJAdOniSSDacug8miwuAFSWWVAJVL9kzWqgsUA2X' + // to fuck this entire function around + 'CPENKBUZXs3BBFjJsRAoPPguoAOhhsLJCEGerjZQRxsbaaFbgQAUH' + + 'JlGA=='); + TypeByte(vk_Escape); + T := GetSystemTime; + while (not(FindBitmapToleranceIn(AudioMask, X, Y, 717, 458, 760, 498, 10))) and (GetSystemTime - T < 5000) do + Wait(100); + if (FindBitmapToleranceIn(AudioMask, X, Y, 717, 458, 760, 498, 10)) then + Mouse(X, Y, 20, 20, mouse_left) + else + begin + FreeBitmap(AudioMask); + Exit; + end; + Wait(100); + Pts := [Volume, SFX, Area]; + for II := 0 to 2 do + begin + if (Pts[II] = 0) then Continue; + if (not(InRange(Pts[II], 0, 5))) then + begin + srl_Warn('Login_SetAudio', 'Points must be between 0 and 5', warn_AllVersions); + Continue; + end; + if Pts[II] = 1 then Tx:=32 else + //Tx := 337 + Round((425 - 337) * (Pts[II] - 1) / 4); + Tx := 319 * (PTS[II] - 1) * 32; //why do hard if we can do easy -.- + Ty := round(II * 22.5) + 397; { I THINK this is the formula, but I don't care. } + { Ty := //Round(3.5 * II * II + 46.5 * II + 245);} + if (GetColor(Tx, Ty) = 1315860) then + Mouse(Tx - 10, Ty - 0, 10, 5, mouse_left); {bit of randomness never hurts } + Wait(50); + end; + if (GetColor(527, 433) = 4473924) and (SMSetting = Mono) then //if set at stereomode + Mouse(527, 433, 10, 10, mouse_left) + else + if (GetColor(527, 411) = 499676) and (SMSetting = Stereo) then + Mouse(527, 411, 10, 10, mouse_left); + Wait(100); + TypeByte(vk_Escape); + FreeBitmap(AudioMask); +end; + +(* +Login_SetGraphics +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure Login_SetGraphics(Brightness: Integer); + +Sets graphic options in the login screen. + +.. note:: + + by ZephyrsFury, fixed by Markus + +Example: + +.. code-block:: pascal + + Login_SetGraphics(4); + +*) +procedure Login_SetGraphics(Brightness: Integer); +var + T, x, y, tx, ty, graphicsslice, i: Integer; + P: TPoint; +begin + if (LoggedIn) then Exit; + graphicsslice := BitmapFromString(28, 3, 'beNrLyMAKGBgYJ85Y' + + 'dOfmw4VrdgPZaFJAdOniSSDacug8miwuAFSWWVAJVL9kzWqgsUA2X' + + 'CPENKBUZXs3BBFjJsRAoPPguoAOhhsLJCEGerjZQRxsbaaFbgQAUH' + + 'JlGA=='); + TypeByte(vk_Escape); + T := GetSystemTime; + while (not(FindBitmapToleranceIn(graphicsslice, X, Y, 717, 458, 760, 498,10))) and (GetSystemTime - T < 5000) do + Wait(100); + if (FindBitmapToleranceIn(graphicsslice, X, Y, 717, 458, 760, 498, 10)) then + Mouse(X, Y, 20, 20, mouse_left) + else + begin + FreeBitmap(graphicsslice); + Exit; + end; + Wait(100); + if not (GetColor(340, 115) = SM_Color) then + for i := 0 to 2 do + begin + //Checks for the green arrow, clicks middle of box + Mouse(260, 162, 5, 5, mouse_left); + if WaitColor(340, 115, SM_Color, 0, 2000) then + Break; + if i = 2 then + begin + srl_Warn('SetGraphics', 'Failed to select Safe Mode', warn_Warning); + Exit; + end; + end; + if (Brightness > 4) then + srl_Warn('Login_SetGraphics', 'Brightness must be between 0 and 4', warn_AllVersions) + else + if (Brightness <> 0) then + begin + x := 0; + repeat + P := Point(328 + (Brightness-1) * 32, 222);//coords of some thing + if (GetColor(P.x, P.y) = 1315860) then + begin + Mouse(P.x, P.y, 3, 3, mouse_left); + if WaitColor(P.x, P.Y, 3976149, 1, 1000) then + break; + Inc(x); + end else + break; + until(x >= 5) + end; + repeat + if FindColor(x, y, 14790912, 361,234, 673,373) then //wtf is this + begin + Mouse(x + 10, y + 3, 10, 7, mouse_left); + getmousepos(tx, ty); + Mouse(tx, ty + 10, 4, 4, mouse_left); + wait(300); + end; + until(not(FindColor(x, y, 14790912, 361,234, 673,373))); + Wait(100); + TypeByte(vk_Escape); + FreeBitmap(graphicsslice); +end; + +(* +SetAudioOff +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SetAudioOff; + +Sets the Audio to off (1 for each bar). Works logged in and out. + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + + // sounds are annoying, let's turn them off + setAudioOff(); +*) +procedure SetAudioOff; +begin + if (LoggedIn) then + SetAudio(1, 1, 1, NoChange) + else + Login_SetAudio(1, 1, 1, NoChange); +end; + +(* +SetAutoingDefaults +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SetAutoingDefaults; + +Sets the graphic options for best SRL compatibility. Works both logged in and out. + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + + procedure SetupScript(); + begin + SetAutoingDefaults(); // set the graphics options appropriately + end; + +*) +procedure SetAutoingDefaults; +begin + if (LoggedIn) then + FixGraphics + else + Login_SetGraphics(4); +end; + +(* +ValidEmail +~~~~~~~~~~ + +.. code-block:: pascal + + function ValidEmail: Boolean; + +Recognizes and handles the "Validate Email" screen in RS. + +.. note:: + + by NCDS + +Example: + +.. code-block:: pascal + + if not ValidEmial then + writeLn('Failed to get past verification screen'); + +*) +function ValidEmail: Boolean; +begin + while (getColor(473, 418) = 1001495) do + begin + //writeln('found email screen'); + MouseBox(502, 424, 548, 435, mouse_left); + waitFunc(@lobbyScreen, 75, 3000); + end; + result := lobbyScreen; +end; + +(* +ExitToLobby +~~~~~~~~~~~ + +.. code-block:: pascal + + function ExitToLobby: Boolean; + +Exits to the Lobby (for breaks?) + +.. note:: + + by Starblaster100, Raymond, IceFire908, & Tarajunky + +Example: + +.. code-block:: pascal + + // world switch! + if (ExitToLobby()) then + SelectWorld(20); // parameters here may be inaccurate + +*) +function ExitToLobby: Boolean; +var + x, y, c, i: Integer; +begin + Result := LobbyScreen; + if Result = True then + Exit; + if SRL_HasProc(srl_OnExitToLobby) then + SRL_Procs[srl_OnExitToLobby](); + if (not (GameTab(tab_LogOut))) then + Exit; + Wait(200 + Random(100)); + while (LoggedIn) and (c < 10) do + begin + Inc(c); + if(FindText(x, y, 'obb', UpCharsEx, MIX1, MIY1, MIX2, MIY2))then + begin + MouseBox(566, 346, 715, 373, mouse_left); + for i := 0 to 10 do + begin + Wait(1000); + if (not LobbyScreen) then + if validEmail then + begin + Result := True; + Exit; + end; + end; + end else + if(FindText(x, y, 'lick', UpCharsEx, MIX1, MIY1, MIX2, MIY2))then + begin + MouseBox(579, 367, 699, 386, mouse_left); + for i := 0 to 10 do + begin + Wait(1000); + if not(LoggedIn) then + begin + Result := True; + SRL_ResetNavBar; + Exit; + end; + end; + end + end; +end; + +(* +LeaveLobby +~~~~~~~~~~ + +.. code-block:: pascal + + function LeaveLobby: Boolean; + +Logs you out from lobby screen. + +.. note:: + + by IceFire908 + +Example: + +.. code-block:: pascal + + if (LobbyScreen()) then + if (not LeaveLobby()) then + WriteLn('Oh no, we didn''t make it out of the Lobby Screen.'); + +*) +function LeaveLobby: Boolean; +var + T: LongInt; +begin + T := GetSystemTime; + while ((not (Result)) and ((GetSystemTime - T) < 30000)) do + begin + MouseBox(678, 24, 699, 43, mouse_left); + Wait(RandomRange(1000, 2000)); + Result := (not (LobbyScreen)); + SRL_ResetNavBar; + end; +end; + +(* +Logout +~~~~~~ + +.. code-block:: pascal + + function Logout: Boolean; + +Logs you all the way out from ingame. + +.. note:: + + by Starblaster100, Raymond, IceFire908, Tarajunky & NCDS + +Example: + +.. code-block:: pascal + + if (not FindTree()) then + Logout(); + +*) +function Logout: Boolean; +var + x, y, c, i: Integer; +begin + SRL_ExitedSquealOfFortune := false; + + Result := (not (LoggedIn)); + if (Result) then + Exit; + if SRL_HasProc(srl_OnLogOut) then + SRL_Procs[srl_OnLogOut](); + if (not (GameTab(tab_LogOut))) then + begin + CloseWindow(); + if (not (GameTab(tab_LogOut))) then + Exit; + end; + Wait(200 + Random(100)); + while (LoggedIn) and (c < 10) do + begin + Inc(c); + if(FindText(x, y, 'ogin', UpCharsEx, MIX1, MIY1, MIX2, MIY2))then + MouseBox(569, 393, 713, 418, mouse_left) + else + if(FindText(x, y, 'lick', UpCharsEx, MIX1, MIY1, MIX2, MIY2))then + MouseBox(569, 349, 713, 375, mouse_left); + + for i := 0 to 10 do + begin + Wait(1000); + if not(LoggedIn) then + begin + Result := True; + SRL_ResetNavBar; + Exit; + end; + end; + end; +end; + +(* +LoginPlayerToLob +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function LoginPlayerToLob: Boolean; + +Like LoginPlayer but only to the lobbyscreen. + +.. note:: + + by SRL Dev Team + +Example: + +.. code-block:: pascal + + LoginPlayerToLob(); + if (not LobbyScreen()) then + LoginPlayerToLob(); // try again! + +*) +function LoginPlayerToLob: Boolean; +var + RetryLogin: Boolean; + typtmp, t, w: integer; + Actions: TVariantArray; + Attempts: LongInt; + p: TPoint; + //ATPA: T2dPointArray; + TPA: TPointArray; + Boxes : TIntegerArray; + //B: TBox; +label + ProcStart; +begin + ActivateClient; + Wait(100); + TypeByte(vk_Escape); + Wait(500); + + {Check for lobby screen already open/ already logged in} + + Result := ((LobbyScreen) or (LoggedIn)); + if (Result) then + Exit; + + {Check for active player.} + + if (not (Players[CurrentPlayer].Active)) then + begin + WriteLn('Player is not Active...'); + if (AllPlayersInActive) then + begin + WriteLn('All players not active!'); + Exit; + end; + NextPlayer(False); + Exit; + end; + + {Wait for the client to finish loading.} + + T := GetSystemTime; + repeat + if (RSReady) then + Break; + if ((GetSystemTime - T) > 180000) then + begin + WriteLn('It has been 3 minutes and Runescape is not yet ready... Terminating.'); + TerminateScript; + end; + Wait(RandomRange(1000, 2000)); + until (False); + WriteLn('Welcome to Runescape.'); + + + {New graphics have changed box} + Case CountColor(LOGIN_TEXTCOLOUR, 198, 192, 567, 259) of + 1079: MouseBox(347, 295, 414, 303, mouse_left); + 1745: MouseBox(347, 305, 414, 312, mouse_left); { "Available graphics options have been changed..." } + 1801: MouseBox(347, 305, 414, 312, mouse_left); { "There was a problem with your current graphics settings..." } + end; + + {Click less info if needed.} + { + if (not (SimilarColors(GetColor(382, 11), 14285562, 20))) then //Runescae sword green bead + begin + MouseBox(212, 479, 550, 495, 1); //Less info button + Wait(RandomRange(1000, 2000)); + end; + } + {Click Members/free.} + + {Members := Players[CurrentPlayer].Member; + if (Length(Players[CurrentPlayer].WorldInfo) > 0) then + Members := Players[CurrentPlayer].WorldInfo[0]; } + + ProcStart: + + {if (Members) then + I := 1; + + if (GetColor(248, 359) <> 1381653) then //Black outline on forgotten pwd button. + begin + FindColors(TPA, 9291999, 10, 370, 675, 475); + ATPA := SplitTPA(TPA, 4); + if (Length(ATPA) > 2) then + begin + if (I = 1) then + I := 0 + else + I := 1; + B := GetTPABounds(ATPA[1 + I]); //If demo mode is still up + end + else + if (Length(ATPA) = 2) then + B := GetTPABounds(ATPA[0 + I]) //When there's no demo mode + else + B := IntToBox(210, 424, 367, 446); + + with B do + MouseBox(X1 + 20, Y1 + 10, X2 - 20, Y2 + 8, 1); + + T := GetSystemTime; //Black outline on forgotten pwd button. + while ((GetSystemTime - T < 3000) and (GetColor(248, 359) <> 1381653)) do + Wait(RandomRange(100, 200)); + + end; } + + {Type in username and pass} + + if (loggedIn) then + exit; + + for W:= 0 to 1 do + begin + if W = 0 then + Boxes:= [UBX1, UBY1, UBX2, UBY2] + else + Boxes:= [PBX1, PBY1, PBX2, PBY2]; + + t := (getSystemTime + (60000 * 2)); + FindColors(TPA, LOGIN_TEXTCOLOUR, Boxes[0], Boxes[1], Boxes[2], Boxes[3]); + repeat + if (Length(TPA) > 0) then + begin + SortTPAFrom(TPA, Point(Boxes[2], Boxes[1] + (Boxes[3] - Boxes[2]) div 2)); + p := point(TPA[0].X + 20, TPA[0].Y); + if (not pointInBox(p, intToBox(Boxes[0], Boxes[1], Boxes[2], Boxes[3]))) then + p := point(UBX2 - (10 + random(10)), p.y); + Mouse(p.x, p.y, 5, 5, mouse_left); + end else + MouseBox(Boxes[0], Boxes[1], Boxes[2], Boxes[3], mouse_left); + + typtmp := 0; + while (CountColor(LOGIN_TEXTCOLOUR, Boxes[0], Boxes[1], Boxes[2], Boxes[3]) > 0) do + begin + Inc(typtmp); + TypeByte(VK_BACK); + Wait(50+Random(50)); + if (typtmp >= RandomRange(20, 24)) then + Break; + end; + until(not FindColors(TPA, LOGIN_TEXTCOLOUR, Boxes[0], Boxes[1], Boxes[2], Boxes[3]) or (getSystemTime > t)); + + Wait(100 + Random(200)); + if W = 0 then + begin + WriteLn(Capitalize(Players[CurrentPlayer].Name)); + TypeSend(Players[CurrentPlayer].Name); + end else + TypeSend(Players[CurrentPlayer].Pass); + Wait(800 + Random(50)); //Should fix the Login -> Spam Recoveries bug + end; + + {Check responses} + + T := GetSystemTime; + repeat + // so the lobby appears (gets rid of black screen) + if (countColorTolerance(clBlack, 0, 0, 500, 500, 20) > 245000) then + begin + wait(2000 + random(1500)); + mouseBox(0, 0, 750, 490, mouse_Move); + end; + SRL_ResetNavBar; + result := validEmail; // To handle "Validate Email" screen + if result then + break; + + SetLength(Actions, 0); + + if ((GetSystemTime - T) > 60000) then + Actions := ['One minute has passed... Debug: ' + ToStr(CountColor(LOGIN_TEXTCOLOUR, 260, 140, 510, 400)), 0, 5, 'PlayerFalse', 'Login Failed'] + else + case (CountColor(LOGIN_TEXTCOLOUR, 260, 140, 510, 400)) of //text colour points + // WriteLn Error Wait for Retrys Action Player[CurrentPlayer].Loc + 763, 2348, 2299: + Actions := ['Invalid Username / Password', 0, 2, 'PlayerFalse', 'Wrong User/Pass']; + 1088: Actions := ['Your account has been disabled', 0, 0, 'PlayerFalse', 'Acc Disabled']; + 951: Actions := ['Your account is already logged in', 5000, 5, 'PlayerTrue', 'Already logged in']; + 1239: Actions := ['Not a Members Account', 0, 1, 'PlayerTrue', '']; + 364: Actions := ['Error Connecting.', 20000, 9, 'Terminate', 'Error Connecting']; + 1057: Actions := ['Too many incorrect logins.', 5 * 60000, 2, 'PlayerFalse', 'Too many logins']; + 732: Actions := ['Runescape has been updated.', 0, 0, 'RSUpdate', 'RS Updated']; + 591: Actions := ['Client token changed.', 0, 0, 'RSUpdate', 'Client Token Changed']; + 1606: Actions := ['Game session expired.', 0, 0, 'RSUpdate', 'Session Expired']; + 777: Actions := ['Login limit exceeded.', 20000, 10, '', 'Waiting for login.']; + end; + {Respond} + + if (Length(Actions) > 0) then + begin + WriteLn(Actions[0]); + if (Actions[0] <> 'Not a Members Account') then + begin + Wait(1000 + Random(500)); + TypeByte(vk_Escape); + end; + Wait(Actions[1] + Random(100)); + if (Actions[2] <> 0) then + if (Attempts < Actions[2]) or (Actions[2] = -1) then + begin + if (Actions[0] = 'Not a Members Account') then + begin + Players[CurrentPlayer].Member := False; + if (Length(Players[CurrentPlayer].WorldInfo) > 0) then + Players[CurrentPlayer].WorldInfo[0] := False; + MouseBox(267, 321, 496, 350, mouse_left); //Play free game instead button + Wait(3000 + Random(2000)); + Result := True; + Exit; + end; + RetryLogin := True; + Wait(2000 + Random(1000)); + Break; + end; + if (Actions[4] <> '') then + Players[CurrentPlayer].Loc := Actions[4]; + case Actions[3] of + 'PlayerFalse': NextPlayer(False); + + 'PlayerTrue': + begin + LeaveLobby(); + NextPlayer(True); + end; + + 'Terminate': TerminateScript; + + 'RSUpdate': + begin + if SRL_HasProc(srl_OnRSUpdate) then + begin + case actions[0] of + 'Runescape has been updated.': + begin + Writeln('Runescape has been updated! Waiting 5 minutes to restart SMART!'); + Wait(300000); + end; + end; + SRL_Procs[srl_OnRSUpdate](); + Exit; + end; + Writeln('Runescape has been updated! Please restart Simba.'); + TerminateScript; + end; + end; + Exit; + end; + Wait(100); + Result := (LobbyScreen) or (LoggedIn); + until (Result); + + TakeIPScreen(); + + {Back to main screen if needed} + + if (RetryLogin) then + begin + RetryLogin := False; + Inc(Attempts); + goto ProcStart; + end; + +end; + +(* +LoginPlayer +~~~~~~~~~~~ + +.. code-block:: pascal + + function LoginPlayer: Boolean; + +Logs in the Player[CurrentPlayer]. Detects most Client Login Errors + +.. note:: + + by SRL Dev Team + +Example: + +.. code-block:: pascal + + if (not LoggedIn()) then + begin + WriteLn('Error: Not Logged In! Fixing'); + LoginPlayer(); + end; + +*) +function LoginPlayer: Boolean; +var + RetryLogin: Boolean; + Actions: TVariantArray; + T, Attempts: LongInt; +label + ProcStart; +begin + ProcStart: + + if (not (Result)) then {Check if Logged in} + Result := LoggedIn; + + if (Result) then + begin + Result := True; + AddToSRLLog('Current player: ' + Capitalize(Players[CurrentPlayer].Name)); + SRL_ExitedSquealOfFortune := false; + PlayerStartTime := GetSystemTime; // PlayerStartTime + if SRL_HasProc(srl_OnLogIn) then + SRL_Procs[srl_OnLogIn](); + + Exit; + end; + + if (not (LoginPlayerToLob)) then {Get to lobby screen} + Exit; + + Wait(500 + Random(500)); + {World switching} + + if Length(Players[CurrentPlayer].WorldInfo) > 0 then + if VariantIsBoolean(Players[CurrentPlayer].WorldInfo[0]) then + Players[CurrentPlayer].Member:= Players[CurrentPlayer].WorldInfo[0]; + + case Length(Players[CurrentPlayer].WorldInfo) of + 1: + if VariantIsInteger(Players[CurrentPlayer].WorldInfo[0]) then + SelectWorld(Players[CurrentPlayer].WorldInfo[0]); + + 2: + SelectWorld(Players[CurrentPlayer].WorldInfo[1]); + + 3: + if (Players[CurrentPlayer].WorldInfo[1] = 0) then + SelectWorld(RandomWorld(Players[CurrentPlayer].WorldInfo[0], Players[CurrentPlayer].WorldInfo[2])) + else + SelectWorld(Players[CurrentPlayer].WorldInfo[1]); + end; + {Click Here to Play} + + if (LobbyScreen) then + MouseBox(270, 450, 490, 470, mouse_left); + + {Check responses} + + T := GetSystemTime; + repeat + + SetLength(Actions, 0); + if ((GetSystemTime - T) > 60000) then + Actions := ['One minute has passed... Debug: ' + ToStr(CountColor(LOGIN_TEXTCOLOUR, 260, 140, 510, 400)), 0, 0, 'NextPlayer', 'Login Failed'] + else + case (CountColor(LOGIN_TEXTCOLOUR, 260, 140, 510, 400)) of //text colour points + // WriteLn Error Wait for Retrys Action Player[CurrentPlayer].Loc + 364: Actions := ['Error Connecting.', 20000, 9, 'Terminate', 'Error Connecting']; + 850: Actions := ['You need skill total of 1000.', 0, 9, 'PlayerTrue', '1000 skill club']; + 1028: Actions := ['You are standing in a members-only area.', 0, 1, 'PlayerFalse', 'In Mems-Only Area']; + 1239: Actions := ['Not a Members Account', 0, 1, 'PlayerFalse', 'Non-member']; + 777: Actions := ['Login limit exceeded.', 0, 10, '', 'Waiting for login.']; + 951: Actions := ['Your account is already logged in', 5000, 5, 'PlayerTrue', 'Already logged in']; + 591: Actions := ['Client token changed.', 0, 0, 'RSUpdate', 'Client Token Changed']; + 1606: Actions := ['Game session expired.', 0, 0, 'RSUpdate', 'Session Expired']; + -1: Actions := ['You need skill total of 1500.', 0, 9, 'PlayerTrue', '1500 skill club']; + -1: Actions := ['You need 20 combat for PvP', 0, 1, 'PlayerFalse', 'PvP warning']; + end; + + if (CountColor(clWhite, 415, 336, 476, 356) = 82) then // HRW login button white colour points + begin + Wait(RandomRange(500, 1000)); + if (Length(Players[CurrentPlayer].WorldInfo) > 2) then + begin + if (Players[CurrentPlayer].WorldInfo[2]) then + MouseBox(391, 361, 498, 383, mouse_left) + else begin + MouseBox(263, 362, 372, 383, mouse_left); + Players[CurrentPlayer].WorldInfo := [False, 0, AllowPVP]; + RetryLogin := True; + Break; + end; + end + else + if (AllowPVP) then + MouseBox(391, 361, 498, 383, mouse_left) + else + MouseBox(263, 362, 372, 383, mouse_left); + Wait(3000 + Random(2000)); + RetryLogin := true; + end; + + {Respond} + + if (Length(Actions) > 0) then + begin + WriteLn(Actions[0]); + Wait(Actions[1] + Random(100)); + if (Actions[2] <> 0) then + if (Attempts < Actions[2]) or (Actions[2] = -1) then + begin + case Actions[0] of + 'You are standing in a members-only area.': begin + Players[CurrentPlayer].Member := True; + Players[CurrentPlayer].WorldInfo := [True, 0, AllowPVP]; + end; + 'You need 20 combat for PvP': Players[CurrentPlayer].WorldInfo := [Players[CurrentPlayer].Member, 0, False]; + 'Not a Members Account': begin + Players[CurrentPlayer].Member := False; + Players[CurrentPlayer].WorldInfo := [False, 0, AllowPVP]; + end; + 'Login limit exceeded.': begin + Writeln('Runescape is lagging or we''re logged in too many times. Keep trying!'); + Players[CurrentPlayer].WorldInfo := [players[currentPlayer].member, 0, AllowPVP]; + Wait(5000+Random(10000)); + end; + 'You need skill total of 1000.': players[currentPlayer].worldInfo := [players[currentPlayer].member, 0, allowPVP]; + end; + RetryLogin := True; + Wait(2000 + Random(1000)); + Break; + end; + if (Actions[4] <> '') then + Players[CurrentPlayer].Loc := Actions[4]; + case Actions[3] of + 'PlayerFalse': NextPlayer(False); + 'PlayerTrue': + begin + LeaveLobby(); + NextPlayer(True); + end; + 'Terminate': TerminateScript; + 'RSUpdate': + begin + wait(randomRange(1000, 1500)); + typeByte(VK_ESCAPE); + leaveLobby(); + + if SRL_HasProc(srl_OnRSUpdate) then + begin + SRL_Procs[srl_OnRSUpdate](); + Exit; + end; + Writeln('Runescape has been updated! Please restart Simba.'); + TerminateScript; + end; + end; + Exit; + end; + Wait(100); + Result := (LoggedIn); + until (Result); + + {Back to lobby screen if needed} + + if (RetryLogin) then + begin + RetryLogin := False; + Inc(Attempts); + goto ProcStart; + end; + + {Set player start time ect...} + + if (Result) then + goto ProcStart; + +end; + +(* +NextPlayerIndex +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function NextPlayerIndex: Integer; + +Returns the player number of the next active player. + +.. note:: + + by Dankness, Ron, Raymond & ZephyrsFury + +Example: + +.. code-block:: pascal + + if (NextPlayerIndex() != -1) then + WriteLn('We still have active players!'); + +*) +function NextPlayerIndex: Integer; +begin + if (AllPlayersInactive) then + begin + Result := -1; + Exit; + end; + Result := (CurrentPlayer + 1) mod Length(Players); + while (Players[Result].Active = False) do + Result := (Result + 1) mod Length(Players); +end; + +(* +RandomPlayerIndex +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function RandomPlayerIndex: Integer; + +Returns the player number of a random active player. + +.. note:: + + by Dankness, Ron, Raymond & ZephyrsFury + +Example: + +.. code-block:: pascal + + procedure NextPlayerRandom(Active: Boolean); + begin + Players[CurrentPlayer].Active := Active; + CurrentPlayer := RandomPlayerIndex(); + if (CurrentPlayer = -1) then + begin + WriteLn('All players inactive..'); + TerminateScript(); + end; + end; + +*) +function RandomPlayerIndex: Integer; +var + N: Integer; +begin + if (AllPlayersInactive) then + begin + Result := -1; + Exit; + end; + N := Random(Length(Players)); + while (Players[N].Active = False) or (N = CurrentPlayer) do + begin + if (PlayersActive = 1) and (N = CurrentPlayer) then Break; + N := Random(Length(Players)); + end; + Result := N; +end; + +(* +SwitchToPlayer +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function SwitchToPlayer(PlayerNo: Integer; Active: Boolean): Boolean; + +Switches to a specific player, setting the current player's activity to True or False. + +.. note:: + + by Dankness, Ron, Raymond & ZephyrsFury + +Example: + +.. code-block:: pascal + + SwitchToPlayer(1, True); + +*) +function SwitchToPlayer(PlayerNo: Integer; Active: Boolean): Boolean; +begin + WriteLn('SwitchToPlayer(PlayerNo: ' + IntToStr(PlayerNo) + ', Active: ' + BoolToStr(Active)+ ');'); + Players[CurrentPlayer].Active := Active; + Logout; + if SRL_HasProc(srl_OnNextPlayer) then + SRL_Procs[srl_OnNextPlayer](); + PlayerCurTime := GetSystemTime; + Players[CurrentPlayer].Worked := Players[CurrentPlayer].Worked + (PlayerCurTime - PlayerStartTime); + CurrentPlayer := PlayerNo; + SRL_Logs := SRL_Logs + 1; + LoginPlayer; + Result := LoggedIn; +end; + +(* +NextPlayer +~~~~~~~~~~ + +.. code-block:: pascal + + procedure NextPlayer(Active: Boolean); + +Logs in the next player that isn't inactive. +Boolean: True - Current player is ok. False - Current player is false. + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + + NextPlayer(True); + +*) +procedure NextPlayer(Active: Boolean); +var + srl_PlayerIndexFunc: function: Integer; + cP: Integer; +begin + if (RandomPlayer) then + srl_PlayerIndexFunc := @RandomPlayerIndex + else + srl_PlayerIndexFunc := @NextPlayerIndex; + + WriteLn('NextPlayer(' + BoolToStr(Active) + ')'); + LogOut; + cP := srl_PlayerIndexFunc(); + while (cP = -1) do + begin + cP := srl_PlayerIndexFunc(); + if SRL_HasProc(srl_InNextPlayerLoop) then + SRL_Procs[srl_InNextPlayerLoop](); + Wait(5000); //Endless loop + end; + + SwitchToPlayer(cP, Active); +end; + +(* +RandomNextPlayer +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure RandomNextPlayer(Active: Boolean); + +Logs in a random player that isn't inactive. +Boolean: True - Current player is ok. False - Current player is false. + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + + RandomNextPlayer(True); + +*) +procedure RandomNextPlayer(Active: Boolean); +var + tmpBool: Boolean; +begin + tmpBool := RandomPlayer; + RandomPlayer := True; + NextPlayer(Active); + RandomPlayer := tmpBool; +end; + +(* +CheckUserNicks +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure CheckUserNicks; + +Checks if all nicks are set correct. + +.. note:: + + by Sumilion, Raymond, and Nava2 + +Example: + +.. code-block:: pascal + + // make sure the user setup their nicks right.. + CheckUserNicks(); + +*) + +// TODO: Remove? Not used? +procedure CheckUserNicks; +var + I, II: Integer; + Wrong, FWrong: Boolean; + WarnStrings: TStringArray; +begin + WarnStrings := ['Please fill in your nickname.', + 'Your nickname isn'' found in the players name']; + + for i := 0 to HowManyPlayers - 1 do + for II := 0 to 1 do + begin + case II of + 0: Wrong := (Players[i].Nick = ''); + 1: Wrong := (Pos(Players[i].nick, Capitalize(Players[i].name))<1); + end; + + if Wrong then + begin; + Writeln('--'); + Writeln('WARNING: ' + WarnStrings[II] + ' with player: ' + Players[i].Name); + FWrong := True; + end; + end; + + if FWrong then + begin + Writeln(''); + Writeln('For more information, visit http://www.villavu.com/forum/showthread.php?t=5410'); + end; +end; diff --git a/SRL/core/mapwalk.simba b/SRL/core/mapwalk.simba new file mode 100644 index 0000000..616712b --- /dev/null +++ b/SRL/core/mapwalk.simba @@ -0,0 +1,1507 @@ +(* +Mapwalk +======= + +The Mapwalk include contains all Mapwalking functions + +.. contents:: + +*) + +(* +RoadColors +~~~~~~~~~~ + +.. code-block:: pascal + + var RoadColors: TIntegerArray; + +Global record containing all roadcolors collected during runtime. + +.. note:: + + by SRL Dev Team +*) + +{******************************************************************************* +var RoadColors: TIntegerArray; +Description: Global record containing all roadcolors collected during runtime. +*******************************************************************************} +var + RoadColors: TIntegerArray; + +(* +variantDirection +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function variantToDirection(dir: Variant): Extended; + +Converts a variant to a direction, catching errors and attempts to fix. This +function expects "compass relative" angles. For example: ('n', 's', 'e', 'w') or +degree (23.3, 25, 205.2) or 'random' (returns 0..360). + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + + dir := variantToDirection('n'); // -> 0.0 + dir := variantToDirection('rand'); // -> in range 0..360 + dir := variantToDirection(50); // -> 50 + +*) +function variantToDirection(dir: Variant): Extended; +var + e: Extended; +begin + if VariantIsNumber(dir) then + Result := FixD(dir + 0.0) + else if VariantIsString(dir) then + case LowerCase(dir) of + 'n': Result := 0; + 'e': Result := 90; + 's': Result := 180; + 'w': Result := 270; + 'random', 'rand': Result := RandomRange(0, 360); + else + begin + e := StrToFloatDef(dir, -1337); + if (e <> -1337) then + Result := FixD(e) + else + begin + srl_Warn('variantToDirection', + 'dir [' + toStr(dir) +'] invalid. Returned 0.0 for safety', + warn_AllVersions); + Result := 0.0; + end; + end; + end; +end; + +(* +MakeCompass +~~~~~~~~~~~ + +.. code-block:: pascal + + function MakeCompass(Direction: Variant): Boolean; + +Aligns RS to specified direction + - Enter a compass angle ('n', 's', 'e', 'w') or degree (23.3, 25, 205.2) + and it will move the compass to that angle. Also accepts 'random', + and 'rand' to make the compass a random direction. + +.. note:: + + by Nielsie95 & Nava2 + +Example: + +.. code-block:: pascal + + // using a string! + MakeCompass('N'); + + // using an integer! + MakeCompass(0); + +*) + +// Helper function for MakeCompass to clean up code +// Compares Angle and DirectionDeg to see how far away it is +function __MakeCompass_MinCheck(Angle, DirectionDeg: Extended): Extended; +begin + // TODO: Check if FixD could be used to remove some cases.. + Result := MinE(Abs(Angle - (DirectionDeg + 360)), Abs((Angle + 360) - DirectionDeg)); + Result := MinE(Abs(Angle - DirectionDeg), Result); +end; + +function MakeCompass(Direction: Variant): Boolean; +var + StartAngle, Angle, DirectionDeg, i: Extended; + Left: Boolean; + Mark: Integer; +begin + Result := False; + StartAngle := (rs_GetCompassAngleDegrees); + if ((StartAngle < 0) or (not LoggedIn)) then Exit; + + // convert from variant to direction: + DirectionDeg := variantToDirection(Direction); + + if (__MakeCompass_MinCheck(StartAngle, DirectionDeg) <= 8.0) then + begin + Result := True; + Exit; + end; + Left := (Round((360 - StartAngle) + DirectionDeg) mod 360 <= Round((StartAngle + 360) - DirectionDeg) mod 360); + KeyDown((Ord(not Left) * 2) + 37); + Wait(10); + MarkTime(Mark); + i := 0.0; + repeat + Wait(16); + Angle:= rs_GetCompassAngleDegrees; + if (((TimeFromMark(Mark) > 6000) and (i < 1.0)) or + ((TimeFromMark(Mark) > 10000) and (i < 2.0)) or + ((TimeFromMark(Mark) > 14000) and (i < 3.0))) then + begin + i := i + 1.0; + end; + // TODO: simplify the maths? + until ((Angle < 0) or + (TimeFromMark(Mark) > 14000) or + (__MakeCompass_MinCheck(Angle, DirectionDeg) <= (7.0 + i))); + if Left then + KeyUp(VK_Left) + else + KeyUp(VK_Right); + Wait(10); + Result := (__MakeCompass_MinCheck(Angle, DirectionDeg) <= (7.0 + i)); +end; + +(* +SetAngle +~~~~~~~~ + +.. code-block:: pascal + + procedure SetAngle(Angle: Integer); + +Sets the mainscreen at highest\lowest angle, dependant on constant passed. + +.. note:: + + by Raymond, edit by NaumanAkhlaQ + +Example: + +.. code-block:: pascal + + // make the camera the highest! + SetAngle(True); + +*) + +// TODO: fix doc for this. +// Allows one to use ClickNorth without waiting 1s every time. +const + SRL_ANGLE_HIGH = 0; + SRL_ANGLE_LOW = 1; + SRL_ANGLE_NONE = 2; + +// TODO: Check if 1000ms wait is necessary +procedure SetAngle(Angle: Integer); +begin + if ((Angle = SRL_ANGLE_NONE) or (not LoggedIn)) then + Exit; + + KeyDown((Angle * 2) + 38); + Sleep(1000 + Random(300)); + KeyUp((Angle * 2) + 38); + Wait(500 + Random(100)); +end; + +(* +ClickNorth +~~~~~~~~~~ + +.. code-block:: pascal + + procedure ClickNorth(AngleHigh: Integer); + +Clicks the compass to make it perfect North. Will set angle at highest depending +on AngleHigh. See `SetAngle` for more information on the Angle parameter. + +.. note:: + + by R1ch + +Example: + +.. code-block:: pascal + + procedure MapWalk(); + begin + ClickNorth(SRL_ANGLE_NONE); + //... + +*) +procedure ClickNorth(AngleHigh: Integer); +begin + if (Random(4) = 1) then + begin + Mouse(542, 24, 15, 15, mouse_right); + WaitOptionMulti(['ace', 'orth'], 1200); + end else + Mouse(542, 24, 15, 15, mouse_left); + + SetAngle(AngleHigh); +end; + +{$DEFINE WALL_ANGLELEFT} + +(* +GetWallAngle +~~~~~~~~~~~~ + +.. code-block:: pascal + + Function GetWallAngle(Ps: TPointArray): Extended; + +Get's the Minimap angle using Walls. Returns Angle in Radians. +Used in Maze.scar, but feel free to use for Perfect map aligning projects. + +.. note:: + + by Wizzup? + +Example: + +.. code-block:: pascal + + + +*) +// TODO: Code example in docs +function GetWallAngle(Ps: TPointArray): Extended; +var + L, I, C: Integer; + ATPA, gATPA: T2DPointArray; + P, P2: TPoint; + B: TBox; +begin + Result := -1.0; + if High(Ps) = -1 then + Exit; + SortTPAFrom(Ps, Point((550 + 703) div 2, 0)); // Sort it from the center. + {$IFDEF WALL_ANGLELEFT} + ATPA := SplitTPAEx(Ps, 0, 1); // This turns a PointArray into + // vertical lines + {$ELSE} + ATPA := SplitTPAEx(Ps, 1, 0); //horizontal lines + {$ENDIF} + + SortATPASize(ATPA, True); // longest 'line'. + L := High(aTPA); + if L = -1 then + Exit; + + SetLength(gATPA, L + 1); + C := 1; + gATPA[0] := aTPA[0]; + P := MiddleTPA(aTPA[0]); // get middle of the line. + + for I := 1 to L do + begin // this loops adds any points that are in a dist of 10 pixels. + // if vert, then x, hori then y (A wall isn't straight.) + if Length(aTPA[I]) < 4 then + Continue; + P2 := MiddleTPA(aTPA[I]); + {$IFDEF WALL_ANGLELEFT} + if (Abs(P.X - P2.X) < 10) then + {$ELSE} + if (Abs(P.Y - P2.Y) < 10) then + {$ENDIF} + begin + gATPA[C] := aTPA[I]; + C := C + 1; + end; + end; + SetLength(gATPA, C); + SetLength(Ps, 0); + + Ps := MergeATPA(gATPA); //Combine all the points. within 10pix + B := GetTPABounds(Ps); + SortTPAFrom(Ps, Point((B.X1 + B.X2) div 2, 0)); // sort from center + + SetLength(ATPA, 0); + ATPA := SplitTPA(Ps, 3); // split dist three, the left over walls + // were all in Ps, and now we split them again. + + SetLength(Ps, 0); + SortATPASize(ATPA, True); // longest wall. + + Ps := ATPA[0]; + L := High(Ps); //angle getting + Result := ArcTan2(Ps[L].Y -Ps[0].Y, Ps[L].X - Ps[0].X) - (Pi * 0.5); + {$IFDEF WALL_ANGLELEFT} {$ELSE} Result := Result + 0.5 * Pi {$ENDIF} +end; + +(* +RunAway +~~~~~~~ + +.. code-block:: pascal + + procedure RunAway(dir: string; RunFar: Boolean; Action, WaitTime: Integer); + +- Runs away in minimap related direction, based on north. +- Dir can be 'N', 'E', 'S', 'W' or an angle in degrees (145, 93, 180, etc). +- RunFar will run further than normal. +- Action can be either 1, 2 or 3: + + 1. RunAway + Wait(WaitTime) + RunBack + 2. RunAway + Wait(WaitTime) + 3. RunBack + +.. note:: + WaitTime is in milliseconds! + +.. note:: + + by nielsie95 modified by ZephyrsFury + +Example: + +.. code-block:: pascal + + if (FindFight()) then + begin + WriteLn('We are in a fight!'); + RunAway('n', True, 1, 2000); + end; + +*) + +// TODO: Implement constants! +procedure RunAway(dir: variant; RunFar: Boolean; Action, WaitTime: Integer); +var + Rad, T: Integer; + Deg: extended; +begin + if (not LoggedIn) then exit; + + if RunFar then + Rad := 63 + else + Rad := 30; + Deg := variantToDirection(dir); + + if (Action < 3) then + begin + SetRun(True); + MFNF(Trunc(Rad * Sin(Radians(FixD(Rs_GetCompassAngleDegrees + Deg))) + MMCX + Random(5)), + Trunc(-Rad * Cos(Radians(FixD(Rs_GetCompassAngleDegrees + Deg))) + MMCY + Random(5)), 1, 1); + FFlag(0); + Wait(500 + Random(1500)); + t := GetSystemTime; + while ((GetSystemTime - t) < WaitTime) and (LoggedIn) do + if (Random(5) = 0) then + IdleTime(2000, 500, 1.0) + else + Wait((WaitTime - (GetSystemTime - t)) div 5); + end; + + if (Action = 1) or (Action = 3) then + begin + MFNF(Trunc(Rad * Sin(Radians(FixD(Rs_GetCompassAngleDegrees + (Deg + 180)))) + MMCX - Random(5)), + Trunc(-Rad * Cos(Radians(FixD(Rs_GetCompassAngleDegrees + (Deg + 180)))) + MMCY - Random(5)), 1, 1); + FFlag(0); + Wait(500 + Random(1500)); + end; + + SetRun(False); +end; + +(* +StoreToRoadColorArray +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure StoreToRoadColorArray; + +Stores RoadColor to an array. Debugging and logging purposes. + +.. note:: + + by Wizzup? / WT-Fakawi, rewritten by EvilChicken! + +Example: + +.. code-block:: pascal + + +*) + +// TODO: Depreciated? +procedure StoreToRoadColorArray; +var + Hi: Integer; +begin + if (InIntArray(RoadColors, RoadColor)) then exit; + Hi := High(RoadColors); + SetLength(RoadColors, Hi + 2); + RoadColors[Hi + 1] := RoadColor; +end; + +(* +GetOldRoadColors +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetOldRoadColors: Boolean; + +Checks if RoadColor matches with any color stored in RoadColors array. +If successful, it sets the roadcolor. + +.. note:: + + by Wizzup? / WT-Fakawi, edited by EvilChicken! + +Example: + +.. code-block:: pascal + + +*) + +// TODO: Depreciated? +function GetOldRoadColors: Boolean; +var + I, X, Y, Hi: Integer; +begin + Result := False; + Hi := High(RoadColors); + for I := 0 to Hi do + if FindColorTolerance(X, Y, RoadColors[I], MMX1, MMY1, MMX2, MMY2, 10) then + begin + RoadColor := GetColor(X, Y); + if (not InIntArray(RoadColors, RoadColor)) then + begin + SetLength(RoadColors, Hi + 2); + RoadColors[Hi + 1] := RoadColor; + end; + srl_Warn('GetOldRoadColors', 'Set RoadColor through RoadColors array.', warn_Debug); + Result := True; + Exit; + end; +end; + +(* +GetNewRoadColor +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetNewRoadColor(xs, ys, xe, ye, tol: Integer): Boolean; + +Searches for new RoadColor in box xs, ys, xe, ye by comparing all the colors found within box against current RoadColor. + +.. note:: + + by Wizzup?/WT-Fakawi, edited by Ron & EvilChicken! + +Example: + +.. code-block:: pascal + + +*) + +// TODO: Depreciated? +function GetNewRoadColor(xs, ys, xe, ye, Tol: Integer): Boolean; +var + X, Y, W, H, Bmp: Integer; + TC: TColor; + +begin + if (not LoggedIn) then exit; + if (XS > XE) then + begin + srl_Warn('GetNewRoadColor', 'Seachbox coordinates error - XS:' + IntToStr(XS) + + ', XE: ' + IntToStr(XE), warn_Warning); + Exit; + end; + if (YS > YE) then + begin + srl_Warn('GetNewRoadColor', 'Seachbox coordinates error - YS:' + IntToStr(YS) + + ', YE: ' + IntToStr(YE), warn_Warning); + Exit; + end; + + w := xe - xs; + h := ye - ys; + + try + Bmp := BitmapFromClient(xs,ys,xe,ye); + except + GetClientDimensions(w, h); + srl_Warn('RadialRoadWalk', 'An error occured. ' + 'xs: ' + IntToStr(xs) + + ', ys: ' + IntToStr(ys) + ', xe: ' + IntToStr(xe) + ', ye: ' + IntToStr(ye), warn_AllVersions); + srl_Warn('RadialRoadWalk', 'Client area is 0, 0, ' + IntToStr(w) + ', ' + + IntToStr(h), warn_AllVersions); + //FreeBitmap(Bmp); + Exit; + end; + + for Y := 0 to (H-1) do + for X := 0 to (W-1) do + begin + TC := FastGetPixel(Bmp, X, Y); + if SimilarColors(TC, RoadColor, Tol) then + begin + RoadColor := TC; + StoreToRoadColorArray; + Result := True; + FreeBitmap(Bmp); + Exit; + end + end; + FreeBitmap(Bmp); +end; + +(* +RoadColorChecker +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function RoadColorChecker: Boolean; + +Checks for presence of RoadColor. If none is found, it will try +various methods to find it. If successful, it sets RoadColor to the new color. + +.. note:: + + by Wizzup?/WT-Fakawi, edited by Ron & EvilChicken! + +Example: + +.. code-block:: pascal + + +*) + +// TODO: Depreciated? +function RoadColorChecker: Boolean; +var + I, X, Y: Integer; +begin + Result := False; + if (not LoggedIn) or (FindColor(X, Y, RoadColor, MMX1 + 20, MMY1 + 20, MMX2 - 20, MMY2 - 20)) then exit; + + for I := 0 to 2 do + begin + case I of + 0: if (FindColor(X, Y, 3026478, MMX1, MMY1, MMX2, MMY2)) then + Result := GetNewRoadColor(X - 14, Y - 14, X + 14, Y + 14, 10); + 1: Result := (GetNewRoadColor(MMCX - 20, MMCY - 20, MMCX + 20, MMCY + 20, 10)); + 2: Result := GetOldRoadColors; + end; + + if (Result) then + begin + case I of + 0: srl_Warn('RoadColorChecker', 'Found RoadColor through flag: ' + IntToStr(RoadColor), warn_Debug); + 1: srl_Warn('RoadColorChecker', 'Found RoadColor through minimap: ' + IntToStr(RoadColor), warn_Debug); + 2: srl_Warn('RoadColorChecker', 'Found RoadColor through GetOldRoadColors: ' + IntToStr(RoadColor), warn_Debug); + end; + Exit; + end else + if (I = 2) then + srl_Warn('RoadColorChecker', 'Couln''t find RoadColor', warn_Warning); + end; +end; + +(* +LinearWalkEx +~~~~~~~~~~~~ + +.. code-block:: pascal + + function LinearWalkEx(var TPA: TPointArray; cx, cy, TheColor, tol: Integer; Direction: Variant; Radius: Integer): Boolean; + +Finds TheColor from Radial (scanning outwards) for Radius Distance. +Valid Arguments: + + - tpa. Result points. + - Direction. See `variantToDirection` for information + - Radius. Distance from the centre of minimap, i.e. how far away the mouse clicks. Use numbers 20-72 + + +.. note:: + + by Nielsie95 + +Example: + +.. code-block:: pascal + + // check if the colour is present + while (FindColor(x,y, RoadColor)) do + begin + // build a tpa to walk on + if (LinearWalkEx(tpa, MMCX, MMCY, RoadColor, 5, -25.0, (MMX1-MMCX))) then + WalkTPA(tpa); // this depends how you want to work with the tpa + end; + +*) +function LinearWalkEx(var TPA: TPointArray; cx, cy, TheColor, tol: Integer; Direction: Variant; Radius: Integer): Boolean; +var + time, SD, ED: Integer; +begin + Result := False; + if (not LoggedIn) then Exit; + time := GetSystemTime; + Direction := variantToDirection(Direction); + + if (Direction < 50) then + SD := ((Direction + 360) - 50) + else + SD := (Direction - 50); + ED := (Direction + 50); + SD := Trunc(FixD(SD + 0.0)); + ED := Trunc(FixD(ED + 0.0)); + + try + FindColorsTolerance(tpa, TheColor, MMX1, MMY1, MMX2, MMY2, tol); + FilterPointsPie(tpa, SD, ED, 10, Radius, cx, cy); + LinearSort(tpa, cx, cy, Direction, False); + Result := (Length(tpa) > 0); + except + srl_Warn('LinearWalkEx', 'LWex error!', warn_AllVersions); + Exit; + end; + srl_Warn('LinearWalkEx', 'Took ' + IntToStr(GetSystemTime - time) + ' ms, found ' + + IntToStr(Length(TPA)) + 'points.', warn_Debug); +end; + +(* +RadialWalkEx +~~~~~~~~~~~~ + +.. code-block:: pascal + + function RadialWalkEx(var TPA: TPointArray; cx, cy, TheColor, tol: Integer; StartRadial, EndRadial: Variant; Radius: Integer): Boolean; + +Finds TheColor from StartRadial to EndRadial for Radius Distance. +Valid Arguments: + + - tpa. Result points. + - StartRadial/EndRadial. See `variantToDirection` for information + - Radius. Distance from the centre of minimap, i.e. how far + away the mouse clicks. Use numbers 20-72 + +.. note:: + + by Nielsie95 + +Example: + +.. code-block:: pascal + + // check if the colour is present + while (FindColor(x,y, RoadColor)) do + begin + // build a tpa to walk on + if (RadialWalkEx(tpa, MMCX, MMCY, RoadColor, 5, -25.0, (MMX1-MMCX))) then + WalkTPA(tpa); // this depends how you want to work with the tpa + end; + +*) +// TODO: Reorder params to clean up type changes? +function RadialWalkEx(var TPA: TPointArray; cx, cy, TheColor, tol: Integer; StartRadial, EndRadial: Variant; Radius: Integer): Boolean; +var + time: Integer; + SD, ED: extended; +begin + Result := False; + if (not LoggedIn) then Exit; + + SD := variantToDirection(StartRadial); + ED := variantToDirection(EndRadial); + if (SD = ED) then + begin + srl_Warn('RadialWalkEx', 'StartRadial = EndRadial, using LinearWalkEx.', warn_Warning); + Result := LinearWalkEx(tpa, cx, cy, TheColor, tol, StartRadial, Radius); + end; + + time := GetSystemTime; + try + FindColorsTolerance(tpa, TheColor, MMX1, MMY1, MMX2, MMY2, tol); + FilterPointsPie(tpa, SD, ED, 10, Radius, cx, cy); + SortCircleWise(tpa, cx, cy, StartRadial, False, StartRadial > EndRadial); + Result := (Length(tpa) > 0); + except + srl_Warn('RadialWalkEx', 'An exception has occured', warn_AllVersions); Exit; + end; + srl_Warn('RadialWalkEx', 'Took ' + IntToStr(GetSystemTime - time) + + ' ms, found' + IntToStr(Length(TPA)) + ' points', warn_Debug); +end; + +(* +RadialWalk +~~~~~~~~~~ + +.. code-block:: pascal + + function RadialWalk(TheColor: Integer; StartRadial, EndRadial: Variant; Radius, Xmod, Ymod: Integer): Boolean; + +Walks TheColor from StartRadial to EndRadial for Radius Distance +Valid Arguments: + + - TheColor. Any Color, but Road- or WaterColor will do fine :) + - StartRadial/EndRadial. See `variantToDirection` for information + - Radius. Distance from the centre of minimap, i.e. how far away the mouse clicks. Use numbers 20-72 + - XMod, YMod: deviation from MouseFindFlag. -2 to 2. + + +.. note:: + + by Nielsie95 from an original idea by WT-Fakawi + +Example: + +.. code-block:: pascal + + while (RadialWalk(GetRoadColor, 'w', 'n', 50, -1, 2)) do + WriteLn('Walking in a ''pie'' shape!'); + +*) +function RadialWalk(TheColor: Integer; StartRadial, EndRadial: Variant; Radius, Xmod, Ymod: Integer): Boolean; +var + TPA: TPointArray; + I: Integer; +begin + Result := False; + if RadialWalkEx(tpa, MMCX, MMCY, TheColor, 0, StartRadial, EndRadial, Radius) then + for i := 0 to High(tpa) do + if MFNF(tpa[i].x, tpa[i].y, Xmod, Ymod) then + begin + FFlag(10); + Result := True; + Exit; + end; +end; + +(* +LinearWalk +~~~~~~~~~~ + +.. code-block:: pascal + + function LinearWalk(TheColor: Integer; Direction: Variant; Radius, Xmod, Ymod: Integer): Boolean; + +Walks TheColor from Direction MIDDLE OUT!by performing windscreenlike scanning movements for Radius Distance +Valid Arguments: + + - TheColor. Any Color, but Road- or WaterColor will do fine :) + - Direction. See `variantToDirection` for information + - Radius. Distance from the centre of minimap, i.e. how far away + the mouse clicks. Use numbers 20-72. + - *XMod*, *YMod*: deviation from MouseFindFlag. -2 to 2. + +.. note:: + + by Nielsie95 from another original idea by WT-Fakawi + +Example: + +.. code-block:: pascal + + while (LinearWalk(GetRoadColor, 25.5, 50, -1, 2)) do + WriteLn('Walking in a ''line''!'); + +*) +function LinearWalk(TheColor: Integer; Direction: Variant; Radius, Xmod, Ymod: Integer): Boolean; +var + TPA: TPointArray; + I: Integer; + +begin + Result := False; + if LinearWalkEx(tpa, MMCX, MMCY, TheColor, 0, Direction, Radius) then + for i := 0 to High(tpa) do + if MFNF(tpa[i].x, tpa[i].y, Xmod, Ymod) then + begin + FFlag(10); + Result := True; + Break; + end; +end; + +(* +LinearWalkTolerance +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function LinearWalkTolerance(TheColor: Integer; Direction: Variant; Radius, Xmod, Ymod, Tol : Integer): Boolean; + +Same as LinearWalk, but with a tolerance. + +.. note:: + + by Nielsie95 + +Example: + +.. code-block:: pascal + + while (LinearWalkTolerance(clRed, 25.5, 50, -1, 2, 5)) do + WriteLn('Walking in a ''line''... with tolerance!'); + +*) +function LinearWalkTolerance(TheColor: Integer; Direction: Variant; Radius, Xmod, Ymod, Tol : Integer): Boolean; +var + TPA: TPointArray; + i, h: Integer; +begin + Result := False; + + if LinearWalkEx(TPA, MMCX, MMCY, TheColor, Tol, Direction, Radius) then + begin + h := High(TPA); + for i := 0 to h do + if MFNF(TPA[i].x, TPA[i].y, XMod, YMod) then + begin + FFlag(10); + Result := True; + Exit; + end; + end; +end; + +(* +RadialRoadWalk +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function RadialRoadWalk(TheColor, StartRadial, EndRadial, Radius, Xmod, Ymod: Integer): Boolean; + +Walks TheColor from StartRadial to EndRadial for Radius Distance +Valid Arguments: + + - TheColor. RoadColor. RoadColor will be dynamically updated. + - StartRadial/EndRadial. Any number between 0-720. 0=N,90=E,180=S,270=W. + - Radius. Distance from the centre of minimap, i.e. how far away the mouse clicks. Use numbers 20-72 + XMod, YMod: deviation from MouseFindFlag. -2 to 2. + + +.. note:: + + by WT-Fakawi? + +Example: + +.. code-block:: pascal + + +*) + +// TODO: Depreciated? +function RadialRoadWalk(TheColor, StartRadial, EndRadial, Radius, Xmod, Ymod: Integer): Boolean; +var + tpa: TPointArray; + i: Integer; +begin + Result := False; + if (not LoggedIn) then exit; + if (RoadColorChecker) then + srl_Warn('RadialRoadWalk', 'Updated RoadColor through RoadColorChecker: ' + + IntToStr(RoadColor), warn_Debug); + + if RadialWalkEx(tpa, MMCX, MMCY, TheColor, 0, StartRadial, EndRadial, Radius) then + for i := 0 to High(tpa) do + if MFNF(tpa[i].x, tpa[i].y, Xmod, Ymod) then + begin + FlagEx(10, True); + Result := True; + Break; + end; + If Result then + RoadColorChecker; +end; + +(* +RadialWalkTolerance +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function RadialWalkTolerance(Color: Integer; sRadial, eRadial: Variant; r, modX, modY, Tol: Integer): Boolean; + +Same as RadialWalk, but with a tolerance. + +.. note:: + + by Coh3n + Last modified: Jan. 08, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + while (RadialWalkTolerance(clRed, 25.5, 60.0, 50, -1, 2, 5)) do + WriteLn('Walking in a ''line''... with tolerance!'); + +*) +function RadialWalkTolerance(Color: Integer; sRadial, eRadial: Variant; r, modX, modY, Tol: Integer): Boolean; +var + TPA: TPointArray; + i, h: Integer; +begin + Result := False; + + if RadialWalkEx(TPA, MMCX, MMCY, Color, Tol, sRadial, eRadial, r) then + begin + h := High(TPA); + for i := 0 to h do + if MFNF(TPA[i].x, TPA[i].y, modX, modY) then + begin + Result := WaitFunc(@Flag, 50, 500); + Exit; + end; + end; +end; + +(* +RadialWalkAutoColor +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function RadialWalkAutoColor(autoColorConst, sRad, eRad, r, modX, modY: Integer): Boolean; + +Uses the TAutoColorInfo record to radial walk. + + +.. note:: + + by Coh3n + +Example: + +.. code-block:: pascal + + +*) +// TODO: Depreciated? +function RadialWalkAutoColor(autoColorConst, sRad, eRad, r, modX, modY: Integer): Boolean; +var + acInfo: TAutoColorInfo; + curCTS: Integer; + hMod, sMod: Extended; +begin + curCTS := GetColorToleranceSpeed; + GetColorSpeed2Modifiers(hMod, sMod); + + acInfo := AutoColorEx(autoColorConst); + with acInfo do + begin + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(hueMod, satMod); + + result := RadialWalkTolerance(color, sRad, eRad, r, modX, modY, lumTol); + end; + + SetColorSpeed2Modifiers(hMod, sMod); + ColorToleranceSpeed(curCTS); +end; + +(* +LinearRoadWalk +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function LinearRoadWalk(TheColor: Integer; Direction: Integer; Radius: Integer; Xmod, Ymod: Integer): Boolean; + +Walks TheColor from Direction MIDDLE OUT!by performing windscreenlike scanning movements for Radius Distance +Valid Arguments: + + - TheColor. Any Color, but Road- or WaterColor will do fine :) + - Direction. Any number between 0-720. 0=N,90=E,180=S,270=W. + - Radius. Distance from the centre of minimap, i.e. how far away + the mouse clicks. Use numbers 20-72 + - XMod, YMod: deviation from MouseFindFlag. -2 to 2. + +.. note:: + + by Nielsie95 + +Example: + +.. code-block:: pascal + + +*) +// TODO: Depreciated? +function LinearRoadWalk(TheColor: Integer; Direction: Integer; Radius: Integer; Xmod, Ymod: Integer): Boolean; +var + tpa: TPointArray; + i: Integer; +begin + Result := False; + if (not LoggedIn) then exit; + if (RoadColorChecker) then + srl_Warn('LinearRoadWalk', 'Updated RoadColor through RoadColorChecker: ' + + IntToStr(RoadColor), warn_Debug); + + if LinearWalkEx(tpa, MMCX, MMCY, TheColor, 0, Direction, Radius) then + for i := 0 to High(tpa) do + if MFNF(tpa[i].x, tpa[i].y, Xmod, Ymod) then + begin + FlagEx(10, True); + Result := True; + Break; + end; + if (Result) then + RoadColorChecker; +end; + +(* +WaterWalk +~~~~~~~~~ + +.. code-block:: pascal + + function WaterWalk(StartRadial, EndRadial, Radius, FFlagBreakOut, Xoff, Yoff, Xmod, Ymod: Integer): Boolean; + +Walks alongside Water. + - StartRadial/EndRadial = Any number between 0-720. 0=N,90=E,180=S,270=W. + - Radius. Distance from the centre of minimap, i.e. how far away the mouse clicks. Use numbers 20-72 + - FFlagBreakOut. Distance to flag where it will break out. 15 - 10 is good. + - Xoff, Yoff. Added to found point. + - XMod, YMod. deviation from MouseFindFlag. -2 to 2. + + +.. note:: + + by Nielsie95 from a third original idea by WT-Fakawi + +Example: + +.. code-block:: pascal + + +*) + +// TODO: Depreciated? +function WaterWalk(StartRadial, EndRadial, Radius, FFlagBreakOut, Xoff, Yoff, Xmod, Ymod: Integer): Boolean; +var + tpa: TPointArray; + i: Integer; +begin + Result := False; + if RadialWalkEx(tpa, MMCX, MMCY, WaterColor, 0, StartRadial, EndRadial, Radius) then + for i := 0 to High(tpa) do + if MFNF(tpa[i].x + Xoff, tpa[i].y + Yoff, Xmod, Ymod) then + begin + FFLag(FFlagBreakOut); + Result := True; + Break; + end; +end; + +(* +TPAWalk +~~~~~~~ + +.. code-block:: pascal + + function TPAWalk(color, tol, offsetX, offsetY: integer; sortFrom: TPoint): boolean; + +Uses a simple TPA sorting method to walk to a spot on the minimap. + * color: the color to be found on the minimap + * tol: the tolerance on color + * offsetX: the offset to click on the X coordinate of the found color + * offsetY: the offset to click on the Y coordinate of the found color + * sortFrom: the point on the minimap to sort found colors from + +.. note:: + + by Coh3n + +Example: + +.. code-block:: pascal + + if (not TPAWalk(1234567, 10, 0, 0, point(MMX1, MMY1)) then + if (not radialWalkTolerance({parameters here}) then + writeln('failed to TPA and radial walk'); +*) +function TPAWalk(color, tol, offsetX, offsetY: integer; sortFrom: TPoint): boolean; +var + i, x, y: integer; + TPA: TPointArray; +begin + result := false; + + if (findColorsTolerance(TPA, color, MMX1, MMY1, MMX2, MMY2, tol)) then + begin + sortTPAFrom(TPA, sortFrom); + + for i := 0 to high(TPA) do + begin + x := TPA[i].x; + y := TPA[i].y; + + if (not rs_OnMinimap(x, y)) then + continue; + + mouse(x + offsetX, y + offsetY, 3, 3, mouse_left); + + if (waitFunc(@flag, 50, 3000)) then + begin + result := true; + exit; + end; + end; + end; +end; + +(* +GetMiniMapDotsIn +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetMiniMapDotsIn(WhatDot: String; x1, y1, x2, y2: Integer): TPointArray; + +Results the dots specified by WhatDot in x1, y1, x2, y2. + +Usage: + + - 'npc', 'yellow' = Yellow Dot; + - 'cape', 'blue' = Blue Dot; + - 'item', 'red' = Red Dot; + - 'player', 'white' = White Dot; + - 'friend', 'green' = Green Dot; + + +.. note:: + + by Nava2 and Rasta Magician + +Example: + +.. code-block:: pascal + + count := Length(GetMiniMapDotsIn('green', MMX1, MMY1, MMX2, MMY2))); + WriteLn(ToStr(count) + ' friends on the map!'); + +*) + +// TODO: Constants +{******************************************************************************* +function GetMiniMapDotsIn(WhatDot: String; x1, y1, x2, y2: Integer): TPointArray; +By: euphemism, mormonman +Description: Results the dots specified by WhatDot in the box x1, y1, x2, y2. +Usage : 'npc', 'yellow', 'n', 'y' : Yellow Dot; + 'cape', 'blue', 'team', 't', 'b' : Blue Dot; + 'item', 'red', 'i', 'r' : Red Dot; + 'player', 'white', 'p', 'w' : White Dot; + 'friend', 'green', 'f', 'g' : Green Dot; +*******************************************************************************} +function GetMiniMapDotsIn(WhatDot: String; x1, y1, x2, y2: Integer): TPointArray; +var + I, Dif, Radius, Hi, C: Integer; + TPA: TPointArray; +begin + case LowerCase(WhatDot) of + 'npc', 'n', 'yellow', 'y': Dif := 4369; + 'item', 'i', 'red', 'r': Dif := 23; + 'player', 'p', 'white', 'w': Dif := 1907997; + 'friend', 'f', 'green', 'g': Dif := 5376; + 'team', 't', 'blue', 'b', 'cape': Dif := 2171941; + {'clan', 'c', 'orange', 'o': Dif := -1;} + else + srl_Warn('GetMiniMapDotsIn', '"' + WhatDot + '" is not a valid dot type', warn_AllVersions); + end; + Freeze; + Radius := Max((x2-x1)div 2, (y2-y1)div 2); + FindColorsPie(TPA, 65536, 0, 0, 360, 0, radius, x1, y1, x2, y2, (x1+x2)div 2, (y1+y2)div 2); + Hi := High(TPA); + SetLength(Result, Hi + 1); + if (Hi < 0) then + begin + UnFreeze; + Exit; + end; + C := 0; + for I := 0 to Hi do + begin + if (GetColor(TPA[I].X-1, TPA[I].Y-1) - GetColor(TPA[I].X, TPA[I].Y-1) = Dif) then + begin + Result[C] := Point(TPA[I].x, TPA[i].y - 2); + Inc(C); + end; + end; + Unfreeze; + SetLength(Result, C); +end; + +(* +GetMMDotsOnMS +~~~~~~~~~~~~~ + +.. code-block:: pascal + + Function GetMMDotsOnMS(WhatDot: String): TPointArray; + +Using minimap gets all MM dots assumed to be on Main Screen and returns it as +a TPA. You can also use it like Length(GetMMDotsOnMS(WhatDot)) to count how +many are actually visable. Returns closes to your position first. Used with +MMtoMS can be very powerful for searching more precise locations. + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + + while (Length(GetMMDotsOnMS('npc')) < 1) and (GetSystemTime < TimeCheck) do + begin + Wait(100); + FindNormalRandoms; + end; + +*) +Function GetMMDotsOnMS(WhatDot: String): TPointArray; +var + i, L, c: integer; + Dots: TPointArray; + B: TBox; +begin + B := IntToBox(32, 23, 24, 17);//Xtop, Ytop, Xbot, Ybot + Dots := GetMiniMapDotsIn(WhatDot, MMCX-Round(B.x1*1.3), MMCY-Round(B.y1*1.3), + MMCX+Round(B.x2*1.3), MMCY+Round(B.y2*1.3)); + L := Length(Dots); + if (L > 0) then + begin + SetLength(Result, L); + for i := 0 to High(Dots) do + If InAbstractBox(MMCX-B.x1, MMCY-B.y1, MMCX+B.x1, MMCY-B.y1, MMCX+B.x2, + MMCY+B.y2, MMCX-B.x2, MMCY+B.y2, Dots[i].x, Dots[i].y) then + begin + Result[c] := Dots[i]; + Inc(c); + end; + SetLength(Result, c); + SortTPAFrom(Result, Point(MMCX, MMCY)); + end; +end; + +(* +GetMiniMapDots +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetMiniMapDots(WhatDot: String): TPointArray; + +Results the dots specified by WhatDot on the Minimap. See `GetMiniMapDotsIn` +for more information. + + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + + // print the minimap positions on the debug canvas + DebugTPA(GetMiniMapDots('white')); + +*) +function GetMiniMapDots(WhatDot: String): TPointArray; +begin + Result := GetMinimapDotsIn(WhatDot, MMX1, MMY1, MMX2, MMY2); +end; + +(* +CountDots +~~~~~~~~~ + +.. code-block:: pascal + + function CountDots(WhatDot: String): integer; + +Counts the occurance of WhatDot on the MiniMap. See `GetMiniMapDots` in +for more information. + + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + + WriteLn(ToStr(CountDots('yellow')) + ' NPCs present on Minimap.'); + +*) +function CountDots(WhatDot: String): integer; +begin + Result := Length(GetMinimapDots(WhatDot)); +end; + +(* +MouseMM +~~~~~~~ + +.. code-block:: pascal + + procedure MouseMM(x, y, randX, randY: Integer); + +Clicks (x, y) on the MM, taking Map Angle into Account. Be sure to choose the +coords when Map Angle = 0 ! + +.. note:: + + by mixster + +Example: + +.. code-block:: pascal + + northPoint := Point(MMCX, MMY1-5); // North part! + MouseMM(NorthPoint.x, NorthPoint.y, 4, 4); // + +*) +procedure MouseMM(x, y, randX, randY: Integer); +var + p: TPoint; +begin + if not rs_OnMinimap(x, y) then + exit; + + p := RotatePoint(Point(x, y), rs_GetCompassAngleRadians, MMCX, MMCY); + Mouse(p.x, p.y, randX, randY, mouse_left); +end; + +(* +LodestoneScreen +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function LodestoneScreen(): Boolean; + +Finds LodestoneScreen. Returns true if Found. + +.. note:: + + Author: Home + +Example: + +.. code-block:: pascal + + If LodestoneScreen then + WriteLn('Lodestone Network screen is open!'); +*) +function LodestoneScreen(): Boolean; +begin + Result := CountColor(12378347, 172, 26, 345, 42) > 500; +end; + +(* +OpenLodestoneScreen +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function OpenLodestoneScreen(): Boolean; + +Opens Lodestone Screen. Returns true if screen appears. + +.. note:: + + Author: euphemism + +Example: + +.. code-block:: pascal + + If OpenLodestoneScreen then + WriteLn('Opened Lodestone Network screen!'); +*) +function OpenLodestoneScreen(): Boolean; +var + TimeMarker: Integer; +begin + Result := LodestoneScreen; + if (Result) then + Exit; + if (not SetAbilityBook(AB_TELEPORT_SPELLS)) then + Exit; + MouseBox(561, 290, 590, 319, mouse_left); + MarkTime(TimeMarker); + while ((TimeFromMark(TimeMarker) < 3000) and (not LodestoneScreen)) do + Wait(50); + Result := LodestoneScreen; + if (Result) then + Wait(RandomRange(800, 1500)) + else + Exit; +end; + +(* +LodestoneTeleport +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function LodestoneTeleport(Where: String): Boolean; + +Teleports you to chosen location via Lodestone teleport. + +.. note:: + + Author: Home + +Example: + +.. code-block:: pascal + + If CastHomeTeleport then + Lodestoneteleport('Lumbridge'); +*) +function LodestoneTeleport(Where: String): Boolean; +var + TPA: TPointArray; + TSA: TStringArray; + CTS, I: Integer; +begin + if not LoggedIn then Exit; + if not LodestoneScreen then + if not OpenLodestoneScreen then + Exit; + Wait(RandomRange(400, 1000)); + CTS := GetColorToleranceSpeed; + ColorToleranceSpeed(1); + + TSA := ['Lunar Isle', 'Yanille', 'Ardougne', 'Seers Village', 'Catherby', 'Taverley', + 'Burthorpe', 'Edgeville', 'Falador', 'Port Sarim', 'Draynor Village', 'Lumbridge', + 'Varrock', 'Al Kharid', 'Bandit Camp']; + + TPA := [Point(45, 78), Point(160, 262), Point(167, 211), Point(192, 158), Point(223, 181), + Point(253, 180), Point(251, 145), Point(293, 160), Point(278, 206), Point(276, 249), Point(308, 211), + Point(327, 243), Point(345, 182), Point(362, 229), Point(326, 297)]; + + for I := 0 to 14 do + if Capitalize(Where) = TSA[I] then + begin + Mouse(TPA[I].X, TPA[I].Y, 2, 2, mouse_left); + Result := True; + end; + + ColorToleranceSpeed(CTS); +end; diff --git a/SRL/core/math.simba b/SRL/core/math.simba new file mode 100644 index 0000000..f199970 --- /dev/null +++ b/SRL/core/math.simba @@ -0,0 +1,1597 @@ +(* +Math +==== + +Supporting math functions. + +.. contents:: + +*) + +const + MATH_PI = 3.14159265358979320; + MATH_2PI = MATH_PI * 2.0; + MATH_PIOVER2 = MATH_PI / 2.0; + MATH_PIOVER3 = MATH_PI / 3.0; + MATH_PIOVER4 = MATH_PI / 4.0; + MATH_PIOVER6 = MATH_PI / 6.0; + +var + SineArray, Cosearray: array[0..360] of Extended; + +(* +LoadCoSineArrays +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure LoadCoSineArrays; + +Load default sin/cos values. Used internally for SRL + +.. note:: + + by Mutant Squirrle + +Example: + +.. code-block:: pascal + +*) +procedure LoadCoSineArrays; +var + i: Integer; + pi_const: extended; +begin + pi_const := Pi; // not necessary, but might as well. + for i := 0 to 360 do + begin + Sinearray[i] := Sin(i * pi_const / 180.0); + Cosearray[i] := Cos(i * pi_const / 180.0); + end; +end; + +(* +CreateTPAFromText +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function CreateTPAFromText(Txt : string; Chars : string) : TPointArray; + +Returns the TPointArray of the inputted Text. + +.. note:: + + by MastaRaymond + +Example: + +.. code-block:: pascal + +*) +function CreateTPAFromText(Txt: string; Chars: string) : TPointArray; +var + w,h : integer; +begin; + result := TPAFromText(Txt,Chars,w,h); +end; + +(* +RBoolEx +~~~~~~~ + +.. code-block:: pascal + + function RBoolEx(chance: integer): boolean; + +Returns a boolean, with a chance of 1 / chance + +.. note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + +*) + +function RBoolEx(chance: Integer): Boolean; +begin + Result := (0 = Random(chance)); +end; + +(* +RBool +~~~~~ + +.. code-block:: pascal + + function RBool: boolean; + +Returns a boolean, with a 50% chance + +.. note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + +*) +function RBool: boolean; +begin + Result := RBoolEx(2); +end; + +type + TVector = record + x, y: Extended; + m: Extended; + end; + +(* +FixRad +~~~~~~ + +.. code-block:: pascal + + function FixRad(rad: Extended): Extended; + +Returns the periodic rad in the range (0,2PI]. + +.. note:: + + By Nava2 + +Example: + +.. code-block:: pascal + +*) +function FixRad(rad: Extended): Extended; // by Nava2 +begin + result := rad; + + while (result >= MATH_2PI) do + result := result - MATH_2PI; + + while (result < 0) do + result := result + MATH_2PI; +end; + + +(* +AngleBetween +~~~~~~~~~~~~ + +.. code-block:: pascal + + function AngleBetween(v1, v2: TVector): Extended; + +Calculates the angle between two TVector records. This is returned in radians +(normalized between (0, 2Pi]). + +.. note:: + + by readysteadygo + +Example: + +.. code-block:: pascal + +*) +function AngleBetween(v1, v2: TVector): Extended; +var + a1, a2: Extended; +begin + a1 := ArcTan2(v1.y, v1.x); + a2 := ArcTan2(v2.y, v2.x); + + Result := fixRad(a1 - a2) +end; + + +(* +Normalize +~~~~~~~~~ + +.. code-block:: pascal + + procedure Normalize(var vect: TVector); + +Converts a TVector to normal TVector (|v| = 1). + +.. note:: + + by readysteadygo + +Example: + +.. code-block:: pascal + +*) +procedure Normalize(var vect: TVector); +begin + vect.x := vect.x / vect.m; + vect.y := vect.y / vect.m; + vect.m := 1; +end; + +(* +CreateVector +~~~~~~~~~~~~ + +.. code-block:: pascal + + function CreateVector(Origin, vPoint: TPoint; NormalizeV: Boolean): TVector; + +Creates a `TVector` object. If NormalzseV is true, will set |v| = 1. + +.. note:: + + by readysteadygo + +Example: + +.. code-block:: pascal + +*) +function CreateVector(Origin, vPoint: TPoint; NormalizeV: Boolean): TVector; +begin + Result.x := vPoint.x - Origin.x; + Result.y := 0 - (vPoint.y - Origin.y); // inverts y axis as well + Result.m := Sqrt(Sqr(Result.x) + Sqr(Result.y)); + if (NormalizeV) then + Normalize(Result); +end; + + +(* +GetSplitPt +~~~~~~~~~~ + +.. code-block:: pascal + + function GetSplinePt(Points: TPointArray; Theta: Extended): TPoint; + +Returns the point on a spline, defined by control points Points, at Theta + +.. note:: + + by BenLand100 + +Example: + +.. code-block:: pascal + +*) +function GetSplinePt(Points: TPointArray; Theta: Extended): TPoint; +var + i, n: Integer; + XTemp, YTemp: Extended; +begin + n := GetArrayLength(Points) - 1; + for i := 0 to n do + begin + XTemp := XTemp + (BinCoe(n, i) * Points[i].x * Pow((1 - Theta), n - i) * + Pow(Theta, i)); + YTemp := YTemp + (BinCoe(n, i) * Points[i].y * Pow((1 - Theta), n - i) * + Pow(Theta, i)); + end; + Result.x := Round(XTemp); + Result.y := Round(YTemp); +end; + +(* +srl_GaussRand +~~~~~~~~~~~~~ + +This is a functional pointer. It behaves transparently as a regular function +would. This function will behave as so: it will return a random Extended +normally distributed with a mean of 0 and a standard deviation of 1. + +If you need more flexibility in this (ex. mean of 2), please use GaussRandom +which converts between the Standard Normal and a custom version. + +.. note:: + + by: SRL Development Team + +Example: + +.. code-block:: pascal + + +*) + +var + srl_GaussRand: function: Extended; + srl_GaussDev_Range, srl_GaussDev_Point: Extended; + +{ + +Helper method for cal_normal_random. Does polynomial calculation using the +`Horner Scheme`_ + +..http://en.wikipedia.org/wiki/Horner_scheme + +} +const + __gauss_norm_0 = 0.029899776; + __gauss_norm_1 = 0.008355968; + __gauss_norm_2 = 0.076542912; + __gauss_norm_3 = 0.252408784; + __gauss_norm_4 = 3.949846138; + +function __gauss_poly(r, rsqr: Extended): Extended; +begin + Result := __gauss_norm_0*rsqr + __gauss_norm_1; + Result := Result*rsqr + __gauss_norm_2; + Result := Result*rsqr + __gauss_norm_3; + Result := Result*rsqr + __gauss_norm_4; + Result := Result*r; +end; + +(* + +n2_gauss +~~~~~~~~ + +.. code-block:: pascal + + function n2_gauss(): Extended; + +Calculates a standard normal value (N(0, 1)). + +By definition, 68.2% of points will lie within +/- 1*sigma, 95.4% within +/- 2. + +.. note:: + + by: Nava2 + +*) +function n2_gauss(): Extended; +var + r: Extended; + i: Integer; +begin + r := 0.0; + for i := 0 to 11 do + r := r + (random(MaxInt)*1.0)/MaxInt; + + r := (r-6.0)/4.0 ; + result := __gauss_poly(r, r*r); +end; + +(* + +GaussMarsPolar +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GaussMarsPolar(): Extended; + +Calculates a standard normal value (N(0, 1]). + +By definition, 68.2% of points will lie within +/- 1*sigma, 95.4% within +/- 2. + +.. note:: + Please use `srl_GaussRand` instead of this function directly, feel free to + set `srl_GaussRand` to this function if you choose. + Currently, this is the default. + +.. note:: + by: BenLand100 + +*) +function GaussMarsPolar(): Extended; +begin + Result := sqrt(-2.0*ln(RandomE()))*cos(2.0*PI*RandomE()); +end; + +(* + +SetupGauss +~~~~~~~~~~ + +.. code-block:: pascal + + procedure setupGauss(); + +Sets up the necessary constants for the gaussian functions used in the Gaussian +math functions internally to SRL. + +.. note:: + + by: SRL Development Team + +*) +procedure setupGauss(); +begin + srl_GaussDev_Point := 0.4; + srl_GaussDev_Range := 0.3; + srl_GaussRand := @GaussMarsPolar; +end; + + +(* + +GaussRand +~~~~~~~~~ + +..code-block:: pascal + + function GaussRand(mean, dev: Extended): Extended; + +Calculates a normally distributed point around mean (u) with a standard +deviation of dev (o). + +..note:: + + by: Nava2 + +Example: + +..code-block:: pascal + + // shooting arrows simulation: + pt := Point(GaussRand(center.x, 0.5), GaussRand(center.y, 0.5)); + WriteLn(Format('Hit the target at (%d, %d).', [pt.x, pt.y])); + +*) + +function GaussRand(mean, dev: Extended): Extended; +begin + result := mean + dev*srl_GaussRand(); +end; + + +(* + +Gauss_Point +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure Gauss_Point(cX, cY: Integer; sAngle, eAngle: Extended; maxRad: Integer; out oX, oY: Integer); + +Calculates a point about cX, cY with radius maxRad. The sangle and eangle are +in radians. The point is returned in the reference parameters oX, oY. + +.. note:: + + by: Nava2 + +Example: + +.. code-block:: pascal + + var + gX, gY: Integer; + // get a gaussian pt in a circle: + Gauss_Point(MMCX, MMCY, 0, math_2PI, MMX2-MMCX, gX, gY); + WriteLn(Format("gX, gY -> %d, %d", gX, gY); + +*) + +procedure Gauss_Point(cX, cY: Integer; sAngle, eAngle: Extended; maxRad: Integer; out oX, oY: Integer); +var + angle: Extended; + radius: Extended; + xShift, yShift: Integer; +begin + + if (eAngle < sAngle) then + swap(eAngle, sAngle); + + { random angle about the center } + angle := sAngle + (eAngle-sAngle)*srl_GaussRand()/2.0; + + { get normal pt about zero, where 68% lie within .5*maxRad } + radius := GaussRand(maxRad,maxRad*srl_GaussDev_Point) - maxRad; + + + { the shifting distance based on the radius and angle (both rand) } + xShift := round(radius * Cos(angle)); + yShift := round(radius * Sin(angle)); + + oX := cX + xShift; + oY := cY + yShift; +end; + +(* +GaussRange +~~~~~~~~~~ + +.. code-block:: pascal + + function GaussRange(minI, maxI: Extended): Extended; + +Returns a number between minI and maxI that is normally distributed in the range. + +.. note:: + + by: Nava2 + +Example: + +.. code-block:: pascal + + randMean := GaussRange(0, 20); + +*) +function GaussRange(minI, maxI: Extended): Extended; +var + valid: Boolean; + mean: Extended; + dev: Extended; + t: Integer; +begin + { calculate the mean } + mean := (maxI+minI)/2.0; + dev := abs(maxI-minI)/2.0 * srl_GaussDev_Range; + + t := 0; + while ((not valid) and (t < 100)) do + begin + Result := GaussRand(mean, dev); + valid := ((Result >= minI) and (Result <= MaxI)); + + inc(t); + end; + +end; + +(* + +iGaussRange +~~~~~~~~~~~ + +.. code-block:: pascal + + function iGaussRange(minI, maxI: Integer): Integer; + +See `GaussRange` for more detail. Same function, but with integers. + +.. note:: + + by: Nava2 + +*) +function iGaussRange(minI, maxI: Integer): Integer; +begin + Result := Round(GaussRange(minI, maxI)); +end; + +(* + +GaussRandom +~~~~~~~~~~~ + +.. code-block:: pascal + + function GaussRandom(maxExt: Integer): Integer; + +Computes a normally distributed number in [0, maxExt). Thus, it behaves like +Random() would be expected to. But normally distributed about maxExt/2. + +It is a wrapper for `iGaussRange`. + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + +*) +function GaussRandom(maxExt: Integer): Integer; +begin + Result := iGaussRange(0, maxExt-1); +end; + +(* + +GaussBox +~~~~~~~~ + +.. code-block:: pascal + + procedure GaussBox(out px, py: Integer; x1, y1, x2, y2: Integer); + +Calculates a point normally distributed from the center of the passed box. It +checks for outlying points and will regenerate points if necessary. + +.. note:: + + by: Nava2 + +Example: + +.. code-block:: pascal + + var + gX, gY: Integer; + + // get a gaussian pt in a circle: + Gauss_Box(gX, gY, MMX1, MMY1, MMX2, MMY2); + WriteLn(Format("gX, gY -> %d, %d", gX, gY); + +*) + +procedure GaussBox(out px, py: Integer; x1, y1, x2, y2: Integer); +begin + px := iGaussRange(x1, x2); + py := iGaussRange(y1, y2); + + if (not PointInBox(Point(px, py), IntToBox(x1, y1, x2, y2))) then + SRL_Warn('GaussBox',Format('Point invalid (%d, %d)', [px, py]), warn_Terminate); +end; + +(* +MakeSplinePath +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function MakeSplinePath(Points: TPointArray; ThetaInc: Extended): TPointArray; + +Returns a spline, defined by control points Points, incrementing theta by +ThetaInc + +.. note:: + + by BenLand100 + +Example: + +.. code-block:: pascal + +*) +function MakeSplinePath(Points: TPointArray; ThetaInc: Extended): TPointArray; +var + i: Integer; + t: Extended; + temp, last: TPoint; + done: Boolean; +begin + repeat + if t >= 1 then + begin + t := 1; + done := True; + end; + temp := GetSplinePt(Points, t); + if ((temp.x <> last.x) and (temp.y <> last.y)) then + begin + i := i + 1; + SetArrayLength(Result, i); + Result[i - 1] := temp; + last := temp; + end; + t := t + ThetaInc; + until (done) +end; + +(* +MidPoints +~~~~~~~~~ + +.. code-block:: pascal + + function MidPoints(Path: TPointArray; MaxDist: Integer): TPointArray; + +Adds midpoints to Path so no distance on it is greater than MaxDist + +.. note:: + + by BenLand100 + +Example: + +.. code-block:: pascal + +*) +function MidPoints(Path: TPointArray; MaxDist: Integer): TPointArray; +var + i, c: Integer; + last: TPoint; + done: Boolean; +begin + if (getarraylength(path) > 0) then + begin + repeat + last := Path[0]; + done := True; + for i := 1 to GetArrayLength(Path) - 1 do + begin + if Sqrt(Pow((Path[i].x - last.x), 2) + Pow((Path[i].y - last.y), 2)) > + MaxDist then + begin + done := False; + SetArrayLength(Path, GetArrayLength(Path) + 1); + for c := GetArrayLength(Path) - 1 downto i + 1 do + begin + Path[c] := Path[c - 1]; + end; + Path[i].x := Round((last.x + Path[i + 1].x) / 2); + Path[i].y := Round((last.y + Path[i + 1].y) / 2); + end; + last := Path[i]; + end; + until (done); + end; + Result := Path; +end; + +(* +InAbstractBox +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function InAbstractBox(x1, y1, x2, y2, x3, y3, x4, y4: Integer; x, y: Integer): Boolean; + +Returns true if point x, y is in an abstract box defined by +*x1, y1, x2, y2, x3, y3, x4, y4*. + +.. code-block:: pascal + + x1, y1 x2, y2 + +--------+ + \ / + \ / + +--+ + x4, y4 x3, y3 + +.. note:: + + by BenLand100 + +Example: + +.. code-block:: pascal + +*) +function InAbstractBox(x1, y1, x2, y2, x3, y3, x4, y4: Integer; x, y: Integer): + Boolean; +var + U, D, R, L: Boolean; + UB, DB, LB, RB, UM, DM, LM, RM: Extended; +begin + UM := (-y1 - -y2) div (x1 - x2); + DM := (-y4 - -y3) div (x4 - x3); + if x1 - x4 <> 0 then + begin + LM := (-y1 - -y4) div (x1 - x4); + end else + begin + LM := Pi; + end; + if x2 - x3 <> 0 then + begin + RM := (-y2 - -y3) div (x2 - x3); + end else + begin + RM := Pi; + end; + UB := -(UM * x1) + -y1; + RB := -(RM * x2) + -y2; + DB := -(DM * x3) + -y3; + LB := -(LM * x4) + -y4; + if (UM * x + UB >= -y) then U := True; + if (DM * x + DB <= -y) then D := True; + if (RM <> Pi) and (RM >= 0) and (RM * x + RB <= -y) then R := True; + if (RM <> Pi) and (RM < 0) and (RM * x + RB >= -y) then R := True; + if (RM = Pi) and (x < x2) then R := True; + if (LM <> Pi) and (LM >= 0) and (LM * x + LB >= -y) then L := True; + if (LM <> Pi) and (LM < 0) and (LM * x + LB <= -y) then L := True; + if (LM = Pi) and (x > x1) then L := True; + if U and D and L and R then Result := True; +end; + +(* +Sine +~~~~ + +.. code-block:: pascal + + function Sine(degrees: Integer): Extended; + +Return the sin of *degrees*. + +.. note:: + + by Mutant Squirrle + +Example: + +.. code-block:: pascal + + if (sine(0) = 0) then + WriteLn('Yay! We made maths!'); + +*) +function Sine(Degrees: Integer): Extended; +begin + Result := sinearray[Trunc(FixD(Degrees))]; +end; + +(* +Cose +~~~~ + +.. code-block:: pascal + + function Cose(degrees: Integer): Extended; + +Return the cos of *degrees*. + +.. note:: + + by Mutant Squirrle + +Example: + +.. code-block:: pascal + + if (Cose(0) = 1) then + WriteLn('Yay! We made more maths!'); + +*) +function Cose(Degrees: Integer): Extended; +begin + Result := cosearray[Trunc(FixD(Degrees))]; +end; + +(* +GridCoords16Ex +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + Function GridCoords16Ex(Xmod, Ymod: integer; Grid16: TPoint): TPoint; + +Using a grid system based off MiniMap size to return grid position on MainScreen. +This is used in MMtoMS as well as other Grid functions. +Why the number 16? Original grid is based off a tile, and this splits one tile +into a 4x4 hence 16. + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + + Example: see MMtoMSEx + +*) + +Function GridCoords16Ex(Xmod, Ymod: integer; Grid16: TPoint): TPoint; +var + Yh, yM, X, Y: Extended; +begin + X := Grid16.x+0.0; + Y := Grid16.y+0.0; + yM := 36.0; + Yh := Abs(Y + yM); + Result.x := Round( (263.5+Xmod) + (X*9.75/(12.8-(Yh/yM*3.15))) * 9.75); + Result.y := Round( (182.0+Ymod) + Y * (6.3 + ((Yh/yM)*2.4))); + if not PointInBox(Result, MSBox) then + Result := Point(-1, -1); +end; + +(* +GetGridAbstractBox +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + Function GetGridAbstractBox(Grid: TPoint): TPointArray; + +Returns TPointArray of points for grid tile to use InAbstractBox in GetGridPos + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + + +*) +Function GetGridAbstractBox(Grid: TPoint): TPointArray; +var + T: TPoint; + i: integer; +begin + T := Point(Grid.x*4, Grid.y*4); + Result := [GridCoords16Ex(0, 0, Point(T.x-2, T.y-2)), GridCoords16Ex(0, 0, Point(T.x+1, T.y-2)), + GridCoords16Ex(0, 0, Point(T.x+1, T.y+1)), GridCoords16Ex(0, 0, Point(T.x-2, T.y+1))]; + for i := 0 to 3 do + if Result[i].x = -1 then + begin + Result := [Point(-1,-1), Point(-1,-1), Point(-1,-1), Point(-1,-1)]; + Exit; + end; +end; + +(* +GetGridPos +~~~~~~~~~~ + +.. code-block:: pascal + + function GetGridPos(MS: TPoint): TPoint; + +Given a MainScreen point it'll return the GridTile position the point is in. +If it fails result is Point(-100, -100), because it can return negative grid +points. + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + + +*) +function GetGridPos(MS: TPoint): TPoint; +var + x, y: integer; + TPA: TPointArray; +begin + Result := Point(-100, -100); //fail point + for x := -8 to 8 do + for y := -8 to 5 do + begin + TPA := GetGridAbstractBox(Point(x,y)); + if TPA[0].x = -1 then + Continue; + if InAbstractBox(TPA[0].x, TPA[0].y, TPA[1].x, TPA[1].y, TPA[2].x, TPA[2].y, TPA[3].x, TPA[3].y, MS.x, MS.y) then + begin + Result := Point(x, y); + Exit; + end; + end; +end; + +(* +GridCoords +~~~~~~~~~~ + +.. code-block:: pascal + + function GridCoords(GridPoint: TPoint): TPoint; + +Returns grid point Main Screen position. (middle of tile) + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + + +*) +function GridCoords(GridPoint: TPoint): TPoint; +var + Yh: Extended; +begin + Yh := Abs((GridPoint.y+0.0) + 6.0); + Result.x := Round(259.5 + ((GridPoint.x+1.0)*38.0/(45.7-(Yh/9.0*12.8))) * 38.0); + Result.y := Round(178.5 + (GridPoint.y+0.0) * (36.0 + ((GridPoint.y+0.0)*37.0)/25.0)); + if not PointInBox(Result, MSBox) then + Result := Point(-1, -1); +end; + +(* +MMToMSEx +~~~~~~~~ + +.. code-block:: pascal + + Function MMtoMSEx(Xmod, Ymod: integer; MM: TPoint): TPoint; + +Turns a Minimap point into a close MS point. New one compensates for angles. +Xmod and Ymod change the starting point on MainScreen. Ymod = -30 would +raise the points on screen by 30 pixels. This is good if you know the +Height of the npc or object your looking for on MS. +Formula in GridCoords16Ex now. + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + + FindTreeOnMinimap(x, y); + msPoint := MMToMSEx(0, -20, Point(x,y)); + MMouse(msPoint.x, msPoint.y, 0, 0); + //... + +*) +Function MMtoMSEx(Xmod, Ymod: integer; MM: TPoint): TPoint; +begin + Result := GridCoords16Ex(Xmod, Ymod, Point(MM.x-MMCX, MM.y-MMCY)); +end; + + +(* +MMToMS +~~~~~~ + +.. code-block:: pascal + + function MMToMS(MM: TPoint): TPoint; + +Refer to MMtoMSEx - Ymod shift required to be backward compatible + +.. note:: + + by Narcle + +Example: + +.. code-block:: pascal + + +*) +Function MMtoMS(MM: TPoint): TPoint; +begin + Result := MMtoMSEx(0, -20, MM); +end; + +(* +DeleteValueInStrArray +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DeleteValueInStrArray(var Arr: TStringArray; ValuePosition: Integer); + +Deletes value with ValuePosition in "Arr" string array. Maintains current order. + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + +*) +// TODO: Remove? +procedure DeleteValueInStrArray(var Arr: TStringArray; ValuePosition: Integer); +var + ArrLen, I: Integer; +begin + ArrLen := High(Arr); + for I := ValuePosition to ArrLen - 1 do + Swap(Arr[I], Arr[I + 1]); + SetArrayLength(Arr, ArrLen); +end; + +(* +DeleteValueInIntArray +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DeleteValueInIntArray(var Arr: TIntegerArray; ValuePosition: Integer); + +Deletes value with ValuePosition in "Arr" Integer array. + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + +*) +// TODO: Remove? +procedure DeleteValueInIntArray(var Arr: TIntegerArray; ValuePosition: Integer); +var + ArrLen, I: Integer; +begin + ArrLen := High(Arr); + for I := ValuePosition to ArrLen - 1 do + Swap(Arr[I], Arr[I + 1]); + SetArrayLength(Arr, ArrLen); +end; + +(* +DeleteValueInFloatArray +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DeleteValueInFloatArray(var Arr: TExtendedArray; ValuePosition: Integer); + + +Deletes value with ValuePosition in "Arr" Float array. + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + +*) +// TODO: Remove? +procedure DeleteValueInFloatArray(var Arr: TExtendedArray; ValuePosition: Integer); +var + ArrLen, I: Integer; +begin + ArrLen := High(Arr); + for I := ValuePosition to ArrLen - 1 do + Swap(Arr[I], Arr[I + 1]); + SetArrayLength(Arr, ArrLen); +end; + +(* +DeleteValueInBoolArray +~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DeleteValueInBoolArray(var Arr: TBooleanArray; ValuePosition: Integer); + +Deletes value with ValuePosition in "Arr" Boolean array. + +.. note:: + + by EvilChicken! + +Example: + +.. code-block:: pascal + +*) +// TODO: Remove? +procedure DeleteValueInBoolArray(var Arr: array of boolean; ValuePosition: Integer); +var + ArrLen, I: Integer; +begin + ArrLen := High(Arr); + for I := ValuePosition to ArrLen - 1 do + Swap(Arr[I], Arr[I + 1]); + SetArrayLength(Arr, ArrLen); +end; + +(* +DeleteValueInTPA +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DeleteValueInTPA(var Arr: TPointArray; ValuePosition: Integer); + +Deletes value with ValuePosition in "Arr" TPointArray. + +.. note:: + + by EvilChicken! & Coh3n + +Example: + +.. code-block:: pascal + +*) +// TODO: Remove? +procedure DeleteValueInTPA(var Arr: TPointArray; ValuePosition: Integer); +var + ArrLen, I: Integer; +begin + ArrLen := High(Arr); + for I := ValuePosition to ArrLen - 1 do + tSwap(Arr[I], Arr[I + 1]); + SetArrayLength(Arr, ArrLen); +end; + +(* +DeleteValueInATPA +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DeleteValueInATPA(var Arr: T2DPointArray; ValuePosition: Integer); + +Deletes value with ValuePosition in "Arr" T2DPointArray. + +.. note:: + + by EvilChicken! & Coh3n + +Example: + +.. code-block:: pascal + +*) +// TODO: Remove? +procedure DeleteValueInATPA(var Arr: T2DPointArray; ValuePosition: Integer); +var + ArrLen, I: Integer; +begin + ArrLen := High(Arr); + for I := ValuePosition to ArrLen - 1 do + tpaSwap(Arr[I], Arr[I + 1]); + SetArrayLength(Arr, ArrLen); +end; + +(* +BoxClosestPoint +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function BoxClosestPoint(p : TPoint; b : TBox) : TPoint; + +There are 'nine' places where the point can be (relative to a box).. +The middle, 5, is the box itself. +The rest looks like this: + +| 1 | 2 | 3 +| --------- +| 4 | 5 | 6 +| --------- +| 7 | 8 | 9 + +Place 9 means it's past the b.x2, and past the b.y2, +therefore the smallest dist between the point and the box is the +distance between the point and the box's x2,y2 coordinate. + +.. note:: + + by Raym0nd + +Example: + +.. code-block:: pascal + +*) + +function BoxClosestPoint(p : TPoint; b : TBox) : TPoint; +var + column,row,place : integer; +begin + result := Point(-1,-1); + + if (p.x < B.X1) then + Column := 1 + else if (p.x > b.x2) then + Column := 3 + else + Column := 2; + + if (p.y < b.y1) then + row := 1 + else if (p.y > b.y2) then + row := 3 + else + row := 2; + + place := (row-1)* 3 + column; + case Place of + 1 : Result := Point(b.x1,b.y1); + 2 : Result := Point(p.x,b.y1); + 3 : Result := point(b.x2,b.y1); + 4 : Result := point(b.x1,p.y); + 5 : Result := p; + 6 : Result := point(b.x2,p.y); + 7 : Result := point(b.x1,b.y2); + 8 : Result := point(p.x,b.y2); + 9 : Result := point(b.x2,b.y2); + end; +end; + +(* +RandomPointBoxEx +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function RandomPointBoxEx(p : TPoint; b : TBox; extraDist : integer) : TPoint; + +Returns a point in the box which is 'aimed' near the TPoint given.. +Basically it only allows points that lay within the extradist from +the closest point to be returned. +Practical example: + + Inventory Box.. When your mouse is on the right of an inv item, + you don't want to click on the left of the box. + +.. note:: + + by Raym0nd + +Example: + +.. code-block:: pascal + +*) +function RandomPointBoxEx(p : TPoint; b : TBox; extraDist : integer) : TPoint; +var + TPA : TPointArray; + Dist : integer; + ClosestPoint : TPoint; +begin + if PointInBox(p,b) then + begin + result := p; + exit; + end; + + ClosestPoint := BoxClosestPoint(p,b); + Dist := Distance(p.x,p.y,ClosestPoint.x,ClosestPoint.y); + TPA := TPAFromBox(b); + FilterPointsDist(TPA,0,dist+extraDist,p.x,p.y); + + if (length(TPA) < 1) then + result := point(RandomRange(b.X1,b.x2),RandomRange(b.y1,b.y2)) + else + result := TPA[random(length(tpa))]; +end; + +(* +MiddleBox +~~~~~~~~~ + +.. code-block:: pascal + + function MiddleBox(b : TBox) : TPoint; + +Returns the middle of the box. + +.. note:: + + by Raym0nd + +Example: + +.. code-block:: pascal + + midPt := MiddleBox(TBox(MMX1, MMY1, MMX2, MMY2)); + // midPt == Point(MMCX, MMCY)! + +*) +function MiddleBox(b : TBox) : TPoint; +begin + result := point((b.x2+b.x1) div 2,(b.y2+b.y1) div 2); +end; + +(* +GroupDigits +~~~~~~~~~~~ + +.. code-block:: pascal + + function GroupDigits(n: integer; token: String): String; + +Nicely formats the number passed by placing *token* in between groups of three +numbers. + +.. note:: + + by PriSoner and Nava2 + +Example: + +.. code-block:: pascal + + foo := GroupDigits(1000, ','); // foo -> '1,000' + bar := GroupDigits(1500423, ' '); // bar -> '1 500 423' + +*) +function GroupDigits(n: integer; token: String): String; +var + b: integer; +begin + Result := IntToStr(n); + + b := length(Result) + 1; + if (b > 3) then + repeat + b := b - 3; + if (b > 1) then + insert(token, Result, b); + until (b < 3); +end; + + + +(* +CashStrToInt +~~~~~~~~~~~~ + +.. code-block:: pascal + + function CondensedStrToInt(Number: string): Integer; + +Converts between '100k' representation to 1000000. + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + + foo := CashStrToInt('2b'); + +*) +function CashStrToInt(Number: string): Integer; +var + p, i: Integer; + n: TIntegerArray; +begin + Number := LowerCase(Number); + n := [ord('k'), 1000, + ord('m'), 1000000, + ord('b'), 1000000000]; + + for i := 0 to 2 do + begin + p := Pos(chr(n[i*2]), Number); + if (p <> 0) then + begin + Delete(Number, p, Length(Number)); + try + Result := Round(StrToFloat(Number) * n[(i*2) + 1]); + except + Writeln(Format('This caused error in StrToFloat (%s): %s', + [n[i*2], Number])); + end; + Exit; + end; + end; + Result := StrToIntDef(Number, 0); +end; + +(* +GridBox +~~~~~~~ + +.. code-block:: pascal + + function GridBox(slot, columns, rows, w, h, diffX, diffY: integer; starTPoint: TPoint): TBox; + +Returns a TBox of the slot 'slot' in a grid created by the other parameters. +Slots start with 1 being the top left of the grid, and counting accross. + * columns: number of columns in the grid + * rows: number of rows in the grid + * w: the width of each box in the grid + * h: the height of each box in the grid + * diffX: pixels from center to center (x) + * diffY: pixels from center to center (y) + * starTPoint: the center point of the top left box in the grid + +.. note:: + + | Author: Coh3n + | Last Modified: Jan. 25th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + result := GridBox(Slot, 4, 2, 95, 80, 0, 150, point(110, 100)); +*) +function GridBox(slot, columns, rows, w, h, diffX, diffY: integer; startPoint: TPoint): TBox; +begin + if (slot > (columns * rows)) then + begin + writeln('GridBox: Invalid slot: '+toStr(slot)); + exit; + end; + + result.x1 := (startPoint.x + (((slot - 1) mod columns) * diffX) - (w div 2)); + result.y1 := (startPoint.y + (((slot - 1) div columns) * diffY) - (h div 2)); + result.x2 := (result.x1 + w); + result.y2 := (result.y1 + h); +end; + +(* +Grid +~~~~ + +.. code-block:: pascal + + function Grid(columns, rows, w, h, diffX, diffY: integer; starTPoint: TPoint): TBoxArray; + +Returns a grid of TBoxes (see GridBox for parameters). + +.. note:: + + | Author: Coh3n + | Last Modified: Jan. 25th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + SMART_DrawBoxes(false, Grid(5, 10, 20, 20, 25, 25, point(30, 30)), clYellow); +*) +function Grid(columns, rows, w, h, diffX, diffY: integer; starTPoint: TPoint): TBoxArray; +var + i: integer; +begin + setLength(result, (columns * rows)); + + for i := 0 to high(result) do + result[i] := GridBox(i + 1, columns, rows, w, h, diffX, diffY, starTPoint); +end; + +(* +TPABetweenPoints +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function TPABetweenPoints(P1, P2: TPoint; Interval, Rand: Integer): TPointArray; + +Generates a TPA between P1 and P2, Interval between points; Rand randomness +on each point. Very useful for generating a random walking path between the +player's position and the ending position. + +.. note:: + + | Author: Nava2 + | Last Modified: Apr. 4thth, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + newTPA := TPABetweenPoints(PlayerPos, EndPos, 25, 10); +*) +function TPABetweenPoints(P1, P2: TPoint; Interval, Rand: Integer): TPointArray; +var + hyp, xR, yR: Extended; + l: Integer; +begin + // set Result Length and first point at initial Point + SetLength(Result, Ceil(Distance(P1.X, P1.y, P2.X, P2.Y) * 1.0 / Interval) + 1); + Result[0] := P1; + + // if no need for intermediate Points then nvm. :) + if (Distance(P1.X, P1.Y, P2.X, P2.Y) <= Interval) then + begin + Result[High(Result)] := P2; + Exit; + end; + + // ratios for 'Similar Triangles' maths + hyp := Hypot(P1.X - P2.x, P1.Y - P2.Y); + xR := (P2.X - P1.X) / hyp; + yR := (P2.Y - P1.Y) / hyp; + + // set points + for l := High(Result) - 1 downto 1 do + begin + Result[l].X := Round(P1.X + l * Interval * xR) + RandomRange(-Rand, Rand); + Result[l].Y := Round(P1.Y + l * Interval * yR) + RandomRange(-Rand, Rand); + end; + + // last point is tT + Result[High(Result)] := P2; +end; diff --git a/SRL/core/mouse.simba b/SRL/core/mouse.simba new file mode 100644 index 0000000..2c51354 --- /dev/null +++ b/SRL/core/mouse.simba @@ -0,0 +1,811 @@ +(* + +Mouse +===== + +Mouse routines. + +.. contents:: + +*) + + +// TODO: Constant/Var docs +var + MouseSpeed: Integer; + + {$IFDEF UseLaptopMouse} + LMouse_MissChance: Integer; + {$ENDIF} + +const + mouse_move = 3; +(* +WindMouse +~~~~~~~~~ + +.. code-block:: pascal + + procedure WindMouse(xs, ys, xe, ye, gravity, wind, minWait, maxWait, maxStep, targetArea: extended); + +Moves the mouse along a spline defined by + +.. note:: + + by Benland100 + +Example: + +.. code-block:: pascal + + + +*) +procedure WindMouse(xs, ys, xe, ye, gravity, wind, minWait, maxWait, maxStep, targetArea: extended); +var + veloX, veloY, windX, windY, veloMag, dist, randomDist, lastDist, step: extended; + lastX, lastY: integer; + sqrt2, sqrt3, sqrt5: extended; +begin + try + sqrt2:= sqrt(2); + sqrt3:= sqrt(3); + sqrt5:= sqrt(5); + while hypot(xs - xe, ys - ye) > 1 do + begin + dist:= hypot(xs - xe, ys - ye); + wind:= minE(wind, dist); + if dist >= targetArea then + begin + windX:= windX / sqrt3 + (random(round(wind) * 2 + 1) - wind) / sqrt5; + windY:= windY / sqrt3 + (random(round(wind) * 2 + 1) - wind) / sqrt5; + end else + begin + windX:= windX / sqrt2; + windY:= windY / sqrt2; + if (maxStep < 3) then + begin + maxStep:= random(3) + 3.0; + end else + begin + maxStep:= maxStep / sqrt5; + end; + end; + veloX:= veloX + windX; + veloY:= veloY + windY; + veloX:= veloX + gravity * (xe - xs) / dist; + veloY:= veloY + gravity * (ye - ys) / dist; + if hypot(veloX, veloY) > maxStep then + begin + randomDist:= maxStep / 2.0 + random(round(maxStep) div 2); + veloMag:= sqrt(veloX * veloX + veloY * veloY); + veloX:= (veloX / veloMag) * randomDist; + veloY:= (veloY / veloMag) * randomDist; + end; + lastX:= Round(xs); + lastY:= Round(ys); + xs:= xs + veloX; + ys:= ys + veloY; + if (lastX <> Round(xs)) or (lastY <> Round(ys)) then + MoveMouse(Round(xs), Round(ys)); + step:= hypot(xs - lastX, ys - lastY); + wait(round((maxWait - minWait) * (step / maxStep) + minWait)); + lastdist:= dist; + end; + if (Round(xe) <> Round(xs)) or (Round(ye) <> Round(ys)) then + MoveMouse(Round(xe), Round(ye)); + except + end; +end; + +(* +MMouse +~~~~~~ + +.. code-block:: pascal + + procedure MMouse(x, y, rx, ry: integer); + +Moves the mouse. + +.. note:: + + by Benland100, laptop mouse by Hobbit (and nielsie95) + +Example: + +.. code-block:: pascal + +*) +procedure MMouse(x, y, rx, ry: integer); +var + cx, cy: integer; + randSpeed: Extended; + {$IFDEF UseLaptopMouse} + seg, e, f, g, nx, ny, hypo: Integer; + a, b, c: Extended; + Miss: Boolean; + {$ENDIF} +begin + GetMousePos(cx, cy); + {$IFDEF UseLaptopMouse} + miss := (Random(LMouse_MissChance) = 0); + e:= 0; + a:= x - cx; + b:= y - cy; + c:= Pow(a,2) + Pow(b,2) + hypo:= Round(Sqrt(c)); + case hypo of + 0: Exit; + 1..225: seg:=1; + 226..600: seg:= Random(2) + 1; + 601..1800: seg:= random(3) + 2; + else seg := 5; + end; + f := Round( a / seg); + g := Round( b / seg); + repeat + Wait(30 + random(50)); + {Begin: Modified from MMouse by Benland100} + randSpeed := (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0; + if randSpeed = 0.0 then + randSpeed := 0.1; + getMousePos(cx,cy); + nx:= (cx + (f * e)) + random(rx); + ny:= (cy + (g * e)) + random(ry); + {End: Modified from MMouse by Benland100} + if Miss then + begin + nx:= nx + RandomRange(rx, rx * 2); + ny:= ny + RandomRange(ry, ry * 2); + end; + WindMouse(cx,cy,nx,ny,11.0,8.0,10.0/randSpeed,12.0/randSpeed,10.0*randSpeed,10.0*randSpeed); + e:= e + 1; + until(e = seg); + GetMousePos(cx, cy); + if not PointInBox(Point(cx, cy), IntToBox(x, y, x + rx, y + ry)) then + begin + Wait(30 + random(30)); + WindMouse(cx,cy,(x + random(rx)),(y + random(ry)),11.0,6.0,10.0/randSpeed,15.0/randSpeed,10.0*randSpeed,10.0*randSpeed); + end; + {$ELSE} + randSpeed:= (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0; + if randSpeed = 0.0 then + randSpeed := 0.1; + X := x + random(rx); + Y := y + random(ry); + WindMouse(cx,cy,x,y,9.0,3.0,10.0/randSpeed,15.0/randSpeed,10.0*randSpeed,10.0*randSpeed); + {$ENDIF} +end; + +(* +ClickMouse2 +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure ClickMouse2(button: variant); + +Clicks the mouse in a human way on the current mouse spot. + +.. note:: + + by SRL Community + +Example: + +.. code-block:: pascal + +*) +procedure ClickMouse2(button: variant); +var + a,b,c : integer; + iButton: Integer; +begin + { Eventually, should be made to just use Integers } + if VariantIsBoolean(button) then + begin + if (button) then + iButton := mouse_left + else + iButton := mouse_right; + end else + iButton := button; + + if (iButton = mouse_move) then Exit; { we aren't actually clicking! } + + GetMousePos(b, c); + + HoldMouse(b, c, iButton); + repeat + Wait(20 + Random(30)); + a := a + 1; + until (a > 4); + GetMousePos(b, c); + ReleaseMouse(b, c, iButton); + Wait(50+Random(50)); +end; + +(* +Mouse +~~~~~ + +.. code-block:: pascal + + procedure Mouse(mousex, mousey, ranx, rany: Integer; button: variant); + +Moves then clicks mouse (will only move if 'mouse_move' passed). + +.. note:: + + by Mutant Squirrle, Harry + +Example: + +.. code-block:: pascal + +*) +procedure Mouse(mousex, mousey, ranx, rany: Integer; button: variant); +begin + MMouse(mousex, mousey, ranx, rany); + Wait(60 + Random(30)); + ClickMouse2(button); + Wait(50 + Random(50)); +end; + +(* +MouseBox +~~~~~~~~ + +.. code-block:: pascal + + procedure MouseBox(x1, y1, x2, y2: Integer; ClickType: Integer); + +Moves mouse into a random position in the box. Clicks if told to. + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + +*) +procedure MouseBox(x1, y1, x2, y2: Integer; ClickType: Integer); +var + fx, fy: Integer; +begin + GaussBox(fx, fy, x1, y1, x2, y2); + + if InRange(ClickType, mouse_Right, mouse_move) then + Mouse(fx, fy, 0, 0, clickType) + else + srl_Warn('MouseBox', 'ClickType is NOT a valid number!', warn_AllVersions); +end; + +(* +MouseTBox +~~~~~~~~~ + +.. code-block:: pascal + + procedure MouseTBox(Box: TBox; ClickType: variant); + +Moves the mouse to the Indicated Box, and performs the ClickType + +.. note:: + + by PhaseCode + +Example: + Mouse(InvBox(1),1); +.. code-block:: pascal + +*) +procedure MouseTBox(Box: TBox; ClickType: variant); +begin + MouseBox(Box.X1, Box.Y1, Box.X2, Box.Y2, ClickType) +end; + +procedure MouseAction(mx, my, rx, ry: Integer; a: fnct_ActionOptions); +begin + case (a) of + Move: MMouse(mx, my, rx, ry); + ClickLeft: Mouse(mx, my, rx, ry, mouse_left); + ClickRight: Mouse(mx, my, rx, ry, mouse_right); + ClickMiddle: Mouse(mx, my, rx, ry, mouse_middle); + end; +end; + +(* +SleepAndMoveMouse +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SleepAndMoveMouse(Time: Integer); + +Waits for specified time and moves mouse around like bored human would. + +.. note:: + + by RsN + +Example: + +.. code-block:: pascal + +*) +procedure SleepAndMoveMouse(Time: Integer); +var + Moving: Boolean; + mx, my: Integer; + x, y, xv, yv: Extended; + gx, gy: Extended; + T: Integer; +begin + GetMousePos(mx, my); + x := mx; + y := my; + if (Random(2) = 0) then + Moving := False + else + Moving := True; + gx := 130 + Random(500); + gy := 130 + Random(300); + T := GetTickCount; + repeat + Sleep(10); + if (Moving) then + begin + if (gx > x) then + xv := xv + 0.1 + else + xv := xv - 0.1; + if (gy > y) then + yv := yv + 0.1 + else + yv := yv - 0.1; + x := x + xv; + y := y + yv; + MoveMouse(Round(x), Round(y)); + end; + if (Random(100) = 0) then + Moving := not Moving; + if (Random(30) = 0) then + begin + gx := 130 + Random(500); + gy := 130 + Random(300); + end; + until (Abs(GetTickCount - T) >= Time); +end; + +(* +IdleTime +~~~~~~~~ + +.. code-block:: pascal + + procedure IdleTime(Time, Rand: integer; Gravity: extended); + +Randomly moves the mouse (Rand, and Gravity) for Time milliseconds + +.. note:: + + by BenLand100 + +Example: + +.. code-block:: pascal + +*) +procedure IdleTime(Time, Rand: Integer; Gravity: Extended); +var + H, W, Cx, Cy, i, n, St: Integer; + Controls, Path: TPointArray; + LastC, LastP: TPoint; +begin + St := GetSystemTime; + GetClientDimensions(W, H); + SetArrayLength(Controls, 4); + GetMousePos(Cx, Cy); + LastP.x := Cx; + LastP.y := Cy; + LastC.x := LastP.x + (Random(Rand * 2) - Rand); + LastC.y := LastP.y + (Random(Rand * 2) - Rand); + repeat + Controls[0].x := LastP.x; + Controls[0].y := LastP.y; + Controls[1].x := LastP.x + -(LastC.x - LastP.x); + Controls[1].y := LastP.y + -(LastC.y - lastP.y); + Controls[2].x := Controls[1].x + (Random(Rand * 2) - Rand); + Controls[2].y := Controls[1].y + (Random(Rand * 2) - Rand); + Controls[3].x := Controls[2].x + (Random(Rand * 2) - Rand); + Controls[3].x := Controls[3].x + Round(-(Controls[3].x - (W / 2)) * + (Gravity)); + Controls[3].y := Controls[2].y + (Random(Rand * 2) - Rand); + Controls[3].y := Controls[3].y + Round(-(Controls[3].y - (H / 2)) * + (Gravity)); + LastC.x := Controls[2].x; + LastC.y := Controls[2].y; + LastP.x := Controls[3].x; + LastP.y := Controls[3].y; + Path := MakeSplinePath(Controls, 0.01); + Path := MidPoints(Path, 5); + n := GetArrayLength(Path); + for i := 0 to n - 1 do + begin + MoveMouse(Path[i].x, Path[i].y); + Wait(Random(2) + 2); + if (GetSystemTime - St >= Time) then Break + end; + until (GetSystemTime - St >= Time) +end; + +function WaitUpTextMulti(S: TStringArray; Time: Integer): Boolean; Forward; + +(* +SpiralMouseMulti +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function SpiralMouseMulti(var fx, fy: Integer; x1, y1, x2, y2: Integer; UpText: TStringArray; PpC, aInc: Integer): Boolean; + +Spirals the mouse in a circle from the center of the defined box. +It will continue to spiral until it finds a spiral completely outside +the box, always skipping points outside. +Returns the occurance of the first occurance of UpText into fx, fy. +Takes multiple UpTexts as a TStringArray. +PpC: The number of pixels to increase per spiral. +aInc: The number of stops to make around each spiral. +Takes some testing to get the right combination of PpC and aInc. + +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + +*) +function SpiralMouseMulti(var fx, fy: Integer; x1, y1, x2, y2: Integer; UpText: TStringArray; PpC, aInc: Integer): Boolean; +var + aStep, a, rStep, rV, oB: Extended; + pX, pY, ms: Integer; + sP: TPoint; + L2R: Boolean; +begin + Result := False; + ms := MouseSpeed; + MouseSpeed := 25 + RandomRange(-3, 3); + sP := MiddleTPA([Point(x1, y1), Point(x2, y2)]); + aStep := Pi / (aInc / 2); + a := 0; + rStep := (PpC / aInc); + L2R := Random(2) = 0; + //Writeln('aStep: ' + FloatToStr(aStep) + ' rStep ' + FloatToStr(rStep)); + repeat + rV := rV + rStep; + pX := Round(rV * cos(a)) + sP.x; + pY := Round(rV * sin(a)) + sP.y; + if L2R then + a := a + aStep + else + a := a - aStep; + if InRange(pX, x1, x2) and InRange(pY, y1, y2) then + begin + oB := 0; + MMouse(pX - 2, pY - 2, 5, 5); + if WaitUpTextMulti(UpText, 300) then + begin + GetMousePos(fx, fy); + Result := True; + end; + end else + oB := oB + aStep; + until Result or (oB > (2 * Pi)); + MouseSpeed := ms; +end; + +(* +SpiralMouse +~~~~~~~~~~~ + +.. code-block:: pascal + + function SpiralMouse(var fx, fy: Integer; x1, y1, x2, y2: Integer; UpText: String; PpC, aInc: Integer): Boolean; + +Spirals the mouse in a circle from the center of the defined box. +It will continue to spiral until it finds a spiral completely outside +the box, always skipping points outside. +Returns the occurance of the UpText into fx, fy. +See `SpiralMouseMulti` for more information +.. note:: + + by Nava2 + +Example: + +.. code-block:: pascal + +*) +function SpiralMouse(var fx, fy: Integer; x1, y1, x2, y2: Integer; UpText: String; PpC, aInc: Integer): Boolean; +begin + Result := SpiralMouseMulti(fx, fy, x1, y1, x2, y2, [UpText], PpC, aInc); +end; + + +(* +DidClick +~~~~~~~~ + +.. code-block:: pascal + + function DidClick(Red: Boolean; Time: integer): boolean; + +Checks for the X after a click, Times Out after Time. +DidClick Time must be at LEAST 200 now. + +.. note:: + + by Rasta Magician + Modded by Narcle on Feb. 4th, 2012 + +Example: + +.. code-block:: pascal + +*) +function DidClick(Red: Boolean; Time: integer): boolean; +var + TimeOut, x, y, w, h, R, G: integer; + B: TBox; +begin + GetMousePos(x, y); + GetClientDimensions(w, h); + B := IntToBox(x - 15, y - 15, x + 15, y + 15); + if B.x1 < 0 then B.x1 := 0; + if B.y1 < 0 then B.y1 := 0; + if B.x2 > w then B.x2 := w; + if B.y2 > h then B.y2 := h; + TimeOut := GetSystemTime + Time; + while (GetSystemTime < TimeOut) do + begin + R := CountColorTolerance(395675, B.x1, B.y1, B.x2, B.y2, 15); + G := CountColorTolerance(1695663, B.x1, B.y1, B.x2, B.y2, 15); + if Red then + begin + if (G > 8) then + Exit; + Result := (R > 20); + end else + begin + if (R > 5) then + Exit; + Result := (G > 35); + end; + if Result then + Exit; + end; +end; + +(* +DidRedClick +~~~~~~~~~~~ + +.. code-block:: pascal + + function DidRedClick: Boolean; + +Checks for the Red X after a Click, Times out after 500 ms + +.. note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + +*) +function DidRedClick: Boolean; +begin + Result := DidClick(true, 1000); +end; + +(* +DidYellowClick +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + + function DidYellowClick: Boolean; + +Checks for the Yellow X after a Click, Times out after 500 ms + +.. note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + +*) +function DidYellowClick: Boolean; +begin + Result := DidClick(false, 1000); +end; + +(* +MouseOval +~~~~~~~~~ + +.. code-block:: pascal + + procedure MouseOval(cx, cy, mx, my, clickType: Integer); + +Clicks a random point within an oval shape. + * cx, cy: The center point of the oval. + * rx, ry: X and Y radius of the oval. + * clickType: mouse_Move, mouse_Left, mouse_Right, or mouse_Middle. + +.. note:: + + by mixster + Last Updated: Unknown. + +Example: + +.. code-block:: pascal + +*) +procedure MouseOval(cx, cy, rx, ry, clickType: Integer); +var + o: TPoint; +begin + if not InRange(clickType, 0, 3) then + begin + srl_Warn('MouseOval', 'ClickType is NOT a valid number!', warn_AllVersions); + exit; + end; + + o.y := Random(ry) * ((Random(2) * 2) - 1); + o.x := Random(Round(Sqrt(Sqr(ry) - Sqr(o.y)) * rx / ry)) * ((Random(2) * 2) - 1); + + case clickType of + mouse_right..mouse_middle: Mouse(cx + o.x, cy + o.y, 0, 0, clickType); + mouse_move: MMouse(cx + o.x, cy + o.y, 0, 0); + end; +end; + +(* +MouseCircle +~~~~~~~~~~~ + +.. code-block:: pascal + + procedure MouseCircle(MidX, MidY, Radius, clickType: Integer); + +Same as MouseOval, but clicks within a circle instead. + +.. note:: + + by mixster + Last Updated: Mar. 21st, 2012 by Coh3n + +Example: + +.. code-block:: pascal + +*) +procedure MouseCircle(MidX, MidY, Radius, clickType: Integer); +begin + MouseOval(MidX, MidY, Radius, Radius, clickType); +end; + +(* +MouseBoxEx +~~~~~~~~~~ + +.. code-block:: pascal + + procedure MouseBoxEx(x1, y1, x2, y2: Integer; Dist,ClickType: Integer); + +Does mouse stuff (ClickType), and uses a point that is within Dist from +the closest point between mouse and the box. + +.. note:: + + by Raymond + +Example: + +.. code-block:: pascal + +*) +procedure MouseBoxEx(x1, y1, x2, y2: Integer; Dist,ClickType: Integer); +var + PT : TPoint; +begin + GetMousePos(pt.x,pt.y); + PT := RandomPointBoxEx(pt,inttobox(x1,y1,x2,y2),Dist); + case ClickType of + mouse_right..mouse_middle : Mouse(pt.x, pt.y, 0, 0, clickType); + mouse_move : MMouse(pt.x, pt.y, 0, 0); + else + srl_Warn('MouseBox', 'ClickType is NOT a valid number!', warn_AllVersions); + end; +end; + +(* +DragMouse +~~~~~~~~~ + +.. code-block:: pascal + + procedure DragMouse(StartX, StartY, SRandX, SRandY, EndX, EndY, ERandX, ERandY: Integer); + +Leftclicks StartX, StartY and drags mouse to EndX, EndY. + +.. note:: + + by NaumanAkhlaQ + +Example: + +.. code-block:: pascal + +*) +procedure DragMouse(StartX, StartY, SRandX, SRandY, EndX, EndY, ERandX, ERandY: Integer); +begin + MMouse(StartX, StartY, SRandX, SRandY); + Wait(150 + Random(20)); + GetMousePos(StartX, StartY); + HoldMouse(StartX, StartY, mouse_left); + Wait(250 + Random(320)); + MMouse(EndX, EndY, ERandX, ERandY); + Wait(250 + Random(120)); + GetMousePos(EndX, EndY); + ReleaseMouse(EndX, EndY, mouse_left); +end; + +(* +DragMouseTBox +~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure DragMouseTBox(StartBox, EndBox: TBox); + +Left clicks a point within StartBox and drags mouse to a point within EndBox, +of which the points selected follows a normal distribution from the centre of the box. + + +.. note:: + + by riwu, modelled after DragMouse by NaumanAkhlaQ + +Example: + +.. code-block:: pascal + +*) +procedure DragMouseTBox(StartBox, EndBox: TBox); +var + StartX, StartY, EndX, EndY: Integer; +begin + MouseTBox(StartBox, mouse_move); + Wait(150 + Random(20)); + GetMousePos(StartX, StartY); + HoldMouse(StartX, StartY, mouse_left); + Wait(250 + Random(320)); + MouseTBox(EndBox, mouse_move); + Wait(250 + Random(120)); + GetMousePos(EndX, EndY); + ReleaseMouse(EndX, EndY, mouse_left); +end; diff --git a/SRL/core/object.simba b/SRL/core/object.simba new file mode 100644 index 0000000..7b255fd --- /dev/null +++ b/SRL/core/object.simba @@ -0,0 +1,638 @@ +(* + +Object Finding +============== + +.. contents:: + +.. note:: + Remove?: + + - Several FindObj*() functions? + +*) +//-----------------------------------------------------------------// +//-- SRL Resource Library --// +//-- � ObjectFinding Routines --// +//-----------------------------------------------------------------// +// * function FindAllObjsRecord(var Objects: TPointArray; AutoInfo: TAutoColorInfo; x1, y1, x2, y2: Integer; QuickSorting, RGBXYZCheck: Boolean): Boolean; // By Sumilion +// * function FindObjRecordEx(var fx, fy: Integer; AutoInfo: TAutoColorInfo; QuickSorting, RGBXYZCheck: Boolean): Boolean; // By Sumilion +// * function FindObjRecord(var fx, fy: Integer; AutoInfo: TAutoColorInfo): Boolean; // By Sumilion +// * function FindObjEx(var cx, cy: Integer; Text: TStringArray; Color: TIntegerArray; Tol, CenterX, CenterY: Integer; Step: Extended; xs, ys, xe, ye: Integer): Boolean; // By Starblaster100 +// * function FindObj(var cx, cy: Integer; Text: string; Color, Tol: Integer): Boolean; // By Starblaster100 +// * function FindObjCustom(var cx, cy: Integer; Text: TStringArray; Color: TIntegerArray; Tol: Integer): Boolean; // By Starblaster100 +// * function FindObjectDeformed(var ObjX, ObjY :integer; UpText1, UpText2: String; BMP, a, b, c, d: integer): Boolean; // By WT-Fakawi +// * function FindObjTPA(Var x, y: Integer; color, tol, cts, ObjWidth, ObjHeight, minCount: Integer; UpText: string): Boolean; // By Wizzup +// * function FindObjTPAMulti(var X, Y: integer; Color: TIntegerArray; Tol, CTS, ObjWidth, ObjHeight, minCount :Integer; UpText: TStringArray): Boolean; // By: Torrent of Flame based on FindObjTPA +// * Function FindObjThroughMM(var x, y: Integer; Kind: String; Colors, Tol: TIntegerArray; UpText: TStringArray; Width, Height: Integer): boolean; // By N1ke! + +(* +FindAllObjsRecord +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindAllObjsRecord(var Objects: TPointArray; AutoInfo: TAutoColorInfo; x1, y1, x2, y2: Integer; QuickSorting, RGBXYZCheck: Boolean): Boolean; + +Finds an Object using a TAutoColorInfo record, returns the center of the found +objects. + +.. note:: + + by Sumilion + +Example: + +.. code-block:: pascal + +*) +function FindAllObjsRecord(var Objects: TPointArray; AutoInfo: TAutoColorInfo; x1, y1, x2, y2: Integer; QuickSorting, RGBXYZCheck: Boolean): Boolean; +var + arP, arAP: TPointArray; + arC, arUC: TIntegerArray; + ararP: T2DPointArray; + i, j, arL, arL2, tmpCTS: Integer; + R, G, B: Integer; + X, Y, Z: Extended; + arLC: Integer; +begin + with AutoInfo do + begin + tmpCTS := GetColorToleranceSpeed; + ColorToleranceSpeed(2); + SetColorSpeed2Modifiers(HueMod, SatMod); + + if not(FindColorsTolerance(arP, Color, x1, y1, x2 - 3, y2 - 3, LumTol)) then + begin + //Writeln('Failed to find the object.'); + ColorToleranceSpeed(tmpCTS); + SetColorSpeed2Modifiers(0.2, 0.2); + Exit; + end; + + Result := True; + + if RGBXYZCheck then + begin + arC := GetColors(arP); + arUC := arC; + ClearSameIntegers(arUC); + arL := High(arUC); + arL2 := High(arC); + + for i := 0 to arL do + begin + ColorToRGB(arC[i], R, G, B); + + if (R >= MinR) and (R <= MaxR) and (G >= MinG) and (G <= MaxG) and (B >= MinB) and (B <= MaxB) then + begin + ColorToXYZ(arC[i], X, Y, Z); + + if (X >= MinX) and (X <= MaxX) and (Y >= MinY) and (Y <= MaxX) and (Z >= MinZ) and (Z <= MaxZ) then + begin + SetLength(arAP, arL2 + 1); + for j := 0 to arL2 do + if (arUC[i] = arC[j]) then + begin + arAP[arLC] := arP[j]; + Inc(arLC); + end; + SetLength(arAP, arLC); + end; + end; + end; + end else + arAP := arP; + + if QuickSorting then + ararP := TPAtoATPA(arAP, MaxDist) + else + ararP := SplitTPA(arAP, MaxDist); + + arL := High(ararP); + SetLength(Objects, arL + 1); + arLC := 0; + + for i := 0 to arL do + begin + if (Length(ararP[i]) < MinCount) then Continue; + if (Length(ararP[i]) > MaxCount) and (MaxCount > 0) then Continue; + Objects[arLC] := MiddleTPA(ararP[i]); + Inc(arLC); + end; + SetLength(Objects, arLC); + + ColorToleranceSpeed(tmpCTS); + SetColorSpeed2Modifiers(0.2, 0.2); + end; +end; + +(* +FindAllObjsRecordEx +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindObjRecordEx(var fx, fy: Integer; AutoInfo: TAutoColorInfo; QuickSorting, RGBXYZCheck: Boolean): Boolean; + +Finds an Object using a TAutoColorInfo record with extra options. + +.. note:: + + by Sumilion + +Example: + +.. code-block:: pascal + +*) +function FindObjRecordEx(var fx, fy: Integer; AutoInfo: TAutoColorInfo; x1, y1, x2, y2: Integer; QuickSorting, RGBXYZCheck: Boolean): Boolean; +var + arP: TPointArray; + i, arL: Integer; +begin + with AutoInfo do + begin + if FindAllObjsRecord(arP, AutoInfo, x1, y1, x2, y2, QuickSorting, RGBXYZCheck) then + begin + SortTPAFrom(arP, Point(MSCX, MSCY)); + arL := High(arP); + + if UpText <> '' then + begin + i := Length(UpTextMulti); + SetLength(UpTextMulti, i + 1); + UpTextMulti[i] := UpText; + end; + + + for i := 0 to arL do + begin + if (Distance(arP[i].x, arP[i].y, MSCX, MSCY) > MaxDistCenter) and (MaxDistCenter > 0) then Continue; + MMouse(arP[i].x, arP[i].y, 5, 5); + Wait(100 + Random(100)); + if (Length(UpTextMulti) > 0) then + if WaitUpTextMulti(UpTextMulti, 300) then + begin; + Result := True; + Break; + end; + end; + + if (i = arL + 1) then + begin + //Writeln('FindObjRecord could not find the object.'); + Exit; + end; + + GetMousePos(fx, fy); + end; + end; +end; + +(* +FindObjRecord +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindObjRecord(var fx, fy: Integer; AutoInfo: TAutoColorInfo): Boolean; + +Finds an Object using a TAutoColorInfo record. + +.. note:: + + by Sumilion + +Example: + +.. code-block:: pascal + +*) +function FindObjRecord(var fx, fy: Integer; AutoInfo: TAutoColorInfo): Boolean; +begin + Result := FindObjRecordEx(fx, fy, AutoInfo, MSX1, MSY1, MSX2, MSY2, False, True); +end; + +(* +FindObjEx +~~~~~~~~~ + +.. code-block:: pascal + + function FindObjEx(var cx, cy: Integer; Text: TStringArray; Color: TIntegerArray; + Tol, Step, xs, ys, xe, ye: Integer): Boolean; + +Searches for an object using an array of colors and texts within the area +you specify. Will start searching from the middle and returns true if found. +Parameters: + + - cx, cy: Coordinate Position of object if result is true + - Text: Array of string you want to search for + - Color: Array of colors you want to search for + - Tol: Tolerance of the colors you will allow + - Step: How big you want to make the search squares. + 50 = Default. 30-70 Recommended + - xs, ys, xe, ye: Bounds you want to search in + +.. note:: + + by Starblaster100 + + +Example: + +.. code-block:: pascal + +*) +function FindObjEx(var cx, cy: Integer; Text: TStringArray; Color: TIntegerArray; + Tol, Step, xs, ys, xe, ye: Integer): Boolean; +var + MidX, MidY, i, j, k, x, y, width, height, HalfWidth, HalfHeight: Integer; + ColorFound: Boolean; + SearchBoxes: Array of Array of TBox; + p: TPointArray; +begin + Result := False; + + //check for all the colors + for i := 0 to (GetArrayLength(Color)-1) do + if (FindColorSpiralTolerance(cx, cy, Color[i], xs, ys, xe, ye, Tol)) then + begin + ColorFound := True; + Break; + end; + + if not(ColorFound) then + Exit; //None of the colors could be found on screen + + //Start coordinates + MidX := Round((xe - xs) / 2); + MidY := Round((ye - ys) / 2); + + //width and height in boxes + Width := Ceil(abs(xe - xs) / 2 / Step - 0.5) * 2 + 1; + Height := Ceil(abs(ye - ys) / 2 / Step - 0.5) * 2 + 1; + + SetLength(SearchBoxes, Width); + + //Getting mid of screen in boxes, not pixels + HalfWidth := Floor(Width / 2); + HalfHeight := Floor(Height / 2) + + //Create the search boxes, starting in mid because of backwards compatibility + for x := -1 * HalfWidth to HalfWidth do + begin + SetLength(SearchBoxes[x + HalfWidth], Height); + for y := -1 * HalfHeight to HalfHeight do + SearchBoxes[x + HalfWidth][y + HalfHeight] := IntToBox( + Max(xs, xs + Round(MidX + ((x - 0.5) * Step))), + Max(ys, ys + Round(MidY + ((y - 0.5) * Step))), + Min(xe, xs + Round(MidX + ((x + 0.5) * Step))), + Min(ye, ys + Round(MidY + ((y + 0.5) * Step)))); + end; + + //Create a TPA, where points are representing the boxes + p := TPAFromBox(IntToBox(0, 0, Width-1, Height-1)); + + //Sort thid TPA from the middle to get a spiral like effect + SortTPAFrom(p, Point(floor(Width / 2), floor(Height / 2))); + + //Loop through the boxes, searching for the object (the k and j loop might be better to switch though) + for k := 0 to High(Color) do + for j := 0 to High(p) do + begin + if (FindColorTolerance(cx, cy, Color[k], SearchBoxes[p[j].x][p[j].y].x1, + SearchBoxes[p[j].x][p[j].y].y1, SearchBoxes[p[j].x][p[j].y].x2, + SearchBoxes[p[j].x][p[j].y].y2, Tol)) then + begin + MMouse(cx, cy, 3, 3); + If (WaitUptextMulti(Text, 300)) then + begin + GetMousePos(cx, cy); + Result := True; + Exit; + end; + end; + end; +end; + +(* +FindObj +~~~~~~~ + +.. code-block:: pascal + + + function FindObj(var cx, cy: Integer; Text: string; Color, Tol: Integer): Boolean; + +Finds Object + +.. note:: + + by Starblaster100 + +Example: + +.. code-block:: pascal + +*) +function FindObj(var cx, cy: Integer; Text: string; Color: Integer; Tol: Integer): Boolean; +begin + Result := FindObjEx(cx, cy, [Text], [Color], Tol, 50, MSX1, MSY1, MSX2, MSY2); +end; + +(* +FindObjCustom +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindObjCustom(var cx, cy: Integer; Text: TStringArray; Color: TIntegerArray; Tol: Integer): Boolean; + +Finds Object with custom amount of colors and custom amount of Uptext + +.. note:: + + by Starblaster100 + +Example: + +.. code-block:: pascal + + FindObjCustom(x, y, ['att', 'ack'], [123456, 345678], 5); + +*) +function FindObjCustom(var cx, cy: Integer; Text: TStringArray; Color: TIntegerArray; Tol: Integer): Boolean; +begin + Result := FindObjEx(cx, cy, Text, Color, Tol, 50, MSX1, MSY1, MSX2, MSY2); +end; + +(* +FindObjectDeformed +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindObjectDeformed(var ObjX, ObjY: Integer; UpText1, UpText2: String; BMP, a, b, c, d: Integer): Boolean; + +Finds Object in Box a,b,c,d, specified by BitMap and Uptext1 or Uptext2 +Returns coords in ObjX and ObjY. +Uses Deformed Bitmap. FindObjectDeformed will gradually lower Tol and reduce +Accuracy. +Functon can cause severe Lag when using bitmaps bigger than 16 pixels. + +Works but lags. + +.. note:: + + by WT-Fakawi + +Example: + +.. code-block:: pascal + +*) +function FindObjectDeformed(var ObjX, ObjY: Integer; UpText1, UpText2: string; + BMP, a, b, c, d: Integer): Boolean; +var + acc, ref: Extended; + XT, YT, times, tol: Integer; +begin + ref := 0.9; + tol := 0; + for times := 1 to 50 do + begin + FindDeformedBitmapToleranceIn(BMP, XT, YT, a, b, c, d, tol, 2, True, acc); + if (acc >= ref) then + begin + MMouse(XT, YT, 0, 0); + if (WaitUptextMulti([UpText1, UpText2], 300)) then + begin + ObjX := XT; + ObjY := YT; + Result := True; + Exit; + end; + end; + if times mod 5 = 0 then + begin + ref := ref - 0.1; + tol := tol + 10; + end; + Wait(1); + end; +end; + +(* +FindObjTPA +~~~~~~~~~~ + +.. code-block:: pascal + + function FindObjTPA(var x, y: integer; color, tol, cts, ObjWidth, ObjHeight, minCount :Integer; UpText: tstringarray): Boolean; + +Finds object using WizzyPlugin functions. Starts with a Spiral from x and y. +Put in the color, Tolerance and ColorToleranceSpeed. +If you don't know what colortolerancespeed to choose, put in -1. +ObjWidth and ObjHeight are the parameters TPAToATPAEx uses, thus filtering +the MS's FindColorsSpiralTolerance points in boxes defined by +ObjWidth and ObjHeigth. +minCount is the amount of colors it should at least find in a Object box. +UpText, is ofcourse the text the object should have. In the Multi variant the +UpText is a string array. + +.. note:: + + by Wizzup? + +Example: + +.. code-block:: pascal + +*) +function FindObjTPA(var X, Y: Integer; Color, Tol, CTS, ObjWidth, ObjHeight, minCount: Integer; UpText: TStringArray): Boolean; +var + I, tCTS: Integer; + myPoint: TPoint; + Points: TPointArray; + aPoints: T2DPointArray; +begin + Result := False; + if not LoggedIn then exit; + tCTS := GetColorToleranceSpeed; + CTS := Integer(CTS * 9 mod 3 <> 0); + ColorToleranceSpeed(CTS); + FindColorsSpiralTolerance(X, Y, Points, Color, MSX1, MSY1, MSX2, MSY2, Tol); + if Length(Points) = 0 then + begin + ColorToleranceSpeed(tCTS); + Exit; + end; + ColorToleranceSpeed(1); + aPoints := TPAtoATPAEx(Points, ObjWidth, ObjHeight); + SetLength(Points, 0); + for I := 0 to High(aPoints) do + begin + if Length(aPoints[i]) < minCount then + Continue; + myPoint := MiddleTPA(aPoints[i]); + MMouse(myPoint.X, myPoint.Y, 0, 0); + if WaitUpTextMulti(UpText, 300) then + begin + GetMousePos(X, Y); + Result := True; + ColorToleranceSpeed(tCTS); + Exit; + end; + end; + ColorToleranceSpeed(tCTS); +end; + +(* +FindObjTPAMulti +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindObjTPAMulti(var X, Y: integer; Color: TIntegerArray; Tol, CTS, ObjWidth, ObjHeight, minCount :Integer; UpText: TStringArray): Boolean; + +This is a modification of FindObjTPA, which uses a TIntegerArray for the Colors. + +.. note:: + + by Torrent of Flame based on FindObjTPA + +Example: + +.. code-block:: pascal + +*) +function FindObjTPAMulti(var X, Y: Integer; Colour: TIntegerArray; Tol, CTS, ObjWidth, ObjHeight, minCount: Integer; UpText: TStringArray): Boolean; +var + i, tCTS: Integer; + myPoint: TPoint; + aPoints: T2DPointArray; + ATPA: T2DPointArray; + TPA: TPointArray; +begin + Result := False; + if not LoggedIn then exit; + tCTS := GetColorToleranceSpeed; + CTS := Integer(CTS * 9 mod 3 <> 0); + ColorToleranceSpeed(CTS); + SetLength(ATPA, Length(Colour)); + for i := 0 to High(Colour) do + begin + FindColorsSpiralTolerance(x, y, ATPA[i], Colour[i], MSX1, MSY1, MSX2, MSY2, Tol); + end; + TPA := MergeATPA(ATPA); + if Length(TPA) = 0 then + begin + ColorToleranceSpeed(tCTS); + Exit; + end; + ColorToleranceSpeed(1); + aPoints := TPAtoATPAEx(TPA, ObjWidth, ObjHeight); + for I := 0 to High(aPoints) do + begin + if Length(aPoints[i]) < minCount then + Continue; + myPoint := MiddleTPA(aPoints[i]); + MMouse(myPoint.x, myPoint.y, 0, 0); + if WaitUpTextMulti(UpText, 300) then + begin + GetMousePos(X, Y); + Result := True; + ColorToleranceSpeed(tCTS); + Exit; + end; + end; + + ColorToleranceSpeed(tCTS); +end; + +(* +FindObjThroughMM +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindObjThroughMM(var x, y: Integer; Kind: string; Colors, Tol: TIntegerArray; UpText: TStringArray; Width, Height: Integer): boolean; + +Finds a object with the given parameters. +Uses minimap dots to get locations of objects. +Will put the matching areas first in the TPA array,so it hovers those +first. + +.. note:: It still searches the whole screen, but it puts items first in + the array. + +Valid kinds are: + - npc/yellow + - item/red + - player/white + +.. note:: + + by N1ke! + +Example: + +.. code-block:: pascal + +*) +function FindObjThroughMM(var x, y: Integer; Kind: string; Colors, Tol: TIntegerArray; UpText: TStringArray; Width, Height: Integer): boolean; +var + ATPA: T2DPointArray; + TPA, TPA2, TPA3: TPointArray; + I, II, H, HH, ArrC: Integer; +begin + SetLength(ATPA, Length(Colors)); + + H := High(Colors); + for I:= 0 to H do + FindColorsTolerance(ATPA[i], Colors[i], MSX1, MSY1, MSX2, MSY2, Tol[i]); + + TPA := MergeATPA(ATPA); + ATPA := TPAToATPAEx(TPA, Width, Height); + + SetLength(TPA, GetArrayLength(ATPA)); + H := High(TPA); + for i:= 0 to H do + TPA[i] := MiddleTPA(ATPA[i]); + + TPA2 := GetMiniMapDots(Kind); + H := High(TPA2); + for I:=0 to H do + TPA2[i] := MMToMS(TPA2[i]); + + H := High(TPA); + HH := High(TPA2); + SetArrayLength(TPA3, GetArrayLength(TPA)); + for I:=0 to H do + for II:=0 to HH do + If IntInBox(TPA[i].X, TPA[i].Y, IntToBox(TPA2[II].X-55, TPA2[II].Y-55, TPA2[II].X+55, TPA2[II].Y+55)) then + begin + TPA3[ArrC] := TPA[i]; + Inc(ArrC); + Break; + end; + SetArrayLength(TPA3, ArrC); + ClearTPAFromTPA(TPA, TPA3); + TPA := CombineTPA(TPA3, TPA); + + SortTPAFrom(TPA, Point(MSCX, MSCY)); + + H := High(TPA); + for I:=0 to H do + begin + MMouse(TPA[i].X, TPA[i].Y, 4, 4); + If WaitUptextMulti(UpText, 250+Random(100))then + begin + GetMousePos(X, Y); + Result := True; + Exit; + end; + end; +end; diff --git a/SRL/core/players.simba b/SRL/core/players.simba new file mode 100644 index 0000000..27b4f0b --- /dev/null +++ b/SRL/core/players.simba @@ -0,0 +1,266 @@ +(* + +Player Management +================= + +.. contents:: + +.. note:: + + TODO: + + - Document variables + +*) +//-----------------------------------------------------------------// +//-- SRL Resource Library --// +//-- � PlayerArray Routines --// +//-----------------------------------------------------------------// +// * function LoggedIn: Boolean; // by WT-Fakawi +// * procedure NumberOfPlayers(Number: Integer); // by BenLand100 & Wizzup? +// * procedure SetPlayerNameTPAs; // by ??? +// * function PlayersActive: Integer; // by ss23 +// * function AllPlayersInactive: Boolean; // by ZephyrsFury + +{ type TUser; + Description: The User Record. } +type + TUser = record + Name: string; // * User Name + Pass: string; // * User Pass + Pin: string; // * Current Users Pin Number + Member: boolean; // * For Login + WorldInfo: TVariantArray; // * [Members {Boolean}, World {Integer}, PVP {Boolean}] + Nick: string; // * Screen Name for random detection + {NickTPA: TPointArray; // * TPA Of Player Name} + Level: array[0..24] of Integer; // * Levels of all skills. + Active: Boolean; // * Set to True if Ok, False if Lost. + Loc: string; // * User Location + Status: string; // * User Status + Skill: string; // * User Action to Perform + ActionBarSet: Boolean; // * Used in SwitchActionBar + LampSkill: Integer; + Worked: Integer; // * Time User has worked + Banked: Integer; // * Number of Banks User has done + Rand: string; // * Current Random + Booleans: array of Boolean; // * For reports, etc. + Integers: array of Integer; // * For reports, etc. + Strings: array of string; // * For reports, etc. + Extendeds: array of Extended; // * For reports, etc. + Arrays: array of TVariantArray; // * For custom arrays. + BoxRewards: TStringArray; // * Partial texts for rewards, place in desired order. + end; + +{ const Skills consts + Description: To be used with Players.Level[] array + Players woodcutting level: Players[i].Level[Skill_WoodCutting] + Last Edit: 22 June 2010 -- Nava2 +} +const + SKILL_COUNT = 28; + SKILL_ATTACK = 0; + SKILL_DEFENCE = 1; + SKILL_STRENGTH = 2; + SKILL_HITPOINTS = 3; SKILL_HP = SKILL_HITPOINTS; + SKILL_RANGE = 4; + SKILL_PRAYER = 5; + SKILL_MAGIC = 6; + SKILL_COOKING = 7; + SKILL_WOODCUTTING = 8; + SKILL_FLETCHING = 9; + SKILL_FISHING = 10; + SKILL_FIREMAKING = 11; + SKILL_CRAFTING = 12; + SKILL_SMITHING = 13; + SKILL_MINING = 14; + SKILL_HERBLORE = 15; + SKILL_AGILITY = 16; + SKILL_THIEVING = 17; + SKILL_SLAYER = 18; + SKILL_FARMING = 19; + SKILL_RUNECRAFTING = 20; + SKILL_HUNTER = 21; + SKILL_CONSTRUCTION = 22; + SKILL_SUMMONING = 23; + SKILL_DUNGEONEERING = 24; + SKILL_ALLCOMBAT = 25; + SKILL_EVERYSKILL = 26; + SKILL_NONE = 27; + +// * Antirandom const +{ var UseSandwichSolver, UseBoxSolver, UseCerterSolve: Boolean; + Description: For Slower Computers you may turn off and it will use other means to solve or logout. } +var + UseFindMod, UseFindTrade: Boolean; + +{ var Players: Array of TUser; + Description: Array of users. } +var + Players: array of TUser; + CurrentPlayer, HowManyPlayers: Integer; + +{ var CheckHpFirst: Boolean; + Description: If you want the script to look at the hp and see that it's been lowered before it runs away from a fight. } +var + CheckHpFirst: Boolean; + +{ var ReinCarnate: Boolean; + Description: If you want your Status to stay True when you die. (Autofighters) } +var + ReinCarnate: Boolean; + +{ var LogoutOnMod: Boolean; + Description: If you wish to logout, wait then login again when a mod is found. } +var + LogoutOnMod: Boolean; + +var + PlayerCurTime, PlayerStartTime: LongInt; + + +(* +LoggedIn +~~~~~~~~ + +.. code-block:: pascal + + function LoggedIn: Boolean; + +Returns True if Logged in. + +.. note:: + + by WT-Fakawi + +Example: + +.. code-block:: pascal + +*) +function LoggedIn: Boolean; +begin + //White text on Report Abuse Button + SRL_ResetNavBar; + Result := (GetColor(472, 490) = 16777215); +end; + +(* +NumberOfPlayers +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure NumberOfPlayers(Number: Integer); + +Makes the Players array have Number indexes, also sets strings and +other player array's too standard 100. + +.. note:: + + by BenLand100 / Wizzup? + +Example: + +.. code-block:: pascal + +*) +procedure NumberOfPlayers(Number: Integer); +var + I: Integer; +begin + SetLength(Players, Number); + HowManyPlayers := Number; + for I := 0 to HowManyPlayers - 1 do + begin + SetLength(Players[i].Strings, 100); + SetLength(Players[i].Integers, 100); + SetLength(Players[i].Booleans, 100); + SetLength(Players[i].Extendeds, 100); + SetLength(Players[i].Arrays, 100); + end; +end; + +(* +PlayersActive +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function PlayersActive: Integer; + +Numbers of players active in the Players array. + +.. note:: + + by ss23 + +Example: + +.. code-block:: pascal + +*) +function PlayersActive: Integer; +var + i, h: Integer; +begin + Result := 0; + h := High(Players); + for i := 0 to h do + if (Players[i].Active) then + Inc(Result); +end; + +(* +AllPlayersInactive +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure NumberOfPlayers(Number: Integer); + +Returns true if all players are inactive in the Players array. + +.. note:: + + by ZephyrsFury + +Example: + +.. code-block:: pascal + +*) +function AllPlayersInactive: Boolean; +begin + Result := (PlayersActive = 0); +end; + +(* +PlayerWorked +~~~~~~~~~~~~ + +.. code-block:: pascal + + function PlayerWorked(player : integer) : integer; + +Returns the time a player has worked.. + +.. note:: + + by SRL Community + +Example: + +.. code-block:: pascal + +*) +function PlayerWorked(player: integer): integer; +begin + if (player = currentPlayer) then + if (playerStartTime > 0) then // if it's been set at all + begin + incEx(players[player].worked, (getSystemTime - playerStartTime)); + playerStartTime := getSystemTime; + end; + + result := players[player].worked; +end; diff --git a/SRL/core/rc.simba b/SRL/core/rc.simba new file mode 100644 index 0000000..a9fc9f6 --- /dev/null +++ b/SRL/core/rc.simba @@ -0,0 +1,319 @@ +//----------------------------------------------------------------------------// +//-- SRL Resource Library --// +//-- » Remote Control Routines Beta --// +//----------------------------------------------------------------------------// +// * procedure RC_SetStandards; // * by N1ke! +// * function RCReadCommand: String; // * by WT-Fakawi +// * function RC_MasterCalls(var RC_S: String): Boolean; // * by N1ke! +// * function RC_PMFound: Boolean; // * by N1ke! +// * function RC_Busy: Boolean; // * by N1ke! +// * function RC_ReturnStatus: string; // * by N1ke! +// * procedure RC_FixFL; // * by N1ke! +// * function RC_MasterOnline(Var MasterCords: TPoint; Master: String): Boolean; // * by N1ke! +// * function RC_TakeAction(AN: Integer; RC_Master: String): Boolean; // * by WT-Fakawi +// * function RC: Boolean // * by WT-Fakawi Rewritten by N1ke! +// * procedure SetupRC(Masters: TStringArray); // * by N1ke! + +Type + RC_Action = Record + Triggers: TStringArray; + Action: Integer; + end; + +var + RC_Actions: Array [0..4] of RC_Action; + RC_Masters: TStringArray; + RC_TSL : Integer; + RC_InUse: Boolean; + RC_StartLocs: TStringArray; + +{******************************************************************************* +Procedure RC_SetStandards; +by: N1ke! +Description: Sets your account settings so that you can use the +features in RC.Scar. +*******************************************************************************} +procedure RC_SetStandards; +begin + SetChat('hide', 1); + SetChat('friends', 2); + + if not GameTab(tab_Options) then + Exit; + + Wait(175+Random(120)); + if (GetColor(678, 341) = 987203) then + Mousebox(684, 344, 713, 372, mouse_left); +end; + +{******************************************************************************* +function RCReadCommand: String; +by: WT-Fakawi Small fix by N1ke! +Description: Returns string of red typed message (color 128) +*******************************************************************************} +function RC_ReadCommand: string; +var + LC:TPoint; +begin + LC := TextCoords(8); + Result := LowerCase(Trim(GetTextAtEx(LC.x - 2, LC.y - 2, 45, SmallChars, False, False, 0, + 2, 128, 45, False, tr_NormalChars))); +end; + +{******************************************************************************* +function RC_MasterCalls(var RC_S: string): Boolean; +by: N1ke! +Description: Checks if it's a master typing to you and if so it will +get the masters name. +*******************************************************************************} +function RC_MasterCalls(var RC_S: string): Boolean; +var + S: String; + I, H: Integer; +begin + S := LowerCase(GetChatBoxText(8, clBlack)); + H := High(RC_Masters); + for I:= 0 to H do + If Pos(RC_Masters[i], S) > 0 then + begin + Result := True; + Delete(S, 1, 5); + Delete(S, Length(S), Length(S)); + RC_S := S; + Exit; + end; +end; + +{******************************************************************************* +function RC_PMFound: Boolean; +by: WT-Fakawi +Description: Returns True if Color 128 (red) was found in ChatWindow. +*******************************************************************************} +function RC_PMFound: Boolean; +var + dumX, dumY: Integer; +begin + Result := FindColor(dumX, dumY, 128, MCX1, MCY1, MCX1 + 30, MCY2); +end; + +{******************************************************************************* +function RC_Busy: Boolean; +by: N1ke! +Description: Checks if you've done a trigger in the last 5 mins. +*******************************************************************************} +function RC_Busy: Boolean; +begin + Result := (GetSystemTime - RC_TSL < 60000*5); +end; + +{******************************************************************************* +function RC_ReturnStatus: string; +by: N1ke! +Description: Returns how many players are active. +If every player is active it results "Everything is cool." +*******************************************************************************} +function RC_ReturnStatus: string; +begin + If PlayersActive < HowManyPlayers then + begin + Result := IntToStr(PlayersActive) + ' out of ' + IntToStr(HowManyPlayers); + Exit; + end; + Result := 'Everything is cool.'; +end; + +{******************************************************************************* +procedure RC_FixFL; +by: N1ke! +Description: Scrolls to the top of the Friend list. +*******************************************************************************} +procedure RC_FixFL; +begin + If (GetColor(729, 248) = 2106924) then + Mouse(729, 248, 5, 2, mouse_left); +end; + +{******************************************************************************* +function RC_MasterOnline(Var MasterCords: TPoint; Master: string): Boolean; +by: N1ke! +Description: Checks if the master given is online, and results +his cords on the Friend list. +*******************************************************************************} +function RC_MasterOnline(Var MasterCords: TPoint; Master: string): Boolean; +var + I: Integer; + S: string; +begin + If not GameTab(tab_Friends) then + Exit; + Wait(175+Random(140)); + RC_FixFL; + for I:=0 to 12 do + If not (GetColor(675, 233+(15*I)) = 255) then + begin + S := LowerCase(Trim(GetTextAtEx(558, 231+(15*I), 45, FriendChars, True, False, 0, 2, 16777215, 20, False, tr_AllChars))); + Writeln(S); + If S = Lowercase(Master) then + begin + MasterCords := Point(576, 236+(15*I)); + Result := True; + Exit; + end; + end; +end; + +{******************************************************************************* +function RC_TakeAction(AN: Integer; RC_Master: String): Boolean; +by: N1ke! +Description: Performs the action given in AN and sometimes responds +them using the given master. +*******************************************************************************} +function RC_TakeAction(AN: Integer; RC_Master: string): Boolean; +var + S: String; + MasterCords: TPoint; + I: Integer; +begin + Result := False; + Case AN Of + 1: + begin + Writeln('[RC.Scar] - Checking player status..'); + S := RC_ReturnStatus; + Writeln('[RC.Scar] - ' + S); + If Not GameTab(tab_Friends)then + Exit; + Wait(175+Random(125)); + If Not RC_MasterOnline(MasterCords, Lowercase(RC_Master))then + begin + srl_Warn('RC_TakeAction', 'Problems finding master', warn_AllVersions); + Exit; + end; + Mouse(MasterCords.X, MasterCords.Y, 25, 3, mouse_left); + Wait(255+Random(175)); + TypeSend(S); + Result := True; + end; + + 2: + begin + Writeln('[RC.Scar] - Reseting players..'); + For I:=0 to High(RC_StartLocs)do + If Not I = CurrentPlayer then + begin + Players[i].Active := True; + Players[i].Loc := RC_StartLocs[i]; + end; + AddToSRLLog('********** RC.SCAR RESET '); + Result := True; + end; + + 3: + begin + Writeln('[RC.Scar] - Stopping script..'); + If LoggedIn then + Logout; + TerminateScript; + end; + + 4: + begin + Writeln('[RC.Scar] - Logging out..'); + Logout; + Result := True; + end; + + 5: + begin + if SRL_HasProc(srl_OnCustomRC) then + SRL_Procs[srl_OnCustomRC](); + Result := True; + end; + + else + begin + srl_Warn('RC_TakeAction', 'Unknown action trigger, [' + IntToStr(AN) + ']', warn_AllVersions); + Exit; + end; + end; +end; + +{******************************************************************************* +function RC: Boolean; +by: WT-Fakawi rewritten by N1ke! +Description: High Level Remote Control Command. Handles Remote Control. +Works as follows: +Checks for existence of red color in chat window. +If red color is found, it checks if it's from any of the given masters. +If found it waits peforms the given action. +Then RC sleeps five minutes to get rid of the red text. +*******************************************************************************} +function RC: Boolean; +var + S, Master: string; + I, II: Integer; +begin + Result := False; + if not RC_InUse then + Exit; + if (RC_Busy) or (not RC_PMFound) then + Exit; + if not RC_MasterCalls(Master) then + Exit; + S := RC_ReadCommand; + if (S = '') then + Exit; + Writeln('Got a PM from master(' + Master + '), checking for triggers...'); + + for I:=0 to High(RC_Actions) do + for II:=0 to High(RC_Actions[i].Triggers) do + If Pos(RC_Actions[i].Triggers[II], S) > 0 then + begin + RC_TakeAction(RC_Actions[i].Action, Master); + RC_TSL := GetSystemTime; + Exit; + end; +end; + +{******************************************************************************* +procedure SetupRC(Masters: TStringArray); +by: N1ke! +Description: Sets up everything needed to use RC.scar. +Needs to be executed AFTER DeclarePlayers. +*******************************************************************************} +procedure SetupRC(Masters: TStringArray); +var + I: Integer; +begin + If GetArrayLength(Masters) = 0 then + begin + srl_Warn('SetupRC', 'No masters given - RC will not be used.', warn_AllVersions); + Exit; + end; + Writeln('Setting up RC..'); + + RC_Masters := Masters; + RC_InUse := True; + + SetArrayLength(RC_StartLocs, HowManyPlayers); + For I:=0 to High(RC_StartLocs)do + RC_StartLocs[i] := Players[CurrentPlayer].Loc; + + RC_Actions[0].Triggers := ['status', 'check', 'hows it going']; + RC_Actions[0].Action := 1; + + RC_Actions[1].Triggers := ['reset', 'back from square one', 'rewind']; + RC_Actions[1].Action := 2; + + RC_Actions[2].Triggers := ['stop', 'enough', 'come outside']; + RC_Actions[2].Action := 3; + + RC_Actions[3].Triggers := ['logout', 'log']; + RC_Actions[3].Action := 4; + + RC_Actions[4].Triggers := ['that thing', 'hey', 'remember']; + RC_Actions[4].Action := 5; + + If LoggedIn Then + RC_SetStandards; +end; diff --git a/SRL/core/simba.simba b/SRL/core/simba.simba new file mode 100644 index 0000000..113b4ac --- /dev/null +++ b/SRL/core/simba.simba @@ -0,0 +1,487 @@ +//-----------------------------------------------------------------// +//-- Scar Standard Resource Library --// +//-- Simba.simba --// +//-----------------------------------------------------------------// + +function VariantIsInteger(const v: Variant): Boolean; +begin + case VarType(v) of + varByte, + varShortInt, + varSmallInt, + varWord, + varInteger, + varLongWord, + varInt64: Result := True; + else Result := False; + end; +end; + +function VariantIsFloat(const v: Variant): Boolean; +begin + case VarType(v) of + varCurrency, + varSingle, + varDouble: Result := True; + else Result := False; + end; +end; + +function VariantIsNumber(const v: Variant): Boolean; +begin + Result := VariantIsInteger(v) or VariantIsFloat(v); +end; + +function VariantIsString(const v: Variant): Boolean; +begin + case VarType(v) of + varOleStr, + varString: Result := True; + else Result := False; + end; +end; + +function VariantIsBoolean(const v: Variant): Boolean; +begin + Result := VarType(v) = varBoolean; +end; + +(* +tmp_TPAFromLine +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function tmp_TPAFromLine(const x1, y1, x2, y2: Integer): TPointArray; + +Returns a TPA of the points that make up a line connecting the points (x1, y1) +and (x2, y2) and most closely follow the slope of that line. + +.. note:: + + by euphemism + Last modified: Jan. 31st, 2013 by euphemism + +Example: + +.. code-block:: pascal + + TPA := TPAFromLine(10, 10, 30, 20); +*) +function tmp_TPAFromLine(const x1, y1, x2, y2: Integer): TPointArray; +var + Dx, Dy, CurrentX, CurrentY, Len, TwoDx, TwoDy, Xinc, YInc: Integer; + TwoDxAccumulatedError, TwoDyAccumulatedError: Integer; +begin + Len := 0; + Dx := (X2 - X1); + Dy := (Y2 - Y1); + TwoDx := Dx + Dx; + TwoDy := Dy + Dy; + CurrentX := X1; + CurrentY := Y1; + Xinc := 1; + Yinc := 1; + if (Dx < 0) then + begin + Xinc := - 1; + Dx := - Dx; + TwoDx := - TwoDx; + end; + if (Dy < 0) then + begin + Yinc := - 1; + Dy := - Dy; + TwoDy := - TwoDy; + end; + SetLength(Result, 1); + Result[0] := Point(X1, Y1); + if ((Dx <> 0) or (Dy <> 0)) then + begin + if (Dy <= Dx) then + begin + TwoDxAccumulatedError := 0; + repeat + IncEx(CurrentX, Xinc); + IncEx(TwoDxAccumulatedError, TwoDy); + if (TwoDxAccumulatedError > Dx) then + begin + IncEx(CurrentY, Yinc); + DecEx(TwoDxAccumulatedError, TwoDx); + end; + Inc(Len); + SetLength(Result, Len + 1); + Result[Len] := Point(CurrentX, CurrentY); + until (CurrentX = X2); + end + else + begin + TwoDyAccumulatedError := 0; + repeat + IncEx(CurrentY, Yinc); + IncEx(TwoDyAccumulatedError, TwoDx); + if (TwoDyAccumulatedError > Dy) then + begin + IncEx(CurrentX, Xinc); + DecEx(TwoDyAccumulatedError, TwoDy); + end; + Inc(Len); + SetLength(Result, Len + 1); + Result[Len] := Point(CurrentX, CurrentY); + until (CurrentY = Y2); + end; + end +end; + +(* +tmp_TPAFromLineWrap +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure tmp_TPAFromLineWrap(const x1, y1, x2, y2: Integer; var Res: TPointArray); + +Wrapper function for TPAFromLine. + +.. note:: + + Last modified: Jan. 31st, 2013 by euphemism +*) +procedure tmp_TPAFromLineWrap(const x1, y1, x2, y2: Integer; var Res: TPointArray); +begin + Res := tmp_TPAFromLine(x1, y1, x2, y2); +end; +{$ifdef Simba} + +//{$define SimbaDebug} +type + TDTMPointDef = TSDTMPointDef; + TDTMPointDefArray = TSDTMPointDefArray; + TDTM = TSDTM; +function AddDTM(DTM : TDTM) : integer; +begin + Result := AddSDTM(dtm); +end; + +function InitializeHTTPClient(HandleCookies,handleredirects: Boolean): Integer; {$IFDEF LAPE}overload;{$ENDIF} +begin + {$ifdef SimbaDebug} + if HandleRedirects then + Writeln('Simba does not support automatic redirects yet'); + {$endif} + result := InitializeHTTPClientWrap(HandleCookies); +end; + +function IntToPoint(x,y : integer) : TPoint; +begin + result := Point(x,y); +end; + +procedure GetColorspeed2Modifiers(var hue,sat : extended); +begin; + GetToleranceSpeed2Modifiers(hue,sat); +end; + +function StartsWith(prefix, s: string): Boolean; +var + i,l : integer; +begin + result := false; + l := length(prefix); + if l > length(s) then + exit; + for i := 1 to l do + if s[i] <> prefix[i] then + exit; + result := true; +end; + +procedure AddToReport(str : string); +begin + writeln('Status: ' + str); +end; +procedure ClearReport; +begin + DebugLn('Should clear report now..'); +end; + +{$IFNDEF LAPE} +var + Bladieblatempthingy : TForm; +procedure CreateFormBladieblatempthingy; +begin + Bladieblatempthingy := TForm.Create(nil); +end; +procedure FreeFormBladieblatempthingy; +begin + if assigned(Bladieblatempthingy) then + Bladieblatempthingy.free; +end; + +procedure FreeForm(var form : TForm); +var + v : TVariantArray; +begin; + Bladieblatempthingy := Form; + ThreadSafeCall('FreeFormBladieblatempthingy',v); + form := nil; +end; + +function CreateForm : TForm; +var + v : TVariantArray; +begin; + ThreadSafeCall('CreateFormBladieblatempthingy',v); + result := Bladieblatempthingy; +end; +{$ENDIF} + +function IsFKeyDown(FKey : integer) : boolean; +begin + if not InRange(FKey,1,12) then + raiseexception(erCustomError,'FKey not in range 1..12'); + result := IsKeyDown(VK_F1 + FKey - 1); +end; + +function InCircle(x, y, mx, my, r: Integer): Boolean; +begin + result := (Sqrt(sqr(x-mx) + sqr(y-my)) <= r); +end; + +function CreateBitmapMaskFromText(txt,chars : string) : integer; +begin + result := BitmapFromText(txt,chars); +end; + +function GetNumbers(text : string) : string; +begin; + result := ExtractFromStr(text,numbers); +end; + +function GetLetters(Text: string): string; +begin + result := ExtractFromStr(Text,letters); +end; + +function GetOthers(Text: string): string; +begin; + result := ExtractFromStr(text,others); +end; + +function FindDTMRotated(DTM: Integer; var x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean; +begin; + result := FindDTMRotatedAlternating(DTM,x,y,x1,y1,x2,y2,sangle,eangle,astep,afound); +end; + +const + tr_AllChars = 0; + tr_BigLetters = 1; + tr_SmallLetters = 2; + tr_Digits = 3; + tr_BigSymbols = 4; + tr_SmallSymbols = 5; + tr_SecondTableChars = 6; + tr_Letters = 7; + tr_AlphaNumericChars = 8; + tr_Symbols = 9; + tr_NormalChars = 10; + +type + TCharRange = longword; //I donno + +function GetTextAtEx(x, y: Integer; Tolerance: Integer; Chars: String; CheckShadow, CheckOutline: Boolean; MinSpacing, MaxSpacing: Integer; TextColor: Integer; TextLength: Integer; Strict: Boolean; Range: TCharRange): string; {$IFDEF LAPE}overload;{$ENDIF} +begin + // no hspacing, defaulting to 4. (with 4 ' and : will work) + // Defaulting MaxSpacing to 3 + if TextColor = -1 then + raiseexception(ercustomerror,'GetTextAtEx with color = -1, is not supported'); + Maxspacing := 3; + {$ifdef SimbaDebug} + Writeln([x, y, minSpacing, maxSpacing, 4, textcolor, tolerance, textlength, Chars]); + {$endif} + Result := GetTextAt(x, y, minSpacing, maxSpacing, 4, textcolor, tolerance, textlength, Chars); + {$ifdef SimbaDebug} + Writeln('GetTextAt result: ' + Result); + {$endif} + if Range = tr_Digits then + result := GetNumbers(result); +end; + +function IsTextInAreaEx(xs, ys, xe, ye: Integer; var x, y: Integer; S: string; Tolerance: Integer; Chars: String; CheckShadow, CheckOutline: Boolean; MinSpacing, MaxSpacing: Integer; TextColor: Integer): Boolean; +var + TextTPA,SearchTPA, Matches: TPointArray; + Box : TBox; + xx,yy,i,len : integer; +begin + if TextColor = -1 then + raiseexception(ercustomerror,'IsTextInArea with color = -1, is not supported'); + Result := False; + FindColorsTolerance(SearchTPA,TextColor,xs,ys,xe,ye,tolerance); + if Length(SearchTPA) < 1 then + Exit; + TextTPA:= TPAFromText(S,Chars,xx,yy); + Result := FindTextTPAinTPA(yy ,TextTPA,SearchTPA,Matches); + x := 0; y:=0; + if Result = False then + Exit; + Box := GetTPABounds(TextTPA); + SortTPAFrom(Matches, Point(Box.x1, Box.y1)); + x := matches[0].x; + yy := 500000; + len := High(TextTPA); + for i := 0 to Len do + if TextTPA[i].x = Box.x1 then + yy := min(yy,TextTPA[i].y); + y := matches[0].y-yy; + {$ifdef SimbaDebug} + Writeln(Format('IsTextInAreaEx: (%d,%d)',[x,y])); + {$endif} +end; + +function GetColorToleranceSpeed : integer; +begin; + result := GetToleranceSpeed; +end; + +procedure ColorToleranceSpeed(cts : integer); +begin; + SetColorToleranceSpeed(cts); +end; + +type + TColorComp = (ccRed, ccGreen, ccBlue, ccHue, ccSat, ccLum); + +function FindColorComp(var x, y: Integer; Comp: Variant; CompType: TColorComp; xs, ys, xe, ye: Integer; Tolerance: Extended): Boolean; +begin + Writeln('FindColorComp is not yet implemented! Use another color finder ;-)'); + Result := false; +end; + +procedure SetColorspeed2Modifiers(huemodifier, saturationmodifier: Extended); +begin + SetToleranceSpeed2Modifiers(Huemodifier, saturationmodifier); +end; + +function InStrArr(Str: string; Arr: TStringArray; CaseSensitive: Boolean): Boolean; +var + i : integer; +begin; + result := true; + if not casesensitive then + begin + str := lowercase(str); + for i := high(arr) downto 0 do + if lowercase(arr[i]) = str then + exit; + end else + for i := high(arr) downto 0 do + if arr[i] = str then + exit; + result := false; +end; + +function Replace(Text, FindStr, ReplaceStr: string): string; {$IFDEF LAPE}overload;{$ENDIF} +begin; + result := {$IFDEF LAPE}Replace{$ELSE}ReplaceWrap{$ENDIF}(Text,FindStr,ReplaceStr,[rfReplaceAll]); +end; + +//Sends arrow to Client's window. For a, 0 = up, 1 = right, 2 = down, 3 = left. +procedure SendArrow(Key: Byte); +begin + if not InRange(Key,0,3) then + Writeln('KEY IS NOT INRANGE!!') + else + case key of + 0 : PressKey(vk_up); + 1 : PressKey(vk_right); + 2 : PressKey(vk_down); + 3 : PressKey(vk_left); + end; +end; + +procedure SendArrowWait(Key: Byte; WaitTime: Integer); +var + KeyCode : integer; +begin; + if not InRange(Key,0,3) then + Writeln('KEY IS NOT INRANGE!!') + else + begin + case key of + 0 : Keycode := (vk_up); + 1 : Keycode := (vk_right); + 2 : Keycode := (vk_down); + 3 : Keycode := (vk_left); + end; + KeyDown(keycode); + wait(waittime); + KeyUp(keycode); + end; +end; + +procedure SendArrowSilentWait(Key : byte; WaitTime : integer); +begin + SendArrowWait(key,waittime); +end; + +procedure SendArrowSilent(Key : byte); +begin + SendArrow(key); +end; + +function AMax(Data: TIntegerArray): Integer; +var + i : integer; +begin; + if length(data) = 0 then + begin + Writeln('cannot define result of AMax, input length = 0'); + raiseexception(erCustomError,'AMax input with length of zero'); + end; + result := data[0]; + for i := high(data) downto 1 do + result := max(result,data[i]); +end; + +function AddOnTerminate(const proc : string) : boolean; +var + OldProcs : TVariantArray; + i : integer; +begin + result := false; + GetScriptProp(SP_OnTerminate,OldProcs); + for i := 0 to high(OldProcs) do + if lowercase(OldProcs[i]) = lowercase(proc) then + exit; + setlength(OldProcs,Length(OldProcs)+1); + OldProcs[high(OldProcs)] := proc; + SetScriptProp(SP_OnTerminate,oldprocs); + result := True; +end; + +function DeleteOnTerminate(const proc : string) : boolean; +var + OldProcs : TVariantArray; + NewProcs : TVariantArray; + i : integer; +begin + result := False; + GetScriptProp(SP_OnTerminate,OldProcs); + for i := 0 to high(OldProcs) do + if lowercase(OldProcs[i]) = lowercase(proc) then + result := true + else + begin + setlength(NewProcs,Length(NewProcs)+1); + NewProcs[high(NewProcs)] := lowercase(OldProcs[i]); + end; + SetScriptProp(SP_OnTerminate,NewProcs); +end; + +function Readln(Question : string ) : string; +begin + InputQuery('Question box',Question,result); +end; +const + NPCChars = CharsNPC; +{$endif} diff --git a/SRL/core/symbol.simba b/SRL/core/symbol.simba new file mode 100644 index 0000000..3f89720 --- /dev/null +++ b/SRL/core/symbol.simba @@ -0,0 +1,1072 @@ +(* +Symbol +====== + +The Symbol include contains minimap symbol related functions. + +.. contents:: + +*) +//-----------------------------------------------------------------// +//-- SRL Resource Library --// +//-- ********* Symbol Routines --// +//-----------------------------------------------------------------// +// * function LoadSymbolBitmapColor(Name: String): Integer; // * by Stupid3ooo, WT-Fakawi, Bebemycat2, Ron, and StarBlaster100 +// * function GetSymbolColorIn(var rx, ry: Integer; Name: string; xs, ys, xe, ye: Integer): Integer; // * by Starblaster100 based off of the ideas of Stupid3000 +// * function GetSymbolColor(var rx, ry: Integer; Name: string): Integer; // * by Stupid3ooo and Modified by Starblaster100 +// * function FindSymbol(var rx, ry: Integer; Name: String): Boolean; // * by Stupid3ooo +// * function FindSymbolIn(var rx, ry: Integer; Name: string; xs, ys, xe, ye: Integer): Boolean; // * by Starblaster100, based on the ideas of Stupid3ooo +// * function FindSymbolsIn(var AnsTPA: TPointArray; SymbolName: string; x1, y1, x2, y2: integer): Boolean; // * by lordsaturn +// * function FindSymbols(var AnsTPA: TPointArray; SymbolName: string): Boolean; // * by lordsaturn +// * procedure FindSymbolsMulti(var aTPA: TPointArray; Symbols: TStringArray); // * by Nava2 + +{ var SymbolAccuracy: Extended; + Description: How accurate it must be, in %, to find symbols or icons on the minimap. } +var + SymbolAccuracy: Extended; + SymbolBitmap: Integer; + +// Comment fix by drizzt: +// Updated list - 20/05/2012 - [J]ustin +{******************************************************************************* +Valid Arguments are: +- agility - gem stall - rest, resting spot +- altar - guide - sandpit +- anvil - hair dresser - saw mill +- apothecary - herbalist - scimitar shop +- archery shop - house - shield +- arrow - hunter store - shop, store +- axe shop - hunter training - short cut +- bar - jewelery - silk stall +- bank - kebab shop - silver stall +- candle shop - lodestone - slayer master +- churn - mace shop - spice stall +- clothes shop - magic shop - spinning wheel, spin +- cookery shop - makeover mage - staff shop +- cookery, cook - mill - summoning store +- crafing shop - minigame - summoning obelisk +- dungeon - mining shop, mining site, mine - sword shop +- farming shop - pet shop - tanner +- farming spot - platebody shop - training dummy +- fishing shop, fish store - plateskirt shop - underground +- fishing spot, fish - portal (to player owned houses) - water source, water +- food shop - pottery, pot - weave +- fur trader - quest - windmill +- furnace - rare trees, tree + +*******************************************************************************} + +Const //Symbol Constants, may be changed to integers in SRL6 + Symbol_Agility = 'agility'; + Symbol_Furnace = 'furnace'; + Symbol_Altar = 'altar'; + Symbol_Anvil = 'anvil'; + Symbol_Apothecary = 'apothecary'; + Symbol_ArcheryShop = 'archery shop'; + Symbol_Arrow = 'arrow'; + Symbol_AxeShop = 'axe shop'; + Symbol_Bar = 'bar'; + Symbol_Bank = 'bank'; + Symbol_CandleShop = 'candle shop'; + Symbol_Lodestone = 'lodestone'; + Symbol_Churn = 'churn'; + Symbol_ClothesShop = 'clothes shop'; + Symbol_CookeryShop = 'cookery shop'; + Symbol_Cookery = 'cookery'; + Symbol_Cook = Symbol_Cookery; + Symbol_CraftingShop = 'crafting shop'; + Symbol_Dungeon = 'dungeon'; + Symbol_FarmingShop = 'farming shop'; + Symbol_FarmingSpot = 'farming spot'; + Symbol_FishingShop = 'fishing shop'; + Symbol_FishingStore = Symbol_FishingShop; + Symbol_FishingSpot = 'fishing spot'; + Symbol_Fish = Symbol_FishingSpot; + Symbol_FoodShop = 'food shop'; + Symbol_FoodStore = Symbol_FoodShop; + Symbol_FurTrader = 'fur trader'; + Symbol_RareTrees = 'rare trees'; + Symbol_Tree = Symbol_RareTrees; + Symbol_RestingSpot = 'resting spot'; + Symbol_Rest = Symbol_RestingSpot; + Symbol_Runecrafting = 'runecrafting'; + Symbol_Rcing = Symbol_Runecrafting; + Symbol_Rc = Symbol_Runecrafting; + Symbol_GemStall = 'gem stall'; + Symbol_Guide = 'guide'; + Symbol_HairDresser = 'hair dresser'; + Symbol_Herbalist = 'herbalist'; + Symbol_House = 'house'; + Symbol_HunterStore = 'hunter store'; + Symbol_HunterTraining = 'hunter training'; + Symbol_Jewelery = 'jewelery'; + Symbol_KebabShop = 'kebab shop'; + Symbol_MaceShop = 'mace shop'; + Symbol_MagicShop = 'magic shop'; + Symbol_MakeoverMage = 'makeover mage'; + Symbol_Mill = 'mill'; + Symbol_Minigame = 'minigame'; + Symbol_MiniObelisk = 'mini obelisk'; + Symbol_MiningShop = 'mining shop'; + Symbol_MiningSpot = 'mining spot'; + Symbol_MiningSite = Symbol_MiningSpot; + Symbol_Mine = Symbol_MiningSpot; + Symbol_PetShop = 'pet shop'; + Symbol_PlatebodyShop = 'platebody shop'; + Symbol_PlateskirtShop = 'plateskirt shop'; + Symbol_Portal = 'portal'; + Symbol_Pottery = 'pottery'; + Symbol_Pot = Symbol_Pottery; + Symbol_Quest = 'quest'; + Symbol_Windmill = 'windmill'; + Symbol_Sandpit = 'sandpit'; + Symbol_SawMill = 'saw mill'; + Symbol_ScimitarShop = 'scimitar shop'; + Symbol_Shield = 'shield'; + Symbol_Shop = 'shop'; + Symbol_Store = Symbol_Shop; + Symbol_ShortCut = 'short cut'; + Symbol_SilkStall = 'silk stall'; + Symbol_SilverStall = 'silver stall'; + Symbol_SlayerMaster = 'slayer master'; + Symbol_SpiceStall = 'spice stall'; + Symbol_SpinningWheel = 'spinning wheel'; + Symbol_Spin = Symbol_SpinningWheel; + Symbol_StaffShop = 'staff shop'; + Symbol_SummoningStore = 'summoning store'; + Symbol_SummoningObelisk = 'summoning obelisk'; + Symbol_SwordShop = 'sword shop'; + Symbol_Tanner = 'tanner'; + Symbol_TrainingDummy = 'training dummy'; + Symbol_Transportation = 'transportation'; + Symbol_Underground = 'underground'; + Symbol_WaterSource = 'water source'; + Symbol_Water = Symbol_WaterSource; + Symbol_Weave = 'weave'; + +(* +LoadSymbolBitmapColor +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + + function LoadSymbolBitmapColor(Name: String): Integer; + +Loads Bitmap and Color of a Specific Symbol. + +.. note:: + + by Stupid3ooo, WT-Fakawi, Bebemycat2, Ron, and StarBlaster100 + +Example: + +.. code-block:: pascal + +*) +function LoadSymbolBitmapColor(Name: string): Integer; +begin + case LowerCase(Name) of + Symbol_Bank: + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpjYGRgYDwAAxsWun/9NjnbX' + + '/D9BUUgOR8GILJAlWiKIcogJBAdQAKYiiHqIQiiHpfJyOqRHYNLMa' + + 'ZjEIoBKZB32A=='); + result := 2216175; + end; + Symbol_MiniObelisk: + begin + SymbolBitmap := BitmapFromString(15, 5, 'meJxjYGDYjwTO75ymWJUpaO7FKyw' + + '7f/58ZCkGMEAW0QrM8q3vAapPz/AgqFg2wguoGEhyKfHhVwx0w4NH' + + 'D4AIaL5TQh4Q4VEMcQNQDVA90HAeRStkw4EqAbnwdxs='); + result := 12566463; + end; + Symbol_MiningSpot, 'mining site', 'mine': + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpjYGRgYDyAAXqrfB' + + 'vCddIzMsrKSiMiIiCCQJWYiufk2INUWova2dkD1Xv7ec+fPx+rYrj' + + 'K+WAANBaXYqDK7GDtIAsBiEqgCFAxnI2seEKsNVCluzoPXBauGOpm' + + 'ADVlcCo='); + Result := 5077645; + end; + Symbol_Transportation: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA33303534347074353' + + '4B73032219E34763173348592A62E666E66A6C8B20660330D904C' + + '86A841D6858BC454896C3EA6C9C498899FC465B291A3B193910B3' + + '124A69910715C269317CEC866229B0C00B3496273'); + Result := 2650848; + end; + Symbol_MagicShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA95D0510A80300806' + + 'E02B9906B6C77F3AEF7FA4A0066DABC17A1111FD1469A74CC5C46' + + '0D6C60875CEA17288D63CE08C771D02A09BA5CBA499DC99AD3CFA' + + 'EB72041B97B9D9C83F6F2ECE69C3D71F46F9EE5C979D155AFDBAA' + + '5BBFF312D915399C927AF756C82'); + Result := 1714669; + end; + Symbol_WaterSource, 'water': + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpjYGRgYDyABFJrHmt' + + 'm/ACi+fPnH0AFQJW4FAMRfsUQlYfPPgSS7Hb30QzHVAxUCVcMRHgUQ2xHVoxs' + + 'OAMAbyOCjQ=='); + Result := 16279593; + end; + Symbol_Furnace: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA3334353435B470' + + '3101423308696A028466E6C6A6A626E66E6E1640062E12A206A2D' + + 'EC90408A1261882CD3424CA6427472320DBCDCDC810C61EFC2653' + + '3F34882171990C0058F36390'); + Result := 3508223; + end; + Symbol_Anvil: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA95CF510AC0300803D02B' + + 'A59DE0F2D9F6FE771A2CFB10CAC4FE04117C443434D8E4C2EA4A8' + + '7DFCE8B06FB369AF38C025E139B5C7194EA106F73B9D2991C187D' + + '3773F92F2BE6A91CBFD05CE9FC00C9DB6164'); + Result := 4012591; + end; + Symbol_RareTrees, 'tree': + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpjYGRgYDwABmw+jCx5' + + 'vBDE08sOQZK7GYAkRAFQJX7FcISpGK4eKIumZf78+ZiKsZo/HwyQF' + + 'cPVA8Xd1XmAJLJKkDMAo5RFgw=='); + Result := 494860; + end; + Symbol_FishingSpot, 'fish': + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA8DCE410E80300844D12B4D5BA' + + '9BAA404EE7F2413675343AA6EFE82D217D061682636ACCCADA779' + + '045B641F117987CDAFB84D2479D67257B28A0EFD90B9C9F9BB3FD' + + 'FF02EC337F347B39977D83F37AFFEA2D76EDEA4543DE870B2922F' + + 'BB6B6878'); + Result := 16743189; + end; + Symbol_Cookery, 'cook': + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAA590410AC0200C04BFB41' + + 'B4D5B8F2ACDFF9FD4D25008885EBC0C21EC0E211010EC6CD66EE7' + + 'C1A4F869A9524AD74BB2CF3139233E2782D9BB713F52CE37A1D98' + + '4A823D7E678A15FAE4CC4EDDDB5B9B258D932BB61C67DF3FACF0F' + + '3E40632F'); + Result := 1194607; + end; + Symbol_Quest: + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpjYGRgYDwAA22Tnkzffim1' + + '5jEQAdmmPvuB5Pz58yGyQJVwxUBxIAIqg6iHqIQgNMUQ0/AgrCbDXQI0GeIYi' + + 'EuAAFkx3M0Qx8BdAlEJMhkAMoB+aA=='); + Result := 14908517; + end; + Symbol_mill: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAB58F3B0AC0300C43AF24A' + + '75D3CD621BEFF9102D52228822C5D1EC69F878C8140CCA8AEE5D8' + + 'DD0BA97C223BED3E5E27C48CBAE7B878ABF54987B5337FB3E995D' + + '26DF2973F323B33C9A9D26573A47303B52569D1'); + Result := 655103; + end; + Symbol_Dungeon: + begin + SymbolBitmap :=BitmapFromString(8, 9, 'meJw7cAAEFiz4ExDwBYi0tD4wMMSw' + + '5vwDCs6cORMoApHCKg4URBOHiBAUl3b9CxGHG8LPPx8oDkRg50Clg' + + 'ILp6a+BbEYGhgMwMBMJHEACEKOAJIQLAAEpc48='); + Result := 2698232; + end; + Symbol_weave: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA33303230343074367472' + + '73724526CD0C4C0C8CDC1C0D2DDD2C5D8DDD8C4C0CA0E2103644D' + + 'CDCD1CCD4C40CC246D66B0036D300AFC9986622B3293119979B21' + + 'ECC1E966649793EA6600F03E685F'); + Result := 926783; + end; + Symbol_Pottery, 'pot': + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA8DCE5B0AC0200C44D1' + + '2D6592691B3F2DD5FD2FA98F08554A410217C9C73102B966673E7' + + '64617AA094DA16349D4B15E96621EED05C13B5F19F9DEFF178E14' + + '3F869CE8479A9267FCFEE619992A55100D7F8519CC37562DBDD6F' + + 'AECE76FEEFD55D5A50983FFBCB76A807CE5139EC460AC'); + Result := 270148; + end; + Symbol_SpinningWheel, 'spin': + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpjYGRgYDwABtn' + + '+gvPnz28I1wGygSQaG8gAqoQoDrIQAJIQQbgauMiEWGs0xenWokAE0QVXD0dA' + + 'XciK58MAUAvIVcHaEJMh7kFWDAQQNZgk3D0MAH8HZ/A='); + Result := 2710649; + end; + Symbol_guide: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA33303400424717470B27' + + '33086961E168E4EC64E866E264EE0C614349170B0B4B336411143' + + '56059880906860848C06488995432193F89CB47F84D869A8FE14E' + + '8869F8CD24C664E2431E533DC44C00EBA66771'); + Result := 13345416; + end; + Symbol_shop, 'store': + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA95D0410EC4200' + + '840D12B2102C25290DEFF486DCA2C4C9A6666363F46E2D308020D' + + '32D83DA2AA3E6804276633B66B7AB4006E7D5F57E9406E51DD05B' + + '84D78C8435849DD5970E9EC0629AB13B692ABB5B34F279BCF6F32' + + '12A15CE3E8B9B7EE3265C52C73EFF0818A6FB2CA085D4FF317598' + + '484FA9B6C69689FB37FBFF9FEC35D3E01559765AB'); + Result := 3176384; + end; + Symbol_Shield: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DACDCC3112C0200844D12' + + 'B611484920DE4FE47CA8CA63085BDCD9F6DF6511614BE233CEADA' + + '16ECFC9553204DD36055D92EF56E2AFD99DB038EDF97864927C8C' + + '339595EFD9D3CCD9DFC02CAE26976'); + Result := 9542286; + end; + Symbol_altar: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA33703574323475767171' + + '7431B670B574B2A4888498630036D300C96464F3DD880610F58E2' + + 'E4E8E4E501297C9C49B8F69267E37936732B25EFC26131F1AB84C' + + '06006E357035'); + Result := 9542286; + end; + Symbol_arrow: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA33303570333470353437' + + '3372249E343633B33475829026161646E626C8B20660330D904C8' + + '6A841D6858BC454896C3EA6C9C498899FC465B2919BB1A5B12931' + + '24A69910715C269317CEC866229B0C001E5A61CB'); + Result := 2782945; + end; + Symbol_bar: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAB5CC310EC0200C43D12B41' + + 'E3001D0389EF7FA44ACD82D4952E5F968757B5B4E28EA56B66E33' + + '685908EEEA4115736FF1523A016BD8113A636079B0877A1BE663D' + + '24E73E25A7F99F9CE659F96BEEF2031A5D69A8'); + Result := 4433385; + end; + Symbol_underground: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA33303400422743' + + '272727134CD2D5C2C8D4D01993B47033303630B434B474B2C4A2C' + + 'BC01001E96FB28B9BA3A10516335D5DCC8C4D9D293119D97C62CC' + + '24D5646412622631260300830265FA'); + Result := 1844712; + end; + Symbol_tanner: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA8D904B0EC0200805AF0' + + '4F85F4ABDFF991AFB162521D26E26462703919898BAAACEAB82B5' + + 'E5C4ABB52289FED316E8699229DBE63ECB8AA7F8D75319843374C' + + 'C594B4FC2C5177003C7FAE0A90CC2C92ACA392E5B3FDED9F22DCB' + + '47D9FFF30DFAEB6308'); + Result := 3363443; + end; + Symbol_churn: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA9590410A00210845AFA4' + + 'A5FE5A564CF73FD240CE40502DDA3C5CE8031F318150D1ACE94C4' + + '104C7D04365F159253E2C16A5737342B5735F6F6938E960D66430' + + '9B0D1B5292146ECD92156ABF1F013CD39DBE736D1E05FCF644FFE' + + '8BAC6A8FAF927AEB5338A958DF905A105631F'); + Result := 1720403; + end; + Symbol_house: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA9D90410AC0300804BF6' + + '41B2DF66863F3FF2715BA978560A0BD0C32E2B228F766123D53BB' + + '33E5F5A08DC3ECD434550779BBBE9D3D1290C9846FDEC63EC02A8' + + '13D9B7F5C77AE9AF337B86DE4A5E1E0D7649EABE4F9F601C37765' + + 'F5'); + Result := 4740173 + end; + Symbol_AxeShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA95D04B0EC3300804D02B91' + + '0033F6127F72FF23A52A1BA4AA55BA1959483C036202E953A74F7' + + 'EA6BBC35B260C403335377680767CEB92B7293FE59A71BEBE187D' + + '1136D2C7C583CAC6E0CCCABF7235B9A13A728B34EB2EA1E1F148E' + + 'E8D8655CDECADF7C977D69FC8B1BA0269E2B27DEEDA9B13D63933' + + 'EB356E4B7C6439'); + Result := 6841956; + end; + Symbol_CookeryShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA8DCE410AC0300804C0' + + '2F194CDCE42896FCFF49856E0F421072D983BA83D2C56485C608E' + + '4C484236CA341999CBBFA7020A6CEFEDF74339B9CF3463E530A99' + + '4993ADDCA55C6D6F647E955B959CB757F22754F2F9ED8DBCCCD01' + + 'B137B3CDAB290E76797E60B5A736560'); + Result := 7565679 + end; + Symbol_windmill: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA3330313033B074367' + + '6367536C745BA0181A11132E968EC68EA8853BD01D84C0324930D' + + '5C4C8D8C9C217A91D9C48840D8B84CC6741BB22E6412974A885F6' + + '8E1665C264348882C3289CB6DB848889900AC8467DB'); + Result := 1245183; + end; + Symbol_minigame: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA8D90410EC0200804B' + + 'FB4AD22E568B1FFFF52132129C6DAF432214626CB22A340342929' + + '47B68DAE82066E2C0D99323BFBBB0A0E88CD3555AAC32EBA1393D' + + '99D6E36E7E38FCEC86FF3906D412D09FBB9E4FFCCA113DFED996D' + + '8E7FAC13E3CAFCD2B3DD1BB34D3DC7B6CD79039CA16371'); + Result := 4670928; + end; + Symbol_furtrader: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA3330313033B0743' + + '67636753647262D2C4C8C0D2C31497357A07A0B64D2D1D8D1D4D1' + + '1C4242F41A80CD34C06132A6F9C49849BCC9B8CCC76526792623B' + + 'B16BF7A52438378F321660200DE126419'); + Result := 607112; + end; + Symbol_archeryshop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAA5CE490AC0201' + + '044D12BB5560F71E910EF7FA4403A0B8318846CFEAA78143129A5' + + '8A2AD5769A9A29172F8385CD9B91253F1BBA4DDA964733A91A07D' + + '7FEC8A366A702C59D51DB9215140BF77804BCCC2E0D6136E7AE64' + + '37477FF5F35BBE0049C36545'); + Result := 4945565; + end; + Symbol_StaffShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAA5D03B0AC0300C0' + + '3D02BD9F1AF198D83EF7FA442BCB6C1B48B26F110020685191412' + + 'D6C9A96A8C96B2089D5CFCA103DB84B65CA60F49CC32FFCBA55D8' + + 'B7DD0D9ECCBFD9DDFE4F3AB6FF20D38E96664'); + Result := 4286358; + end; + Symbol_ClothesShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA8DD04B0AC0200' + + 'C45D12D3DF2D13A0CE9FED754681CA4484A267720CF8308C1C072' + + '76F51925BE2023CAB2A0D66916F09A487236CF66A73AAFE4686C8' + + 'C4D6DE25622AFE4D8E4FDBE55C8D1BE9CF7FF6FFEFC585B3EFFF9' + + '012BE4618A'); + Result := 5935156; + end; + Symbol_FarmingSpot: + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpjYGRgYDyAAwRZC' + + 'Lir87iJ8c2fPx/IBarEpRiicj4M4FGMrBIuiKm4rKw0PSMDqBhNJaZiiEoIQl' + + 'MJUgwAOf97Lg=='); + Result := 12632256; + end; + Symbol_Apothecary: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA9DD0310AC030088' + + '5E12B69A3A68ED6D6FB1FA9D02C4230942CFF241F0F814040BD39' + + '7BAFAA8748C46847C2A75B33B6F21E3E13967236B33CBA2767CDD' + + '5EFE05926C5F3D23DB932B33C7FE6FFE66AED5A7E01E72B65AE'); + Result := 16737938; + end; + Symbol_SwordShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA95D0410AC030080' + + '4C02FD9C66CE25125FFFF524BBD08A5C520EC41964124269078F3' + + 'EEE33FC5EF918535971A1B0C6000539B761D91D1A4C7A4829CCD1' + + '06293E5DCFF929BF231CEBAB92B47EE9A956FBC2FAF9859BE0057' + + 'DB6637'); + Result := 10067100; + end; + Symbol_PlatebodyShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA8DD0410AC02' + + '00C44D12BA56832761902BDFF910A9DCD8055DCFC850C4FD1BA85' + + 'DDD5CA0B6CF48818F1E042633190A87D55B0CF349167534FD459D' + + 'DBB92596EB2A527DC3DFC4FFE6EE446F7EC4A66CF65DDEFDFAC3D' + + '97E77F7E014609646B'); + Result := 8157816; + end; + Symbol_ScimitarShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA9DD04D0AC340' + + '0805E02B8D7FCF71399349EF7FA4A6B8A825109A203C5CE887D8A' + + '81D356962CA3FD9475FDD96AE581012880405E267A6D1B7CE0277' + + '61DBAB56CDEC6963A2F14CAE5AA69B0FF76ADE95315CBDA59FBB2' + + 'AEAAAF50367F35A0630711C0AB697B1B9E9678223F3DAACF21B5C' + + '65625E'); + Result := 8752522; + end; + Symbol_GemStall: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAA58E4B0AC0300844' + + 'AFA4F96719F3B9FF919A640A154A3729836F21FA18629A1196201' + + '6ECCD772FE0E03AAA057B32F350338DF50B6A03F1932FF34DEDDC' + + '1BED0433E7900FCD835C76011B89BFCDAFB6AEAEFB504FCC6013F' + + '6C4DA8C9E306B1653E29C4D6DBE0027B7630B'); + Result := 1777896; + end; + Symbol_SilkStall: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA333034004227432' + + '733276364D2C2C4C0D0D488181253AF81210262CA42484B67030B' + + '33476248DA996C696869664994C9C48706B299F84D36733630347' + + '62486849889CB6400B4306127'); + Result := 5374340; + end; + Symbol_PlateskirtShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA3330340042' + + '2743273327634CD2D9D8CCC2D9009974323235763282909686966' + + '696587419182220F126239B4F9EC9B8DC8929423B93315D4E2034' + + '709843BCC900457662CC'); + Result := 12609731; + end; + Symbol_Agility: + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpjYGRgYDwABkAGEM2fPx' + + '+NAWHDFRyAAbgssgIIA1Mxsnq4GjyK0czHFMcUmQ8G6I4EAIrAWyc='); + Result := 65536; + end; + Symbol_TrainingDummy: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAA5CC5B0AC43' + + '00805D02D69468DF9BC6DEAFE97D401032384F92845B8888F434C' + + 'DF0210386A6A6B9D3833270E0F5F5B7371D2FD2B93F857FFE4D4A' + + 'AE962D402E738ED1A0768E08D5CE743FA14A49CB9DF3C95CDA4B3' + + 'A6EC1FB73E6BBE974D6572403C74F9AB2F9769DEA32D69B5'); + Result := 1586538; + end; + Symbol_FoodShop, 'food store': + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAA5D0610AC0200806' + + 'D02B559ADA4F37DAFD8F3499C11C6D63B02F900A79882959B28AC' + + 'A825E09908A0893A0B4C25441ED49A0DA2AB3DFFDDF7B467FE64D' + + 'C88594CF13E56651A08C1DD66146F9A82E47532C0DDFE531F92C8' + + '77A9183F945BED9C66F396EC385D91F321AD29FE41DF6B66191'); + Result := 7837098; + end; + Symbol_FishingShop, 'fish store': + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA3330340042470B470B' + + '27134CD2D2C2C4C8C010425A0081A509844456832962608880E49' + + '9099431773425DE64E2CD4426F19B8C6CA6990950812BAE50C234' + + '19D9765C6E8698894C62BA193334304D0600DE086263'); + Result := 9734280; + end; + Symbol_Jewelery: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA9D904B0AC0300844A' + + 'F646843E2D24FBCFF911A6217820DB4DD0C32EA43070A28B08088' + + '6054AB664DB46B07E64276220109A1D7EEFB4CDE85C5840D79E0E' + + '05223D3D5BBEEFB4CF4DF933333AA5FFE957CFFDB95DB5356CBFF' + + '479E471FB395F2DCE59FC917FB9B6AAB'); + Result := 4829105; + end; + Symbol_CraftingShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA95CEC10AC020' + + '0C03D05F8AD3D979AC71FFFF4BC27A29C8A45E420EE111240C748' + + '2648B24BEFDD5B36414149626F793E45D3708CBDEACA98EAA662A' + + '94DA2C4FE5D5F49A374FE53F73FF642F9B693D627A79020EC868E' + + 'C'); + Result := 3159851; + end; + Symbol_Portal: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAA5D04B0AC0300805' + + 'C02B69D2D6B8D47CEE7FA4045CD442ED22457848D0410208AB549' + + '4942D2F4858DAA9B05A6A4895251DB93FD2DE6DC6E6BD0078D7B7' + + 'A98374A0CFC86761E2173977C052F764DB8DE43F375B46F2DE3F7' + + 'BD3CB13F26764CE'); + Result := 15287202; + end; + Symbol_MakeoverMage: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA333034703170' + + '7236707676B68490066011571367734B174CD2D2D8CCD5C418993' + + '4C06182015E9391D5608A209BEC68E0E8EC4882C9C4BB99129391' + + 'DD499EC9F8CDC76526A6C9003E5F6688'); + Result := 10340324; + end; + Symbol_MaceShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA9DD14B0A80300C04' + + 'D02B4D4CF3E93226DEFF4A82155404296EB21A1E330484C29AC8C' + + 'CFE7DAD7BB89A38D9A6696EA2A4A511888C4712878909D9521BB3' + + 'A6086368B248C969FE932F7381546BE477ED6DCEC80F135C64DFD' + + 'A8C7CDFFEEE39F39161EE1ADD6893'); + Result := 8817273; + end; + Symbol_HairDresser: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA33303470317072' + + '36707676B68490066011030C71E2D5E0977534707476C4A206998' + + 'DAC8654B7E1B2059984C84248F27C8D6C3EB269C4BB19531CD91C' + + '4CF7E37233005E916796'); + Result := 13225152; + end; + Symbol_MiningShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA33B03430313074' + + 'B670367672C5241D2D1C8D2DA1A40158258474737473333285909' + + '8BA9055E232199944360DBFF9C49B8C6926B22F20E21011FC263B' + + '5998BAC0447099499EC9C498896C022E9301172B6823'); + Result := 10396584; + end; + Symbol_SilverStall: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA958E410AC0400' + + '803BF14D1823D6E6DF3FF2715EA4510A17B09C198211008347031' + + 'A4AB4169E2E6EA071F06EFF4F5DE5BF89818C8D9ADB4AE13FF0FB' + + '976FBF2F4F9B370726D90FBB64977C913BFA6D3E61755066363'); + Result := 8749956; + end; + Symbol_SpiceStall: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA9DD0C10E80200C' + + '03D05FEA06883B22D2FFFF2413F140B240D44BD3C3FA0E8340102' + + 'A0E5619D3984CAC714B50B224D1A72B9BEEBDF71BBFC56DC2C96F' + + 'CCB5EFE5A9F9D1F77244609C66B67CE6B6CE0263997EE39FDFCD5' + + '1BE002BE06493'); + Result := 157167; + end; + Symbol_FarmingShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA95CE410E80200' + + 'C44D12B4D5B405C160CF73F92C461D1C498E0E6D374F1280402EB' + + '68A30B6B559340150D25F5F95ED55392D556735365BBA96B661DE' + + '7F025E031F192A9D1E75CAA1D52A2CFD2E42FFB7234BFE478FF8E' + + '9CE7128332E72FEDAF1C2FDF91A319E51BD93562F0'); + Result := 1918090; + end; + Symbol_SlayerMaster: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAA5D04B0AC030' + + '0804D02B8D89A5CD320D9DFB1FA9BF8D622D8582B810E6210381A' + + '00EAC1CA2A85461E3F34C1CB366FBCE7634F6533C4C04D9FAEE62' + + '84ECF22EDB3F9D53B89525CADF7F4E1BB864B77FB411B359C351D' + + 'E019F8C655C'); + Result := 7666933; + end; + Symbol_Herbalist: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA7D8E5D0AC0300883' + + 'AFA4FDD33E5AC6EE7FA415C258C0D10A22267E8DA8EC5A253C9CB' + + 'B5EF5166D7D4C89DE6DE9C45C6DF8BB1733FBBB15FD0A1B10B001' + + '99F9CCC42C5AB77B16DFEF4C86BF370B355C653272428513EA990' + + 'C3FF3393954EEFC2327CFE4CCCFC933136A263F5CC35F29'); + Result := 682309 + end; + Symbol_CandleShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA33303400422723' + + '470B470B4CD2CDD0C2D5C01042BA9ABB9A9A3A218BE0D26560888' + + '0B8D4209B8F6CB2A591051040488A4C367035753571317136B134' + + '8390B8CC1CEA26030022F6653F'); + Result := 6022631; + end; + Symbol_SawMill: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DAB58EB10DC03008045' + + '70A600C2EFDF1FE33450A299088A53469AEB08FD3D3498D7861C9' + + '3A2A4D3ABA0FF1E99619EFBB2BBA9B54CA0A157D69C66FED87FFA' + + '55CD7663FF7C30120F87173EEEFCA266DF2431F0AB6E11D3C770C' + + 'A76EBE00CD48658B'); + Result := 8882835; + end; + Symbol_KebabShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpj4OBg4Dh37BgQZTtJRDFwZM8' + + 'xhKD/mpo9DAwgEScJiAKgSohioIjEFJBKIAlEQJUQxcjqkRUDVULE' + + 'gSQQzUl2ArKB5N7qKCBj6dKlyIoh4lhJNMWY6iEIZCNYJUgxALQIU' + + '2Q='); + Result := 7316427; + end; + Symbol_ShortCut: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA8D90410AC0300804' + + 'BFA421A1E95137EDFF9F54E8F62088259741161D64C5B4E98573E' + + '9821B1A206E3EE49F5DAC1F835724F36F7E9D12CCD370DBE40EE7' + + '9854FE9864330DF993C8ECC9CC66F65039F7FD551B3BDCFFF9018' + + '756682E'); + Result := 5286667 + end; + Symbol_HunterStore: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA95D0510AC3300' + + '806E02BC558CDEFA309F6FE47DAC08E3942A143F041934FB1517B' + + '87C78447CD76BA591CCA445015EE5DD641C459F9D4F554C997F56' + + 'FA36FEC3204819E663A77F25CAE633C972F01BC48AAB9FBB9C373' + + '79DFB6E69C98DDE1E0813FAE1106FCF897564C992A6277F20B925' + + '96443'); + Result := 1261916; + end; + Symbol_HunterTraining: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA8DCF410A00' + + '210C03C02FC52D76E9B18AFFFF92B0EB2150025E728876AC78916' + + '8D3678C55D360F6F89FE919211B9EC267A2C87CB32F6FFD08EC70' + + 'CF6FDDC8D554597F712FF3AC3AE546C96A1FE573B2BC0197F063A' + + 'B'); + Result := 10398118 + end; + Symbol_Sandpit: + begin + SymbolBitmap := BitmapFromString(15, 5, 'z78DA8DCF4B0AC0300' + + '804D02B8DA9F9B84CA4BDFF91526A16820D64330CA20F0481208A' + + '51B4FA1C4998CBD07EE5D5EFA654B34F9BC75B7C2682BC336D72E' + + '247B921239137577766ECB629E9BD959D5CC14CCF8F1FBE88A665' + + '8794BE952DFDFE49DA95972794856206'); + Result := 7717352; + end; + Symbol_PetShop: + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpj42Nm4zt87GxnbWFhUkh' + + 'skCsQ7dm7CYIgXKB4dUkYUA1QJVwxULyypllFSQMoBUEQLlAcyF68' + + 'bA1ccV1hBlAQKAXkQoxdOL0LyMalGCgLUQYRhOsCOgOI0BQfWt0JQ' + + 'TomBhAEVAnkAo0FGg5SDADYtlua'); + result:= 11713980; + end; + Symbol_SummoningObelisk: + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNpj42Nm4zt87CwE2SVP1' + + 'XaoKeidC0SeUTWfHj4AiixetgYoCCSBKuGKgSKVNc1AZXMO3AOpWf' + + '8EqBiiEaIFrhioEigCRJPnrAAqBqJjl98BEVAlxFigGmSTIVqAtgM' + + 'VAI0FqgeSEBMwFQNVAo0FigPVgxjrnwB1Obj4IBQDAImMdLM='); + result:= 10325360; + end; + Symbol_SummoningStore: + begin + SymbolBitmap := BitmapFromString(15, 5, 'meJyzicq0QUKMDAzIyAZVFk3ZAVS' + + 'AVQtQJGrCfCA6gA0gqweyFyxY8OjFi5MPvwLVb9uyEVM9muLJ377C' + + '1WNqgRgOABDhZzk='); + result:= 9697013; + end; + Symbol_RestingSpot, 'rest': + begin + SymbolBitmap := BitmapFromString(15, 5, 'beNptjUENwDAMAw2lU' + + 'AylUAyljwEZtFryukVd7xHpYisBzF2wjnEdFfjKWCTdtJY9exfJpJ' + + 'u6kKVhAxeNyj76f/ReM5IceVZ9yhPESE1p'); + Result := 65536; + end; + Symbol_Runecrafting, 'rc', 'rcing': + begin + SymbolBitmap := BitmapFromString(15, 5, 'meJxjZGA4cOBAREpJY3M7U+tPxu3' + + 'fgAjICAmJBCKIOJABVMPIwMAIVgwR5/T8C1QGIZkFvsPVY1UMJOGG' + + 'A7VA1GMq1rawgQgCFQCVwdUD9QLFgbLIilV0teCGABFcPcRwoCxEM' + + 'QBG91kH'); + result := 542972; + end; + Symbol_Lodestone: + begin + SymbolBitmap := BitmapFromString(7, 7, 'meJzb09k0KSgPgvZ0Ni2qzb0yDyRS' + + 'YhkMQUA2UBCIfv/5DWQ72tkBSQh7D1jvw8cPgVwgCdEFIYEiEARUD' + + 'xfcvXX9y/MHgCTcZCAXyICYCWEDzQQA7QVQBA=='); + result := 13934210; + end; + end; +end; + +(* +GetSymbolColorIn +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetSymbolColorIn(var rx, ry: Integer; Name: string; xs, ys, xe, ye: Integer): Integer; + +Returns the Color of the Chosen Symbol, Searching in a selected area +of the Minimap + +.. note:: + + by Starblaster100 based off of the ideas of Stupid3000 + +Example: + +.. code-block:: pascal + +*) +function GetSymbolColorIn(var rx, ry: Integer; Name: string; xs, ys, xe, ye: Integer): Integer; +var + TheColor, c, Speed, x, y: Integer; + acc: Extended; +begin + Speed := GetColorToleranceSpeed; + ColorToleranceSpeed(1); + TheColor := LoadSymbolBitmapColor(LowerCase(Name)); + if (TheColor <> 0) then + begin + FindDeformedBitmapToleranceIn(SymbolBitmap, x, y, xs, ys, xe, ye, 70, 0, True, acc); + if (acc > SymbolAccuracy) then + repeat + c := c + 5; + if FindColorTolerance(x, y, TheColor, x, y, x + 15, y + 5, c) then + begin + Result := GetColor(x, y); + rx := x; + ry := y; + end; + until (Result > 0) or (c > 70); + end else + srl_Warn('GetSymbolColorIn', Name + ' is not a valid name.', warn_AllVersions); + try + FreeBitmap(SymbolBitmap); + except + Result := 0; + finally + ColorToleranceSpeed(Speed); + end; +end; + +(* +GetSymbolColor +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetSymbolColor(var rx, ry: Integer; Name: string): Integer; + +Returns the Color of the Chosen Symbol, searching the whole Minimap + +.. note:: + + by Stupid3ooo and Modified by Starblaster100 + +Example: + +.. code-block:: pascal + +*) +function GetSymbolColor(var rx, ry: Integer; Name: string): Integer; +begin + Result := GetSymbolColorIn(rx, ry, LowerCase(Name), MMX1, MMY1, MMX2, MMY2); +end; + +(* +FindSymbol +~~~~~~~~~~ + +.. code-block:: pascal + + function FindSymbol(var rx, ry: Integer; Name: String): Boolean; + +Finds a minimap Symbol and returns a Boolean if True. + +.. note:: + + by Stupid3ooo + +Example: + +.. code-block:: pascal + +*) +function FindSymbol(var rx, ry: Integer; Name: string): Boolean; +begin + Result := (GetSymbolColor(rx, ry, LowerCase(Name)) > 0); +end; + +(* +FindSymbolIn +~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindSymbolIn(var rx, ry: Integer; Name: string; xs, ys, xe, ye: Integer): Boolean; + +Finds a minimap Symbol and returns a Boolean if True. +Searches a selected area of the Minimap + +.. note:: + + by Starblaster100, based on the ideas of Stupid3ooo + +Example: + +.. code-block:: pascal + +*) +function FindSymbolIn(var rx, ry: Integer; Name: string; xs, ys, xe, ye: Integer): Boolean; +begin + Result := (GetSymbolColorIn(rx, ry, LowerCase(Name), xs, ys, xe, ye) > 0); +end; + +(* +IsPointInTPA +~~~~~~~~~~~~ + +.. code-block:: pascal + + function IsPointInTPA(Point:TPoint; TPA:TPointArray): Boolean; + +Returns true if a point is in a TPA. + +.. note:: + + by IceFire908 + +Example: + +.. code-block:: pascal + +*) +function IsPointInTPA(Point: TPoint; TPA: TPointArray): Boolean; +var + I: LongInt; +begin + for I := High(TPA) downto 0 do + if (TPA[I].X = Point.X) then + if (TPA[I].Y = Point.Y) then + begin + Result:= True; + Exit; + end; +end; + +(* +FindSymbolsIn +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindSymbolsIn(var AnsTPA: TPointArray; SymbolName: string; x1, y1, x2, y2: integer): Boolean; + +Finds a symbol in multiple places within the search coords. Results +true if at least 1 symbol is found. + +.. note:: + + by lordsaturn Fixed by Bad Boy JH + +Example: + +.. code-block:: pascal + +*) +function FindSymbolsIn(var AnsTPA: TPointArray; SymbolName: string; x1, y1, x2, y2: integer): Boolean; +var + CTS, Col, Hi, i, x, y, fx, fy, L: integer; + aP: T2DPointArray; + P: TPointArray; + Pt: TPoint; + acc: Extended; +begin + Col := GetSymbolColorIn(fx, fy, SymbolName, x1, y1, x2, y2); + if Col = 0 then + Exit; + FindColorsTolerance(P, Col, x1, y1, x2, y2, 0); + aP := TPAtoATPA(P, 10); + Hi := High(aP); + LoadSymbolBitmapColor(LowerCase(SymbolName)); + CTS := GetColorToleranceSpeed; + ColorToleranceSpeed(1); + SetLength(AnsTPA, Hi+1); + for i := 0 to Hi do + begin + Pt := MiddleTPA(aP[i]); + if IsPointInTPA(Point(fx, fy), aP[i]) then + acc := 1 + else + FindDeformedBitmapToleranceIn(SymbolBitmap, x, y, Pt.x-15, Pt.y-5, Pt.x+15, Pt.y+5, 70, 0, True, acc); + if (acc > SymbolAccuracy) then + begin + AnsTPA[L] := Pt; + Inc(L); + end; + end; + Result := L > 0; + SetLength(AnsTPA, L); + try + FreeBitmap(SymbolBitmap); + finally + ColorToleranceSpeed(CTS); + end; +end; + +(* +FindSymbols +~~~~~~~~~~~ + +.. code-block:: pascal + + function FindSymbols(var AnsTPA: TPointArray; SymbolName: string): Boolean; + +Finds a symbol in multiple places searching the whole minimap. +Results true if at least 1 symbol is found. + +.. note:: + + by lordsaturn + +Example: + +.. code-block:: pascal + +*) +function FindSymbols(var AnsTPA: TPointArray; SymbolName: string): Boolean; +begin + Result := FindSymbolsIn(AnsTPA, SymbolName, MMX1, MMY1, MMX2, MMY2); +end; + +(* +FindSymbolsMultiIn +~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindSymbolsMultiIn(var aTPA: TPointArray; Symbols: TStringArray; x1, y1, x2, y2: integer): Boolean; + +Finds multiple symbols the specified area. Results true if at least +1 symbol is found. + +.. note:: + + by Nava2 & NCDS + +Example: + +.. code-block:: pascal + +*) +function FindSymbolsMultiIn(var aTPA: TPointArray; Symbols: TStringArray; x1, y1, x2, y2: integer): Boolean; +var + gTPA: TPointArray; + I, H: Integer; +begin + H := High(Symbols); + for I := 0 to H do + begin + if FindSymbolsIn(gTPA, Symbols[i], x1, y1, x2, y2) then + Result := True; + aTPA := CombineTPA(gTPA, aTPA); + end; +end; + +(* +FindSymbolsMulti +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + + function FindSymbolsMulti(var aTPA: TPointArray; Symbols: TStringArray): Boolean + +Finds multiple symbols in multiple places. Results true if at least +1 symbol is found. + +.. note:: + + by NCDS + +Example: + +.. code-block:: pascal + +*) +function FindSymbolsMulti(var aTPA: TPointArray; Symbols: TStringArray): Boolean; +begin + Result := FindSymbolsMultiIn(aTPA, Symbols, MMx1, MMy1, MMx2, MMy2); +end; diff --git a/SRL/core/text.simba b/SRL/core/text.simba new file mode 100644 index 0000000..35ae138 --- /dev/null +++ b/SRL/core/text.simba @@ -0,0 +1,1349 @@ +(* +Text +==== + +The Text include contains all sorts of functions used for finding, analysing and +using text in RS. It also contains a few useful input routines + +.. contents:: + +*) + +{ const VK_ENTER + Description: Platform independent virtual enter key. } +const + VK_ENTER = {$IFDEF LINUX}10{$ELSE}VK_RETURN{$ENDIF}; + +{ var OldLine,TheLine, TheName: String; + Description: ChatLog vars. } +var + OldLine, TheLine, TheName: string; + +{ const clMessage, clChat, clTrade, clFriend + Description: Text colour constants. } +const + clMessage = clBlack; + clAssist = 14822282; + clChat = clBlue; + clTrade = clPurple; + clFriend = 128; + +{ type TOptions + Descripts: Choose option record. } +Type + TOptions = Record + Str: string; + Bounds, BigBox: TBox; + end; + +function CloseBank: Boolean; Forward; +function PlayerChatActive: Boolean; Forward; + +(* +srl_Explode +~~~~~~~~~~~ + +.. code-block:: pascal + + function srl_Explode(str, del: string): TStringArray; + +Explodes a string into TStringArray, seperated by del. + +.. note:: + + by mixster + +Example: + +.. code-block:: pascal + +*) +function srl_Explode(str, del: string): TStringArray; +begin + Result := Explode(del, str); +end; + +(* +srl_Implode +~~~~~~~~~~~ + +.. code-block:: pascal + + function srl_Implode(Pieces: TStringArray; Glue: string): string; + +Combines Pieces in a single string seperated by Seperator + +.. note:: + + by ZephyrsFury & mixster + +Example: + +.. code-block:: pascal + +*) +function srl_Implode(Pieces: TStringArray; Glue: string): string; +begin + Result := Implode(glue, pieces); +end; + +(* +InStrArrEx +~~~~~~~~~~ + +.. code-block:: pascal + + function InStrArrEx(S: string; StrArr: TStringArray; var Where: Integer): Boolean; + +Returns true if the string S was found in the StrArr, and if so stores the index into Where. + +.. note:: + + by n3ss3s + +Example: + +.. code-block:: pascal + +*) +function InStrArrEx(S: string; StrArr: TStringArray; var Where: Integer): Boolean; +var + I, H: Integer; +begin + H := High(StrArr); + for I := 0 to H do + if LowerCase(StrArr[i]) = LowerCase(S) then + begin + Where := i; + Result := True; + Break; + end; +end; + +(* +StrInArr +~~~~~~~~ + + + + function StrInArr(str: string; arrS: TStringArray): Boolean; + +Returns True if str is found in the Array. Case sensitive. + +.. note:: + + by Narcle & Nava2 + +Example: + +.. code-block:: pascal + +*) +function StrInArr(str: string; arrS: TStringArray): Boolean; +var + I, L, H: Integer; +begin + Result := True; + L := Low(arrS); H := High(arrS); + for I := L to H do + if Pos(Str, arrS[I]) > 0 then + Exit; + Result := False; +end; + +(* +ArrInStr +~~~~~~~~ + +.. code-block:: pascal + + function ArrInStr(arrS: TStringArray; str: string): Boolean; + +Returns True if the Array is found in the str. Case sensitive. + +.. note:: + + by Narcle & Nava2 + +Example: + +.. code-block::pascal + +*) +function ArrInStr(arrS: TStringArray; str: string): Boolean; +var + I, L, H: Integer; +begin + Result := True; + L := Low(arrS); H := High(arrS); + for I := L to H do + if Pos(arrS[I], Str) > 0 then + Exit; + Result := False; +end; + +(* +TypeByte +~~~~~~~~ + +.. code-block:: pascal + + procedure TypeByte(k: Byte); + +Types one character k. + +.. note:: + + by Mutant Squirrle + +Example: + +.. code-block:: pascal + +*) +procedure TypeByte(k: Byte); +begin + {$IFDEF SMART} + If (K = 13) then + K:= 10; + {$ENDIF} + KeyDown(k); + Wait(10 + Random(50)); + KeyUp(k); +end; + +(* +TypeSendEx +~~~~~~~~~~ + +.. code-block:: pascal + + procedure TypeSendEx(Text : string; PressEnter : Boolean); + +Types text in a human-like way. + +.. note:: + + by SKy Scripter + +Example: + +.. code-block:: pascal + +*) +procedure TypeSendEx(Text: string; PressEnter: Boolean); +var + I: Integer; +begin + if (PressEnter and (not PlayerChatActive)) then + TypeByte(VK_ENTER); + + for i := 1 to Length(Text) do + begin + {$IFDEF SIMBAMAJOR980} + SendKeys(Text[i], 40 + Random(40)); + {$ELSE} + SendKeys(Text[i], 30 + Random(30), 30 + Random(30)); + {$ENDIF} + Wait(40 + Random(40)); + end; + + if (PressEnter) then + TypeByte(VK_ENTER); +end; + +(* +TypeSend +~~~~~~~~ + +.. code-block:: pascal + + procedure TypeSend(Text : string); + +Types Text in a human-like way and presses enter. Wrapper function for TypeSendEx +for compatibility purposes. + +.. note:: + + by N1ke! + +Example: + +.. code-block::pascal + +*) +procedure TypeSend(Text: string); +begin + TypeSendEx(Text, True); +end; + +(* +AddMistakes +~~~~~~~~~~~ + +.. code-block:: pascal + + function AddMistakes(Orig: string; Chance: Integer): string; + +Adds human mistakes to Orig such as mistypes, missing letters, +wrong cases. Probability that a character is typed wrong is 1 / Chance. ie. +Higher 'Chance' = less mistakes (I know thats stupid but oh well...). +Probability is the chance that an individual character is typed incorrectly. +That is if you have more characters in a string you will get more mistakes overall. +20 - 30 is usually good but it varies depending on your string so experiment! + +.. note:: + by Zephyrsfury + +Example + +.. code-block:: pascal + +*) +function AddMistakes(Orig: string; Chance: Integer): string; +var + Line1, Line2, Line: array [0..3] of string; + i, j, TPos, Prob, Mist, L: Integer; + Norm, Caps, Excp, TLine, NewKey: string; +begin + Result := ''; + Norm := '`1234567890-=qwertyuiop[]\asdfghjkl;''zxcvbnm,./'; + Caps := '~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>?'; + Excp := '`1234567890-=[]\;'',./~!@#$%^&*()_+{}|:"<>?'; + Line1[0] := '`1234567890-= '; Line2[0] := '~!@#$%^&*()_+ '; + Line1[1] := ' qwertyuiop[]\'; Line2[1] := ' QWERTYUIOP{}|'; + Line1[2] := ' asdfghjkl;'' '; Line2[2] := ' ASDFGHJKL:" '; + Line1[3] := ' zxcvbnm,./ '; Line2[3] := ' ZXCVBNM<>? '; + L := Length(Orig); + for i := 1 to L do + begin + Prob := Chance; + Prob := Prob + Mist; //More mistakes = less chance of another mistake + if (Pos(Orig[i], Excp) <> 0) then Prob := Prob - 2; //If char is hard to type (numbers/symbols) - more chance + if (i = 1) then Prob := Prob + 5; //The first letter - less chance + if (Orig[i] <> ' ') and (Random(Max(Prob, 0)) = 0) then + begin + if (Pos(Orig[i], Norm) <> 0) then + Line := Line1 + else + if (Pos(Orig[i], Caps) <> 0) then + Line := Line2; + for j := 0 to 3 do + begin + TPos := Pos(Orig[i], Line[j]); + if (TPos <> 0) then + case Random(19) of + 0..5: //Same line + begin + TLine := Line[j]; + try + NewKey := TLine[TPos - 1 + Random(3)]; + except end; + if (NewKey = '') or (NewKey = ' ') then + NewKey := TLine[TPos]; + end; + 6..8: //Line above + begin + TLine := Line[Max(j - 1, 0)]; + try + NewKey := Line[j - 1][TPos + Random(2)]; + except end; + if (NewKey = '') or (NewKey = ' ') then + NewKey := TLine[TPos]; + end; + 9..11: //Line below + begin + TLine := Line[Min(j + 1, High(Line))]; + try + NewKey := TLine[TPos - 1 + Random(2)]; //Wrong case + except end; + if (NewKey = '') or (NewKey = ' ') then + NewKey := TLine[TPos]; + end; + 12..16: + begin + if (i - 1 >= 1) then + begin + if (Pos(Orig[i - 1], Caps) <> 0) then + NewKey := Line2[j][TPos] + else + if (Pos(Orig[i - 1], Norm) <> 0) then + NewKey := Line1[j][TPos] + end else + if (i + 1 <= Length(Orig)) then + begin + if (Pos(Orig[i + 1], Caps) <> 0) then + NewKey := Line2[j][TPos] + else + if (Pos(Orig[i + 1], Norm) <> 0) then + NewKey := Line1[j][TPos]; + end; + end; + 17, 18: if (i <> 1) then NewKey := ''; //Missing letters + end; + end; + end else + NewKey := Orig[i]; + if (NewKey <> Orig[i]) then Inc(Mist); + Result := Result + NewKey; + end; +end; + +(* +GetUpText +~~~~~~~~~ + +.. code-block:: pascal + + function GetUpText : string; + +Returns the text in the upperleft corner (often referred to as UpText). + +.. note:: + + by Simba Development Team. + +Example: + +.. code-block:: pascal + +*) +function GetUpText: string; +begin + Result := rs_GetUpText +end; + +(* +IsUpTextEx +~~~~~~~~~~ + +.. code-block:: pascal + + function IsUpTextEx(Text: String): Boolean; + +Checking uptext using wildcards + +.. note:: + + by Frement + +Example: + +.. code-block:: pascal + +*) +function IsUpTextEx(Text: String): Boolean; +begin + Text := Replace(Text, '?', '.'); + Result := ExecRegExpr('.*'+Text+'.*', GetUpText); +end; + +(* +IsUpTextRe +~~~~~~~~~~ + +.. code-block:: pascal + + function IsUpTextRe(RegEx: String): Boolean; + +Checking uptext using regex + +.. note:: + + by Frement + +Example: + +.. code-block:: pascal + +*) +function IsUpTextRe(RegEx: String): Boolean; +begin + Result := ExecRegExpr(RegEx, GetUpText); +end; + +(* +IsUpText +~~~~~~~~ + +.. code-block:: pascal + + function IsUpText(UpText : string) : Boolean; + +Returns True if there is currently Uptext on the screen + +.. note:: + + by Simba Development Team. + +Example: + +.. code-block:: pascal + +*) +function IsUpText(UpText: string): Boolean; +begin + Result := (Pos(UpText, GetUpText) > 0); +end; + +(* +IsUpTextMultiCustom +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function IsUpTextMultiCustom(Text: TStringArray): Boolean; + +Checks for the occurance of any of the strings in the array. + +.. note:: + + by Starblaster100 & Nielsie95 & Freddy1990 + +Example: + +.. code-block:: pascal + + IsUpTextMultiCustom(['Att', 'ttac', 'ack', 'monst', 'ster']) + +*) +function IsUpTextMultiCustom(Text: TStringArray): Boolean; +var + TheText: string; + i, n: Integer; +begin + TheText := GetUpText; + n := High(Text); + for i := 0 to n do + if (Pos(Text[i], TheText) > 0) then + begin + Result := True; + Exit; + end; +end; + +(* +GetLevelAtPos +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetLevelAtPos(x, y : integer) : integer; + +Returns the level of the characater found at (x, y), uses uptext. Returns -1 if +none are found. + +.. note:: + + by marpis and Nava2 + +Example: + +.. code-block:: pascal + +*) +function GetLevelAtPos(x, y: Integer): integer; +begin + MMouse(x, y, 0, 0); + Wait(RandomRange(80, 150)); + Result := StrToIntDef(Between('l: ', ')', GetUpText), -1); +end; + +(* +FindTextEx +~~~~~~~~~~ + +.. code-block:: pascal + + function FindTextEx(var cx, cy: Integer; txt,font: TStringArray; xs, ys, xe, ye: Integer): Boolean; + +Searches for text or texts in specified box with specified font or fonts returns +true on first find of one of the texts with one of the fonts in the specified +box, returns x, y values aswell. + +.. note:: + + by Stupid3ooo, modified by LordJashin + +Example: + +.. code-block:: pascal + + var + x, y, w, h: Integer; + fonts, txts: TStringArray; + begin + fonts := ['MyOwnFontSet', 'SmallCharacters']; + txts := ['Simba', 'HakunaMatata']; + + SetDesktopAsClient; + GetClientDimensions(w, h); + + if FindTextEx(x, y, txts, fonts, 0, 0, w - 1, h - 1) then + MoveMouse(x, y); + end. +*) + +function FindTextEx(var cx, cy: Integer; txt, fonts: TStringArray; xs, ys, xe, ye: Integer): Boolean; +var + s, j, i: Integer; +begin + for j := 0 to High(txt) do + for i := 0 to High(fonts) do + begin + s := CreateBitmapMaskFromText(ToStr(txt[j]), ToStr(fonts[i])); + + if (xs < 0) then xs := 0; + if (ys < 0) then ys := 0; + + Result := FindBitmapMaskTolerance(S, cx, cy, xs, ys, xe, ye, 30, 30); + FreeBitmap(S); + + if (result) then + exit; + end; +end; + +(* +FindText +~~~~~~~~ + +.. code-block:: pascal + + function FindText(var cx, cy: Integer; txt,font: string; xs, ys, xe, ye: Integer): Boolean; + +Searches for text in specified box with specified font. + +.. note:: + + by Coh3n + +Example: + +.. code-block:: pascal + +*) +function FindText(var cx, cy: integer; txt, font: string; xs, ys, xe, ye: integer): boolean; +begin + result := findTextEx(cx, cy, [txt], [font], xs, ys, xe, ye); +end; + +(* +ClickText +~~~~~~~~~ + +.. code-block:: pascal + + function ClickText(text, chars: string; x1, y1, x2, y2: integer; button: variant): boolean; + +Clicks text if found in the specified box. + +.. note:: + + by Coh3n + Last Updated: Mar. 5th, 2012 by Coh3n + +Example + +.. code-block:: pascal + +*) +function ClickText(text, chars: string; x1, y1, x2, y2: integer; button: variant): boolean; +var + x, y: integer; +begin + if (findText(x, y, text, chars, x1, y1, x2, y2)) then + begin + mouse(x, y, 5, 5, button); + result := true; + end; +end; + +(* +LoadTextTPA +~~~~~~~~~~~ + +.. code-block:: pascal + + Function LoadTextTPA(Text : String; Chars : Integer;var height : integer) : TPointArray; + +Loads a TPA of the text.. It also returns the real height of the Text. Used in FindTextTPAinTPA. + +.. note:: + + by Raymond + +Example + +.. code-block:: pascal + +*) +function LoadTextTPA(Text, Chars: string; var height: integer): TPointArray; +var + w: integer; +begin + result := TPAFromText(text,chars,w,height); + dec(height); +end; + +(* +FindTextTpaEx +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindTextTpaEx(Color,Tol,xs,ys,xe,ye : integer;var x,y : integer; Txt : string; Chars : Integer; Action : (ClickLeft,ClickRight,Move,Nothing)) : Boolean; + +Uses TPA's to find text..Returns the found pos in x and y (if not found both are 0) +In action you can put what you want to do after its found.. +Nothing - Just return wether its found +Move - Just move the mouse to it +Clickleft - Movemouse & Clickmouse left +Clickright - MoveMouse & Clickmouse right + +.. note:: + + by Raymond + +Example: + +.. code-block:: pascal + +*) +function FindTextTPAEx(Color,Tol,xs,ys,xe,ye : integer;var x,y : integer; Txt, Chars : string; Action :fnct_ActionOptions ) : Boolean; +var + TextTPA,SearchTPA, Matches: TPointArray; + Box : TBox; + xx,yy : integer; +begin + FindColorsTolerance(SearchTPA,Color,xs,ys,xe,ye,tol); + if Length(SearchTPA) < 1 then + Exit; + TextTPA:= LoadTextTPA(Txt,Chars,yy); + Result := FindTextTPAinTPA(yy ,TextTPA,SearchTPA,Matches); + x := 0; y:=0; + if Result = False then + Exit; + Box := GetTPABounds(TextTPA); + SortTPAFrom(Matches, Point(Box.x1, Box.y1)); + x := matches[0].x; + y := matches[0].y; + if Action = Nothing then + Exit; + GetMousePos(xx,yy); + if not IntInBox(xx,yy,IntToBox(matches[0].x,matches[0].y,matches[0].x + Box.x2,Matches[0].y + (Box.y2 shr 1))) then + MMouse(matches[0].x + Random(box.x2),Matches[0].y + Random(Box.y2 shr 1),0,0); + if Action = Move then + Exit; + GetMousePos(xx,yy); + MouseAction(xx, yy, 0, 0, Action); +end; + +(* +FindTextTPA +~~~~~~~~~~~ + +.. code-block:: pascal + + function FindTextTpa(Color,Tol,xs,ys,xe,ye : integer; Txt : string; Chars : Integer; Action : (ClickLeft,ClickRight,Move,Nothing)) : Boolean; + +Just like FindTextTpaEx, but without the x and y pos returning. + +.. note:: + + by Raymond + +Example: + +.. code-block:: pascal + +*) +function FindTextTPA(Color, Tol, xs, ys, xe, ye: integer; Txt, Chars: string; Action: fnct_ActionOptions): Boolean; +var + x,y : integer; +begin + Result := FindTextTPAEx(Color,Tol,xs,ys,xe,ye,x,y,Txt,chars,action); +end; + +(* +FindTextTPAMulti +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindTextTPAMulti(Color, tol, xs, ys, xe, ye: integer; Texts: TStringArray; Chars: string;/integer; Action: fnct_ActionOptions): Boolean; + +Just like FindTextTPA, only that it takes an array of strings as text to search for. + +.. note:: + + by Cigue and EvilChicken! + +Example: + +.. code-block:: pascal + +*) + function FindTextTPAMulti(Color, tol, xs, ys, xe, ye: integer; + Texts: TStringArray; Chars: string; Action: fnct_ActionOptions): Boolean; + +var + I: Integer; +begin + for i := 0 to High(Texts) do + if FindTextTPA(Color, Tol, xs, ys, xe, ye, Texts[i], Chars, Action) then + begin + Result := True; + Exit; + end; +end; + +(* +FindNPCChatTextMulti +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindNPCChatTextMulti(txt: TStringArray; action: fnct_ActionOptions): boolean; + +Finds a text said by a NPC in chat. If found it'll perform action, +where action can be: +Nothing - Just return wether its found +Move - Just move the mouse to it +Clickleft - Movemouse & Clickmouse left +Clickright - MoveMouse & Clickmouse right + +.. note:: + + by Kernel Klink, Nielsie95 & Narcle + Last Modified: January 31st, 2012 by Coh3n + +Example: + +.. code-block:: pascal + +*) +function FindNPCChatTextMulti(txt: TStringArray; action: fnct_ActionOptions): boolean; +var + x, y: integer; + chars: TStringArray; +begin + chars := [UpChars, CharsNPC]; + + if (findTextEx(x, y, txt, chars, MCX1, MCY1, MCX2, MCY2)) then + begin + case action of + Move: MMouse(x, y, 6, 3); + ClickLeft: Mouse(x, y, 6, 3, mouse_Left); + ClickRight: Mouse(x, y, 6, 3, mouse_Right); + end; + + result := true; + exit; + end; +end; + +(* +FindNPCChatText +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function FindNPCChatText(txt: string; Action: fnct_ActionOptions): Boolean; + +Finds a text said by a NPC in chat. If found it'll perform action, +where action can be: +Nothing - Just return wether its found +Move - Just move the mouse to it +Clickleft - Movemouse & Clickmouse left +Clickright - MoveMouse & Clickmouse right + +.. note:: + + by Coh3n + +Example: + +.. code-block:: pascal + +*) +function FindNPCChatText(txt: string; action: fnct_ActionOptions): boolean; +begin + result := findNPCChatTextMulti([txt], action); +end; + +(* +SortATPAFromFirstPointY +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SortATPAFromFirstPointY(var a: T2DPointArray; const From: TPoint); + +Sorts the Y coords of the ATPA. + +.. note:: + + by Wizzup? & Narcle + +Example: + +.. code-block:: pascal + +*) +procedure SortATPAFromFirstPointY(var a: T2DPointArray; const From: TPoint); +var + i, l: Integer; + DistArr: TIntegerArray; +begin + l := high(a); + if (l < 0) then + Exit; + + setLength(DistArr, l + 1); + for i := 0 to l do + begin + if (length(a[i]) <= 0) then // prevent out of range errors + continue; + + DistArr[i] := Round(Sqr(From.y - a[i][0].y)); + end; + + QuickATPASort(DistArr, a, 0, l, True); +end; + +(* +SortATPAFromFirstPointX +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure SortATPAFromFirstPointX(var a: T2DPointArray; const From: TPoint); + +Sorts the X coords of the ATPA. + +.. note:: + + by Wizzup? & Narcle + +Example: + +.. code-block:: pascal + +*) +procedure SortATPAFromFirstPointX(var a: T2DPointArray; const From: TPoint); +var + i, l: Integer; + DistArr: TIntegerArray; +begin + l := High(a); + if (l < 0) then + Exit; + + SetLength(DistArr, l + 1); + for i := 0 to l do + begin + if (length(a[i]) <= 0) then + continue; + + DistArr[i] := Round(Sqr(From.x - a[i][0].x)); + end; + + QuickATPASort(DistArr, a, 0, l, True); +end; + +(* +GetChooseOptions +~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetChooseOptions(TextType: string): Array of TOptions; + +Gets the texe from the options menu. + +.. note:: + + by Wizzup? & Narcle + +Example: + +.. code-block:: pascal + +*) +Function GetChooseOptions(TextType: string): Array of TOptions; +var + B, BB, sB, BigBox: TBox; + TPA, TPA1, TPA2: TPointArray; + ATPA, tempatpa: T2DPointArray; + I, L, target, bmp,w,h, cts: Integer; + BoxColors: TIntegerArray; +begin + target := GetImageTarget; + GetClientDimensions(B.X2, B.Y2); + B := IntToBox(0, 0, B.X2-1, B.Y2-1); + cts := GetColorToleranceSpeed; + ColorToleranceSpeed(1); + // Black, Top Blue, grey + BoxColors := [131843, 3682593, 3552822]; + SetLength(ATPA, Length(BoxColors)); + for i := 0 to High(BoxColors) do + FindColorsTolerance(ATPA[i], BoxColors[i], B.X1, B.Y1, B.X2, B.Y2, 0); + TPA := MergeATPA(ATPA); + If Length(TPA) < 100 Then + begin + ColorToleranceSpeed(cts); + Exit; + end; + + ATPA := SplitTPA(TPA, 4); + For i := 0 to High(ATPA) do + begin + B := GetTPABounds(ATPA[i]); + if ((B.x2-B.x1) > 90) and ((B.y2-B.y1) > 18) then + Break + else + B := IntToBox(0, 0, 0, 0); + end; + + If (B.x2 = 0) then + begin + ColorToleranceSpeed(cts); + Exit; + end; + + BigBox := B; + + SetColorToleranceSpeed(3); + FindColorsTolerance(TPA1, 4996381, B.X1, B.Y1, B.X2, B.Y2, 18);//One color covers both Highlighted and non + sB := GetTPABounds(TPA1); + ReturnPointsNotInTPAWrap(TPA1, sB, TPA); + FindColorsTolerance(TPA2, 460291, B.X1, B.Y1, B.X2, B.Y2, 6);//shadow + SetColorToleranceSpeed(cts); + + bmp := CreateBitmap(B.X2-B.X1+2, B.Y2-B.Y1+2); + OffsetTPA(TPA, Point(-B.X1, -B.Y1)); + OffsetTPA(TPA2, Point(-B.X1, -B.Y1)); + FastDrawClear(bmp, 0); + DrawTPABitmap(bmp, TPA, clRed);//Text + DrawTPABitmap(bmp, TPA2, clPurple);//Shadow + ocr_FilterUpTextByCharacteristics(GetMufasaBitmap(bmp)); + GetbitmapSize(bmp,w,h); + SetTargetBitmap(bmp); // new target for findcolorstolerance. + SetLength(ATPA, H div 16); + for i := 0 to High(ATPA) do + FindColorsTolerance(ATPA[i], clRed, 0, 2+i*16, W-1, 18+i*16, 0);//+2 to y to line it up + L := High(ATPA); + SortATPAFromFirstPointY(ATPA, Point(w div 2,0)); + + SetArrayLength(Result, Length(ATPA)); + Result[0].BigBox := BigBox; + for i := 0 to high(ATPA) do + begin + TPA := ATPA[i]; + tempatpa := SplitTPAEx(TPA, 1, 10); // Split one into characters + SortATPAFromFirstPointX(tempatpa, Point(0, 0)); + Result[i].Str := GetTextATPA(tempatpa, 5, 'UpCharsEx'); //Writeln(Result[i].Str); + BB := GetTPABounds(ATPA[i]); + Result[i].Bounds := IntToBox(BB.X1+B.X1, BB.Y1+B.Y1, BB.X2+B.X1, BB.Y2+B.Y1); + setlength(tempatpa,0); + setlength(TPA,0); + end; + ColorToleranceSpeed(cts); + SetImageTarget(target); + FreeBitmap(bmp); +end; + + +(* +ChooseOptionMultiEx +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ChooseOptionMultiEx(Texts: TStringArray; TextType: String; Action: fnct_ActionOptions): Boolean; + +Finds Popup menu, then clicks on it. +Will look for the first string first and so on. +It will search for the Text Type you input valid arguments are +'action', 'player': The white text +'npc': The yellow text +'object': The cyan text +'all': Searches for all colors of text. +Will default to 'all'. + +.. note:: + + by Wizzup? & Nava2 & N1ke! + Last Modified: 22/12/12 by riwu + +Example: + +.. code-block:: pascal + +*) +function ChooseOptionMultiEx(Texts: TStringArray; TextType: String; Action: fnct_ActionOptions): Boolean; +var + B: TBox; + i, H, x, R: Integer; + T: TPoint; + Options: array of TOptions; +begin + Result := False; + Options := GetChooseOptions(TextType); + if (Length(Options) < 1) then + Exit; + H := High(Options); + for i := 0 To H do + begin + if ArrInStr(Texts, Options[i].Str) then + begin + Result := True; + B := Options[i].Bounds; + GetMousePos(T.x, T.y); + + R:= Min(((B.X2 - B.X1) shr 1), 5); //Prevents x2 passed to MouseBoxEx being smaller than x1 + case Action of + ClickLeft: + if PointInBox(T, B) then + ClickMouse2(true) + else + MouseBoxEx(B.x1 + R, B.Y1, B.x2 - R, B.Y1 + 5, R, mouse_Left); + + Move: + if not PointInBox(T, B) then + MouseBoxEx(B.x1 + R, B.Y1, B.x2 - R, B.Y1 + 5, R, mouse_move); + + Nothing: + begin + end; + + else + srl_warn('ChooseOptionMultiEx', 'ClickRight not a valid click for RS menus!', warn_AllVersions); + end; + Exit; + end; + end; + B := Options[0].BigBox;//to mmouse away + if Action <> Nothing then + begin + x := Max(B.X1 - 52, 0); + if x = 0 then + x := B.X2+10; + MMouse(x, Max(B.Y1 - 50, 0), 40, B.Y2-B.Y1); + Wait(200 + Random(100)); + end; +end; + +(* +ChooseOptionMulti +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ChooseOptionMulti(Txt: TStringArray): Boolean; + +Finds Popup menu, then clicks on it. Will look for the first string first and so on. + +.. note:: + + by Wizzup? & N1ke! + +Example: + +.. code-block:: pascal + +*) +function ChooseOptionMulti(Txt: TStringArray): Boolean; +begin + Result := ChooseOptionMultiEx(Txt, 'All', ClickLeft); +end; + +(* +ChooseOptionEx +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function ChooseOptionEx(Txt, TextType: string): Boolean; + +Finds an option in a popup menu, then clicks on it. Searches for TextType. +See ChooseOptionMultiEx for valid options. +Default is 'all'. + +.. note:: + + by Wizzup? + +Example: + +.. code-block:: pascal + +*) +function ChooseOptionEx(Txt, TextType: string): Boolean; +begin + Result := ChooseOptionMultiEx([Txt], TextType, ClickLeft); +end; + +(* +ChooseOption +~~~~~~~~~~~~ + +.. code-block:: pascal + + function ChooseOption(txt: String): Boolean; + +Finds an option in a popup menu, then clicks on it. + +.. note:: + + by Wizzup? + +Example: + +.. code-block:: pascal + +*) +function ChooseOption(Txt: String): Boolean; +begin + Result := ChooseOptionMultiEx([Txt], 'All', ClickLeft); +end; + +(* +OptionsExist +~~~~~~~~~~~~ + +.. code-block:: pascal + + function OptionsExist(txt: TStringArray; Move: boolean): boolean; + +Returns true if an Option in txt is found in the RS Option Menu, will move or do +nothing according to the boolean Move. + +.. note:: + + by Rasta Magician + +Example + +.. code-block:: pascal + +*) +function OptionsExist(txt: TStringArray; MoveMouse: boolean): boolean; +begin + if MoveMouse then + Result := ChooseOptionMultiEx(Txt, 'All', Move) + else + Result := ChooseOptionMultiEx(Txt, 'All', Nothing); +end; + +(* +CloseWindow +~~~~~~~~~~~ + +.. code-block:: pascal + + function CloseWindow: Boolean; + +Closes any open windows. (In RS not your pc roflmaololz, j/k) + +.. note:: + + by NaumanAkhlaQ, Narcle, and Nava2 + Updated: 12 December 2011 by Coh3n + +Example: + +.. code-block:: pascal + + if (BankScreen) then + CloseWindow(); +*) +function CloseWindow: Boolean; +var + Col: TIntegerArray; + b: array[0..1] of TPointArray; + a: T2DPointArray; + Pa: TBox; + i, ii, l, x, y: Integer; +begin + if (CloseBank) then + begin + Result := true; + exit; + end; + + // handles the advanced skill guide window + if (findColorTolerance(x, y, 2994428, 728, 8, 753, 30, 20)) then + begin + mouse(x, y, 3, 3, mouse_Left); + result := true; + exit; + end; + + Col := [1118997, 1449250, {Main typ 1} + 3912691, 1973857, {Quest} + 4282212, 2503226, {Main typ 2} + 39423, 13567, {Red X} + 1514271, 1580837, {Deposit Box} + 1383457, 2107437]; + + for i := 0 to 5 do + begin + FindColorsTolerance(b[0], Col[i * 2], MSCX, MSY1, MSX2, MSCY, 5); + FindColorsTolerance(b[1], Col[i * 2 + 1], MSCX, MSY1, MSX2, MSCY, 5); + l := (High(b[0]) + High(b[1])); + + if InRange(l, 6, 53) or InRange(l, 94, 250) then + begin + a := SplitTPA(CombineTPA(b[0], b[1]), 5); + SortATPAFromFirstPoint(a, Point(507, 14)); + + if (length(a) < 1) then + Continue; + + for ii := 0 to high(a) do + begin + Pa := GetTPABounds(a[ii]); + if ((Pa.x2 - Pa.x1) > 50) or ((Pa.y2 - Pa.y1) > 50) then + Continue; + + MouseBox(Pa.x1, Pa.y1, Pa.x2, Pa.y2, mouse_move); + if (WaitUptextMulti(['lose', 'ack', 'Cl', 'se'], 300)) then + begin + GetMousePos(Pa.x1, Pa.y1); + Mouse(Pa.x1, Pa.y1, 0, 0, mouse_left); + Result := True; + Exit; + end; + end; + end; + end; +end; + +{******************************************************************************* +procedure SetDebugColors(Text, Back: Integer); +By: Nava2 +Description: Sets the next WriteLn's colours to Text and Back respectively. +*******************************************************************************} +{procedure SetDebugColors(txtCol, BackCol: Integer); +begin +end; } + +{******************************************************************************* +procedure WriteArrayCols(Lines: TStringArray; Text, Back: Integer); +By: Nava2 +Description: Writes a TStringArray with Text and Back colours. If not using + 3.20, it will just writeln the array. +*******************************************************************************} +{procedure WriteArrayCols(Lines: TStringArray; Text, Back: Integer); +var + i, h: Integer; +begin + h := High(Lines); + for i := 0 to h do + begin + SetDebugColors(Text, Back); + Writeln(Lines[i]); + end; +end; } diff --git a/SRL/core/timing.simba b/SRL/core/timing.simba new file mode 100644 index 0000000..44e3122 --- /dev/null +++ b/SRL/core/timing.simba @@ -0,0 +1,981 @@ +(* +Timing +====== + +The Timing include contains a lot of timing related functions. + +.. contents:: + +*) +//-----------------------------------------------------------------// +//-- SRL Resource Library --// +//-- » Timing Routines --// +//-----------------------------------------------------------------// +// * function MsToTime(MS, StrType: Integer): string; // by ZephyrsFury, Nava2, and Rasta Magician +// * function TimeRunning: String; // by Rasta Magician +// * procedure MarkTime(var TimeMarker: Integer); // by Stupid3ooo +// * function TimeFromMark(TimeMarker: Integer): Integer; // by Stupid3ooo +// * function TheTime : string; // by RsN +// * function TheDate(DateFormat : Integer) : String; // by Ron & Nava2 +// * function WaitOptionMulti(S: TStringArray; Time: Integer): Boolean; // by Marpis, N1ke! & Rasta Magician +// * function WaitOption(S: String; Time: Integer): Boolean; // by N1ke! +// * function WaitUptextMulti(S: TStringArray; Time: integer): Boolean; // by Marpis & N1ke! +// * function WaitUptext(S: String; Time: Integer): Boolean; // by N1ke! +// * function WaitInvMaxCount(Count, MaxTime: integer): boolean; // by Rasta Magician +// * function WaitInvMinCount(Count, MaxTime: integer): boolean; // by Rasta Magician +// * function WaitColor(x, y, Color, Tol, MaxTime: integer): Boolean; // by Rasta Magician, fixed by TRiLeZ +// * function WaitFindColor(var x, y: integer; x1, y1, x2, y2, Color, Tol, MaxTime: integer): boolean; // by Rasta Magician, fixed by TRiLeZ +// * function WaitColorCount(x1, y1, x2, y2, Color, Tol, MinCount, MaxCount, MaxTime: integer):boolean; // by Rasta Magician +// * function WaitColorGone(Color, x, y, Tol, MaxTime: integer): Boolean; // by TRiLeZ +// * function WaitColorGoneIn(Colour, x1, y1, x2, y2, Tol, MaxTime: integer): Boolean; // by TRiLeZ +// * procedure WaitNone; // by IceFire908 + +const + Time_Formal = 0; + Time_Short = 1; + Time_Abbrev = 2; + Time_Bare = 3; + Time_FStop = 4; + + Date_Formal = 1; + Date_Month = 2; + Date_Day = 3; + +{ const srl_MaxWaitTime; + Description: Used when ever WaitFunc is used in SRL. Increase for slow computers. } + srl_MaxWaitTime = 400; + +function InvCount: Integer; forward; +function GetCurrentTab: Integer; forward; +function TabExists(Tab: Integer): Boolean; forward; +function GameTab(Tab: Integer): Boolean; forward; + +(* +MsToTime +~~~~~~~~ + +.. code-block:: pascal + + function MsToTime(MS, StrType: Integer): string; + +Takes MS in milliseconds and outputs a string with hours, mins and +seconds. Different styles can be created with different StrType values: +Str Type: + + - Time_Formal: 2 Hours, 47 Minutes and 28 Seconds + - Time_Short: 02h, 47m, 28s + - Time_Abbrev: 2 hr, 47 min, 28 sec + - Time_Bare: 02:47:28 + - Time_FStop: 12.04.40 + +.. note:: + + by Zephyrsfury, Nava2 and Rasta Magician. + +Example: + +.. code-block:: pascal + +*) +function MsToTime(MS, TheType: Integer): string; +var + STA: array [0..4] of TVariantArray; + Time: array [0..2] of Integer; + i: Integer; +begin + Result := ''; + if (not(InRange(TheType, 0, High(STA)))) then + begin + srl_Warn('MsToTime', 'TheType: ''' + IntToStr(TheType) + ''' is not a valid value. Using Time_Bare.', warn_AllVersions); + TheType := Time_Bare; + end; + STA[Time_Formal] := [' Hours, ', ' Minutes and ', ' Seconds', False, 0]; + STA[Time_Short] := ['h ', 'm ', 's', False, 2]; + STA[Time_Abbrev] := [' hr ', ' min ', ' sec', False, 0]; + STA[Time_Bare] := [':', ':', '', True, 2]; + STA[Time_FStop] := ['.', '.', '', True, 2]; + ConvertTime(MS, Time[0], Time[1], Time[2]); + for i := 0 to 2 do + if (Time[i] > 0) or (STA[TheType][3]) or (i = 2) then + Result := Result + PadZ(IntToStr(Time[i]), STA[TheType][4]) + STA[TheType][i]; +end; + +(* +TimeRunning +~~~~~~~~~~~ + +.. code-block:: pascal + + function TimeRunning: String; + +Returns Time since the script was started (GetTimeRunning). + +.. note:: + + by Rasta Magician. + +Example: + +.. code-block:: pascal + +*) +function TimeRunning: string; +begin + Result := MsToTime(GetTimeRunning, Time_Formal); +end; + +(* +MarkTime +~~~~~~~~ + +.. code-block:: pascal + + procedure MarkTime(var TimeMarker: Integer); + +Sets TimeMarker to current system time + +.. note:: + + by Stupid3ooo + +Example: + +.. code-block:: pascal + +*) +procedure MarkTime(var TimeMarker: Integer); +begin + TimeMarker := GetSystemTime; +end; + +(* +TimeFromMark +~~~~~~~~~~~~ + +.. code-block:: pascal + + function TimeFromMark(TimeMarker: Integer): Integer; + +Returns Milliseconds since MarkTime was set + +.. note:: + + by Stupid3ooo + +Example: + +.. code-block:: pascal + +*) +function TimeFromMark(TimeMarker: Integer): Integer; +begin + Result := GetSystemTime - TimeMarker; +end; + + +(* +TheTime +~~~~~~~~ + +.. code-block:: pascal + + function TheTime(FullTime : boolean) : string; + +Returns current time as a string +FullTime = True will return in 24 hours rather than 12 hours + +.. note:: + + by RsN (fixed by Ron and Markus) + +Example: + +.. code-block:: pascal + +*) +function TheTime: string; +var + Hour, Mins, Sec, MSec: Word; + PAM: string; +begin + DecodeTime(Now, Hour, Mins, Sec, MSec); + PAM := 'AM'; + if (Hour > 12) then + begin + Hour := Hour - 12; + PAM := 'PM'; + end else if (Hour = 12) then + PAM := 'PM' + else if (Hour = 0) then + Hour := 12; + Result := (Padz(IntToStr(Hour), 2) + ':' + Padz(IntToStr(Mins), 2) + ':' + Padz(IntToStr(Sec), 2) + ' ' + PAM); +end; + +(* +TheDate +~~~~~~~ + +.. code-block:: pascal + + function TheDate(DateFormat : Integer) : String; + +TheDate will return the current date. DateFormats can be: + + - Date_Formal = April 2nd, 2007 Month Day, Year + - Date_Month = 04/02/07 Month/Day/Year + - Date_Day = 02-04-07 Day-Month-Year + +.. note:: + + by Ron, Nava2 & Narcle + +Example: + +.. code-block:: pascal + +*) +function TheDate(DateFormat: Integer): string; +var + Year, Month, Day: Word; + D: string; + Mnths, sfx: TStringArray; +begin + DecodeDate(Date, Year, Month, Day); + Mnths := ['January', 'February', 'March', 'April', 'May', 'June', 'July', + 'August', 'September', 'October', 'November', 'December']; + sfx := ['st', 'nd', 'rd']; + case DateFormat of + 1: + begin + if InRange(Day mod 10, 1, 3) and not InRange(Day, 11, 13) then + D := sfx[(Day mod 10)-1] + else + D := 'th'; + Result := Mnths[Month - 1] + ' ' + IntToStr(Day) + D +', ' + IntToStr(Year); + end; + 2: Result := Padz(IntToStr(Month), 2) + '/' + Padz(IntToStr(Day), 2) + '/' + Copy(IntToStr(Year), 3, 4); + 3: Result := Padz(IntToStr(Day), 2) + '-' + Padz(IntToStr(Month), 2) + '-' + Copy(IntToStr(Year), 3, 4); + else + srl_Warn('TheDate', 'DateFormat can only be 1, 2, or 3!', warn_AllVersions); + end; +end; + +(* +WaitFuncEx +~~~~~~~~~~ + +.. code-block:: pascal + + function WaitFuncEx(Func: string; var Args: TVariantArray; WaitPerLoop, MaxWait: integer): boolean; + +Calls Func with arguments Args every WaitPerLoop milliseconds for a max of +MaxWait milliseconds. Func can return any basic types (boolean, string, +integer). Boolean: Returns it. String: Returns true if string equals 'true'. +Integer: Returns true unless it equals 0. + +.. note:: + + by Dgby714 + +Example: + +.. code-block:: pascal + + var + V: TVariantArray; + begin + V := [0, 0, 16711680, 4, 4, 500, 500]; + WriteLn(WaitFuncEx('FindColorEx', V, 10 + Random(15), 1000)); + end. +*) +function WaitFuncEx(Func: string; var Args: TVariantArray; WaitPerLoop, MaxWait: integer): boolean; +var + T: integer; + Temp: variant; +begin + T := GetSystemTime + MaxWait; + while (GetSystemTime < T) do + begin + Temp := CallProc(Func, Args); + if (not VariantIsString(Temp)) then + Temp := ToStr(Temp); + Result := StrToBoolDef(Temp, False); + if (Result) then + Exit; + Wait(WaitPerLoop); + end; +end; + +(* +WaitFunc +~~~~~~~~ + +.. code-block:: pascal + + function WaitFunc(Func: Function: Boolean; WaitPerLoop, MaxTime: Integer): Boolean; + +Waits for function Func to be true. WaitPerLoop is how often you +want to call "Func" function. +Example: "WaitFunc(@BankScreen, 10 + Random(15), 750);" will check if BankScreen +is open every 10-25th millisecond, for a maximum of 750 milliseconds. +Notice the '@'. + +.. note:: + + by Rasta Magician, small edit by EvilChicken! + +Example: + +.. code-block:: pascal + +*) +function WaitFunc(Func: function: Boolean; WaitPerLoop, MaxTime: Integer): Boolean; +var + T: Integer; +begin + T := GetSystemTime + MaxTime; + while (GetSystemTime < T) do + begin + if (Func()) then + begin + Result := True; + Exit; + end; + Wait(WaitPerLoop); + end; +end; + +(* +WaitOptionMultiEx +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitOptionMultiEx(S: TStringArray; TextType: string; + Action: fnct_ActionOptions; Time: Integer): Boolean; + +Waits for a TStringArray of options and selects one of them. +Searches for TextType you input. +'action', 'player': The white text +'item': The orange text +'npc': The yellow text +'object': The cyan text +'all': Searches for all colors of text. +Will default to 'all'. + +.. note:: + + by Infantry001 + +Example: + +.. code-block:: pascal + +*) +function WaitOptionMultiEx(S: TStringArray; TextType: string; Action: fnct_ActionOptions; Time: Integer): Boolean; +var + T: Integer; +begin + Result := False; + T := GetSystemTime + Time; + while (GetSystemTime < T) do + begin + if (ChooseOptionMultiEx(S, TextType, Action)) then + begin + Result := True; + Exit; + end; + Wait(20 + Random(10)); + end; +end; + +(* +WaitOptionMulti +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitOptionMulti(S: TStringArray; Time: Integer): Boolean; + +Waits for a TStringArray of options and selects one of them + +.. note:: + + by Marpis, N1ke! & Rasta Magician + +Example: + +.. code-block:: pascal + +*) +function WaitOptionMulti(S: TStringArray; Time: Integer): Boolean; +begin + Result := WaitOptionMultiEx(S, 'all', ClickLeft, Time); +end; + +(* +WaitOptionEx +~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitOptionEx(S, TextType: String; Time: Integer): Boolean; + +Waits for an Option and selects it. Searches for TextType. + +.. note:: + + by Infantry001 + +Example: + +.. code-block:: pascal + +*) +function WaitOptionEx(S, TextType: string; Action: fnct_ActionOptions; Time: Integer): Boolean; +begin + Result := WaitOptionMultiEx([S], TextType, Action, Time); +end; + +(* +WaitOption +~~~~~~~~~~ + +.. code-block:: pascal + + function WaitOption(S: String; Time: Integer): Boolean; + +Waits for an Option and selects it + +.. note:: + + by N1ke! + +Example: + +.. code-block:: pascal + +*) +function WaitOption(S: string; Time: Integer): Boolean; +begin + Result := WaitOptionMultiEx([S], 'all', ClickLeft, Time); +end; + +(* +WaitUpTextMulti +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitUpTextMulti(S: TStringArray; Time: integer): Boolean; + +Waits for a TStringArray of UpText, returns true if found + +.. note:: + + by Marpis & N1ke! + +Example: + +.. code-block:: pascal + +*) +function WaitUpTextMulti(S: TStringArray; Time: Integer): Boolean; +var + T: Integer; +begin + Result := false; + T := GetSystemTime + Time; + while (GetSystemTime < T) do + begin + if (IsUpTextMultiCustom(S)) then + begin + Result := True; + Exit; + end; + Wait(20 + Random(20)); + end; +end; + +(* +WaitUptext +~~~~~~~~~~ + +.. code-block:: pascal + + function WaitUptext(S: String; Time: Integer): Boolean; + +Waits for an UpText, returns true if found + +.. note:: + + by Marpis edited by N1ke! + +Example: + +.. code-block:: pascal + +*) +function WaitUptext(S: string; Time: Integer): Boolean; +begin + Result := WaitUptextMulti([S], Time); +end; + +(* +WaitInvCount +~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitInvCount(Count, MaxTime: Integer; CountType: (MaxCT, MinCT, ExactCT)): boolean; + +Waits for a maximum inv count. Returns true if InvCount <= Count + +.. note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + +*) +function BankScreen: Boolean; forward; +function WaitInvCount(Count, MaxTime: Integer; CountType: (MaxCT, MinCT, ExactCT)): boolean; +var + T: integer; +begin + if not(BankScreen) then + if not GameTab(tab_Inv) then exit; + + Result := false; + T := GetSystemTime + MaxTime; + + while GetSystemTime < T do + begin + wait(10); + case CountType of + MaxCT : if InvCount <= Count then Result := true; + MinCT : if InvCount >= Count then Result := true; + ExactCT : if InvCount = Count then Result := true; + end; + + if Result then break; + + end; +end; + +(* +WaitInvMaxCount +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitInvMaxCount(Count, MaxTime: integer): boolean; + +Waits for a maximum inv count. Returns true if InvCount <= Count + +.. note:: + + by Rasta Magician. + +Example: + +.. code-block:: pascal + +*) +function WaitInvMaxCount(Count, MaxTime: integer): boolean; +begin + Result := WaitInvCount(Count, MaxTime, MaxCT); +end; + +(* +WaitInvMinCount +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitInvMinCount(Count, MaxTime: integer): boolean; + +Waits for a minimum inv count. Returns true if InvCount >= Count + +.. note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + +*) +function WaitInvMinCount(Count, MaxTime: integer): boolean; +begin + Result := WaitInvCount(Count, MaxTime, MinCT); +end; + +(* +WaitColor +~~~~~~~~~ + +.. code-block:: pascal + + function WaitColor(x, y, Color, Tol, MaxTime: integer): Boolean; + +Waits for a color at (x, y) with tolerance Tol, returns true if found + +.. note:: + + by Rasta Magician, fixed by TRiLeZ + +Example: + +.. code-block:: pascal + +*) +function WaitColor(X, Y, Color, Tol, MaxTime: Integer): Boolean; +var + Time: Integer; +begin + Result := False; + if tol = 0 then tol := 1; //due to scar bug + Time := GetSystemTime + MaxTime; + while (Time > GetSystemTime) do + begin + if SimilarColors(GetColor(X, Y), Color, Tol) then + begin + Result := True; + Exit; + end; + Wait(5 + Random(6)); + end; +end; + +(* +WaitFindColor +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitFindColor(var x, y: integer; Color, Tol, x1, y1, x2, y2, MaxTime: integer): Boolean; + +Waits for a color at (x, y) with tolerance Tol, returns true if found + +.. note:: + + by Rasta Magician, fixed by TRiLeZ + +Example: + +.. code-block:: pascal + +*) +function WaitFindColor(var X, Y: Integer; Color, x1, y1, x2, y2, Tol, MaxTime: Integer): Boolean; +var + Time: Integer; +begin + Result := False; + Time := GetSystemTime + MaxTime; + while (GetSystemTime < Time) do + begin + if FindColorTolerance(X, Y, Color, x1, y1, x2, y2, Tol) then + begin + Result := True; + Exit; + end; + Wait(10 + Random(6)); + end; +end; + +(* +WaitFindColors +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitFindColors(var x, y: integer; Color, Tol, x1, y1, x2, y2, MaxTime: integer): Boolean; + +Waits for a color at (x, y) with tolerance Tol, returns true if found + +.. note:: + + by IceFire908 based completely off WaitFindColor + +Example: + +.. code-block:: pascal + +*) +function WaitFindColors(var TPA: TPointArray; Color, x1, y1, x2, y2, Tol, MaxTime: Integer): Boolean; +var + Time: Integer; +begin + Result := False; + Time := GetSystemTime + MaxTime; + while (GetSystemTime < Time) do + begin + FindColorsTolerance(TPA, Color, x1, y1, x2, y2, Tol); + if (Length(TPA) > 0) then + begin + Result := True; + Exit; + end; + Wait(10 + Random(6)); + end; +end; + +(* +WaitColorCount +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitColorCount(Color, x1, y1, x2, y2, Tol, MinCount, MaxCount, MaxTime: integer):boolean; + +Waits Color count in box (x1, y1, x2, y2) with Tol + +.. note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + +*) +function WaitColorCount(Color, x1, y1, x2, y2, Tol, MinCount, MaxCount, MaxTime: integer):boolean; +var + Time: integer; + TPA: TPointArray; +begin + Result := False; + Time := GetSystemTime + MaxTime; + while (GetSystemTime < Time) do + begin + if FindColorsTolerance(TPA, Color, x1, y1, x2, y2, Tol) then + if InRange(Length(TPA), MinCount, MaxCount) then + begin + Result := True; + Exit; + end; + Wait(15 + Random(10)); + end; +end; + +(* +WaitColorGone +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitColorGone(Color, x, y, Tol, MaxTime: integer): Boolean; + +Waits until a colour is gone at (x, y) with tolerance and a timeout. +Results true if the colour disappeared at (x, y) within the time cap. + +.. note:: + + by TRiLeZ + +Example: + +.. code-block:: pascal + +*) +function WaitColorGone(Color, x, y, Tol, MaxTime: integer): Boolean; +var + Time: Integer; +begin + Result := False; + if Tol = 0 then Tol := 1; + Time := GetSystemTime + MaxTime; + while (Time > GetSystemTime) do + begin + if (not SimilarColors(GetColor(X, Y), Color, Tol)) then + begin + Result := True; + Exit; + end; + Wait(10); + end; +end; + +(* +WaitColorGoneIn +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitColorGoneIn(Colour, x1, y1, x2, y2, Tol, MaxTime: integer): Boolean; + +Waits until a colour is gone in an area with tolerance and a timeout. +Results true if the colour disappeared in the area within the time cap. + +.. note:: + + by TRiLeZ + +Example: + +.. code-block:: pascal + +*) +function WaitColorGoneIn(Colour, x1, y1, x2, y2, Tol, MaxTime: integer): Boolean; +var + Time, CX, CY: Integer; +begin + Result := False; + if Tol = 0 then Tol := 1; + Time := GetSystemTime + MaxTime; + while (Time > GetSystemTime) do + begin + if (not FindColorTolerance(cx, cy, Colour, x1, y1, x2, y2, Tol)) then + begin + Result := True; + Exit; + end; + Wait(10); + end; +end; + +(* +WaitFindDTMEx +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitFindDTM(var x, y: integer; DTM, waitTime: integer): boolean; + +waits 'waitTime' for the 'DTM' to be found. If found, returns true and the +DTM's coodinates in x and y. + +.. note:: + + Author: Coh3n + Last Modified: Mar. 8th, 2012 by beginner5 + +Example: + +.. code-block:: pascal + + if (WaitFindDTM(dtmHatchet, x, y, MIX1, MIY1, MIX2, MIY2, 5000)) then + mouse(x, y, 5, 5, mouse_Left); +*) +function WaitFindDTMEx(DTM: integer; var x, y: integer; xs, ys, xe, ye, WaitPerLoop, MaxTime: integer): boolean; +var + t: integer; +begin + t := (getSystemTime + MaxTime); + + while (getSystemTime < t) do + begin + if (findDTM(DTM, x, y, xs, ys, xe, ye)) then + begin + result := true; + break; + end; + + wait(WaitPerLoop); + end; +end; + +(* +WaitFindDTM +~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitFindDTM(var x, y: integer; DTM, waitTime: integer): boolean; + +waits 'waitTime' for the 'DTM' to be found. If found, returns true and the +DTM's coodinates in x and y. + +.. note:: + + Author: Coh3n + Last Modified: Mar. 8th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + if (WaitDTM(x, y, dtmHatchet, 5000)) then + mouse(x, y, 5, 5, mouse_Left); +*) +function WaitFindDTM(var x, y: integer; DTM, waitTime: integer): boolean; +begin + result := waitFindDTMEx(DTM, x, y, MIX1, MIY1, MIX2, MIY2, 50, waitTime); +end; + +(* +WaitTabExists +~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitTabExists(tab, waitTime: integer): boolean; + +waits 'waitTime' for the 'tab' to exist. Useful for detecting when a player +has returned from a random event. + +.. note:: + + Author: Coh3n + Last Modified: Jan. 22nd, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + if (WaitTabExists(TAB_MAGIC, 5000)) then + writeln('exited the random'); +*) +function WaitTabExists(tab, waitTime: integer): boolean; +var + t: Integer; +begin + t := GetTickCount() + waitTime; + repeat + Result := TabExists(tab); + until Result or (GetTickCount() >= t); +end; + +(* +WaitNPCTalking +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WaitNPCTalking(NPC: string, waitTime: integer): boolean; + +waits 'waitTime' for the 'NPC' name to appear in the chat box. + +.. note:: + + Author: Coh3n + Last Modified: Jan. 29th, 2012 by Coh3n + +Example: + +.. code-block:: pascal + + if (WaitNPCTalking(NAME_NPC_GILES, 5000)) then + writeln('Talking to Giles'); +*) +function getNPCChatName(): string; forward; +function WaitNPCTalking(NPC: string; waitTime: integer): boolean; +var + t: integer; +begin + t := (getSystemTime + waitTime); + + while (getSystemTime < t) do + begin + if (getNPCChatName() = NPC) then + begin + result := true; + break; + end; + + wait(50 + random(25)); + end; +end; diff --git a/SRL/core/worldswitcher.simba b/SRL/core/worldswitcher.simba new file mode 100644 index 0000000..1e57f64 --- /dev/null +++ b/SRL/core/worldswitcher.simba @@ -0,0 +1,783 @@ +(* +Worldswitcher +============= + +The Worldswitcher include contains all kinds of functions to control the built-in RS world switcher. + +.. contents:: + +*) + +type + TWorld = record + Number, PlayerNo: Integer; + Members: Boolean; + Prefix, Location, Activity, Language: String; + LootShare, QuickChat, PVP: Boolean; + end; + TWorldArray = array of TWorld; + +var + WorldArray: TWorldArray; + WorldsOrdered: Boolean; + +function ExitToLobby: Boolean; forward; +function LogInPlayer: Boolean; forward; + +(* +WorldScreen +~~~~~~~~~~~ + +.. code-block:: pascal + + function Worldscreen: boolean; + +Returns true if the Worldswitcher screen is open + +.. note:: + + by Icefire908 + +Example: + +.. code-block:: pascal + +*) +function WorldScreen: Boolean; +begin + Result := (GetLobbyTab = L_WorldSelect); +end; + +(* +OpenWorldScreen +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function: OpenWorldScreen: Boolean; + +Opens the Worldswitcher screen. Returns true if it is succesfully opened. + +.. note:: + + by Bionicle1800 + +Example: + +.. code-block::pascal + +*) +function OpenWorldScreen: Boolean; +begin + Result := LobbyTab(2); +end; + +const + SRL_LG_ENGLISH = 0; + SRL_LG_GERMAN = 1; + SRL_LG_FRENCH = 2; + SRL_LG_PORTUGUESE = 3; + SRL_WORLDPARSE_LANG = SRL_LG_ENGLISH; + SRL_WS_ARROWCOLOR = 1008783;//Arrow color that can order the worlds; + SRL_WS_WHITECOLOR = 16579836;//White text color, (f2p); + SRL_WS_YELLOWCOLOR = 6618364;//Yellow text color, (p2p); + SRL_WS_SCROLLCOLOR1 = 1250841;//Black color on the left side of scroll area + SRL_WS_SCROLLCOLOR2 = 592137;//Black color under scroll bar + +(* +UpdateWorlds +~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure UpdateWorlds; + +Parses the worlds page into Worlds.ini + +.. note:: + + by mixster + +Example: + +.. code-block::pascal + +*) +function UpdateWorlds: Boolean; +var + worldList: TWorldArray; + str, Path: string; + tsa, tsb: TStringArray; + W, I, H, Time: Integer; +begin + try + Result := True; + + Path := IncludePath + 'SRL/SRL/misc/worlds.ini'; + Writeln('NOTE: Attempting to update the Worlds.INI, please allow the script to access this file.'); + Time := GetTimeRunning; + W := RewriteFile(Path, False); + CloseFile(W); + if (SRL_WORLDPARSE_LANG = SRL_LG_ENGLISH) then + str := '' + else + str := 'l=' + IntToStr(SRL_WORLDPARSE_LANG) + '/'; + str := GetPage('http://www.runescape.com/' + str + 'slu.ws?order=WMPLA'); + Delete(str, 1, Pos('', str)); + Delete(str, 1, Pos('', '<', tsb[2]), 2000); + if (Between('"', '"', tsb[3]) = 'a') or (Between('"', '"', tsb[3]) = 'a d') then + begin + Location := 'Activity'; + Activity := Between('>', '<', tsb[3]); + end + else + begin + Location := Between('>', '<', tsb[3]); + Activity := ''; + end; + Prefix := Between('http://', '.runescape', tsb[1]); + if Prefix = '' then + Prefix := Replace(Lowercase(Between('>' + #10, #10 + #10, tsb[1])), ' ', ''); + Number := StrToIntDef(Replace(Prefix, 'world', ''), -1); + if Number = -1 then + begin + Writeln('Invalid world number produced: ' + Prefix); + Writeln('Assuming has suffix, trying again'); + str := Replace(Prefix, 'world', ''); + Number := StrToIntDef(Copy(str, 1, Length(str) - 1), -1); + if Number = -1 then + Writeln('Failed to gather a world number') + else + Writeln('Succeeded, got ' + IntToStr(Number)); + end; + LootShare := Between('"', '"', tsb[4]) = 'd'; + QuickChat := Activity = 'Quick Chat'; + PvP := Activity = 'High-risk Wilderness Worlds'; + Members := Between('"', '"', tsb[5]) = 'm'; + end; + //Writeln('Writing to the INI File. T: ' + IntToStr(GetTimeRunning - W)); + except + Result := False; + //SRL_Warn('UpdateWorlds', ExceptionToString(ExceptionType, ExceptionParam), Warn_AllVersions); + end; + if not Result then Exit; + WriteINI('Worlds', 'Count', IntToStr(High(worldList) + 1), Path); + WriteINI('Worlds', 'High', IntToStr(worldList[High(worldList)].Number) + #13#10, Path); + H := High(worldList); + for I := 0 to H do + with worldList[I] do + begin + Str := 'World' + IntToStr(Number); + DeleteINI(Str, '', Path); + WriteINI(Str, 'Prefix', Prefix, Path); + WriteINI(Str, 'Activity', Activity, Path); + //WriteINI(Str, 'Type', BoolToStr(Members), Path); + if (Members) then + WriteINI(Str, 'Type', 'Members', Path) + else + WriteINI(Str, 'Type', 'Free', Path); + //WriteINI(Str, 'Flag', fla + 'Flag', Path); + WriteINI(Str, 'Location', Location, Path); + WriteINI(Str, 'LootShare', BoolToStr(LootShare), Path); + WriteINI(Str, 'QuickChat', BoolToStr(QuickChat), Path); + WriteINI(Str, 'PvP', BoolToStr(PvP) + #13#10, Path); + end; + Writeln('Parsed Worlds Page into Worlds.INI. Took ' + IntToStr(GetTimeRunning - Time) + ' ms.'); +end; + +(* +LoadWorldArrays +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + procedure LoadWorldArrays; + +Loads the world array into Worldarray from Worlds.ini + +..note:: + + by Narcle; Edits by Nava2; + +Example: + +.. code-block:: pascal + +*) +procedure LoadWorldArrays; +var + i, H, Hw: integer; + FilePath: String; +begin + FilePath := IncludePath + 'SRL/SRL/misc/worlds.ini'; + try + H := StrToInt(ReadINI('Worlds', 'High', FilePath)); + except + Writeln('LoadWorldArrays: Could not load world arrays, attempting to rewrite Worlds.INI'); + if not UpdateWorlds then + begin + SRL_Warn('LoadWorldArrays', 'Could not Load World arrays, please download mixster''s world parser, and replace Worlds.ini', Warn_AllVersions); + Exit; + end; + end; + SetArrayLength(WorldArray, H + 1); + for i := 1 to H do + if not (ReadINI('World' + IntToStr(i), 'Prefix', FilePath) = '') then + begin + WorldArray[Hw].Number := i; + WorldArray[Hw].Prefix := ReadINI('World' + IntToStr(i), 'Prefix', FilePath); + WorldArray[Hw].Members := (ReadINI('World' + IntToStr(i), 'Type', FilePath) = 'Members'); + WorldArray[Hw].LootShare := StrToBool(ReadINI('World' + IntToStr(i), 'Lootshare', FilePath)); + WorldArray[Hw].QuickChat := StrToBool(ReadINI('World' + IntToStr(i), 'Quickchat', FilePath)); + WorldArray[Hw].PVP := StrToBool(LowerCase(ReadINI('World' + IntToStr(i), 'PvP', FilePath))); + WorldArray[Hw].Language := ReadINI('World' + IntToStr(i), 'ServLang', FilePath); + Inc(Hw); + end; + SetArrayLength(WorldArray, Hw); +end; + +(* +WS_CurrentWorldEx +~~~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WS_CurrentWorldEx: Integer; + +Results Current world from WorldScreen + +..note:: + + by Home + +Example: + +.. code-block:: pascal + +*) +function WS_CurrentWorldEx: Integer; +var + Box :TBox; + TPA :TPointArray; +begin + if (not (WorldScreen)) then + Exit; + FindColors(TPA, 12378347, 628, 79, 689, 92); + Box := GetTPABounds(TPA); + Result := StrToIntDef(ExtractFromStr(GetTextAtExWrap(Box.X1, Box.Y1, Box.X2, Box.Y2, 0, 3, 4, 12378347, 0, UpChars), Numbers), - 1); +end; + + +(* +WS_CurrentWorld +~~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function WS_CurrentWorld(var World: Integer): Boolean; + +Results true if we are currently in same world as what user inputted. + +..note:: + + by Home + +Example: + +.. code-block:: pascal + +*) + +function WS_CurrentWorld(var World: Integer): Boolean; +begin + if (not (WorldScreen)) then + Exit; + Result := WS_CurrentWorldEx = World; + World := WS_CurrentWorldEx; +end; + + +(* +OrderWorlds +~~~~~~~~~~~ + +.. code-block:: pascal + + Procedure OrderWorlds(by: string; Descending: boolean); + +Orders worlds by 'by' in order 'Descending', Check function for valid params of +'by', Descending = true means the left button + +..note:: + + by NaumanAkhlaQ + +Example: + +.. code-block:: pascal + +*) +Function OrderWorlds(by: string; Descending: boolean): boolean; +var + ATPA: T2DPointArray; + Arr: array of tstringarray; + TPA: TPointArray; + I: Byte; + TB: TBox; +begin + Arr := [TStringArray(['world', 'w', 'worlds']), TStringArray(['players', 'pl', 'player']), TStringArray(['activity', 'location', 'loc', 'act']), + TStringArray(['type', 't']), TStringArray(['ls', 'lootshare']), TStringArray(['ping', 'pi'])]; + + for I := 0 to High(Arr) do + begin + if (InStrArr(Lowercase(By), Arr[i], False)) then + begin + FindColorsTolerance(TPA, SRL_WS_ARROWCOLOR, 92, 0, 716, 200, 1); + + ATPA := SplitTPA(TPA, 2); + SortATPAFromFirstPoint(ATPA, Point(92, 166)); + + if (Length(ATPA) < (I * 2)) then + Exit; + + TB := GetTPABounds(ATPA[(I * 2) + Ord(Descending)]); + MouseBox(TB.x1 + 2, TB.y1 + 2, TB.x2, TB.y2, 1); + + Result := True; + end; + end; +end; + + +(* +FindWorld +~~~~~~~~~ + +.. code-block:: pascal + + function FindWorld(W: integer): Boolean; + +Scrolls to area and returns true if world was found. + +..note:: + + by Narcle fixed by Shuttleu + +Example: + +.. code-block:: pascal + +*) +function FindWorld(W: integer): Boolean; +Var + WPos, SPos, CurPos, i, H, CurW, TextColor: integer; + BarHeight, WorldsOnScreen: integer; + p: TPoint; + TPA, TPA2, TPA3: TPointArray; + SP, SB: TBox; +begin + if not WorldScreen then + Exit; + WS_CurrentWorld(CurW); + if (W = CurW) then + begin + Result := True; + WriteLn('Already on world ' + IntToStr(W)); + Exit; + end; + + if not WorldsOrdered then + begin + if not OrderWorlds('w', True) then + begin + Writeln('FindWorld: Could not order worlds properly.'); + Exit; + end; + WorldsOrdered := true; + wait(400+random(200)); + end; + + FindColorsTolerance(TPA, SRL_WS_SCROLLCOLOR1, 680, 1, 705, 500, 0);//These coords determine the scroll bars general area, it deviates everything. + SB := GetTPABounds(TPA); + With SB do + begin + FindColorsTolerance(TPA2, SRL_WS_SCROLLCOLOR1, x1+3, y1, x1+3, y2, 0);//SRL_WS_SCROLLCOLOR1 + FindColorsTolerance(TPA3, SRL_WS_SCROLLCOLOR2, x1+3, y1, x1+3, y2, 0);//SRL_WS_SCROLLCOLOR2 + end; + TPA2 := CombineTPA(TPA2, TPA3); + SP := GetTPABounds(TPA2); + + BarHeight := (SP.Y2-SP.Y1); + WorldsOnScreen := (SB.y2-SB.y1+32) div 42;//This is HALF of the worlds on screen. I don't use the full amount. + + if Length(WorldArray) < 1 then + LoadWorldArrays; + WPos := -1; + H := High(WorldArray); + for i := 0 to H do + if (WorldArray[i].Number = W) then + begin + WPos := i; + if i < (WorldsOnScreen) then + WPos := 0; + if i > (H+1-(WorldsOnScreen)) then + WPos := (H+1); + if WorldArray[i].Members then + TextColor := SRL_WS_YELLOWCOLOR + else + TextColor := SRL_WS_WHITECOLOR; + Break; + end; + + if WPos = -1 then + begin + srl_Warn('FindWorld', 'World '+IntToStr(W)+' does not exist in worlds.ini ', warn_AllVersions); + Exit; + end; + + SPos := (SB.y1+BarHeight div 2) + (WPos)*(SB.y2-SB.y1-BarHeight) div (H+1-WorldsOnScreen);//need the 0.0 to make it extended inside () + CurPos := (SP.y1 + BarHeight div 2); + Debugln('SCROLLINFO: CurPos: '+ToStr(CurPos)+' WPos: '+ToStr(WPos)+' H+1: '+ToSTr(H+1)+' SPos: '+ToStr(SPos)); + if InRange(SPos, CurPos - BarHeight, CurPos + BarHeight) then + begin//if its too close the scroll bar won't move to correct position + if (CurPos < ((SB.y1+BarHeight/2)+ (SB.y2-SB.y1-BarHeight)/2)) then//half point + Mouse((SB.x1 + (SB.x2-SB.x1)div 2), SB.y2, 0, 0, mouse_left) + else + Mouse((SB.x1 + (SB.x2-SB.x1)div 2), SB.y1, 0, 0, mouse_left); + end; + + //Writeln('SPos := '+ToStr(SPos)); + Mouse((SB.x1 + (SB.x2-SB.x1)div 2), SPos, 0, 0, mouse_left); + wait(300+Random(100)); + Result := IsTextInAreaEx(84, 134, 134, 440, p.X, p.Y, IntToStr(W) + ' ', 0, StatChars, False, False, -1, 2, TextColor); +end; + +(* +GetWorldInfo +~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetWorldInfo(World: Integer; var WorldRec: TWorld): Boolean; + +Records World info into TWorld record, also Results true if world was found. + +..note:: + + by Narcle + +Example: + +.. code-block:: pascal + +*) +function GetWorldInfo(World: Integer; var WorldRec: TWorld): Boolean; +var + xx, yy, x, y, Color: integer; + Num: String; +begin + if (WorldScreen) then + begin + Color := SRL_WS_WHITECOLOR;//white + if not IsTextInAreaEx(84, 134, 134, 440, X, Y, IntToStr(World) + ' ', 0, StatChars, False, False, 0, 2, Color) then + begin + Color := SRL_WS_YELLOWCOLOR;//yellow + if IsTextInAreaEx(84, 134, 134, 440, X, Y, IntToStr(World) + ' ', 0, StatChars, False, False, 0, 2, Color) then + WorldRec.Members := true + else + Exit; + end; + WorldRec.Number := World; + Num := LowerCase(Trim(GetTextAtEx(137, y, 0, StatChars, False, False, 0, 2, Color, 5, False, tr_AllChars))); + if Num = 'full' then + WorldRec.PlayerNo := -2 + else + WorldRec.PlayerNo := StrToIntDef(Num, -1); + WorldRec.Activity := Trim(GetTextAtEx(238, y, 0, StatChars, False, False, 0, 2, Color, 24, False, tr_AllChars)); + WorldRec.LootShare := FindColor(xx, yy, 7711612, 600, y-4, 636, y+14); + WorldRec.QuickChat := Pos('uick', WorldRec.Activity) > 0; + WorldRec.PVP := (Pos('ildern', WorldRec.Activity) > 0); + Result := (WorldRec.PlayerNo > 0); + end; +end; + +(* +QuickSelect +~~~~~~~~~~~ + +.. code-block:: pascal + + Function QuickSelect(World: Integer): Boolean; + +Checks to see if desired world is in the favorites shortcut. Returns 1 if left spot successful, 2 if right spot successful. + +..note:: + + by Ashaman88 & Le Jingle + +Example: + +.. code-block:: pascal + +*) +function QuickSelect(World: Integer): Integer; +var + txt : array [0..1] of String; + i : integer; +begin + Result := -1; + for i := 0 to 1 do + begin + if inRange(world, 1, 99) then + txt[i] := GetTextAtExWrap(569+(i*43), 448, 597+(i*47), 472, 0, 5, 2, 12378347, 2, 'LoginChars') + else + txt[i] := GetTextAtExWrap(569+(i*43), 448, 597+(i*47), 472, 0, 5, 2, 12378347, 2, 'SmallCharsNS'); + txt[i] := Copy(txt[i], 0, High(txt[i])); + if strToIntDef(txt[0], 0) = world then + result := 1 + else if strToIntDef(txt[1], 0) = world then + result := 2; + if inrange(result, 1, 2) then exit; + end; +end; + +(* +SelectWorld +~~~~~~~~~~~ + +.. code-block:: pascal + + Function SelectWorld(W: Integer): Boolean; + +Switches to the specified world. Returns true if successful. + +..note:: + + by Narcle & ZephyrsFury - edited by Ashaman88 + +Example: + +.. code-block:: pascal + +*) +function SelectWorld(W: integer): boolean; +var + x, y, xx, yy, T, CurW: integer; + WRec: TWorld; +begin + if not InRange(W, 1, 200) then + begin + srl_Warn('SelectWorld', 'Invalid World', warn_AllVersions); + Exit; + end; + + case QuickSelect(W) of + -1: + if OpenWorldScreen then + begin + T := GetSystemTime + 60000; + Repeat + Wait(100+random(100)); + until InRange(CountColorTolerance(SRL_WS_ARROWCOLOR, 0, 0, 716, 240, 1), 550, 650) or (GetSystemTime > T); + if (GetSystemTime > T) then + begin + Writeln('World screen did not load after a minute, please refreash.'); + Exit; + end; + WS_CurrentWorld(CurW); + if (W = CurW) then + begin + Result := True; + WriteLn('Already on world ' + IntToStr(W)); + Exit; + end; + + if FindWorld(W) then + begin + wait(100+random(100)); + if GetWorldInfo(W, WRec) then + begin + Writeln('World: '+inttostr(WRec.Number)+', Players: '+inttostr(WRec.PlayerNo)+', Members: '+Booltostr(WRec.Members)+', PvP: '+Booltostr(WRec.PVP)); + if FindText(x, y, ' '+inttostr(W)+' ', StatChars, 84, 134, 140, 440) then + begin + MMouse(x, y, 500, 4); + GetMousePos(x, y); + wait(400+random(100)); + if FindColor(xx, yy, 6316128, x-20, y-2, x+20, y+2) then + begin + GetMousePos(x, y); + Mouse(x, y, 0, 0, mouse_left); + if FindColor(xx, yy, 19890, x-20, y-2, x+20, y+2) then + begin + Writeln('World '+inttostr(W)+' selected.'); + Result := true; + end; + end; + end; + end else + if WRec.PlayerNo = -2 then + WriteLn('World ' + IntToStr(W) + ' is FULL.') + else + WriteLn('World ' + IntToStr(W) + ' is OFFLINE.') + end else + WriteLn('Failed to find World ' + IntToStr(W) + '!'); + if (not(Result)) then TypeByte(vk_Escape); + end; + 1: + begin + MouseBox(569, 498-50, 597, 522-50, Mouse_Left); + Result:=True; + end; + 2: + begin + MouseBox(614, 498-50, 643, 522-50, Mouse_Left); + Result:=True; + end; + end; +end; + + +(* +RandomWorld +~~~~~~~~~~~ + +.. code-block:: pascal + + function RandomWorld(Members, PvP: Boolean): Integer; + +Returns a random world by paramaters. + +..note:: + + by Narcle & mixster + +Example: + +.. code-block:: pascal + +*) +function RandomWorld(Members, PvP: Boolean): Integer; +var + i, H, l: integer; + wArray: TWorldArray; + Mems, Pv: Boolean; +begin + if Length(WorldArray) < 1 then + LoadWorldArrays; + H := High(WorldArray); + SetLength(wArray, H + 1); + if (Members) then + Mems := True; + if (PvP) then + Pv := True; + for i := 0 to H do + if (WorldArray[i].Members = Mems) and (WorldArray[i].PvP = Pv) and (InStrArr(WorldArray[i].Language, ['English', ''], False)) then + begin + wArray[l] := WorldArray[i]; + Inc(l); + end; + Result := wArray[random(l)].Number; +end; + +(* +ChangeWorld +~~~~~~~~~~~ + +.. code-block:: pascal + + function ChangeWorld(W: Integer): Boolean; + +Changes to world W. Returns True if successful. + +..note:: + + by Nava2 + +Example: + +.. code-block:: pascal + +*) +function ChangeWorld(W: Integer): Boolean; +begin + if LoggedIn then + WaitFunc(@ExitToLobby, 500, 5000); + Result := SelectWorld(W); + LoginPlayer; +end; + +(* +ChooseWorldBy +~~~~~~~~~~~~~ + +.. code-block:: pascal + + Function ChooseWorldBy(SettingsNames:TStringArray; SettingsDescending: array of boolean; Members, PVP: boolean): boolean; + +Chooses a world by SettingsNames , ordered by SettingsDescending, Takes into account Members and PVP, Check OrderWorlds for valid params for SettingsNames + +..note:: + + by Rasta Magician + +Example: + +.. code-block:: pascal + +*) +function ChooseWorldBy(SettingsNames:TStringArray; SettingsDescending: array of boolean; Members, PVP: boolean): boolean; +var + TPA: TPointArray; + i, C : integer; +begin + if not WorldScreen then + if not OpenWorldScreen then + exit; + if length(SettingsNames) <> length(SettingsDescending) then + begin + srl_warn('ChooseWorldBy', 'Arrays are not the same length', warn_AllVersions); + SelectWorld(RandomWorld(Members, PVP)); + exit; + end; + for i:= 0 to High(SettingsNames) do + begin + OrderWorlds(SettingsNames[i], SettingsDescending[i]); + wait(1000+random(200)); + end; + wait(1500+random(500)); + for i:= 0 to 15 do //16 worlds show up in screen + begin + FindColorsTolerance(TPA, 16777215, 182, 150+18*i, 206, 159+18*i, 0); + C := Length(TPA); + if (C = 0)or(C = 66) then //failed detection or full + Continue; + if (Members)xor(GetColor(620, 157+18*i) <> 11316396) then + Continue; + if (PVP)xor(GetColor(589, 156+18*i) <> 1251528) then + Continue; + MouseBox(79, 148+18*i, 685, 165+18*i, mouse_left); + for c := 0 to 4 do + begin + wait(200); + Result := not WorldScreen; + if Result then exit; + end; + end; + Result := false; + writeln('Failed to sort the worlds. Choosing random world. Members: ' + + BoolToStr(Members) + '; PVP: ' + BoolToStr(PVP) + ';'); + SelectWorld(RandomWorld(Members, PVP)); +end; diff --git a/SRL/misc/SmartGraphics.simba b/SRL/misc/SmartGraphics.simba new file mode 100644 index 0000000..630331c --- /dev/null +++ b/SRL/misc/SmartGraphics.simba @@ -0,0 +1,558 @@ +{$DEFINE SMART_GRAPHICS} +{* +Smart Grahpics +============== + +The Smart Grahpics include contains functions that will paint graphics on to the +SMART screen. Used to make scripts look nicer and sometimes to display +progress reports. Also used as a useful debugging tool. This is for Simba 0.99 and above. + +*} + +var + SMART_Canvas: TMufasaBitmap; + SMART_DebugSetup, SMART_Reset: Boolean; + +{* + Authors: Coh3n, Brandon. + + Declares everything needed for setting up SmartDebug. + There is no need to call this in scripts. +*} +procedure SMART_SetupDebug; +begin + SmartSetDebug(True); + SMART_Canvas := TMufasaBitmap.Create; + SMART_Canvas.SetPersistentMemory(SmartDebugArray, 765, 553); + SMART_DebugSetup := true; + if not SMART_Reset then + AddOnTerminate('SMART_FreeDebug'); +end; + +{* + Author: Brandon. + + Creates an array of specific colours for use with FastSetPixels. +*} +Function ColorsFromTPA(TPA: TPointArray; Color: Integer): TIntegerArray; +var + I, L: Integer; +begin + SetLength(Result, Length(TPA)); + L:= High(TPA); + For I:= 0 To L Do + Result[I]:= Color; +end; + +{* + Authors: Coh3n, Brandon. + + Clears an Area of the canvas Specified by the box. +*} +procedure SMART_ClearCanvasArea(Area: TBox); +{$IFDEF SMART} +begin + if (not SMART_DebugSetup) then + SMART_SetupDebug; + + SMART_Canvas.Rectangle(Area, 0); + +{$ELSE} +begin +{$ENDIF} +end; + +{* + Author: Coh3n, Brandon. + + Clears the entire Smart Canvas. +*} +procedure SMART_ClearCanvas; +begin + if (not SMART_DebugSetup) then + SMART_SetupDebug; + + If (SMART_CANVAS.TransparentColorSet) then + SMART_CANVAS.FastDrawClear(SMART_CANVAS.GetTransparentColor) + else + SMART_CANVAS.FastDrawClear(0); +end; + +{* + Author: Mormanman. + Clears the MainScreen of Smart. +*} +procedure SMART_ClearMS; +begin + SMART_ClearCanvasArea(IntToBox(MSBox.X1 + SRL_NAVBAR_INGAME_X, + MSBox.Y1 + SRL_NAVBAR_INGAME_Y, MSBox.X2, MSBox.Y2 + SRL_NAVBAR_INGAME_Y)); +end; + +{* + Authors: Sir R. Magician, Brandon. + + Draws a TPA with a specified Colour onto Smart's Canvas. + Clears the Canvas first if Clear is set to true. +*} +procedure SMART_DrawDotsEx(Clear: boolean; Pixels: TPointArray; Color: TColor); +{$IFDEF SMART} +var + P: TPointArray; +begin + if (not SMART_DebugSetup) then + SMART_SetupDebug; + + if Clear then SMART_ClearCanvas; + P := CopyTPA(Pixels); + OffsetTPA(P, Point(SRL_NAVBAR_INGAME_X, SRL_NAVBAR_INGAME_Y)); + SMART_Canvas.DrawTPA(P, Color); +{$ELSE} +begin +{$ENDIF} +end; + +{* + Authors: Sir R. Magician, mormanman, Brandon. + + Draws a 2-Dimensional Array of Pixels on Smart. + Clears the Canvas first if Set to True. +*} +procedure SMART_DrawDotsMulti(Clear: boolean; pixels : T2DPointArray); +{$IFDEF SMART} +var + h, color : integer; +begin + if (not SMART_DebugSetup) then + SMART_SetupDebug; + + if Clear then SMART_ClearCanvas; + + for h := 0 to High(pixels) do + begin + + color := h div 10 + h mod 10; + case color of + 0 : color := clWhite; + 1 : color := clYellow; + 2 : color := clBlue; + 3 : color := clLime; + 4 : color := 26367;//orange + 5 : color := clPurple; + 6 : color := clAqua; + 7 : color := clFuchsia; + 8 : color := clGreen; + 9 : color := clRed; + end; + + SMART_DrawDotsEx(False, pixels[h], color); + end; +{$ELSE} +begin +{$ENDIF} +end; + +{* + Author: mormonman. + + Draws the box of each TPA in the ATPA and write the index number in the top + left corner and a cross at the point found by MiddleTPA. +*} +procedure SMART_DebugATPA(Clear: Boolean; ATPA: T2DPointArray); +{$IFDEF SMART} +var + i, h, len: Integer; + B: TBox; + MP: TPoint; + TPA: TPointArray; + Points: T2DPointArray; +begin + len := Length(ATPA); + if (len < 1) then + Exit; + SetLength(Points, len); + + for i := 0 to High(ATPA) do + begin + B := GetTPABounds(ATPA[i]); + len := Length(ATPA[i]); + if (len > 0) then + begin + TPA := LoadTextTPA(ToStr(i), SmallChars, h); + OffsetTPA(TPA, Point(B.X1+1, B.Y1+1)); + end; + CombineTPAWrap(FindTPAEdges(TPAFromBox(B)), TPA, Points[i]); + MP := MiddleTPA(ATPA[i]); + TPA := [Point(MP.x-1, MP.y), Point(MP.x+1, MP.y), Point(MP.x, MP.y-1), + Point(MP.x, MP.y+1), Point(MP.x-2, MP.y), Point(MP.x, MP.y), + Point(MP.x+2, MP.y), Point(MP.x, MP.y-2), Point(MP.x, MP.y+2)]; + CombineTPAWrap(Points[i], TPA, Points[i]); + end; + + SMART_DrawDotsMulti(Clear, Points); +{$ELSE} +begin +{$ENDIF} +end; + +{* + Author: mormonman + + Draws the TPA bounds and puts a cross at the point created by MiddleTPA. +*} +procedure SMART_DebugTPA(Clear: Boolean; TPA: TPointArray); +begin + SMART_DebugATPA(Clear, [TPA]); +end; + +{* + Author: Sir R. Magician + + Clears the SMART canvas, then draws a red TPA (Dots). +*} +procedure SMART_DrawDots(Dots: TPointArray); +begin + SMART_DrawDotsEx(True, Dots, clRed); +end; + +{* + Author: Coh3n + + Draws a single colored dot (Color) at the set point (Point) on the SMART canvas. + Will clear the SMART canvas if set to do so (Clear). +*} +procedure SMART_DrawDot(Clear: Boolean; Point: TPoint; Color: TColor); +begin + SMART_DrawDotsEx(Clear, [Point], Color); +end; + +{* + Authors: mormonman, Brandon. + + Draws an array of boxes onto the SMART canvas. Set Color to -1 for it to use + different colors (like in SMART_DrawDotsMulti). + Fill will fill each box with a color. +*} +procedure SMART_DrawBoxes(Clear, Fill: Boolean; TBA: TBoxArray; Color: Integer); +{$IFDEF SMART} +var + i, colour, temp: Integer; + Box: TBox; + TPAEdges: TPointArray; +begin + if (not SMART_DebugSetup) then + SMART_SetupDebug; + + if Clear then SMART_ClearCanvas; + + if (Length(TBA) < 1) then Exit; + for i := 0 to High(TBA) do + begin + Box := TBA[i]; + if (Color > 0) then + begin + Temp := color; + end else + begin + colour := i div 5 + i mod 5; + case colour of + 0 : Temp := clWhite; + 1 : Temp := clYellow; + 2 : Temp := clBlue; + 3 : Temp := clLime; + 4 : Temp := clGreen; + end; + end; + + if Fill then + begin + Box := IntToBox(Min(TBA[i].X1, TBA[i].X2), Min(TBA[i].Y1, TBA[i].Y2) + SRL_NAVBAR_INGAME_Y, + Max(TBA[i].X1, TBA[i].X2), Max(TBA[i].Y1, TBA[i].Y2) + SRL_NAVBAR_INGAME_Y); + if (Box.X1 < 0) then Box.X1 := 0; + if (Box.X2 < 0) then Box.X2 := 0; + if (Box.Y1 < 0) then Box.Y1 := 0; + if (Box.Y2 < 0) then Box.Y2 := 0; + SMART_Canvas.Rectangle(Box, Temp) + end else + begin + FindTPAEdgesWrap(TPAFromBox(Box), TPAEdges); + SMART_DrawDotsEx(False, TPAEdges, Temp); + end; + + end; + +{$ELSE} +begin +{$ENDIF} +end; + +{* + Author: mormonman, Brandon. + + Draws a single colored (color) box (Box) on the SMART canvas. Will clear the + canvas if set to do so (Clear). + Fill will fill in the box with the specified Color. +*} +procedure SMART_DrawBoxEx(Clear, Fill: boolean; Box: TBox; color: TColor); +begin + SMART_DrawBoxes(Clear, Fill, [Box], color); +end; + +{* + Author: mormonman + + Clears the SMART canvas, then draws a single red box, specified by 'Box'. +*} +procedure SMART_DrawBox(Box: TBox); +begin + SMART_DrawBoxEx(True, False, Box, clRed); +end; + +{* + Author: Coh3n + + Draws a box on the RS mainscreen, even if the coordinates are outside client + boundaries. + Fill will Fill in the box with the specified Color. +*} +procedure SMART_DrawBoxMS(Clear, Fill: Boolean; Box: TBox; Color: TColor); +begin + if (Box.X1 < MSX1) then Box.X1 := MSX1; + if (Box.Y1 < MSY1) then Box.Y1 := MSY1; + if (Box.X2 > MSX2) then Box.X2 := MSX2; + if (Box.Y2 > MSY2) then Box.Y2 := MSY2; + SMART_DrawBoxEx(Clear, Fill, Box, Color); +end; + +{* + Author: mormonman + + Draws a line a set color (Color) from point 1 (TP1) to point 2 (TP2). Will + clear the SMART canvas if set to do so (Clear). +*} +procedure SMART_DrawLine(Clear: Boolean; TP1, TP2: TPoint; Color: TColor); +var + TempMufasa: TMufasaBitmap; + TempTBitmap: TBitmap; +begin +{$IFDEF SMART} + if (not SMART_DebugSetup) then + SMART_SetupDebug; + + if (Clear) then + SMART_ClearCanvas; + + TempTBitmap := TBitmap.Create; + TempTBitmap.Width := Max(1, iAbs(TP2.X - TP1.X)); + TempTBitmap.Height := Max(1, iAbs(TP2.Y - TP1.Y)); + TempTBitmap.Canvas.Pen.COLOR := Color; + + TempTBitmap.Canvas.moveto(0, 0); + TempTBitmap.Canvas.LineTo(iAbs(TP2.X - TP1.X), iAbs(TP2.Y - TP1.Y)); + + TempMufasa := TMufasaBitmap.Create; + TempMufasa.LoadFromTBitmap(TempTBitmap); + if (SMART_Canvas.TransparentColorSet) then + TempMufasa.SetTransparentColor(SMART_Canvas.GetTransparentColor); + + FastDrawTransparent(Min(TP1.X, TP2.X), Min(TP1.Y, TP2.Y) + SRL_NAVBAR_INGAME_Y, TempMufasa.Index, SMART_Canvas.Index); + + TempMufasa.Free; + TempTBitmap.Free; +{$ENDIF} +end; + +{* + Author: mormonman + + Draws an ellipse on the SMART canvas defined by 'Center', 'XRadius', and + 'YRadius'. If 'Fill' is true it will fill the ellipse, otherwise it draws just + the border. Will clear the SMART canvas if set to do so (Clear). +*} +procedure SMART_DrawEllipse(Clear: Boolean; Center: TPoint; XRadius, YRadius: Integer; Fill: Boolean; Color: TColor); +{$IFDEF SMART} +var + TPA: TPointArray; + TempMufasa: TMufasaBitmap; + TempTBitmap: TBitmap; +begin + if Fill then + begin + if (not SMART_DebugSetup) then + SMART_SetupDebug; + + if Clear then + SMART_ClearCanvas; + + TempTBitmap := TBitmap.Create; + TempTBitmap.Canvas.Brush.COLOR := Color; + + TempTBitmap.Width := (XRadius * 2); + TempTBitmap.Height := (YRadius * 2); + + TempTBitmap.Canvas.Ellipse(Center.X - XRadius, Center.Y - YRadius, Center.X + XRadius, Center.Y + YRadius); + + TempMufasa := TMufasaBitmap.Create; + TempMufasa.LoadFromTBitmap(TempTBitmap); + if (SMART_Canvas.TransparentColorSet) then + TempMufasa.SetTransparentColor(SMART_Canvas.GetTransparentColor); + + FastDrawTransparent(0, SRL_NAVBAR_INGAME_Y, TempMufasa.Index, SMART_Canvas.Index); + TempMufasa.Free; + TempTBitmap.Free; + end else + begin + TPA := TPAFromEllipse(Center.X, Center.Y, XRadius, YRadius); + + if (Length(TPA) >= 1) then + SMART_DrawDotsEx(Clear, TPA, Color); + end; +{$ELSE} +begin +{$ENDIF} +end; + +{* + Author: mormonman + + Draws a circle on the SMART canvas defined by 'Center' and 'Radius'. If 'Fill' + is true it will fill the circle, otherwise it draws just the border. Will + clear the SMART canvas if set to do so (Clear). +*} +procedure SMART_DrawCircle(Clear: Boolean; Center: TPoint; Radius: Integer; Fill: Boolean; Color: TColor); +begin + SMART_DrawEllipse(Clear, Center, Radius, Radius, Fill, Color); +end; + +{* + Author: mormonman + + Draws an array of polygons on the SMART canvas in the set color. Will clear the + SMART canvas if set to do so (Clear). +*} +procedure SMART_DrawPolygons(Clear: Boolean; Polygons: T2DPointArray; color: TColor); +{$IFDEF SMART} +var + i, h, Hi: Integer; +begin + if (Clear) then + SMART_ClearCanvas; + + if (Length(Polygons) < 1) then + Exit; + + for h := 0 to High(Polygons) do + begin + Hi := High(Polygons[h]); + if (Hi < 2) then Exit; + + for i := 0 to Hi - 1 do + SMART_DrawLine(False, Polygons[h][i], Polygons[h][i+1], color); + + SMART_DrawLine(False, Polygons[h][Hi], Polygons[h][0], color); + end; +{$ELSE} +begin +{$ENDIF} +end; + +{* + Authors: Flight & Coh3n + + Draws text on the SMART canvas. Used mainly for progress reports. Parameters + are as follows: + * Clear: Clear the SMART canvas before drawing + * Shadow: if set to true, will add a shadow to the text + * TSA: the string array of what to be printed; each element is a different line + * Placement: the point to start the text drawing + * Font: the font to use (see Simba/Fonts/) + * Colour: the color of the font +*} +procedure SMART_DrawTextMulti(Clear, Shadow: Boolean; TSA: TStringArray; Placement: TPoint; Font: string; Colour: TColor); +var + i, h, TPH: Integer; + TTP, SArr: TPointArray; +begin + if (not SMART_DebugSetup) then + SMART_SetupDebug; + + if (Clear) then + SMART_ClearCanvas; + + TPH := High(TSA); + + for i := 0 to TPH do + begin + TTP := LoadTextTPA(TSA[i], Font, h); + OffsetTPA(TTP, Point(Placement.x, Placement.y+(i*h))); + SMART_DrawDotsEx(False, TTP, Colour); + if Shadow then + begin + SArr := CopyTPA(TTP); + OffsetTPA(SArr, Point(1, 1)); + ClearTPAFromTPAWrap(SArr, TTP, SArr); + SMART_DrawDotsEx(False, SArr, 65536); + end; + end; +end; + +{* + Author: Coh3n + + Draws shadowed line of text on the SMART canvas. Parameters are as follows: + * Clear: Clear the SMART canvas before drawing + * x, y: the coords of where to place the text + * font: the font to use (see Simba/Fonts/) + * Text: the text to draw to the SMART canvas + * Colour: the color of the font +*} +procedure SMART_DrawTextEx(Clear: Boolean; x, y: Integer; font, Text: string; Color: TColor); +begin + SMART_DrawTextMulti(Clear, true, [Text], Point(x, y), font, Color); +end; + +{* + Author: Coh3n + + Same as SMART_DrawTextEx, except clears the canvas before drawing. +*} +procedure SMART_DrawText(x, y: Integer; font, Text: string; Color: TColor); +begin + SMART_DrawTextEx(False, x, y, font, Text, Color); +end; + +{* + Author: Coh3n + + Draws a bitmap (Bitmap) on the SMART canvas at given coordinates (Placement). + Will clear the canvas beforehand if specified to do so (Clear). +*} +procedure SMART_DrawBitmap(Clear: Boolean; Bitmap: Integer; Placement: TPoint); +begin + if (not SMART_DebugSetup) then + SMART_SetupDebug; + + if (Clear) then + SMART_ClearCanvas; + + FastDrawTransparent(Placement.X, Placement.Y + SRL_NAVBAR_INGAME_Y, Bitmap, SMART_Canvas.Index); +end; + +{* + Authors: Coh3n, Brandon. + + Frees the SMART_Canvas bitmap. +*} +procedure SMART_FreeDebug; +begin + try + if (SMART_DebugSetup) then + begin + SMART_Canvas.ResetPersistentMemory; + SMART_Canvas.Free; + SMART_DebugSetup := False; + SMART_Reset := True; + end; + except + Writeln('Failed to free SMART_Canvas bitmap: '+ExceptionToString(ExceptionType, ExceptionParam)); + end; +end; diff --git a/SRL/misc/SmartParams.simba b/SRL/misc/SmartParams.simba new file mode 100644 index 0000000..b2b94c2 --- /dev/null +++ b/SRL/misc/SmartParams.simba @@ -0,0 +1,425 @@ +(* +Smart Params +============ + +.. contents:: + +*) + +{$DEFINE SRL_SMART} +{$DEFINE SMART} +{$loadlib libsmartremote} + +(* +GetSmartParams +~~~~~~~~~~~~~~ + +.. code-block:: pascal + + function GetSmartParams: TStringArray; + +Grabs The Correct Parameters For passing to the SmartClient. + +.. note:: + + By: Brandon. + Modified By: Mormanman, Benland100. + +Example: + +.. code-block:: pascal + +*) +function GetSmartParams: TStringArray; +var + Params: TStringArray; + Page: String; +begin + Page := Between('