forked from 2009Scape/Server
Compare commits
327 commits
Aug-03-202
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 3cdf7767eb | |||
| e9085a8270 | |||
| bfa62864fa | |||
| b372d5e963 | |||
| 590e9fe44f | |||
| 59c55708a6 | |||
| 5a896cecb4 | |||
| e046f46ed2 | |||
| 2ecdde1011 | |||
| cd8cce30a0 | |||
| 06055c0ff8 | |||
| 6e91725d58 | |||
| a9065d763b | |||
| 2ad90e9ed8 | |||
| cecdb97b19 | |||
| 52185005aa | |||
| 7e8c2d8883 | |||
| af446a4c27 | |||
| 67990205b4 | |||
| fa429edc03 | |||
| 3f0c44b1c3 | |||
| b3196a282c | |||
| 4053fdf43c | |||
| 415aa512fb | |||
| 54055e36d0 | |||
| 269eb82850 | |||
| 4d7f26bb47 | |||
| 7538322006 | |||
| 08ffa6fee6 | |||
|
|
bfbfae8391 | ||
| 45ee87e64e | |||
|
|
bcc3bc069e | ||
|
|
48bc0ffb28 | ||
|
|
7b1ebd4608 | ||
|
|
1b0a7d5fca | ||
|
|
fc2247f457 | ||
|
|
47ac5e93d6 | ||
|
|
63f8ec3cbf | ||
|
|
0622aed00c | ||
| 4799069ebd | |||
| 4991b07ff8 | |||
| 7be39c73b9 | |||
| a5eb1ea929 | |||
| d02b16d970 | |||
| 07d8bb6a13 | |||
| 61f5120cfc | |||
| fb0dd3a27d | |||
| 81730af934 | |||
| 6458a6ef95 | |||
| b109b98247 | |||
| daf312ce6b | |||
|
|
dda80d535b | ||
| 9c8c2ada70 | |||
| 18d30a3e1e | |||
| 9926b5c244 | |||
| 40d5478b57 | |||
|
|
5eddd5e98a | ||
| fe117e6976 | |||
| c59e13f0aa | |||
| e88bdf94d3 | |||
| a411c7a5e2 | |||
| 16da0ed93e | |||
| 249c501184 | |||
|
|
448f970c10 | ||
|
|
83b8689b86 | ||
|
|
7592372dc4 | ||
|
|
9b8ba3b6dd | ||
| 680a08ea98 | |||
|
|
6362eee753 | ||
|
|
f0ee476e42 | ||
|
|
0e65f20223 | ||
|
|
af58fae1fc | ||
|
|
74ed5e1bee | ||
|
|
cf08e700fb | ||
|
|
d65a53b275 | ||
|
|
fb9d6307b3 | ||
|
|
45fb89ec73 | ||
|
|
50ba3682b5 | ||
|
|
df73f4a171 | ||
|
|
9eedfc2336 | ||
|
|
e25780a4c5 | ||
|
|
b6560c0e3f | ||
|
|
2d1a626df0 | ||
|
|
4f97dbef8c | ||
|
|
be76ca143b | ||
|
|
053254b504 | ||
|
|
486ca4bb19 | ||
|
|
104533c11d | ||
|
|
9886049429 | ||
|
|
f1131b7d00 | ||
|
|
be47c1d5c9 | ||
|
|
bb860b60e0 | ||
|
|
fed309a70b | ||
|
|
1afd4d5328 | ||
|
|
a6eb706358 | ||
|
|
957477b9b0 | ||
|
|
4387b346dc | ||
|
|
618d39d73c | ||
|
|
62a7dd4324 | ||
|
|
212ce57580 | ||
| 84951244f9 | |||
|
|
389c5858d0 | ||
|
|
5540febf6e | ||
|
|
8a4ea5d1f3 | ||
|
|
0f14639e9b | ||
|
|
e63c6f523a | ||
|
|
612ccc6776 | ||
|
|
b5784c5782 | ||
|
|
867c332466 | ||
|
|
8b1763c3ba | ||
|
|
d0fdf08d13 | ||
| 8e822234fb | |||
| 718d7e39e1 | |||
|
|
d91f77c294 | ||
| 7b5ac708dc | |||
| dd35e479c1 | |||
|
|
c03947e0b0 | ||
|
|
acc6c182a5 | ||
|
|
1b85808885 | ||
|
|
2cf8392691 | ||
|
|
4a016d45e5 | ||
|
|
cd43f8d269 | ||
|
|
0a26d5039a | ||
|
|
c3929cf06c | ||
|
|
fcbea5acdc | ||
|
|
3d7e93b6c2 | ||
|
|
6e9f3cb8b9 | ||
|
|
0c8efbac7a | ||
|
|
ccc60b1240 | ||
|
|
818ffc01e7 | ||
|
|
f37b30749e | ||
|
|
edc6f9cf07 | ||
|
|
064edfbbe4 | ||
|
|
b62f4e9525 | ||
|
|
57f5617fe8 | ||
|
|
6c386e6ed2 | ||
|
|
93890769e1 | ||
|
|
4039c0123b | ||
|
|
27f2d457ea | ||
|
|
c6b508b3ed | ||
|
|
67b6855370 | ||
|
|
4480618748 | ||
|
|
9fff4dbb5d | ||
|
|
6a68cf9d7c | ||
|
|
e34a81ec6c | ||
|
|
00b5a44c31 | ||
|
|
f75577d41d | ||
|
|
3838f01adf | ||
|
|
a932c309b3 | ||
|
|
9af776e3c6 | ||
|
|
39634b6caf | ||
|
|
eb3884180e | ||
|
|
d5c7d74767 | ||
|
|
d08656021c | ||
|
|
9beb7219ea | ||
|
|
deecf136bc | ||
|
|
b849de2dab | ||
|
|
b4950343ec | ||
| 6cf3e97985 | |||
| 579df71848 | |||
| bd8669f629 | |||
| 97053798ff | |||
| b1ca068e3f | |||
| 05c1ac1dc0 | |||
| b381d78362 | |||
| ed9a6fa118 | |||
| ecb3a66d58 | |||
| ffe1e11d11 | |||
| ff80ec3b51 | |||
| be7143be20 | |||
| a788b64e44 | |||
| 6cc6a4c69c | |||
| 30113613e0 | |||
| 40196333ad | |||
| f3c9dd2d9c | |||
| f258632fb5 | |||
|
|
7749e8263f | ||
| e19c89f441 | |||
| 3119a01e3f | |||
| fba2e413cf | |||
| 456925264b | |||
| 6ed0ead8a7 | |||
| 6cca2d1bed | |||
| 440f8ce3ac | |||
| ee11daa0be | |||
| b33ad22740 | |||
| 3f8828457b | |||
| 793acecf2e | |||
| eebcb25274 | |||
| 9ed560cca6 | |||
| a86b734e0d | |||
| 5319cabdae | |||
| ee6f83eb7e | |||
| 63c7fc3f70 | |||
| 8f55baa13e | |||
| 6845a3740f | |||
| 02a36f7bf7 | |||
|
|
79c69e3d43 | ||
|
|
7d79c9a82a | ||
|
|
e216a6366f | ||
|
|
9054e36288 | ||
|
|
1a67932351 | ||
|
|
7a6adda997 | ||
|
|
1da53c448d | ||
|
|
53dc169774 | ||
|
|
b0be48501b | ||
|
|
98c99e7550 | ||
|
|
ed41f3a228 | ||
|
|
a2eafa8bc0 | ||
|
|
2be5f9eac0 | ||
| 251934d3a9 | |||
| 964c95b572 | |||
| e7ed5b0d7a | |||
| a6ad4f8f3b | |||
| 0b05424690 | |||
| e45f8fa81b | |||
| 3035aaa7e6 | |||
| 9143cd5f47 | |||
| d92a3f3a8e | |||
| 65cb778a18 | |||
| 563fcc23bc | |||
| 2e68ac1522 | |||
| 62463576cf | |||
| ac14e7a22e | |||
| f2aad1c957 | |||
| ee3a71a5d0 | |||
|
|
a361915281 | ||
| e5e6006212 | |||
| fa808accd4 | |||
| df3fc6c973 | |||
| da071b795d | |||
| 48069e2234 | |||
| 2e65f0d186 | |||
| 7da14bd3b8 | |||
| de4f67832b | |||
| d21452a8bf | |||
| e8afa4e529 | |||
| 98e8cd4592 | |||
| 974c44a041 | |||
| 325b8f6f20 | |||
| 13e4a0b640 | |||
| f4c51dbafe | |||
| 81779f1fae | |||
| 7113ef393d | |||
| 3fd5f60d7f | |||
| acfd5c90b9 | |||
| 6195af3e7b | |||
| 4eebee34c4 | |||
| 8a72ac52db | |||
| 7779d03654 | |||
| 1f538d2976 | |||
| 4b5687b8ab | |||
| d4da75e6ab | |||
| 8094465579 | |||
| 6305e2a718 | |||
| bbaa4bbdbe | |||
| 4cd703097c | |||
| 1ef61d8c33 | |||
| 54d755b12d | |||
| 010cd58460 | |||
| 9295c91a7d | |||
| 86913bf75f | |||
| 90c80fbd8e | |||
| 4912b39831 | |||
| 17ac2ab4da | |||
| 845a00079b | |||
| 82681e8303 | |||
| d74d83b2ec | |||
| 2abf540515 | |||
| 78847c2415 | |||
| 540db8e15a | |||
| 020c10d961 | |||
| 0f00221cd9 | |||
| bbf8f3c348 | |||
| 0fddd2134b | |||
| b35159b5b7 | |||
| 490c6d42ec | |||
| bc5958b60d | |||
| cc6f33ab7e | |||
| 62dc8bc324 | |||
| ea980fe909 | |||
| ab78bce769 | |||
| af47ae42c1 | |||
| 661aa22e41 | |||
|
|
876b87b72a | ||
|
|
32cd17bfa2 | ||
|
|
393752d77b | ||
|
|
2b460b64f2 | ||
|
|
59075798ea | ||
|
|
034c05f512 | ||
|
|
01b5e59250 | ||
|
|
7d32e77860 | ||
|
|
f11149ebe2 | ||
|
|
ba1e190cdb | ||
|
|
1c9fbc79aa | ||
|
|
218a040f8b | ||
|
|
cc8dd4edb4 | ||
|
|
3982258500 | ||
|
|
2be422e7da | ||
|
|
5abe50430d | ||
|
|
97b8ed19a6 | ||
|
|
9d38357c4e | ||
|
|
64fa1d89c3 | ||
|
|
e31397b42f | ||
|
|
9f61ffb153 | ||
|
|
b2f7f86d6a | ||
|
|
4799176c14 | ||
|
|
0a89439c80 | ||
|
|
9c202aa47a | ||
|
|
6b0f942598 | ||
|
|
8db9060a40 | ||
|
|
f94221918f | ||
|
|
cc47f4b488 | ||
|
|
5c027e2649 | ||
|
|
4156f28b93 | ||
|
|
c271d4e74b | ||
|
|
97464ef1d2 | ||
|
|
518b5d91dd | ||
|
|
e25c7d7824 | ||
|
|
29fa9a5a21 | ||
|
|
083df1aae2 | ||
|
|
3a73c98e19 | ||
|
|
80cb2d9ba4 | ||
|
|
317b4e9b5c | ||
|
|
24143f5d20 | ||
|
|
209e1ae8cf | ||
|
|
37836ae992 |
1116 changed files with 82338 additions and 15406 deletions
|
|
@ -149,4 +149,4 @@ These credits can be spent in the 2009Scape Reward Shop. It's important to be cl
|
|||
|
||||
Testers are not the only people who can gain credits - other ways of earning credits can be found on [the 2009Scape website](https://2009scape.org/site/game_guide/credits.html).
|
||||
|
||||
Please be patient! The Credit system is not fully complete yet, so it will take a long time for credits to be awarded.
|
||||
Please be patient! The Credit system is not fully complete yet, so it will take a long time for credits to be awarded.
|
||||
1
Server/.gitignore
vendored
1
Server/.gitignore
vendored
|
|
@ -2,6 +2,7 @@ bin/**
|
|||
out/**
|
||||
data/logs/**
|
||||
data/profile/**
|
||||
data/playerstats/**
|
||||
.idea/**
|
||||
/bin
|
||||
.DS_Store**
|
||||
|
|
|
|||
152
Server/README.md
152
Server/README.md
|
|
@ -1,152 +0,0 @@
|
|||
[![AGPL-3.0 License][license-shield]][license-url]
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://gitlab.com/2009scape/2009scape">
|
||||
<img src="https://i.imgur.com/RsfVfkB.png" alt="Logo" width="300" height="67">
|
||||
</a>
|
||||
<h3 align="center">An open source MMORPG emulation server</h3>
|
||||
|
||||
<h1 align="center"><a href="https://2009scape.org/"><strong>Play the live server »</strong></a></h1>
|
||||
<p align="center">
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://2009scape.org/">Community Hosted Server</a>
|
||||
·
|
||||
<a href="https://discord.gg/43YPGND">Discord Invite</a>
|
||||
· <a href="https://gitlab.com/2009scape/2009scape/-/issues">Report Bug</a>
|
||||
</p>
|
||||
<h3>NOTE: Bug reports and support are only accepted by/offered to players of our live hosted server. We will not provide support to those running their own copies.</h3>
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Live Server Information](#live-server-information)
|
||||
* [History of this Codebase](#history-of-this-codebase)
|
||||
* [Our Core Values](#our-core-values)
|
||||
* [Contributing](#contributing)
|
||||
* [Setup for Content Developers](#content-developers-setting-up-the-project)
|
||||
* [GitLab Setup](#gitlab-setup)
|
||||
* [Prerequisites](#prerequisites)
|
||||
* [Project Setup](#project-setup)
|
||||
* [Running the project](#running-the-project)
|
||||
* [License](#license)
|
||||
* [Contact](#contact)
|
||||
|
||||
|
||||
## Live Server Information
|
||||
|
||||
Did you know that the 2009Scape Development Team hosts the main branch of this repo that you can connect to and play? Come join a growing community of people that love to grind out skills, quest, and hangout together. A download link for the launcher can be found [here](https://2009scape.org). Connecting to the live server is also one of the easiest ways to identify bugs/typos/missing features. Identifying these issues help developers, whether already on the project, or are even brand new to the project, fix bugs and issues in an expedited rate.
|
||||
|
||||
## History of this Codebase
|
||||
|
||||
The 2009Scape you see today has gone through a magnitude of changes. Originally starting its life as Arios498, this server saw a lot of people playing it daily, unfortunately, it was for profit and closed source. It was later upgraded to Arios530, targeting the build 530 of runescape with content in and around January 1st, 2009. Development came to a halt when a developer of the closed source project released the source code. The original developers of this server went on to create Kratos 530 back in 2015.
|
||||
|
||||
This project was started out of love for the 530 revision. A small group of developers spent thousands of hours improving on the existing source that was left to the curb. Over the past year, this project has seen many developers coming and going, fixing bugs that they find either through their own server, or bugs that they find in the live game that is currently hosted. We do not accept donations of any kind. The smiles and wonderful compliments are more than enough to keep us going! Content and bugfixes are always number one on our list, and we try our best to answer any questions that you may have, provided you have read through this readme and frequently asked questions on the discord.
|
||||
|
||||
## Our Core Values
|
||||
|
||||
In the current climate of RuneScape Private Servers in general, we believe it's important to wear our core values on our sleeves and defend them with everything we have! Below are what we hold as our core, most important values:
|
||||
|
||||
* **We do NOT believe in profiting off an RSPS.** To many of us here at the 2009Scape team, what we care about most is preserving the wonderful work of the Gower brothers in the most true-to-spirit manner possible. We do NOT do this to make a profit, and in fact **we outright refuse donations.** This is a labor of love and passion for everyone involved, a love for real RS2! This is perhaps the single most central value we have. If you want to "donate" to us, do so with your time and your dedication. That is what we desire most.
|
||||
|
||||
|
||||
* **Authenticity is central to the work**. As a remake, one of the most important things to us is being true to the Gower spirit. What the Gowers brought to us in our childhood is what we are driven to preserve for the remainder of the world.
|
||||
|
||||
|
||||
* **Open Source is crucial to the project**. We believe open source remakes to be crucial to preserving what we loved in our childhood, and we believe for-profit and/or closed-source servers are destined to flounder out and fail.
|
||||
|
||||
|
||||
* **Be welcoming**. One of our most important goals is to provide a community of friendly and caring people that get along and love to enjoy the game with eachother. For this reason, we do tend to be very strict when it comes to toxicity. We care about quality a whole lot more than quantity!
|
||||
|
||||
## Contributing
|
||||
|
||||
**Note: All merge requests MUST be made using the defaut MR template. Merge requests that do not use this template will not be accepted.**
|
||||
|
||||
**Note: All new contributions MUST be made in Kotlin unless you are updating or fixing a bug in legacy code. More information on Kotlin can be found [here](https://kotlinlang.org/).**
|
||||
|
||||
There are many ways everyone can contribute! From the most seasoned programmers to those who do not have the most remote clue how code works! Below are some things that can always use some love from the community.
|
||||
|
||||
* **Content Testers**: I'm putting this one up top because of its importance. We, the contributors and developers, aren't perfect. Sometimes, we make mistakes. This is where you come in - If you want a sneak peek at upcoming content, have a knack for breaking things, or just want to contribute to the project without making code changes, you can become a tester! If you are interested in becoming a tester, reach out in the testing channel of the discord. [Why become a tester?](#why-become-a-tester)
|
||||
|
||||
|
||||
* **Wiki Editors**: Did you know we have a wiki? Well it's always in need of people to fill it out and stay on top of it. Editing the wiki is one of the easiest ways you can contribute to 2009Scape! If you're an active player and have the will, there's so much you could be helping out with over at the wiki. [Click here to go to the wiki](https://cdn.2009scape.org/wiki/doku.php?id=start).
|
||||
|
||||
|
||||
* **JSON editors**: We could always use more JSON editors! Please note that JSON editing **must** be done using the [Thanos Tool](https://gitlab.com/2009scape/tools/rs09-thanos-tool/-/jobs/5153567519/artifacts/file/build/libs/zaros.jar). **This does not run on modern Java** and requires **Java 11** to run (using the usual 'java -jar zaros.jar').
|
||||
|
||||
|
||||
* **Authenticity Auditors**: As a remake, authenticity is central to our core values! We could always use someone to go through the game and create large lists of simple tasks that can be done to bring us closer to the authentic 2009 game! The preferred way to do this is one-area-at-a-time. If you want to see an example of some audits we've done in the past, take a look [here](https://gitlab.com/2009scape/2009scape/-/issues/46).
|
||||
|
||||
|
||||
* **Code Contributors**: As a remake, we have massive amounts of content that need to be implemented or corrected. If you know how to program or are willing to learn, this is where you could be extremely helpful! We need everything from quests, to dialogue, to mini-games, to skills that still need to be corrected or implemented. This is perhaps one of the most valuable ways someone could help out the project! If you are interested in developing content, reach out in the development channel of the Discord.
|
||||
|
||||
## Content Developers: Setting Up the Project.
|
||||
### GitLab Setup
|
||||
**Note: This allows you to commit changes to the main repo (with approval)! Also, always stay up to date with the most recent updates by pulling into your copy when 2009Scape updates!**
|
||||
|
||||
1. Create a GitLab account if you haven't done so already.
|
||||
|
||||
2. Follow our Git Basics guide [over on the wiki.](https://gitlab.com/2009scape/2009scape/-/wikis/git-basics)
|
||||
|
||||
**If at anytime you have an issue with GitLab please refer to the [GitLab help center](https://gitlab.com/help).**
|
||||
|
||||
### Prerequisites
|
||||
|
||||
These are mandatory. If you don't install **all** of these programs **in order** prior to
|
||||
the project's setup, things won't work. At all.
|
||||
|
||||
*For Windows users* - Turn developer mode on first in Windows developer settings.
|
||||
|
||||
* [JDK 11](https://adoptium.net) or the Java SE Development Kit Version 11
|
||||
* [IntelliJ IDEA Community](https://www.jetbrains.com/idea/download/)
|
||||
|
||||
### SSH setup
|
||||
|
||||
1. [Set up a key if you don't have one (ed25519)](https://docs.gitlab.com/ee/user/ssh.html#generate-an-ssh-key-pair)
|
||||
2. [Add your public key to your gitlab account](https://docs.gitlab.com/ee/user/ssh.html#add-an-ssh-key-to-your-gitlab-account)
|
||||
3. [Verify you can connect to git@gitlab.com](https://docs.gitlab.com/ee/user/ssh.html#verify-that-you-can-connect)
|
||||
|
||||
### Project Setup
|
||||
|
||||
1. If you haven't already, make sure to follow our [Git Basics](https://gitlab.com/2009scape/2009scape/-/wikis/git-basics) guide.
|
||||
2. Run `git lfs pull` in the 2009scape folder you cloned as part of that guide. This only has to be done once, ever.
|
||||
3. Follow our [IntelliJ IDEA Setup Guide](https://gitlab.com/2009scape/2009scape/-/wikis/Setup-for-IntelliJ-IDEA-IDE)
|
||||
|
||||
### Running the project
|
||||
|
||||
1. If you followed the IntelliJ setup guide, which you probably should have, just use the provided run configuration.
|
||||
***Note: If you choose not to use the provided run scripts or IntelliJ, you *must* run `mvn clean` before it will build correctly.***
|
||||
|
||||
#### Linux / OSX
|
||||
|
||||
Start the game server with the included run script. Use `./run -h` for more info.
|
||||
|
||||
#### Windows
|
||||
|
||||
Start the game server with `run-server.bat`
|
||||
|
||||
### License
|
||||
|
||||
We use the AGPL 3.0 license, which can be found [here](https://www.gnu.org/licenses/agpl-3.0.en.html). Please be sure to read and understand the license. Failure to follow the guidelines outlined in the license will result in legal action. If you know or hear of anyone breaking this license, please send a report, with proof, to Red Bracket#8151, ceikry#2724, or woahscam#8535 on discord or email woahscam@hotmail.com. **We WILL NOT change the license to fit your needs.**
|
||||
|
||||
### Contact
|
||||
|
||||
**Reminder: There is no official support for setting up your own server. Do not ping/dm developers, or ask in support channels about setting up your server. Support for the live server and 2009Scape single-player is available on the [2009Scape forums](https://forum.2009scape.org/).**
|
||||
|
||||
|
||||
[license-shield]: https://img.shields.io/badge/license-AGPL--3.0-informational
|
||||
[license-url]: https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
### Why become a tester?
|
||||
|
||||
Before content hits Live, it has to be tested. We can, but do not want to do this alone, and would love the help! But don't worry, there is something in it for you. Credits! Keep in mind that credits will only be awarded to people who thoroughly test the content and provide detailed reports on them. Like votes or HoF you must claim them in the #claim-to-fame channel on discord or matrix.
|
||||
|
||||
* If you test smaller things like bug fixes there is a 2 credit reward.
|
||||
* If you test full quests or minigames you will be rewarded 5 credits.
|
||||
* If you find a bug in the content you are testing that hasn't already been found you will earn an extra credit.
|
||||
|
||||
These credits can be spent in the 2009Scape Reward Shop. It's important to be clear that credits are gained by contributions to the project. We cannot and will not accept donations (of any kind), especially not in exchange for in-game credits or perks.
|
||||
|
||||
Testers are not the only people who can gain credits - other ways of earning credits can be found on [the 2009Scape website](https://2009scape.org/site/game_guide/credits.html).
|
||||
|
||||
Please be patient! The Credit system is not fully complete yet, so it will take a long time for credits to be awarded.
|
||||
|
|
@ -25,4 +25,7 @@
|
|||
<ObjectAction mode="add" id="21301" x="2662" y="3162" z="0" direction="e"/>
|
||||
<ObjectAction mode="add" id="4176" x="2629" y="3661" z="2" type="4" direction="e"/>
|
||||
|
||||
<ObjectAction mode="add" id="2489" x="2839" y="3282" z="0" direction="w"/>
|
||||
<ObjectAction mode="add" id="36695" x="2894" y="3510" z="0" direction="w"/>
|
||||
|
||||
</parsing>
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@
|
|||
"Always check announcments",
|
||||
"We thrivin",
|
||||
"Ship @name",
|
||||
"Dont forget to vote 2009Scape!",
|
||||
"Dont forget to vote 2009scape!",
|
||||
"Kermit is too legit 2 quit",
|
||||
"Out here on the range we are having fun",
|
||||
"I am hank steel",
|
||||
|
|
@ -367,33 +367,16 @@
|
|||
"May Guthix bring you balance.",
|
||||
"May Guthix bring you balance.",
|
||||
"May Guthix bring you balance.",
|
||||
"Thy death was not in vain, for it brought some balance to the world. May Guthix bring you rest.",
|
||||
"May you walk the path, and never fall, for Guthix walks beside thee on thy journey. May Guthix bring you peace.",
|
||||
"All things must end, as all begin; Only Guthix knows the role thou must play. May Guthix bring you balance.",
|
||||
"In life, in death, in joy, in sorrow: May thine experience show thee balance. May Guthix bring you balance.",
|
||||
"Thou must do as thou must, no matter what. Thine actions bring balance to this world. May Guthix bring you balance.",
|
||||
"The river flows, the sun ignites, May you stand with Guthix in thy fights. May Guthix bring you balance.",
|
||||
"A journey of a single step, May take thee over a thousand miles. May Guthix bring you balance.",
|
||||
"Zamorak give me strength!",
|
||||
"Zamorak give me strength!",
|
||||
"Zamorak give me strength!",
|
||||
"May your bloodthirst never be sated, and may all your battles be glorious. Zamorak bring you strength.",
|
||||
"There is no opinion that cannot be proven true...by crushing those who choose to disagree with it. Zamorak give me strength!",
|
||||
"Battles are not lost and won; They simply remove the weak from the equation. Zamorak give me strength!",
|
||||
"Those who fight, then run away, shame Zamorak with their cowardice. Zamorak give me strength!",
|
||||
"Battle is by those who choose to disagree with it. Zamorak give me strength!",
|
||||
"Strike fast, strike hard, strike true: The strength of Zamorak will be with you. Zamorak give me strength!",
|
||||
"The weak deserve to die, so the strong may flourish. This is the creed of Zamorak.",
|
||||
"This is Saradomin's wisdom.",
|
||||
"This is Saradomin's wisdom.",
|
||||
"This is Saradomin's wisdom.",
|
||||
"Go in peace in the name of Saradomin; may his glory shine upon you like the sun.",
|
||||
"Thy cause was false, thy skills did lack; See you in Lumbridge when you get back.",
|
||||
"Protect your self, protect your friends. Mine is the glory that never ends. This is Saradomin's wisdom.",
|
||||
"The darkness in life may be avoided, by the light of wisdom shining. This is Saradomin's wisdom.",
|
||||
"Show love to your friends, and mercy to your enemies, and know that the wisdom of Saradomin will follow. This is Saradomin's wisdom.",
|
||||
"A fight begun, when the cause is just, will prevail over all others. This is Saradomin's wisdom.",
|
||||
"The currency of goodness is honour; It retains its value through scarcity. This is Saradomin's wisdom.",
|
||||
"For Camelot!",
|
||||
"Firmly grasp it!",
|
||||
"My legs!",
|
||||
|
|
@ -496,21 +479,525 @@
|
|||
"Shlisshalpshlaap",
|
||||
"Somebody call for an exterminator?",
|
||||
"Decisive action. Should work.",
|
||||
"R E A D Y T O R A I S E S O M E H E L L",
|
||||
"Darkness overpowering.",
|
||||
"Got any questions about propane? Or propane accessories?",
|
||||
"When someone asks me if I am a god, I say Y E S!!!",
|
||||
"You run out of Marines?",
|
||||
"Goliath Online",
|
||||
"I'm escaping to the one place that hasn't been corrupted by Capitalism. Lunar Isle!",
|
||||
"Selling wildy protection, 100k gp",
|
||||
"Can't we get you on Mastermind, @name? Next contestant - @name from Lumbridge. Special subject - the bleedin' obvious.",
|
||||
"Oh, you're German! I'm sorry, I thought there was something wrong with you.",
|
||||
"Can't we get you on Mastermind, @name?",
|
||||
"Listen, don't mention the war! I mentioned it once, but I think I got away with it all right.",
|
||||
"Cunnilingus and psychiatry brought us to this.",
|
||||
"Oh, poor baby. What do you want, a Brimstail's Sampler?",
|
||||
"There's an old TzHarrian saying, you fuck up once, you lose two teeth.",
|
||||
"The lineup consisted simply of six hydrocoptic marzelvanes so fitted to the ambifacient lunar waneshaft that sidefumbling was prevented."
|
||||
"Ah, the Wilderness... where dreams of riches meet a swift demise.",
|
||||
"Who needs a quest guide? I've got the whole wiki memorized.",
|
||||
"Buying GF 10k coins. Must have at least 70 Agility.",
|
||||
"I swear, the goblins in Goblin Village have it out for me.",
|
||||
"Why do wizards always hang out in towers? Is it a zoning thing?",
|
||||
"I'm training my Construction skill. My house is gonna be lit!",
|
||||
"The GE is like the stock market, but with dragon bones.",
|
||||
"Why do we need a cabbage patch in Draynor? Seriously.",
|
||||
"I've been mining rune essence for hours. My pickaxe hates me.",
|
||||
"@name hit 99 Cooking. Time to open a gourmet restaurant in Varrock.",
|
||||
"I'm convinced the @name is actually a time-traveling wizard.",
|
||||
"Anyone up for a Castle Wars match? I need that decorative armor.",
|
||||
"Accidentally clicked Attack on a guard. Now I'm a wanted criminal.",
|
||||
"Why do we even have a Duel Arena? It's just a fancy boxing ring.",
|
||||
"I've got a stack of burnt lobsters. Anyone want to buy them?",
|
||||
"Greetings, @name! Looking for a quest?",
|
||||
"Just got a rare drop! The RNG gods are smiling upon me!",
|
||||
"Anyone need help with a boss fight? I've got my dragon dagger ready.",
|
||||
"Buying feathers! Will pay top price!",
|
||||
"The Lumbridge cows are my favorite training spot.",
|
||||
"Who needs a teleport? I've got my magic runes stocked.",
|
||||
"@name hit 99 Woodcutting. Time to chop some yews!",
|
||||
"Anyone seen the Wise Old Man lately? I owe him a visit.",
|
||||
"Selling lobsters! Freshly caught from Catherby.",
|
||||
"Swear, the Wilderness is scarier than my nightmares.",
|
||||
"Looking for a clan to join. Any takers?",
|
||||
"I'm an ironman, so no trading for me!",
|
||||
"Anyone up for a Castle Wars match?",
|
||||
"The Grand Exchange prices are crashing. Panic sell!",
|
||||
"Who else remembers the Falador Massacre?",
|
||||
"I'm saving up for a party hat. Wish me luck!",
|
||||
"Barrows runs are my addiction. Those crypts are spooky.",
|
||||
"I'm convinced the Wise Old Man is secretly Zamorak.",
|
||||
"I'm a completionist, so I'm grinding out all the achievements.",
|
||||
"The music in this game is surprisingly epic.",
|
||||
"Tried to trade with a tree... It didn't go well.",
|
||||
"My bank is like a black hole. Items disappear forever.",
|
||||
"I'm convinced the Wise Old Man is just a confused tourist.",
|
||||
"My character's fashion sense? Let's just say it's 'unique.'",
|
||||
"Challenged a cow to a dance-off. It won.",
|
||||
"Why does the Lumbridge Guide always look so lost?",
|
||||
"I'm training Agility, but my real-life agility is zero.",
|
||||
"Tried to fish in the desert. Sandfish are elusive.",
|
||||
"The Grand Exchange is like a chaotic stock market.",
|
||||
"I'm a master at clicking 'Continue' during quests.",
|
||||
"I'm convinced the chickens are plotting world domination.",
|
||||
"I'm a woodcutter, but I've never seen a talking tree.",
|
||||
"I'm a vegetarian, except when it comes to killing dragons.",
|
||||
"Why do wizards wear pointy hats? Is it a fashion statement?",
|
||||
"Challenged a guard to a staring contest. He won.",
|
||||
"I'm collecting cabbage. It's a noble pursuit.",
|
||||
"Accidentally set my cat on fire. It's now a firecat.",
|
||||
"I'm convinced the Wise Old Man is secretly a time traveler.",
|
||||
"I'm a quest completionist, but I still can't find my keys.",
|
||||
"I'm convinced the ducks are spying on us.",
|
||||
"I'm a pro at avoiding the Lumbridge swamp. Too many frogs.",
|
||||
"Hey, can someone lend me 10k? I promise I'll pay it back... eventually.",
|
||||
"Why do I always find the one square where the random event spawns?",
|
||||
"I'm training Prayer by burying bones. It's like a spiritual workout.",
|
||||
"The Wise Old Man's fashion sense is questionable.",
|
||||
"I'm convinced the ducks are secretly plotting world domination.",
|
||||
"Why do wizards wear pointy hats? Is it a dress code?",
|
||||
"I'm collecting cabbage. It's a noble pursuit, really.",
|
||||
"I'm a vegetarian, except when it comes to killing dragons.",
|
||||
"Why does the Lumbridge Guide always look so lost?",
|
||||
"Training Agility, but my real-life agility is zero.",
|
||||
"I'm convinced the Wise Old Man is secretly a time traveler.",
|
||||
"Tried to mine air. It's an untapped resource.",
|
||||
"I'm a quest completionist, but I still can't find my keys.",
|
||||
"Challenged a guard to a staring contest. He won.",
|
||||
"I'm saving up for a party hat. Priorities, you know?",
|
||||
"Why do goblins drop coins? Do they moonlight as accountants?",
|
||||
"I'm convinced the chickens are plotting something.",
|
||||
"Clicked 'Attack' on a chicken. Now I'm a poultry murderer.",
|
||||
"My character's fashion sense? Let's just say it's 'unique.'",
|
||||
"Do you know where I can find the entrance to the Taverley Dungeon?",
|
||||
"Hey, anyone here familiar with the Barrows? I need some tips.",
|
||||
"Is there a bank nearby? My inventory is overflowing with loot",
|
||||
"I'm clueless about clue scrolls",
|
||||
"Where's the best spot to catch sharks? I'm aiming for 99 Fishing.",
|
||||
"Is there a shortcut to the Karamja Volcano?",
|
||||
"Can someone explain the mechanics of the Jad fight in the Fight Caves?",
|
||||
"I'm stuck on the Elemental Workshop quest. Any hints?",
|
||||
"Where can I find a loom to spin flax into bowstrings?",
|
||||
"What's the best gear setup for killing dragons? I want that visage drop!",
|
||||
"I'm trying to unlock the fairy rings",
|
||||
"How do I recharge my amulet of glory?",
|
||||
"Why do goblins drop coins?",
|
||||
"The Grand Exchange is like the stock market",
|
||||
"My real-life agility is more like a lumbering tortoise.",
|
||||
"The Wise Old Man's fashion sense is like Woahs",
|
||||
"I challenged a cow to a dance off, surprisingly smooth mooves.",
|
||||
"Why does the Lumbridge Guide always look lost?",
|
||||
"I'm convinced the ducks in Lumbridge are plotting world domination!",
|
||||
"I accidentally ate my prayer potion I'm blessed with heartburn",
|
||||
"I'm a vegetarian, except when it comes to slaying dragons.",
|
||||
"Why do wizards wear pointy hats? Is it a magical dress code?",
|
||||
"I'm a quest completionist, but I still can't find my keys in real life.",
|
||||
"I challenged a guard to a staring contest. He won.",
|
||||
"I'm saving up for a party hat. Priorities, ya know?",
|
||||
"What's the deal with the Wilderness?",
|
||||
"I'm convinced the chickens are secretly plotting world domination!",
|
||||
"Accidentally clicked 'Attack' on a guard. Now I'm on a watchlist.",
|
||||
"My character's fashion sense? Let's just say it's 'unique'",
|
||||
"Lobsters heal my soul",
|
||||
"Trimmed armor or bust!",
|
||||
"Wilderness: Where friendships go to die",
|
||||
"Buying gf 10k",
|
||||
"Dancing for coins at Lumbridge",
|
||||
"Wearing full rune like a boss",
|
||||
"Teleporting to Camelot for quests",
|
||||
"Fishing for hours at Catherby",
|
||||
"PKing with a rune 2h",
|
||||
"World 1 Falador Park parties",
|
||||
"Staking my bank at the Duel Arena",
|
||||
"Dying to Elvarg's fiery breath sums up my life",
|
||||
"Got the Quest cape finally on my main!",
|
||||
"Wearing a party hat with pride",
|
||||
"Castle Wars: Red vs Blue",
|
||||
"Trading in Varrock Square",
|
||||
"Barrows runs for that sweet loot",
|
||||
"Spending hours in Pest Control is life",
|
||||
"Killing cows for leather armor is a good start",
|
||||
"Farming herbs in Ardougne can be good money",
|
||||
"Clan chat drama LOL",
|
||||
"Mining rune essence endlessly",
|
||||
"Agility courses: A love-hate relationship",
|
||||
"Dueling for honor.... and GP",
|
||||
"Buying runes from Aubury is decent money",
|
||||
"Chasing the Easter Bunny like a scam",
|
||||
"Wearing a skillcape with pride",
|
||||
"Fletching yew longbows for profit",
|
||||
"Going to implings in Puro-Puro",
|
||||
"Castle Wars barricade wars",
|
||||
"Dropping party hats at drop parties like pennies",
|
||||
"Killing lesser demons in Karamja is part of my holy conquest",
|
||||
"@name lures noobs into the Wilderness",
|
||||
"Farming ranarrs for cash",
|
||||
"Getting lost in the Underground Pass",
|
||||
"Selling coal at the Grand Exchange",
|
||||
"Fighting the Kalphite Queen",
|
||||
"Picking flax in Seers' Village",
|
||||
"Begging for free stuff in Lumbridge",
|
||||
"Smithing rune platebodies for profit",
|
||||
"Logging out in Lumbridge Castle",
|
||||
"Hey @name, how do I get to the Grand Exchange?",
|
||||
"Veteran here! @name, what's your favorite quest?",
|
||||
"@name, how do I make money fast?",
|
||||
"Hey @name, what's the best combat style for bossing?",
|
||||
"@name, always carry an emergency teleport!",
|
||||
"New player here! @name, what's the Wilderness like?",
|
||||
"Hey @name, how do I join a clan?",
|
||||
"@name, prioritize Prayer levels!",
|
||||
"@name, what's the best way to train Agility?",
|
||||
"Hey @name, what's your favorite minigame?",
|
||||
"@name, never trust a PKer in Lumbridge!",
|
||||
"@name, how do I get a fire cape?",
|
||||
"Hey @name, what's the fastest way to level up Magic?",
|
||||
"@name, try the Barrows tunnels!",
|
||||
"@name, what's the deal with Pest Control?",
|
||||
"Hey @name, how do I unlock the Fairy Rings?",
|
||||
"@name, remember the old random events?",
|
||||
"@name, should I train Strength or Attack first?",
|
||||
"Hey @name, what's your favorite skillcape?",
|
||||
"@name, can't do the Fight Caves!",
|
||||
"@name, how do I get a pet?",
|
||||
"Hey @name, what's the best food for boss fights?",
|
||||
"@name, Castle Wars or Clan Wars?",
|
||||
"@name, what's a clue scroll?",
|
||||
"Hey @name, how do I defeat Jad?",
|
||||
"@name, use Protect from Melee at KBD!",
|
||||
"@name, should I train Ranged or Magic?",
|
||||
"Hey @name, what's the best way to level up Crafting?",
|
||||
"@name, don't forget your anti-dragon shield!",
|
||||
"@name, what's the Stronghold of Security?",
|
||||
"Hey @name, how do I access the Legends' Guild?",
|
||||
"@name, remember the old PvP worlds?",
|
||||
"@name, how do I get a dragon defender?",
|
||||
"Hey @name, what's the best way to level up Herblore?",
|
||||
"@name, always carry a charged amulet of glory!",
|
||||
"@name, should I train Fishing or Cooking?",
|
||||
"Hey @name, how do I defeat the Chaos Elemental?",
|
||||
"@name, try the TzHaar Fight Pit!",
|
||||
"@name, what's the best way to level up Smithing?",
|
||||
"Hey @name, what's your favorite Slayer master?",
|
||||
"@name, use the Ardougne cloak teleports!",
|
||||
"@name, what's the Legends' Quest about?",
|
||||
"Hey @name, how do I unlock the Ancient Magicks?",
|
||||
"@name, remember the old Pest Control boats?",
|
||||
"@name, what's the best way to level up Construction?",
|
||||
"Hey @name, what's the fastest way to level up Prayer?",
|
||||
"@name, the old Duel Arena stakes!",
|
||||
"@name, what's the Warriors' Guild?",
|
||||
"Hey @name, how do I defeat the Kalphite Queen?",
|
||||
"@name, use the fairy ring code BIP!",
|
||||
"@name, should I train Attack or Defense first?",
|
||||
"Hey @name, what's the best way to level up Thieving?",
|
||||
"@name, don't forget your charged glory amulet!",
|
||||
"@name, what's the Legends' Cape?",
|
||||
"Hey @name, how do I access the Heroes' Guild?",
|
||||
"@name, remember the old Pest Control void gear?",
|
||||
"@name, how do I get a firemaking skillcape?",
|
||||
"Buying gf 10k",
|
||||
"Trimming armor for free!",
|
||||
"Wanna join my clan? We're called The Mighty Cabbages'!",
|
||||
"I'll meet you at the Falador Party Room!",
|
||||
"Dancing for coins in Varrock Square!",
|
||||
"Remember when the Wilderness was dangerous?",
|
||||
"I got a rune scimitar drop from Lesser Demons!",
|
||||
"Lumbridge Swamp is haunted!",
|
||||
"Anyone up for Castle Wars?",
|
||||
"I miss the old random events!",
|
||||
"World 2 is the trading hub!",
|
||||
"I'm going to train my Agility at the Gnome Stronghold!",
|
||||
"I just got 99 Cooking!",
|
||||
"Fishing lobsters at Catherby is life!",
|
||||
"The Legends' Guild is so exclusive!",
|
||||
"Who needs a quest guide? I'll figure it out!",
|
||||
"I'm mining rune essence for hours!",
|
||||
"Barrows armor looks sick!",
|
||||
"I'm stuck in the Underground Pass!",
|
||||
"The Stronghold of Security taught me about account security!",
|
||||
"I'm going to farm herbs in Ardougne!",
|
||||
"I'm getting my fire cape!",
|
||||
"I love the music in RuneScape!",
|
||||
"I'm alching my maple longbows!",
|
||||
"I'm doing the Recipe for Disaster subquests!",
|
||||
"I'm going to train my combat stats at the Rock Crabs!",
|
||||
"I'm going for the Quest Cape!",
|
||||
"I'm going to mine pure essence!",
|
||||
"I'm hunting chinchompas in the Feldip Hills!",
|
||||
"I'm going to train my Woodcutting at Seers' Village!",
|
||||
"I'm going to fish sharks at the Fishing Guild!",
|
||||
"I'm going to train my Thieving at Ardougne Knights!",
|
||||
"I'm going to hunt implings in Puro-Puro!",
|
||||
"I'm going to train my Hunter at the Falconry!",
|
||||
"I'm smithing rune platebodies!",
|
||||
"I'm going to train my Farming at the Tree Gnome Stronghold!",
|
||||
"I'm going to hunt red chinchompas in the Wilderness!",
|
||||
"I'm doing the Underground Pass quest!",
|
||||
"I'm going to fish monkfish in Piscatoris!",
|
||||
"Meet me in Varrock, @name, for an epic trade",
|
||||
"@name, join my clan; we'll conquer the Wilderness together!",
|
||||
"Beware the dragons, @name, they're fiercer than you think",
|
||||
"Crafting runes with @name, the best mage in Gielinor",
|
||||
"Fishing lobsters with @name, the sea's no match for us",
|
||||
"@name, your swordsmanship at Duel Arena is unmatched!",
|
||||
"Questing through dark caves, @name always leads the way",
|
||||
"Share your wisdom, @name, how'd you master those spells?",
|
||||
"Legends speak of @name bravery at the God Wars",
|
||||
"Need more arrows, @name? I've got plenty to spare",
|
||||
"Cooking's a breeze when @name around, no burnt lobsters!",
|
||||
"Mining together, @name and I strike gold every time",
|
||||
"@name, let's barter; your herbs for my potions?",
|
||||
"Training agility with @name, leaping like graceful gazelles",
|
||||
"Heard @name got the best magic beans in town",
|
||||
"Fletching bows with @name, aiming for perfection",
|
||||
"Smithing with @name, our anvils never cool down",
|
||||
"Adventuring with @name, every quest is a thrill",
|
||||
"Battling demons, @name courage inspires us all",
|
||||
"Slaying dragons, @name the hero we need",
|
||||
"Gathering at Falador, @name party room is legendary",
|
||||
"Hunting chinchompas, @name traps are always full",
|
||||
"Farming's fun with @name, our crops never fail",
|
||||
"Brewing potions, @name mixtures are magical",
|
||||
"Casting spells with @name, we're invincible",
|
||||
"Building fires, @name flames warm the coldest nights",
|
||||
"Sailing to Pest Control, @name our fearless captain",
|
||||
"Trading runes, @name deals are the fairest",
|
||||
"Exploring dungeons, @name the light in the darkness",
|
||||
"Charging orbs with @name, our energy knows no bounds",
|
||||
"Dancing in Draynor, @name moves are enchanting",
|
||||
"Playing Gnomeball, @name the star player",
|
||||
"Harvesting willows, @name axe swings true",
|
||||
"Enchanting jewelry, @name touch turns copper to gold",
|
||||
"Summoning familiars, @name spirit wolf leads the pack",
|
||||
"Thieving from stalls, @name hands are lightning-fast",
|
||||
"Crafting runes, @name essence never runs dry",
|
||||
"Fishing at Catherby, @name catch feeds us all",
|
||||
"Cooking feasts, @name dishes delight the gods",
|
||||
"Mining runite, @name pickaxe strikes rich veins",
|
||||
"Bartering at Grand Exchange, @name a trading master",
|
||||
"Training prayer, @name piety moves mountains",
|
||||
"Fighting revenants, @name valor shines bright",
|
||||
"Building homes, @name construction is flawless",
|
||||
"Hunting imps, @name net is always full",
|
||||
"Brewing ale, @name tavern is the town's favorite",
|
||||
"Casting high alchemy, @name turns junk into treasure",
|
||||
"Sailing to Karamja, @name adventures are legendary",
|
||||
"Forging alliances, @name charisma unites clans",
|
||||
"Defeating bosses, @name name echoes in legends",
|
||||
"Are you mewing @name???",
|
||||
"Check out that gyatt @name",
|
||||
"Bruhhhhh @name got that rizz",
|
||||
"@name rizzing up the bots",
|
||||
"Ironman? More like copperboy LOL",
|
||||
"What that gyatt do @name",
|
||||
"He's got the zoomies!",
|
||||
"@name likes pickles and dipped in mayo",
|
||||
"Lmaaooooooo",
|
||||
"Bruh she said she loved me...",
|
||||
"I caught @name rizzing a mewing teacher",
|
||||
"What that mouth do bb",
|
||||
"Ayo tf he say",
|
||||
"Ayo",
|
||||
"Ayo @name a freak lowkey",
|
||||
"Ayo tf",
|
||||
"@name catch me outside howbout that",
|
||||
"Wasssssuuuuppppppp",
|
||||
"Knock knock @name",
|
||||
"Oh boy howdy do i have a surprise for you",
|
||||
"Noooooo",
|
||||
"What do you mean I haven't done anything wtf",
|
||||
"Redrocket redrocket!!!",
|
||||
"I made 20,000 crochet sock puppets for ceikry",
|
||||
"Come on @name",
|
||||
"Are we rading tonight @name?",
|
||||
"Why would he say that",
|
||||
"Penguins are technically reptiles",
|
||||
"Brb smell something burning",
|
||||
"Need pest control partner, you handle the portals, i will afk",
|
||||
"Bruhhhh the skibiddi rizz in my gyatt makes my mewing sesh rough",
|
||||
"@name jajajajaja",
|
||||
"Wait, I can't raid tonight @name",
|
||||
"Brb, pizza's here. Hope they ask why I'm a grown man dressed like an elf",
|
||||
"Sorry, gotta go AFK. My dog just ate my gaming headset.",
|
||||
"Brb, my grandma just fell down the stairs",
|
||||
"Hold on, the baby's crying, aka @name",
|
||||
"Oops, spilled my drink",
|
||||
"Guys, I need to log off, my plants are staging a revolt for not watering them",
|
||||
"AFK a sec, my neighbor's llama is in my backyard again",
|
||||
"My pizza rolls are ready",
|
||||
"Lost track of time, i'm late for my own wedding",
|
||||
"Sorry, can't hear you over the sound of my laundry",
|
||||
"Turn HDR off in windows @name",
|
||||
"Www. no one cares .com",
|
||||
"Hey @name www dot stfu dot com",
|
||||
"Like pitching a tent in a pair of britches",
|
||||
"Mad as a bag of ferrets",
|
||||
"I dont think beavers built the hoover dam",
|
||||
"How do beavers get the concrete for dams?",
|
||||
"@name show me the way",
|
||||
"@name onwards brutha",
|
||||
"@name eats fried rat tails",
|
||||
"@name is a rat",
|
||||
"Why are there so many people farming right now",
|
||||
"@name fuck the police",
|
||||
"@name says the like pickles on their hotdogs",
|
||||
"Fuck the guards, free woah in varrock prison",
|
||||
"Ayo fuck u mean",
|
||||
"Woop woop thats da sound of the beast",
|
||||
"How are you the way that you are",
|
||||
"She sells seashells by the sea shore",
|
||||
"@name certified rat",
|
||||
"@name buys skimmed milk",
|
||||
"Got milk?",
|
||||
"Are you JSON because i want you to get array from me",
|
||||
"@name likes string manipulation",
|
||||
"@name sells legos",
|
||||
"JUST DO IT",
|
||||
"Why are there so many motherfucking options",
|
||||
"Just hit the fucking auto hide thing",
|
||||
"Just play",
|
||||
"Hell no this shit is fuzzy as balls",
|
||||
"@name is fuzzy as balls",
|
||||
"Turn your brightness up @name",
|
||||
"On my pc it runs perfectly",
|
||||
"I know why mine seems a little jumpy",
|
||||
"Stream the window not the monitor",
|
||||
"Discords a bitch",
|
||||
"Why are there so many handsome people at the ge like @name",
|
||||
"I'll make you squeel of fortune",
|
||||
"You will get it in due time @name",
|
||||
"I was one turn away",
|
||||
"It do be pipe time @name",
|
||||
"Sometimes i like to cover myself in vaseline and pretend i'm a slug",
|
||||
"Woah is a greased pig",
|
||||
"Sometimes i dig holes in my backyard and pretend i'm a carrot",
|
||||
"It's pipe time @name",
|
||||
"If i am not pipe timing i am programming",
|
||||
"Yes i have thigh high socks, no you cannot have them",
|
||||
"I scream when i wear my programming socks",
|
||||
"Anyone wanna buy @name's bathwater?",
|
||||
"Anyone wanna buy my used socks?",
|
||||
"@name be getting bags",
|
||||
"What the fuck is this",
|
||||
"Hi i noticed you haven't taken a break in hours @name",
|
||||
"I really am seething rn",
|
||||
"I am so fucking tilted",
|
||||
"Go back to your fucking frogs",
|
||||
"Life is simple as frog farmer",
|
||||
"A q p",
|
||||
"Oooooh that's a first",
|
||||
"Been a minute @name",
|
||||
"Hey @name",
|
||||
"Oh shit it's @name",
|
||||
"Hey @name wyd today?",
|
||||
"Ayo @name",
|
||||
"Wyd @name",
|
||||
"Wbu @name?",
|
||||
"Good fuck em, that's what they get",
|
||||
"Deathknight lookin rat ass mf @name",
|
||||
"@name sucks slugs",
|
||||
"Brb gotta take a shit",
|
||||
"@name will brb went to take a shit",
|
||||
"Tell me when he is coming",
|
||||
"This guy is being incredibly based",
|
||||
"@name is based af",
|
||||
"Taking l's all day today @name",
|
||||
"That sucks massive dongus",
|
||||
"Ah i was about to type that",
|
||||
"Where is stormwind?",
|
||||
"How do i buy gold",
|
||||
"@name sells gold",
|
||||
"@name is a gold digger",
|
||||
"Ayo @name wanna buy some frog legs?",
|
||||
"Brb fucking burnt my pizza rolls",
|
||||
"I swear @name if you need roll again",
|
||||
"@name you are a hunter you don't need plate armor",
|
||||
"Dragonriding is satisfying",
|
||||
"There's an old TzHarrian saying, you fuck up once, you lose two teeth",
|
||||
"FUCK",
|
||||
"@name i am ready when you are",
|
||||
"Anyone selling logs?",
|
||||
"That is hilarious @name",
|
||||
"Alright @name",
|
||||
"I need to go get my quest cape",
|
||||
"500 barrows runs dry",
|
||||
"Back to back to back barrows items, easy game",
|
||||
"@name did you know them?",
|
||||
"@name sucks eggs",
|
||||
"@name eats snails",
|
||||
"Who is that?",
|
||||
"I've gotta go in 20 minutes",
|
||||
"Bonk",
|
||||
"Gtg in 30 minutes",
|
||||
"They left 50 minutes ago",
|
||||
"I think it's just gonna be us",
|
||||
"Who is that?",
|
||||
"Stop following me",
|
||||
"@name stop following me",
|
||||
"I think @name is watching me",
|
||||
"@name wouldn't let me get a hit in at clan wars",
|
||||
"Clan wars and chill?",
|
||||
"Quick mewing sesh",
|
||||
"Don't you stickbug me",
|
||||
"Get stick bugged",
|
||||
"Wtf why are you a dragon",
|
||||
"Fun fact, woah eats eggs whole like a snake",
|
||||
"Ceikys there's a rare over there",
|
||||
"Where is goldshire?",
|
||||
"How long have you played @name?",
|
||||
"Wanna quest?",
|
||||
"TROGDORRRRRR",
|
||||
"Fuck this shit i'm out",
|
||||
"Wait till you get your first 99",
|
||||
"How is that even possible",
|
||||
"That's the max",
|
||||
"@name is trying to max",
|
||||
"Complesionist cape?",
|
||||
"How can you increase your run speed?",
|
||||
"@name where is barrows?",
|
||||
"@name where are rune rocks?",
|
||||
"@name where is yanille?",
|
||||
"@name how long have you played for?",
|
||||
"Yes these quotes were hand typed",
|
||||
"Kermit was here",
|
||||
"World of Warcraft died after Wrath",
|
||||
"Ceikry needs to add talent trees",
|
||||
"How do you get to the wilderness?",
|
||||
"Anyone tryna lure @name?",
|
||||
"@name tried to lure me",
|
||||
"@name bots all the time",
|
||||
"Anyone want chicken tendies",
|
||||
"Brb foods ready",
|
||||
"Brb",
|
||||
"Gotta go get food",
|
||||
"Anyone else from northern alaska?",
|
||||
"Fishing 4 gp",
|
||||
"Looking for gf",
|
||||
"Anyone wanna be my discord kitten?",
|
||||
"Selling discord kittens",
|
||||
"@name is a discord kitten",
|
||||
"Add me on discord",
|
||||
"Are you in the 09discord",
|
||||
"Where are you going @name?",
|
||||
"Idk what i am going to cook today",
|
||||
"What should i eat tonight",
|
||||
"He is in the cave",
|
||||
"Don't forget to save game before logging out",
|
||||
"American horror story died after season 1",
|
||||
"Prequels are better than the sequels",
|
||||
"Disney star wars is the best star wars",
|
||||
"Halo 5 sucked",
|
||||
"Selling xbox live gold and 1600 microsoft points for 50k gp",
|
||||
"Buying gf 25gp and a bucket",
|
||||
"@name i heard evilwaffles bots",
|
||||
"@name hopefully ceikry doesn't find out about evilwaffles",
|
||||
"Honk honk",
|
||||
"Where is the road to mordor?",
|
||||
"Golem lookin ass bitch",
|
||||
"@name rat looking mf",
|
||||
"@name uses sand paper to wipe",
|
||||
"@name said Woah is cute",
|
||||
"You need 25 of 40 to do that",
|
||||
"Over 1000 unique lines of dialogue",
|
||||
"What should i get to eat",
|
||||
"Ge be poppin today",
|
||||
"Where all the woahs at",
|
||||
"Ayo woahscam got that gyatt",
|
||||
"That is one i haven't seen before"
|
||||
],
|
||||
"halloween": [
|
||||
"Trick or treat!!!",
|
||||
|
|
@ -521,9 +1008,9 @@
|
|||
"Costume party at my P O H!! Follow me!",
|
||||
"Trick, then!",
|
||||
"Brrrainssssssss...",
|
||||
"'Cause this is thriller, thriller night, and no one's gonna save you from the beast about to strike!",
|
||||
"This is Hallowe'en, this is Hallowe'en, pumpkins scream in the dead of night!",
|
||||
"This is Hallowe'en, everybody make a scene, Trick or treat till the neighbors gonna die of fright!",
|
||||
"'Cause this is thriller, thriller night!",
|
||||
"This is Hallowe'en, this is Hallowe'en!",
|
||||
"This is Hallowe'en, everybody make a scene!",
|
||||
"In this town we call home, everyone hail to the pumpkin song!",
|
||||
"Watch out for Skeleton Jack!",
|
||||
"The headless-what-man? Horse? Never heard of those.",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
BIN
Server/data/cache/main_file_cache.dat2
(Stored with Git LFS)
vendored
BIN
Server/data/cache/main_file_cache.dat2
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Server/data/cache/main_file_cache.idx255
(Stored with Git LFS)
vendored
BIN
Server/data/cache/main_file_cache.idx255
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Server/data/cache/main_file_cache.idx5
(Stored with Git LFS)
vendored
BIN
Server/data/cache/main_file_cache.idx5
(Stored with Git LFS)
vendored
Binary file not shown.
|
|
@ -301,7 +301,7 @@
|
|||
},
|
||||
{
|
||||
"id": "2025",
|
||||
"replaceId": "1534",
|
||||
"replaceId": "2026",
|
||||
"fence": "false",
|
||||
"metal": "false"
|
||||
},
|
||||
|
|
@ -312,7 +312,7 @@
|
|||
"metal": "false"
|
||||
},
|
||||
{
|
||||
"id": "2036",
|
||||
"id": "1530",
|
||||
"replaceId": "1531",
|
||||
"fence": "false",
|
||||
"metal": "false"
|
||||
|
|
@ -925,7 +925,7 @@
|
|||
},
|
||||
{
|
||||
"id": "3747",
|
||||
"replaceId": "1534",
|
||||
"replaceId": "3748",
|
||||
"fence": "false",
|
||||
"metal": "false"
|
||||
},
|
||||
|
|
@ -943,7 +943,7 @@
|
|||
},
|
||||
{
|
||||
"id": "4148",
|
||||
"replaceId": "4248",
|
||||
"replaceId": "4246",
|
||||
"fence": "false",
|
||||
"metal": "false"
|
||||
},
|
||||
|
|
@ -1759,7 +1759,7 @@
|
|||
},
|
||||
{
|
||||
"id": "14245",
|
||||
"replaceId": "14248",
|
||||
"replaceId": "14246",
|
||||
"fence": "true",
|
||||
"metal": "false"
|
||||
},
|
||||
|
|
@ -1984,16 +1984,14 @@
|
|||
"replaceId": "28518",
|
||||
"fence": "false",
|
||||
"metal": "true",
|
||||
"autowalk": "true",
|
||||
"questRequirement": "Icthlarin's Little Helper"
|
||||
"autowalk": "true"
|
||||
},
|
||||
{
|
||||
"id": "28514",
|
||||
"replaceId": "28518",
|
||||
"fence": "false",
|
||||
"metal": "true",
|
||||
"autowalk": "true",
|
||||
"questRequirement": "Icthlarin's Little Helper"
|
||||
"autowalk": "true"
|
||||
},
|
||||
{
|
||||
"id": "21065",
|
||||
|
|
|
|||
|
|
@ -3262,7 +3262,7 @@
|
|||
}
|
||||
],
|
||||
"charm": [],
|
||||
"ids": "73,74,75,419,420,421,422,423,424,1826,2714,2863,2866,2869,2878,3622,4392,4393,4394,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5375,5376,5377,5378,5379,5380,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,6099,6100,6131",
|
||||
"ids": "73,74,75,419,420,421,422,423,424,2714,2863,2866,2869,2878,3622,4392,4393,4394,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5375,5376,5377,5378,5379,5380,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,6099,6100,6131",
|
||||
"description": "",
|
||||
"main": [
|
||||
{
|
||||
|
|
@ -5858,205 +5858,165 @@
|
|||
"charm": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "12158",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "12159",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "12160",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "12163",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5600.0",
|
||||
"weight": "1000.0",
|
||||
"id": "0",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"tertiary": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "4986.5",
|
||||
"id": "0",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "12.5",
|
||||
"id": "10976",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "10977",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"ids": "114",
|
||||
"description": "",
|
||||
"main": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "50.0",
|
||||
"id": "7844",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5.0",
|
||||
"id": "10977",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5.0",
|
||||
"id": "10976",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5323",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5298",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5281",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5301",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5280",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5294",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5297",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5104",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5100",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5106",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "12176",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5293",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5296",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5311",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5105",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "5292",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5.0",
|
||||
"id": "5295",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5.0",
|
||||
"id": "5303",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5.0",
|
||||
"id": "5302",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5.0",
|
||||
"id": "5321",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5.0",
|
||||
"id": "5299",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5.0",
|
||||
"id": "31",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "0",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "3.0",
|
||||
"weight": "39.0625",
|
||||
"id": "6666",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "3.0",
|
||||
"weight": "78.125",
|
||||
"id": "6665",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "13.0",
|
||||
"id": "14422",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "13.0",
|
||||
"id": "14430",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "156.25",
|
||||
"id": "345",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "156.25",
|
||||
"id": "327",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "156.25",
|
||||
"id": "371",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "2",
|
||||
"weight": "156.25",
|
||||
"id": "372",
|
||||
"maxAmount": "5"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "156.25",
|
||||
"id": "359",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "156.25",
|
||||
"id": "360",
|
||||
"maxAmount": "3"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "39.0625",
|
||||
"id": "383",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "39.0625",
|
||||
"id": "349",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "39.0625",
|
||||
"id": "331",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "5",
|
||||
"weight": "156.25",
|
||||
"id": "313",
|
||||
"maxAmount": "15"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "156.25",
|
||||
"id": "1511",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "39.0625",
|
||||
"id": "1383",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "78.125",
|
||||
"id": "407",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "4",
|
||||
"weight": "78.125",
|
||||
"id": "402",
|
||||
"maxAmount": "8"
|
||||
},
|
||||
{
|
||||
"minAmount": "5",
|
||||
"weight": "4.0",
|
||||
"id": "555",
|
||||
"maxAmount": "18"
|
||||
},
|
||||
{
|
||||
"minAmount": "3",
|
||||
"weight": "78.125",
|
||||
"id": "6664",
|
||||
"maxAmount": "6"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "39.0625",
|
||||
"id": "401",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "39.0625",
|
||||
"id": "6667",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -11426,47 +11386,11 @@
|
|||
"weight": "100.0",
|
||||
"id": "526",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "1506",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "6065",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "6067",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "6069",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "6068",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "100.0",
|
||||
"id": "6070",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"charm": [],
|
||||
"ids": "347,348,357,369,370,371,372,717,718,719,2349,2350,2351,2373,2374,2784,3216",
|
||||
"description": "",
|
||||
"ids": "370,357,348,369,347,371",
|
||||
"description": "all combat mourners",
|
||||
"main": []
|
||||
},
|
||||
{
|
||||
|
|
@ -18161,7 +18085,7 @@
|
|||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"ids": "1183,1184,1201,2359,2360,2361,2362,7438,7439,7440,7441",
|
||||
"ids": "1183,1184,1201,2359,2360,2361,2362,2373,7438,7439,7440,7441",
|
||||
"description": "",
|
||||
"main": [
|
||||
{
|
||||
|
|
@ -20143,6 +20067,208 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "526",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"charm": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "55.0",
|
||||
"id": "0",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "13.0",
|
||||
"id": "12158",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "6.0",
|
||||
"id": "12159",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "12160",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "12163",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"ids": "1338",
|
||||
"description": "Chaos Tunnels / Lighthouse Dagannoths",
|
||||
"main": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5.0",
|
||||
"id": "1237",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "5.0",
|
||||
"id": "1239",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "1243",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "15",
|
||||
"weight": "4.0",
|
||||
"id": "555",
|
||||
"maxAmount": "15"
|
||||
},
|
||||
{
|
||||
"minAmount": "15",
|
||||
"weight": "2.0",
|
||||
"id": "886",
|
||||
"maxAmount": "15"
|
||||
},
|
||||
{
|
||||
"minAmount": "3",
|
||||
"weight": "1.0",
|
||||
"id": "828",
|
||||
"maxAmount": "3"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "18.0",
|
||||
"id": "14428",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "12.0",
|
||||
"id": "301",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "3",
|
||||
"weight": "4.0",
|
||||
"id": "345",
|
||||
"maxAmount": "3"
|
||||
},
|
||||
{
|
||||
"minAmount": "5",
|
||||
"weight": "4.0",
|
||||
"id": "327",
|
||||
"maxAmount": "5"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "3.0",
|
||||
"id": "311",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "15",
|
||||
"weight": "2.0",
|
||||
"id": "314",
|
||||
"maxAmount": "15"
|
||||
},
|
||||
{
|
||||
"minAmount": "50",
|
||||
"weight": "2.0",
|
||||
"id": "313",
|
||||
"maxAmount": "50"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "2.0",
|
||||
"id": "377",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "2.0",
|
||||
"id": "359",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "10",
|
||||
"weight": "2.0",
|
||||
"id": "402",
|
||||
"maxAmount": "10"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "413",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "2",
|
||||
"weight": "1.0",
|
||||
"id": "411",
|
||||
"maxAmount": "2"
|
||||
},
|
||||
{
|
||||
"minAmount": "56",
|
||||
"weight": "29.0",
|
||||
"id": "995",
|
||||
"maxAmount": "56"
|
||||
},
|
||||
{
|
||||
"minAmount": "25",
|
||||
"weight": "9.0",
|
||||
"id": "995",
|
||||
"maxAmount": "25"
|
||||
},
|
||||
{
|
||||
"minAmount": "44",
|
||||
"weight": "8.0",
|
||||
"id": "995",
|
||||
"maxAmount": "44"
|
||||
},
|
||||
{
|
||||
"minAmount": "41",
|
||||
"weight": "6.0",
|
||||
"id": "995",
|
||||
"maxAmount": "41"
|
||||
},
|
||||
{
|
||||
"minAmount": "12",
|
||||
"weight": "2.0",
|
||||
"id": "45",
|
||||
"maxAmount": "12"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "405",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "5733",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "14426",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": [
|
||||
{
|
||||
|
|
@ -28343,60 +28469,10 @@
|
|||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"charm": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "85.8093",
|
||||
"id": "0",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "10.9113",
|
||||
"id": "12158",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.6775",
|
||||
"id": "12159",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.6019",
|
||||
"id": "12160",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "0.0",
|
||||
"id": "12163",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"ids": "2044,2045,2046,2047,2048,2049,2051,2052,2053,2054,2055",
|
||||
"charm": [],
|
||||
"ids": "2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057",
|
||||
"description": "",
|
||||
"main": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "1",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "124.0",
|
||||
"id": "0",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "3.0",
|
||||
"id": "7848",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
]
|
||||
"main": []
|
||||
},
|
||||
{
|
||||
"default": [
|
||||
|
|
@ -29330,6 +29406,18 @@
|
|||
"id": "1438",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "1456",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "1450",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
|
|
@ -29502,6 +29590,18 @@
|
|||
"id": "1438",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "1456",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "1450",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
|
|
@ -29674,6 +29774,18 @@
|
|||
"id": "1438",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "1456",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
"id": "1450",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "25.0",
|
||||
|
|
@ -39691,7 +39803,20 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"default": [],
|
||||
"default": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "532",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "9080",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"charm": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
|
|
@ -58663,6 +58788,26 @@
|
|||
"description": "Ram",
|
||||
"main": []
|
||||
},
|
||||
{
|
||||
"default": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "526",
|
||||
"maxAmount": "1"
|
||||
},
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "1583",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"charm": [],
|
||||
"ids": "6108",
|
||||
"description": "",
|
||||
"main": []
|
||||
},
|
||||
{
|
||||
"default": [],
|
||||
"charm": [],
|
||||
|
|
@ -58676,5 +58821,19 @@
|
|||
"maxAmount": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default": [
|
||||
{
|
||||
"minAmount": "1",
|
||||
"weight": "1.0",
|
||||
"id": "592",
|
||||
"maxAmount": "1"
|
||||
}
|
||||
],
|
||||
"charm": [],
|
||||
"ids": "8127",
|
||||
"description": "Dark energy core",
|
||||
"main": []
|
||||
}
|
||||
]
|
||||
|
|
@ -233,7 +233,7 @@
|
|||
},
|
||||
{
|
||||
"item_id": "946",
|
||||
"loc_data": "{1,2903,3148,0,80}-{1,3205,3212,0,80}-{1,3224,3202,0,80}-{1,3218,3416,1,90}-{1,2820,3450,0,90}-{1,3106,3956,0,60}-{1,2566,9526,0,30}-{1,3215,9625,0,80}-{1,3218,9887,0,33}-"
|
||||
"loc_data": "{1,2903,3148,0,80}-{1,3205,3212,0,80}-{1,3224,3202,0,80}-{1,3218,3416,1,90}-{1,2820,3450,0,90}-{1,3106,3956,0,60}-{1,2566,9526,0,30}-{1,3215,9625,0,80}-{1,3218,9887,0,33}-{1,2700,3407,0,100}-"
|
||||
},
|
||||
{
|
||||
"item_id": "952",
|
||||
|
|
@ -241,7 +241,7 @@
|
|||
},
|
||||
{
|
||||
"item_id": "954",
|
||||
"loc_data": "{1,2094,3152,0,150}-"
|
||||
"loc_data": "{1,2094,3152,0,150}-{1,2785,3279,0,150}-{1,2786,3287,0,150}-{1,2786,3286,0,150}-"
|
||||
},
|
||||
{
|
||||
"item_id": "960",
|
||||
|
|
@ -339,6 +339,14 @@
|
|||
"item_id": "1422",
|
||||
"loc_data": "{1,3320,3137,0,150}-"
|
||||
},
|
||||
{
|
||||
"item_id": "1467",
|
||||
"loc_data": "{1,2784,3289,0,0}-"
|
||||
},
|
||||
{
|
||||
"item_id": "1469",
|
||||
"loc_data": "{1,2766,3277,0,100}-{1,2766,3289,0,100}-"
|
||||
},
|
||||
{
|
||||
"item_id": "1510",
|
||||
"loc_data": "{1,2576,3334,0,100}-"
|
||||
|
|
@ -619,6 +627,10 @@
|
|||
"item_id": "4707",
|
||||
"loc_data": "{1,3571,3312,0,40}-"
|
||||
},
|
||||
{
|
||||
"item_id": "4838",
|
||||
"loc_data": "{1,2593,3103,1,40}-"
|
||||
},
|
||||
{
|
||||
"item_id": "5008",
|
||||
"loc_data": "{1,3230,9609,0,44}-"
|
||||
|
|
@ -627,6 +639,10 @@
|
|||
"item_id": "5523",
|
||||
"loc_data": "{1,2935,3282,1,90}-"
|
||||
},
|
||||
{
|
||||
"item_id": "5586",
|
||||
"loc_data": "{1,2473,4941,0,90}-"
|
||||
},
|
||||
{
|
||||
"item_id": "6291",
|
||||
"loc_data": "{1,2681,3111,0,30}-{1,2673,3112,0,30}-{1,2674,3094,0,30}-{1,2671,3089,0,30}-"
|
||||
|
|
|
|||
|
|
@ -95,6 +95,30 @@
|
|||
"walkable": "false",
|
||||
"tabIndex": "-1"
|
||||
},
|
||||
{
|
||||
"id": "68",
|
||||
"interfaceType": "4",
|
||||
"walkable": "false",
|
||||
"tabIndex": "-1"
|
||||
},
|
||||
{
|
||||
"id": "69",
|
||||
"interfaceType": "4",
|
||||
"walkable": "false",
|
||||
"tabIndex": "-1"
|
||||
},
|
||||
{
|
||||
"id": "70",
|
||||
"interfaceType": "4",
|
||||
"walkable": "false",
|
||||
"tabIndex": "-1"
|
||||
},
|
||||
{
|
||||
"id": "71",
|
||||
"interfaceType": "4",
|
||||
"walkable": "false",
|
||||
"tabIndex": "-1"
|
||||
},
|
||||
{
|
||||
"id": "74",
|
||||
"interfaceType": "4",
|
||||
|
|
@ -365,6 +389,30 @@
|
|||
"walkable": "false",
|
||||
"tabIndex": "-1"
|
||||
},
|
||||
{
|
||||
"id": "245",
|
||||
"interfaceType": "4",
|
||||
"walkable": "false",
|
||||
"tabIndex": "-1"
|
||||
},
|
||||
{
|
||||
"id": "246",
|
||||
"interfaceType": "4",
|
||||
"walkable": "false",
|
||||
"tabIndex": "-1"
|
||||
},
|
||||
{
|
||||
"id": "247",
|
||||
"interfaceType": "4",
|
||||
"walkable": "false",
|
||||
"tabIndex": "-1"
|
||||
},
|
||||
{
|
||||
"id": "248",
|
||||
"interfaceType": "4",
|
||||
"walkable": "false",
|
||||
"tabIndex": "-1"
|
||||
},
|
||||
{
|
||||
"id": "256",
|
||||
"interfaceType": "8",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -2079,6 +2079,18 @@
|
|||
"region": "12880",
|
||||
"id": "441"
|
||||
},
|
||||
{
|
||||
"region": "12888",
|
||||
"id": "445"
|
||||
},
|
||||
{
|
||||
"region": "12889",
|
||||
"id": "445"
|
||||
},
|
||||
{
|
||||
"region": "12890",
|
||||
"id": "445"
|
||||
},
|
||||
{
|
||||
"region": "12944",
|
||||
"id": "606"
|
||||
|
|
@ -2199,6 +2211,18 @@
|
|||
"region": "13142",
|
||||
"id": "459"
|
||||
},
|
||||
{
|
||||
"region": "13144",
|
||||
"id": "445"
|
||||
},
|
||||
{
|
||||
"region": "13145",
|
||||
"id": "445"
|
||||
},
|
||||
{
|
||||
"region": "13146",
|
||||
"id": "445"
|
||||
},
|
||||
{
|
||||
"region": "13199",
|
||||
"id": "388"
|
||||
|
|
@ -2271,6 +2295,18 @@
|
|||
"region": "13373",
|
||||
"id": "586"
|
||||
},
|
||||
{
|
||||
"region": "13400",
|
||||
"id": "445"
|
||||
},
|
||||
{
|
||||
"region": "13401",
|
||||
"id": "445"
|
||||
},
|
||||
{
|
||||
"region": "13402",
|
||||
"id": "445"
|
||||
},
|
||||
{
|
||||
"region": "13456",
|
||||
"id": "452"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -16324,7 +16324,7 @@
|
|||
"ids": "11629"
|
||||
},
|
||||
{
|
||||
"examine": "South to Falador :: West to Taverley :: East to Varrock.",
|
||||
"examine": "This tells you which way is which.",
|
||||
"ids": "11630,11631,11632,11633"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@
|
|||
"general_store": "true",
|
||||
"id": "25",
|
||||
"title": "Lumbridge General Store",
|
||||
"stock": "{1931,30,100}-{1935,30,100}-{1735,10,100}-{1925,10,100}-{1923,10,100}-{1887,10,100}-{590,10,100}-{1755,10,100}-{2347,10,100}-{550,10,100}-{9003,10,100}"
|
||||
"stock": "{1931,30,100}-{1935,30,100}-{1735,10,100}-{1925,10,100}-{1923,10,100}-{1887,10,100}-{590,10,100}-{1755,10,100}-{2347,10,100}-{550,10,100}-{9003,10,100}-{1939,1000,1}"
|
||||
},
|
||||
{
|
||||
"npcs": "4716",
|
||||
|
|
@ -564,7 +564,7 @@
|
|||
"general_store": "false",
|
||||
"id": "65",
|
||||
"title": "Dodgy Mikes Second-hand Clothing",
|
||||
"stock": "{7114,10,100}"
|
||||
"stock": "{7114,10,100}-{7122,10,100}-{7128,10,100}-{7134,10,100}-{7110,10,100}-{7126,10,100}-{7132,10,100}-{7138,10,100}-{7116,10,100}-{7124,10,100}-{7130,10,100}-{7112,10,100}-{7136,10,100}"
|
||||
},
|
||||
{
|
||||
"npcs": "2161",
|
||||
|
|
@ -1599,7 +1599,7 @@
|
|||
"general_store": "false",
|
||||
"id": "181",
|
||||
"title": "MoonClan Fine Clothes",
|
||||
"stock": "{9068,10,100}-{9069,10,100}-{9070,10,100}-{9071,10,100}-{9072,10,100}-{9073,10,100}-{9074,10,100}-{1733,50,100}-{1734,500,100}"
|
||||
"stock": "{9068,10,100}-{9069,10,100}-{9070,10,100}-{9071,10,100}-{9072,10,100}-{9073,10,100}-{9074,10,100}-{1733,50,100}-{1734,500,100}-{9084,10,100}-{9096,10,100}-{9097,10,100}-{9098,10,100}-{9099,10,100}-{9100,10,100}-{9101,10,100}-{9102,10,100}-{9104,10,100}"
|
||||
},
|
||||
{
|
||||
"npcs": "",
|
||||
|
|
@ -2177,5 +2177,23 @@
|
|||
"id": "255",
|
||||
"title": "Castle Wars Ticket Exchange",
|
||||
"stock": "{4068,1,100}-{4069,1,100}-{4070,1,100}-{4071,1,100}-{4072,1,100}-{4503,1,100}-{4504,1,100}-{4505,1,100}-{4506,1,100}-{4507,1,100}-{4508,1,100}-{4509,1,100}-{4510,1,100}-{4511,1,100}-{4512,1,100}-{4513,1,100}-{4514,1,100}-{4515,1,100}-{4516,1,100}"
|
||||
},
|
||||
{
|
||||
"npcs": "5111",
|
||||
"high_alch": "0",
|
||||
"currency": "995",
|
||||
"general_store": "false",
|
||||
"id": "256",
|
||||
"title": "Leon's Prototype Crossbow",
|
||||
"stock": "{10156,2,100}"
|
||||
},
|
||||
{
|
||||
"npcs": "2039",
|
||||
"high_alch": "0",
|
||||
"currency": "995",
|
||||
"general_store": "false",
|
||||
"id": "256",
|
||||
"title": "Uglug's Stuffsies",
|
||||
"stock": "{4844,100,10}-{10927,0,100}-{2862,100,100}-{1777,10,200}-{2876,0,500}-{2878,10,100}-{4850,0,100}-{946,5,100}-{4773,0,1000}-{4778,0,1000}-{4783,0,1000}-{4788,0,1500}-{4793,0,2000}-{4798,0,3000}-{4803,0,4000}-{4827,0,2000}"
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -2,6 +2,7 @@ package content.data
|
|||
|
||||
import content.global.skill.magic.TeleportMethod
|
||||
import content.global.skill.slayer.SlayerManager.Companion.getInstance
|
||||
import content.global.skill.slayer.SlayerUtils
|
||||
import core.ServerConstants
|
||||
import core.api.*
|
||||
import core.game.event.TeleportEvent
|
||||
|
|
@ -304,7 +305,7 @@ enum class EnchantedJewellery(
|
|||
return
|
||||
}
|
||||
sendNPCDialogue(player, slayerManager.master!!.npc, "You're currently " +
|
||||
"assigned to kill ${getSlayerTaskName(player).lowercase(Locale.getDefault())}'s; " +
|
||||
"assigned to kill ${SlayerUtils.pluralise(getSlayerTaskName(player))} " +
|
||||
"only ${getSlayerTaskKillsRemaining(player)} more to go.", core.game.dialogue.FacialExpression.FRIENDLY)
|
||||
// Slayer tracker UI
|
||||
setVarp(player, 2502, slayerManager.flags.taskFlags shr 4)
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ public enum GodBook {
|
|||
* @param page the page.
|
||||
*/
|
||||
public void insertPage(Player player, Item book, Item page) {
|
||||
if (!hasRequirement(player, "Horror from the Deep"))
|
||||
if (!hasRequirement(player, Quests.HORROR_FROM_THE_DEEP))
|
||||
return;
|
||||
if (hasPage(player, book, page)) {
|
||||
player.sendMessage("The book already has that page.");
|
||||
|
|
|
|||
158
Server/src/main/content/data/Quests.kt
Normal file
158
Server/src/main/content/data/Quests.kt
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
package content.data
|
||||
|
||||
enum class Quests(val questName: String) {
|
||||
MYTHS_OF_THE_WHITE_LANDS("Myths of the White Lands"),
|
||||
BLACK_KNIGHTS_FORTRESS("Black Knights' Fortress"),
|
||||
COOKS_ASSISTANT("Cook's Assistant"),
|
||||
DEMON_SLAYER("Demon Slayer"),
|
||||
DORICS_QUEST("Doric's Quest"),
|
||||
DRAGON_SLAYER("Dragon Slayer"),
|
||||
ERNEST_THE_CHICKEN("Ernest the Chicken"),
|
||||
GOBLIN_DIPLOMACY("Goblin Diplomacy"),
|
||||
IMP_CATCHER("Imp Catcher"),
|
||||
THE_KNIGHTS_SWORD("The Knight's Sword"),
|
||||
PIRATES_TREASURE("Pirate's Treasure"),
|
||||
PRINCE_ALI_RESCUE("Prince Ali Rescue"),
|
||||
THE_RESTLESS_GHOST("The Restless Ghost"),
|
||||
ROMEO_JULIET("Romeo & Juliet"),
|
||||
RUNE_MYSTERIES("Rune Mysteries"),
|
||||
SHEEP_SHEARER("Sheep Shearer"),
|
||||
SHIELD_OF_ARRAV("Shield of Arrav"),
|
||||
VAMPIRE_SLAYER("Vampire Slayer"),
|
||||
WITCHS_POTION("Witch's Potion"),
|
||||
ANIMAL_MAGNETISM("Animal Magnetism"),
|
||||
BETWEEN_A_ROCK("Between a Rock..."),
|
||||
BIG_CHOMPY_BIRD_HUNTING("Big Chompy Bird Hunting"),
|
||||
BIOHAZARD("Biohazard"),
|
||||
CABIN_FEVER("Cabin Fever"),
|
||||
CLOCK_TOWER("Clock Tower"),
|
||||
CONTACT("Contact!"),
|
||||
ZOGRE_FLESH_EATERS("Zogre Flesh Eaters"),
|
||||
CREATURE_OF_FENKENSTRAIN("Creature of Fenkenstrain"),
|
||||
DARKNESS_OF_HALLOWVALE("Darkness of Hallowvale"),
|
||||
DEATH_TO_THE_DORGESHUUN("Death to the Dorgeshuun"),
|
||||
DEATH_PLATEAU("Death Plateau"),
|
||||
DESERT_TREASURE("Desert Treasure"),
|
||||
DEVIOUS_MINDS("Devious Minds"),
|
||||
THE_DIG_SITE("The Dig Site"),
|
||||
DRUIDIC_RITUAL("Druidic Ritual"),
|
||||
DWARF_CANNON("Dwarf Cannon"),
|
||||
EADGARS_RUSE("Eadgar's Ruse"),
|
||||
EAGLES_PEAK("Eagles' Peak"),
|
||||
ELEMENTAL_WORKSHOP_I("Elemental Workshop I"),
|
||||
ELEMENTAL_WORKSHOP_II("Elemental Workshop II"),
|
||||
ENAKHRAS_LAMENT("Enakhra's Lament"),
|
||||
ENLIGHTENED_JOURNEY("Enlightened Journey"),
|
||||
THE_EYES_OF_GLOUPHRIE("The Eyes of Glouphrie"),
|
||||
FAIRYTALE_I_GROWING_PAINS("Fairytale I - Growing Pains"),
|
||||
FAIRYTALE_II_CURE_A_QUEEN("Fairytale II - Cure a Queen"),
|
||||
FAMILY_CREST("Family Crest"),
|
||||
THE_FEUD("The Feud"),
|
||||
FIGHT_ARENA("Fight Arena"),
|
||||
FISHING_CONTEST("Fishing Contest"),
|
||||
FORGETTABLE_TALE("Forgettable Tale..."),
|
||||
THE_FREMENNIK_TRIALS("The Fremennik Trials"),
|
||||
WATERFALL_QUEST("Waterfall Quest"),
|
||||
GARDEN_OF_TRANQUILITY("Garden of Tranquility"),
|
||||
GERTRUDES_CAT("Gertrude's Cat"),
|
||||
GHOSTS_AHOY("Ghosts Ahoy"),
|
||||
THE_GIANT_DWARF("The Giant Dwarf"),
|
||||
THE_GOLEM("The Golem"),
|
||||
THE_GRAND_TREE("The Grand Tree"),
|
||||
THE_HAND_IN_THE_SAND("The Hand in the Sand"),
|
||||
HAUNTED_MINE("Haunted Mine"),
|
||||
HAZEEL_CULT("Hazeel Cult"),
|
||||
HEROES_QUEST("Heroes' Quest"),
|
||||
HOLY_GRAIL("Holy Grail"),
|
||||
HORROR_FROM_THE_DEEP("Horror from the Deep"),
|
||||
ICTHLARINS_LITTLE_HELPER("Icthlarin's Little Helper"),
|
||||
IN_AID_OF_THE_MYREQUE("In Aid of the Myreque"),
|
||||
IN_SEARCH_OF_THE_MYREQUE("In Search of the Myreque"),
|
||||
JUNGLE_POTION("Jungle Potion"),
|
||||
LEGENDS_QUEST("Legend's Quest"),
|
||||
LOST_CITY("Lost City"),
|
||||
THE_LOST_TRIBE("The Lost Tribe"),
|
||||
LUNAR_DIPLOMACY("Lunar Diplomacy"),
|
||||
MAKING_HISTORY("Making History"),
|
||||
MERLINS_CRYSTAL("Merlin's Crystal"),
|
||||
MONKEY_MADNESS("Monkey Madness"),
|
||||
MONKS_FRIEND("Monk's Friend"),
|
||||
MOUNTAIN_DAUGHTER("Mountain Daughter"),
|
||||
MOURNINGS_END_PART_I("Mourning's End Part I"),
|
||||
MOURNINGS_END_PART_II("Mourning's End Part II"),
|
||||
MURDER_MYSTERY("Murder Mystery"),
|
||||
MY_ARMS_BIG_ADVENTURE("My Arm's Big Adventure"),
|
||||
NATURE_SPIRIT("Nature Spirit"),
|
||||
OBSERVATORY_QUEST("Observatory Quest"),
|
||||
ONE_SMALL_FAVOUR("One Small Favour"),
|
||||
PLAGUE_CITY("Plague City"),
|
||||
PRIEST_IN_PERIL("Priest in Peril"),
|
||||
RAG_AND_BONE_MAN("Rag and Bone Man"),
|
||||
RATCATCHERS("Ratcatchers"),
|
||||
RECIPE_FOR_DISASTER("Recipe for Disaster"),
|
||||
RECRUITMENT_DRIVE("Recruitment Drive"),
|
||||
REGICIDE("Regicide"),
|
||||
ROVING_ELVES("Roving Elves"),
|
||||
ROYAL_TROUBLE("Royal Trouble"),
|
||||
RUM_DEAL("Rum Deal"),
|
||||
SCORPION_CATCHER("Scorpion Catcher"),
|
||||
SEA_SLUG("Sea Slug"),
|
||||
THE_SLUG_MENACE("The Slug Menace"),
|
||||
SHADES_OF_MORTTON("Shades of Mort'ton"),
|
||||
SHADOW_OF_THE_STORM("Shadow of the Storm"),
|
||||
SHEEP_HERDER("Sheep Herder"),
|
||||
SHILO_VILLAGE("Shilo Village"),
|
||||
A_SOULS_BANE("A Soul's Bane"),
|
||||
SPIRITS_OF_THE_ELID("Spirits of the Elid"),
|
||||
SWAN_SONG("Swan Song"),
|
||||
TAI_BWO_WANNAI_TRIO("Tai Bwo Wannai Trio"),
|
||||
A_TAIL_OF_TWO_CATS("A Tail of Two Cats"),
|
||||
TEARS_OF_GUTHIX("Tears of Guthix"),
|
||||
TEMPLE_OF_IKOV("Temple of Ikov"),
|
||||
THRONE_OF_MISCELLANIA("Throne of Miscellania"),
|
||||
THE_TOURIST_TRAP("The Tourist Trap"),
|
||||
WITCHS_HOUSE("Witch's House"),
|
||||
TREE_GNOME_VILLAGE("Tree Gnome Village"),
|
||||
TRIBAL_TOTEM("Tribal Totem"),
|
||||
TROLL_ROMANCE("Troll Romance"),
|
||||
TROLL_STRONGHOLD("Troll Stronghold"),
|
||||
UNDERGROUND_PASS("Underground Pass"),
|
||||
WANTED("Wanted!"),
|
||||
WATCHTOWER("Watchtower"),
|
||||
COLD_WAR("Cold War"),
|
||||
THE_FREMENNIK_ISLES("The Fremennik Isles"),
|
||||
TOWER_OF_LIFE("Tower of Life"),
|
||||
THE_GREAT_BRAIN_ROBBERY("The Great Brain Robbery"),
|
||||
WHAT_LIES_BELOW("What Lies Below"),
|
||||
OLAFS_QUEST("Olaf's Quest"),
|
||||
ANOTHER_SLICE_OF_HAM("Another Slice of H.A.M"),
|
||||
DREAM_MENTOR("Dream Mentor"),
|
||||
GRIM_TALES("Grim Tales"),
|
||||
KINGS_RANSOM("King's Ransom"),
|
||||
THE_PATH_OF_GLOUPHRIE("The Path of Glouphrie"),
|
||||
BACK_TO_MY_ROOTS("Back to my Roots"),
|
||||
LAND_OF_THE_GOBLINS("Land of the Goblins"),
|
||||
DEALING_WITH_SCABARAS("Dealing with Scabaras"),
|
||||
WOLF_WHISTLE("Wolf Whistle"),
|
||||
AS_A_FIRST_RESORT("As a First Resort..."),
|
||||
CATAPULT_CONSTRUCTION("Catapult Construction"),
|
||||
KENNITHS_CONCERNS("Kennith's Concerns"),
|
||||
LEGACY_OF_SEERGAZE("Legacy of Seergaze"),
|
||||
PERILS_OF_ICE_MOUNTAIN("Perils of Ice Mountain"),
|
||||
TOKTZ_KET_DILL("TokTz-Ket-Dill"),
|
||||
SMOKING_KILLS("Smoking Kills"),
|
||||
ROCKING_OUT("Rocking Out"),
|
||||
SPIRIT_OF_SUMMER("Spirit of Summer"),
|
||||
MEETING_HISTORY("Meeting History"),
|
||||
ALL_FIRED_UP("All Fired Up"),
|
||||
SUMMERS_END("Summer's End"),
|
||||
DEFENDER_OF_VARROCK("Defender of Varrock"),
|
||||
SWEPT_AWAY("Swept Away"),
|
||||
WHILE_GUTHIX_SLEEPS("While Guthix Sleeps"),
|
||||
IN_PYRE_NEED("In Pyre Need"),
|
||||
TEST_QUEST("Test Quest");
|
||||
|
||||
override fun toString(): String {
|
||||
return questName
|
||||
}
|
||||
}
|
||||
|
|
@ -30,36 +30,36 @@ public enum Consumables {
|
|||
HERRING(new Food(new int[] {347}, new HealingEffect(5))),
|
||||
MACKEREL(new Food(new int[] {355}, new HealingEffect(6))),
|
||||
ROAST_BIRD_MEAT(new Food(new int[] {9980}, new HealingEffect(6))),
|
||||
THIN_SNAIL(new Food(new int[] {3369}, new HealingEffect(5))),
|
||||
THIN_SNAIL(new Food(new int[] {3369}, new RandomHealthEffect(5, 7))),
|
||||
TROUT(new Food(new int[] {333}, new HealingEffect(7))),
|
||||
SPIDER_ON_STICK(new Food(new int[] {6297, 6305}, new HealingEffect(7))),
|
||||
SPIDER_ON_STICK(new Food(new int[] {6297, 6305}, new RandomHealthEffect(7, 11))),
|
||||
SPIDER_ON_SHAFT(new Food(new int[] {6299}, new HealingEffect(7))),
|
||||
ROAST_RABBIT(new Food(new int[] {7223}, new HealingEffect(7))),
|
||||
LEAN_SNAIL(new Food(new int[] {3371}, new HealingEffect(8))),
|
||||
LEAN_SNAIL(new Food(new int[] {3371}, new RandomHealthEffect(6, 8))),
|
||||
COD(new Food(new int[] {339}, new HealingEffect(7))),
|
||||
PIKE(new Food(new int[] {351}, new HealingEffect(8))),
|
||||
ROAST_BEAST_MEAT(new Food(new int[] {9988}, new HealingEffect(8))),
|
||||
COOKED_CRAB_MEAT(new Food(new int[] {7521, 7523, 7524, 7525, 7526}, new HealingEffect(2))),
|
||||
FAT_SNAIL(new Food(new int[] {3373}, new HealingEffect(9))),
|
||||
FAT_SNAIL(new Food(new int[] {3373}, new RandomHealthEffect(7, 9))),
|
||||
SALMON(new Food(new int[] {329}, new HealingEffect(9))),
|
||||
SLIMY_EEL(new Food(new int[] {3381}, new HealingEffect(6))),
|
||||
SLIMY_EEL(new Food(new int[] {3381}, new RandomHealthEffect(6, 10))),
|
||||
TUNA(new Food(new int[] {361}, new HealingEffect(10))),
|
||||
COOKED_KARAMBWAN(new Food(new int[] {3144}, new HealingEffect(18)), true),
|
||||
COOKED_CHOMPY(new Food(new int[] {2878}, new HealingEffect(10))),
|
||||
RAINBOW_FISH(new Food(new int[] {10136}, new HealingEffect(11))),
|
||||
CAVE_EEL(new Food(new int[] {5003}, new HealingEffect(7))),
|
||||
CAVE_EEL(new Food(new int[] {5003}, new RandomHealthEffect(8, 12))),
|
||||
LOBSTER(new Food(new int[] {379}, new HealingEffect(12))),
|
||||
COOKED_JUBBLY(new Food(new int[] {7568}, new HealingEffect(15))),
|
||||
BASS(new Food(new int[] {365}, new HealingEffect(13))),
|
||||
SWORDFISH(new Food(new int[] {373}, new HealingEffect(14))),
|
||||
LAVA_EEL(new Food(new int[] {2149}, new HealingEffect(14))),
|
||||
LAVA_EEL(new Food(new int[] {2149}, new HealingEffect(11))),
|
||||
MONKFISH(new Food(new int[] {7946}, new HealingEffect(16))),
|
||||
SHARK(new Food(new int[] {385}, new HealingEffect(20))),
|
||||
SEA_TURTLE(new Food(new int[] {397}, new HealingEffect(21))),
|
||||
MANTA_RAY(new Food(new int[] {391}, new HealingEffect(22))),
|
||||
KARAMBWANJI(new Food(new int[] {3151}, new HealingEffect(3))),
|
||||
STUFFED_SNAKE(new Food(new int[] {7579}, new HealingEffect(20), "You eat the stuffed snake-it's quite a meal! It tastes like chicken.")),
|
||||
CRAYFISH(new Food(new int[] {13433}, new HealingEffect(2))),
|
||||
CRAYFISH(new Food(new int[] {13433}, new HealingEffect(1))),
|
||||
GIANT_FROG_LEGS(new Food(new int [] {4517}, new HealingEffect(6))),
|
||||
|
||||
/** Breads */
|
||||
|
|
@ -111,7 +111,7 @@ public enum Consumables {
|
|||
|
||||
/** Vegetables */
|
||||
POTATO(new Food(new int[] {1942}, new HealingEffect(1), "You eat the potato. Yuck!")),
|
||||
BAKED_POTATO(new Food(new int[] {6701}, new HealingEffect(2))),
|
||||
BAKED_POTATO(new Food(new int[] {6701}, new HealingEffect(4))),
|
||||
SPICY_SAUCE(new Food(new int[] {7072, 1923}, new HealingEffect(2))),
|
||||
CHILLI_CON_CARNE(new Food(new int[] {7062, 1923}, new HealingEffect(5))),
|
||||
SCRAMBLED_EGG(new Food(new int[] {7078, 1923}, new HealingEffect(5))),
|
||||
|
|
@ -128,8 +128,8 @@ public enum Consumables {
|
|||
MUSHROOM_POTATO(new Food(new int[] {7058}, new HealingEffect(20))),
|
||||
TUNA_AND_CORN(new Food(new int[] {7068, 1923}, new HealingEffect(13))),
|
||||
TUNA_POTATO(new Food(new int[] {7060}, new HealingEffect(22))),
|
||||
ONION(new Food(new int[] {1957}, new HealingEffect(2), "It's always sad to see a grown man/woman cry.")),
|
||||
CABBAGE(new Food(new int[] {1965}, new HealingEffect(2), "You eat the cabbage. Yuck!")),
|
||||
ONION(new Food(new int[] {1957}, new HealingEffect(1), "It's always sad to see a grown man/woman cry.")),
|
||||
CABBAGE(new Food(new int[] {1965}, new HealingEffect(1), "You eat the cabbage. Yuck!")),
|
||||
DRAYNOR_CABBAGE(new Food(new int[] {1967}, new DraynorCabbageEffect(), "You eat the cabbage.", "It seems to taste nicer than normal.")),
|
||||
EVIL_TURNIP(new Food(new int[] {12134, 12136, 12138}, new HealingEffect(6))),
|
||||
SPINACH_ROLL(new Food(new int[] {1969}, new HealingEffect(2))),
|
||||
|
|
@ -147,7 +147,7 @@ public enum Consumables {
|
|||
ORANGE(new Food(new int[] {2108}, new HealingEffect(2))),
|
||||
ORANGE_CHUNKS(new Food(new int[] {2110}, new HealingEffect(2))),
|
||||
ORANGE_SLICES(new Food(new int[] {2112}, new HealingEffect(2))),
|
||||
PAPAYA_FRUIT(new Food(new int[] {5972}, new HealingEffect(2))),
|
||||
PAPAYA_FRUIT(new Food(new int[] {5972}, new MultiEffect(new EnergyEffect(5), new HealingEffect(8)))),
|
||||
TENTI_PINEAPPLE(new FakeConsumable(1851, new String[] {"Try using a knife to slice it into pieces."})),
|
||||
PINEAPPLE(new FakeConsumable(2114, new String[] {"Try using a knife to slice it into pieces."})),
|
||||
PINEAPPLE_CHUNKS(new Food(new int[] {2116}, new HealingEffect(2))),
|
||||
|
|
@ -169,8 +169,8 @@ public enum Consumables {
|
|||
STRANGE_FRUIT(new Food(new int[] {464}, new MultiEffect(new RemoveTimerEffect("poison"), new EnergyEffect(30)))),
|
||||
|
||||
/** Gnome Cooking */
|
||||
TOAD_CRUNCHIES(new Food(new int[] {2217}, new HealingEffect(12))),
|
||||
PREMADE_TD_CRUNCH(new Food(new int[] {2243}, new HealingEffect(12))),
|
||||
TOAD_CRUNCHIES(new Food(new int[] {2217}, new HealingEffect(8))),
|
||||
PREMADE_TD_CRUNCH(new Food(new int[] {2243}, new HealingEffect(8))),
|
||||
SPICY_CRUNCHIES(new Food(new int[] {2213}, new HealingEffect(7))),
|
||||
PREMADE_SY_CRUNCH(new Food(new int[] {2241}, new HealingEffect(7))),
|
||||
WORM_CRUNCHIES(new Food(new int[] {2205}, new HealingEffect(8))),
|
||||
|
|
@ -307,7 +307,7 @@ public enum Consumables {
|
|||
OOMLIE_WRAP(new Food(new int[] {Items.COOKED_OOMLIE_WRAP_2343}, new MultiEffect(new HealingEffect(14), new AchievementEffect(DiaryType.KARAMJA, 2, 2)))),
|
||||
ROE(new Food(new int[]{11324}, new HealingEffect(3))),
|
||||
EQUA_LEAVES(new Food(new int[]{2128}, new HealingEffect(1))),
|
||||
CHOC_ICE(new Food(new int[]{6794}, new HealingEffect(6))),
|
||||
CHOC_ICE(new Food(new int[]{6794}, new HealingEffect(7))),
|
||||
EDIBLE_SEAWEED(new Food(new int[] {403}, new HealingEffect(4))),
|
||||
FROG_SPAWN(new Food(new int[] {5004}, new RandomHealthEffect(3, 7), "You eat the frogspawn. Yuck.")),
|
||||
|
||||
|
|
@ -319,44 +319,44 @@ public enum Consumables {
|
|||
STRENGTH(new Potion(new int[] {113, 115, 117, 119}, new SkillEffect(Skills.STRENGTH, 3, 0.1))),
|
||||
ATTACK(new Potion(new int[] {2428, 121, 123, 125}, new SkillEffect(Skills.ATTACK, 3, 0.1))),
|
||||
DEFENCE(new Potion(new int[] {2432, 133, 135, 137}, new SkillEffect(Skills.DEFENCE, 3, 0.1))),
|
||||
RANGING(new Potion(new int[] {2444, 169, 171, 173}, new SkillEffect(Skills.RANGE, 3, 0.1))),
|
||||
MAGIC(new Potion(new int[] {3040, 3042, 3044, 3046}, new SkillEffect(Skills.MAGIC, 3, 0.1))),
|
||||
SUPER_STRENGTH(new Potion(new int[] {2440, 157, 159, 161}, new SkillEffect(Skills.STRENGTH, 3, 0.2))),
|
||||
SUPER_ATTACK(new Potion(new int[] {2436, 145, 147, 149}, new SkillEffect(Skills.ATTACK, 3, 0.2))),
|
||||
SUPER_DEFENCE(new Potion(new int[] {2442, 163, 165, 167}, new SkillEffect(Skills.DEFENCE, 3, 0.2))),
|
||||
RANGING(new Potion(new int[] {2444, 169, 171, 173}, new SkillEffect(Skills.RANGE, 4, 0.1))),
|
||||
MAGIC(new Potion(new int[] {3040, 3042, 3044, 3046}, new SkillEffect(Skills.MAGIC, 4, 0))),
|
||||
SUPER_STRENGTH(new Potion(new int[] {2440, 157, 159, 161}, new SkillEffect(Skills.STRENGTH, 5, 0.15))),
|
||||
SUPER_ATTACK(new Potion(new int[] {2436, 145, 147, 149}, new SkillEffect(Skills.ATTACK, 5, 0.15))),
|
||||
SUPER_DEFENCE(new Potion(new int[] {2442, 163, 165, 167}, new SkillEffect(Skills.DEFENCE, 5, 0.15))),
|
||||
ANTIPOISON(new Potion(new int[] {2446, 175, 177, 179}, new AddTimerEffect("poison:immunity", secondsToTicks(90)))),
|
||||
ANTIPOISON_(new Potion(new int[] {5943, 5945, 5947, 5949}, new AddTimerEffect("poison:immunity", minutesToTicks(9)))),
|
||||
ANTIPOISON__(new Potion(new int[] {5952, 5954, 5956, 5958}, new AddTimerEffect("poison:immunity", minutesToTicks(12)))),
|
||||
SUPER_ANTIP(new Potion(new int[] {2448, 181, 183, 185}, new AddTimerEffect("poison:immunity", minutesToTicks(6)))),
|
||||
RELICYM(new Potion(new int[] {4842, 4844, 4846, 4848}, new MultiEffect(new SetAttributeEffect("disease:immunity", 300), new RemoveTimerEffect("disease")))),
|
||||
RELICYM(new Potion(new int[] {4842, 4844, 4846, 4848}, new CureDiseaseEffect())),
|
||||
AGILITY(new Potion(new int[] {3032, 3034, 3036, 3038}, new SkillEffect(Skills.AGILITY, 3, 0))),
|
||||
HUNTER(new Potion(new int[] {9998, 10000, 10002, 10004}, new SkillEffect(Skills.HUNTER, 3, 0))),
|
||||
RESTORE(new Potion(new int[] {2430, 127, 129, 131}, new RestoreEffect(10, 0.3))),
|
||||
SARA_BREW(new Potion(new int[] {6685, 6687, 6689, 6691}, new MultiEffect(new PercentHeal(2, .15), new SkillEffect(Skills.ATTACK, 0, -0.10), new SkillEffect(Skills.STRENGTH, 0, -0.10), new SkillEffect(Skills.MAGIC, 0, -0.10), new SkillEffect(Skills.RANGE, 0, -0.10), new SkillEffect(Skills.DEFENCE, 2, 0.2)))),
|
||||
SARA_BREW(new Potion(new int[] {6685, 6687, 6689, 6691}, new MultiEffect(new PercentHeal(0, .15), new SkillEffect(Skills.ATTACK, 0, -0.10), new SkillEffect(Skills.STRENGTH, 0, -0.10), new SkillEffect(Skills.MAGIC, 0, -0.10), new SkillEffect(Skills.RANGE, 0, -0.10), new SkillEffect(Skills.DEFENCE, 0, 0.25)))),
|
||||
SUMMONING(new Potion(new int[] {12140, 12142, 12144, 12146}, new MultiEffect(new RestoreSummoningSpecial(), new SummoningEffect(7, 0.25)))),
|
||||
COMBAT(new Potion(new int[] {9739, 9741, 9743, 9745}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, .1), new SkillEffect(Skills.ATTACK, 3, .1)))),
|
||||
ENERGY(new Potion(new int[] {3008, 3010, 3012, 3014}, new MultiEffect(new EnergyEffect(10), new HealingEffect(3)))),
|
||||
ENERGY(new Potion(new int[] {3008, 3010, 3012, 3014}, new EnergyEffect(10))),
|
||||
FISHING(new Potion(new int[] {2438, 151, 153, 155}, new SkillEffect(Skills.FISHING, 3, 0))),
|
||||
PRAYER(new Potion(new int[] {2434, 139, 141, 143}, new PrayerEffect(7, 0.25))),
|
||||
SUPER_RESTO(new Potion(new int[] {3024, 3026, 3028, 3030}, new MultiEffect(new RestoreEffect(8, 0.25), new PrayerEffect(8, 0.25), new SummoningEffect(8, 0.25)))),
|
||||
ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))),
|
||||
ANTIFIRE(new Potion(new int[] {2452, 2454, 2456, 2458}, new SetAttributeEffect("fire:immune", 600, true))),
|
||||
SUPER_RESTO(new Potion(new int[] {3024, 3026, 3028, 3030}, new RestoreEffect(8, 0.25, true))),
|
||||
ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.25), new SkillEffect(Skills.STRENGTH, 0, 0.15), new SkillEffect(Skills.DEFENCE, 0, -0.1)))),
|
||||
ANTIFIRE(new Potion(new int[] {2452, 2454, 2456, 2458}, new AddTimerEffect("dragonfire:immunity", 600, true))),
|
||||
GUTH_REST(new Potion(new int[] {4417, 4419, 4421, 4423}, new MultiEffect(new RemoveTimerEffect("poison"), new EnergyEffect(5), new HealingEffect(5)))),
|
||||
MAGIC_ESS(new Potion(new int[] {11491, 11489}, new SkillEffect(Skills.MAGIC,3,0))),
|
||||
SANFEW(new Potion(new int[] {10925, 10927, 10929, 10931}, new MultiEffect(new RestoreEffect(8,0.25), new PrayerEffect(8,0.25), new RemoveTimerEffect("poison"), new RemoveTimerEffect("disease")))),
|
||||
SANFEW(new Potion(new int[] {10925, 10927, 10929, 10931}, new MultiEffect(new RestoreEffect(8,0.25, true), new AddTimerEffect("poison:immunity", secondsToTicks(90)), new RemoveTimerEffect("disease")))),
|
||||
SUPER_ENERGY(new Potion(new int[] {3016, 3018, 3020, 3022}, new EnergyEffect(20))),
|
||||
BLAMISH_OIL(new FakeConsumable(1582, new String[] {"You know... I'd really rather not."})),
|
||||
|
||||
/** Barbarian Mixes */
|
||||
PRAYERMIX(new BarbarianMix(new int[] {11465, 11467}, new MultiEffect(new PrayerEffect(7, 0.25), new HealingEffect(6)))),
|
||||
ZAMMY_MIX(new BarbarianMix(new int[] {11521, 11523}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))),
|
||||
ZAMMY_MIX(new BarbarianMix(new int[] {11521, 11523}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1)))),
|
||||
ATT_MIX(new BarbarianMix(new int[] {11429, 11431}, new MultiEffect(new SkillEffect(Skills.ATTACK, 3, 0.1), new HealingEffect(3)))),
|
||||
ANTIP_MIX(new BarbarianMix(new int[] {11433, 11435}, new MultiEffect(new AddTimerEffect("poison:immunity", secondsToTicks(90)), new HealingEffect(3)))),
|
||||
RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new RemoveTimerEffect("disease"), new SetAttributeEffect("disease:immunity", 300), new HealingEffect(3)))),
|
||||
RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new CureDiseaseEffect(), new HealingEffect(3)))),
|
||||
STR_MIX(new BarbarianMix(new int[] {11443, 11441}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0.1), new HealingEffect(3)))),
|
||||
RESTO_MIX(new BarbarianMix(new int[] {11449, 11451}, new MultiEffect(new RestoreEffect(10, 0.3), new HealingEffect(3)))),
|
||||
SUPER_RESTO_MIX(new BarbarianMix(new int [] {11493, 11495}, new MultiEffect(new RestoreEffect(8,0.25), new PrayerEffect(8, 0.25), new SummoningEffect(8, 0.25), new HealingEffect(6)))),
|
||||
ENERGY_MIX(new BarbarianMix(new int[] {11453, 11455}, new MultiEffect(new EnergyEffect(10), new HealingEffect(6)))),
|
||||
ENERGY_MIX(new BarbarianMix(new int[] {11453, 11455}, new MultiEffect(new EnergyEffect(10), new HealingEffect(3)))),
|
||||
DEF_MIX(new BarbarianMix(new int[] {11457, 11459}, new MultiEffect(new SkillEffect(Skills.DEFENCE, 3, 0.1), new HealingEffect(6)))),
|
||||
AGIL_MIX(new BarbarianMix(new int[] {11461, 11463}, new MultiEffect(new SkillEffect(Skills.AGILITY, 3, 0), new HealingEffect(6)))),
|
||||
COMBAT_MIX(new BarbarianMix(new int[] {11445, 11447}, new MultiEffect(new SkillEffect(Skills.ATTACK, 3, 0.1), new SkillEffect(Skills.STRENGTH, 3, 0.1), new HealingEffect(6)))),
|
||||
|
|
@ -367,6 +367,7 @@ public enum Consumables {
|
|||
SUPER_STR_MIX(new BarbarianMix(new int[] {11485, 11487}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 5, 0.15), new HealingEffect(6)))),
|
||||
ANTIDOTE_PLUS_MIX(new BarbarianMix(new int[] {11501, 11503}, new MultiEffect(new AddTimerEffect("poison:immunity", minutesToTicks(9)), new RandomHealthEffect(3, 7)))),
|
||||
ANTIP_SUPERMIX(new BarbarianMix(new int[] {11473, 11475}, new MultiEffect(new AddTimerEffect("poison:immunity", minutesToTicks(6)), new RandomHealthEffect(3, 7)))),
|
||||
ANTIFIRE_MIX(new BarbarianMix(new int[] {11505, 11507}, new MultiEffect(new AddTimerEffect("dragonfire:immunity", 600, true), new RandomHealthEffect(3, 7)))),
|
||||
|
||||
/** Stealing creation potions */
|
||||
SC_PRAYER(new Potion(new int[] {14207, 14209, 14211, 14213, 14215}, new PrayerEffect(7, 0.25))),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package content.data.consumables.effects
|
||||
|
||||
import core.api.*
|
||||
import core.game.consumable.ConsumableEffect
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.system.timer.impl.Disease
|
||||
|
||||
class CureDiseaseEffect () : ConsumableEffect() {
|
||||
override fun activate (p: Player) {
|
||||
val existingTimer = getTimer<Disease>(p)
|
||||
if (existingTimer != null) {
|
||||
existingTimer.hitsLeft -= 9
|
||||
if (existingTimer.hitsLeft <= 0) {
|
||||
sendMessage(p, "The disease has been cured.")
|
||||
removeTimer<Disease>(p)
|
||||
}else{
|
||||
sendMessage(p,"You feel slightly better.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,21 +6,37 @@ import core.game.node.entity.skill.Skills;
|
|||
|
||||
public class RestoreEffect extends ConsumableEffect {
|
||||
double base,bonus;
|
||||
boolean all_skills; // Except for hitpoints
|
||||
public RestoreEffect(double base, double bonus){
|
||||
this.base = base;
|
||||
this.bonus = bonus;
|
||||
this.all_skills = false;
|
||||
}
|
||||
|
||||
public RestoreEffect(double base, double bonus, boolean all_skills){
|
||||
this.base = base;
|
||||
this.bonus = bonus;
|
||||
this.all_skills = all_skills;
|
||||
}
|
||||
final int[] SKILLS = new int[] { Skills.DEFENCE, Skills.ATTACK, Skills.STRENGTH, Skills.MAGIC, Skills.RANGE };
|
||||
final int[] ALL_SKILLS = new int[]{
|
||||
Skills.ATTACK,Skills.DEFENCE, Skills.STRENGTH,Skills.RANGE,Skills.PRAYER,Skills.MAGIC, Skills.COOKING,
|
||||
Skills.WOODCUTTING,Skills.FLETCHING,Skills.FISHING,Skills.FIREMAKING,Skills.CRAFTING,Skills.SMITHING,
|
||||
Skills.MINING,Skills.HERBLORE,Skills.AGILITY,Skills.THIEVING,Skills.SLAYER,Skills.FARMING,
|
||||
Skills.RUNECRAFTING,Skills.HUNTER,Skills.CONSTRUCTION,Skills.SUMMONING };
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
Skills sk = p.getSkills();
|
||||
for(int skill : SKILLS){
|
||||
int[] skills = this.all_skills ? ALL_SKILLS : SKILLS;
|
||||
for(int skill : skills){
|
||||
int statL = sk.getStaticLevel(skill);
|
||||
int boost = (int) (base + (statL * bonus));
|
||||
int curL = sk.getLevel(skill);
|
||||
if(curL < statL){
|
||||
int boost = (int) (base + (statL * bonus));
|
||||
p.getSkills().updateLevel(skill, boost, statL);
|
||||
}
|
||||
if (skill == Skills.PRAYER)
|
||||
p.getSkills().incrementPrayerPoints(boost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ class ChampionChallengeListener : InteractionListener, MapArea {
|
|||
)
|
||||
|
||||
private val PORTCULLIS = Scenery.PORTCULLIS_10553
|
||||
private val LADDER = Scenery.LADDER_10554
|
||||
private val CHAMPION_STATUE_CLOSED = Scenery.CHAMPION_STATUE_10556
|
||||
private val CHAMPION_STATUE_OPEN = Scenery.CHAMPION_STATUE_10557
|
||||
private val TRAPDOOR_CLOSED = Scenery.TRAPDOOR_10558
|
||||
|
|
@ -124,6 +123,13 @@ class ChampionChallengeListener : InteractionListener, MapArea {
|
|||
private val ARENA_ZONE = 12696
|
||||
|
||||
override fun defineListeners() {
|
||||
// Champion's Guild Basement Ladder to Main Floor
|
||||
addClimbDest(Location(3190, 9758, 0), Location(3190, 3356, 0))
|
||||
// Champion Statue Ladder to Arena
|
||||
addClimbDest(Location(3184, 9758, 0), Location(3182, 9758, 0))
|
||||
// Arena Ladder to Champion's Guild Basement
|
||||
addClimbDest(Location(3183, 9758, 0), Location(3185, 9758, 0))
|
||||
|
||||
on(LARXUS, IntType.NPC, "talk-to") { player, _ ->
|
||||
openDialogue(player, LarxusDialogue(false))
|
||||
return@on true
|
||||
|
|
@ -134,18 +140,18 @@ class ChampionChallengeListener : InteractionListener, MapArea {
|
|||
return@on true
|
||||
}
|
||||
|
||||
on(TRAPDOOR_CLOSED, IntType.SCENERY, "open") { _, node ->
|
||||
replaceScenery(node.asScenery(), TRAPDOOR_OPEN, 100, node.location)
|
||||
return@on true
|
||||
}
|
||||
|
||||
onUseWith(IntType.NPC, ChampionScrollsDropHandler.SCROLLS, NPCs.LARXUS_3050) { player, _, _ ->
|
||||
openDialogue(player, LarxusDialogue(true))
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
on(TRAPDOOR_CLOSED, IntType.SCENERY, "open") { _, node ->
|
||||
replaceScenery(node.asScenery(), TRAPDOOR_OPEN, 100, node.location)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(TRAPDOOR_OPEN, IntType.SCENERY, "close") { _, node ->
|
||||
replaceScenery(node.asScenery(), TRAPDOOR_CLOSED, 100, node.location)
|
||||
replaceScenery(node.asScenery(), TRAPDOOR_CLOSED, -1, node.location)
|
||||
return@on true
|
||||
}
|
||||
|
||||
|
|
@ -154,15 +160,6 @@ class ChampionChallengeListener : InteractionListener, MapArea {
|
|||
return@on true
|
||||
}
|
||||
|
||||
on(LADDER, IntType.SCENERY, "climb-up") { player, _ ->
|
||||
teleport(player, Location.create(3185, 9758, 0))
|
||||
return@on true
|
||||
}
|
||||
on(CHAMPION_STATUE_OPEN, IntType.SCENERY, "climb-down") { player, _ ->
|
||||
teleport(player, Location.create(3182, 9758, 0))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(PORTCULLIS, IntType.SCENERY, "open") { player, node ->
|
||||
if (player.getAttribute("championsarena:start", false) == false) {
|
||||
sendNPCDialogue(player, NPCs.LARXUS_3050, "You need to arrange a challenge with me before you enter the arena.")
|
||||
|
|
@ -229,4 +226,4 @@ class ChampionChallengeListener : InteractionListener, MapArea {
|
|||
ZoneRestriction.RANDOM_EVENTS
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,12 +11,13 @@ import core.ServerStore.Companion.getString
|
|||
|
||||
import content.global.bots.ShootingStarBot
|
||||
import core.game.world.repository.Repository
|
||||
import core.tools.RandomFunction
|
||||
|
||||
/**
|
||||
* Represents a shooting star object (Only ever initialized once) (ideally)
|
||||
* @author Ceikry
|
||||
*/
|
||||
class ShootingStar(var level: ShootingStarType = ShootingStarType.values().random()){
|
||||
class ShootingStar(var level: ShootingStarType = ShootingStarType.values().random()) {
|
||||
val crash_locations = mapOf(
|
||||
"East of Dark Wizards' Tower" to Location.create(2925, 3339, 0), // East of Dark Wizards' Tower
|
||||
"Crafting Guild" to Location.create(2940, 3280, 0), // Crafting Guild Mine
|
||||
|
|
@ -30,7 +31,7 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
|
|||
"Relleka mining site" to Location.create(2682, 3700, 0), // Rellekka mining site
|
||||
"Jatizso mine" to Location.create(2393, 3815, 0), //Jatiszo mining site (requires Fremennik Isles prereqs)
|
||||
"Lunar Isle mine" to Location.create(2140, 3939, 0), // Lunar Isle mine (requires Lunar Diplomacy prereqs)
|
||||
"Miscellania coal mine" to Location.create(2529, 3887, 0), // Miscellania coal mine (requires Fremennik Trials)
|
||||
"Miscellania coal mine" to Location.create(2529, 3887, 0), // Miscellania coal mine (requires The Fremennik Trials)
|
||||
//"Neitiznot runite mine" to Location.create(2376, 3835, 0), // Near the Neitiznot runite mine (requires Fremennik Isles prereqs) currently inaccessible as bridge does not work
|
||||
"Ardougne mining site" to Location.create(2600, 3232, 0), // Ardougne mining site (Monastery)
|
||||
"Ardougne eastern mine" to Location.create(2706, 3334, 0), // Ardougne mining site (Legends Guild)
|
||||
|
|
@ -79,22 +80,15 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
|
|||
* Degrades a ShootingStar (or removes the starObject and spawns a Star Sprite if it's the last star)
|
||||
*/
|
||||
fun degrade() {
|
||||
if(level.ordinal == 0){
|
||||
selfBots.filter { it.isMining() }.forEach { it.sleep() }
|
||||
SceneryBuilder.remove(starObject)
|
||||
isSpawned = false
|
||||
starSprite.location = starObject.location
|
||||
starSprite.init()
|
||||
spriteSpawned = true
|
||||
ShootingStarPlugin.getStoreFile().clear()
|
||||
if(level.ordinal == 0) {
|
||||
spawnSprite()
|
||||
return
|
||||
}
|
||||
level = getNextType()
|
||||
maxDust = level.totalStardust
|
||||
dustLeft = level.totalStardust
|
||||
|
||||
ShootingStarPlugin.getStoreFile()["level"] = level.ordinal
|
||||
ShootingStarPlugin.getStoreFile()["isDiscovered"] = isDiscovered
|
||||
ShootingStarPlugin.getStoreFile()["dustLeft"] = dustLeft
|
||||
|
||||
val newStar = Scenery(level.objectId, starObject.location)
|
||||
SceneryBuilder.replace(starObject, newStar)
|
||||
|
|
@ -110,7 +104,6 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
|
|||
*/
|
||||
fun fire() {
|
||||
SceneryBuilder.remove(starObject)
|
||||
rebuildVars()
|
||||
clearSprite()
|
||||
SceneryBuilder.add(starObject)
|
||||
if(!isSpawned) {
|
||||
|
|
@ -123,37 +116,54 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
|
|||
}
|
||||
isSpawned = true
|
||||
Repository.sendNews("A shooting star level ${level.ordinal + 1} just crashed near ${location}!")
|
||||
ShootingStarPlugin.getStoreFile()["level"] = level.ordinal
|
||||
ShootingStarPlugin.getStoreFile()["location"] = location
|
||||
ShootingStarPlugin.getStoreFile()["isDiscovered"] = isDiscovered
|
||||
ShootingStarPlugin.getStoreFile()["dustLeft"] = dustLeft
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuilds some of the variables with new information.
|
||||
*/
|
||||
fun rebuildVars(){
|
||||
if(firstStar && ShootingStarPlugin.getStoreFile().isNotEmpty()){
|
||||
level = ShootingStarType.values()[ShootingStarPlugin.getStoreFile().getInt("level")]
|
||||
location = ShootingStarPlugin.getStoreFile().getString("location")
|
||||
isDiscovered = ShootingStarPlugin.getStoreFile().getBoolean("isDiscovered")
|
||||
} else {
|
||||
level = ShootingStarType.values().random()
|
||||
location = crash_locations.entries.random().key
|
||||
isDiscovered = false
|
||||
// Defaults
|
||||
var levelOrd = RandomFunction.random(9)
|
||||
level = ShootingStarType.values()[levelOrd]
|
||||
location = crash_locations.entries.random().key
|
||||
isDiscovered = false
|
||||
dustLeft = level.totalStardust
|
||||
ticks = 0
|
||||
spriteSpawned = false
|
||||
|
||||
if (firstStar && ShootingStarPlugin.getStoreFile().isNotEmpty()) {
|
||||
// Replace default with stored values, if any
|
||||
levelOrd = ShootingStarPlugin.getStoreFile().getInt("level", levelOrd)
|
||||
level = ShootingStarType.values()[levelOrd]
|
||||
location = ShootingStarPlugin.getStoreFile().getString("location", location)
|
||||
isDiscovered = ShootingStarPlugin.getStoreFile().getBoolean("isDiscovered", false)
|
||||
dustLeft = ShootingStarPlugin.getStoreFile().getInt("dustLeft", dustLeft)
|
||||
ticks = ShootingStarPlugin.getStoreFile().getInt("ticks", ticks)
|
||||
spriteSpawned = ShootingStarPlugin.getStoreFile().getBoolean("spriteSpawned", false)
|
||||
}
|
||||
|
||||
maxDust = level.totalStardust
|
||||
dustLeft = level.totalStardust
|
||||
starObject = Scenery(level.objectId, crash_locations.get(location))
|
||||
}
|
||||
|
||||
ShootingStarPlugin.getStoreFile()["level"] = level.ordinal
|
||||
ShootingStarPlugin.getStoreFile()["location"] = location
|
||||
ShootingStarPlugin.getStoreFile()["isDiscovered"] = false
|
||||
|
||||
ticks = 0
|
||||
firstStar = false
|
||||
fun spawnSprite() {
|
||||
selfBots.filter { it.isMining() }.forEach { it.sleep() }
|
||||
SceneryBuilder.remove(starObject)
|
||||
isSpawned = false
|
||||
starSprite.location = starObject.location
|
||||
starSprite.init()
|
||||
spriteSpawned = true
|
||||
ShootingStarPlugin.getStoreFile()["spriteSpawned"] = spriteSpawned
|
||||
}
|
||||
|
||||
fun clearSprite() {
|
||||
starSprite.clear()
|
||||
spriteSpawned = false
|
||||
ShootingStarPlugin.getStoreFile()["spriteSpawned"] = spriteSpawned
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,6 +171,7 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
|
|||
*/
|
||||
fun decDust() {
|
||||
if(--dustLeft <= 0) degrade()
|
||||
ShootingStarPlugin.getStoreFile()["dustLeft"] = dustLeft
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class ShootingStarMiningPulse(player: Player?, node: Scenery?, val star: Shootin
|
|||
player.sendMessage("You have ${player.skills.experienceMultiplier * player.getAttribute("shooting-star:bonus-xp", 0).toDouble()} bonus xp towards mining stardust.")
|
||||
ShootingStarPlugin.submitScoreBoard(player)
|
||||
star.isDiscovered = true
|
||||
ShootingStarPlugin.getStoreFile()["isDiscovered"] = star.isDiscovered
|
||||
return player.skills.getLevel(Skills.MINING) >= star.miningLevel
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ import core.ServerStore.Companion.getBoolean
|
|||
import core.game.dialogue.DialogueFile
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
import core.tools.SystemLogger
|
||||
import core.game.system.command.Privilege
|
||||
import core.game.world.GameWorld
|
||||
import core.tools.Log
|
||||
import core.tools.secondsToTicks
|
||||
import content.data.Quests
|
||||
|
||||
class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Commands, StartupListener {
|
||||
override fun login(player: Player) {
|
||||
|
|
@ -27,14 +27,30 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com
|
|||
override fun tick() {
|
||||
++star.ticks
|
||||
|
||||
// Check if the current star sprite should expire
|
||||
val maxDelay = tickDelay + (tickDelay / 3)
|
||||
if(star.ticks > maxDelay && star.spriteSpawned){
|
||||
star.clearSprite()
|
||||
}
|
||||
|
||||
if ((star.ticks >= tickDelay && !star.spriteSpawned) || (!star.isSpawned && !star.spriteSpawned)) {
|
||||
if (star.firstStar && !star.isSpawned && !star.spriteSpawned) {
|
||||
// Apparently, the server has only just booted
|
||||
star.rebuildVars()
|
||||
if (star.spriteSpawned) {
|
||||
star.spawnSprite()
|
||||
} else {
|
||||
star.fire()
|
||||
}
|
||||
star.firstStar = false
|
||||
}
|
||||
|
||||
// Check if it's time to fire a new one
|
||||
if (star.ticks >= tickDelay && !star.spriteSpawned) {
|
||||
star.rebuildVars()
|
||||
star.fire()
|
||||
}
|
||||
|
||||
getStoreFile()["ticks"] = star.ticks
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
|
|
@ -80,17 +96,17 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com
|
|||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
fun teleportToStar(player: Player) {
|
||||
val condition: (p: Player) -> Boolean = when (star.location.toLowerCase()) {
|
||||
"canifis bank" -> {p -> requireQuest(p, "Priest in Peril", "to access this.") }
|
||||
//"burgh de rott bank" -> {p -> hasRequirement(p, "In Aid of the Myreque") } //disabled: crash
|
||||
"crafting guild" -> {p -> hasLevelStat(p, Skills.CRAFTING, 40) }
|
||||
"lletya bank" -> {p -> hasRequirement(p, "Mourning's End Part I") }
|
||||
"jatizso mine" -> {p -> hasRequirement(p, "The Fremennik Isles") }
|
||||
"south crandor mining site" -> {p -> hasRequirement(p, "Dragon Slayer") }
|
||||
"shilo village mining site" -> {p -> hasRequirement(p, "Shilo Village") }
|
||||
"mos le'harmless bank" -> {p -> hasRequirement(p, "Cabin Fever") } //needs to be updated to check for completion when the quest releases; https://runescape.wiki/w/Mos_Le%27Harmless?oldid=913025
|
||||
"lunar isle mine" -> {p -> hasRequirement(p, "Lunar Diplomacy") }
|
||||
"miscellania coal mine" -> {p -> requireQuest(p, "The Fremennik Trials", "to access this.") }
|
||||
//"neitiznot runite mine" -> {p -> hasRequirement(p, "The Fremennik Isles") } //disabled: currently not reachable
|
||||
"canifis bank" -> {p -> requireQuest(p, Quests.PRIEST_IN_PERIL, "to access this.")}
|
||||
//"burgh de rott bank" -> {p -> hasRequirement(p, Quests.IN_AID_OF_THE_MYREQUE)} //disabled: crash
|
||||
"crafting guild" -> {p -> hasLevelStat(p, Skills.CRAFTING, 40)}
|
||||
"lletya bank" -> {p -> hasRequirement(p, Quests.MOURNINGS_END_PART_I)}
|
||||
"jatizso mine" -> {p -> hasRequirement(p, Quests.THE_FREMENNIK_ISLES)}
|
||||
"south crandor mining site" -> {p -> hasRequirement(p, Quests.DRAGON_SLAYER)}
|
||||
"shilo village mining site" -> {p -> hasRequirement(p, Quests.SHILO_VILLAGE)}
|
||||
"mos le'harmless bank" -> {p -> hasRequirement(p, Quests.CABIN_FEVER)} //needs to be updated to check for completion when the quest releases; https://runescape.wiki/w/Mos_Le%27Harmless?oldid=913025
|
||||
"lunar isle mine" -> {p -> hasRequirement(p, Quests.LUNAR_DIPLOMACY)}
|
||||
"miscellania coal mine" -> {p -> requireQuest(p, Quests.THE_FREMENNIK_TRIALS, "to access this.")}
|
||||
//"neitiznot runite mine" -> {p -> hasRequirement(p, Quests.THE_FREMENNIK_ISLES)} //disabled: currently not reachable
|
||||
else -> {_ -> true}
|
||||
}
|
||||
if (!condition.invoke(player)) {
|
||||
|
|
@ -122,6 +138,7 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com
|
|||
}
|
||||
|
||||
define("submit", Privilege.ADMIN) { _, _ ->
|
||||
star.rebuildVars()
|
||||
star.fire()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ public abstract class ClueScrollPlugin extends MapZone implements Plugin<Object>
|
|||
int hasAmt = 0;
|
||||
for (int i = 0; i < equipment.length; i++) {
|
||||
for (int k = 0; k < equipment[i].length; k++) {
|
||||
if (player.getEquipment().contains(equipment[i][k], 1)) {
|
||||
if (player.getEquipment().contains(equipment[i][k], 1) || player.costumeRoomBank.contains(equipment[i][k], 1)) {
|
||||
hasAmt++;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
28
Server/src/main/content/global/ame/KidnapHelper.kt
Normal file
28
Server/src/main/content/global/ame/KidnapHelper.kt
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package content.global.ame
|
||||
|
||||
import core.ServerConstants
|
||||
import core.api.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.TeleportManager.TeleportType
|
||||
import core.game.world.map.Location
|
||||
|
||||
fun kidnapPlayer(player: Player, loc: Location, type: TeleportType) {
|
||||
setAttribute(player, "kidnapped-by-random", true)
|
||||
if (getAttribute(player, "/save:original-loc", null) == null) {
|
||||
setAttribute(player, "/save:original-loc", player.location)
|
||||
}
|
||||
teleport(player, loc, type)
|
||||
}
|
||||
|
||||
fun returnPlayer(player: Player) {
|
||||
// Prevent returning more than once and sending the player back to HOME_LOCATION
|
||||
if (getAttribute<Location?>(player, "kidnapped-by-random", null) == null) {
|
||||
return
|
||||
}
|
||||
|
||||
player.locks.unlockTeleport()
|
||||
val destination = getAttribute(player, "/save:original-loc", ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0))
|
||||
teleport(player, destination)
|
||||
unlock(player)
|
||||
removeAttributes(player, "/save:original-loc", "kidnapped-by-random")
|
||||
}
|
||||
|
|
@ -3,9 +3,15 @@ package content.global.ame
|
|||
import content.global.ame.events.MysteriousOldManNPC
|
||||
import core.api.playGlobalAudio
|
||||
import core.api.poofClear
|
||||
import core.api.sendMessage
|
||||
import core.api.utils.WeightBasedTable
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.combat.CombatStyle
|
||||
import core.game.node.entity.impl.PulseType
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.npc.agg.AggressiveBehavior
|
||||
import core.game.node.entity.npc.agg.AggressiveHandler
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
|
|
@ -13,10 +19,11 @@ import core.game.world.map.RegionManager
|
|||
import core.game.world.map.path.Pathfinder
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.integrations.discord.Discord
|
||||
import core.api.utils.WeightBasedTable
|
||||
import core.tools.secondsToTicks
|
||||
import core.tools.ticksToCycles
|
||||
import org.rs09.consts.Sounds
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.min
|
||||
import kotlin.random.Random
|
||||
import kotlin.reflect.full.createInstance
|
||||
|
||||
|
|
@ -66,7 +73,6 @@ abstract class RandomEventNPC(id: Int) : NPC(id) {
|
|||
if (!player.getAttribute("random:pause", false)) {
|
||||
ticksLeft--
|
||||
}
|
||||
|
||||
if (!pulseManager.hasPulseRunning() && !finalized) {
|
||||
follow()
|
||||
}
|
||||
|
|
@ -87,6 +93,11 @@ abstract class RandomEventNPC(id: Int) : NPC(id) {
|
|||
location = spawnLocation
|
||||
player.setAttribute("re-npc", this)
|
||||
super.init()
|
||||
super.aggressiveHandler = AggressiveHandler(this, object : AggressiveBehavior() {
|
||||
override fun canSelectTarget(entity: Entity, target: Entity): Boolean {
|
||||
return target == player
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
open fun onTimeUp() {
|
||||
|
|
@ -118,4 +129,19 @@ abstract class RandomEventNPC(id: Int) : NPC(id) {
|
|||
}
|
||||
|
||||
abstract fun talkTo(npc: NPC)
|
||||
}
|
||||
|
||||
override fun isAttackable(entity: Entity, style: CombatStyle, message: Boolean): Boolean {
|
||||
if (entity != player) {
|
||||
if (entity is Player) {
|
||||
sendMessage(entity, "It isn't interested in fighting you.") //TODO authentic message
|
||||
}
|
||||
return false
|
||||
}
|
||||
return super.isAttackable(entity, style, message)
|
||||
}
|
||||
|
||||
fun idForCombatLevel(ids: List<Int>, player: Player): Int {
|
||||
val index = min(ids.size, ceil(player.properties.currentCombatLevel / 20.0).toInt()) - 1
|
||||
return ids[index]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,18 @@ package content.global.ame
|
|||
import org.rs09.consts.Items
|
||||
import content.global.ame.events.MysteriousOldManNPC
|
||||
import content.global.ame.events.certer.CerterNPC
|
||||
import content.global.ame.events.drilldemon.SeargentDamienNPC
|
||||
import content.global.ame.events.drilldemon.SergeantDamienNPC
|
||||
import content.global.ame.events.drunkendwarf.DrunkenDwarfNPC
|
||||
import content.global.ame.events.evilbob.EvilBobNPC
|
||||
import content.global.ame.events.evilchicken.EvilChickenNPC
|
||||
import content.global.ame.events.freakyforester.FreakyForesterNPC
|
||||
import content.global.ame.events.maze.MazeNPC
|
||||
import content.global.ame.events.genie.GenieNPC
|
||||
import content.global.ame.events.pillory.PilloryNPC
|
||||
import content.global.ame.events.rickturpentine.RickTurpentineNPC
|
||||
import content.global.ame.events.rivertroll.RiverTrollRENPC
|
||||
import content.global.ame.events.rockgolem.RockGolemRENPC
|
||||
import content.global.ame.events.quizmaster.QuizMasterNPC
|
||||
import content.global.ame.events.sandwichlady.SandwichLadyRENPC
|
||||
import content.global.ame.events.shade.ShadeRENPC
|
||||
import content.global.ame.events.strangeplant.StrangePlantNPC
|
||||
|
|
@ -43,7 +46,8 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n
|
|||
WeightedItem(Items.TOOTH_HALF_OF_A_KEY_985,1,1,0.1),
|
||||
WeightedItem(Items.LOOP_HALF_OF_A_KEY_987,1,1,0.1)
|
||||
)),
|
||||
DRILL_DEMON(npc = SeargentDamienNPC()),
|
||||
MAZE(npc = MazeNPC()),
|
||||
DRILL_DEMON(npc = SergeantDamienNPC()),
|
||||
EVIL_CHICKEN(npc = EvilChickenNPC()),
|
||||
STRANGE_PLANT(npc = StrangePlantNPC()),
|
||||
SWARM(npc = SwarmNPC()),
|
||||
|
|
@ -52,7 +56,9 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n
|
|||
RICK_TURPENTINE(npc = RickTurpentineNPC(), loot = CERTER.loot),
|
||||
SURPRISE_EXAM(npc = MysteriousOldManNPC(), type = "sexam"),
|
||||
FREAKY_FORESTER(npc = FreakyForesterNPC(), skillIds = intArrayOf(Skills.WOODCUTTING)),
|
||||
PILLORY(npc = PilloryNPC(), skillIds = intArrayOf(Skills.THIEVING)),
|
||||
TREE_SPIRIT(npc = TreeSpiritRENPC(), skillIds = intArrayOf(Skills.WOODCUTTING)),
|
||||
QUIZ_MASTER(npc = QuizMasterNPC()),
|
||||
RIVER_TROLL(RiverTrollRENPC(), skillIds = intArrayOf(Skills.FISHING)),
|
||||
ROCK_GOLEM(RockGolemRENPC(), skillIds = intArrayOf(Skills.MINING)),
|
||||
SHADE(ShadeRENPC(), skillIds = intArrayOf(Skills.PRAYER)),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package content.global.ame.events
|
||||
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.npc.NPCBehavior
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
class HostileRandomEventBehavior : NPCBehavior(
|
||||
NPCs.EVIL_CHICKEN_2463, NPCs.EVIL_CHICKEN_2464, NPCs.EVIL_CHICKEN_2465, NPCs.EVIL_CHICKEN_2466, NPCs.EVIL_CHICKEN_2467, NPCs.EVIL_CHICKEN_2468,
|
||||
NPCs.RIVER_TROLL_391, NPCs.RIVER_TROLL_392, NPCs.RIVER_TROLL_393, NPCs.RIVER_TROLL_394, NPCs.RIVER_TROLL_395, NPCs.RIVER_TROLL_396,
|
||||
NPCs.ROCK_GOLEM_413, NPCs.ROCK_GOLEM_414, NPCs.ROCK_GOLEM_415, NPCs.ROCK_GOLEM_416, NPCs.ROCK_GOLEM_417, NPCs.ROCK_GOLEM_418,
|
||||
NPCs.SHADE_425, NPCs.SHADE_426, NPCs.SHADE_427, NPCs.SHADE_428, NPCs.SHADE_429, NPCs.SHADE_430, NPCs.SHADE_431,
|
||||
NPCs.TREE_SPIRIT_438, NPCs.TREE_SPIRIT_439, NPCs.TREE_SPIRIT_440, NPCs.TREE_SPIRIT_441, NPCs.TREE_SPIRIT_442, NPCs.TREE_SPIRIT_443,
|
||||
NPCs.ZOMBIE_419, NPCs.ZOMBIE_420, NPCs.ZOMBIE_421, NPCs.ZOMBIE_422, NPCs.ZOMBIE_423, NPCs.ZOMBIE_424
|
||||
) {
|
||||
override fun getXpMultiplier(self: NPC, attacker: Entity): Double {
|
||||
return super.getXpMultiplier(self, attacker) / 16.0
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@ class DrillDemonListeners : InteractionListener, MapArea {
|
|||
}
|
||||
|
||||
override fun getRestrictions(): Array<ZoneRestriction> {
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS)
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.OFF_MAP)
|
||||
}
|
||||
|
||||
override fun areaEnter(entity: Entity) {
|
||||
|
|
@ -90,4 +90,4 @@ class DrillDemonListeners : InteractionListener, MapArea {
|
|||
setComponentVisibility(entity.asPlayer(), 746, 12, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package content.global.ame.events.drilldemon
|
||||
|
||||
import content.global.ame.kidnapPlayer
|
||||
import content.global.ame.returnPlayer
|
||||
import core.api.*
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.update.flag.context.Animation
|
||||
|
|
@ -11,7 +14,6 @@ import org.rs09.consts.NPCs
|
|||
|
||||
object DrillDemonUtils {
|
||||
val DD_KEY_TASK = "/save:drilldemon:task"
|
||||
val DD_KEY_RETURN_LOC = "/save:original-loc"
|
||||
val DD_SIGN_VARP = 531
|
||||
val DD_SIGN_JOG = 0
|
||||
val DD_SIGN_SITUP = 1
|
||||
|
|
@ -23,8 +25,7 @@ object DrillDemonUtils {
|
|||
val DD_NPC = NPCs.SERGEANT_DAMIEN_2790
|
||||
|
||||
fun teleport(player: Player) {
|
||||
setAttribute(player, DD_KEY_RETURN_LOC, player.location)
|
||||
teleport(player, Location.create(3163, 4819, 0))
|
||||
kidnapPlayer(player, Location.create(3163, 4819, 0), TeleportManager.TeleportType.INSTANT)
|
||||
player.interfaceManager.closeDefaultTabs()
|
||||
setComponentVisibility(player, 548, 69, true)
|
||||
setComponentVisibility(player, 746, 12, true)
|
||||
|
|
@ -63,13 +64,8 @@ object DrillDemonUtils {
|
|||
}
|
||||
|
||||
fun cleanup(player: Player) {
|
||||
player.locks.unlockTeleport()
|
||||
unlock(player)
|
||||
teleport(player, getAttribute(player, DD_KEY_RETURN_LOC, Location.create(3222, 3218, 0)))
|
||||
removeAttribute(player, DD_KEY_RETURN_LOC)
|
||||
removeAttribute(player, DD_KEY_TASK)
|
||||
removeAttribute(player, DD_CORRECT_OFFSET)
|
||||
removeAttribute(player, DD_CORRECT_COUNTER)
|
||||
returnPlayer(player)
|
||||
removeAttributes(player, DD_KEY_TASK, DD_CORRECT_OFFSET, DD_CORRECT_COUNTER)
|
||||
player.interfaceManager.openDefaultTabs()
|
||||
setComponentVisibility(player, 548, 69, false)
|
||||
setComponentVisibility(player, 746, 12, false)
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ import core.game.interaction.QueueStrength
|
|||
import core.game.system.timer.impl.AntiMacro
|
||||
import core.tools.secondsToTicks
|
||||
|
||||
class SeargentDamienNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.SERGEANT_DAMIEN_2790) {
|
||||
class SergeantDamienNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.SERGEANT_DAMIEN_2790) {
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
sendChat(player.username.capitalize() + "! Drop and give me 20!")
|
||||
sendChat(player.username+ "! Drop and give me 20!")
|
||||
queueScript(player, 4, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package content.global.ame.events.evilbob
|
||||
|
||||
import content.global.ame.returnPlayer
|
||||
import core.ServerConstants
|
||||
import core.api.*
|
||||
import core.game.dialogue.FacialExpression
|
||||
|
|
@ -8,8 +9,6 @@ import core.game.interaction.InteractionListener
|
|||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.link.emote.Emotes
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.zone.ZoneRestriction
|
||||
|
|
@ -121,7 +120,7 @@ class EvilBobListeners : InteractionListener, MapArea {
|
|||
}
|
||||
3 -> {
|
||||
sendMessage(player, "Welcome back to ${ServerConstants.SERVER_NAME}.")
|
||||
teleport(player, getAttribute(player, EvilBobUtils.prevLocation, Location.create(3222, 3219, 0)))
|
||||
returnPlayer(player)
|
||||
EvilBobUtils.reward(player)
|
||||
EvilBobUtils.cleanup(player)
|
||||
resetAnimator(player)
|
||||
|
|
@ -139,7 +138,7 @@ class EvilBobListeners : InteractionListener, MapArea {
|
|||
}
|
||||
|
||||
override fun getRestrictions(): Array<ZoneRestriction> {
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS)
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.OFF_MAP)
|
||||
}
|
||||
|
||||
override fun areaEnter(entity: Entity) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package content.global.ame.events.evilbob
|
||||
|
||||
import content.global.ame.kidnapPlayer
|
||||
import content.global.ame.returnPlayer
|
||||
import core.api.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
|
|
@ -13,10 +16,8 @@ import org.rs09.consts.NPCs
|
|||
import org.rs09.consts.Scenery
|
||||
|
||||
object EvilBobUtils {
|
||||
const val prevLocation = "/save:original-loc"
|
||||
const val eventComplete = "/save:evilbob:eventcomplete"
|
||||
const val assignedFishingZone = "/save:evilbob:fishingzone"
|
||||
const val fishCaught = "evilbob:fishcaught"
|
||||
const val attentive = "/save:evilbob:attentive"
|
||||
const val servantHelpDialogueSeen = "/save:evilbob:servantdialogeseen"
|
||||
const val attentiveNewSpot = "/save:evilbob:attentivenewspot"
|
||||
|
|
@ -53,14 +54,11 @@ object EvilBobUtils {
|
|||
}
|
||||
|
||||
fun teleport(player: Player) {
|
||||
setAttribute(player, prevLocation, player.location)
|
||||
player.properties.teleportLocation = Location.create(3419, 4776, 0)
|
||||
kidnapPlayer(player, Location.create(3419, 4776, 0), TeleportManager.TeleportType.INSTANT)
|
||||
}
|
||||
|
||||
fun cleanup(player: Player) {
|
||||
player.locks.unlockTeleport()
|
||||
player.properties.teleportLocation = getAttribute(player, prevLocation, null)
|
||||
removeAttributes(player, assignedFishingZone, eventComplete, prevLocation, attentive, servantHelpDialogueSeen, attentiveNewSpot, startingDialogueSeen)
|
||||
removeAttributes(player, assignedFishingZone, eventComplete, attentive, servantHelpDialogueSeen, attentiveNewSpot, startingDialogueSeen)
|
||||
removeAll(player, Items.FISHLIKE_THING_6202)
|
||||
removeAll(player, Items.FISHLIKE_THING_6202, Container.BANK)
|
||||
removeAll(player, Items.FISHLIKE_THING_6206)
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ import core.tools.RandomFunction
|
|||
import org.rs09.consts.Items
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
import java.lang.Integer.max
|
||||
|
||||
val ids = 2463..2468
|
||||
val ids = (2463..2468).toList()
|
||||
|
||||
class EvilChickenNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(2463) {
|
||||
val phrases = arrayOf("Bwuk","Bwuk bwuk bwuk","Flee from me, @name!","Begone, @name!","Bwaaaauuuk bwuk bwuk","MUAHAHAHAHAAA!")
|
||||
|
|
@ -19,8 +18,7 @@ class EvilChickenNPC(override var loot: WeightBasedTable? = null) : RandomEventN
|
|||
|
||||
override fun init() {
|
||||
super.init()
|
||||
val index = max(0, (player.properties.combatLevel / 20) - 1)
|
||||
val id = ids.toList()[index]
|
||||
val id = idForCombatLevel(ids, player)
|
||||
this.transform(id)
|
||||
this.attack(player)
|
||||
sendChat(phrases.random().replace("@name",player.username.capitalize()))
|
||||
|
|
|
|||
|
|
@ -57,10 +57,10 @@ class FreakListeners : InteractionListener, MapArea {
|
|||
}
|
||||
|
||||
override fun getRestrictions(): Array<ZoneRestriction> {
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS)
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.OFF_MAP)
|
||||
}
|
||||
|
||||
override fun areaEnter(entity: Entity) {
|
||||
entity.locks.lockTeleport(1000000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
package content.global.ame.events.freakyforester
|
||||
|
||||
import content.global.ame.kidnapPlayer
|
||||
import content.global.ame.returnPlayer
|
||||
import core.api.*
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.tools.RandomFunction
|
||||
|
||||
object FreakUtils{
|
||||
const val freakNpc = NPCs.FREAKY_FORESTER_2458
|
||||
const val freakPreviousLoc = "/save:original-loc"
|
||||
const val freakTask = "/save:freakyf:task"
|
||||
const val freakComplete = "/save:freakyf:complete"
|
||||
const val pheasantKilled = "freakyf:killed"
|
||||
|
|
@ -27,14 +29,12 @@ object FreakUtils{
|
|||
}
|
||||
|
||||
fun teleport(player: Player) {
|
||||
setAttribute(player, freakPreviousLoc, player.location)
|
||||
teleport(player, Location.create(2599, 4777 ,0))
|
||||
kidnapPlayer(player, Location.create(2599, 4777 ,0), TeleportManager.TeleportType.INSTANT)
|
||||
}
|
||||
|
||||
fun cleanup(player: Player) {
|
||||
player.locks.unlockTeleport()
|
||||
player.properties.teleportLocation = getAttribute(player,freakPreviousLoc,null)
|
||||
removeAttributes(player, freakPreviousLoc, freakTask, freakComplete, pheasantKilled)
|
||||
returnPlayer(player)
|
||||
removeAttributes(player, freakTask, freakComplete, pheasantKilled)
|
||||
removeAll(player, Items.RAW_PHEASANT_6178)
|
||||
removeAll(player, Items.RAW_PHEASANT_6178, Container.BANK)
|
||||
removeAll(player, Items.RAW_PHEASANT_6179)
|
||||
|
|
|
|||
277
Server/src/main/content/global/ame/events/maze/MazeInterface.kt
Normal file
277
Server/src/main/content/global/ame/events/maze/MazeInterface.kt
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
package content.global.ame.events.maze
|
||||
|
||||
import content.global.ame.returnPlayer
|
||||
import core.api.*
|
||||
import core.api.utils.WeightBasedTable
|
||||
import core.api.utils.WeightedItem
|
||||
import core.game.event.EventHook
|
||||
import core.game.event.TickEvent
|
||||
import core.game.global.action.DoorActionHandler
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.GameWorld.Pulser
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.zone.ZoneRestriction
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import org.rs09.consts.*
|
||||
|
||||
class MazeInterface : InteractionListener, EventHook<TickEvent>, MapArea {
|
||||
companion object {
|
||||
const val MAZE_TIMER_INTERFACE = Components.MAZETIMER_209
|
||||
const val MAZE_TIMER_VARP = 531 // Interface 209 child 2 config: [531, 0]
|
||||
const val MAZE_ATTRIBUTE_TICKS_LEFT = "maze:percent-ticks-left"
|
||||
const val MAZE_ATTRIBUTE_CHESTS_OPEN = "/save:maze:chests-opened"
|
||||
|
||||
val STARTING_POINTS = arrayOf(
|
||||
Location(2928, 4553, 0),
|
||||
Location(2917, 4553, 0),
|
||||
Location(2908, 4555, 0),
|
||||
Location(2891, 4589, 0),
|
||||
Location(2891, 4595, 0),
|
||||
Location(2891, 4595, 0),
|
||||
Location(2926, 4597, 0),
|
||||
Location(2931, 4597, 0),
|
||||
// There's 2 more, but there isn't a door for them...
|
||||
)
|
||||
|
||||
val REWARD_ITEM = intArrayOf(
|
||||
Items.COINS_995,
|
||||
Items.FEATHER_314,
|
||||
Items.IRON_ARROW_884,
|
||||
Items.CHAOS_RUNE_562,
|
||||
Items.STEEL_ARROW_886,
|
||||
Items.DEATH_RUNE_560,
|
||||
Items.COAL_454,
|
||||
Items.NATURE_RUNE_561,
|
||||
Items.MITHRIL_ORE_448
|
||||
)
|
||||
|
||||
val ITEM_DIVISOR = arrayOf(
|
||||
1.0,
|
||||
2.0,
|
||||
3.0,
|
||||
9.0,
|
||||
12.0,
|
||||
18.0,
|
||||
45.0,
|
||||
162.0,
|
||||
180.0,
|
||||
)
|
||||
|
||||
val CHEST_REWARDS = WeightBasedTable.create(
|
||||
WeightedItem(Items.AIR_RUNE_556,15,15,1.0),
|
||||
WeightedItem(Items.WATER_RUNE_555,10,10,1.0),
|
||||
WeightedItem(Items.EARTH_RUNE_557,10,10,1.0),
|
||||
WeightedItem(Items.FIRE_RUNE_554,10,10,1.0),
|
||||
WeightedItem(Items.BRONZE_ARROW_882,20,20,1.0),
|
||||
WeightedItem(Items.BRONZE_BOLTS_877,10,10,1.0),
|
||||
WeightedItem(Items.IRON_ARROW_884,15,15,1.0),
|
||||
WeightedItem(Items.ATTACK_POTION2_123,1,1,1.0),
|
||||
WeightedItem(Items.STRENGTH_POTION2_117,1,1,1.0),
|
||||
WeightedItem(Items.DEFENCE_POTION2_135,1,1,1.0),
|
||||
)
|
||||
|
||||
fun initMaze(player: Player) {
|
||||
setAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 300)
|
||||
setVarp(player, MAZE_TIMER_VARP, (getAttribute<Int>(player, MAZE_ATTRIBUTE_TICKS_LEFT, 0) / 3),false)
|
||||
openOverlay(player, MAZE_TIMER_INTERFACE)
|
||||
sendMessage(player, "You need to reach the maze center, then you'll be returned to where you were.")
|
||||
sendNPCDialogue(player, NPCs.MYSTERIOUS_OLD_MAN_410, "You need to reach the maze center, then you'll be returned to where you were.")
|
||||
}
|
||||
|
||||
fun calculateLoot(player: Player) {
|
||||
val randomNumber = (0..8).random()
|
||||
val totalLevel = player.getSkills().totalLevel.toDouble()
|
||||
val rewardPotential = getAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 0).toDouble() / 300.0
|
||||
val itemDivisor = ITEM_DIVISOR[randomNumber]
|
||||
val itemQuantity = (totalLevel * rewardPotential * 3.33) / itemDivisor
|
||||
// sendMessage(player, "Maze reward calculation: $totalLevel * $rewardPotential * 3.33 / $itemDivisor = $itemQuantity")
|
||||
if (itemQuantity.toInt() > 0) {
|
||||
addItemOrDrop(player, REWARD_ITEM[randomNumber], itemQuantity.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Chest Location to rotation mapping.
|
||||
* This is needed as it is impossible to obtain the underlying chest scenery for the rotation.
|
||||
* 0: Facing North, 1: Facing East, 2: Facing South, 3: Facing West
|
||||
*/
|
||||
val chestLocationRotationMap = mapOf(
|
||||
Location(2930, 4595, 0).toString() to 2,
|
||||
Location(2924, 4572, 0).toString() to 2,
|
||||
Location(2925, 4573, 0).toString() to 0,
|
||||
Location(2900, 4578, 0).toString() to 2,
|
||||
Location(2901, 4560, 0).toString() to 1,
|
||||
Location(2890, 4599, 0).toString() to 2,
|
||||
Location(2896, 4591, 0).toString() to 2,
|
||||
Location(2895, 4592, 0).toString() to 1,
|
||||
Location(2901, 4560, 0).toString() to 3,
|
||||
Location(2918, 4590, 0).toString() to 1,
|
||||
Location(2917, 4590, 0).toString() to 3,
|
||||
)
|
||||
|
||||
/**
|
||||
* Chest Interaction workaround
|
||||
*
|
||||
* The issue here is that the walls(3626) of the Maze are overlapping some(not all) chest sceneries.
|
||||
*
|
||||
* The types for the wallScenery:
|
||||
* Type 0 - flat panel |
|
||||
* Type 2 - right angle panel with rotation 0:r 1:7 2:> 3:L
|
||||
* Type 3 - corner post . for angle edges of walls
|
||||
*/
|
||||
fun overrideScenery(wallScenery: core.game.node.scenery.Scenery, chestSceneryId: Int): core.game.node.scenery.Scenery {
|
||||
if (wallScenery.id == chestSceneryId) {
|
||||
replaceScenery(wallScenery, Scenery.CHEST_3636, 30)
|
||||
wallScenery.isActive = true
|
||||
return wallScenery // Return the chest scenery as the wallScenery isn't there.
|
||||
}
|
||||
|
||||
addScenery(Scenery.CHEST_3636, wallScenery.location, chestLocationRotationMap[wallScenery.location.toString()] ?: 0, 10)
|
||||
addScenery(wallScenery)
|
||||
// replaceScenery(newChestScenery, Scenery.CHEST_3636, 3) // didn't work for an underlying scenery
|
||||
// I did a world pulse since everyone will get to see the chest open.
|
||||
Pulser.submit(object : Pulse(30) {
|
||||
override fun pulse(): Boolean {
|
||||
addScenery(Scenery.CHEST_3635, wallScenery.location, chestLocationRotationMap[wallScenery.location.toString()] ?: 0, 10)
|
||||
addScenery(wallScenery)
|
||||
return true
|
||||
}
|
||||
})
|
||||
// Return the chest scenery to replace PacketProcessor so that MISMATCH will not happen.
|
||||
return core.game.node.scenery.Scenery(
|
||||
chestSceneryId,
|
||||
wallScenery.location,
|
||||
chestLocationRotationMap[wallScenery.location.toString()] ?: 0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
|
||||
// This somehow doesn't trigger as the scenery.id != objId (3626 != 3635)
|
||||
on(Scenery.CHEST_3635, IntType.SCENERY, "open") { player, node ->
|
||||
if (getAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 0) > 0 && getAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, 0) < 10) {
|
||||
animate(player, 536)
|
||||
// val actualScenery = RegionManager.getObject(node.location.z, node.location.x, node.location.y, 3626)
|
||||
val tableRoll = CHEST_REWARDS.roll()
|
||||
addItemOrBank(player, tableRoll[0].id)
|
||||
when (tableRoll[0].id){
|
||||
Items.AIR_RUNE_556 -> sendItemDialogue(player, Items.AIR_RUNE_556, "You've found some air runes!")
|
||||
Items.WATER_RUNE_555 -> sendItemDialogue(player, Items.WATER_RUNE_555, "You've found some water runes!")
|
||||
Items.EARTH_RUNE_557 -> sendItemDialogue(player, Items.EARTH_RUNE_557, "You've found some earth runes!")
|
||||
Items.FIRE_RUNE_554 -> sendItemDialogue(player, Items.FIRE_RUNE_554, "You've found some fire runes!")
|
||||
Items.BRONZE_ARROW_882 -> sendItemDialogue(player, Items.BRONZE_ARROW_882, "You've found some bronze arrows!")
|
||||
Items.BRONZE_BOLTS_877 -> sendItemDialogue(player, Items.BRONZE_BOLTS_877, "You've found some bronze bolts!")
|
||||
Items.IRON_ARROW_884 -> sendItemDialogue(player, Items.IRON_ARROW_884, "You've found some iron arrows!")
|
||||
Items.ATTACK_POTION2_123 -> sendItemDialogue(player, Items.ATTACK_POTION2_123, "You've found an attack potion!")
|
||||
Items.STRENGTH_POTION2_117 -> sendItemDialogue(player, Items.STRENGTH_POTION2_117, "You've found a strength potion!")
|
||||
Items.DEFENCE_POTION2_135 -> sendItemDialogue(player, Items.DEFENCE_POTION2_135, "You've found a defence potion!")
|
||||
}
|
||||
setAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, getAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, 0))
|
||||
} else {
|
||||
sendMessage(player,"You find nothing of interest.")
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.CHEST_3636, SCENERY, "search") { player, node ->
|
||||
sendMessage(player,"You find nothing of interest.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.WALL_3626, IntType.SCENERY, "open") { player, node ->
|
||||
sendMessage(player, "That bit doesn't open.") // 0xBrLo9woIY
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.WALL_3628, IntType.SCENERY, "open") { player, node ->
|
||||
// Door opening workaround
|
||||
// Ignore 3629(WALL_3629) and 3630(WALL_3630) in handleAutowalkDoor ignoreSecondDoor
|
||||
DoorActionHandler.handleAutowalkDoor(player, node as core.game.node.scenery.Scenery)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.STRANGE_SHRINE_3634, IntType.SCENERY, "touch") { player, node ->
|
||||
player.unhook(this)
|
||||
closeOverlay(player)
|
||||
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
lock(player, 6)
|
||||
sendGraphics(Graphics(86, 0, 3), player.location)
|
||||
animate(player,862)
|
||||
return@queueScript delayScript(player, 6)
|
||||
}
|
||||
1 -> {
|
||||
lock(player, 6)
|
||||
sendGraphics(Graphics(1576, 0, 0), player.location)
|
||||
animate(player,8939)
|
||||
playAudio(player, Sounds.TELEPORT_ALL_200)
|
||||
return@queueScript delayScript(player, 3)
|
||||
}
|
||||
2 -> {
|
||||
returnPlayer(player)
|
||||
sendGraphics(Graphics(1577, 0, 0), player.location)
|
||||
animate(player,8941)
|
||||
closeOverlay(player)
|
||||
return@queueScript delayScript(player, 1)
|
||||
}
|
||||
3 -> {
|
||||
calculateLoot(player)
|
||||
removeAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT)
|
||||
removeAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN)
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
override fun process(entity: Entity, event: TickEvent) {
|
||||
if (entity is Player) {
|
||||
if (getAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, 0) > 0) {
|
||||
setAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, getAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, 0) - 1)
|
||||
}
|
||||
setVarp(entity, MAZE_TIMER_VARP, (getAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, 0) / 3), false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineAreaBorders(): Array<ZoneBorders> {
|
||||
return arrayOf(getRegionBorders(11591))
|
||||
}
|
||||
|
||||
override fun getRestrictions(): Array<ZoneRestriction> {
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT, ZoneRestriction.OFF_MAP)
|
||||
}
|
||||
|
||||
override fun areaEnter(entity: Entity) {
|
||||
if (entity is Player) {
|
||||
sendMessage(entity, "Head for the center of the maze.")
|
||||
entity.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 12)
|
||||
openOverlay(entity, MAZE_TIMER_INTERFACE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun areaLeave(entity: Entity, logout: Boolean) {
|
||||
if (entity is Player) {
|
||||
entity.interfaceManager.restoreTabs()
|
||||
closeOverlay(entity)
|
||||
entity.unhook(this)
|
||||
}
|
||||
}
|
||||
override fun entityStep(entity: Entity, location: Location, lastLocation: Location) {
|
||||
if (entity is Player) {
|
||||
entity.hook(Event.Tick, this)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
57
Server/src/main/content/global/ame/events/maze/MazeNPC.kt
Normal file
57
Server/src/main/content/global/ame/events/maze/MazeNPC.kt
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package content.global.ame.events.maze
|
||||
|
||||
import content.global.ame.RandomEventNPC
|
||||
import content.global.ame.kidnapPlayer
|
||||
import core.api.*
|
||||
import core.api.utils.WeightBasedTable
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.system.timer.impl.AntiMacro
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Sounds
|
||||
|
||||
class MazeNPC(var type: String = "", override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.MYSTERIOUS_OLD_MAN_410) {
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
sendChat("Aha, you'll do ${player.username}!")
|
||||
face(player)
|
||||
queueScript(player, 4, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
lock(player, 6)
|
||||
sendGraphics(Graphics(1576, 0, 0), player.location)
|
||||
animate(player,8939)
|
||||
playAudio(player, Sounds.TELEPORT_ALL_200)
|
||||
return@queueScript delayScript(player, 3)
|
||||
}
|
||||
1 -> {
|
||||
MazeInterface.initMaze(player)
|
||||
// Note: This event is NOT instanced:
|
||||
// Sources:
|
||||
// https://youtu.be/2gpzn9oNdy0 (2007)
|
||||
// https://youtu.be/Tni1HURgnxg (2008)
|
||||
// https://youtu.be/igdwDZOv9LU (2008)
|
||||
// https://youtu.be/0oBCkLArUmc (2011 - even with personal Mysterious Old Man) - "Sorry, this is not the old man you are looking for."
|
||||
// https://youtu.be/FMuKZm-Ikgs (2011)
|
||||
// val region = DynamicRegion.create(11591)
|
||||
kidnapPlayer(player, MazeInterface.STARTING_POINTS.random(), TeleportManager.TeleportType.INSTANT) // 10 random spots
|
||||
AntiMacro.terminateEventNpc(player)
|
||||
sendGraphics(Graphics(1577, 0, 0), player.location)
|
||||
animate(player,8941)
|
||||
removeAttribute(player, MazeInterface.MAZE_ATTRIBUTE_CHESTS_OPEN)
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun talkTo(npc: NPC) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
package content.global.ame.events.pillory
|
||||
|
||||
import content.global.ame.RandomEvents
|
||||
import content.global.ame.returnPlayer
|
||||
import core.api.*
|
||||
import core.game.dialogue.FacialExpression
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.interaction.InterfaceListener
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.zone.ZoneRestriction
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Scenery
|
||||
import org.rs09.consts.Sounds
|
||||
|
||||
/**
|
||||
* Pillory Unlocking Interface PILLORY_189
|
||||
*
|
||||
* https://www.youtube.com/watch?v=caWn7pE2mkE
|
||||
* https://www.youtube.com/watch?v=TMVR5cZZwZ0
|
||||
* https://www.youtube.com/watch?v=Ym9LCDP-Q74
|
||||
* https://www.youtube.com/watch?v=_vn0QZTtI6U (Failure)
|
||||
* https://www.youtube.com/watch?v=zmXDikQIua4
|
||||
*
|
||||
* Child IDs
|
||||
* 4 - Rotating Lock Model
|
||||
* 5 6 7 - Swinging Keys Models
|
||||
* 8 9 10 - Buttons for the Swinging Keys Models
|
||||
* 11 12 13 14 15 16 - Padlocks at the Top
|
||||
* 17 18 19 20 21 22 - Padlocks stars? Model 15272, Anim 4135
|
||||
*
|
||||
* Model IDs
|
||||
* Using the amazeballs ::listifmodels
|
||||
* 9749, 9750, 9751, 9752 - Swinging Keys Models
|
||||
* 9753, 9754, 9755, 9756 - Rotating Lock Models
|
||||
* 9757 9758 locked unlock
|
||||
*/
|
||||
class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
|
||||
companion object {
|
||||
const val PILLORY_LOCK_INTERFACE = 189
|
||||
const val PILLORY_ATTRIBUTE_EVENT_KEYS = "pillory:event-keys"
|
||||
const val PILLORY_ATTRIBUTE_EVENT_LOCK = "pillory:event-lock"
|
||||
const val PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT = "/save:pillory:target-correct"
|
||||
const val PILLORY_ATTRIBUTE_CORRECT_COUNTER = "/save:pillory:num-correct"
|
||||
|
||||
val LOCATIONS = arrayOf(
|
||||
// Varrock Cages
|
||||
Location(3226, 3407, 0),
|
||||
Location(3228, 3407, 0),
|
||||
Location(3230, 3407, 0),
|
||||
// Seers Village Cages
|
||||
Location(2681, 3489, 0),
|
||||
Location(2683, 3489, 0),
|
||||
Location(2685, 3489, 0),
|
||||
// Yannile Cages
|
||||
Location(2604, 3105, 0),
|
||||
Location(2606, 3105, 0),
|
||||
Location(2608, 3105, 0),
|
||||
)
|
||||
|
||||
fun initPillory(player: Player) {
|
||||
setAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3)
|
||||
setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)
|
||||
player.dialogueInterpreter.sendPlainMessage(true, "", "Solve the pillory puzzle to be returned to where you came from.")
|
||||
}
|
||||
|
||||
fun randomPillory(player: Player) {
|
||||
// Shuffle all 4 kinds of keys in, pick 3 for the keys, pick 1 from the 3 as the lock.
|
||||
val keys = (0..3).toIntArray().let{ keys -> keys.shuffle(); return@let keys }
|
||||
val lock = intArrayOf(keys[1], keys[2], keys[3]).random() // Last 3 as there are 4 keys. key[0] is fallback.
|
||||
|
||||
setAttribute(player, PILLORY_ATTRIBUTE_EVENT_KEYS, keys)
|
||||
setAttribute(player, PILLORY_ATTRIBUTE_EVENT_LOCK, lock)
|
||||
|
||||
player.packetDispatch.sendModelOnInterface(9753 + lock, PILLORY_LOCK_INTERFACE, 4, 0)
|
||||
player.packetDispatch.sendModelOnInterface(9749 + keys[1], PILLORY_LOCK_INTERFACE, 5, 0)
|
||||
player.packetDispatch.sendModelOnInterface(9749 + keys[2], PILLORY_LOCK_INTERFACE, 6, 0)
|
||||
player.packetDispatch.sendModelOnInterface(9749 + keys[3], PILLORY_LOCK_INTERFACE, 7, 0)
|
||||
|
||||
val numberToGetCorrect = getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3)
|
||||
val correctCount = getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)
|
||||
for (i in 1.. 6) {
|
||||
// Set if lock is red or green.
|
||||
if (i <= correctCount) {
|
||||
player.packetDispatch.sendModelOnInterface(9758, PILLORY_LOCK_INTERFACE, 10 + i, 0)
|
||||
} else {
|
||||
player.packetDispatch.sendModelOnInterface(9757, PILLORY_LOCK_INTERFACE, 10 + i, 0)
|
||||
}
|
||||
// Set if hide or show lock.
|
||||
player.packetDispatch.sendInterfaceConfig(PILLORY_LOCK_INTERFACE, 10 + i, i > numberToGetCorrect)
|
||||
}
|
||||
}
|
||||
|
||||
fun selectedKey(player: Player, buttonID: Int) {
|
||||
val keys = getAttribute(player, PILLORY_ATTRIBUTE_EVENT_KEYS, intArrayOf(0, 0, 0))
|
||||
val lock = getAttribute(player, PILLORY_ATTRIBUTE_EVENT_LOCK, -1)
|
||||
if (keys[buttonID] == lock) {
|
||||
// CORRECT ANSWER
|
||||
setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) + 1)
|
||||
if (getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3) <= getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, -1)) {
|
||||
player.dialogueInterpreter.sendPlainMessage(true, "", "You've escaped!")
|
||||
sendMessage(player, "You've escaped!")
|
||||
removeAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT)
|
||||
removeAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER)
|
||||
closeInterface(player)
|
||||
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
lock(player, 6)
|
||||
sendGraphics(Graphics(1576, 0, 0), player.location)
|
||||
animate(player,8939)
|
||||
playAudio(player, Sounds.TELEPORT_ALL_200)
|
||||
return@queueScript delayScript(player, 3)
|
||||
}
|
||||
1 -> {
|
||||
val loot = RandomEvents.CERTER.loot!!.roll(player)[0]
|
||||
addItemOrDrop(player, loot.id, loot.amount)
|
||||
returnPlayer(player)
|
||||
sendGraphics(Graphics(1577, 0, 0), player.location)
|
||||
animate(player,8941)
|
||||
closeInterface(player)
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
randomPillory(player)
|
||||
player.dialogueInterpreter.sendPlainMessage(
|
||||
true,
|
||||
"",
|
||||
"Correct!",
|
||||
"" + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) + " down, " +
|
||||
(getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3) - getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)) + " to go!")
|
||||
// Animation for the star, but it doesn't work.
|
||||
player.packetDispatch.sendInterfaceConfig(PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 1), false)
|
||||
sendAnimationOnInterface(player, 4135, PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 1))
|
||||
} else {
|
||||
// WRONG ANSWER
|
||||
player.dialogueInterpreter.close()
|
||||
player.dialogueInterpreter.sendDialogues(NPCs.TRAMP_2794 , FacialExpression.OLD_ANGRY1, "Bah, that's not right.","Use the key that matches the hole", "in the spinning lock.")
|
||||
if (getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 0) < 6) {
|
||||
setAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 0) + 1)
|
||||
}
|
||||
setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)
|
||||
closeInterface(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineInterfaceListeners() {
|
||||
on(PILLORY_LOCK_INTERFACE){ player, component, opcode, buttonID, slot, itemID ->
|
||||
when (buttonID) {
|
||||
8 -> selectedKey(player, 1)
|
||||
9 -> selectedKey(player, 2)
|
||||
10 -> selectedKey(player, 3)
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
onOpen(PILLORY_LOCK_INTERFACE){ player, component ->
|
||||
return@onOpen true
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on(Scenery.CAGE_6836, IntType.SCENERY, "unlock") { player, node ->
|
||||
if (player.location in LOCATIONS) { // When you aren't inside.
|
||||
randomPillory(player)
|
||||
openInterface(player, PILLORY_LOCK_INTERFACE)
|
||||
player.dialogueInterpreter.sendPlainMessage(true, "", "Pick the <col=8A0808>swinging key</col> that matches the", "hole in the <col=8A0808>spinning lock</col>.")
|
||||
} else {
|
||||
sendMessage(player, "You can't unlock the pillory, you'll let all the prisoners out!")
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineAreaBorders(): Array<ZoneBorders> {
|
||||
return arrayOf(
|
||||
// Varrock Cages
|
||||
ZoneBorders(3226, 3407, 3226, 3407),
|
||||
ZoneBorders(3228, 3407, 3228, 3407),
|
||||
ZoneBorders(3230, 3407, 3230, 3407),
|
||||
// Seers Village Cages
|
||||
ZoneBorders(2681, 3489, 2681, 3489),
|
||||
ZoneBorders(2683, 3489, 2683, 3489),
|
||||
ZoneBorders(2685, 3489, 2685, 3489),
|
||||
// Yannile Cages
|
||||
ZoneBorders(2604, 3105, 2604, 3105),
|
||||
ZoneBorders(2606, 3105, 2606, 3105),
|
||||
ZoneBorders(2608, 3105, 2608, 3105),
|
||||
)
|
||||
}
|
||||
|
||||
override fun getRestrictions(): Array<ZoneRestriction> {
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT, ZoneRestriction.OFF_MAP)
|
||||
}
|
||||
|
||||
override fun areaEnter(entity: Entity) {
|
||||
if (entity is Player) {
|
||||
entity.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 12)
|
||||
}
|
||||
}
|
||||
|
||||
override fun areaLeave(entity: Entity, logout: Boolean) {
|
||||
if (entity is Player) {
|
||||
entity.interfaceManager.restoreTabs()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package content.global.ame.events.pillory
|
||||
|
||||
import content.global.ame.RandomEventNPC
|
||||
import content.global.ame.kidnapPlayer
|
||||
import core.api.*
|
||||
import core.api.utils.WeightBasedTable
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.system.timer.impl.AntiMacro
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Sounds
|
||||
|
||||
// "::revent [-p] <lt>player name<gt> [-e <lt>event name<gt>]"
|
||||
class PilloryNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.PILLORY_GUARD_2791) {
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
sendChat("${player.username}, you're under arrest!")
|
||||
face(player)
|
||||
player.dialogueInterpreter.sendPlainMessage(true, "", "Solve the pillory puzzle to be returned to where you came from.")
|
||||
queueScript(player, 4, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
lock(player, 6)
|
||||
sendGraphics(Graphics(1576, 0, 0), player.location)
|
||||
animate(player,8939)
|
||||
playAudio(player, Sounds.TELEPORT_ALL_200)
|
||||
return@queueScript delayScript(player, 3)
|
||||
}
|
||||
1 -> {
|
||||
PilloryInterface.initPillory(player)
|
||||
val dest = PilloryInterface.LOCATIONS.random() //9 random spots!
|
||||
kidnapPlayer(player, dest, TeleportManager.TeleportType.INSTANT)
|
||||
AntiMacro.terminateEventNpc(player)
|
||||
sendGraphics(Graphics(1577, 0, 0), player.location)
|
||||
animate(player,8941)
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun talkTo(npc: NPC) {
|
||||
//player.dialogueInterpreter.open(FreakyForesterDialogue(),npc)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package content.global.ame.events.quizmaster
|
||||
|
||||
import core.api.*
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.zone.ZoneRestriction
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
class QuizMasterBorders : MapArea {
|
||||
override fun defineAreaBorders(): Array<ZoneBorders> {
|
||||
return arrayOf(getRegionBorders(7754))
|
||||
}
|
||||
|
||||
override fun getRestrictions(): Array<ZoneRestriction> {
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT, ZoneRestriction.OFF_MAP)
|
||||
}
|
||||
|
||||
override fun areaEnter(entity: Entity) {
|
||||
if (entity is Player) {
|
||||
entity.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 12)
|
||||
face(entity, Location(1952, 4768, 1))
|
||||
animate(entity,2378)
|
||||
openDialogue(entity, QuizMasterDialogueFile(), NPC(NPCs.QUIZ_MASTER_2477))
|
||||
}
|
||||
}
|
||||
|
||||
override fun areaLeave(entity: Entity, logout: Boolean) {
|
||||
if (entity is Player) {
|
||||
entity.interfaceManager.restoreTabs()
|
||||
//closeOverlay(entity)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
package content.global.ame.events.quizmaster
|
||||
|
||||
import content.global.ame.returnPlayer
|
||||
import core.ServerConstants
|
||||
import core.api.*
|
||||
import core.api.utils.WeightBasedTable
|
||||
import core.api.utils.WeightedItem
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.game.dialogue.FacialExpression
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.player.Player
|
||||
import core.tools.END_DIALOGUE
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class QuizMasterDialogueFile : DialogueFile() {
|
||||
companion object {
|
||||
const val QUIZMASTER_INTERFACE = Components.MACRO_QUIZSHOW_191
|
||||
const val QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT = "/save:quizmaster:questions-correct"
|
||||
const val QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER = "quizmaster:random-answer"
|
||||
|
||||
/*
|
||||
// Golden Models:
|
||||
8828 ADAMANT_BATTLEAXE_1371
|
||||
8829 SALMON_329
|
||||
8830 TROUT_333
|
||||
8831 NECKLACE
|
||||
8832 WOODEN_SHIELD_1171
|
||||
8833 BRONZE_MED_HELM_1139
|
||||
8834 RING
|
||||
8835 SECATEURS_5329
|
||||
8836 BRONZE_SWORD_1277
|
||||
8837 GARDENING_TROWEL_5325
|
||||
*/
|
||||
val sets = arrayOf(
|
||||
intArrayOf(8828, 8829, 8829),
|
||||
intArrayOf(8831, 8837, 8835),
|
||||
intArrayOf(8830, 8832, 8833),
|
||||
intArrayOf(8835, 8834, 8831),
|
||||
intArrayOf(8837, 8836, 8828),
|
||||
)
|
||||
|
||||
fun randomQuestion(player: Player): Int {
|
||||
val randomSet = intArrayOf(*sets.random())
|
||||
val answer = intArrayOf(*randomSet)[0]
|
||||
randomSet.shuffle()
|
||||
val correctButton = randomSet.indexOf(answer) + 2 // buttons are 3,4,5
|
||||
|
||||
player.packetDispatch.sendModelOnInterface(randomSet[0], QUIZMASTER_INTERFACE, 6, 512)
|
||||
player.packetDispatch.sendModelOnInterface(randomSet[1], QUIZMASTER_INTERFACE, 7, 512)
|
||||
player.packetDispatch.sendModelOnInterface(randomSet[2], QUIZMASTER_INTERFACE, 8, 512)
|
||||
player.packetDispatch.sendAngleOnInterface(QUIZMASTER_INTERFACE, 6, 512,0,0)
|
||||
player.packetDispatch.sendAngleOnInterface(QUIZMASTER_INTERFACE, 7, 512,0,0)
|
||||
player.packetDispatch.sendAngleOnInterface(QUIZMASTER_INTERFACE, 8, 512,0,0)
|
||||
|
||||
return correctButton
|
||||
}
|
||||
|
||||
// Random Item should be "Mystery Box", but the current MYSTERY_BOX_6199 is already inauthentically used by Giftmas.
|
||||
val tableRoll = WeightBasedTable.create(
|
||||
WeightedItem(Items.LAMP_2528, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.CABBAGE_1965, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.DIAMOND_1601, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.BUCKET_1925, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.FLIER_956, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.OLD_BOOT_685, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.BODY_RUNE_559, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.ONION_1957, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.MITHRIL_SCIMITAR_1329, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.CASKET_405, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.STEEL_PLATEBODY_1119, 1, 1, 1.0, false),
|
||||
WeightedItem(Items.NATURE_RUNE_561, 20, 20, 1.0, false),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
when (stage) {
|
||||
0 -> npc(FacialExpression.FRIENDLY,"WELCOME to the GREATEST QUIZ SHOW in the", "whole of ${ServerConstants.SERVER_NAME}:", "<col=8A0808>O D D</col> <col=8A088A>O N E</col> <col=08088A>O U T</col>").also { stage++ }
|
||||
1 -> player(FacialExpression.THINKING, "I'm sure I didn't ask to take part in a quiz show...").also { stage++ }
|
||||
2 -> npc(FacialExpression.FRIENDLY,"Please welcome our newest contestant:", "<col=FF0000>${player?.username}</col>!", "Just pick the O D D O N E O U T.", "Four questions right, and then you win!").also { stage++ }
|
||||
3 -> {
|
||||
setAttribute(player!!, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER, randomQuestion(player!!))
|
||||
player!!.interfaceManager.openChatbox(QUIZMASTER_INTERFACE)
|
||||
stage++
|
||||
}
|
||||
4-> {
|
||||
if (buttonID == getAttribute(player!!, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER, 0)) {
|
||||
// Correct Answer
|
||||
setAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, getAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0) + 1)
|
||||
if (getAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0) >= 4) {
|
||||
npc(FacialExpression.FRIENDLY,"<col=08088A>CONGRATULATIONS!</col>", "You are a <col=8A0808>WINNER</col>!", "Please choose your <col=08088A>PRIZE</col>!")
|
||||
stage = 5
|
||||
} else {
|
||||
npc(FacialExpression.FRIENDLY,"Wow, you're a smart one!", "You're absolutely RIGHT!", "Okay, next question!")
|
||||
stage = 3
|
||||
}
|
||||
} else {
|
||||
// Wrong Answer
|
||||
npc(FacialExpression.FRIENDLY,"WRONG!", "That's just WRONG!", "Okay, next question!")
|
||||
stage = 3
|
||||
}
|
||||
}
|
||||
// Random Item should be "Mystery Box", but the current MYSTERY_BOX_6199 is already inauthentically used by Giftmas.
|
||||
5 -> options("1000 Coins", "Random Item").also { stage++ }
|
||||
6 -> {
|
||||
resetAnimator(player!!)
|
||||
returnPlayer(player!!)
|
||||
when (buttonID) {
|
||||
1 -> {
|
||||
queueScript(player!!, 0, QueueStrength.SOFT) { stage: Int ->
|
||||
addItemOrDrop(player!!, Items.COINS_995, 1000)
|
||||
return@queueScript stopExecuting(player!!)
|
||||
}
|
||||
}
|
||||
2 -> {
|
||||
queueScript(player!!, 0, QueueStrength.SOFT) { stage: Int ->
|
||||
addItemOrDrop(player!!, tableRoll.roll()[0].id)
|
||||
return@queueScript stopExecuting(player!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
removeAttributes(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER)
|
||||
stage = END_DIALOGUE
|
||||
end()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package content.global.ame.events.quizmaster
|
||||
|
||||
import content.global.ame.RandomEventNPC
|
||||
import content.global.ame.kidnapPlayer
|
||||
import core.api.*
|
||||
import core.api.utils.WeightBasedTable
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.system.timer.impl.AntiMacro
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Sounds
|
||||
|
||||
/**
|
||||
* Quiz Master NPC:
|
||||
*
|
||||
* https://www.youtube.com/watch?v=EFAWSiPTfcM
|
||||
* https://www.youtube.com/watch?v=caWn7pE2mkE
|
||||
* https://www.youtube.com/watch?v=Bc1gAov2o4w
|
||||
* https://www.youtube.com/watch?v=oHU8-MUarxE
|
||||
* https://www.youtube.com/watch?v=wvjYiF4v9tI
|
||||
* https://www.youtube.com/watch?v=dC6rlSnXEfw
|
||||
*/
|
||||
class QuizMasterNPC(var type: String = "", override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.QUIZ_MASTER_2477) {
|
||||
override fun init() {
|
||||
super.init()
|
||||
sendChat("Hey ${player.username}! It's your lucky day!")
|
||||
queueScript(player, 4, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
lock(player, 6)
|
||||
sendGraphics(Graphics(1576, 0, 0), player.location)
|
||||
animate(player,8939)
|
||||
playAudio(player, Sounds.TELEPORT_ALL_200)
|
||||
return@queueScript delayScript(player, 3)
|
||||
}
|
||||
1 -> {
|
||||
kidnapPlayer(player, Location(1952, 4764, 1), TeleportManager.TeleportType.INSTANT)
|
||||
setAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0)
|
||||
AntiMacro.terminateEventNpc(player)
|
||||
sendGraphics(Graphics(1577, 0, 0), player.location)
|
||||
animate(player,8941)
|
||||
sendMessage(player, "Answer four questions correctly in a row to be teleported back where you came from.")
|
||||
sendMessage(player, "You will need to relog in if you lose the quiz dialog.") // Inauthentic, but there to notify the player in case.
|
||||
return@queueScript delayScript(player, 6)
|
||||
}
|
||||
2 -> {
|
||||
face(player, Location(1952, 4768, 1))
|
||||
animate(player,2378)
|
||||
// This is not needed as when you enter the QuizMasterBorders, it should fire off the dialogue
|
||||
// openDialogue(player, QuizMasterDialogueFile(), this.asNpc())
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun talkTo(npc: NPC) {
|
||||
openDialogue(player, QuizMasterDialogueFile(), this.asNpc())
|
||||
}
|
||||
}
|
||||
|
|
@ -4,17 +4,14 @@ import core.game.node.entity.Entity
|
|||
import core.game.node.entity.npc.NPC
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
import java.lang.Integer.max
|
||||
|
||||
|
||||
val ids = 391..396
|
||||
val ids = (391..396).toList()
|
||||
|
||||
class RiverTrollRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(391){
|
||||
override fun talkTo(npc: NPC) {}
|
||||
override fun init() {
|
||||
super.init()
|
||||
val index = max(0, (player.properties.combatLevel / 20) - 1)
|
||||
val id = ids.toList()[index]
|
||||
val id = idForCombatLevel(ids, player)
|
||||
this.transform(id)
|
||||
this.attack(player)
|
||||
sendChat("Fishies be mine, leave dem fishies!")
|
||||
|
|
|
|||
|
|
@ -4,17 +4,14 @@ import core.game.node.entity.Entity
|
|||
import core.game.node.entity.npc.NPC
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
import kotlin.math.max
|
||||
|
||||
|
||||
val ids = 413..418
|
||||
val ids = (413..418).toList()
|
||||
|
||||
class RockGolemRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(413){
|
||||
override fun talkTo(npc: NPC) {}
|
||||
override fun init() {
|
||||
super.init()
|
||||
val index = max(0,(player.properties.combatLevel / 20) - 1)
|
||||
val id = ids.toList()[index]
|
||||
val id = idForCombatLevel(ids, player)
|
||||
this.transform(id)
|
||||
this.attack(player)
|
||||
sendChat("Raarrrgghh! Flee human!")
|
||||
|
|
|
|||
|
|
@ -4,15 +4,13 @@ import core.game.node.entity.Entity
|
|||
import core.game.node.entity.npc.NPC
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
import kotlin.math.*
|
||||
|
||||
class ShadeRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(425){
|
||||
val ids = (425..430).toList()
|
||||
override fun talkTo(npc: NPC) {}
|
||||
override fun init() {
|
||||
super.init()
|
||||
val index = max(0, min(ids.size, (player.properties.combatLevel / 20) - 1))
|
||||
val id = ids[index]
|
||||
val id = idForCombatLevel(ids, player)
|
||||
this.transform(id)
|
||||
this.attack(player)
|
||||
sendChat("Leave this place!")
|
||||
|
|
|
|||
|
|
@ -32,4 +32,8 @@ class StrangePlantBehavior() : NPCBehavior(NPCs.STRANGE_PLANT_408) {
|
|||
override fun onDeathStarted(self: NPC, killer: Entity) {
|
||||
AntiMacro.terminateEventNpc(killer.asPlayer())
|
||||
}
|
||||
}
|
||||
|
||||
override fun getXpMultiplier(self: NPC, attacker: Entity): Double {
|
||||
return super.getXpMultiplier(self, attacker) / 16.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package content.global.ame.events.supriseexam
|
||||
package content.global.ame.events.surpriseexam
|
||||
|
||||
import core.game.component.Component
|
||||
import core.game.dialogue.FacialExpression
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package content.global.ame.events
|
||||
|
||||
import core.game.node.entity.player.Player
|
||||
import content.global.ame.events.supriseexam.SurpriseExamUtils
|
||||
import content.global.ame.events.surpriseexam.SurpriseExamUtils
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.game.system.timer.impl.AntiMacro
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package content.global.ame.events.supriseexam
|
||||
package content.global.ame.events.surpriseexam
|
||||
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.tools.END_DIALOGUE
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package content.global.ame.events.supriseexam
|
||||
package content.global.ame.events.surpriseexam
|
||||
|
||||
import core.game.node.entity.npc.NPC
|
||||
import org.rs09.consts.Components
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package content.global.ame.events.supriseexam
|
||||
package content.global.ame.events.surpriseexam
|
||||
|
||||
import core.game.component.Component
|
||||
import core.game.node.entity.player.Player
|
||||
|
|
@ -9,20 +9,22 @@ import org.rs09.consts.NPCs
|
|||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
import content.global.handlers.iface.ExperienceInterface
|
||||
import core.api.MapArea
|
||||
import core.api.removeItem
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.zone.ZoneRestriction
|
||||
|
||||
class SupriseExamListeners : InteractionListener {
|
||||
val MORDAUT = NPCs.MR_MORDAUT_6117
|
||||
val BOOK_OF_KNOWLEDGE = Items.BOOK_OF_KNOWLEDGE_11640
|
||||
class SupriseExamListeners : InteractionListener, MapArea {
|
||||
override fun defineListeners() {
|
||||
|
||||
on(MORDAUT, IntType.NPC, "talk-to"){ player, node ->
|
||||
on(NPCs.MR_MORDAUT_6117, IntType.NPC, "talk-to") { player, node ->
|
||||
player.faceLocation(Location.create(1886, 5024, 0))
|
||||
val examComplete = player.getAttribute(SurpriseExamUtils.SE_KEY_CORRECT,0) == 3
|
||||
player.dialogueInterpreter.open(MordautDialogue(examComplete),node.asNpc())
|
||||
val examComplete = player.getAttribute(SurpriseExamUtils.SE_KEY_CORRECT, 0) == 3
|
||||
player.dialogueInterpreter.open(MordautDialogue(examComplete), node.asNpc())
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(SurpriseExamUtils.SE_DOORS, IntType.SCENERY, "open"){ player, node ->
|
||||
on(SurpriseExamUtils.SE_DOORS, IntType.SCENERY, "open") { player, node ->
|
||||
val correctDoor = player.getAttribute(SurpriseExamUtils.SE_DOOR_KEY,-1)
|
||||
|
||||
if(correctDoor == -1){
|
||||
|
|
@ -39,9 +41,9 @@ class SupriseExamListeners : InteractionListener {
|
|||
return@on true
|
||||
}
|
||||
|
||||
on(BOOK_OF_KNOWLEDGE, IntType.ITEM, "read"){ player, _ ->
|
||||
player.setAttribute("caller"){skill: Int,p: Player ->
|
||||
if(p.inventory.remove(Item(BOOK_OF_KNOWLEDGE))) {
|
||||
on(Items.BOOK_OF_KNOWLEDGE_11640, IntType.ITEM, "read") { player, _ ->
|
||||
player.setAttribute("caller") { skill: Int, p: Player ->
|
||||
if (removeItem(p, Items.BOOK_OF_KNOWLEDGE_11640)) {
|
||||
val level = p.skills.getStaticLevel(skill)
|
||||
val experience = level * 15.0
|
||||
p.skills.addExperience(skill, experience)
|
||||
|
|
@ -54,8 +56,16 @@ class SupriseExamListeners : InteractionListener {
|
|||
}
|
||||
|
||||
override fun defineDestinationOverrides() {
|
||||
setDest(IntType.NPC,MORDAUT){ _, _ ->
|
||||
setDest(IntType.NPC, NPCs.MR_MORDAUT_6117) { _, _ ->
|
||||
return@setDest Location.create(1886, 5025, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineAreaBorders(): Array<ZoneBorders> {
|
||||
return arrayOf(ZoneBorders.forRegion(7502))
|
||||
}
|
||||
|
||||
override fun getRestrictions(): Array<ZoneRestriction> {
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.OFF_MAP)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,18 @@
|
|||
package content.global.ame.events.supriseexam
|
||||
package content.global.ame.events.surpriseexam
|
||||
|
||||
import content.global.ame.kidnapPlayer
|
||||
import content.global.ame.returnPlayer
|
||||
import core.api.*
|
||||
import core.game.node.entity.impl.PulseType
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.GroundItemManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.Items
|
||||
import core.ServerConstants
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
|
||||
object SurpriseExamUtils {
|
||||
|
||||
val SE_KEY_LOC = "/save:original-loc"
|
||||
val SE_KEY_INDEX = "supexam:index"
|
||||
val SE_LOGOUT_KEY = "suprise_exam"
|
||||
val SE_DOOR_KEY = "supexam:door"
|
||||
val INTER_PATTERN_CHILDS = intArrayOf(6,7,8)
|
||||
val INTER_OPTION_CHILDS = intArrayOf(10,11,12,13)
|
||||
|
|
@ -29,28 +26,16 @@ object SurpriseExamUtils {
|
|||
intArrayOf(Items.FLY_FISHING_ROD_309,Items.BARBARIAN_ROD_11323,Items.SMALL_FISHING_NET_303,Items.HARPOON_311)
|
||||
)
|
||||
|
||||
fun teleport(player: Player){
|
||||
player.setAttribute(SE_KEY_LOC,player.location)
|
||||
|
||||
registerLogoutListener(player, SE_LOGOUT_KEY){p ->
|
||||
p.location = getAttribute(p, SE_KEY_LOC, ServerConstants.HOME_LOCATION)
|
||||
}
|
||||
|
||||
player.properties.teleportLocation = Location.create(1886, 5025, 0)
|
||||
fun teleport(player: Player) {
|
||||
kidnapPlayer(player, Location.create(1886, 5025, 0), TeleportManager.TeleportType.INSTANT)
|
||||
}
|
||||
|
||||
fun cleanup(player: Player){
|
||||
player.properties.teleportLocation = player.getAttribute(SE_KEY_LOC,null)
|
||||
clearLogoutListener(player, SE_LOGOUT_KEY)
|
||||
player.removeAttribute(SE_KEY_LOC)
|
||||
player.removeAttribute(SE_KEY_INDEX)
|
||||
player.removeAttribute(SE_KEY_CORRECT)
|
||||
returnPlayer(player)
|
||||
removeAttributes(player, SE_KEY_INDEX, SE_KEY_CORRECT)
|
||||
player.pulseManager.run(object : Pulse(2){
|
||||
override fun pulse(): Boolean {
|
||||
val reward = Item(Items.BOOK_OF_KNOWLEDGE_11640)
|
||||
if(!player.inventory.add(reward)){
|
||||
GroundItemManager.create(reward,player)
|
||||
}
|
||||
addItemOrDrop(player, Items.BOOK_OF_KNOWLEDGE_11640)
|
||||
return true
|
||||
}
|
||||
}, PulseType.CUSTOM_1)
|
||||
|
|
@ -4,17 +4,14 @@ import core.game.node.entity.Entity
|
|||
import core.game.node.entity.npc.NPC
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
import kotlin.math.max
|
||||
|
||||
|
||||
val ids = 438..443
|
||||
val ids = (438..443).toList()
|
||||
|
||||
class TreeSpiritRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(438){
|
||||
override fun talkTo(npc: NPC) {}
|
||||
override fun init() {
|
||||
super.init()
|
||||
val index = max(0,(player.properties.combatLevel / 20) - 1)
|
||||
val id = ids.toList()[index]
|
||||
val id = idForCombatLevel(ids, player)
|
||||
this.transform(id)
|
||||
this.attack(player)
|
||||
sendChat("Leave these woods and never return!")
|
||||
|
|
|
|||
|
|
@ -4,15 +4,13 @@ import core.game.node.entity.Entity
|
|||
import core.game.node.entity.npc.NPC
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
import kotlin.math.*
|
||||
|
||||
class ZombieRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(419){
|
||||
val ids = (419..424).toList()
|
||||
override fun talkTo(npc: NPC) {}
|
||||
override fun init() {
|
||||
super.init()
|
||||
val index = max(0, min(ids.size, (player.properties.combatLevel / 20) - 1))
|
||||
val id = ids[index]
|
||||
val id = idForCombatLevel(ids, player)
|
||||
this.transform(id)
|
||||
this.attack(player)
|
||||
sendChat("Brainsssss!")
|
||||
|
|
|
|||
|
|
@ -12,15 +12,16 @@ import core.game.world.map.Location
|
|||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.update.flag.*
|
||||
import core.tools.RandomFunction
|
||||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import core.ServerConstants
|
||||
import core.api.log
|
||||
import core.game.bots.AIRepository
|
||||
import core.game.bots.CombatBotAssembler
|
||||
import core.game.bots.Script
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
import core.tools.Log
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.time.LocalDateTime
|
||||
|
|
@ -40,21 +41,27 @@ import kotlin.random.Random
|
|||
* @author Ceikry
|
||||
*/
|
||||
|
||||
//Adventure Bots v4.0.0 -Expansion Edition-
|
||||
// Adventure Bots v1.1.0 : Expansion Edition (Previously v4.0.0)
|
||||
// Super Grand Exchange Update
|
||||
class Adventurer(val style: CombatStyle): Script() {
|
||||
|
||||
var city: Location = lumbridge
|
||||
var ticks = 0
|
||||
var freshspawn = true
|
||||
var sold = false
|
||||
private val geloc: Location = if (Random.nextBoolean()){
|
||||
Location.create(3165, 3487, 0)
|
||||
}else{
|
||||
Location.create(3164, 3492, 0)
|
||||
}
|
||||
var poiloc: Location = karamja
|
||||
var geSocialLoc: Location = getRandomGESocialLocation()
|
||||
var geClerkLoc: Location = getRandomGELocation()
|
||||
var geClerksloc: Location = neGEClerk
|
||||
|
||||
var freshspawn: Boolean = true
|
||||
var sold: Boolean = false
|
||||
var poi: Boolean = false
|
||||
|
||||
val chance: Int = if (cityLocationsGE.contains(city)) 3500 else 3000
|
||||
var ticks: Int = 0
|
||||
var counter: Int = 0
|
||||
var random: Int = (5..30).random()
|
||||
val waitTotal: Int = 8
|
||||
var returnToAdventure: Int = 0
|
||||
var geWait: Int = 0
|
||||
var geLongWait: Int = 0
|
||||
|
||||
val type = when(style){
|
||||
CombatStyle.MELEE -> CombatBotAssembler.Type.MELEE
|
||||
|
|
@ -74,23 +81,81 @@ class Adventurer(val style: CombatStyle): Script() {
|
|||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "${bot.name} is an Adventurer bot at ${bot.location}! State: $state - City: $city"
|
||||
return "${bot.username} is an Adventurer bot " +
|
||||
"at ${bot.location}! " +
|
||||
"State: $state - " +
|
||||
"City: $city - " +
|
||||
"Ticks: $ticks - " +
|
||||
"Freshspawn: $freshspawn - " +
|
||||
"Sold: $sold - " +
|
||||
"Counter: $counter"
|
||||
}
|
||||
|
||||
var state = State.START
|
||||
|
||||
fun getRandomCity(): Location{
|
||||
private fun getRandomCity(): Location{
|
||||
return cities.random()
|
||||
}
|
||||
|
||||
fun getRandomPoi(): Location{
|
||||
private fun getRandomPoi(): Location{
|
||||
return pois.random()
|
||||
}
|
||||
|
||||
private fun getRandomGESocialLocation(): Location{
|
||||
return socialLocationsGE.random()
|
||||
}
|
||||
|
||||
private fun getRandomGELocation(): Location {
|
||||
return cityLocationsGE.random()
|
||||
}
|
||||
|
||||
private fun randomNumberFromOne(maxInt: Int): Int {
|
||||
return Random.nextInt(0, maxInt)
|
||||
}
|
||||
|
||||
private fun otherPlayersNearby(): Boolean {
|
||||
val localPlayers = RegionManager.getLocalPlayers(bot)
|
||||
val otherPlayers = localPlayers.filter { it.name != bot.name }
|
||||
return otherPlayers.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun checkNearBank() {
|
||||
if(bankMap[city] == null){
|
||||
scriptAPI.teleport(getRandomCity().also { city = it })
|
||||
} else {
|
||||
if(bankMap[city]?.insideBorder(bot) == true){
|
||||
state = State.FIND_BANK
|
||||
} else {
|
||||
bankMap[city]?.let { scriptAPI.walkTo(it.randomLoc) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkCounter(maxCounter: Int) {
|
||||
if (counter++ >= maxCounter) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
}
|
||||
|
||||
private fun teleportToRandomCity() {
|
||||
city = getRandomCity()
|
||||
when (city) {
|
||||
neGEClerk -> { scriptAPI.teleport(scriptAPI.randomizeLocationInRanges(city,-3,2,0,1,0)) }
|
||||
swGEClerk -> { scriptAPI.teleport(scriptAPI.randomizeLocationInRanges(city,-2,3,-1,0,0)) }
|
||||
nwGEBanker -> { scriptAPI.teleport(scriptAPI.randomizeLocationInRanges(city,-2,0,-3,2,0)) }
|
||||
seGEBanker -> { scriptAPI.teleport(scriptAPI.randomizeLocationInRanges(city,0,2,-2,3,0)) }
|
||||
else -> { scriptAPI.teleport(scriptAPI.randomizeLocationInRanges(city,-1,1,-1,1,0)) }
|
||||
}
|
||||
}
|
||||
|
||||
val resources = listOf(
|
||||
"Rocks","Tree","Oak","Willow",
|
||||
"Maple tree","Yew","Magic tree",
|
||||
"Teak","Mahogany")
|
||||
|
||||
//TODO: Optimise and adjust how bots handle picking up ground items further.
|
||||
fun immerse() {
|
||||
if (counter++ == 180) {state = State.TELEPORTING
|
||||
}
|
||||
if (counter++ >= Random.nextInt(150,300)) { state = State.TELEPORTING }
|
||||
val items = AIRepository.groundItems[bot]
|
||||
if (Random.nextBoolean()) {
|
||||
if (items.isNullOrEmpty()) {
|
||||
|
|
@ -98,33 +163,13 @@ class Adventurer(val style: CombatStyle): Script() {
|
|||
state = State.LOOT_DELAY
|
||||
}
|
||||
if (bot.inventory.isFull) {
|
||||
if(bankMap[city] == null){
|
||||
scriptAPI.teleport(getRandomCity().also { city = it })
|
||||
} else {
|
||||
if(bankMap[city]?.insideBorder(bot) == true){
|
||||
state = State.FIND_BANK
|
||||
} else {
|
||||
scriptAPI.walkTo(bankMap[city]?.randomLoc ?: Location(0, 0, 0))
|
||||
}
|
||||
}
|
||||
checkNearBank()
|
||||
}
|
||||
|
||||
} else {
|
||||
if (bot.inventory.isFull){
|
||||
if(bankMap[city] == null){
|
||||
scriptAPI.teleport(getRandomCity().also { city = it })
|
||||
} else {
|
||||
if(bankMap[city]?.insideBorder(bot) == true){
|
||||
state = State.FIND_BANK
|
||||
} else {
|
||||
scriptAPI.walkTo(bankMap[city]?.randomLoc ?: Location(0, 0, 0))
|
||||
}
|
||||
}
|
||||
checkNearBank()
|
||||
} else {
|
||||
val resources = listOf(
|
||||
"Rocks","Tree","Oak","Willow",
|
||||
"Maple tree","Yew","Magic tree",
|
||||
"Teak","Mahogany")
|
||||
val resource = scriptAPI.getNearestNodeFromList(resources,true)
|
||||
if(resource != null){
|
||||
if(resource.name.contains("ocks")) InteractionListeners.run(resource.id,
|
||||
|
|
@ -137,18 +182,17 @@ class Adventurer(val style: CombatStyle): Script() {
|
|||
}
|
||||
|
||||
fun refresh() {
|
||||
// log(this::class.java, Log.WARN, "${bot.username} refreshed from $state at $city with $ticks and $counter counter.")
|
||||
scriptAPI.teleport(lumbridge)
|
||||
freshspawn = true
|
||||
state = State.START
|
||||
}
|
||||
|
||||
var poi = false
|
||||
var poiloc = karamja
|
||||
|
||||
//Adventure Bots Actual Code STARTS HERE!!!
|
||||
// 100 ticks = 60 seconds
|
||||
override fun tick() {
|
||||
ticks++
|
||||
if (ticks++ >= 800) {
|
||||
// Hard refresh
|
||||
if (ticks >= 1000) {
|
||||
ticks = 0
|
||||
refresh()
|
||||
return
|
||||
|
|
@ -186,49 +230,42 @@ class Adventurer(val style: CombatStyle): Script() {
|
|||
}
|
||||
return
|
||||
} else {
|
||||
state = State.EXPLORE
|
||||
state = State.ADVENTURE
|
||||
}
|
||||
}
|
||||
|
||||
State.START -> {
|
||||
if (freshspawn) {
|
||||
freshspawn = false
|
||||
scriptAPI.randomWalkTo(lumbridge, 20)
|
||||
scriptAPI.randomWalkTo(lumbridge, randomNumberFromOne(25))
|
||||
} else {
|
||||
city = getRandomCity()
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
}
|
||||
|
||||
State.TELEPORTING -> {
|
||||
if (freshspawn){ freshspawn = false }
|
||||
teleportToRandomCity()
|
||||
poi = false
|
||||
sold = false
|
||||
ticks = 0
|
||||
counter = 0
|
||||
if (bot.location != city) {
|
||||
poi = false
|
||||
scriptAPI.teleport(city)
|
||||
} else {
|
||||
poi = false
|
||||
state = State.EXPLORE
|
||||
}
|
||||
state = State.ADVENTURE
|
||||
return
|
||||
}
|
||||
|
||||
State.EXPLORE -> {
|
||||
if (counter++ == 350) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
|
||||
val chance = if (city == ge || city == ge2) 5000 else 2500
|
||||
if (RandomFunction.random(chance) <= 10) {
|
||||
val nearbyPlayers = RegionManager.getLocalPlayers(bot)
|
||||
if (nearbyPlayers.isNotEmpty()) {
|
||||
State.ADVENTURE -> {
|
||||
checkCounter(800)
|
||||
if (randomNumberFromOne(chance) <= 10) {
|
||||
if (otherPlayersNearby()) {
|
||||
ticks = 0
|
||||
dialogue()
|
||||
}
|
||||
}
|
||||
|
||||
if (RandomFunction.random(1000) <= 150 && !poi) {
|
||||
val roamDistance = if (city != ge && city != ge2) 225 else 7
|
||||
if ((city == ge || city == ge2) && RandomFunction.random(100) < 90) {
|
||||
if (!poi && randomNumberFromOne(1000) <= 75) {
|
||||
val roamDistance = if (!cityLocationsGE.contains(city)) 225 else randomNumberFromOne(5)
|
||||
if (cityLocationsGE.contains(city) && randomNumberFromOne(100) < 90) {
|
||||
if (!bot.bank.isEmpty) {
|
||||
state = State.FIND_GE
|
||||
}
|
||||
|
|
@ -238,33 +275,46 @@ class Adventurer(val style: CombatStyle): Script() {
|
|||
return
|
||||
}
|
||||
|
||||
if (RandomFunction.random(1000) <= 50 && poi){
|
||||
if (poi && randomNumberFromOne(1000) <= 100){
|
||||
immerse()
|
||||
return
|
||||
}
|
||||
|
||||
if (poi && randomNumberFromOne(1000) <= 25){
|
||||
dialogue()
|
||||
}
|
||||
|
||||
if (poi && randomNumberFromOne(1000) <= 50){
|
||||
val roamDistancePoi = when(poiloc){
|
||||
teakfarm, crawlinghands -> 5
|
||||
treegnome -> 50
|
||||
isafdar -> 40
|
||||
eaglespeek -> 40
|
||||
keldagrimout -> 30
|
||||
teak1 -> 30
|
||||
miningguild -> 5
|
||||
magics, coal -> 7
|
||||
gemrocks, chaosnpc, chaosnpc2 -> 1
|
||||
magics, coalTrucks -> 7
|
||||
miningguild, teakfarm, crawlinghands -> 5
|
||||
varLumberYard -> 20
|
||||
keldagrimout, teak1 -> 30
|
||||
eaglespeek, isafdar -> 40
|
||||
treegnome -> 50
|
||||
else -> 60
|
||||
}
|
||||
scriptAPI.randomWalkTo(poiloc,roamDistancePoi)
|
||||
return
|
||||
}
|
||||
|
||||
if (RandomFunction.random(1000) <= 75) {
|
||||
if (city != ge && city != ge2) {
|
||||
if (randomNumberFromOne(1000) <= 75) {
|
||||
if (!cityLocationsGE.contains(city)) {
|
||||
ticks = 0
|
||||
immerse()
|
||||
return
|
||||
} else {
|
||||
return
|
||||
} else if (randomNumberFromOne(chance) <= 55 && otherPlayersNearby()) {
|
||||
ticks = 0
|
||||
dialogue()
|
||||
}
|
||||
}
|
||||
|
||||
if (RandomFunction.random(20000) <= 60 && !poi) {
|
||||
if (cityLocationsGE.contains(city) && randomNumberFromOne(1000) <= 50) {
|
||||
state = State.IDLE_GE
|
||||
}
|
||||
|
||||
if (!poi && randomNumberFromOne(1000) <= 5) {
|
||||
poiloc = getRandomPoi()
|
||||
city = teak1
|
||||
poi = true
|
||||
|
|
@ -272,26 +322,24 @@ class Adventurer(val style: CombatStyle): Script() {
|
|||
return
|
||||
}
|
||||
|
||||
if ((city == ge || city == ge2) && RandomFunction.random(1000) >= 999) {
|
||||
ticks = 0
|
||||
city = getRandomCity()
|
||||
if (cityLocationsGE.contains(city) && randomNumberFromOne(1000) <= 100) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
|
||||
if (city == ge || city == ge2) {
|
||||
return
|
||||
}
|
||||
|
||||
if (city == teak1 && counter++ >= 240){
|
||||
city = getRandomCity()
|
||||
state = State.TELEPORTING
|
||||
if (cityLocationsGE.contains(city)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (counter++ >= 240 && RandomFunction.random(100) >= 10) {
|
||||
if (poi && randomNumberFromOne(1000) <= 20){
|
||||
state = State.TELEPORTING
|
||||
return
|
||||
}
|
||||
|
||||
if (counter++ >= 750 && randomNumberFromOne(100) <= 50) {
|
||||
// log(this::class.java, Log.FINE, "${bot.username} has moved on to a different city at $ticks ticks and $counter counter.")
|
||||
city = getRandomCity()
|
||||
if (RandomFunction.random(100) % 2 == 0) {
|
||||
counter = 0
|
||||
ticks = 0
|
||||
if (randomNumberFromOne(100) % 2 == 0) {
|
||||
state = State.TELEPORTING
|
||||
} else {
|
||||
if (citygroupA.contains(city)) {
|
||||
|
|
@ -309,122 +357,122 @@ class Adventurer(val style: CombatStyle): Script() {
|
|||
return
|
||||
}
|
||||
|
||||
State.GE -> {
|
||||
var ge = false
|
||||
if (counter++ == 180) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
if (!sold) {
|
||||
if (counter++ >= 15) {
|
||||
sold = true
|
||||
ge = true
|
||||
State.IDLE_GE -> {
|
||||
returnToAdventure = Random.nextInt(350, 750)
|
||||
if (counter++ >= returnToAdventure){
|
||||
if (randomNumberFromOne(100) <= 25){
|
||||
ticks = 0
|
||||
counter = 0
|
||||
poiloc = getRandomPoi()
|
||||
city = teak1
|
||||
poi = true
|
||||
scriptAPI.teleport(poiloc)
|
||||
state = State.ADVENTURE
|
||||
return
|
||||
} else {
|
||||
counter = 0
|
||||
ticks = 0
|
||||
scriptAPI.sellAllOnGeAdv()
|
||||
state = State.TELEPORTING
|
||||
return
|
||||
}
|
||||
}
|
||||
if (cityLocationsGE.contains(city)){
|
||||
if (randomNumberFromOne(1000) <= 5) {
|
||||
ticks = 0
|
||||
geSocialLoc = scriptAPI.randomizeLocationInRanges(getRandomGESocialLocation(),-1,1,-1,1,0)
|
||||
} else if (randomNumberFromOne(1000) <= 10) {
|
||||
ticks = 0
|
||||
scriptAPI.randomWalkTo(geSocialLoc, randomNumberFromOne(5))
|
||||
return
|
||||
}
|
||||
if (randomNumberFromOne(1000) <= 5 && otherPlayersNearby()){
|
||||
ticks = 0
|
||||
dialogue()
|
||||
} else if (randomNumberFromOne(1000) <= 250){
|
||||
return
|
||||
}
|
||||
} else if (ge && sold) {
|
||||
ge = false
|
||||
city = getRandomCity()
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
State.FIND_GE -> {
|
||||
if (counter++ == 180) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
sold = false
|
||||
val ge: Scenery? = scriptAPI.getNearestNode("Desk", true) as Scenery?
|
||||
if (ge == null || bot.bank.isEmpty) state = State.EXPLORE
|
||||
if (ge == null || bot.bank.isEmpty) state = State.ADVENTURE
|
||||
class GEPulse : MovementPulse(bot, ge, DestinationFlag.OBJECT) {
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(ge?.location)
|
||||
state = State.GE
|
||||
return true
|
||||
return true.also { state = State.GE }
|
||||
}
|
||||
}
|
||||
if (ge == null || bot.bank.isEmpty) state = State.ADVENTURE
|
||||
if (ge != null && !bot.bank.isEmpty) {
|
||||
counter = 0
|
||||
scriptAPI.randomWalkTo(geloc, 3)
|
||||
GameWorld.Pulser.submit(GEPulse())
|
||||
if (randomNumberFromOne(1000) <= 25 && otherPlayersNearby()){
|
||||
dialogue()
|
||||
scriptAPI.randomWalkTo(geSocialLoc, randomNumberFromOne(5))
|
||||
} else if (randomNumberFromOne(500) <= 50) {
|
||||
GameWorld.Pulser.submit(GEPulse())
|
||||
}
|
||||
}
|
||||
checkCounter(500)
|
||||
return
|
||||
}
|
||||
|
||||
State.GE -> {
|
||||
geClerksloc = clerkLocationsGe.random()
|
||||
geWait = Random.nextInt(35, 100)
|
||||
geLongWait = Random.nextInt(350, 750)
|
||||
if (!sold) {
|
||||
if (randomNumberFromOne(500) <= 25){ scriptAPI.randomWalkTo(geClerksloc, randomNumberFromOne(4))}
|
||||
if (counter++ >= geWait) {
|
||||
scriptAPI.randomWalkTo(geClerksloc, randomNumberFromOne(1))
|
||||
sold = true
|
||||
counter = 0
|
||||
ticks = 0
|
||||
scriptAPI.sellAllOnGeAdv()
|
||||
state = State.TELEPORTING
|
||||
return
|
||||
}
|
||||
} else if (counter++ >= geLongWait) {
|
||||
state = State.TELEPORTING
|
||||
return
|
||||
}
|
||||
checkCounter(1000)
|
||||
return
|
||||
}
|
||||
|
||||
State.FIND_BANK -> {
|
||||
if (counter++ == 300) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
val bank: Scenery? = scriptAPI.getNearestNode("Bank booth", true) as Scenery?
|
||||
if (badedge.insideBorder(bot) || bot.location == badedge2 || bot.location == badedge3 || bot.location == badedge4) {
|
||||
bot.randomWalk(5, 5)
|
||||
}
|
||||
if (bank == null) state = State.EXPLORE
|
||||
class BankingPulse : MovementPulse(bot, bank, DestinationFlag.OBJECT) {
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank?.location)
|
||||
state = State.IDLE_BANKS
|
||||
return true
|
||||
}
|
||||
}
|
||||
if (bank != null) {
|
||||
bot.pulseManager.run(BankingPulse())
|
||||
if (bank == null) { state = State.TELEPORTING }
|
||||
if (bank != null && randomNumberFromOne(100) <= 5) {
|
||||
scriptAPI.depositAtBank()
|
||||
} else if (bank != null && randomNumberFromOne(100) <= 5){
|
||||
scriptAPI.randomWalkTo(bank.location,3)
|
||||
}
|
||||
checkCounter(500)
|
||||
return
|
||||
}
|
||||
|
||||
State.IDLE_BANKS -> {
|
||||
if (counter++ == 300) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
if (RandomFunction.random(1000) < 100) {
|
||||
for (item in bot.inventory.toArray()) {
|
||||
item ?: continue
|
||||
when (item.id) {
|
||||
1359, 590, 1271, 995 -> continue
|
||||
}
|
||||
bot.bank.add(item)
|
||||
bot.inventory.remove(item)
|
||||
}
|
||||
counter = 0
|
||||
state = State.EXPLORE
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
State.FIND_CITY -> {
|
||||
if (counter++ >= 600 || (city == ge || city == ge2)) {
|
||||
counter = 0
|
||||
if (counter++ >= 500 || cityLocationsGE.contains(city)){
|
||||
scriptAPI.teleport(getRandomCity().also { city = it })
|
||||
state = State.EXPLORE
|
||||
state = State.ADVENTURE
|
||||
}
|
||||
if (bot.location.equals(city)) {
|
||||
state = State.EXPLORE
|
||||
state = State.ADVENTURE
|
||||
} else {
|
||||
scriptAPI.randomWalkTo(city, 5)
|
||||
scriptAPI.randomWalkTo(city, randomNumberFromOne(10))
|
||||
}
|
||||
checkCounter(600)
|
||||
return
|
||||
}
|
||||
|
||||
State.IDLE_CITY -> {
|
||||
if (counter++ == 300) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
var random = (120..300).random()
|
||||
if (counter++ == random && RandomFunction.random(1000) % 33 == 0) {
|
||||
counter = 0
|
||||
state = State.EXPLORE
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun dialogue() {
|
||||
val localPlayer = RegionManager.getLocalPlayers(bot).random()
|
||||
val until = 1225 - dateCode
|
||||
val lineStd = dialogue.getLines("standard").rand()
|
||||
var lineAlt = ""
|
||||
|
|
@ -455,20 +503,29 @@ class Adventurer(val style: CombatStyle): Script() {
|
|||
dateCode == 404 -> lineAlt = dialogue.getLines("easter").rand()
|
||||
}
|
||||
|
||||
val chat = if (lineAlt.isNotEmpty() && Random.nextBoolean()) { lineAlt } else { lineStd }
|
||||
.replace("@name", localPlayer.username)
|
||||
.replace("@timer", until.toString())
|
||||
|
||||
scriptAPI.sendChat(chat)
|
||||
var localPlayers = RegionManager.getLocalPlayers(bot)
|
||||
if (localPlayers.isNotEmpty()) {
|
||||
val localPlayer = localPlayers
|
||||
.filter { it.name != bot.name }
|
||||
.randomOrNull()
|
||||
if (localPlayer != null) {
|
||||
val chat = if (lineAlt.isNotEmpty() && Random.nextBoolean()) { lineAlt } else { lineStd }
|
||||
.replace("@name", localPlayer.username)
|
||||
.replace("@timer", until.toString())
|
||||
scriptAPI.sendChat(chat)
|
||||
} else {
|
||||
val chat = if (lineAlt.isNotEmpty() && Random.nextBoolean()) { lineAlt } else { lineStd }
|
||||
scriptAPI.sendChat(chat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class State{
|
||||
START,
|
||||
EXPLORE,
|
||||
ADVENTURE,
|
||||
FIND_BANK,
|
||||
IDLE_BANKS,
|
||||
FIND_CITY,
|
||||
IDLE_CITY,
|
||||
IDLE_GE,
|
||||
GE,
|
||||
TELEPORTING,
|
||||
LOOT,
|
||||
|
|
@ -489,44 +546,94 @@ class Adventurer(val style: CombatStyle): Script() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
val badedge = ZoneBorders(3094, 3494, 3096, 3497)
|
||||
val badedge2 = Location.create(3094, 3492, 0)
|
||||
val badedge3 = Location.create(3094, 3490, 0)
|
||||
val badedge4 = Location.create(3094, 3494, 0)
|
||||
|
||||
// Start Cities
|
||||
val yanille: Location = Location.create(2615, 3104, 0)
|
||||
val ardougne: Location = Location.create(2662, 3304, 0)
|
||||
val seers: Location = Location.create(2726, 3485, 0)
|
||||
val edgeville: Location = Location.create(3088, 3486, 0)
|
||||
val ge: Location = Location.create(3168, 3487, 0)
|
||||
val ge2: Location = Location.create(3161, 3493, 0)
|
||||
val catherby: Location = Location.create(2809, 3435, 0)
|
||||
val falador: Location = Location.create(2965, 3380, 0)
|
||||
val varrock: Location = Location.create(3213, 3428, 0)
|
||||
val draynor: Location = Location.create(3080, 3250, 0)
|
||||
val rimmington: Location = Location.create(2977, 3239, 0)
|
||||
val lumbridge: Location = Location.create(3222, 3219, 0)
|
||||
val karamja = Location.create(2849, 3033, 0)
|
||||
val alkharid = Location.create(3297, 3219, 0)
|
||||
val feldiphills = Location.create(2535, 2919, 0)
|
||||
val isafdar = Location.create(2241, 3217, 0)
|
||||
val eaglespeek = Location.create(2333, 3579, 0)
|
||||
val canafis = Location.create(3492, 3485, 0)
|
||||
val treegnome = Location.create(2437, 3441, 0)
|
||||
val teak1 = Location.create(2334, 3048, 0)
|
||||
val teakfarm = Location.create(2825, 3085, 0)
|
||||
val keldagrimout = Location.create(2724,3692,0)
|
||||
val miningguild = Location.create(3046,9740,0)
|
||||
val magics = Location.create(2285,3146,0)
|
||||
val coal = Location.create(2581,3481,0)
|
||||
val crawlinghands = Location.create(3422,3548,0)
|
||||
val gemrocks = Location.create(2825,2997,0)
|
||||
val chaosnpc = Location.create(2612,9484,0)
|
||||
val chaosnpc2 = Location.create(2580,9501,0)
|
||||
val taverly = Location.create(2909, 3436, 0)
|
||||
val karamja: Location = Location.create(2849, 3033, 0)
|
||||
val alkharid: Location = Location.create(3297, 3219, 0)
|
||||
|
||||
// Start POI
|
||||
val feldiphills: Location = Location.create(2535, 2919, 0)
|
||||
val isafdar: Location = Location.create(2241, 3217, 0)
|
||||
val eaglespeek: Location = Location.create(2333, 3579, 0)
|
||||
val canafis: Location = Location.create(3492, 3485, 0)
|
||||
val treegnome: Location = Location.create(2437, 3441, 0)
|
||||
val teak1: Location = Location.create(2334, 3048, 0)
|
||||
val teakfarm: Location = Location.create(2825, 3085, 0)
|
||||
val keldagrimout: Location = Location.create(2724,3692, 0)
|
||||
val miningguild: Location = Location.create(3046,9740, 0)
|
||||
val magics: Location = Location.create(2285,3146, 0)
|
||||
val coalTrucks: Location = Location.create(2581,3481, 0)
|
||||
val crawlinghands: Location = Location.create(3422,3548, 0)
|
||||
val gemrocks: Location = Location.create(2825,2997, 0)
|
||||
val chaosnpc: Location = Location.create(2612,9484, 0)
|
||||
val chaosnpc2: Location = Location.create(2586, 9501, 0)
|
||||
val varLumberYard: Location = Location.create(3289, 3482, 0)
|
||||
val taverly: Location = Location.create(2909, 3436, 0)
|
||||
|
||||
val swGEClerk: Location = Location.create(3164, 3487, 0)
|
||||
val neGEClerk: Location = Location.create(3165, 3492, 0)
|
||||
val nwGEBanker: Location = Location.create(3162, 3490, 0)
|
||||
val seGEBanker: Location = Location.create(3167, 3489, 0)
|
||||
|
||||
val badedge = ZoneBorders(3094, 3494, 3096, 3497)
|
||||
val badedge2: Location = Location.create(3094, 3492, 0)
|
||||
val badedge3: Location = Location.create(3094, 3490, 0)
|
||||
val badedge4: Location = Location.create(3094, 3494, 0)
|
||||
|
||||
var citygroupA = listOf(falador, varrock, draynor, rimmington, lumbridge, edgeville)
|
||||
var citygroupB = listOf(yanille, ardougne, seers, catherby)
|
||||
|
||||
val cities = listOf(
|
||||
swGEClerk, neGEClerk, nwGEBanker, seGEBanker,
|
||||
yanille, ardougne, seers, catherby,
|
||||
falador, varrock, draynor, rimmington,
|
||||
lumbridge, edgeville
|
||||
)
|
||||
|
||||
val pois = listOf(
|
||||
karamja, karamja, alkharid,
|
||||
alkharid, feldiphills, feldiphills,
|
||||
isafdar, eaglespeek, eaglespeek,
|
||||
canafis, treegnome, treegnome,
|
||||
teak1, teakfarm, keldagrimout,
|
||||
miningguild, coalTrucks, crawlinghands,
|
||||
magics, gemrocks, chaosnpc, chaosnpc,
|
||||
chaosnpc2, taverly,
|
||||
varLumberYard)
|
||||
|
||||
val cityLocationsGE = listOf(swGEClerk, neGEClerk, nwGEBanker, seGEBanker)
|
||||
|
||||
val socialLocationsGE = listOf(
|
||||
Location.create(3158, 3483, 0),
|
||||
Location.create(3165, 3480, 0),
|
||||
Location.create(3172, 3483, 0),
|
||||
Location.create(3174, 3489, 0),
|
||||
Location.create(3171, 3497, 0),
|
||||
Location.create(3164, 3499, 0),
|
||||
Location.create(3157, 3497, 0),
|
||||
Location.create(3155, 3489, 0),
|
||||
Location.create(3167, 3492, 0),
|
||||
Location.create(3162, 3492, 0),
|
||||
Location.create(3162, 3487, 0),
|
||||
Location.create(3167, 3487, 0)
|
||||
)
|
||||
|
||||
val clerkLocationsGe = listOf(
|
||||
Location.create(3165, 3492, 0),
|
||||
Location.create(3164, 3492, 0),
|
||||
Location.create(3164, 3487, 0),
|
||||
Location.create(3165, 3487, 0)
|
||||
)
|
||||
|
||||
var bankMap = mapOf<Location, ZoneBorders>(
|
||||
falador to ZoneBorders(2950, 3374, 2943, 3368),
|
||||
varrock to ZoneBorders(3182, 3435, 3189, 3446),
|
||||
|
|
@ -538,22 +645,10 @@ class Adventurer(val style: CombatStyle): Script() {
|
|||
catherby to ZoneBorders(2807, 3438, 2811, 3441)
|
||||
)
|
||||
|
||||
val cities = listOf(yanille, ardougne, seers, catherby, falador, varrock,
|
||||
draynor, rimmington, lumbridge, ge, ge2, edgeville)
|
||||
|
||||
val pois = listOf(
|
||||
karamja, karamja, alkharid,
|
||||
alkharid, feldiphills, feldiphills,
|
||||
isafdar, eaglespeek, eaglespeek,
|
||||
canafis, treegnome, treegnome,
|
||||
teak1, teakfarm, keldagrimout,
|
||||
miningguild, coal, crawlinghands,
|
||||
magics, gemrocks, chaosnpc, chaosnpc,
|
||||
chaosnpc2, taverly)
|
||||
|
||||
private val whiteWolfMountainTop = Location(2850, 3496, 0)
|
||||
private val catherbyToTopOfWhiteWolf = arrayOf(Location(2856, 3442, 0), Location(2848, 3455, 0), Location(2848, 3471, 0), Location(2848, 3487, 0))
|
||||
private val tavleryToTopOfWhiteWolf = arrayOf(Location(2872, 3425, 0), Location(2863, 3440, 0), Location(2863, 3459, 0), Location(2854, 3475, 0), Location(2859, 3488, 0))
|
||||
|
||||
val common_stuck_locations = mapOf(
|
||||
// South of Tavlery dungeon
|
||||
ZoneBorders(2878, 3386, 2884, 3395) to { it: Adventurer ->
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ import core.api.*
|
|||
import core.game.bots.*
|
||||
import core.game.ge.GrandExchange
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.skill.Skills
|
||||
|
|
@ -16,6 +14,7 @@ import core.game.node.item.Item
|
|||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import org.rs09.consts.Items
|
||||
import content.data.Quests
|
||||
|
||||
@PlayerCompatible
|
||||
@ScriptName("Falador Cannonball Smelter")
|
||||
|
|
@ -273,6 +272,6 @@ class CannonballSmelter : Script() {
|
|||
skills.put(Skills.HITPOINTS,99)
|
||||
skills.put(Skills.DEFENCE,99)
|
||||
skills.put(Skills.SMITHING,35)
|
||||
quests.add("Dwarf Cannon")
|
||||
quests.add(Quests.DWARF_CANNON)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,18 +45,7 @@ class BankerDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin
|
|||
|
||||
2 -> showTopics(
|
||||
Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to access my bank account, please.", 10),
|
||||
IfTopic(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"I'd like to switch to my ${getBankAccountName(player, true)} bank account.",
|
||||
13,
|
||||
hasActivatedSecondaryBankAccount(player)
|
||||
),
|
||||
IfTopic(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"I'd like to open a secondary bank account.",
|
||||
20,
|
||||
!hasActivatedSecondaryBankAccount(player)
|
||||
),
|
||||
Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to switch my default bank account.", 7),
|
||||
Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to check my PIN settings.", 11),
|
||||
Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to collect items.", 12),
|
||||
Topic(core.game.dialogue.FacialExpression.ASKING, "What is this place?", 3),
|
||||
|
|
@ -78,6 +67,53 @@ class BankerDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin
|
|||
"Leave your valuables with us if you want to keep them safe."
|
||||
).also { stage = END_DIALOGUE }
|
||||
|
||||
7 -> showTopics(
|
||||
IfTopic(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"I'd like to turn on the Clan bank, please.",
|
||||
8,
|
||||
!(player.getAttribute("clanbank:enabled",false))
|
||||
),
|
||||
IfTopic(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"I'd like to turn off the Clan bank, please.",
|
||||
9,
|
||||
player.getAttribute("clanbank:enabled",false)
|
||||
),
|
||||
IfTopic(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"I'd like to switch to my ${getBankAccountName(player, true)} bank account.",
|
||||
13,
|
||||
hasActivatedSecondaryBankAccount(player)
|
||||
),
|
||||
IfTopic(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"I'd like to open a secondary bank account.",
|
||||
20,
|
||||
!hasActivatedSecondaryBankAccount(player)
|
||||
),
|
||||
)
|
||||
|
||||
8 -> {
|
||||
player.setAttribute("/save:clanbank:enabled", true)
|
||||
|
||||
npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"The Clan bank has been enabled. " +
|
||||
"If the Clan owner is online, you will access their primary bank account instead of your own."
|
||||
).also { stage = 2 }
|
||||
}
|
||||
|
||||
9 -> {
|
||||
player.removeAttribute("clanbank:enabled")
|
||||
|
||||
npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"The Clan bank has been disabled. " +
|
||||
"You will now always open your personal bank account."
|
||||
).also { stage = 2 }
|
||||
}
|
||||
|
||||
10 -> {
|
||||
openBankAccount(player)
|
||||
end()
|
||||
|
|
|
|||
|
|
@ -3,160 +3,227 @@ package content.global.dialogue
|
|||
import content.global.skill.farming.FarmerPayOptionDialogue
|
||||
import content.global.skill.farming.Farmers
|
||||
import content.global.skill.farming.FarmingPatch
|
||||
import core.game.node.entity.npc.NPC
|
||||
import content.global.skill.farming.PatchType
|
||||
import core.api.*
|
||||
import core.game.dialogue.FacialExpression
|
||||
import core.game.dialogue.IfTopic
|
||||
import core.game.dialogue.Topic
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.Items
|
||||
import core.tools.END_DIALOGUE
|
||||
import core.tools.START_DIALOGUE
|
||||
|
||||
@Initializable
|
||||
class GardenerDialoguePlugin(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) {
|
||||
override fun newInstance(player: Player?): core.game.dialogue.DialoguePlugin {
|
||||
return GardenerDialoguePlugin(player)
|
||||
}
|
||||
|
||||
override fun open(vararg args: Any?): Boolean {
|
||||
npc = args[0] as NPC
|
||||
options("Would you look after my crops for me?","Can you sell me something?")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
when(stage){
|
||||
0 -> when(buttonId){
|
||||
1 -> player("Would you look after my crops for me?").also { stage = 10 }
|
||||
2 -> player("Can you sell me something?").also { stage = 30 }
|
||||
val patches = Farmers.forId(npc.id)!!.patches
|
||||
when (stage) {
|
||||
// TODO: Can fruit trees be chopped down by the gardener too?
|
||||
START_DIALOGUE -> {
|
||||
val patch = patches[0].getPatchFor(player)
|
||||
showTopics(
|
||||
IfTopic(
|
||||
FacialExpression.ASKING,
|
||||
"Would you chop my tree down for me?",
|
||||
1000,
|
||||
patch.patch.type == PatchType.TREE_PATCH && patch.plantable != null && patch.isGrown()
|
||||
),
|
||||
IfTopic(
|
||||
FacialExpression.ASKING,
|
||||
"Would you look after my crops for me?",
|
||||
10,
|
||||
!(patch.patch.type == PatchType.TREE_PATCH && patch.plantable != null && patch.isGrown())
|
||||
),
|
||||
Topic(FacialExpression.ASKING, "Can you give me any farming advice?", 2000),
|
||||
Topic(FacialExpression.ASKING, "Can you sell me something?", 30),
|
||||
Topic(FacialExpression.NEUTRAL, "That's all, thanks.", END_DIALOGUE)
|
||||
)
|
||||
}
|
||||
|
||||
10 -> npc("I might. Which one were you thinking of?").also { stage++ }
|
||||
11 -> when(npc.id){
|
||||
Farmers.ELSTAN.id, Farmers.LYRA.id -> options("The north-western allotment.","The south-eastern allotment.").also { stage = 15 }
|
||||
Farmers.DANTAERA.id, Farmers.KRAGEN.id -> options("The north allotment.","The south allotment.").also { stage = 15 }
|
||||
else -> player("Uh, that one.").also { stage++ }
|
||||
10 -> {
|
||||
if (patches.size > 1) {
|
||||
npc("I might. Which one were you thinking of?").also { stage = 20 }
|
||||
} else {
|
||||
openPayGardenerDialogue(player, patches[0])
|
||||
}
|
||||
}
|
||||
|
||||
12 -> npc("Oh, right. My bad.").also { stage++ }
|
||||
13 -> checkPatch(player,Farmers.forId(npc.id)!!.patches[0])
|
||||
|
||||
15 -> when(buttonId){
|
||||
1 -> checkPatch(player,Farmers.forId(npc.id)!!.patches[0])
|
||||
2 -> checkPatch(player,Farmers.forId(npc.id)!!.patches[1])
|
||||
20 -> when (npc.id) {
|
||||
Farmers.ELSTAN.id, Farmers.LYRA.id -> showTopics(
|
||||
Topic(FacialExpression.NEUTRAL, "The north-western allotment.", 21),
|
||||
Topic(FacialExpression.NEUTRAL, "The south-eastern allotment.", 22)
|
||||
)
|
||||
Farmers.DANTAERA.id, Farmers.KRAGEN.id -> showTopics(
|
||||
Topic(FacialExpression.NEUTRAL, "The northern allotment.", 21),
|
||||
Topic(FacialExpression.NEUTRAL, "The southern allotment.", 22)
|
||||
)
|
||||
}
|
||||
21 -> openPayGardenerDialogue(player, patches[0])
|
||||
22 -> openPayGardenerDialogue(player, patches[1])
|
||||
|
||||
30 -> npc("That depends on whether I have it to sell.","What is it that you're looking for?").also { stage++ }
|
||||
31 -> options("Some plant cure.","A bucket of compost.","A rake.","(See more items)").also { stage = 32 }
|
||||
32 -> when(buttonId){
|
||||
1 -> player("Some plant cure.").also { stage = 100 }
|
||||
2 -> player("A bucket of compost.").also { stage = 200 }
|
||||
3 -> player("A rake.").also { stage = 300 }
|
||||
4 -> options("A watering can.","A gardening trowel.","A seed dibber.","(See previous items)").also { stage++ }
|
||||
}
|
||||
33 -> when(buttonId){
|
||||
1 -> player("A watering can.").also { stage = 400 }
|
||||
2 -> player("A gardening trowel.").also { stage = 500 }
|
||||
3 -> player("A seed dibber.").also { stage = 600 }
|
||||
4 -> options("Some plant cure.","A bucket of compost.","A rake.","(See more items)").also { stage = 32 }
|
||||
}
|
||||
30 -> npc(FacialExpression.NEUTRAL, "That depends on whether I have it to sell. What is it", "that you're looking for?").also { stage++ }
|
||||
31 -> showTopics(
|
||||
Topic(FacialExpression.NEUTRAL, "Some plant cure.", 100),
|
||||
Topic(FacialExpression.NEUTRAL, "A bucket of compost.", 200),
|
||||
Topic(FacialExpression.NEUTRAL, "A rake.", 300),
|
||||
Topic("(See more items)", 32, true)
|
||||
)
|
||||
32 -> showTopics(
|
||||
Topic(FacialExpression.NEUTRAL, "A watering can.", 400),
|
||||
Topic(FacialExpression.NEUTRAL, "A gardening trowel.", 500),
|
||||
Topic(FacialExpression.NEUTRAL, "A seed dibber.", 600),
|
||||
Topic("(See previous items)", 31, true),
|
||||
Topic(FacialExpression.NEUTRAL, "Forget it.", 40, true)
|
||||
)
|
||||
|
||||
100 -> npc("Plant cure, eh? I might have some put aside for myself.","Tell you what, I'll sell you some plant cure","for 25 gp if you like.").also { stage++ }
|
||||
101 -> options("Yes, that sounds like a fair price.","No thanks, I can get that much cheaper.").also { stage++ }
|
||||
102 -> when(buttonId){
|
||||
40 -> player("Forget it, you don't have anything I need.").also { stage = END_DIALOGUE }
|
||||
|
||||
100 -> npc("Plant cure, eh? I might have some put aside for myself.", "Tell you what. I'll sell you some plant cure for 25 gp if", "you like.").also { stage++ }
|
||||
101 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ }
|
||||
102 -> when (buttonId) {
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,25))){
|
||||
player.inventory.add(Item(Items.PLANT_CURE_6036))
|
||||
player(FacialExpression.HAPPY, "Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if (removeItem(player, Item(Items.COINS_995, 25))) {
|
||||
addItemOrDrop(player, Items.PLANT_CURE_6036)
|
||||
} else {
|
||||
player.sendMessage("You need 25 gp to pay for that.")
|
||||
sendMessage(player, "You need 25 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
200 -> npc("A bucket of compost, eh? I might have one spare...","tell you what, I'll sell it to you for 35 gp if you like.").also { stage++ }
|
||||
201 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ }
|
||||
202 -> when(buttonId){
|
||||
200 -> npc("A bucket of compost, eh? I might have one spare...", "tell you what, I'll sell it to you for 35 gp if you like.").also { stage++ }
|
||||
201 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ }
|
||||
202 -> when (buttonId) {
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,35))){
|
||||
player.inventory.add(Item(Items.COMPOST_6032))
|
||||
if (removeItem(player, Item(Items.COINS_995, 35))) {
|
||||
addItemOrDrop(player, Items.COMPOST_6032)
|
||||
} else {
|
||||
player.sendMessage("You need 35 gp to pay for that.")
|
||||
sendMessage(player, "You need 35 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
300 -> npc("A rake, eh? I might have one spare...","tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ }
|
||||
301 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ }
|
||||
302 -> when(buttonId){
|
||||
300 -> npc("A rake, eh? I might have one spare...", "tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ }
|
||||
301 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ }
|
||||
302 -> when (buttonId) {
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,15))){
|
||||
player.inventory.add(Item(Items.RAKE_5341))
|
||||
if (removeItem(player, Item(Items.COINS_995, 15))) {
|
||||
addItemOrDrop(player, Items.RAKE_5341)
|
||||
} else {
|
||||
player.sendMessage("You need 15 gp to pay for that.")
|
||||
sendMessage(player, "You need 15 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
400 -> npc("A watering can, eh? I might have one spare...","tell you what, I'll sell it to you for 25 gp if you like.").also { stage++ }
|
||||
401 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ }
|
||||
400 -> npc("A watering can, eh? I might have one spare...", "tell you what, I'll sell it to you for 25 gp if you like.").also { stage++ }
|
||||
401 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ }
|
||||
402 -> when(buttonId){
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,25))){
|
||||
player.inventory.add(Item(Items.WATERING_CAN8_5340))
|
||||
if (removeItem(player, Item(Items.COINS_995, 25))) {
|
||||
addItemOrDrop(player, Items.WATERING_CAN8_5340)
|
||||
} else {
|
||||
player.sendMessage("You need 25 gp to pay for that.")
|
||||
sendMessage(player, "You need 25 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
500 -> npc("A gardening trowel, eh? I might have one spare...","tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ }
|
||||
501 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ }
|
||||
502 -> when(buttonId){
|
||||
500 -> npc("A gardening trowel, eh? I might have one spare...", "tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ }
|
||||
501 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ }
|
||||
502 -> when (buttonId) {
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,15))){
|
||||
player.inventory.add(Item(Items.GARDENING_TROWEL_5325))
|
||||
if (removeItem(player, Item(Items.COINS_995, 15))) {
|
||||
addItemOrDrop(player, Items.GARDENING_TROWEL_5325)
|
||||
} else {
|
||||
player.sendMessage("You need 15 gp to pay for that.")
|
||||
sendMessage(player, "You need 15 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
600 -> npc("A seed dibber, eh? I might have one spare...","tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ }
|
||||
601 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ }
|
||||
602 -> when(buttonId){
|
||||
600 -> npc("A seed dibber, eh? I might have one spare...", "tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ }
|
||||
601 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ }
|
||||
602 -> when (buttonId) {
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,15))){
|
||||
player.inventory.add(Item(Items.SEED_DIBBER_5343))
|
||||
if (removeItem(player, Item(Items.COINS_995, 15))) {
|
||||
addItemOrDrop(player, Items.SEED_DIBBER_5343)
|
||||
} else {
|
||||
player.sendMessage("You need 15 gp to pay for that.")
|
||||
sendMessage(player, "You need 15 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
// Note: This dialogue changes slightly in April 2009, and significantly in December 2009
|
||||
1000 -> npc(FacialExpression.THINKING, "Why? You look like you could chop it down yourself!").also { stage++ }
|
||||
1001 -> showTopics(
|
||||
Topic(FacialExpression.NEUTRAL, "Yes, you're right - I'll do it myself.", END_DIALOGUE),
|
||||
Topic(FacialExpression.NEUTRAL, "I can't be bothered - I'd rather pay you to do it.", 1020)
|
||||
)
|
||||
|
||||
1020 -> npc(FacialExpression.NEUTRAL, "Well, it's a lot of hard work - if you pay me 200 GP", "I'll chop it down for you.").also { stage++ }
|
||||
1021 -> {
|
||||
if (inInventory(player, Items.COINS_995, 200)) {
|
||||
showTopics(
|
||||
Topic(FacialExpression.NEUTRAL, "Here's 200GP - chop my tree down please.", 1022),
|
||||
Topic(FacialExpression.NEUTRAL, "I don't want to pay that much, sorry.", END_DIALOGUE)
|
||||
)
|
||||
} else {
|
||||
player("I don't have that much money on me.").also { stage = END_DIALOGUE } // not authentic
|
||||
}
|
||||
}
|
||||
1022 -> {
|
||||
end()
|
||||
if (removeItem(player, Item(Items.COINS_995, 200))) {
|
||||
patches[0].getPatchFor(player).clear()
|
||||
}
|
||||
}
|
||||
|
||||
2000 -> {
|
||||
val advice = arrayOf(
|
||||
"There are four main Farming areas - Elstan looks after an area south of Falador, Dantaera has one to the north of Catherby, Kragen has one near Ardougne, and Lyra looks after a place in north Morytania.",
|
||||
"If you want to grow fruit trees you could try a few places: Catherby and Brimhaven have a couple of fruit tree patches, and I hear that the gnomes are big on that sort of thing.",
|
||||
"Bittercap mushrooms can only be grown in a special patch in Morytania, near the Mort Myre swamp. There the ground is especially dank and suited to growing poisonous fungi.",
|
||||
"There is a special patch for growing Belladonna - I believe it's somewhere near Draynor Manor, where the ground is a tad 'unblessed'.",
|
||||
|
||||
"Don't just throw away your weeds after you've raked a patch - put them in a compost bin and make some compost.",
|
||||
"Applying compost to a patch will not only reduce the chance that your crops will get diseased, but you will also grow more crops to harvest.",
|
||||
"Supercompost is far better than normal compost, but more expensive to make. You need to rot the right type of item; show me an item, and I'll tell you if it's super-compostable or not.",
|
||||
|
||||
"Tree seeds must be grown in a plantpot of soil into a sapling, and then transferred to a tree patch to continue growing to adulthood.",
|
||||
"You don't have to buy all your plantpots you know, you can make them yourself on a pottery wheel. If you're a good enough ${if (player!!.isMale) "craftsman" else "craftswoman"}, that is.",
|
||||
"You can fill plantpots with soil from Farming patches, if you have a gardening trowel.",
|
||||
|
||||
"Vegetables, hops and flowers are far more likely to grow healthily if you water them periodically.",
|
||||
"The only way to cure a bush or tree of disease is to prune away the diseased leaves with a pair of secateurs. For all other crops I would just apply some plant-cure.",
|
||||
"If you need to be rid of your fruit trees for any reason, all you have to do is chop them down and then dig up the stump.",
|
||||
|
||||
"You can put up to ten potatoes, cabbages or onions in vegetable sacks, although you can't have a mix in the same sack.",
|
||||
"You can put up to five tomatoes, strawberries, apples, bananas or oranges into a fruit basket, although you can't have a mix in the same basket.",
|
||||
"If you want to make your own sacks and baskets you'll need to use the loom that's near the Farming shop in Falador. If you're a good enough ${if (player!!.isMale) "craftsman" else "craftswoman"}, that is.",
|
||||
"You can buy all the farming tools from farming shops, which can be found close to the allotments.",
|
||||
|
||||
"Hops are good for brewing ales. I believe there's a brewery up in Keldagrim somewhere, and I've heard rumours that a place called Phasmatys used to be good for that type of thing. 'Fore they all died, of course.",
|
||||
)
|
||||
npcl(FacialExpression.NEUTRAL, advice.random()).also { stage = START_DIALOGUE }
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun checkPatch(player: Player,fPatch: FarmingPatch){
|
||||
if(fPatch.getPatchFor(player).isWeedy()){
|
||||
npc("You don't have anything planted in that patch.","Plant something and I might agree to look after it for you.").also { stage = END_DIALOGUE }
|
||||
} else if(fPatch.getPatchFor(player).isGrown()){
|
||||
npc("That patch is already fully grown!","I don't know what you want me to do with it!").also { stage = END_DIALOGUE }
|
||||
} else if(fPatch.getPatchFor(player).protectionPaid) {
|
||||
npc("Are you alright? You've already", "paid me for that.").also { stage = END_DIALOGUE }
|
||||
} else {
|
||||
end()
|
||||
player.dialogueInterpreter.open(FarmerPayOptionDialogue(fPatch.getPatchFor(player)),npc)
|
||||
}
|
||||
fun openPayGardenerDialogue(player: Player, fPatch: FarmingPatch) {
|
||||
end()
|
||||
openDialogue(player, FarmerPayOptionDialogue(fPatch.getPatchFor(player)), npc)
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public class ManDialoguePlugin extends DialoguePlugin {
|
|||
/**
|
||||
* The NPC ids that use this dialogue plugin.
|
||||
*/
|
||||
private static final int[] NPC_IDS = {1, 2, 3, 4, 5, 6, 16, 24, 25, 170, 351, 352, 353, 354, 359, 360, 361, 362, 363, 726, 727, 728, 729, 730, 1086, 2675, 2776, 3224, 3225, 3227, 5923, 5924,};
|
||||
private static final int[] NPC_IDS = {1, 2, 3, 4, 5, 6, 16, 24, 25, 170, 1086, 2675, 2776, 3224, 3225, 3227, 5923, 5924,};
|
||||
|
||||
public ManDialoguePlugin() {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,17 +36,21 @@ public final class ClanInterfacePlugin extends ComponentPlugin {
|
|||
switch (component.getId()) {
|
||||
case 589:
|
||||
switch (button) {
|
||||
case 9:
|
||||
if (player.getInterfaceManager().getComponent(590) != null) {
|
||||
player.getPacketDispatch().sendMessage("Please close the interface you have open before using 'Clan Setup'");
|
||||
case 9:
|
||||
if (player.getInterfaceManager().getComponent(590) != null) {
|
||||
player.getPacketDispatch().sendMessage("Please close the interface you have open before using 'Clan Setup'");
|
||||
return true;
|
||||
}
|
||||
ClanRepository.openSettings(player);
|
||||
return true;
|
||||
}
|
||||
ClanRepository.openSettings(player);
|
||||
return true;
|
||||
case 14:
|
||||
player.getDetails().getCommunication().toggleLootshare(player);
|
||||
return true;
|
||||
case 14:
|
||||
if (player.getIronmanManager().checkRestriction()) {
|
||||
return false;
|
||||
}
|
||||
player.getDetails().getCommunication().toggleLootshare(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case 590:
|
||||
final ClanRepository clan = ClanRepository.get(player.getName(), true);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import core.plugin.Initializable
|
|||
import core.plugin.Plugin
|
||||
import core.tools.Log
|
||||
import org.rs09.consts.Sounds
|
||||
import content.data.Quests
|
||||
|
||||
/**
|
||||
* Represents the experience interface.
|
||||
|
|
@ -78,15 +79,15 @@ class ExperienceInterface() : ComponentPlugin() {
|
|||
}
|
||||
|
||||
private fun checkHerblore(player: Player): Boolean{
|
||||
return (player.questRepository.isComplete("Druidic Ritual"))
|
||||
return (player.questRepository.isComplete(Quests.DRUIDIC_RITUAL))
|
||||
}
|
||||
|
||||
private fun checkSummoning(player: Player): Boolean{
|
||||
return player.questRepository.isComplete("Wolf Whistle")
|
||||
return player.questRepository.isComplete(Quests.WOLF_WHISTLE)
|
||||
}
|
||||
|
||||
private fun checkRunecrafting(player: Player): Boolean{
|
||||
return player.questRepository.isComplete("Rune Mysteries")
|
||||
return player.questRepository.isComplete(Quests.RUNE_MYSTERIES)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -2,109 +2,130 @@ package content.global.handlers.iface
|
|||
|
||||
import core.api.*
|
||||
import core.game.event.FairyRingDialEvent
|
||||
import core.game.component.Component
|
||||
import core.game.interaction.InterfaceListener
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.GameWorld
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.tools.RandomFunction
|
||||
import core.game.interaction.InterfaceListener
|
||||
import core.game.world.GameWorld
|
||||
|
||||
val RING_1 = arrayOf('a','d','c','b')
|
||||
val RING_2 = arrayOf('i','l','k','j')
|
||||
val RING_3 = arrayOf('p','s','r','q')
|
||||
import content.data.Quests
|
||||
|
||||
/**
|
||||
* Handles the fairy ring interface
|
||||
* @author Ceikry
|
||||
*/
|
||||
class FairyRingInterface : InterfaceListener {
|
||||
|
||||
val RINGS = 734
|
||||
val TRAVEL_LOG = 735
|
||||
companion object {
|
||||
const val RINGS_IFACE = 734
|
||||
const val LOG_IFACE_ID = 735
|
||||
const val VARP_F_RING = 816
|
||||
const val VB_LOG_SORT_ORDER = 4618
|
||||
const val VB_RING_1 = 2341
|
||||
const val VB_RING_2 = 2342
|
||||
const val VB_RING_3 = 2343
|
||||
val RING_1 = arrayOf('a','d','c','b')
|
||||
val RING_2 = arrayOf('i','l','k','j')
|
||||
val RING_3 = arrayOf('p','s','r','q')
|
||||
}
|
||||
|
||||
override fun defineInterfaceListeners() {
|
||||
|
||||
onOpen(RINGS){player, _ ->
|
||||
player.interfaceManager.openSingleTab(Component(TRAVEL_LOG))
|
||||
player.setAttribute("fr:ring1", 0)
|
||||
player.setAttribute("fr:ring2", 0)
|
||||
player.setAttribute("fr:ring3", 0)
|
||||
FairyRing.drawLog(player)
|
||||
onOpen(RINGS_IFACE){ player, _ ->
|
||||
openSingleTab(player, LOG_IFACE_ID)
|
||||
saveVarp(player, VARP_F_RING)
|
||||
return@onOpen true
|
||||
}
|
||||
|
||||
onClose(RINGS){player, _ ->
|
||||
closeTabInterface(player)
|
||||
player.removeAttribute("fr:ring1")
|
||||
player.removeAttribute("fr:ring2")
|
||||
player.removeAttribute("fr:ring3")
|
||||
setVarp(player, 816, 0)
|
||||
onOpen(LOG_IFACE_ID){ player, _ ->
|
||||
drawLog(player)
|
||||
return@onOpen true
|
||||
}
|
||||
|
||||
onClose(RINGS_IFACE){ player, _ ->
|
||||
closeTabInterface(player)
|
||||
return@onClose true
|
||||
}
|
||||
|
||||
on(RINGS){player, _, _, buttonID, _, _ ->
|
||||
if(player.getAttribute("fr:time",0L) > System.currentTimeMillis()) return@on true
|
||||
var delayIncrementer = 1750L
|
||||
on(RINGS_IFACE){ player, _, _, buttonID, _, _ ->
|
||||
when(buttonID){
|
||||
23 -> delayIncrementer += increment(player,1)
|
||||
25 -> delayIncrementer += increment(player,2)
|
||||
27 -> delayIncrementer += increment(player,3)
|
||||
23 -> increment(player,1)
|
||||
25 -> increment(player,2)
|
||||
27 -> increment(player,3)
|
||||
24 -> decrement(player,1)
|
||||
26 -> decrement(player,2)
|
||||
28 -> decrement(player,3)
|
||||
21 -> confirm(player)
|
||||
}
|
||||
player.setAttribute("fr:time",System.currentTimeMillis() + delayIncrementer)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(TRAVEL_LOG,12){player, _, _, _, _, _ ->
|
||||
on(LOG_IFACE_ID,12){ player, _, _, _, _, _ ->
|
||||
toggleSortOrder(player)
|
||||
return@on true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun toggleSortOrder(player: Player): Long{
|
||||
val ring1index = player.getAttribute("fr:ring1",0)
|
||||
var toSet = player.getAttribute("fr:sortorder",true)
|
||||
toSet = !toSet
|
||||
player.setAttribute("fr:sortorder",toSet)
|
||||
if(toSet) {
|
||||
setVarp(player, 816, ring1index)
|
||||
player.setAttribute("fr:ring2",0)
|
||||
player.setAttribute("fr:ring3",0)
|
||||
/**
|
||||
* Draws the travel log interface
|
||||
* Currently, the visited logs is a bool array in globalData. Someone should migrate this to prefs or something at some point.
|
||||
* On transmit of Varp 816, which all used varbits are part of here, the CS2 is invoked to populate the codes in the log and sort them correctly.
|
||||
* @param player The player to draw the interface for
|
||||
*/
|
||||
private fun drawLog (player: Player)
|
||||
{
|
||||
for (i in FairyRing.values().indices) {
|
||||
/* Snowscape: show all fairy ring destinations, whether they have been there or not.
|
||||
if (!player.savedData.globalData.hasTravelLog(i)) {
|
||||
continue
|
||||
}
|
||||
*/
|
||||
val ring = FairyRing.values()[i]
|
||||
if (ring.childId == -1) {
|
||||
continue
|
||||
}
|
||||
setInterfaceText(player, "<br>${ring.tip}", LOG_IFACE_ID, ring.childId)
|
||||
}
|
||||
return -1750L
|
||||
}
|
||||
|
||||
fun increment(player: Player,ring: Int): Long{
|
||||
val curIndex = player.getAttribute("fr:ring$ring",0)
|
||||
var nextIndex = 0
|
||||
if(curIndex == 3) nextIndex = 0
|
||||
else if(curIndex == 1) nextIndex = 3
|
||||
else if(curIndex == 2) nextIndex = 2
|
||||
else nextIndex = curIndex + 1
|
||||
player.setAttribute("fr:ring$ring",nextIndex)
|
||||
return if (curIndex == 1) 1750L else 0L
|
||||
private fun toggleSortOrder(player: Player) {
|
||||
val curSort = getVarbit(player, VB_LOG_SORT_ORDER) == 0
|
||||
setVarbit(player, VB_LOG_SORT_ORDER, if (curSort) 1 else 0)
|
||||
drawLog(player)
|
||||
}
|
||||
|
||||
fun increment(player: Player,ring: Int) {
|
||||
val vbit = when(ring) {
|
||||
1 -> VB_RING_1
|
||||
2 -> VB_RING_2
|
||||
3 -> VB_RING_3
|
||||
else -> return
|
||||
}
|
||||
val curIndex = getVarbit(player, vbit)
|
||||
val nextIndex: Int = if(curIndex == 3) 0
|
||||
else curIndex + 1
|
||||
setVarbit(player, vbit, nextIndex)
|
||||
}
|
||||
|
||||
fun decrement(player: Player,ring: Int){
|
||||
val curIndex = player.getAttribute("fr:ring$ring",0)
|
||||
var nextIndex = 0
|
||||
if(curIndex == 0) nextIndex = 3
|
||||
else nextIndex = curIndex - 1
|
||||
player.setAttribute("fr:ring$ring",nextIndex)
|
||||
val vbit = when(ring) {
|
||||
1 -> VB_RING_1
|
||||
2 -> VB_RING_2
|
||||
3 -> VB_RING_3
|
||||
else -> return
|
||||
}
|
||||
val curIndex = getVarbit(player, vbit)
|
||||
val nextIndex: Int = if(curIndex == 0) 3
|
||||
else curIndex - 1
|
||||
setVarbit(player, vbit, nextIndex)
|
||||
}
|
||||
|
||||
private fun confirm(player: Player){
|
||||
val ring1index = player.getAttribute("fr:ring1",0)
|
||||
val ring2index = player.getAttribute("fr:ring2",0)
|
||||
val ring3index = player.getAttribute("fr:ring3",0)
|
||||
val ring1index = getVarbit(player, VB_RING_1)
|
||||
val ring2index = getVarbit(player, VB_RING_2)
|
||||
val ring3index = getVarbit(player, VB_RING_3)
|
||||
val code = "${RING_1[ring1index]}${RING_2[ring2index]}${RING_3[ring3index]}"
|
||||
val ring: FairyRing? = try {
|
||||
FairyRing.valueOf(code.uppercase())
|
||||
|
|
@ -160,7 +181,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int
|
|||
AKS(Location.create(2571, 2956, 0), "Feldip Hills: Jungle Hunter area", 25),
|
||||
ALQ(Location.create(3597, 3495, 0), "Morytania: Haunted Woods east of Canifis", 27) {
|
||||
override fun checkAccess(player: Player) : Boolean {
|
||||
return requireQuest(player, "Priest in Peril", "to use this ring.")
|
||||
return requireQuest(player, Quests.PRIEST_IN_PERIL, "to use this ring.")
|
||||
}
|
||||
},
|
||||
ALS(Location.create(2644, 3495, 0), "Kandarin: McGrubor's Wood", 29),
|
||||
|
|
@ -172,7 +193,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int
|
|||
BKQ(Location.create(3041, 4532, 0), "Other realms: Enchanted Valley", 39),
|
||||
BKR(Location.create(3469, 3431, 0), "Morytania: Mort Myre, south of Canifis", 40) {
|
||||
override fun checkAccess(player: Player) : Boolean {
|
||||
return requireQuest(player, "Priest in Peril", "to use this ring.")
|
||||
return requireQuest(player, Quests.PRIEST_IN_PERIL, "to use this ring.")
|
||||
}
|
||||
},
|
||||
BLP(Location.create(2437, 5126, 0), "Dungeons: TzHaar area", 42),
|
||||
|
|
@ -180,7 +201,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int
|
|||
BLR(Location.create(2740, 3351, 0), "Kandarin: Legends' Guild", 44),
|
||||
CIP(Location.create(2513, 3884, 0), "Islands: Miscellania", 46) {
|
||||
override fun checkAccess(player: Player): Boolean {
|
||||
return requireQuest(player, "Fremennik Trials", "to use this ring.")
|
||||
return requireQuest(player, Quests.THE_FREMENNIK_TRIALS, "to use this ring.")
|
||||
}
|
||||
},
|
||||
CIQ(Location.create(2528, 3127, 0), "Kandarin: North-west of Yanille", 47),
|
||||
|
|
@ -189,7 +210,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int
|
|||
CKR(Location.create(2801, 3003, 0), "Karamja: South of Tai Bwo Wannai Village", 56),
|
||||
CKS(Location.create(3447, 3470, 0), "Morytania: Canifis", 57) {
|
||||
override fun checkAccess(player: Player) : Boolean {
|
||||
return requireQuest(player, "Priest in Peril", "to use this ring.")
|
||||
return requireQuest(player, Quests.PRIEST_IN_PERIL, "to use this ring.")
|
||||
}
|
||||
},
|
||||
CLP(Location.create(3082, 3206, 0), "Islands: South of Draynor Village", 58),
|
||||
|
|
@ -208,23 +229,4 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int
|
|||
open fun checkAccess(player: Player) : Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Draws the travel log.
|
||||
* @param player the player.
|
||||
*/
|
||||
fun drawLog(player: Player) {
|
||||
for (i in FairyRing.values().indices) {
|
||||
if (!player.savedData.globalData.hasTravelLog(i)) {
|
||||
continue
|
||||
}
|
||||
val ring = FairyRing.values()[i]
|
||||
if (ring.childId == -1) {
|
||||
continue
|
||||
}
|
||||
setInterfaceText(player, "<br>${ring.tip}", 735, ring.childId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ public final class JewelleryInterface extends ComponentPlugin {
|
|||
amount = 5;
|
||||
break;
|
||||
case 124:
|
||||
/* No need to calculate the maximum amount here, because the make() function will perform that step
|
||||
if (data.name().contains("GOLD")) {
|
||||
amount = player.getInventory().getAmount(new Item(GOLD_BAR));
|
||||
} else {
|
||||
|
|
@ -178,6 +179,8 @@ public final class JewelleryInterface extends ComponentPlugin {
|
|||
amount = first;
|
||||
}
|
||||
}
|
||||
*/
|
||||
amount = 99;
|
||||
break;
|
||||
case 199:
|
||||
final JewelleryItem d = data;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
|||
import core.game.world.GameWorld;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
import content.data.Quests;
|
||||
import static core.api.ContentAPIKt.hasRequirement;
|
||||
|
||||
/**
|
||||
* Represents the magic book interface handling of non-combat spells.
|
||||
* @author 'Vexia
|
||||
|
|
@ -42,9 +45,44 @@ public final class MagicBookInterface extends ComponentPlugin {
|
|||
? SpellBook.ANCIENT
|
||||
: SpellBook.LUNAR;
|
||||
|
||||
// Snowscape: Allow switching between unlocked spellbooks with the magic interface sort buttons
|
||||
if (spellBook == SpellBook.MODERN) {
|
||||
if (button == 65 && swapSpellBook(player, SpellBook.ANCIENT)) {
|
||||
return true;
|
||||
} else if (button == 66 && swapSpellBook(player, SpellBook.LUNAR)) {
|
||||
return true;
|
||||
}
|
||||
} else if (spellBook == SpellBook.ANCIENT) {
|
||||
if (button == 29 && swapSpellBook(player, SpellBook.MODERN)) {
|
||||
return true;
|
||||
} else if (button == 31 && swapSpellBook(player, SpellBook.LUNAR)) {
|
||||
return true;
|
||||
}
|
||||
} else if (spellBook == SpellBook.LUNAR) {
|
||||
if (button == 40 && swapSpellBook(player, SpellBook.MODERN)) {
|
||||
return true;
|
||||
} else if (button == 41 && swapSpellBook(player, SpellBook.ANCIENT)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SpellListeners.run(button, SpellListener.NONE, SpellUtils.getBookFromInterface(component.getId()),player,null);
|
||||
boolean result = MagicSpell.castSpell(player, spellBook, button, player);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Snowscape custom function
|
||||
private boolean swapSpellBook(final Player player, SpellBook spellBook) {
|
||||
if (spellBook == SpellBook.ANCIENT && !hasRequirement(player, Quests.DESERT_TREASURE)) {
|
||||
return false;
|
||||
} else if (spellBook == SpellBook.LUNAR && !hasRequirement(player, Quests.LUNAR_DIPLOMACY)) {
|
||||
return false;
|
||||
}
|
||||
player.getSpellBookManager().setSpellBook(spellBook);
|
||||
player.getSpellBookManager().update(player);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import core.plugin.Initializable;
|
|||
import core.plugin.Plugin;
|
||||
|
||||
import static core.api.ContentAPIKt.hasRequirement;
|
||||
import content.data.Quests;
|
||||
|
||||
/**
|
||||
* Represents the prayer interface.
|
||||
|
|
@ -27,7 +28,7 @@ public final class PrayerTabInterface extends ComponentPlugin {
|
|||
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
|
||||
final PrayerType type = PrayerType.get(button);
|
||||
if (type == PrayerType.CHIVALRY || type == PrayerType.PIETY)
|
||||
if (!hasRequirement(player, "King's Ransom"))
|
||||
if (!hasRequirement(player, Quests.KINGS_RANSOM))
|
||||
return true;
|
||||
if (type == null) {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -10,12 +10,13 @@ import kotlin.math.*
|
|||
import java.util.*
|
||||
|
||||
import org.rs09.consts.*
|
||||
import content.data.Quests
|
||||
|
||||
object QuestTabUtils {
|
||||
@JvmStatic
|
||||
fun showRequirementsInterface (player: Player, button: Int) {
|
||||
val questName = getNameForButton (button)
|
||||
val questReq = QuestRequirements.values().filter { it.questName.equals(questName, true) }.firstOrNull() ?: return
|
||||
fun showRequirementsInterface(player: Player, button: Int) {
|
||||
val questName = getNameForButton(button)
|
||||
val questReq = QuestRequirements.values().filter { it.quest.questName == questName }.firstOrNull() ?: return
|
||||
var (isMet, unmetReqs) = QuestReq(questReq).evaluate(player)
|
||||
|
||||
var messageList = ArrayList<String>()
|
||||
|
|
@ -27,7 +28,7 @@ object QuestTabUtils {
|
|||
closeInterface(player)
|
||||
for (req in unmetReqs) {
|
||||
if (req is QuestReq)
|
||||
questList.add(req.questReq.questName)
|
||||
questList.add(req.questReq.quest.questName)
|
||||
else if (req is SkillReq) {
|
||||
if (statMap[req.skillId] == null || (statMap[req.skillId] != null && statMap[req.skillId]!! < req.level))
|
||||
statMap[req.skillId] = req.level
|
||||
|
|
@ -82,163 +83,163 @@ object QuestTabUtils {
|
|||
openInterface(player, Components.QUESTJOURNAL_SCROLL_275)
|
||||
}
|
||||
|
||||
fun getNameForButton (button: Int) : String {
|
||||
val name = when (button) {
|
||||
10 -> "Myths of the White Lands"
|
||||
11 -> "Myths of the White Lands"
|
||||
private fun getNameForButton(button: Int) : String {
|
||||
val quest = when (button) {
|
||||
10 -> Quests.MYTHS_OF_THE_WHITE_LANDS.questName
|
||||
11 -> Quests.MYTHS_OF_THE_WHITE_LANDS.questName
|
||||
12 -> "Free Quests"
|
||||
13 -> "Black Knights' Fortress"
|
||||
14 -> "Cook's Assistant"
|
||||
15 -> "Demon Slayer"
|
||||
16 -> "Doric's Quest"
|
||||
17 -> "Dragon Slayer"
|
||||
18 -> "Ernest the Chicken"
|
||||
19 -> "Goblin Diplomacy"
|
||||
20 -> "Imp Catcher"
|
||||
21 -> "The Knight's Sword"
|
||||
22 -> "Pirate's Treasure"
|
||||
23 -> "Prince Ali Rescue"
|
||||
24 -> "The Restless Ghost"
|
||||
25 -> "Romeo & Juliet"
|
||||
26 -> "Rune Mysteries"
|
||||
27 -> "Sheep Shearer"
|
||||
28 -> "Shield of Arrav"
|
||||
29 -> "Vampire Slayer"
|
||||
30 -> "Witch's Potion"
|
||||
13 -> Quests.BLACK_KNIGHTS_FORTRESS.questName
|
||||
14 -> Quests.COOKS_ASSISTANT.questName
|
||||
15 -> Quests.DEMON_SLAYER.questName
|
||||
16 -> Quests.DORICS_QUEST.questName
|
||||
17 -> Quests.DRAGON_SLAYER.questName
|
||||
18 -> Quests.ERNEST_THE_CHICKEN.questName
|
||||
19 -> Quests.GOBLIN_DIPLOMACY.questName
|
||||
20 -> Quests.IMP_CATCHER.questName
|
||||
21 -> Quests.THE_KNIGHTS_SWORD.questName
|
||||
22 -> Quests.PIRATES_TREASURE.questName
|
||||
23 -> Quests.PRINCE_ALI_RESCUE.questName
|
||||
24 -> Quests.THE_RESTLESS_GHOST.questName
|
||||
25 -> Quests.ROMEO_JULIET.questName
|
||||
26 -> Quests.RUNE_MYSTERIES.questName
|
||||
27 -> Quests.SHEEP_SHEARER.questName
|
||||
28 -> Quests.SHIELD_OF_ARRAV.questName
|
||||
29 -> Quests.VAMPIRE_SLAYER.questName
|
||||
30 -> Quests.WITCHS_POTION.questName
|
||||
31 -> "Members' Quests"
|
||||
32 -> "Animal Magnetism"
|
||||
33 -> "Between a Rock..."
|
||||
34 -> "Big Chompy Bird Hunting"
|
||||
35 -> "Biohazard"
|
||||
36 -> "Cabin Fever"
|
||||
37 -> "Clock Tower"
|
||||
38 -> "Contact!"
|
||||
39 -> "Zogre Flesh Eaters"
|
||||
40 -> "Creature of Fenkenstrain"
|
||||
41 -> "Darkness of Hallowvale"
|
||||
42 -> "Death to the Dorgeshuun"
|
||||
43 -> "Death Plateau"
|
||||
44 -> "Desert Treasure"
|
||||
45 -> "Devious Minds"
|
||||
46 -> "The Dig Site"
|
||||
47 -> "Druidic Ritual"
|
||||
48 -> "Dwarf Cannon"
|
||||
49 -> "Eadgar's Ruse"
|
||||
50 -> "Eagles' Peak"
|
||||
51 -> "Elemental Workshop I"
|
||||
52 -> "Elemental Workshop II"
|
||||
53 -> "Enakhra's Lament"
|
||||
54 -> "Enlightened Journey"
|
||||
55 -> "The Eyes of Glouphrie"
|
||||
56 -> "Fairytale I - Growing Pains"
|
||||
57 -> "Fairytale II - Cure a Queen"
|
||||
58 -> "Family Crest"
|
||||
59 -> "The Feud"
|
||||
60 -> "Fight Arena"
|
||||
61 -> "Fishing Contest"
|
||||
62 -> "Forgettable Tale..."
|
||||
63 -> "The Fremennik Trials"
|
||||
64 -> "Waterfall Quest"
|
||||
65 -> "Garden of Tranquillity"
|
||||
66 -> "Gertrude's Cat"
|
||||
67 -> "Ghosts Ahoy"
|
||||
68 -> "The Giant Dwarf"
|
||||
69 -> "The Golem"
|
||||
70 -> "The Grand Tree"
|
||||
71 -> "The Hand in the Sand"
|
||||
72 -> "Haunted Mine"
|
||||
73 -> "Hazeel Cult"
|
||||
74 -> "Heroes' Quest"
|
||||
75 -> "Holy Grail"
|
||||
76 -> "Horror from the Deep"
|
||||
77 -> "Icthlarin's Little Helper"
|
||||
78 -> "In Aid of the Myreque"
|
||||
79 -> "In Search of the Myreque"
|
||||
80 -> "Jungle Potion"
|
||||
81 -> "Legend's Quest"
|
||||
82 -> "Lost City"
|
||||
83 -> "The Lost Tribe"
|
||||
84 -> "Lunar Diplomacy"
|
||||
85 -> "Making History"
|
||||
86 -> "Merlin's Crystal"
|
||||
87 -> "Monkey Madness"
|
||||
88 -> "Monk's Friend"
|
||||
89 -> "Mountain Daughter"
|
||||
90 -> "Mourning's End Part I"
|
||||
91 -> "Mourning's End Part II"
|
||||
92 -> "Murder Mystery"
|
||||
93 -> "My Arm's Big Adventure"
|
||||
94 -> "Nature Spirit"
|
||||
95 -> "Observatory Quest"
|
||||
96 -> "One Small Favour"
|
||||
97 -> "Plague City"
|
||||
98 -> "Priest in Peril"
|
||||
99 -> "Rag and Bone Man"
|
||||
100 -> "Ratcatchers"
|
||||
101 -> "Recipe for Disaster"
|
||||
102 -> "Recruitment Drive"
|
||||
103 -> "Regicide"
|
||||
104 -> "Roving Elves"
|
||||
105 -> "Royal Trouble"
|
||||
106 -> "Rum Deal"
|
||||
107 -> "Scorpion Catcher"
|
||||
108 -> "Sea Slug"
|
||||
109 -> "The Slug Menace"
|
||||
110 -> "Shades of Mort'ton"
|
||||
111 -> "Shadow of the Storm"
|
||||
112 -> "Sheep Herder"
|
||||
113 -> "Shilo Village"
|
||||
114 -> "A Soul's Bane"
|
||||
115 -> "Spirits of the Elid"
|
||||
116 -> "Swan Song"
|
||||
117 -> "Tai Bwo Wannai Trio"
|
||||
118 -> "A Tail of Two Cats"
|
||||
119 -> "Tears of Guthix"
|
||||
120 -> "Temple of Ikov"
|
||||
121 -> "Throne of Miscellania"
|
||||
122 -> "The Tourist Trap"
|
||||
123 -> "Witch's House"
|
||||
124 -> "Tree Gnome Village"
|
||||
125 -> "Tribal Totem"
|
||||
126 -> "Troll Romance"
|
||||
127 -> "Troll Stronghold"
|
||||
128 -> "Underground Pass"
|
||||
129 -> "Wanted!"
|
||||
130 -> "Watchtower"
|
||||
131 -> "Cold War"
|
||||
132 -> "The Fremennik Isles"
|
||||
133 -> "Tower of Life"
|
||||
134 -> "The Great Brain Robbery"
|
||||
135 -> "What Lies Below"
|
||||
136 -> "Olaf's Quest"
|
||||
137 -> "Another Slice of H.A.M"
|
||||
138 -> "Dream Mentor"
|
||||
139 -> "Grim Tales"
|
||||
140 -> "King's Ransom"
|
||||
141 -> "The Path of Glouphrie"
|
||||
142 -> "Back to my Roots"
|
||||
143 -> "Land of the Goblins"
|
||||
144 -> "Dealing with Scabaras"
|
||||
145 -> "Wolf Whistle"
|
||||
146 -> "As a First Resort..."
|
||||
147 -> "Catapult Construction"
|
||||
148 -> "Kennith's Concerns"
|
||||
149 -> "Legacy of Seergaze"
|
||||
150 -> "Perils of Ice Mountain"
|
||||
151 -> "TokTz-Ket-Dill"
|
||||
152 -> "Smoking Kills"
|
||||
153 -> "Rocking Out"
|
||||
154 -> "Spirit of Summer"
|
||||
155 -> "Meeting History"
|
||||
156 -> "All Fired Up"
|
||||
157 -> "Summer's End"
|
||||
158 -> "Defender of Varrock"
|
||||
159 -> "Swept Away"
|
||||
160 -> "While Guthix Sleeps"
|
||||
161 -> "In Pyre Need"
|
||||
162 -> "Myths of the White Lands"
|
||||
32 -> Quests.ANIMAL_MAGNETISM.questName
|
||||
33 -> Quests.BETWEEN_A_ROCK.questName
|
||||
34 -> Quests.BIG_CHOMPY_BIRD_HUNTING.questName
|
||||
35 -> Quests.BIOHAZARD.questName
|
||||
36 -> Quests.CABIN_FEVER.questName
|
||||
37 -> Quests.CLOCK_TOWER.questName
|
||||
38 -> Quests.CONTACT.questName
|
||||
39 -> Quests.ZOGRE_FLESH_EATERS.questName
|
||||
40 -> Quests.CREATURE_OF_FENKENSTRAIN.questName
|
||||
41 -> Quests.DARKNESS_OF_HALLOWVALE.questName
|
||||
42 -> Quests.DEATH_TO_THE_DORGESHUUN.questName
|
||||
43 -> Quests.DEATH_PLATEAU.questName
|
||||
44 -> Quests.DESERT_TREASURE.questName
|
||||
45 -> Quests.DEVIOUS_MINDS.questName
|
||||
46 -> Quests.THE_DIG_SITE.questName
|
||||
47 -> Quests.DRUIDIC_RITUAL.questName
|
||||
48 -> Quests.DWARF_CANNON.questName
|
||||
49 -> Quests.EADGARS_RUSE.questName
|
||||
50 -> Quests.EAGLES_PEAK.questName
|
||||
51 -> Quests.ELEMENTAL_WORKSHOP_I.questName
|
||||
52 -> Quests.ELEMENTAL_WORKSHOP_II.questName
|
||||
53 -> Quests.ENAKHRAS_LAMENT.questName
|
||||
54 -> Quests.ENLIGHTENED_JOURNEY.questName
|
||||
55 -> Quests.THE_EYES_OF_GLOUPHRIE.questName
|
||||
56 -> Quests.FAIRYTALE_I_GROWING_PAINS.questName
|
||||
57 -> Quests.FAIRYTALE_II_CURE_A_QUEEN.questName
|
||||
58 -> Quests.FAMILY_CREST.questName
|
||||
59 -> Quests.THE_FEUD.questName
|
||||
60 -> Quests.FIGHT_ARENA.questName
|
||||
61 -> Quests.FISHING_CONTEST.questName
|
||||
62 -> Quests.FORGETTABLE_TALE.questName
|
||||
63 -> Quests.THE_FREMENNIK_TRIALS.questName
|
||||
64 -> Quests.WATERFALL_QUEST.questName
|
||||
65 -> Quests.GARDEN_OF_TRANQUILITY.questName
|
||||
66 -> Quests.GERTRUDES_CAT.questName
|
||||
67 -> Quests.GHOSTS_AHOY.questName
|
||||
68 -> Quests.THE_GIANT_DWARF.questName
|
||||
69 -> Quests.THE_GOLEM.questName
|
||||
70 -> Quests.THE_GRAND_TREE.questName
|
||||
71 -> Quests.THE_HAND_IN_THE_SAND.questName
|
||||
72 -> Quests.HAUNTED_MINE.questName
|
||||
73 -> Quests.HAZEEL_CULT.questName
|
||||
74 -> Quests.HEROES_QUEST.questName
|
||||
75 -> Quests.HOLY_GRAIL.questName
|
||||
76 -> Quests.HORROR_FROM_THE_DEEP.questName
|
||||
77 -> Quests.ICTHLARINS_LITTLE_HELPER.questName
|
||||
78 -> Quests.IN_AID_OF_THE_MYREQUE.questName
|
||||
79 -> Quests.IN_SEARCH_OF_THE_MYREQUE.questName
|
||||
80 -> Quests.JUNGLE_POTION.questName
|
||||
81 -> Quests.LEGENDS_QUEST.questName
|
||||
82 -> Quests.LOST_CITY.questName
|
||||
83 -> Quests.THE_LOST_TRIBE.questName
|
||||
84 -> Quests.LUNAR_DIPLOMACY.questName
|
||||
85 -> Quests.MAKING_HISTORY.questName
|
||||
86 -> Quests.MERLINS_CRYSTAL.questName
|
||||
87 -> Quests.MONKEY_MADNESS.questName
|
||||
88 -> Quests.MONKS_FRIEND.questName
|
||||
89 -> Quests.MOUNTAIN_DAUGHTER.questName
|
||||
90 -> Quests.MOURNINGS_END_PART_I.questName
|
||||
91 -> Quests.MOURNINGS_END_PART_II.questName
|
||||
92 -> Quests.MURDER_MYSTERY.questName
|
||||
93 -> Quests.MY_ARMS_BIG_ADVENTURE.questName
|
||||
94 -> Quests.NATURE_SPIRIT.questName
|
||||
95 -> Quests.OBSERVATORY_QUEST.questName
|
||||
96 -> Quests.ONE_SMALL_FAVOUR.questName
|
||||
97 -> Quests.PLAGUE_CITY.questName
|
||||
98 -> Quests.PRIEST_IN_PERIL.questName
|
||||
99 -> Quests.RAG_AND_BONE_MAN.questName
|
||||
100 -> Quests.RATCATCHERS.questName
|
||||
101 -> Quests.RECIPE_FOR_DISASTER.questName
|
||||
102 -> Quests.RECRUITMENT_DRIVE.questName
|
||||
103 -> Quests.REGICIDE.questName
|
||||
104 -> Quests.ROVING_ELVES.questName
|
||||
105 -> Quests.ROYAL_TROUBLE.questName
|
||||
106 -> Quests.RUM_DEAL.questName
|
||||
107 -> Quests.SCORPION_CATCHER.questName
|
||||
108 -> Quests.SEA_SLUG.questName
|
||||
109 -> Quests.THE_SLUG_MENACE.questName
|
||||
110 -> Quests.SHADES_OF_MORTTON.questName
|
||||
111 -> Quests.SHADOW_OF_THE_STORM.questName
|
||||
112 -> Quests.SHEEP_HERDER.questName
|
||||
113 -> Quests.SHILO_VILLAGE.questName
|
||||
114 -> Quests.A_SOULS_BANE.questName
|
||||
115 -> Quests.SPIRITS_OF_THE_ELID.questName
|
||||
116 -> Quests.SWAN_SONG.questName
|
||||
117 -> Quests.TAI_BWO_WANNAI_TRIO.questName
|
||||
118 -> Quests.A_TAIL_OF_TWO_CATS.questName
|
||||
119 -> Quests.TEARS_OF_GUTHIX.questName
|
||||
120 -> Quests.TEMPLE_OF_IKOV.questName
|
||||
121 -> Quests.THRONE_OF_MISCELLANIA.questName
|
||||
122 -> Quests.THE_TOURIST_TRAP.questName
|
||||
123 -> Quests.WITCHS_HOUSE.questName
|
||||
124 -> Quests.TREE_GNOME_VILLAGE.questName
|
||||
125 -> Quests.TRIBAL_TOTEM.questName
|
||||
126 -> Quests.TROLL_ROMANCE.questName
|
||||
127 -> Quests.TROLL_STRONGHOLD.questName
|
||||
128 -> Quests.UNDERGROUND_PASS.questName
|
||||
129 -> Quests.WANTED.questName
|
||||
130 -> Quests.WATCHTOWER.questName
|
||||
131 -> Quests.COLD_WAR.questName
|
||||
132 -> Quests.THE_FREMENNIK_ISLES.questName
|
||||
133 -> Quests.TOWER_OF_LIFE.questName
|
||||
134 -> Quests.THE_GREAT_BRAIN_ROBBERY.questName
|
||||
135 -> Quests.WHAT_LIES_BELOW.questName
|
||||
136 -> Quests.OLAFS_QUEST.questName
|
||||
137 -> Quests.ANOTHER_SLICE_OF_HAM.questName
|
||||
138 -> Quests.DREAM_MENTOR.questName
|
||||
139 -> Quests.GRIM_TALES.questName
|
||||
140 -> Quests.KINGS_RANSOM.questName
|
||||
141 -> Quests.THE_PATH_OF_GLOUPHRIE.questName
|
||||
142 -> Quests.BACK_TO_MY_ROOTS.questName
|
||||
143 -> Quests.LAND_OF_THE_GOBLINS.questName
|
||||
144 -> Quests.DEALING_WITH_SCABARAS.questName
|
||||
145 -> Quests.WOLF_WHISTLE.questName
|
||||
146 -> Quests.AS_A_FIRST_RESORT.questName
|
||||
147 -> Quests.CATAPULT_CONSTRUCTION.questName
|
||||
148 -> Quests.KENNITHS_CONCERNS.questName
|
||||
149 -> Quests.LEGACY_OF_SEERGAZE.questName
|
||||
150 -> Quests.PERILS_OF_ICE_MOUNTAIN.questName
|
||||
151 -> Quests.TOKTZ_KET_DILL.questName
|
||||
152 -> Quests.SMOKING_KILLS.questName
|
||||
153 -> Quests.ROCKING_OUT.questName
|
||||
154 -> Quests.SPIRIT_OF_SUMMER.questName
|
||||
155 -> Quests.MEETING_HISTORY.questName
|
||||
156 -> Quests.ALL_FIRED_UP.questName
|
||||
157 -> Quests.SUMMERS_END.questName
|
||||
158 -> Quests.DEFENDER_OF_VARROCK.questName
|
||||
159 -> Quests.SWEPT_AWAY.questName
|
||||
160 -> Quests.WHILE_GUTHIX_SLEEPS.questName
|
||||
161 -> Quests.IN_PYRE_NEED.questName
|
||||
162 -> Quests.MYTHS_OF_THE_WHITE_LANDS.questName
|
||||
else -> ""
|
||||
}
|
||||
return name
|
||||
return quest as String
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public class SmeltingInterface extends ComponentPlugin {
|
|||
* @author 'Vexia
|
||||
*/
|
||||
public enum BarButton {
|
||||
BRONZE_1(16, Bar.BRONZE, 1), BRONZE_5(15, Bar.BRONZE, 5), BRONZE_10(14, Bar.BRONZE, 10), BRONZE_X(13, Bar.BRONZE, -1), BLURITE_1(20, Bar.BLURITE, 1), BLURITE_5(19, Bar.BLURITE, 5), BLURITE_10(18, Bar.BLURITE, 10), BLURITE_X(17, Bar.BLURITE, -1), IRON_1(24, Bar.IRON, 1), IRON_5(23, Bar.IRON, 5), IRON_10(22, Bar.IRON, 10), IRON_X(21, Bar.IRON, -1), SILVER_1(28, Bar.SILVER, 1), SILVER_5(27, Bar.SILVER, 5), SILVER_10(26, Bar.SILVER, 10), SILVER_X(25, Bar.SILVER, -1), STEEL_1(32, Bar.STEEL, 1), STEEL_5(31, Bar.STEEL, 5), STEEL_10(30, Bar.STEEL, 10), STEEL_X(29, Bar.STEEL, -1), GOLD_1(36, Bar.GOLD, 1), GOLD_5(35, Bar.GOLD, 5), GOLD_10(34, Bar.GOLD, 10), GOLD_X(33, Bar.GOLD, -1), MITHRIL_1(40, Bar.MITHRIL, 1), MITHRIL_5(39, Bar.MITHRIL, 5), MITHRIL_10(38, Bar.MITHRIL, 10), MITHRIL_X(37, Bar.MITHRIL, -1), ADAMANT_1(44, Bar.ADAMANT, 1), ADAMANT_5(43, Bar.ADAMANT, 5), ADAMANT_10(42, Bar.ADAMANT, 10), ADAMANT_X(41, Bar.ADAMANT, -1), RUNE_1(48, Bar.RUNITE, 1), RUNE_5(47, Bar.RUNITE, 5), RUNE_10(46, Bar.RUNITE, 10), RUNE_X(45, Bar.RUNITE, -1);
|
||||
BRONZE_1(16, Bar.BRONZE, 1), BRONZE_5(15, Bar.BRONZE, 5), BRONZE_10(14, Bar.BRONZE, 30), BRONZE_X(13, Bar.BRONZE, -1), BLURITE_1(20, Bar.BLURITE, 1), BLURITE_5(19, Bar.BLURITE, 5), BLURITE_10(18, Bar.BLURITE, 30), BLURITE_X(17, Bar.BLURITE, -1), IRON_1(24, Bar.IRON, 1), IRON_5(23, Bar.IRON, 5), IRON_10(22, Bar.IRON, 30), IRON_X(21, Bar.IRON, -1), SILVER_1(28, Bar.SILVER, 1), SILVER_5(27, Bar.SILVER, 5), SILVER_10(26, Bar.SILVER, 30), SILVER_X(25, Bar.SILVER, -1), STEEL_1(32, Bar.STEEL, 1), STEEL_5(31, Bar.STEEL, 5), STEEL_10(30, Bar.STEEL, 30), STEEL_X(29, Bar.STEEL, -1), GOLD_1(36, Bar.GOLD, 1), GOLD_5(35, Bar.GOLD, 5), GOLD_10(34, Bar.GOLD, 30), GOLD_X(33, Bar.GOLD, -1), MITHRIL_1(40, Bar.MITHRIL, 1), MITHRIL_5(39, Bar.MITHRIL, 5), MITHRIL_10(38, Bar.MITHRIL, 30), MITHRIL_X(37, Bar.MITHRIL, -1), ADAMANT_1(44, Bar.ADAMANT, 1), ADAMANT_5(43, Bar.ADAMANT, 5), ADAMANT_10(42, Bar.ADAMANT, 30), ADAMANT_X(41, Bar.ADAMANT, -1), RUNE_1(48, Bar.RUNITE, 1), RUNE_5(47, Bar.RUNITE, 5), RUNE_10(46, Bar.RUNITE, 30), RUNE_X(45, Bar.RUNITE, -1);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BarButton} {@code Object}.
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import core.game.world.update.flag.context.Graphics
|
|||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.Scenery
|
||||
import org.rs09.consts.Sounds
|
||||
import content.data.Quests
|
||||
|
||||
@Suppress("unused")
|
||||
class EctophialListener : InteractionListener {
|
||||
|
|
@ -37,7 +38,7 @@ class EctophialListener : InteractionListener {
|
|||
}
|
||||
|
||||
on(Items.ECTOPHIAL_4251, IntType.ITEM, "empty") { player, node ->
|
||||
if (!hasRequirement(player, "Ghosts Ahoy"))
|
||||
if (!hasRequirement(player, Quests.GHOSTS_AHOY))
|
||||
return@on true
|
||||
|
||||
if (player.isTeleBlocked) {
|
||||
|
|
|
|||
|
|
@ -10,12 +10,14 @@ import org.rs09.consts.Sounds
|
|||
class EnchantJewelleryTabListener : InteractionListener {
|
||||
|
||||
private val LVL_1_ENCHANT = mapOf(
|
||||
Items.BLUE_DRAGONHIDE_1751 to Items.PLAIN_SATCHEL_10877,
|
||||
Items.SAPPHIRE_RING_1637 to Items.RING_OF_RECOIL_2550,
|
||||
Items.SAPPHIRE_NECKLACE_1656 to Items.GAMES_NECKLACE8_3853,
|
||||
Items.SAPPHIRE_AMULET_1694 to Items.AMULET_OF_MAGIC_1727,
|
||||
Items.SAPPHIRE_BRACELET_11072 to Items.BRACELET_OF_CLAY_11074
|
||||
)
|
||||
private val LVL_2_ENCHANT = mapOf(
|
||||
Items.GREEN_DRAGONHIDE_1753 to Items.GREEN_SATCHEL_10878,
|
||||
Items.EMERALD_RING_1639 to Items.RING_OF_DUELLING8_2552,
|
||||
Items.EMERALD_NECKLACE_1658 to Items.BINDING_NECKLACE_5521,
|
||||
Items.EMERALD_AMULET_1696 to Items.AMULET_OF_DEFENCE_1729,
|
||||
|
|
@ -23,6 +25,7 @@ class EnchantJewelleryTabListener : InteractionListener {
|
|||
)
|
||||
|
||||
private val LVL_3_ENCHANT = mapOf(
|
||||
Items.RED_DRAGONHIDE_1749 to Items.RED_SATCHEL_10879,
|
||||
Items.RUBY_RING_1641 to Items.RING_OF_FORGING_2568,
|
||||
Items.RUBY_NECKLACE_1660 to Items.DIGSITE_PENDANT_5_11194,
|
||||
Items.RUBY_AMULET_1698 to Items.AMULET_OF_STRENGTH_1725,
|
||||
|
|
@ -30,6 +33,7 @@ class EnchantJewelleryTabListener : InteractionListener {
|
|||
)
|
||||
|
||||
private val LVL_4_ENCHANT = mapOf(
|
||||
Items.DAGANNOTH_HIDE_6155 to Items.GOLD_SATCHEL_10881,
|
||||
Items.DIAMOND_RING_1643 to Items.RING_OF_LIFE_2570,
|
||||
Items.DIAMOND_NECKLACE_1662 to Items.PHOENIX_NECKLACE_11090,
|
||||
Items.DIAMOND_AMULET_1700 to Items.AMULET_OF_POWER_1731,
|
||||
|
|
@ -37,6 +41,7 @@ class EnchantJewelleryTabListener : InteractionListener {
|
|||
)
|
||||
|
||||
private val LVL_5_ENCHANT = mapOf(
|
||||
Items.SUQAH_HIDE_9080 to Items.RUNE_SATCHEL_10882,
|
||||
Items.DRAGONSTONE_RING_1645 to Items.RING_OF_WEALTH4_14646,
|
||||
Items.DRAGON_NECKLACE_1664 to Items.SKILLS_NECKLACE4_11105,
|
||||
Items.DRAGONSTONE_AMMY_1702 to Items.AMULET_OF_GLORY4_1712,
|
||||
|
|
@ -44,6 +49,7 @@ class EnchantJewelleryTabListener : InteractionListener {
|
|||
)
|
||||
|
||||
private val LVL_6_ENCHANT = mapOf(
|
||||
Items.BLACK_DRAGONHIDE_1747 to Items.BLACK_SATCHEL_10880,
|
||||
Items.ONYX_RING_6575 to Items.RING_OF_STONE_6583,
|
||||
Items.ONYX_NECKLACE_6577 to Items.BERSERKER_NECKLACE_11128,
|
||||
Items.ONYX_AMULET_6581 to Items.AMULET_OF_FURY_6585,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package content.global.handlers.item
|
||||
|
||||
import content.global.skill.slayer.SlayerUtils
|
||||
import core.api.*
|
||||
import content.global.skill.slayer.Tasks
|
||||
import org.rs09.consts.Items
|
||||
|
|
@ -41,7 +42,8 @@ class EnchantedGemDialogue() : DialogueFile() {
|
|||
if(getSlayerTask(player!!) == Tasks.JAD) {
|
||||
npcl(core.game.dialogue.FacialExpression.FRIENDLY, "You're currently assigned to kill TzTok-Jad!")
|
||||
} else {
|
||||
npcl(core.game.dialogue.FacialExpression.FRIENDLY, "You're currently assigned to kill ${getSlayerTaskName(player!!)}s; only ${getSlayerTaskKillsRemaining(player!!)} more to go.")
|
||||
npcl(core.game.dialogue.FacialExpression.FRIENDLY, "You're currently assigned to kill ${SlayerUtils.pluralise(
|
||||
getSlayerTaskName(player!!))}; only ${getSlayerTaskKillsRemaining(player!!)} more to go.")
|
||||
}
|
||||
setVarp(player!!, 2502, getSlayerTaskFlags(player!!) shr 4)
|
||||
stage = 1
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ class ExplorersRingPlugin : InteractionListener {
|
|||
sendMessage(player, "You have used up all of your charges for the day.")
|
||||
return@on true
|
||||
}
|
||||
sendDialogue(player, "Choose the item that you wish to convert to coins.")
|
||||
addDialogueAction (player) {_,_ ->
|
||||
sendItemSelect (player, "Choose") { slot, optionIndex ->
|
||||
//sendDialogue(player, "Choose the item that you wish to convert to coins.")
|
||||
//addDialogueAction (player) {_,_ ->
|
||||
sendItemSelect (player, "Cast Low Level Alchemy on:") { slot, optionIndex ->
|
||||
val item = player.inventory[slot]
|
||||
if (item == null)
|
||||
return@sendItemSelect
|
||||
|
|
@ -63,7 +63,7 @@ class ExplorersRingPlugin : InteractionListener {
|
|||
return@sendItemSelect
|
||||
getStoreFile()[player.username.lowercase() + ":alchs"] = remaining - 1
|
||||
}
|
||||
}
|
||||
//}
|
||||
return@on true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,24 +5,34 @@ import core.game.interaction.IntType
|
|||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.repository.Repository
|
||||
|
||||
class HouseTeleTabOptionListener : InteractionListener {
|
||||
override fun defineListeners() {
|
||||
val homeTabID = 8013
|
||||
on(homeTabID, IntType.ITEM, "break") {player, node ->
|
||||
var hasHouse = player.houseManager.location.exitLocation != null
|
||||
if (!hasHouse) {
|
||||
sendMessage( player, "You must have a house to teleport to before attempting that.")
|
||||
return@on false
|
||||
//Snowscape: teleport to the last house you entered, if possible
|
||||
var owner: Player
|
||||
val lastHouseOwner = Repository.getPlayerByName(player.getAttribute("lasthouseentered", null))
|
||||
if (lastHouseOwner != null && !lastHouseOwner.getHouseManager().isLocked()) {
|
||||
owner = lastHouseOwner
|
||||
} else {
|
||||
var hasHouse = player.houseManager.location.exitLocation != null
|
||||
if (!hasHouse) {
|
||||
sendMessage( player, "You must have a house to teleport to before attempting that.")
|
||||
return@on false
|
||||
}
|
||||
owner = player
|
||||
}
|
||||
closeInterface(player)
|
||||
lock(player, 5)
|
||||
if (inInventory(player, node.id)) {
|
||||
player.houseManager.preEnter(player, false)
|
||||
val location = player.houseManager.getEnterLocation()
|
||||
owner.houseManager.preEnter(player, false)
|
||||
val location = owner.houseManager.getEnterLocation()
|
||||
if (teleport(player, location, TeleportManager.TeleportType.TELETABS)) {
|
||||
removeItem(player, Item(node.id, 1))
|
||||
player.houseManager.postEnter(player, false)
|
||||
owner.houseManager.postEnter(player, false)
|
||||
}
|
||||
}
|
||||
return@on true
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import core.api.*
|
|||
import core.game.node.entity.player.link.quest.QuestRepository
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.InteractionListener
|
||||
import content.data.Quests
|
||||
|
||||
class ItemQuestRequirementListener : InteractionListener {
|
||||
|
||||
|
|
@ -106,7 +107,7 @@ class ItemQuestRequirementListener : InteractionListener {
|
|||
|
||||
/*
|
||||
onEquip(fremennikIslesEquipment) { player, _ ->
|
||||
if (!isQuestComplete(player, "Fremennik Isles")) {
|
||||
if (!isQuestComplete(player, Quests.THE_FREMENNIK_ISLES)) {
|
||||
sendMessage(player, "You must have completed The Fremennik Isles to equip this.")
|
||||
return@onEquip false
|
||||
}
|
||||
|
|
@ -114,7 +115,7 @@ class ItemQuestRequirementListener : InteractionListener {
|
|||
}
|
||||
|
||||
onEquip(fremennikIslesDuringQuestEquipment){ player, _ ->
|
||||
if (questStage(player, "Fremennik Isles") > 0) {
|
||||
if (questStage(player, Quests.THE_FREMENNIK_ISLES) > 0) {
|
||||
sendMessage(player, "You must have started The Fremennik Isles to equip this.")
|
||||
return@onEquip false
|
||||
}
|
||||
|
|
@ -123,23 +124,23 @@ class ItemQuestRequirementListener : InteractionListener {
|
|||
*/
|
||||
|
||||
onEquip(fremennikTrialsEquipment) { player, _ ->
|
||||
return@onEquip hasRequirement(player, "Fremennik Trials")
|
||||
return@onEquip hasRequirement(player, Quests.THE_FREMENNIK_TRIALS)
|
||||
}
|
||||
|
||||
onEquip(fremennikIslesEquipment) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "The Fremennik Isles")
|
||||
return@onEquip hasRequirement(player, Quests.THE_FREMENNIK_ISLES)
|
||||
}
|
||||
|
||||
onEquip(avasBackpacks){ player, _ ->
|
||||
return@onEquip hasRequirement(player, "Animal Magnetism")
|
||||
return@onEquip hasRequirement(player, Quests.ANIMAL_MAGNETISM)
|
||||
}
|
||||
|
||||
onEquip(lostCityWeapons){ player, _ ->
|
||||
return@onEquip hasRequirement(player, "Lost City")
|
||||
return@onEquip hasRequirement(player, Quests.LOST_CITY)
|
||||
}
|
||||
|
||||
onEquip(Items.CAPE_OF_LEGENDS_1052) { player, _ ->
|
||||
return@onEquip hasRequirement(player, "Legend's Quest")
|
||||
return@onEquip hasRequirement(player, Quests.LEGENDS_QUEST)
|
||||
}
|
||||
|
||||
onEquip(questCapes) { player, _ ->
|
||||
|
|
@ -152,84 +153,84 @@ class ItemQuestRequirementListener : InteractionListener {
|
|||
}
|
||||
|
||||
onEquip(Items.WOLFBANE_2952){ player, _ ->
|
||||
return@onEquip hasRequirement(player, "Priest in Peril")
|
||||
return@onEquip hasRequirement(player, Quests.PRIEST_IN_PERIL)
|
||||
}
|
||||
|
||||
onEquip(Items.ANCIENT_MACE_11061){ player, _ ->
|
||||
return@onEquip hasRequirement(player, "Another Slice of H.A.M")
|
||||
return@onEquip hasRequirement(player, Quests.ANOTHER_SLICE_OF_HAM)
|
||||
}
|
||||
|
||||
onEquip(Items.ANCIENT_STAFF_4675){ player, _ ->
|
||||
return@onEquip hasRequirement(player, "Desert Treasure")
|
||||
return@onEquip hasRequirement(player, Quests.DESERT_TREASURE)
|
||||
}
|
||||
|
||||
onEquip(Items.ELEMENTAL_SHIELD_2890) { player, _ ->
|
||||
return@onEquip hasRequirement(player, "Elemental Workshop I")
|
||||
return@onEquip hasRequirement(player, Quests.ELEMENTAL_WORKSHOP_I)
|
||||
}
|
||||
|
||||
onEquip(crystalEquipment){ player, _ ->
|
||||
return@onEquip hasRequirement(player, "Roving Elves")
|
||||
return@onEquip hasRequirement(player, Quests.ROVING_ELVES)
|
||||
}
|
||||
|
||||
onEquip(dragonSlayerEquipment) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Dragon Slayer")
|
||||
return@onEquip hasRequirement(player, Quests.DRAGON_SLAYER)
|
||||
}
|
||||
|
||||
onEquip(Items.DRAGON_SCIMITAR_4587) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Monkey Madness")
|
||||
return@onEquip hasRequirement(player, Quests.MONKEY_MADNESS)
|
||||
}
|
||||
|
||||
onEquip(Items.GLOVES_7462) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Recipe for Disaster")
|
||||
return@onEquip hasRequirement(player, Quests.RECIPE_FOR_DISASTER)
|
||||
}
|
||||
|
||||
onEquip(Items.SLAYER_HELMET_13263) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Smoking Kills")
|
||||
return@onEquip hasRequirement(player, Quests.SMOKING_KILLS)
|
||||
}
|
||||
|
||||
onEquip (Items.DRAGON_HALBERD_3204) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Regicide")
|
||||
return@onEquip hasRequirement(player, Quests.REGICIDE)
|
||||
}
|
||||
|
||||
onEquip (Items.CLIMBING_BOOTS_3105) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Death Plateau")
|
||||
return@onEquip hasRequirement(player, Quests.DEATH_PLATEAU)
|
||||
}
|
||||
|
||||
onEquip (godBooks) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Horror from the Deep")
|
||||
return@onEquip hasRequirement(player, Quests.HORROR_FROM_THE_DEEP)
|
||||
}
|
||||
|
||||
onEquip (pharaohScepters) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Icthlarin's Little Helper")
|
||||
return@onEquip hasRequirement(player, Quests.ICTHLARINS_LITTLE_HELPER)
|
||||
}
|
||||
|
||||
onEquip (Items.DRAGON_SQ_SHIELD_1187) {player, _ ->
|
||||
//because I know people won't believe it: https://runescape.wiki/w/Dragon_sq_shield?oldid=899636
|
||||
return@onEquip hasRequirement(player, "Legend's Quest")
|
||||
return@onEquip hasRequirement(player, Quests.LEGENDS_QUEST)
|
||||
}
|
||||
|
||||
onEquip (initiateArmour) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Recruitment Drive")
|
||||
return@onEquip hasRequirement(player, Quests.RECRUITMENT_DRIVE)
|
||||
}
|
||||
|
||||
onEquip (proselyteArmour) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "The Slug Menace")
|
||||
return@onEquip hasRequirement(player, Quests.THE_SLUG_MENACE)
|
||||
}
|
||||
|
||||
onEquip (spiritShields) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Summer's End")
|
||||
return@onEquip hasRequirement(player, Quests.SUMMERS_END)
|
||||
}
|
||||
|
||||
onEquip (Items.DRAGON_MACE_1434) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Heroes' Quest")
|
||||
return@onEquip hasRequirement(player, Quests.HEROES_QUEST)
|
||||
}
|
||||
|
||||
onEquip (Items.DRAGON_BATTLEAXE_1377) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Heroes' Quest")
|
||||
return@onEquip hasRequirement(player, Quests.HEROES_QUEST)
|
||||
}
|
||||
|
||||
onEquip (Items.DARKLIGHT_6746) {player, _ ->
|
||||
return@onEquip hasRequirement(player, "Shadow of the Storm")
|
||||
return@onEquip hasRequirement(player, Quests.SHADOW_OF_THE_STORM)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import core.game.node.entity.player.Player;
|
|||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import content.region.morytania.quest.naturespirit.NSUtils;
|
||||
import content.data.Quests;
|
||||
|
||||
/**
|
||||
* Handles the Silver Sickle (b) to collect Mort Myre Fungus.
|
||||
|
|
@ -28,7 +29,7 @@ public final class SilverSicklePlugin extends OptionHandler {
|
|||
switch (option) {
|
||||
case "operate":
|
||||
case "cast bloom":
|
||||
if(player.getQuestRepository().getQuest("Nature Spirit").getStage(player) >= 75) {
|
||||
if(player.getQuestRepository().getQuest(Quests.NATURE_SPIRIT).getStage(player) >= 75) {
|
||||
player.getPacketDispatch().sendAnimation(9021);
|
||||
NSUtils.castBloom(player);
|
||||
} else {
|
||||
|
|
|
|||
183
Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt
Executable file
183
Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt
Executable file
|
|
@ -0,0 +1,183 @@
|
|||
package content.global.handlers.item
|
||||
|
||||
import core.api.*
|
||||
import core.game.container.Container
|
||||
import content.global.skill.summoning.familiar.BurdenContainerListener
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.player.Player
|
||||
//import core.game.node.entity.player.info.login.PlayerSaver
|
||||
import core.game.node.item.Item
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import org.json.simple.parser.JSONParser
|
||||
import org.rs09.consts.Items
|
||||
|
||||
import core.game.component.Component
|
||||
import core.game.component.CloseEvent
|
||||
import core.game.container.access.InterfaceContainer
|
||||
import content.global.handlers.scenery.BankBoothListener
|
||||
import content.global.handlers.npc.BankerNPC
|
||||
|
||||
/**
|
||||
* Listener for satchels from Creature Creation, repurposed for Snowscape
|
||||
* They are repurposed as item pouches, using the summoning familiar inventory interface
|
||||
* @author
|
||||
*/
|
||||
class SnowscapeSatchelListener : InteractionListener {
|
||||
|
||||
companion object {
|
||||
|
||||
val plainSatchelId = 10877
|
||||
val greenSatchelId = 10878
|
||||
val redSatchelId = 10879
|
||||
val blackSatchelId = 10880
|
||||
val goldSatchelId = 10881
|
||||
val runeSatchelId = 10882
|
||||
val satchelIds = intArrayOf(plainSatchelId,greenSatchelId,redSatchelId,blackSatchelId,goldSatchelId,runeSatchelId)
|
||||
|
||||
|
||||
|
||||
|
||||
private fun transferItem(player: Player, satchelId: Int, item: Item, amount: Int, withdraw: Boolean, asNote: Boolean = false) {
|
||||
if (withdraw == false && !isAllowed(player, satchelId, unnote(item).getId())) {
|
||||
player.sendMessage(item.getName() + " cannot be stored in the " + Item(satchelId).getName() + ".")
|
||||
return
|
||||
}
|
||||
if (withdraw == true && asNote == false && satchelId == plainSatchelId) {
|
||||
player.sendMessage("This satchel can only be emptied by a banker. Use it on a bank booth to get the items.")
|
||||
return
|
||||
}
|
||||
val to = if (withdraw) player.getInventory() else getSatchel(player, satchelId)
|
||||
val from = if (withdraw) getSatchel(player, satchelId) else player.getInventory()
|
||||
val maximum = if (asNote) to.getMaximumAdd(note(item)) else to.getMaximumAdd(unnote(item))
|
||||
if (maximum < 1 && withdraw == false) {
|
||||
player.sendMessage("There is not enough space for the " + item.getName() + " in the satchel.")
|
||||
return
|
||||
}
|
||||
val finalAmount = kotlin.comparisons.minOf(amount, from.getAmount(item), maximum)
|
||||
val finalItem = Item(item.getId(), finalAmount)
|
||||
if (finalAmount > 0 && from.remove(finalItem)) {
|
||||
if (asNote) to.add(note(finalItem)) else to.add(unnote(finalItem))
|
||||
}
|
||||
}
|
||||
|
||||
private fun emptySatchel(player: Player, satchelId: Int, asNote: Boolean = false) {
|
||||
if (asNote == false && satchelId == plainSatchelId) {
|
||||
player.sendMessage("This satchel can only be emptied by a banker. Use it on a Bank Booth to get the items.")
|
||||
return
|
||||
}
|
||||
val satchel = getSatchel(player, satchelId)
|
||||
repeat(satchel.capacity()) { index ->
|
||||
var item = satchel.get(index)
|
||||
if (item != null) {
|
||||
transferItem(player, satchelId, item, satchel.getAmount(item), true, asNote)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Function to handle constructing the correct interfaces when the satchel is opened
|
||||
private fun openSatchel(player: Player, node: Node) {
|
||||
val satchelId = node.asItem().getId()
|
||||
val satchel = getSatchel(player, satchelId)
|
||||
if (satchel.getListeners().count() < 1) satchel.register(BurdenContainerListener(player))
|
||||
|
||||
player.getInterfaceManager().open(Component(671)).setCloseEvent(CloseEvent { player, component ->
|
||||
player.getInterfaceManager().closeSingleTab()
|
||||
removeAttribute(player, "openSatchel")
|
||||
return@CloseEvent true
|
||||
}
|
||||
)
|
||||
setAttribute(player, "openSatchel", satchelId)
|
||||
satchel.shift()
|
||||
player.getInterfaceManager().openSingleTab(Component(665))
|
||||
InterfaceContainer.generateItems(player, player.getInventory().toArray(), arrayOf("Store-X","Store-All","Store-10","Store-5","Store-1"),665,0,7,4,93)
|
||||
InterfaceContainer.generateItems(player, satchel.toArray(), arrayOf("Withdraw-X","Withdraw-All","Withdraw-10","Withdraw-5","Withdraw-1"),671,27,5,6,30)
|
||||
}
|
||||
|
||||
// This is called by BurdenInterfacePlugin.java when the player interacts with the familiar interface and the "openSatchel" attribute exists
|
||||
fun satchelInterfaceAction(player: Player, component: Component, opcode: Int, button: Int, slot: Int, itemId: Int) {
|
||||
val satchelId = getAttribute(player, "openSatchel", 0)
|
||||
val withdraw = component.getId() == 671
|
||||
val container = if (withdraw) getSatchel(player, satchelId) else player.getInventory()
|
||||
val item = if (slot >= 0 && slot < container.capacity()) container.get(slot) else null
|
||||
if (item == null && button != 29) return
|
||||
when (opcode) {
|
||||
155 -> if (button == 29) emptySatchel(player, satchelId) else transferItem(player, satchelId, item!!, 1, withdraw)
|
||||
196 -> transferItem(player, satchelId, item!!, 5, withdraw)
|
||||
124 -> transferItem(player, satchelId, item!!, 10, withdraw)
|
||||
199 -> transferItem(player, satchelId, item!!, container.getAmount(item), withdraw)
|
||||
234 -> sendInputDialogue(player, true, "Enter the amount:") { value -> transferItem(player, satchelId, item!!, value as Int, withdraw) }
|
||||
9 -> player.sendMessage(item!!.getDefinition().getExamine())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun getSatchel(player: Player, satchelId: Int): Container {
|
||||
var satchel: Container? = null
|
||||
when (satchelId) {
|
||||
plainSatchelId -> satchel = player.plainSatchel
|
||||
greenSatchelId -> satchel = player.greenSatchel
|
||||
redSatchelId -> satchel = player.redSatchel
|
||||
blackSatchelId -> satchel = player.blackSatchel
|
||||
goldSatchelId -> satchel = player.goldSatchel
|
||||
runeSatchelId -> satchel = player.runeSatchel
|
||||
}
|
||||
return satchel!!
|
||||
}
|
||||
|
||||
// Checks if the item is allowed in the satchel. The NPCDropTables.java function calls this on satchels the player is carrying.
|
||||
fun isAllowed(player: Player, satchelId: Int, itemId: Int): Boolean {
|
||||
when (satchelId) {
|
||||
plainSatchelId -> return itemId !in satchelIds
|
||||
greenSatchelId -> return (Item(itemId).getName().contains(" seed") || Item(itemId).getName().contains("Grimy") || Item(itemId).getName().contains("Clean "))
|
||||
redSatchelId -> return itemId in intArrayOf(*(12158..12168).toList().toIntArray()) || Item(itemId).getName().equals("Clue scroll")
|
||||
blackSatchelId -> return itemId in intArrayOf(995)
|
||||
goldSatchelId -> return itemId in intArrayOf(436,438,440,442,444,446,447,449,451,453,668,2892,2349,2351,2353,2355,2357,2359,2361,2363,2365,1601,1603,1605,1607,1609,1611,1613,1615,1617,1619,1621,1623,1625,1627,1629,1631,6571,6573)
|
||||
runeSatchelId -> return itemId in intArrayOf(556,555,557,554,558,559,564,562,9075,561,563,560,565,566,4694,4695,4696,4697,4698,4699)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun defineListeners() {
|
||||
|
||||
onUseAnyWith(IntType.ITEM, *satchelIds) { player, used, with ->
|
||||
val satchelId = with.asItem().getId()
|
||||
transferItem(player, satchelId, used.asItem(), player.getInventory().getAmount(used.asItem()),false)
|
||||
return@onUseAnyWith true
|
||||
}
|
||||
|
||||
on(satchelIds, IntType.ITEM, "inspect","operate") { player, node ->
|
||||
openSatchel(player, node)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(satchelIds, IntType.ITEM, "empty") { player, node ->
|
||||
emptySatchel(player, node.asItem().getId())
|
||||
return@on true
|
||||
}
|
||||
|
||||
// BankBoothListener values are public but BankChestListener values are not, so rather than edit the BankChestListener file I have copied the IDs here. 12309 is the Culinomancer's chest.
|
||||
val bankChests = intArrayOf(3194,4483,10562,14382,16695,16696,21301,27662,27663)
|
||||
val bankUseWiths = intArrayOf(*BankBoothListener.BANK_BOOTHS, 12309, *bankChests)
|
||||
onUseWith(IntType.SCENERY, satchelIds, *bankUseWiths) { player, used, with ->
|
||||
emptySatchel(player, used.asItem().getId(), true)
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
//6362 is the Ourania Altar banker.
|
||||
val bankers = intArrayOf(*BankerNPC.NPC_IDS, *BankerNPC.SPECIAL_NPC_IDS, 6362)
|
||||
|
||||
onUseWith(IntType.NPC, satchelIds, *bankers) { player, used, with ->
|
||||
emptySatchel(player, used.asItem().getId(), true)
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
146
Server/src/main/content/global/handlers/item/SnowscapeTeleorb.kt
Normal file
146
Server/src/main/content/global/handlers/item/SnowscapeTeleorb.kt
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
package content.global.handlers.item
|
||||
|
||||
import core.api.*
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
import core.game.world.map.zone.ZoneRestriction
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.dialogue.*
|
||||
import core.tools.START_DIALOGUE
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.Sounds
|
||||
|
||||
import core.game.component.Component
|
||||
|
||||
/**
|
||||
* Listener for the strange teleorb object. Normally this object is part of the While Guthix Sleeps quest, but it has been repurposed.
|
||||
* The new purpose is a custom teleport artifact, allowing players to save a location and teleport back to it.
|
||||
* @author
|
||||
*/
|
||||
class SnowscapeTeleorb : InteractionListener {
|
||||
|
||||
// The teleorb item id
|
||||
val teleorb = 14534
|
||||
|
||||
// How many law runes are required for one teleport charge
|
||||
val runesPerTeleportNormal = 20
|
||||
val runesPerTeleportBoosted = 2
|
||||
|
||||
override fun defineListeners() {
|
||||
on(teleorb, IntType.ITEM, "inspect") { player, node ->
|
||||
inspect(player, node)
|
||||
return@on true
|
||||
}
|
||||
on(teleorb, IntType.ITEM, "activate") { player, node ->
|
||||
activate(player, node)
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
private fun inspect(player: Player, node: Node) {
|
||||
openDialogue(player,SnowscapeTeleorbDialogue())
|
||||
}
|
||||
|
||||
private fun activate(player: Player, node: Node) {
|
||||
val charges = getAttribute(player, "teleorb:charges",0) as Int
|
||||
var runesPerTeleport = if (getAttribute(player, "snowscape:boostedmode", false)) runesPerTeleportBoosted else runesPerTeleportNormal
|
||||
if (charges >= runesPerTeleport) {
|
||||
val destination = getAttribute(player, "teleorb:location", Location.create(3236,3218,0))
|
||||
player.getTeleporter().send(destination, TeleportManager.TeleportType.ENTRANA_MAGIC_DOOR)
|
||||
setAttribute(player, "/save:teleorb:charges", charges - runesPerTeleport)
|
||||
player.sendMessage("Charges remaining: " + ((getAttribute(player, "teleorb:charges",0) as Int) / runesPerTeleport))
|
||||
rewardXP(player, Skills.MAGIC, 15.0 * runesPerTeleport)
|
||||
} else {
|
||||
player.sendMessage("<col=ff0000>The teleorb is out of charges.</col>")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class SnowscapeTeleorbDialogue : DialogueFile() {
|
||||
|
||||
// How many law runes are required for one teleport charge
|
||||
val runesPerTeleportNormal = 20
|
||||
val runesPerTeleportBoosted = 2
|
||||
|
||||
val teleorb = 14534
|
||||
val lawRune = 563
|
||||
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
when (stage) {
|
||||
START_DIALOGUE -> options("Update Location","Recharge","Show Info").also {stage++}
|
||||
|
||||
1 -> when (buttonID) {
|
||||
1 -> player?.let {
|
||||
end()
|
||||
val region = it.getViewport().getRegion()
|
||||
if (region == null || region is DynamicRegion || it.getZoneMonitor().isRestricted(ZoneRestriction.OFF_MAP)) {
|
||||
it.sendMessage("This location cannot be saved!")
|
||||
} else {
|
||||
setAttribute(it, "/save:teleorb:location", it.getLocation())
|
||||
sendInputDialogue(it, false, "Location saved. Enter a description of this location:",) { value ->
|
||||
setAttribute(it, "/save:teleorb:description", value as String)
|
||||
}
|
||||
it.sendMessage("Location saved.")
|
||||
it.graphics(Graphics(343))
|
||||
it.animate(Animation(1818))
|
||||
playAudio(it, Sounds.TELE_OTHER_CAST_199)
|
||||
}
|
||||
}
|
||||
2 -> options("Recharge with Law Runes","Recharge with additional orbs").also {stage++}
|
||||
3 -> player?.let {
|
||||
end()
|
||||
var runesPerTeleport = if (getAttribute(it, "snowscape:boostedmode", false)) runesPerTeleportBoosted else runesPerTeleportNormal
|
||||
it.sendMessage("Current saved location: " + getAttribute(it, "teleorb:description", "Unknown").replace("_"," "))
|
||||
it.sendMessage("Charges remaining: " + ((getAttribute(it, "teleorb:charges",0) as Int) / runesPerTeleport))
|
||||
}
|
||||
}
|
||||
2 -> when (buttonID) {
|
||||
1 -> player?.let {
|
||||
end()
|
||||
var runesPerTeleport = if (getAttribute(it, "snowscape:boostedmode", false)) runesPerTeleportBoosted else runesPerTeleportNormal
|
||||
sendInputDialogue(it, true, "Each charge requires $runesPerTeleport Law Runes. How many runes would you like to use?",) { value ->
|
||||
var amount = kotlin.math.min(amountInInventory(it,lawRune), value as Int)
|
||||
if (removeItem(it, Item(lawRune, amount))) {
|
||||
it.sendMessage("You charge the teleorb with $amount Law Runes.")
|
||||
amount += (getAttribute(it, "teleorb:charges",0) as Int)
|
||||
setAttribute(it, "/save:teleorb:charges", amount)
|
||||
it.sendMessage("Current charges: " + ((getAttribute(it, "teleorb:charges",0) as Int) / runesPerTeleport))
|
||||
it.graphics(Graphics(141,96))
|
||||
it.animate(Animation(722))
|
||||
playAudio(it, Sounds.LUNAR_EMBUE_RUNES_2888) //Yes, Imbue is mispelled in the sounds list.
|
||||
}
|
||||
}
|
||||
}
|
||||
2 -> player?.let {
|
||||
end()
|
||||
var runesPerTeleport = if (getAttribute(it, "snowscape:boostedmode", false)) runesPerTeleportBoosted else runesPerTeleportNormal
|
||||
sendInputDialogue(it, true, "Each additional orb adds one charge. How many would you like to use?",) { value ->
|
||||
var amount = kotlin.math.min(amountInInventory(it,teleorb) - 1, value as Int)
|
||||
if (amount > 0 && removeItem(it, Item(teleorb, amount))) {
|
||||
it.sendMessage("You destroy $amount teleorbs, fusing their energy into one.")
|
||||
amount = amount * runesPerTeleport
|
||||
amount += (getAttribute(it, "teleorb:charges",0) as Int)
|
||||
setAttribute(it, "/save:teleorb:charges", amount)
|
||||
it.sendMessage("Current charges: " + ((getAttribute(it, "teleorb:charges",0) as Int) / runesPerTeleport))
|
||||
it.graphics(Graphics(141,96))
|
||||
it.animate(Animation(722))
|
||||
playAudio(it, Sounds.LUNAR_EMBUE_RUNES_2888)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +1,55 @@
|
|||
package content.global.handlers.item
|
||||
|
||||
import core.api.inInventory
|
||||
import core.api.removeItem
|
||||
import core.api.teleport
|
||||
import content.region.kandarin.ardougne.quest.plaguecity.PlagueCityListeners.Companion.ARDOUGNE_TELE_ATTRIBUTE
|
||||
import core.api.*
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.api.hasRequirement;
|
||||
import content.data.Quests
|
||||
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
|
||||
class TeleTabsListener : InteractionListener {
|
||||
|
||||
enum class TeleTabs(val item: Int, val location: Location, val exp: Double, val requirementCheck: (Player) -> Boolean = { true }) {
|
||||
ADDOUGNE_TELEPORT(8011, Location.create(2662, 3307, 0), 61.0, {
|
||||
player -> hasRequirement(player, "Plague City");
|
||||
player -> getAttribute(player, ARDOUGNE_TELE_ATTRIBUTE, false)
|
||||
}),
|
||||
AIR_ALTAR_TELEPORT(13599, Location.create(2978, 3296, 0), 0.0),
|
||||
ASTRAL_ALTAR_TELEPORT(13611, Location.create(2156, 3862, 0), 0.0),
|
||||
BLOOD_ALTAR_TELEPORT(13610, Location.create(3559, 9778, 0), 0.0),
|
||||
ASTRAL_ALTAR_TELEPORT(13611, Location.create(2156, 3862, 0), 0.0, {
|
||||
player -> hasRequirement(player, Quests.LUNAR_DIPLOMACY);
|
||||
}),
|
||||
BLOOD_ALTAR_TELEPORT(13610, Location.create(3559, 9778, 0), 0.0, {
|
||||
player -> hasRequirement(player, Quests.LEGACY_OF_SEERGAZE);
|
||||
}),
|
||||
BODY_ALTAR_TELEPORT(13604, Location.create(3055, 3443, 0), 0.0),
|
||||
CAMELOT_TELEPORT(8010, Location.create(2757, 3477, 0), 55.5),
|
||||
CHAOS_ALTAR_TELEPORT(13606, Location.create(3058, 3593, 0), 0.0),
|
||||
COSMIC_ALTAR_TELEPORT(13605, Location.create(2411, 4380, 0), 0.0),
|
||||
DEATH_ALTAR_TELEPORT(13609, Location.create(1863, 4639, 0), 0.0),
|
||||
COSMIC_ALTAR_TELEPORT(13605, Location.create(2411, 4380, 0), 0.0, {
|
||||
player -> hasRequirement(player, Quests.LOST_CITY);
|
||||
}),
|
||||
DEATH_ALTAR_TELEPORT(13609, Location.create(1863, 4639, 0), 0.0, {
|
||||
player -> hasRequirement(player, Quests.MOURNINGS_END_PART_II);
|
||||
}),
|
||||
EARTH_ALTAR_TELEPORT(13602, Location.create(3304, 3472, 0), 0.0),
|
||||
FALADOR_TELEPORT(8009, Location.create(2966, 3380, 0), 47.0),
|
||||
FIRE_ALTAR_TELEPORT(13603, Location.create(3311, 3252, 0), 0.0),
|
||||
LAW_ALTAR_TELEPORT(13608, Location.create(2857, 3378, 0), 0.0),
|
||||
LAW_ALTAR_TELEPORT(13608, Location.create(2857, 3378, 0), 0.0, {
|
||||
player -> if (!ItemDefinition.canEnterEntrana(player)) (player.sendMessage("The power of Saradomin prevents you from taking armour or weaponry to Entrana.") !is Unit) else true; // ugly way of doing this, but the sendMessage function returns a Unit type, so by using !is Unit it becomes false.
|
||||
}),
|
||||
LUMBRIDGE_TELEPORT(8008, Location.create(3222, 3218, 0), 41.0),
|
||||
MIND_ALTAR_TELEPORT(13600, Location.create(2979, 3510, 0), 0.0),
|
||||
NATURE_ALTAR_TELEPORT(13607, Location.create(2868, 3013, 0), 0.0),
|
||||
TELEKINETIC_GRAB(8022, Location.create(2836, 3285, 0), 0.0, {
|
||||
player -> hasRequirement(player, Quests.DRAGON_SLAYER);
|
||||
}),
|
||||
VARROCK_TELEPORT(8007, Location.create(3212, 3423, 0), 35.00),
|
||||
WATCH_TOWER_TELEPORT(8012, Location.create(2548, 3114, 0), 68.00),
|
||||
WATCH_TOWER_TELEPORT(8012, Location.create(2548, 3114, 0), 68.00, {
|
||||
player -> hasRequirement(player, Quests.WATCHTOWER);
|
||||
}),
|
||||
WATER_ALTAR_TELEPORT(13601, Location.create(3182, 3162, 0), 0.0);
|
||||
|
||||
companion object {
|
||||
|
|
@ -51,9 +67,17 @@ class TeleTabsListener : InteractionListener {
|
|||
val tabEnum = TeleTabs.forId(tab)
|
||||
if (tabEnum != null && inInventory(player,tab)) {
|
||||
val tabloc = tabEnum.location
|
||||
if (inInventory(player, tab) && tabEnum.requirementCheck(player)) {
|
||||
if (teleport(player, tabloc, TeleportManager.TeleportType.TELETABS)) {
|
||||
removeItem(player, Item(node.id, 1))
|
||||
if (inInventory(player, tab)) {
|
||||
if (tabEnum.requirementCheck(player)){
|
||||
if (teleport(player, tabloc, TeleportManager.TeleportType.TELETABS)) {
|
||||
removeItem(player, Item(node.id, 1))
|
||||
}
|
||||
}
|
||||
else {
|
||||
when (tabEnum){
|
||||
TeleTabs.ADDOUGNE_TELEPORT -> sendMessage(player, "You need to complete Plague City to use this tablet.")
|
||||
else -> sendMessage(player, "You do not have the requirements to use this tablet.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import core.game.world.map.zone.impl.WildernessZone;
|
|||
import core.plugin.Plugin;
|
||||
|
||||
import static core.api.ContentAPIKt.hasRequirement;
|
||||
import content.data.Quests;
|
||||
|
||||
/**
|
||||
* Represents the rotten potato plugin.
|
||||
|
|
@ -34,7 +35,7 @@ public final class TeleportCrystalPlugin extends OptionHandler {
|
|||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
if (!hasRequirement(player, "Mourning's End Part I"))
|
||||
if (!hasRequirement(player, Quests.MOURNINGS_END_PART_I))
|
||||
return true;
|
||||
if (!WildernessZone.checkTeleport(player, 20)) {
|
||||
player.getPacketDispatch().sendMessage("The crystal is unresponsive.");
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class CrystalEquipmentRegister : StartupListener {
|
|||
val shield: Array<Int> = arrayOf(Items.NEW_CRYSTAL_SHIELD_4224, Items.CRYSTAL_SHIELD_FULL_4225, Items.CRYSTAL_SHIELD_9_10_4226, Items.CRYSTAL_SHIELD_8_10_4227, Items.CRYSTAL_SHIELD_7_10_4228, Items.CRYSTAL_SHIELD_6_10_4229, Items.CRYSTAL_SHIELD_5_10_4230, Items.CRYSTAL_SHIELD_4_10_4231, Items.CRYSTAL_SHIELD_3_10_4232, Items.CRYSTAL_SHIELD_2_10_4233, Items.CRYSTAL_SHIELD_1_10_4234, Items.CRYSTAL_SEED_4207)
|
||||
val bow: Array<Int> = arrayOf(Items.NEW_CRYSTAL_BOW_4212, Items.CRYSTAL_BOW_FULL_4214, Items.CRYSTAL_BOW_9_10_4215, Items.CRYSTAL_BOW_8_10_4216, Items.CRYSTAL_BOW_7_10_4217, Items.CRYSTAL_BOW_6_10_4218, Items.CRYSTAL_BOW_5_10_4219, Items.CRYSTAL_BOW_4_10_4220, Items.CRYSTAL_BOW_3_10_4221, Items.CRYSTAL_BOW_2_10_4222, Items.CRYSTAL_BOW_1_10_4223, Items.CRYSTAL_SEED_4207)
|
||||
override fun startup() {
|
||||
EquipmentDegrader.registerSet(250, shield)
|
||||
EquipmentDegrader.registerSet(250, bow)
|
||||
EquipmentDegrader.registerSet(1200, shield)
|
||||
EquipmentDegrader.registerSet(1200, bow)
|
||||
}
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@ public final class AncientMaceSpecialHandler extends MeleeSwingHandler implement
|
|||
state.setStyle(CombatStyle.MELEE);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.1, 0.98)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1));
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1) + 1);
|
||||
if (entity.getSkills().getPrayerPoints() < entity.getSkills().getStaticLevel(5)) {
|
||||
entity.getSkills().setPrayerPoints(entity.getSkills().getPrayerPoints() + hit);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,13 +59,10 @@ public final class BackstabSpecialHandler extends MeleeSwingHandler implements P
|
|||
}
|
||||
state.setStyle(CombatStyle.MELEE);
|
||||
int hit = 0;
|
||||
double accuracy = 1.0;
|
||||
if (!victim.getProperties().getCombatPulse().isAttacking()) {
|
||||
accuracy = 1.75;
|
||||
}
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, accuracy, 0.98)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.0));
|
||||
victim.getSkills().updateLevel(Skills.DEFENCE, -hit / 10, 0);
|
||||
if (!victim.getProperties().getCombatPulse().isAttacking() || isAccurateImpact(entity, victim, CombatStyle.MELEE)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.0) + 1);
|
||||
if (victim.getSkills().getStaticLevel(Skills.DEFENCE) >= victim.getSkills().getDynamicLevels()[Skills.DEFENCE])
|
||||
victim.getSkills().updateLevel(Skills.DEFENCE, -hit, 0);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
package content.global.handlers.item.equipment.special;
|
||||
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.BattleState;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.DeathTask;
|
||||
import core.game.node.entity.combat.*;
|
||||
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
|
|
@ -17,7 +15,6 @@ import core.game.world.update.flag.context.Graphics;
|
|||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
import core.game.node.entity.combat.RangeSwingHandler;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.repository.Repository;
|
||||
import org.rs09.consts.Sounds;
|
||||
|
|
@ -34,6 +31,13 @@ import static core.api.ContentAPIKt.playGlobalAudio;
|
|||
@Initializable
|
||||
public final class ChainhitSpecialHandler extends RangeSwingHandler implements Plugin<Object> {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ChainhitSpecialHandler} {@code Object}.
|
||||
*/
|
||||
public ChainhitSpecialHandler() {
|
||||
super(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* The sp::ecial energy required.
|
||||
*/
|
||||
|
|
@ -159,7 +163,7 @@ public final class ChainhitSpecialHandler extends RangeSwingHandler implements P
|
|||
public boolean pulse() {
|
||||
BattleState bs = new BattleState(entity, e);
|
||||
bs.setMaximumHit(calculateHit(player, e, 1.0));
|
||||
bs.setEstimatedHit(RandomFunction.RANDOM.nextInt(bs.getMaximumHit()));
|
||||
bs.setEstimatedHit(RandomFunction.random(bs.getMaximumHit() + 1));
|
||||
handleHit(victim, e, player, bs);
|
||||
ChainhitSpecialHandler.super.visualizeImpact(player, e, bs);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -31,13 +31,6 @@ public final class ChinchompaSwingHandler extends RangeSwingHandler {
|
|||
*/
|
||||
private static final Graphics END_GRAPHIC = new Graphics(157, 96);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ChinchompaSwingHandler} {@code Object}.
|
||||
*/
|
||||
public ChinchompaSwingHandler() {
|
||||
super(SwingHandlerFlag.IGNORE_STAT_BOOSTS_DAMAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int swing(Entity entity, Entity victim, BattleState state) {
|
||||
boolean multi = entity.getProperties().isMultiZone() && victim.getProperties().isMultiZone();
|
||||
|
|
@ -72,7 +65,7 @@ public final class ChinchompaSwingHandler extends RangeSwingHandler {
|
|||
s.setStyle(CombatStyle.RANGE);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, e, CombatStyle.RANGE)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, e, 1.0));
|
||||
hit = RandomFunction.random(calculateHit(entity, e, 1.0) + 1);
|
||||
}
|
||||
s.setEstimatedHit(hit);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ public final class CleaveSpecialHandler extends MeleeSwingHandler implements Plu
|
|||
}
|
||||
state.setStyle(CombatStyle.MELEE);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.18, 1.0)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.2203));
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.25) + 1);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public final class DescentOfDarknessSpecialHandler extends RangeSwingHandler imp
|
|||
/**
|
||||
* The special energy required.
|
||||
*/
|
||||
private static final int SPECIAL_ENERGY = 65;
|
||||
private static final int SPECIAL_ENERGY = 55;
|
||||
|
||||
/**
|
||||
* The descent of dragons projectile.
|
||||
|
|
@ -102,13 +102,13 @@ public final class DescentOfDarknessSpecialHandler extends RangeSwingHandler imp
|
|||
state.setMaximumHit(max);
|
||||
int hit = minDamage;
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.RANGE, 1.15, 1.0)) {
|
||||
hit += RandomFunction.random(max - minDamage);
|
||||
hit += RandomFunction.random(max - minDamage + 1);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
if (w.getType() == WeaponType.DOUBLE_SHOT) {
|
||||
hit = minDamage;
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.RANGE, 1.15, 1.0)) {
|
||||
hit += RandomFunction.random(max - minDamage);
|
||||
hit += RandomFunction.random(max - minDamage + 1);
|
||||
}
|
||||
state.setSecondaryHit(hit);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ public final class EnergyDrainSpecialHandler extends MeleeSwingHandler implement
|
|||
}
|
||||
state.setStyle(CombatStyle.MELEE);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.2, 1.0)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1));
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.25, 1.0)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1) + 1);
|
||||
}
|
||||
if (victim instanceof Player) {
|
||||
((Player) victim).getSettings().updateRunEnergy(10);
|
||||
|
|
|
|||
|
|
@ -52,8 +52,9 @@ public final class FeintSpecialHandler extends MeleeSwingHandler implements Plug
|
|||
}
|
||||
state.setStyle(CombatStyle.MELEE);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.0, 1.0)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, RandomFunction.random(1.0, 1.2)));
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.0, 0.25)) {
|
||||
int minDamage = calculateHit(entity, victim, 0.2);
|
||||
hit = minDamage + RandomFunction.random(calculateHit(entity, victim, 1.0) + 1);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ public final class HamstringSpecialHandler extends RangeSwingHandler implements
|
|||
state.setMaximumHit(max);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, victim)) {
|
||||
hit = RandomFunction.random(max);
|
||||
int minDamage = calculateHit(entity, victim, 0.2);
|
||||
hit = minDamage + RandomFunction.random(calculateHit(entity, victim, 1.0) + 1);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
Companion.useAmmo(entity, state, victim.getLocation());
|
||||
|
|
|
|||
|
|
@ -57,20 +57,20 @@ public final class HealingBladeSpecialHandler extends MeleeSwingHandler implemen
|
|||
}
|
||||
state.setStyle(CombatStyle.MELEE);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.12, 0.98)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.005));
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 2.0, 1.0)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.1) + 1);
|
||||
int healthRestore = hit / 2;
|
||||
double prayerRestore = hit * 0.25;
|
||||
if (healthRestore < 10) {
|
||||
healthRestore = 10;
|
||||
}
|
||||
if (prayerRestore < 5) {
|
||||
prayerRestore = 5;
|
||||
}
|
||||
entity.getSkills().heal(healthRestore);
|
||||
entity.getSkills().incrementPrayerPoints(prayerRestore);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
int healthRestore = hit / 2;
|
||||
double prayerRestore = hit * 0.25;
|
||||
if (healthRestore < 10) {
|
||||
healthRestore = 10;
|
||||
}
|
||||
if (prayerRestore < 5) {
|
||||
prayerRestore = 5;
|
||||
}
|
||||
entity.getSkills().heal(healthRestore);
|
||||
entity.getSkills().incrementPrayerPoints(prayerRestore);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ public final class IceCleaveSpecialHandler extends MeleeSwingHandler implements
|
|||
}
|
||||
state.setStyle(CombatStyle.MELEE);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.075, 0.98)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.005));
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 2.0, 1.0)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.1) + 1);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public final class ImpaleSpecialHandler extends MeleeSwingHandler implements Plu
|
|||
state.setStyle(CombatStyle.MELEE);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.1, 0.98)) {
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.1));
|
||||
hit = RandomFunction.random(calculateHit(entity, victim, 1.1) + 1);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
return 1;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue