Compare commits

...

978 commits

Author SHA1 Message Date
3cdf7767eb Updated Crumble Undead and created Snowscape API
New API will allow creating new global functions without conflicting with upstream changes.
Crumble undead now works on more undead, including Barrows brothers and revenants.
2025-12-25 21:10:40 -07:00
e9085a8270 Fixed ::dps command taking the melee attack speed of the staff instead of the autocast speed when using magic.
Also shortened the command description so it fits on the ::commands list.
2025-08-26 21:15:55 -06:00
bfa62864fa Implemented custom ::dps command to combine the information from ::calcmaxhit and ::calcaccuracy 2025-08-25 16:00:14 -06:00
b372d5e963 Players can now freely swap between unlocked spellbooks with the magic interface sort buttons.
The "Level Order" button is the Modern spellbook, "Combat First" is Ancient, and "Teleports first" is Lunar.
This makes the ability to swap spellbooks with the Mage's book obsolete, so that feature has been removed.
2025-08-25 10:55:37 -06:00
590e9fe44f Telekinetic grab now grabs all matching items within 10 tiles of the target item
If casting without line of sight, the player will now walk closer rather than simply being unable to cast
2025-08-20 13:23:00 -06:00
59c55708a6 Improvements to autolooting blacklist.
Since player names are shorter than many item names, items will now be prevented from being looted if the beginning of the name is in the block list.
The blocklist now also prevents satchels and the ring of wealth from looting items, not just familiars as it did previously.
2025-08-19 11:53:24 -06:00
5a896cecb4 Alchemy Improvements
Experimental note spell that replaced low level alchemy was removed. Now, Low level alchemy casts faster and alchemizes 10 items per cast, making it a viable alternative to alchemize cheap items in bulk.
Both alchemy spells continuous cast time was reduced from 90 to 60 seconds, but can be refreshed at any time by manually casting again.
Explorer's ring was improved. It no longer has a dialogue prompt and also alchemizes 10 items per cast, same as the spell version.
2025-08-18 14:26:19 -06:00
e046f46ed2 Slower melee weapons now do a minimum damage on successful hits to compensate for the lower dps.
The minimum damage is 10% of the max hit for each tick below scimitar speeds (rounded down). This leads to a maximum dps increase of 10% for 5 tick weapons, 22% for 6 tick, and 40% for 7 tick. Usually less though, due to the rounding.
Also added the formula to the ::calcmaxhit command so players can see the minimum hit in game.
2025-08-18 08:29:34 -06:00
2ecdde1011 The Fairy Ring interface now shows all destinations, not just the ones you have visited before. 2025-08-17 09:21:30 -06:00
cd8cce30a0 Fixed Plain Satchel not looting noted items 2025-08-16 20:06:07 -06:00
06055c0ff8 Remove another check preventing Ancient magick teleport spells from working in the wilderness for non-admins. 2025-08-15 11:41:12 -06:00
6e91725d58 Ghostly Robes now also prevent NPC aggro when the full set is worn
This is shared with the Protect from Summoning prayer. In addition, the effect was improved so a hidden player cannot shield another player from aggro by standing between them and the NPC
Fixed missing animations and sounds for the Shadow Sword
2025-08-15 11:03:21 -06:00
a9065d763b Even more steps to remove random events 2025-08-14 16:56:30 -06:00
2ad90e9ed8 Fixed Combiniation rune consumption and rebalanced rune satchel
Combination runes have been fixed. A spell using 1 air and 1 earth rune will now only use 1 dust rune instead of 2.
Rune satchel has been changed. Instead of allowing only catalytic runes, it now allows all runes but only has 6 slots. In addition, combination runes can be used from the satchel.
2025-08-14 16:47:56 -06:00
cecdb97b19 Several Housing improvements
Can enter house from any house portal in the world, and can exit to any portal the owner has the construction level to move their house to.
Can enter house even if owner is not home. House is no longer unloaded when the owner leaves, instead is unloaded when the last player leaves. Guests are kicked when owner logs out.
Locking house persists after logout/login. Using the Building mode buttons when outside the house allows remotely locking/unlocking the house.
Teleport to House and Tablet now teleport to the last house that was entered through a house portal, if it is online and unlocked. Falls back to your own house if that fails.
2025-05-13 14:29:51 -06:00
52185005aa Enchanting spells repeat if there are more of the same item in the player inventory 2025-05-06 10:57:31 -06:00
7e8c2d8883 Herblore makes potions with 4 doses instead of 3. 2025-04-21 11:36:02 -06:00
af446a4c27 Changed Construction Workbenches to no longer require upgrading
Since hotspot upgrading is not in, they were requiring an unobtainable item in order to craft.
They now only require oak planks and steel bars. The ammounts have been increased to compensate for the lack of upgrade mechanic.
2025-04-17 09:47:30 -06:00
67990205b4 Fixed Ibis not rewarding exp when catching swordfish 2025-04-12 08:31:36 -06:00
fa429edc03 Fixed Ibis familiar foraging raw fish instead of cooked fish 2025-04-12 07:43:03 -06:00
3f0c44b1c3 Firemaking improments
Improved the firemaking repeat pulse. Logs are now consumed after the space is verified, preventing loss of logs when running out of room. Additionally, the timing has changed to match the animation better.
Firemaking now also repeats when done by using a log on a pyrelord. This requires a tinderbox in your inventory, so that the pulse can be interrupted by dropping it.
Also fixed the bug where pyrelords could light logs you didn't have the firemaking level for.
2025-04-11 12:07:51 -06:00
b3196a282c Implemented construction training in workshop
As a temporary feature until making flatpacks is implemented, working at a workbench will simply consume planks for construction exp. Less clicking than creating and destroying tables over and over.
Each plank type requires a specific construction level and workbench tier to use.
2025-04-02 11:42:28 -06:00
4053fdf43c Fixed null pointer exception when runecrafting without a familiar 2025-04-01 11:58:25 -06:00
415aa512fb Satchels can now be emptied by using on a banker npc
This is to address some banks (like zanaris) not having a bank booth
2025-04-01 11:55:26 -06:00
54055e36d0 Runecrafting pouch improvements
Using any of the essence pouches on a bank booth, bank chest, or banker npc will refill all the pouches in the player inventory, as well as their familiar.
When runecrafting, if the player runs out of essence then essence will be withdrawn from the familiar and pouches.
Both of the previous functions only work on pure essence, not rune essence.
Also moved the Ourania teleport closer to the altar.
2025-04-01 11:47:08 -06:00
269eb82850 Added bank tab handling for the Costume Room Bank 2025-04-01 08:46:49 -06:00
4d7f26bb47 Disabled Easter Event 2025-04-01 08:38:50 -06:00
7538322006 Implemented Costume Room Bank
Interacting with the fancy dress box in the costume room of a player owned house will allow access to this extra storage.
Items stored in this bank count as "worn" when doing treasure trail emote clues.
2025-03-31 13:03:41 -06:00
08ffa6fee6 Crafting Gold Jewellery will automatically take gems from the Gold Satchel 2025-03-30 15:53:05 -06:00
randy
bfbfae8391 Merge pull request 'Update from 2009scape' (#18) from 2009Scape/Server:master into master
Reviewed-on: #18
2025-03-27 19:36:57 -06:00
45ee87e64e Blast Furnace improvements
Shoving coke no longer requires intense clicking, the player will keep shoveling until the stove is full.
Adding ore that requires coal to the conveyor belt will take the needed coal from the gold satchel, if carried.
2025-03-27 19:30:06 -06:00
Lucid Enigma
bcc3bc069e Potentially fixed bank visuals when opening bank 2025-03-25 20:58:27 +11:00
Player Name
48bc0ffb28 Fixed requirement check issue with PoH portals checking for Plague City completion 2025-03-25 20:55:37 +11:00
DeadlyGenga
7b1ebd4608 Added melee attack animation to Mystic Mud staff 2025-03-25 20:52:15 +11:00
Alex Page
1b0a7d5fca Fixed random events returning players to Lumbridge 2025-03-25 20:51:47 +11:00
sirdabalot
fc2247f457 Fixed teleport on logout for pest control landers 2025-03-25 20:49:09 +11:00
Alex Page
47ac5e93d6 Fixed issues causing pie crafting to stop or consume additional ingredients 2025-03-25 20:48:27 +11:00
Lucid Enigma
63f8ec3cbf Fixed facial expressions in dialogue for Tree Gnome Village NPCs 2025-03-25 20:37:27 +11:00
Player Name
0622aed00c Fixed incorrect items in circulation
Corrected incorrect rune kite (h)
Corrected incorrect adamant kite (h)
Corrected incorrect lamps
Corrected incorrect blurberry specials
2025-03-25 20:28:15 +11:00
4799069ebd Summoning rework
Pouches are not consumed. Points are not lost when summoning. However, lifespan is directly tied to summoning points, and the familiar despawns at zero points.
Created a new pouch storage that can be accessed from the summoning tab by pressing "call pet" when no familiar is active. This allows freely switching familiars as long as points are maintained.
Special move points start at empty instead of full, and replenish 1 point every 3 ticks instead of 15 points every 50 ticks.
2025-03-22 21:23:28 -06:00
4991b07ff8 Changes to Gold Satchel
Only coal will be used from the satchel when smelting, the other ores must be in the inventory (to prevent smelting more than you can carry).
Bars and gems (cut and uncut) can now also be stored in the satchel.
2025-03-21 14:59:52 -06:00
7be39c73b9 All satchels now autoloot items they can hold
The plain satchel, due to its ability to carry any item, will only loot items that already exist in the satchel.
2025-03-17 15:48:40 -06:00
a5eb1ea929 Elemental Battlestaves can optionally be crafted with a Dramen staff instead of a Battlestaff 2025-03-17 10:42:24 -06:00
d02b16d970 Selecting "Make 10" on crafting dragonhide gear now makes 30. 2025-03-17 10:19:17 -06:00
07d8bb6a13 Silver Sickle custom bonecrusher now also "buries" ashes that are dropped by enemies. 2025-03-17 08:53:29 -06:00
61f5120cfc Fixed attack range when attacking large creatures from certain angles
When attacking a 2x2 or larger creature from the SW, attack range would be reduced. Most noticeable on halberds. Fixed by checking the closest tile when attacking from a distance.
2025-03-17 08:24:43 -06:00
fb0dd3a27d Minor fixes for the custom runecrafting implementation
Fixed the exp rate for mind and fire runes.
Combination runes now also get double exp like the rest of runecrafting, and all of them give the same exp as lava runes
Added a message when crafting combination runes without a binding necklace.
2025-03-13 11:19:56 -06:00
81730af934 Customized world list info 2025-03-12 12:04:53 -06:00
6458a6ef95 Satchel changes. Rune satchel allows all runes in Boosted mode. Red satchel allows clue scrolls. 2025-03-12 11:30:37 -06:00
b109b98247 Strange teleorb custom teleport item now only requires 2 Law runes per charge instead of 20 2025-03-12 09:52:19 -06:00
daf312ce6b Fixes related to ironman mode and exp rates
Default exp rate is now 1.0, Restored the option to select 10x (no longer limited to hardcore ironmen)
Restored option to select hardcore ironman mode.
Permadeath now properly clears the custom satchels.
Ironmen can no longer trade (custom feature allow untradebale items to be traded was allowing ironmen to trade all items with a warning)
Implemented option to select Boosted mode
2025-03-12 08:31:22 -06:00
Player Name
dda80d535b Fixed a pet growth bug that could cause an error logging in 2025-03-10 14:18:27 +11:00
9c8c2ada70 Can now talk to people on Lunar Isle even if your seal of passage is in the bank 2025-03-08 15:00:08 -07:00
18d30a3e1e Added ability to swap spellbooks by operating the Mage's Book
The spellbook needs to first be unlocked by completing the quest and using the book on the respoctive altar.
2025-03-08 14:50:09 -07:00
9926b5c244 Fixed autocast bug - Player autocast spell now loads properly on login
This was caused by items being unequipped and re-equipped on login to verify that the player meets the requirements to use it. As a consequence of this bugfix, if the requirements for an item change (like a new quest comes out) then the item won't be forcibly unequipped. I can live with that though.
2025-03-06 21:40:20 -07:00
40d5478b57 Runecrafting rebalance - use one essence at a time
Runecraft with one essence at a time instead of the whole inventory at once. Doubled rune and exp output to compensate.
Also, Ourania and Combination runes are now affected by rune multiplier.
All elemental runes share the same level, exp, and multiplier as air runes.
Add small multiplier for Soul Runes.
2025-03-06 05:57:40 -07:00
randy
5eddd5e98a Merge pull request 'Merge 2009scape updates' (#17) from 2009Scape/Server:master into master
Reviewed-on: #17
2025-03-05 19:11:53 -07:00
fe117e6976 Added Fountain of Heroes to main floor of the Heroes Guild 2025-03-05 15:57:02 -07:00
c59e13f0aa Added Spirit Weed Seeds to Master Farmer drop table 2025-03-05 15:50:40 -07:00
e88bdf94d3 Port Phasmatys entry fee can be paid with Ecto-tokens in the bank 2025-03-05 15:15:24 -07:00
a411c7a5e2 Custom Silver Sickle bonecrusher functionality improvements
The automatic bone burying function now works when the sickle is equipped or in the inventory, and also affects bones from hunter traps.
2025-03-05 11:21:34 -07:00
16da0ed93e Implemented custom satchels
These satchels are normally from creature creation. The custom versions can be crafted by using an enchantment spell on hides, and have a stackable inventory that only stores certain items.
- Plain: Level 1 enchant on Blue D hide. Carries anything but can only be emptied by using it on a bank booth.
- Green: Level 2 enchant on Green D hide. Carries any seed or herb. Harvesting farming plots with the satchel equipped returns noted produce.
- Red: Level 3 enchant on Red D hide. Carries summoning charms. Charms dropped by mobs are automatically added to the satchel.
- Gold: Level 4 enchant on Dagannoth hide. Carries ore. Smelting at the furnace will use ore in the satchel.
- Rune: Level 5 enchant on Suqah hide. Carries catalytic runes. Spells will use runes in the satchel.
- Black: Level 6 enchant on Black D hide. Placeholder, as I don't have a use for it yet.
2025-03-05 09:34:48 -07:00
249c501184 Squashed commit of the following:
commit 3177468c3261b783bdab2486e939121d7d28bff3
Author: randy <randy@in.snowlab.cc>
Date:   Mon Feb 24 20:35:53 2025 -0700

    Final touches on teleorb

commit e7b41fbf509150ef489ab2644e55b0d5baaec638
Author: randy <randy@in.snowlab.cc>
Date:   Mon Feb 24 19:22:04 2025 -0700

    Added new teleorb file

commit f99da5b28817ab5b03fe0506f0e9442d463381a8
Author: randy <randy@in.snowlab.cc>
Date:   Mon Feb 24 19:20:56 2025 -0700

    Implemented Strange Teleorb as a custom teleport item

Implemented Strange Teleport as a custom teleport item
This item is crafting by casting Charge Air Orb on the Abyssal Rift at the center of the abyss. It can be inspected to save a location and add charges, and can be activated to teleport to the saved location. Charges require 20 law runes or an additional orb.
2025-02-24 20:44:17 -07:00
Kennynes
448f970c10 Fixed wrong door used in heroes' quest 2025-02-23 13:13:47 +00:00
Oven Bread
83b8689b86 Corrected quizmaster lamp reward 2025-02-23 04:02:11 +00:00
randy
7592372dc4 Merge pull request 'Update master with 2009scape updates' (#16) from dev into master
Reviewed-on: #16
2025-02-20 20:49:37 -07:00
randy
9b8ba3b6dd Merge branch 'master' into dev 2025-02-20 20:47:03 -07:00
680a08ea98 Merged updates from 2009scape 2025-02-20 19:43:05 -07:00
Oven Bread
6362eee753 Can now recover your digsite trowel from the examiner 2025-02-20 10:53:59 +00:00
Oven Bread
f0ee476e42 Fixed pyramid spawns not despawning
Relaxed getting thrown out of the pyramid to rates that appear more authentic
2025-02-19 07:33:42 +00:00
Player Name
0e65f20223 Fixed another softlock in The Fremennik Trials 2025-02-19 07:31:29 +00:00
Player Name
af58fae1fc Corrected Biohazard requirements check when using West Ardougne's eastern gates 2025-02-19 07:30:51 +00:00
Oven Bread
74ed5e1bee Fixed bug where swamp tar interactions could steal an entire stack 2025-02-19 07:29:26 +00:00
Player Name
cf08e700fb Runecrafting pouches now synchronise across bank instances
BoB can no longer be used to smuggle weapons to Entrana
2025-02-18 06:24:15 +00:00
Player Name
d65a53b275 Fixed loss of equippable items when swapped with another item that is dropped in the same tick 2025-02-18 06:03:18 +00:00
Player Name
fb9d6307b3 Corrected diamond bolts (e) effect
Removed inauthentic Verac armour effect of +1 max hit increase
2025-02-18 04:32:21 +00:00
Player Name
45fb89ec73 Hostile random events now take the player's summoning level into account
Random event combat level is now selected authentically resulting in more difficult hostile random events
2025-02-17 10:44:44 +00:00
Oven Bread
50ba3682b5 Corrected fishing contest quest log
Fixed dialogue after fishing contest
2025-02-17 10:42:19 +00:00
Oven Bread
df73f4a171 Fixed child animations for the following NPCs:
Boy (Witch's House quest)
Kanel (Inside Gertrude house)
Philop (Inside Gertrude house)
Shilop (Gertrude's Cat quest)
Wilough (Gertrude's Cat quest)
2025-02-17 10:40:27 +00:00
GregF
9eedfc2336 Added some new regions 2025-02-17 10:37:28 +00:00
Ryan
e25780a4c5 Fixed player status SQLite conversion breaking on usernames with spaces 2025-02-16 11:10:18 +00:00
GregF
b6560c0e3f Implemented Mogre miniquest 2025-02-16 10:42:27 +00:00
Player Name
2d1a626df0 Zamorak robe top and bottom now count as Zamorak god items
Zamorak robe top and bottom now allowed into Entrana
Implemented the right-click take-boat options for the monks of Entrana
Fixed some silly typos in the Monk-of-Entrana dialogue
Removed unused god item definitions
2025-02-16 10:23:21 +00:00
GregF
4f97dbef8c Completed very large refactor of Plague City quest and related functionality 2025-02-16 10:19:20 +00:00
Player Name
be76ca143b Fixed softlock in Priest in Peril and The Fremennik Trials 2025-02-16 10:03:20 +00:00
Elbarto 2
053254b504 Corrected restore for various consumables 2025-02-16 09:48:21 +00:00
Oven Bread
486ca4bb19 Implemented Desert Treasure quest 2025-02-16 09:33:56 +00:00
DeadlyGenga
104533c11d Corrected stats, levels and combat styles of many familiars 2025-02-16 07:40:42 +00:00
Oven Bread
9886049429 Implemented Zogre Flesh Eaters quest 2025-02-16 07:09:36 +00:00
Player Name
f1131b7d00 Made random event teleports more robust, fixing edge cases 2025-02-16 07:00:13 +00:00
Player Name
be47c1d5c9 Added cats raised to ::stats
Added food cooked to ::stats
2025-02-16 05:35:27 +00:00
Player Name
bb860b60e0 Pest control XP formula is now authentic, includes 1% XP bonus if handing in 10 points or more and 10% XP bonus if handing in 100 points or more 2025-02-16 05:32:57 +00:00
Oven Bread
fed309a70b Fixed map areas that caused client crashes in HD 2025-02-16 05:28:53 +00:00
Player Name
1afd4d5328 Fixed bug preventing The Fremennik Trials lyre concert being marked as completed 2025-02-16 05:22:36 +00:00
Player Name
a6eb706358 Corrected many examine texts 2025-02-16 05:20:14 +00:00
Oven Bread
957477b9b0 Fixed Death Plateau softlock in Dunstan dialogue
Fixed Harold not accepting blurberry special
Spiked boots now accessible
2025-02-16 05:17:13 +00:00
Oven Bread
4387b346dc Implemented The Curse of Zaros Miniquest 2025-02-13 12:34:23 +00:00
Player Name
618d39d73c Fixed shooting star resetting on server shutdown 2025-02-13 11:30:02 +00:00
sirdabalot
62a7dd4324 Ported kill stats and rare item drop storage to sqlite from json
This fixes lengthy and memory intensive server shutdowns
Existing global_kill_stats.json will be imported on first run
2025-02-12 12:17:02 +00:00
GregF
212ce57580 Fixed barbarian fishing xp rate manipulation 2025-02-12 11:35:17 +00:00
84951244f9 Farming leprechauns now give free buckets
There is no way to increase the limit past 31, but buckets are so cheap they are just an inconvenience. So now you can deposit and withraw any number of buckets, regardless of what is stored.
2025-02-11 11:12:39 -07:00
randy
389c5858d0 Reverting sliding scale exp multiplier
Reverting manually instead of doing a git revert because this version of gitea has an error when attempting reverts.

I still like how it reduced the early game boost, however it has some disadvantages. It's impossible to calculate the needed number of actions for a certain level, quest and minigame rewards get more valuable the longer you put them off, and some skills have no early game content and are a bit of a slog. Setting it back to a static multiplier.
2025-02-11 10:35:10 -07:00
randy
5540febf6e Reverting sliding scale exp multiplier
Reverting manually instead of doing a git revert because this version of gitea has an error when attempting reverts.

I still like how it reduced the early game boost, however it has some disadvantages. It's impossible to calculate the needed number of actions for a certain level, quest and minigame rewards get more valuable the longer you put them off, and some skills have no early game content and are a bit of a slog. Setting it back to a static multiplier.
2025-02-11 10:23:06 -07:00
Player Name
8a4ea5d1f3 Runecrafting skillcape now only consume a charge if the teleport took place
Improved navigation of the runecrafting skillcape teleport menu
Runecrafting skillcape message improvement
2025-02-11 13:17:20 +00:00
MrKingFish
0f14639e9b Added examine text for Ahad, Phingspet and Grimesquit 2025-02-11 13:13:31 +00:00
Player Name
e63c6f523a Fixed bug where ::forcegravedeath could make admins lose admin status
Added ::makeadmin command to promote accounts to admin
Added ::dropadmin command to demote accounts from admin
Added ::setpestpoints to set Pest Control points
Testing commands now take optional player name argument ::max, ::noobme, ::setlevel and ::addxp
2025-02-11 13:06:49 +00:00
Oven Bread
612ccc6776 Implemented Maze random event 2025-02-11 13:03:30 +00:00
Oven Bread
b5784c5782 Implemented Quiz Master random event 2025-02-11 12:59:25 +00:00
Oven Bread
867c332466 Populated Gnome Stronghold area 2025-02-11 12:50:41 +00:00
Player Name
8b1763c3ba Improved inventory handling for Jossik 2025-02-11 12:47:06 +00:00
Elbarto 2
d0fdf08d13 Added Plant Cure, Compost and Supercompost to the ::farmkit admin command 2025-02-11 12:18:58 +00:00
8e822234fb Implemented shared banks aka clan banks
Players can talk to a banker to enable clan banks. When enabled, any banking function will use the primary bank of the owner of the clan chat the player is in. This only works while the bank owner is online; if they are offline the player will fallback to their own bank.
2025-02-08 19:46:04 -07:00
718d7e39e1 Cracking safes the the Rogue's Den now repeats
The repetition will stop if you move away, get low health, or run out of inventory space.
2025-02-08 19:46:04 -07:00
Player Name
d91f77c294 Refactored how quests are referred to internally
Fixed numerous requirement checks for Rag and Bone Man II, The Lost Tribe, The Tourist Trap, Waterfall Quest and The Fremennik Trials
2025-02-09 02:37:14 +00:00
7b5ac708dc Implemented shared banks aka clan banks
Players can talk to a banker to enable clan banks. When enabled, any banking function will use the primary bank of the owner of the clan chat the player is in. This only works while the bank owner is online; if they are offline the player will fallback to their own bank.
2025-02-07 16:40:10 -07:00
dd35e479c1 Cracking safes the the Rogue's Den now repeats
The repetition will stop if you move away, get low health, or run out of inventory space.
2025-02-05 21:32:27 -07:00
Player Name
c03947e0b0 Cleaned up legacy save code 2025-02-03 00:48:51 +00:00
Oven Bread
acc6c182a5 Implemented Tears of Guthix Quest
Implemented Tears of Guthix Minigame
2025-02-01 14:20:43 +00:00
Player Name
1b85808885 Fixed hostile random events attacking other players
Fixed players being able to attack hostile random events for other players
Hostile random events now authentically only reward 1/16th xp (except for pheasants, which give 0 xp)
2025-02-01 14:15:45 +00:00
Player Name
2cf8392691 Fixed incubator appearing to lose contents 2025-02-01 14:13:26 +00:00
Player Name
4a016d45e5 Fixed farming patches wrongly getting diseased during offline catchup 2025-02-01 14:08:55 +00:00
Player Name
cd43f8d269 Star sprite bonus now drops bonus ore if inventory is full
Rocks mined attribute now takes into account bonus ore
2025-02-01 14:07:03 +00:00
troido
0a26d5039a Aggressive NPCs will no longer always attack the last player to enter the area 2025-02-01 14:04:03 +00:00
Player Name
c3929cf06c Fixed telegrab through walls 2025-02-01 14:00:59 +00:00
Player Name
fcbea5acdc Fixed some incorrect replacement doors in Rellekka
Disabled the unimplemented TzHaar door
Fixed some doors causing buggy player movement
2025-02-01 13:58:55 +00:00
DeadlyGenga
3d7e93b6c2 Refactored Antifire potion effect
Relicym Balm can now cure disease
Antifire potion effect now persists through log out
2025-02-01 13:53:10 +00:00
Ceikry
6e9f3cb8b9 Disabled the ability to create new HCIM accounts
Disabled the ability to select HCIM 10x xp rate
Existing HCIM will turn back to standard players after their next death (all permadeath rules still apply for that death)
Players on HCIM 10x will be reverted to 5x after their next death
If the player is in combat and disconnects via AFK timeout, then their forced logout timer has been reduced to 30 seconds from 15 minutes
If the player is in combat and x-logs or disconnects via network issues, then their forced logout timer has been reduced to 5 minutes from 15 minutes
2025-02-01 13:48:18 +00:00
GregF
0c8efbac7a Added all missing NPCs to config file for future use 2025-02-01 13:42:53 +00:00
Tooze
ccc60b1240 Implemented knife spawn in Sorcerer's Tower 2025-02-01 13:38:50 +00:00
Player Name
818ffc01e7 Removed random events from Tutorial Island 2025-02-01 13:27:04 +00:00
GregF
f37b30749e Iron men can no longer participate in lootshare 2025-02-01 13:25:23 +00:00
Player Name
edc6f9cf07 Implemented Gaze of Saradomin
Fixed respawn bugs
2025-02-01 13:23:42 +00:00
DeadlyGenga
064edfbbe4 Implemented spirit saratrice 2025-02-01 13:20:27 +00:00
GregF
b62f4e9525 Implemented black swan NPC 2025-02-01 13:19:17 +00:00
Player Name
57f5617fe8 Fixed loss of draconic visages if used on an anvil without an anti-dragon shield in the player's inventory
Fixed dragonfire shield and dragon square shield smithing not checking for a hammer in inventory
2025-02-01 13:18:19 +00:00
GregF
6c386e6ed2 Implemented Hunters' Crossbow 2025-02-01 13:15:07 +00:00
GregF
93890769e1 Significantly improved slayer tasks implementation
More authentic tasks
Better dialogue and hints
New tasks added in preparation for when relevant quests are implemented
2025-02-01 13:14:04 +00:00
Oven Bread
4039c0123b Correctly limited quest log and achievement diary scrolling 2025-02-01 13:12:58 +00:00
Player Name
27f2d457ea Fixed issues in Jarvald's dialogue 2025-02-01 13:08:20 +00:00
Oven Bread
c6b508b3ed Lucien now gives a pendant after Temple of Ikov completion 2025-02-01 13:07:49 +00:00
Oven Bread
67b6855370 Implemented Sea Slug quest 2025-02-01 13:07:39 +00:00
GregF
4480618748 Added pirate clothes to store and examine text to Mike 2025-02-01 13:06:53 +00:00
Player Name
9fff4dbb5d Implemented spade pickup in the Rimmington mine
Rewrote the permadeath code to more thoroughly wipe HCIM when they die
HCIM permadeath code destroys items dropped on death
Cleaned up redundant blast furnace player save code
2025-02-01 13:02:22 +00:00
GregF
6a68cf9d7c Fixed issue with trees not being able to be health checked 2025-02-01 12:56:18 +00:00
Oven Bread
e34a81ec6c Implemented Heroes Quest 2025-02-01 12:29:51 +00:00
Oven Bread
00b5a44c31 Added additional dialogue helpers 2025-02-01 12:23:10 +00:00
Player Name
f75577d41d ::itemsearch now usable by everyone 2025-01-20 13:56:18 +00:00
Player Name
3838f01adf Made POH deaths safer, fixing random event bug 2025-01-20 13:54:34 +00:00
Player Name
a932c309b3 Fixed bug where ultimate ironmen could have rewards sent to bank
Fixed the allquest command on new accounts on first login
2025-01-20 13:52:46 +00:00
Player Name
9af776e3c6 Refactored some runecrafting code
Corrected the Ourania altar reward, now fully authentic
2025-01-20 13:49:58 +00:00
gregf36665
39634b6caf Implement penguin egg acquisition 2025-01-20 13:26:56 +00:00
Oven Bread
eb3884180e Signpost improvements
Minor quest log fixes
Implemented map for talismans in Wizard Tower basement
2025-01-20 12:56:20 +00:00
Player Name
d5c7d74767 Fixed a bug where the player could get locked planting while farming 2025-01-20 12:46:57 +00:00
Player Name
d08656021c Fixed pillory random event completion teleport location 2025-01-20 12:35:01 +00:00
Kennynes
9beb7219ea Fixed examine texts for some cabbages and other items 2025-01-20 12:25:25 +00:00
Player Name
deecf136bc Fixed slayer cape perk activation 2025-01-20 12:08:58 +00:00
Player Name
b849de2dab Fixed magic secateurs patch bones not applying 2025-01-20 12:00:38 +00:00
GregF
b4950343ec Fixed bug preventing super restore recovering prayer 2025-01-20 11:49:01 +00:00
6cf3e97985 Merge pull request 'Implemented familiar auto loot blocklist' (#10) from dev into master
Reviewed-on: #10
2024-12-08 14:46:37 -07:00
579df71848 Implemented familiar auto loot blocklist
Adding the name of an item to the player ignore list will prevent familiars from looting that item.
2024-12-08 14:36:34 -07:00
bd8669f629 Merge pull request 'dev' (#9) from dev into master
Reviewed-on: #9
2024-12-07 20:23:38 -07:00
97053798ff Fixed free spell cast bug and removed delay on bind spells
The chance to not consume runes was being checked before checking if the runes were in the inventory, allowing casting of spells that the player did not have the runes for. This has been fixed. Additionaly, the forced delay on bind spells has been removed, so they can be spammed. This is definitely unbalanced for pvp, nobody does pvp so it's fine. If possible in the future, reinstat the delay when targeting players.
2024-12-07 20:16:45 -07:00
b1ca068e3f Removed delay on note spell casting
Since it only does 10 items at a time, it is often cast 2-3 times in a row. The delay is unnecessary for this spell.
2024-12-07 19:54:27 -07:00
05c1ac1dc0 Added runecrafting exp when crafting altar teleport tablets 2024-12-07 19:36:12 -07:00
b381d78362 Merge pull request 'dev' (#8) from dev into master
Reviewed-on: #8
2024-12-06 09:17:07 -07:00
ed9a6fa118 Merge branch 'master' into dev 2024-12-06 09:16:27 -07:00
ecb3a66d58 Fishing with Hunter feathers and Note Spell changes
Feathers earned with hunting can now be used for fly fishing. The note spell no longer charges a 10% tax, but is instead limited to noting 10 items at a time.
2024-12-06 09:13:09 -07:00
ffe1e11d11 Traps with a catch now last 10 minutes instead of 1 2024-12-06 08:05:40 -07:00
ff80ec3b51 Merge pull request 'Update Master' (#7) from dev into master
Reviewed-on: #7
2024-12-05 15:59:23 -07:00
be7143be20 Updated pickpocket to stop if health gets low
If your health is low enough that you'll die if you get caught, then pickpocketing will stop repeating.
2024-12-05 15:53:31 -07:00
a788b64e44 Added Burgh de Rott bank functionality 2024-12-05 15:20:10 -07:00
6cc6a4c69c Fixing minecarts that lead to keldagrim. 2024-12-05 15:01:26 -07:00
30113613e0 Merge pull request 'Update Master' (#6) from dev into master
Reviewed-on: #6
2024-11-24 22:03:59 -07:00
40196333ad Changes to Ava's devices from Animal Magnetism
The devices no longer need to be worn, completing the quest is enough. Also standardized arrow break rates to exactly 20% at all levels. Ava's devices will pick up 100% of the arrows that don't break.
2024-11-24 21:52:06 -07:00
f3c9dd2d9c Changed Low Alch spell into Note Spell
Casting on an item will note all of the matching items in your inventory. 10% of the items (rounded down) are charged as a "tax" so that other remote deposit options are still competitive.
2024-11-24 21:07:42 -07:00
f258632fb5 Farming produce is automatically noted if wearing an amulet of farming or amulet of nature
Since the leprechaun is right there and can do the same function, this just saves the annoying clicking of harvesting and using the produce on the leprechaun over and over.

Note that the other functions of the amulet of farming or amulet of nature are not implemented yet.
2024-11-24 20:21:34 -07:00
Oven Bread
7749e8263f Introduced new dialogue engine compatible with spinoff revision 578 project 2024-11-22 06:59:42 +00:00
e19c89f441 Merge pull request 'Update master' (#5) from dev into master
Reviewed-on: #5
2024-11-21 17:45:09 -07:00
3119a01e3f Additional steps to remove random events
The random events came back for some characters, seems the timer got started somehow. This change should pause the timer every time it's registered, so it should never start again.
2024-11-21 17:44:13 -07:00
fba2e413cf Added small summoning exp gain every minute a familiar is summoned
The gain is the summoning level required + 10.
2024-11-21 17:10:08 -07:00
456925264b Merge pull request 'Push updates to master' (#4) from dev into master
Reviewed-on: #4
2024-11-21 06:43:18 -07:00
6ed0ead8a7 Removed door dialogue in the stronghold of security
No need to explain how to secure your account over and over, we aren't kids.
2024-11-20 19:39:50 -07:00
6cca2d1bed Allow trading any item
Attempting to trade an untradeable item will give a warning message, but the trade will still be allowed to go through.
2024-11-20 19:33:24 -07:00
440f8ce3ac Corrected default exp rate
Changing the default exp rate to anything other than 5.0 causes the new rate to override the player's selection at tutorial island. I lowered the default just to reduce the amount of exp you gain during tutorial island, but with the new scaling exp rate that's no longer required.
2024-11-20 19:21:17 -07:00
ee11daa0be Merge pull request 'Refresh dev environment' (#3) from master into dev
Reviewed-on: #3
2024-11-17 17:16:58 -07:00
b33ad22740 Removing Jarvald reference to NPC Constlib, since I have no idea how to update that
The original change (fb2535e248) Says it requires a constlib update. From what I can tell, that is made here: https://gitlab.com/2009scape/tools/rs09-constants-library.

However, I have no idea how to actually get a new build of this. Perhaps the server files will be updated to include this in the future, but in the meantime I am changing this back so the server actually starts.
2024-11-17 17:16:20 -07:00
3f8828457b Merge pull request 'Initial build of Snowscape' (#1) from dev into master
Reviewed-on: #1
2024-11-17 15:51:17 -07:00
793acecf2e Merge pull request 'Updating from 2009scape' (#2) from 2009Scape/Server:master into master
Reviewed-on: #2
2024-11-17 15:45:30 -07:00
eebcb25274 Updated fletching message to include the new arrowshaft quantities 2024-11-17 14:18:44 -07:00
9ed560cca6 Can now fletch arrow shafts from higher tier logs, getting more arrowshafts in return
This uses the same exp, level requirements, and arrowshaft output as Old School Runescape.
2024-11-17 14:16:39 -07:00
a86b734e0d Replaced "Make 10" with "Make 30" for crafting interfaces that use the chat dialogue
The client will still display 10, but the action will repeat 30 times.
2024-11-17 13:04:51 -07:00
5319cabdae Selecting "make 10 bars" in the smelting interface will now make 30, allowing a full inventory 2024-11-17 12:59:35 -07:00
ee6f83eb7e Improved timing of pickpocket repeating, and allowed repeating even when caught 2024-11-17 10:56:19 -07:00
63c7fc3f70 Fixed typo in variable name 2024-11-16 16:45:43 -07:00
8f55baa13e Experience multiplier now scales based on the skill level
This slows down the extremely boosted early game while still allowing the multiplier to reduce late-game grind.
2024-11-16 16:19:06 -07:00
6845a3740f Rebalanced prayer point drain rates (almost everything except protection prayers drains far less)
- Protection prayers are now all equal at 10 points per minute
- the 5%, 10%, and 15% bonus prayers now drain 1, 2, and 3 points per minute, respectively. Having all of them active at once is now a lower drain than Chivalry.
-- The attack and strength versions drain half of that, since you need two of them active.
- Chivalry and Piety now also boost magic and ranged at the same rate as attack, and have had their drain slightly lowered. (7.5 and 10 points per minute)
2024-11-16 09:47:46 -07:00
02a36f7bf7 Removed gloves of silence requirement for auto-pickpocketing 2024-11-15 12:37:47 -07:00
Ryan
79c69e3d43 Changed timestamp in logs to ISO standard datetime format 2024-11-14 12:42:48 +00:00
GregF
7d79c9a82a Construction can now be used to fix the ladder to the wilderness beacon 2024-11-14 12:14:31 +00:00
Oven Bread
e216a6366f Use the system update countdown for the daily restart 2024-11-14 12:08:21 +00:00
Player Name
9054e36288 King Bolren now gives back lost gnome amulets 2024-11-14 12:05:47 +00:00
Oven Bread
1a67932351 Implemented Pillory random event (this event occurs while pick-pocketing) 2024-11-14 12:02:37 +00:00
Player Name
7a6adda997 Authenticity improvements to runecrafting pouches. Due to changes in degrade counters, they will degrade within the next 1 or 2 fills after this update; this is a one-time event. Resolve (or prevent) this by repairing via the dark mage 2024-11-14 11:56:16 +00:00
GregF
1da53c448d Rewrote dream spell
Fixed healing rate of dream
Added sound to dream spell
2024-11-14 11:51:34 +00:00
Player Name
53dc169774 Corporeal beast authenticity improvements
Dark core will no longer jump to players in safe area
Adjusted maximum attack hits
Protect from magic now blocks the big dart attack by 40%
Now resummons the dark core when it dies
Made the dark core respawn mechanics more authentic
Dark core now drops ashes
2024-11-14 11:36:09 +00:00
Player Name
b0be48501b Made the following POH hotspots refund their non-plank items when torn down: any quest item, any guild trophy, any armor stand
Refactored some construction code
Removed decorations and hotspots for "Menagerie" rooms, which seem to be inauthentic
Changed the following hotspots to be recursive: decoration, wall chart (study)
Corrected xp for a few construction items
2024-11-14 11:18:25 +00:00
Player Name
98c99e7550 POH telescope now estimates the shooting star time based on its tier 2024-11-14 11:06:41 +00:00
Player Name
ed41f3a228 Bounty Hunter music is now unlockable 2024-11-14 11:02:26 +00:00
Player Name
a2eafa8bc0 Fixed exception on server boot related to a duplicated attempt to register dialogue for Jarvald 2024-11-14 10:44:00 +00:00
Sinipelto
2be5f9eac0 Fixed loss of combat tabs after recruitment drive 2024-11-14 10:22:04 +00:00
251934d3a9 Audded autolooting of coins and tokkul if wearing ring of wealth 2024-11-13 20:51:24 -07:00
964c95b572 Fixed noncombat spells getting the 33% chance to not use runes. 2024-11-13 15:21:17 -07:00
e7ed5b0d7a Added check to allow permanant unlock to act as a worn ring of wealth
This only affects NPC drops, not gem drops from mining.

Due to this affecting the rare drop table only, this has not been tested.
2024-11-13 14:23:17 -07:00
a6ad4f8f3b High Alching Ring of Wealth now adds permanent unlock. 2024-11-13 14:10:24 -07:00
0b05424690 Changed Imp-in-a-box to act a full deposit box. One-time use.
The Imp-in-a-box is broken, and I don't know how to fix it so I buffed it instead.
2024-11-12 21:04:11 -07:00
e45f8fa81b Implemented rune multipliers on combination runes
The altar you are at will now give its multiplier to the combination runes crafted. This only saves essence, the opposing rune cost is multiplied as well. (If you get 10 air runes per essence, then making mist runes at the air altar will cost 10 water runes and 1 essence to give you 10 mist runes).
2024-11-12 16:00:02 -07:00
3035aaa7e6 Implemented proper probabilities when using the Ourania altar 2024-11-12 15:00:37 -07:00
9143cd5f47 Fixed getting slayer exp from hunting 2024-11-12 07:52:06 -07:00
d92a3f3a8e Increase bird snare feather drops from 8 to 60
As part of the plan to make self-sufficient fletching more viable.
2024-11-12 06:24:27 -07:00
65cb778a18 Hunter traps last 10 minutes instead of 1 minute 2024-11-11 22:16:17 -07:00
563fcc23bc Farming patches now return the seeds if the plant being cleared or harvested is fully grown 2024-11-11 21:43:20 -07:00
2e68ac1522 Fixed overwritten herb cleaning line 2024-11-11 19:16:53 -07:00
62463576cf Herb cleaning is now a pulse that cleans all the matching herbs in your inventory 2024-11-11 19:14:58 -07:00
ac14e7a22e Remove last check preventing Ancient Magicks from working in wilderness. 2024-11-11 18:29:55 -07:00
f2aad1c957 Allow Ancient Teleports to bypass the isTeleBlocked function so that they work in the wilderness
Note that they are still restricted by the checks in the ZoneMonitor file, which does include teleblock checks, as well as specific wilderness levels.
2024-11-11 18:05:16 -07:00
ee3a71a5d0 Allow Ancient Magick spells to work up to level 48 wilderness. 2024-11-11 18:01:57 -07:00
root
a361915281 Familiar timer now only decreases if at zero summoning points
This change reduces the upkeep cost of Summoning, now you only need points or pouches, but not both.
2024-11-11 09:57:51 -07:00
e5e6006212 Protect from Summoning prayer now prevents NPC aggression when active 2024-11-10 22:36:00 -07:00
fa808accd4 Added requirement checks to the teleport tablets 2024-11-10 22:09:13 -07:00
df3fc6c973 Increased the Herb:Tar ratio from 1:15 to 1:45
Salamanders burn through ammo, and herbs are a lot of work to come by. This increases how much ammo you get per herb by 3x.
2024-11-10 21:17:30 -07:00
da071b795d Normal trees now have a chance to deplete, like higher level trees
This is done to make collecting normal logs for arrowshafts less click-intensive.
2024-11-10 20:55:02 -07:00
48069e2234 Added Lunar Robes to Moonclan clothing shop
There is no way to get the robes until the quest is implemented, so this is a temporary solution. The robes are very cheap, but they also aren't very good so it should be fine.
2024-11-10 20:47:32 -07:00
2e65f0d186 Changed combat spells to only consume runes 33% of the time
This is part of the attempt to balance ammo production and consumption rates.
2024-11-10 19:06:13 -07:00
7da14bd3b8 Increased Crystal Equipment charges to 12,000 2024-11-10 18:46:47 -07:00
de4f67832b Changed crystal equipment to recharge with rune arrows and kiteshields instead of coins
New Crystal Bows require 3600 rune arrows, recharging requires 3000. New Shields cost 24 Rune Kite shields, recharging requires 20.
2024-11-10 18:45:01 -07:00
d21452a8bf Increased arrowheads and other ranged ammo produced from bars by 3x
This is done with the intention to balance the value of rune arrows and bolts with the value of a rune bar (12800 if you make high-end rune gear and high alch it), as well as the value of the crystal bow (72 gp per shot).
2024-11-10 17:36:38 -07:00
e8afa4e529 Add damage scaling to Crumble Undead
The spell damage scales like Magic Dart, but due to the limitation of only affecting undead enemies, deals 2 more damage.

If the enemy is not undead, deals only 1 damage (set to 1 instead of 0 to prevent splashing abuse).
2024-11-10 15:15:10 -07:00
98e8cd4592 Fixed incorrect autocast animation for the three god spells
Also future-proofed by adding animation for Iban's blast, even though the staff is not obtainable yet and the spell can't normally be autocast.
2024-11-09 21:47:02 -07:00
974c44a041 Remove staff check when autocasting Slayer Dart and Claws of Guthix
This should have no effect on the slayer dart spell, but does allow Claws of Guthix to be autocast with the Guthix Staff and not just the Void Mace.
2024-11-09 20:29:01 -07:00
325b8f6f20 Crystal Bow and Shield no longer lose stats as they degrade 2024-11-09 15:45:48 -07:00
13e4a0b640 Added code to customize logout timer. Set to 1 hour. 2024-11-09 09:08:05 -07:00
f4c51dbafe Reduced Quest Point Requirements for Culinomancer shop so that all gloves are obtainable 2024-11-08 21:17:27 -07:00
81779f1fae Fixing missing healing on Void Spinner Familiar 2024-11-08 21:12:11 -07:00
7113ef393d Added Swamp Tar to Lumbridge General Store 2024-11-08 17:29:55 -07:00
3fd5f60d7f Increased Abyssal Titan carrying capacity 2024-11-08 16:23:02 -07:00
acfd5c90b9 Increased Abyssal Parasite carrying capacity 2024-11-08 16:22:42 -07:00
6195af3e7b Increased Abyssal Lurker carrying capacity 2024-11-08 16:22:21 -07:00
4eebee34c4 Removed Beast of Burden carrying restrictions 2024-11-08 16:21:10 -07:00
8a72ac52db Changed Summoning shard cost for all pouches to 1
Shards are a pure gold sink, which we don't need.
2024-11-08 16:09:13 -07:00
7779d03654 Added Beast of Burden Looting
Mob drops will go to a beast of burden inventory if there is room.

The Pack Yak, if it has Winter Storage scrolls in its inventory, will instead send drops straight to the bank at the cost of one scroll.
2024-11-08 15:42:16 -07:00
1f538d2976 Added agility exp gain when running 2024-11-07 15:56:58 -07:00
4b5687b8ab Added small slayer exp drop even when not on slayer task 2024-11-07 11:53:41 -07:00
d4da75e6ab Added bonecrusher functionality
If the blessed silver sickle is in the player inventory (not equipped) and they have enabled the feature by using "cast bloom", bones will not drop and instead the player will directly get the prayer experience.
2024-11-07 10:05:10 -07:00
8094465579 Added ability to toggle bonecrusher function on blessed sickle
When using "cast bloom", the sickle will grow nearby fungus as usual. If no fungus are grown, it will instead toggle the bone crusher attribute.
2024-11-07 10:02:10 -07:00
6305e2a718 Rewrote Alchemy spells to use pulse, repeating up to 30 times 2024-11-06 13:36:24 -07:00
bbaa4bbdbe Fixed exp reward calc and reduced to one fifth
The reward formula double-dipped with exp multipliers. Corrected the formula to match the original 2009 version, then reduced to 1/5 to account for the increased points given for each round.

The increased points are meant to reduce the grind for the items, but not the purchasable exp.
2024-11-06 11:06:23 -07:00
4cd703097c Increased Pest Control reward points by 5x (10, 15, and 25 for each boat) 2024-11-06 11:03:21 -07:00
1ef61d8c33 Reduced Magic Training Arena costs to 1/5th 2024-11-05 20:00:47 -07:00
54d755b12d Enabled quick banking 2024-11-05 19:48:25 -07:00
010cd58460 Updated server config to desired settings 2024-11-05 19:29:58 -07:00
9295c91a7d Plank Make now automatically recasts on matching logs 2024-11-04 20:37:26 -07:00
86913bf75f Added additional stats to Monster Examine and removed the coin cost from Plank Make.
Correctly done on the dev branch this time.
2024-11-04 19:42:31 -07:00
90c80fbd8e revert 4912b39831
revert Added additional stats to Monster Examine and removed the coin cost from Plank Make.
2024-11-04 19:40:36 -07:00
4912b39831 Added additional stats to Monster Examine and removed the coin cost from Plank Make. 2024-11-04 19:39:29 -07:00
17ac2ab4da Added Death and Blood Talismans to the drop tables of abyssal creatures 2024-11-04 19:30:28 -07:00
845a00079b Changed Soul Altar to use the Telekinetic Grab tablet instead of the Runecrafting Guild tablet 2024-11-04 19:19:38 -07:00
82681e8303 Changed Runecrafting Guild Teleport tablet to the unused Telekinetic Grab tablet 2024-11-04 19:18:39 -07:00
d74d83b2ec Fixed missing dependency for Soul Rift teleport 2024-11-04 06:13:23 -07:00
2abf540515 Added Runecrafting Guild Teleport tablet (teleports to Soul Altar) 2024-11-03 18:54:51 -07:00
78847c2415 Ourania altar now gives multiple runes per essence, the same as all other altars. 2024-11-03 18:44:48 -07:00
540db8e15a Added ability to craft altar teleport tablets by bringing soft clay to the respective altar. 2024-11-03 18:40:32 -07:00
020c10d961 Placed new Soul Altar on Crandor 2024-11-03 18:34:44 -07:00
0f00221cd9 Updated Soul Rift in Abyss to teleport to new altar on Crandor 2024-11-03 18:32:19 -07:00
bbf8f3c348 Ore rocks now only have a chance to deplete based on Mining Level and rock respawn time 2024-10-31 21:49:05 -06:00
0fddd2134b Firemaking now repeats until all the matching logs in your inventory are used 2024-10-31 15:20:14 -06:00
b35159b5b7 Implement pickpocketing auto-repeating if the player is wearing Gloves of Silence
The player.lock function doesn't run if the player has gloves on, since it prevents triggering the pickpocket action immediately afterwards. To avoid pickpocketing every tick, we check the game ticks if the player has gloves and only perform the action every other tick.

Testing indicates that manual pickpocketing can occur every 2 ticks, so the auto-repeat occurs at the same rate. If the player fails pickpocketing, the stun will prevent the auto-repeat from activating.
2024-10-28 12:54:33 -06:00
490c6d42ec Autocast changes - All God staves can autocast, and autocast is now independent of active spellbook. 2024-10-27 21:06:08 -06:00
bc5958b60d Added -Xmx flag to specify the amount of RAM the server allocates 2024-10-27 20:57:03 -06:00
cc6f33ab7e Updating mining levels for mithril, adamant, and rune to 50, 60, 70. 2024-10-27 20:49:19 -06:00
62dc8bc324 Updated Smelting levels
Lowered Adamant and Runite smelting to 60 and 70 respectively.
2024-10-27 20:42:40 -06:00
ea980fe909 Updating Smithing levels
Each item's smithing level requirement has been lowered to match the level required to smith that bar. Adamant and Rune are lowered to 60 and 70 respectively.
2024-10-27 20:41:11 -06:00
ab78bce769 Extend grave timers 2024-10-27 20:24:20 -06:00
af47ae42c1 Disabled logout timer 2024-10-27 20:22:13 -06:00
661aa22e41 Disable Random events 2024-10-27 20:16:48 -06:00
Oven Bread
876b87b72a Fixed exception occuring when JohnnyBeard dies 2024-10-12 05:34:12 +00:00
Player Name
32cd17bfa2 Fixed bugs relating to player location and random events
Improved handling of random events when the location of the abducted player is missing from save file
Added per-tick auditing of data relating to player location
2024-10-12 04:21:49 +00:00
Ceikry
393752d77b Fixed vinesweeper point exchange ratio bug
Disabled spirit kalphite scroll until bug is fixed
2024-10-11 04:52:08 +00:00
Player Name
2b460b64f2 Thread now correctly disappears every 5 items crafted, including bug fixes related to the fact
Ring of forging now correctly disappears every 140 iron ores smelt, including bug fixes related to the fact
2024-10-10 07:14:48 +00:00
Player Name
59075798ea Adventure bot improvements
Adjusted max pulse count for bots from 50 -> 75
Adjusted max skill baseline by +4 for adventure bots to 69
Added 500 lines of unique
Added 45000 bot names
Added recovery methods for bots that get stuck
Added multiple random number functions to help add more variance
Added function to handle checking if a bot is near/in a Bank
Added function to handle getting a new city
Added function to add variability to locations given to bots
Added function to check if other players/bots are nearby
Added function to handle bots banking their inventories if a bank booth is nearby
Improved random number parameters
Improved how bots are spawned & added variance to spawn location
Improved how bots interact & handle the Grand Exchange location
Improved how bots handle starting in Lumbridge
Fixed bots referencing themselves in dialogue
Fixed bots talking when they are by themselves
Fixed multiple cases where bots would get stuck in a state
Fixed multiple logic errors
Fixed issues with bots banking but not switching states
2024-10-10 07:08:57 +00:00
DeadlyGenga
034c05f512 Fixed Mystic Lava staff not counting as earth runes 2024-10-08 07:19:23 +00:00
Tobias H.
01b5e59250 Fixed missing space in pottery messages 2024-10-08 06:57:51 +00:00
Oven Bread
7d32e77860 Removed unnecessary server console debug prints 2024-10-08 06:39:25 +00:00
Oven Bread
f11149ebe2 Corrected quest log for Creatures of Fenkenstrain
Corrected quest log for Troll Stronghold
Corrected quest log for The Dig Site
Corrected quest log for Witch's House
Corrected quest log for Scorpion Catcher
Corrected quest log for Wolf Whistle
Corrected quest log for Nature Spirit
Corrected quest log for What Lies Below
Populated NPCs in Lucien's Camp (Next to Wildy Chaos Temple hut) (Inaccessible)
Populated NPCs in Black knight catacombs (WGS) (Inaccessible)
Populated NPCs in 1st level of Pollnivneach Slayer Dungeon (Smoking Kills) (Accessible)
2024-10-07 11:30:02 +00:00
Oliver Fawcett
ba1e190cdb Typo fixes for dialogue in enter the abyss and dragon slayer 2024-10-07 11:26:03 +00:00
GregF
1c9fbc79aa Fixed up wordwrap for debugging unhandled interactions 2024-10-07 11:24:01 +00:00
zsrv
218a040f8b Major farming improvements including (but not limited to):
Farming animation corrections
Farming message updates and additions
Gardeners will chop down fully grown trees for 200 gp
Gardeners will give farming advice
Compost bin debugging admin command ::finishbins restored (finishes any in-progress compost bins)
Compost bin debugging admin command ::resetbins added (resets the player's compost bins to their initial states)
Players can no longer pay gardeners to protect diseased or dead farming patches
Can no longer water dead patches
Weeds will now grow in farming patches as part of the offline catch-up
Trees that are not fully grown can now be dug up
2024-10-07 11:15:52 +00:00
Bonesy
cc8dd4edb4 Rewrote some Varrock plugins
Removed duplicated handlers for many Varrock related stairs and ladders
Fixed the Champions' Guild trapdoor being unable to be closed
Changed the model ID for the logs outside of Seth Groats's house when the axe is taken
The drawers in Guidor's house will no longer disappear. There doesn't appear to be a related open object, so they just won't open
The Benny NPC yells about newspapers again
Knocking on the door in the Varrock bank will start the dialogue with the bankers
The Varrock Census object in the Varrock castle will now open the Varrock Census interface
Added sounds for opening/closing drawers, wardrobes, and cupboards and animations for wardrobes
Added the Kudos overlay in the Varrock Museum
Corrected the spawns for archeologists in the Varrock Museum dig site area
Implemented the Varrock museum map interface to open from the objects and item
The tool shelf in the museum dig site area will now give items
Looking at the displays in the in the Natural History area of the museum will open the interface for the exam and provided some notes
2024-10-06 13:12:33 +00:00
Player Name
3982258500 Corrected iron-ore-smelting success rate 2024-10-06 13:06:07 +00:00
Kennynes
2be422e7da Reverted some tutorial island dialogue 2024-10-06 12:49:54 +00:00
Ceikry
5abe50430d Improved bank updates, likely fix for bank UI delay 2024-10-06 12:47:54 +00:00
Oven Bread
97b8ed19a6 Fixed the Priest in Peril items not showing up in HD 2024-10-06 12:45:10 +00:00
GregF
9d38357c4e Corrected Lighthouse Dagannoth drop table 2024-10-06 12:43:22 +00:00
Player Name
64fa1d89c3 Players are now rescued out of the unimplemented high-level Bounty Hunter crater 2024-10-06 12:35:49 +00:00
Player Name
e31397b42f Corrected summoning point drain rate 2024-10-06 12:29:07 +00:00
Doggo
9f61ffb153 Rewrote the swing/attack handler for authenticity:
Fixed a lot of off-by-1 miscalculations
Fixed the void ranger bonus, which should be 20%
Fixed granite maul spec not giving xp and ignoring protection prayers
Fixed accuracy being too high
Fixed set bonuses that boost attack or defence being applied twice or to all attacks
Fixed ranged attacks not taking into account prayers that boost defence or defensive attack styles
Fixed red chinchompa having the same damage as normal chinchompas
Fixed some specs being boosted by offensive prayers
::calcmaxhit now has better formatting
::calc_accuracy renamed to ::calcaccuracy for consistency with other commands, and now also gives the actual hit chance
2024-10-06 12:23:24 +00:00
Player Name
b2f7f86d6a Fixed blessing of graves belonging to ironmen
Fixed POH teleport issue
Fixed charter requirements
Fixed entrana weapon check bypass
Small authenticity improvements
2024-10-06 11:14:56 +00:00
Player Name
4799176c14 Fix bugs with familiars
Fixed a bug where familiars would sometimes not respond to the 'Call' button
Fixed random events not spawning when standing in front of the Lumbridge furnace
Fixed incorrect restrictions on familiars and random events inside POHs
2024-10-06 11:03:33 +00:00
Player Name
0a89439c80 Fixed saving of prayer points & hitpoints, dynamic level is now tracked separately to current hit/prayer points 2024-10-06 10:58:18 +00:00
Player Name
9c202aa47a Rewrote pet back end to use a more authentic system
Pets can now stack
Fixes a bug where a pet could get reset to 0 hunger and growth when dropped
Player save version migration messages are no longer shown
Pets now morph into adults in-place
2024-10-06 10:47:36 +00:00
Ceikry
6b0f942598 Fairy ring refactor
Reimplemented the travel log, fixes the issue where all the travel log interface text collapses in on itself
Travel log now displays the relevant code
Log sorting implemented
Fairy ring now remembers the last entered code and automatically re-enters it when opened
Fairy ring no longer skips letters
Direction clicks in quick succession now turn the wheel multiple times
2024-10-06 10:21:58 +00:00
Oven Bread
8db9060a40 Implemented the ogres in combat training camp 2024-10-06 09:59:03 +00:00
Player Name
f94221918f Fixed the unlocking of region-wide music tracks 2024-10-06 09:32:57 +00:00
DeadlyGenga
cc47f4b488 Fixed cockatrice, godtrice and spirit cobra egg implementation 2024-09-11 07:11:14 +00:00
GregF
5c027e2649 Corrected fletching arrow xp 2024-09-11 07:09:46 +00:00
GregF
4156f28b93 Corrected many potion effects 2024-09-11 07:07:55 +00:00
Oliver Fawcett
c271d4e74b Fixed typo in Straven dialogue 2024-08-25 03:50:33 +00:00
DeadlyGenga
97464ef1d2 Corrected All Fired Up item requirements 2024-08-23 01:29:44 +00:00
A F (Hawk)
518b5d91dd Fixed woad leaf typo in Wyson dialogue 2024-08-22 08:19:08 +00:00
Oven Bread
e25c7d7824 Implemented Recruitment Drive quest 2024-08-21 14:04:44 +00:00
DeadlyGenga
29fa9a5a21 Rune hasta requirements fix 2024-08-21 13:25:11 +00:00
Roderik
083df1aae2 Superheat ore order of precedence has been corrected 2024-08-21 13:13:15 +00:00
Jared Thorne
3a73c98e19 Improved server music config loading logging 2024-08-21 13:08:46 +00:00
Ceikry
80cb2d9ba4 Reverted fix for issue where the player could be given stacks of 0 items as it causes other regressions 2024-08-17 01:41:17 +00:00
Ryan
317b4e9b5c Reverted erroroneous config changes (fixes bots missing on single player) 2024-08-10 13:17:11 +00:00
Roderik
24143f5d20 Crafting guild sink can now be used 2024-08-10 11:27:23 +00:00
GregF
209e1ae8cf Implemented taxidermist 2024-08-10 11:13:56 +00:00
Player Name
37836ae992 Improved lootshare so that drops are awarded to clan members near a slain NPC, participation in combat is not necessary
Reconnecting in combat will no longer cause lost drops
2024-08-10 11:09:43 +00:00
Player Name
d15b47fc65 Rewrote the music system to use regions 2024-08-03 08:00:36 +00:00
Kamja Imo
58d9101ef6 Rewrote Lumbridge swamp hole handling 2024-08-03 07:24:47 +00:00
Player Name
ca8bfeab64 Trimmed crafting cape can now be used to enter the crafting guild 2024-08-03 07:20:38 +00:00
Player Name
957b1c2944 Rewrote (un)holy symbol blessing handling 2024-08-03 07:18:10 +00:00
DeadlyGenga
92fcd0ec32 Corrected granite crab pouch crafting experience from 31.6 to 21.6 2024-08-03 07:05:28 +00:00
DeadlyGenga
db3079271e Removed slayer staff from H.A.M. drop tables 2024-08-03 07:03:10 +00:00
Kamja Imo
9d6ad223cb Added frogspawn and cave eel fishing spots in Lumbridge swamp cave 2024-08-03 07:02:43 +00:00
GregF
3837bd3c26 Corrected option handling on GE interface 2024-08-03 06:59:49 +00:00
GregF
18d5d80fba Fixed issue where green dragons are called Elvargs in slayer tasks 2024-08-03 06:19:31 +00:00
GregF
9d2e173f71 Implemented ground guam as a tar recipe 2024-08-03 05:40:34 +00:00
Player Name
68c1e572b9 Changed the script processor code to no longer incorrectly close interfaces on SOFT queue scripts
Rewrote Jarvald
2024-07-18 09:39:09 +00:00
Ceikry
806680517b Halt tick processing if the server isn't able to reach the internet when watchdog is enabled (configurable via server config options connectivity_check_url and connectivity_timeout) 2024-07-18 08:07:35 +00:00
GregF
53357d20f3 Rewrote Canifis warewolf handling, fixed stats
Fixed bandit aggression
2024-07-13 06:13:31 +00:00
Dark Sage
a44472e559 Added missing sounds
Added equipping sounds to all Kitesheilds & sq shields that are currently available 
Added equipping sounds to combat Melee Boots that are currently available 
Added equipping sounds to combat Melee Gloves that are currently available 
Added equipping sounds to all Coifs that are currently available 
Added equipping sounds to all D'hide bodies that are currently available 
Added equipping sounds to all D'hide chaps that are currently available 
Added equipping sounds to all D'hide vambracers that are currently available 
Added equipping sounds to all Bows that are currently available 
Added equipping sounds to all Cross bows that are currently available 
Added equipping sounds to all Javelins that are currently available 
Added equipping sounds to all Knifes that are currently available 
Added equipping sounds to all Darts that are currently available 
Added equipping sounds to all Throwing axes that are currently available 
Added equipping sounds to all Arrows that are currently available 
Added equipping sounds to all Claws that are currently available 
Added equipping sounds to all Halbergs that are currently available 
Added equipping sounds to all Hastae that are currently available 
Added equiping sounds to all Daggers that are currently available 
Added equipping sounds to all Swords that are currently available 
Added equipping sounds to all Longswords that are currently available 
Added equipping sounds to all Scimitars that are currently available 
Added equipping sounds to all 2H swords that are currently available 
Added equipping sounds to all War-hammers that are currently available 
Corrected the incorrect equipping sounds to all staves to the correct sound
Added equipping sound to the Easter ring
Added equipping sound to the Jack lantern mask
Added the correct red nose light animation to the Reindeer hat
Corrected the Chocatrice cape to be the real one in game with the logo in the back and also added the emote to it
Added sounds to the Scythe and corrected its combat animations
Added the Rubber chicken emote "dance" with its music jingle and the chicken "bawk" sound
Added the Ice amulet and the Wintumber tree to Diangos item return since they were missing
Added the correct jingle to the Air guitar emote
2024-07-13 05:46:28 +00:00
Player Name
6b152bcc8c Wilderness improvements
Added an extra option to the deep wilderness gate warning: "I wish to proceed, and don't ask me again"
Reused the same warning, with appropriate changes, for the edge/ardy levers due to the pvp mechanics
Removed the interface warning when crossing the ditch until doomsayer is implemented
Removed the inauthentic threat revenant and restricted brawler/pvp drops to revenants and chaos elemental only
Now require 100k risk to obtain the boosted deep-wildy drop rates
Hid our inauthentic mechanics behind a new server config option enhanced_deep_wilderness
2024-07-13 05:46:18 +00:00
Bonesy
30f1cbf710 Rewrote unpowered orb charging
Added Seers' Village diary tasks for ranging tickets, talking to Thermac about staves and charging orbs
Corrected explorer's ring alchemy graphics
2024-07-13 04:37:24 +00:00
Bonesy
0165d373bd Rewrote altar praying
Added the Tai Bwo Wannai Trio as quest requirement for praying at the tribal statue
2024-07-13 04:37:21 +00:00
Player Name
6f9a975f7a Added Waterbirth Island and the Dagannoth Kings' lair to admin ::to teleport destinations 2024-07-13 04:37:19 +00:00
Player Name
21a07841f6 Fixed construction door and wall placement
Fixed the bug where some hotspots were still visible even in non-building mode
2024-07-13 04:37:04 +00:00
Player Name
81495ab8a8 ::ge commands now use book interface to support more than 300 listings 2024-07-13 04:24:13 +00:00
GregF
5ed3cafc4a Cuffs, Narf, Jeff and Rusty now have correct examine information
Corrected Narf's stats
Added examine text for all implings and Balnea
2024-07-13 03:33:28 +00:00
GregF
0b95cfdb8f Fixed incorrect reward amount from stronghold of player safety 2024-07-13 03:31:24 +00:00
Player Name
e8527ff506 Your organs will no longer be stolen. Also fixed unexpected disappearance of beds, big plants, bookcases in study, fireplaces in bedroom and costume box in costume room
Fixed incorrect coordinates for the study crystal ball hotspot
2024-07-13 03:21:22 +00:00
Player Name
ef90d24bdc Improved handling of construction bookcase building 2024-07-13 03:16:29 +00:00
Oven Bread
a2b0548c62 Better handling of quest varp/varbit and values to set the quest color to red/yellow/green 2024-07-13 03:15:17 +00:00
Player Name
611660cbc3 Fixed fishing trawler bugs
Optimised fishing trawler reward logic
2024-07-13 02:58:24 +00:00
Kamja Imo
370d9ef423 Removed quest completion check on fairy ring exit from Zanaris 2024-06-27 14:11:43 +00:00
Doggo
8d2b454b1c Fixed salamander attack style 2024-06-23 13:11:23 +00:00
Doggo
28b168e742 Fixed 1 tick movement delay on some actions 2024-06-08 12:23:06 +00:00
Player Name
98c0698097 Fixed random events occurring at kalphite queen and tormented demons
Fixed bots trying to speak unicode
2024-06-08 12:17:37 +00:00
Player Name
80a5c3a85e Enabled Lunar Isle and Miscellania coal mine star locations
Fixed requirements checking for some star locations
2024-06-08 12:15:46 +00:00
thelemir
ca3bc9cd70 Rewrote Rimmington
Enabled pickpocketing of Anja and Hengel
2024-06-08 12:13:22 +00:00
Player Name
2c3b5cb5a4 Fixed MTA telekinetic theatre statue path check 2024-06-08 11:55:23 +00:00
Oven Bread
5f62047aff Fixed the Druidic Ritual quest log rendering
Implemented two bank noticeboards
2024-06-08 11:25:03 +00:00
Oven Bread
d0f24afc2e Implemented White Wolf Mountain & Ice Queen 2024-06-08 11:24:25 +00:00
Bonesy
1f6b0e900f Fixed bug causing loss of xp when interrupted burying bones 2024-06-08 11:14:03 +00:00
Doggo
ddb9b6f0b0 Fixed NPCs pathing around safespots when standing adjacent to the safespot 2024-06-08 10:17:07 +00:00
Ceikry
45c21767d5 Reduced price of fighter torso to 4.5M (until barbarian assault is implemented) 2024-06-08 10:17:01 +00:00
João Victor
f01a5cfe40 Fixed incorrect description on a fairy ring 2024-06-08 10:15:53 +00:00
Ann
36d8186458 Added drop announcement for dragon platelegs, skirt and black mask (10) 2024-05-31 12:41:17 +00:00
Ceikry
52cf984540 Refactored bank logic
Removed some unnecessary complexity from bank logic
Improved handling of banking actions
Now correctly tracks the active bank tab
2024-05-31 11:38:00 +00:00
Legendary Rare
082d3a561b Fixed Draynor fishing bots not interacting 2024-05-31 11:34:29 +00:00
GregF
dd9f2a34c8 Fixed animations and stats for an ogre
Fixed bone club and butterfly net animations
Fixed black halberd requirements
Fixed stats on unobtainable corrupted pvp equipment
2024-05-31 11:32:53 +00:00
Player Name
49a10d192a Implemented save file versioning
Players who likely bought their crafting capes back when the hood was not obtainable will be given the complementary hood
Unlocked Surok's Theme for players who are eligible
Fixed some bugs relating to the handling of edge cases for random events
Fixed tutorial island quest completion
Made it possible to collapse interface stones in resizable HD
2024-05-31 11:32:48 +00:00
Player Name
2776270c7f Added the basement area of Tutorial 2 (Learning the Ropes) for the lore 2024-05-31 10:16:28 +00:00
Player Name
a184b4ce2f POH room rotation now correctly updates clipping flags 2024-05-31 10:11:38 +00:00
Player Name
76d31a68ad Fixed duplicated runecrafting messages 2024-05-31 10:09:21 +00:00
GregF
51929277ac Fixed issue where vodka was called wine
Fixed drinking wine
Fixed stealing wine in Draynor
2024-05-31 09:53:55 +00:00
thelemir
07c6eab4af Swapped kalphite guardians for soldiers in side room 2024-05-31 09:52:49 +00:00
GregF
dc3daebb59 Implemented Scorpion Catcher quest 2024-05-31 09:50:54 +00:00
thelemir
da6f05f8ce Converted tanners to Kotlin
Fixed snake hide tanning
Fixed interaction with Canifis tanner
2024-05-31 09:49:31 +00:00
GregF
66b1efdaa3 Fixed Vinesweeper exploit
Fixed Vinesweeper server crash
2024-05-31 09:33:32 +00:00
suichi
aed73183d1 Switching interface tabs no longer closes dialogue 2024-05-18 09:14:08 +00:00
GregF
66978b23ee Fixed Family Crest Chronozon Spawn issue 2024-05-13 15:22:45 +00:00
Player Name
f501468ead Fixed ironman mode being stuck after permadeath 2024-05-13 15:13:23 +00:00
GregF
a63867627e Removed slayer tasks from NPC config file
Fixed tutorial island text showing for level 3 skills
2024-05-13 15:12:27 +00:00
GregF
5d54ef56b3 Fixed slayer task bugs
Fixed Elvarg not counting as a green dragon
Fixed some trolls not counting
Fixed some ogres not counting
Fixed some turoths not counting
Fixed kalphite queen not counting correctly
2024-05-13 15:08:56 +00:00
GregF
acf27dada5 Fixed bug at end of Fremennik Trials requiring 10 free inventory slots
Fixed typos
2024-05-13 15:02:44 +00:00
GregF
73102d8f79 Added jungle tree to the list of 1 chop trees 2024-05-13 15:01:33 +00:00
Player Name
158cf41fd3 Fixed Bork/Surok instanced area music 2024-05-13 15:00:37 +00:00
GregF
cdead88473 Corrected ammo usable on each crossbow 2024-05-13 14:59:36 +00:00
Player Name
5d21ab74c0 Corrected NPC IDs for the Keldagrim carts 2024-05-13 14:55:58 +00:00
h h
782a70a582 Fixed granite lobster foraging 2024-05-13 14:54:51 +00:00
Player Name
38a580a431 Corrected music varps, fixes some music unlocks 2024-05-13 14:51:38 +00:00
Oven Bread
4c736e5aef Fixed all fired up quest log 2024-05-13 14:50:04 +00:00
GregF
0dcdc84f79 Refactored the Player Safety Stronghold 2024-04-17 07:45:55 +00:00
Player Name
6deadc6f90 Fixed an off-by-one error that made cooking brawlers unobtainable
Reworked the ::npc admin command to take an optional amount argument. Usage: ::npc id [amount] [shouldWalk]
Summoning points now no longer regenerate automatically
Rewrote the ring of life
Reverting a slayer ring to an enchanted gem no longer destroys the item if inventory is full
The inauthentic mounted glory in a POH now respects teleblock
Fixed revenents infinite healing
Winkins' farm exit message is now split correctly
Added egg spawn in front of the chicken shrine in Zanaris and added its authentic use handler to the shrine
2024-04-17 07:34:12 +00:00
GregF
50eb295fda Rewrote grappling, fixes Yanille south shortcut, Catherby skill check and requirements text getting cut off 2024-04-15 00:27:30 +00:00
GregF
24b314426e Refactored Seer NPC 2024-04-15 00:20:29 +00:00
GregF
a342f91156 Red feedback text is now used when issued commands are invalid
Yellow feedback text is now used when legacy commands are issued
2024-04-15 00:18:04 +00:00
GregF
64b40fbcf4 Improved handling of achievement diary rewards 2024-04-15 00:10:56 +00:00
Ceikry
0ade8bdf02 Fixed issue where eggs would occasionally spawn out-of-bounds
Added admin command to test egg spawning ::eggspawntest
2024-04-02 11:49:37 +00:00
Trident101
68cf133955 Added Padulah dialogue 2024-03-31 14:39:37 +00:00
Player Name
7190c3eda7 Fixed some construction hotspots for south-facing rooms 2024-03-31 14:29:27 +00:00
Player Name
ee9d386bc9 Added ::permadeath [player] admin command to wipe a player's save
Fixed some HCIM death bugs where state was not cleared
2024-03-31 14:29:26 +00:00
GregF
2da47d8353 Implemented thieving candles on Entrana 2024-03-31 14:29:25 +00:00
Player Name
5c977c0522 Better handling of full inventories
Made it possible to alch when inventory is full with non-coin items, if the alch would free up the necessary space
Made it possible to receive a kitten from Gertrude when inventory is full,  if the transaction would free the space for the kitten
Made it possible to receive a kitten from Gertrude when inventory is full even with more than 100 gp, if the pet can be summoned immediately
Gertrude's Quest completion - fixed bug causing loss of kitten with full inventory
Fixed a bug where Gertrude's kitten-giving dialogue will hang if spoken to while having a non-pet familiar out
Fixed typos
2024-03-31 14:17:25 +00:00
Player Name
2948d58934 Fixed possible softlock at Evil Bob event 2024-03-31 14:14:04 +00:00
Player Name
cde2dcc93f Replaced player name with player username in the Digsite examination certificates
Fixed some typos in the Grand Tree quest dialogue
Replaced unicode with ascii in the Grand Tree quest & Plague City quest
2024-03-31 14:13:23 +00:00
Player Name
4ae1448800 In non-building mode, construction objects that have not been built now no longer leave behind clipping flags
Added command ::drawclipping to visualize construction clipping flags
2024-03-31 14:11:46 +00:00
Ceikry
b1e6c9fe8c 2024 Easter Event
Added Easter event
Refactored event code
Added support for forced-global ground items
2024-03-31 03:43:26 +00:00
downthecrop
a7516f2d6e Fixed Nettle Tea wrong return item
Fixed Yak Hide crafting swapped items
Fixed mining bot dropped ore ironman restrictions
Fixed Ardy teleport tab requirements
Fixed Alice's husband not requiring ghostspeak
Fixed Fishing Trawler stuck on boat bug
Fixed POH debug region info showing in non-debug mode
2024-03-26 01:51:16 +00:00
Bonesy
1d4d380e93 Added missing Master Crafter dialogue 2024-03-26 01:48:50 +00:00
Ann
3b967791a4 Glass making now returns the correct type of bucket 2024-03-26 01:47:42 +00:00
Player Name
c96fa24999 Reformatted JSON config for migration to Zaros tool 2024-03-21 23:56:04 +00:00
GregF
bbfa1bb1e7 Smithing interface fixes
Now handles blurite correctly
Updated title
Fixed bullseye lanterns
Fixed bronze wire
Fixed glass lantern
2024-03-18 12:22:49 +00:00
GregF
675f0c1e37 Fixed Family Crest getting stuck when the drop from Chronozon is not picked up (fight is now repeatable if item is lost) 2024-03-17 09:01:42 +00:00
Bonesy
b8a887b319 Fixed crafting guild tanning interface
Rewrote master crafter dialogue
Added missing master crafter dialogues
Fixed issue preventing crafting guild entry with trimmed crafting cape
2024-03-17 08:59:11 +00:00
Jordan Christiansen
a1fc0ba7cc Fixed line that should be spoken by player in Philop dialogue 2024-03-17 08:27:32 +00:00
Oven Bread
a11b783c39 Fixed the organ animation in Lumbridge 2024-03-17 08:15:39 +00:00
GregF
b22c6057a3 Changed ::allow_aggro admin command to ::allowaggro true/false for consistency with other commands
Added message for ::allowaggro activation
Can now check ::allowaggro without toggling it by running it without a trailing true/false
2024-03-17 08:14:06 +00:00
GregF
6e9183ea8f Fixed unnoting items failing to unnote correctly when quantity is equal to free slots 2024-03-17 08:01:20 +00:00
GregF
ed47883bea Al Kharid warriors now help each other in combat 2024-03-17 07:58:17 +00:00
GregF
60e6049971 Fixed level 25 black guard stats and animations 2024-03-17 07:56:51 +00:00
Oven Bread
06038dbbdc Implemented The Dig Site quest 2024-03-17 07:53:59 +00:00
Jordan Christiansen
ca53059131 Improved ::ge interface handling 2024-03-16 12:31:22 +00:00
Jordan Christiansen
6cb4f118ea Bats now only drop bat wings during Rag and Bone Man quest 2024-03-16 12:17:22 +00:00
Oven Bread
6856d75d88 Corrected contents of Varrock newspaper and refactored related code 2024-03-16 12:10:19 +00:00
Player Name
8729f93d01 Added teleblock message for ancient magicks 2024-03-16 12:09:42 +00:00
Bonesy
dbbcf5601e Rewrote bone burying and corrected xp rates 2024-03-16 12:05:46 +00:00
ipkpjersi
d9355ec85f Fixed rock crab spawns on Waterbirth island 2024-03-16 09:05:37 +00:00
Oven Bread
43c8f43c49 Reverted Askeladden's spawn to the previous location 2024-03-05 01:49:13 +00:00
Patrick W.
28b7a75538 Added docker-compose file 2024-03-03 06:05:03 +00:00
Bonesy
0158d753f0 Karamja bug fixes and improvements
Improved Brimhaven NPC interactions
Both NPCs right click options now function
Dialogue converted to Kotlin for both NPCs
Minor dialogue modifications
Converted the Karamja Option Plugin to a Karamja Listener and Brimhaven Listener
Removed some duplicated handlers such at the ship yard gate and cart
Corrected the coins shown when paying to enter the Brimhaven dungeon
The palm tree now drops the leaf to the ground when shaken and has an animation
2024-03-03 05:49:59 +00:00
Player Name
3df5097442 Cleaned up more server name references and related strings 2024-03-03 05:47:37 +00:00
Bonesy
866372ad54 Fletching now checks for inventory space before fletching darts, headless arrows, and arrows 2024-03-03 05:44:25 +00:00
Jordan Christiansen
9ca9f01ca3 Fixed bank guard dialog typo 2024-03-03 05:32:57 +00:00
Jordan
2714448c61 Added Zanaris Evil Chicken Lair 2024-03-03 05:23:34 +00:00
GregF
98ee184652 Fixed issue with Man (ID 1086) not being able to be pick pocketed 2024-03-03 05:19:42 +00:00
Jordan
6b9a06d175 Stronghold of Player Safety now checks if inventory is full before awarding lamp rewards 2024-03-03 05:19:09 +00:00
zsrv
9068874556 Fixed issue where some scripts weren't cleared when the player moves 2024-03-03 05:18:22 +00:00
GregF
4f5d753104 Ported Peksa from Java to Kotlin 2024-03-03 05:17:18 +00:00
Player Name
ae53116fee Music fixes
Corrected music locations for Tolna's rift
The Digsite and Exam Centre now correctly play Lullaby and Venture all the time
Corrected borders for Venture 2, which now correctly plays in the dungeons underneath the Digsite
Corrected borders for Chain of Command, which now correctly plays in all of the Temple of Ikov dungeon (and the two versions of the boots of lightness dungeon)
Added a new track, the brine rat cave now plays Rising Damp
2024-02-21 02:06:15 +00:00
Jordan
9e5a7aefc8 Fixed issue where the player could be given stacks of 0 items 2024-02-21 02:03:41 +00:00
Jordan
6e2f8c6f30 Fixed fletching blurite c'bow 2024-02-14 22:45:44 +00:00
Bonesy
affb2e58e9 Making sets of bolts, arrows and headless arrows no longer continues indefinitely 2024-02-14 11:41:27 +00:00
Player Name
fff1476714 Replaced item IDs in construction code with constants 2024-02-14 11:36:35 +00:00
Player Name
08241eb1db Implemented pet shoo-away 2024-02-14 11:33:56 +00:00
zsrv
1d12dd741f Implemented auto splitting of excessively long dialogue lines
Many new farming-related player messages added, and some existing messages updated
Raking animation updated
Herb picking animation updated
Digging up farming patch animation updated
Plant cure animation updated
A scarecrow can be retrieved from a flower patch by digging it up with a spade
Picking fruit/berries stops when running out of inventory space
The player can no longer dig up a tree they have planted before chopping it down
2024-02-14 11:33:13 +00:00
Oven Bread
38c50c465d Implemented Temple of Ikov quest 2024-02-14 11:26:53 +00:00
Oven Bread
7804dfe791 Failing to clean herb message is now authentic 2024-02-03 11:19:16 +00:00
Bart Ribbers
37a874f471 Updated release script to use new website update post layout 2024-02-03 11:10:44 +00:00
ipkpjersi
b33517632e Fixed fish caught statistic not saving 2024-01-31 00:12:43 +00:00
Zerken
ed199e1478 Fixed Santa giving 0 coal 2024-01-29 10:02:24 +00:00
ipkpjersi
435ec3b1b6 Removed unused bosses from boss kill counter 2024-01-29 09:50:53 +00:00
Oven Bread
451fa73e3e Fixed the Death Plateau quest log
Fixed Druidic Ritual completion message
2024-01-29 09:49:23 +00:00
Player Name
2255238554 Fixed issue preventing some dragonstone jewellery teleports working at level 30 wilderness 2024-01-29 09:48:28 +00:00
Bonesy
9a5f1e85e2 Fixed text for quest cape removal
Quest cape can now be retrieved from the wise old man if both inventory and bank are full when quests are implemented
2024-01-29 09:47:20 +00:00
Bonesy
020d5a9c05 Fixed inconsistent and inauthentic messages for fishing
Fixed item grinding consuming the whole stack sometimes
Fixed incorrect Fremennik diary cheese task
Fixed Seer's diary candle task
2024-01-29 09:31:30 +00:00
h h
a7b5e77318 Adjusted Varrock armour bonus to be more authentic - 4% for ores up to coal, 3% for ores gold to mithril with tier 2 or 3 and 2% for adamantite with tier 3 2024-01-29 09:14:42 +00:00
Ryan L
66445f61a5 Corrected slayer hint text message formatting 2024-01-29 09:07:22 +00:00
Ryan L
13e5bf1666 Corrected typo in Grand Tree quest 2024-01-20 12:28:52 +00:00
Player Name
dff56510da Fixed music for Zanaris, Puro Puro, Lunar Isle and little cave of horrors 2024-01-20 12:05:49 +00:00
Trident101
2449bfe241 Rewrote Lilly dialogue
Rewrote Eadburg dialogue
Added examine texts for Achietties, Wizard Cromperty and Obli
Corrected seaweed spawn
2024-01-20 12:02:42 +00:00
Bonesy
4ec0f4aa27 Rewrote molten glass blowing
Fixed animations
Timing has been corrected, now takes 2 ticks instead of 3
2024-01-20 12:00:30 +00:00
zsrv
0f9e264788 Improved authenticity of many messages
Fixed explorer's ring using a charge when already at 100% energy
2024-01-20 11:34:51 +00:00
Player Name
86973b6d36 Added message when running out of prayer points
Improved handling of running out of prayer points
2024-01-20 11:31:18 +00:00
Oven Bread
6763758196 Added some missing XTEA keys 2024-01-20 11:23:24 +00:00
Player Name
4fc5e088ad Fixed bug that could result in players losing Christmas event rewards if their inventory is full 2024-01-19 09:50:26 +00:00
Zerken
12daa614bb Implemented news message for achieving max level in all skills 2024-01-09 03:53:39 +00:00
Kennynes
9b484d337c Replaced current rune kite (h#) shield hard clue rewards with the correct shield items 2024-01-09 03:53:07 +00:00
Ryan L
a13b38d6c1 Corrected typo in Tree Gnome Village quest 2024-01-09 03:41:35 +00:00
Player Name
1218ee000f Corrected examine for dragon bones 2024-01-03 04:54:45 +00:00
Bonesy
0a6b607700 Refactored battlestaff crafting to follow authentic interfaces and timing 2023-12-29 01:15:59 +00:00
Player Name
279cfb8b42 Improved pet handling and fixed some bugs
Players with merged pets will have the merge resolved next time they are dropped
2023-12-29 01:09:55 +00:00
Jordan
ee88bfe3f0 Fixed Bogrog spirit shard pouch exchange rounding 2023-12-29 00:55:35 +00:00
Dan Ginovker
04ce0879c8 Fixed stairs around Castle Wars 2023-12-29 00:53:08 +00:00
Player Name
85ee81a42a Fixed pack yak scroll deleting items when bank is full 2023-12-29 00:52:26 +00:00
Player Name
81fd565b4f Corrected music for Tolna's rift and Sorceress's Garden 2023-12-29 00:51:28 +00:00
Player Name
ece16af7ab Bot dialogue now always starts with uppercase character
Fixed hard-coded server name references
Replaced incorrect use of "Keldagrim" with "Gielinor"
2023-12-29 00:50:26 +00:00
fake name
9d19ce2355 Fixed issue where Halgrive does not replace lost poisoned feed 2023-12-13 12:16:47 +00:00
Player Name
cecb937145 Players now kicked out of unimplemented werewolf agility course 2023-12-13 12:13:48 +00:00
Player Name
0cad82029d Authenticity improvements for the dramen tree
The dramen tree now has the highest possible chop speed
Chopping the dramen tree now aborts once the branch has been obtained
The tree spirit no longer uses the rare seed drop table, instead drops nothing
The tree spirit can now be attacked by other players
2023-12-13 12:09:57 +00:00
Bonesy
25e9104375 Pet rock animations & fixes
Made the Pet rock two-handed
Changed Pet rock weight to 1 kg
Edited dialogue for the Talk option to be more authentic
Added animation for the Stroke option & a delay for the second message to wait for the animation to finish
Edited dialogue for the Fetch option to be more authentic, added animations & graphics, and added the projectile with graphics
Added animations & graphics for the Stay option
2023-12-13 12:08:10 +00:00
Oven Bread
6c28a82ebb NPC fixes at:
Mountain Camp (next to Troll Stronghold)
Jiggig
Gu'Tanoth
Oo'glog
2023-12-13 12:06:14 +00:00
Trident101
7a4c2159a4 Dialogue and examine fixes
Converted Lidio dialogue to Kotlin
Converted Anton dialogue to Kotlin
Added Achietties and updated dialogue file
Updated servant dialogue
Updated Wistan dialogue
Changed examine text of Scrying orb, uncharged & charged
Added examine text to wizard Cromperty
Changed bucket examine text
Updated Unferth dialogue
2023-12-13 12:04:46 +00:00
Trident101
ae22b99888 Added missing Zanaris examines
Fixed temple, north staircase interaction
2023-12-13 11:59:41 +00:00
Player Name
7fb90f5afe Corrected examine for Dagannoth Bonemeal 2023-11-25 14:46:26 +00:00
Player Name
d3f1914117 Added music for Chaos Tunnels & Tunnel of Chaos 2023-11-25 14:46:19 +00:00
Player Name
c70c292943 Abyss obstacle success rate is now 100% at level 99 (instead of 99%) 2023-11-25 14:36:50 +00:00
Player Name
8f7683aee4 Skillcape dailies reset with other dailies at midnight server time 2023-11-25 14:35:49 +00:00
Oven Bread
26245dfb10 Bug fixes for getting stuck in Creature of Fenkenstrain 2023-11-12 13:43:26 +00:00
Avi Weinstock
b2eb9cfdc9 Fixed rapid heal bug
Improved reliability of runecrafting unit tests
2023-11-11 05:52:09 +00:00
Oven Bread
2dce4fe98c Implemented Rag and Bone Man quest (part 1) 2023-11-11 05:09:54 +00:00
LostMyPhat
6d0ca0d6fc Fixed male/female dialogue in Druidic Ritual 2023-11-11 04:08:08 +00:00
Zerken
cd4d0ec20b Implemented 7 Christmas Holiday randoms:
Snowman
Snowman Fight
Santa
Jack Frost
Choir
Snowstorm
Cook
2023-11-11 03:49:04 +00:00
Woahscam
8ef5d8bce4 Fixed numerous interfaces, including Puro puro, Destroy item, Equipment, kept on death, Cooking (single prompts i.e. raw fish -> range), Fletching (make set i.e. fletching arrows, bow)
Rewrote herb cleaning to listener
Fixed studded leather crafting level requirement and xp
Fixed bow stringing stealing strings
::quest <player> can now be used to look up a player's completed quests
2023-11-11 03:16:35 +00:00
Oven Bread
098d947d87 Fixed Creature of Fenkenstrain quest point reward 2023-11-05 13:12:10 +00:00
Wouter Standaert
5a6a148cfc Rewrote MysteriousRuinPlugin to a listener
Fixed Varrock earth tiara easy diary task
2023-11-05 09:37:41 +00:00
LostMyPhat
18fa8357a8 Fixed amulet of glory wilderness teleport level 2023-11-05 08:42:48 +00:00
Player Name
e1b7eeaf22 Fencing ring now requires 8 oak planks rather than 8 steel kiteshields 2023-11-05 08:41:33 +00:00
Wouter Standaert
b834ff7404 Fixed gender specific dialogue for Hadley 2023-11-05 08:20:12 +00:00
Player Name
a04c36f5cd Improved accuracy of barrows rewards 2023-11-05 08:20:10 +00:00
Player Name
04882136f8 POH slayer trophy now obtainable, added all heads as tertiary drops 2023-11-05 08:20:09 +00:00
Player Name
d08882cf58 Added optional player argument to ::setlevel 2023-11-05 08:20:08 +00:00
Player Name
f28076f3a4 Fixed bug involving kitten/cat deletion 2023-11-05 08:20:06 +00:00
Player Name
978d70ad0c Fixed typo in Chaos Tunnels portal
Fixed typo in gnome glider to digsite
Fixed a few typos in the random phrases uttered by the Bork minions
Added missing Bork minion phrase
2023-11-05 08:20:04 +00:00
Zachary Terwillegar
af4a316fa1 Fixed failed sheep shearing movement 2023-11-03 15:08:58 +00:00
Zerken
dbb8b5a133 Implemented Strange Plant Random Event 2023-11-03 14:55:41 +00:00
Oven Bread
0eecab4057 Implemented Creature of Fenkenstrain quest 2023-11-02 08:33:02 +00:00
Oven Bread
8316a492c9 Added tool leprechaun dialogue (excluding goth) 2023-11-02 08:28:49 +00:00
LostMyPhat
2ab3c34402 Fixed drill sergeant completion reward drop bug 2023-11-02 08:26:48 +00:00
Oven Bread
70a47aeb5d Implemented Tolna Rift
Improved ::npcanim admin command
2023-11-02 08:26:27 +00:00
Wouter Standaert
7d1a16f7f7 Fixed examine text, slayer tip and drops of vampires 2023-11-02 08:26:25 +00:00
h h
eb18fef53d Corrected typos in Denulth's Troll Stronghold dialogues
Corrected typo in Drezel's Nature Spirit dialogue
Corrected typos in Blaze Sharpeye's All Fired Up dialogues
Corrected typo in Dragon Slayer chest dialogue
2023-10-28 01:39:51 +00:00
Zerken
b7851e7671 Implemented swarm random event 2023-10-27 12:49:26 +00:00
Avi Weinstock
fee56ae528 Backported probabilistic runes. Can now toggle between revision 581, 573 and 570 behavior via runecrafting_formula_revision in server config 2023-10-27 12:41:17 +00:00
Player Name
a74583b13b Big bass, shark, and swordfish are now obtainable from fishing
The message for catching shark now ends with an authentic exclamation mark
The fishing skill cape perk now logs catching a second fish in player stats
2023-10-27 12:37:13 +00:00
Zerken
4942ae0079 Added the correct animation/graphics for emptying the ectophial
Rewrote ectophial
2023-10-27 12:33:11 +00:00
Player Name
9445a2bae5 Death's message for the holiday random event now uses the correct type of player name 2023-10-24 13:35:09 +00:00
Creamy Goodness
3c9dea2830 Sheep now face player when sheared 2023-10-24 13:34:37 +00:00
Player Name
1f2bd0f9fc Corrected linked construction hotspots for shelves, thrones and statues 2023-10-20 23:21:31 +00:00
Trident101
ae0b384e44 Refactored some dialogues in the Ardougne area
Remapped Kortan's shop
Fixed stock of Aemad's shop
2023-10-20 23:20:39 +00:00
Player Name
b640ab7373 Leaving the fight caves now also clears poison, disease and restores run energy (QoL fix) 2023-10-20 07:09:43 +00:00
Kennynes
48e09a3f8a Added examine texts to bob shirts (obtained from easy clues) 2023-10-20 07:03:02 +00:00
Trident101
5f4450c7d2 Several additions and changes to Zanaris
Added fairy queen dialogue
Added movement to the cows
Added a spawnpoint for Blaec
Added examine texts
2023-10-20 06:57:18 +00:00
Kennynes
3b150660b1 Fixed incorrect adamant shield (h#) in medium clue reward pool 2023-10-20 06:56:59 +00:00
Zerken
2bcb05ee6c Fixed rune consumption when teleblocked 2023-10-20 06:56:54 +00:00
Jedediah Orne
e2a13465b6 Fixed wilderness zoning near KBD lever 2023-10-20 06:56:52 +00:00
Player Name
0779a550a3 Updated README.md with working link to Thanos tool + java 11 reminder 2023-10-20 00:48:48 +00:00
ryannathans
c03fa76ea1 Deleted obsolete GE tool 2023-10-18 00:38:19 +00:00
Memzak
874c3883e6 Charlie now says 2009Scape in The Grand Tree 2023-10-17 11:07:03 +00:00
Von
a190544519 Corrected moss giant drop table 2023-10-17 11:02:36 +00:00
Von
102cc65fd2 Corrected fire giant drop table 2023-10-17 11:02:26 +00:00
Zerken
0e6b4ad816 Fixed fishing trawler teleport and random event issues 2023-10-17 11:02:12 +00:00
Player Name
5237051e71 Fixed construction requirement for combat rings 2023-10-17 11:01:47 +00:00
Player Name
0eaa6000e0 Made firemaking skillcape a valid light source for the giant mole 2023-10-14 01:27:08 +00:00
Zerken
4e1ddaeec5 Implemented Rick Turpentine and Drunken Dwarf random events 2023-10-12 23:34:25 +00:00
Von
b308e488f9 Corrected Skeletal Wyvern drop table 2023-10-12 01:48:31 +00:00
Oven Bread
264f78eb11 Added the two NPCs above the furnace in Falador 2023-10-12 01:47:04 +00:00
bushtail
9989ee9905 Rewrote Stat Spy
Refactored lunar spell handlers
2023-10-12 01:43:43 +00:00
Von
1913d0c83f Corrected Waterbirth Island Dagannoth drop tables 2023-10-12 01:40:42 +00:00
Woahscam
0f083bcaaa Fixed incorrect index for statuette rotation attribute used in the Golem quest 2023-10-12 01:32:34 +00:00
Zerken
150e0619c1 Fixed empty item regression breaking rune pouches and ectophial 2023-10-08 12:10:03 +00:00
Von
663558cc8c Corrected Cockatrice drop table 2023-10-07 00:41:57 +00:00
Von
44f7c7bd78 Corrected Ice Giant drop table 2023-10-07 00:36:42 +00:00
Von
3638cf60f7 Corrected Ogre drop table
Corrected Ogress drop table
Corrected Ogress Warrior drop table
Corrected Ogress Champion drop table
2023-10-07 00:34:07 +00:00
Von
d429d3023b Corrected Dark Beast drop table 2023-10-07 00:33:23 +00:00
Oven Bread
ba1807c76f Huge wilderness data audit and correction, including the following areas
Frozen Waste Plateau (Within members gate)
Agility Course
Pirate Cove
Mage Arena Area
Mage Arena
Inside Mage Arena
Deserted Keep
Magic Axe Hut
Near Deserted Keep below Magic Axe Hut
Scorpion Pit
Chaos Elemental
Rogues' Castle
Top Right Volcano
Lava Maze
Red dragon Isle
Mining Hobgoblin Area
Canoe area
Wilderness Volcano
Forgotten Cemetery
West of Stealing Creation
Stealing Creation
Ruins right side
Front of Ruins
Demonic Ruins
Near Corp Cave
Ruins left side
Graveyard of Shadows
Bandit Camp
Spider Mound near Sapphire Gems
Dark Warrior Fortress
Clan Wars
Ruins south of clan wars
Chaos Altar
Bottom East
2023-10-05 01:18:23 +00:00
Von
aaebd7478d Corrected Dagannoth Prime drop table 2023-10-05 00:22:17 +00:00
Von
6325ffefbb Corrected Dagannoth Supreme drop table 2023-10-05 00:15:10 +00:00
Von
25e944f37c Corrected Dagannoth Rex drop table 2023-10-05 00:13:13 +00:00
Von
7f9617554a Corrected Gargoyle drop table 2023-10-05 00:12:50 +00:00
Von
7ced5ae031 Corrected TzHaar-Xil drop table 2023-10-05 00:07:55 +00:00
Trevor
0e87138789 Implemented eating of frog spawn 2023-10-05 00:03:35 +00:00
Player Name
ee42a4b82d The name of the location where the shooting star has dropped is now no longer lowercased 2023-10-05 00:03:32 +00:00
Von
4d3d6e59e1 Corrected TzHaar-Mej drop table 2023-10-05 00:00:00 +00:00
Von
5b1e6de903 Corrected TzHaar-Hur drop table 2023-10-04 23:58:26 +00:00
Trevor
94a55190ee Barbarian potion refactor
Fixed barbarian potions that can take either a roe or caviar from consuming both
Corrected level requirement and product potion id for hunter and antifire mixes
Corrected input potion id for fishing mix
Implemented antidote+ mix
Fixed level requirement for super energy mix
Fixed duration of antipoison mix (now 90 seconds)
2023-10-04 23:48:51 +00:00
downthecrop
708d5bb507 Rewrote Captain Barnaby and Shilo Cart interactions 2023-10-04 23:35:24 +00:00
Oven Bread
e9fd74b379 Refactored canoe handling
Canoe station should now have the full animation suite
Canoe making now scales with axe and level of woodcutting
Interfaces are now fully updated with proper hide/show/animation
Canoes now sink at the end of the journey
Added a black screen backdrop overlay seen only in HD
2023-10-04 23:30:51 +00:00
Ryan
b87a3821dd Corrected Vesta's longsword damage 2023-10-04 23:26:42 +00:00
Player Name
7c38339e16 Rewrote pet management
Fixed being unable to remove pets
Removed redundant pet messaging
2023-10-04 23:19:57 +00:00
Von
e5afeed6db Corrected TzHaar-Ket drop table 2023-10-04 23:17:02 +00:00
Ceikry
cc989d5844 Added support for tertiary drop tables 2023-10-04 23:17:01 +00:00
Player Name
3a72aadbab Corrected music locations and tracks
Water altar (Zealot)
Blood altar (Bloodbath)
Abyss (Into the Abyss)
Rogues' Den
Corporeal beast (Bane of Summer)
Armadyl's Eyrie
2023-10-04 06:15:37 +00:00
Von
db396893f2 Corrected Icefiend drop table 2023-10-04 06:14:51 +00:00
Von
d9c0c58bbb Corrected Aberrant Spectre drop table 2023-10-04 06:05:21 +00:00
Von
dd16588c13 Corrected Nechryael drop table 2023-10-04 06:03:12 +00:00
Player Name
96039978aa Fixed typos in Lokar Searunner dialogue 2023-09-28 09:01:12 +00:00
Player Name
0f1f4dec96 Fixed bug preventing use of slayer boosters for slayer tasks 2023-09-28 08:48:47 +00:00
Zerken
dfdc9dc6a5 Implemented 7 random events for Halloween, 17th October to 7th November
Includes server config options holiday_random_event and force_halloween_randoms
Admin command ::hrevent -p username -e eventName
Admin command ::forcehrevents holidayName
Admin command ::stophrevents
2023-09-28 08:31:21 +00:00
Player Name
f6e83eb28f The Abyss skull is now automatically renewed whenever the player enters the abyss 2023-09-27 07:11:47 +00:00
Von Hresvelg
3c57be80e1 Corrected Stick (Troll) drop table
Corrected Pee Hat (Troll) drop table
Corrected Kraka (Troll) drop table
2023-09-22 08:33:09 +00:00
Von Hresvelg
b477a62a7d Corrected hill giant drop table 2023-09-21 07:47:32 +00:00
Von Hresvelg
73ed09b6ba Corrected stronghold of security giant spider drop table 2023-09-21 07:38:46 +00:00
Von Hresvelg
e3dd47431e Corrected Kalphite Guardian drop table 2023-09-21 07:28:55 +00:00
Ryan
25082c2bb2 Temporarily removed intermittently failing unit tests 2023-09-21 07:18:21 +00:00
Von Hresvelg
470105ae36 Corrected Tyras Guard drop table 2023-09-21 02:37:11 +00:00
Avi Weinstock
e12658ade9 Fixed summoning obelisk scroll creation interface 2023-09-20 09:18:02 +00:00
Player Name
7320bcfd0b Fixed ring of the star sprite bypassing some teleport restrictions 2023-09-20 09:08:14 +00:00
Player Name
5e6f750cee Player username case is now consistent 2023-09-20 06:50:37 +00:00
Player Name
0b6be66cfd Better handling of pitfall NPCs 2023-09-20 06:39:11 +00:00
Von Hresvelg
4e9f932cfb Corrected Anja and Hengel drop tables 2023-09-20 05:25:44 +00:00
Anna Tar
56b195bd9e Corrected stats for cave bugs 2023-09-20 05:03:27 +00:00
Von Hresvelg
608ffcfd90 Corrected Air Elemental drop table
Corrected Water Elemental drop table
2023-09-20 04:03:34 +00:00
Oven Bread
bff955d629 Implemented The Book of the Big High War God 2023-09-20 03:44:36 +00:00
Mihoshika
e264ae8eee Corrected item costs in Varrock's fur clothing shop 2023-09-20 00:40:41 +00:00
Player Name
9ea32d07eb Fixed a construction bug where rooms built off of a south-facing door with a southern orientation were not getting rotated after being built 2023-09-19 13:49:47 +00:00
Oven Bread
e67ca4948b Gates near the lumberyard and the path to the digsite should open properly now 2023-09-19 13:39:42 +00:00
Avi Weinstock
f4163e733a Fixed bug causing some rewards to disappear instead of dropping when inventory fills up as a result of receiving the reward 2023-09-19 13:30:37 +00:00
Trident101
5baa876a55 Implemented pickpocketing for NPCs in Rellekka
Added dialogue for shopkeeper Kofi and shop assistant
Changed examine text of Kofi and added shop assistant
Rewrote Karamja man dialogue to Kotlin
Rewrote Monkey dialogue to Kotlin
Rewrote Zambo dialogue to Kotlin
2023-09-19 13:20:40 +00:00
bushtail
bb46e3f37f Added announcement for new players 2023-09-16 01:39:16 +00:00
Player Name
8a87fa488d Fixed typo in Taverly chest message
Added period to end of some cooking messages
2023-09-16 01:15:13 +00:00
Trident101
8148a453d0 Added Hring Hring dialogue
Corrected stock levels in Hring Hring's shop
2023-09-15 05:39:44 +00:00
Trident101
aa37cd4688 Moved some God Wars NPCs back into the map
Fixed stairs in Heroes' Guild
Fixed stairs in Gnome Village
Fixed stairs in Dagannoth King room
Fixed stairs near Sir Amik Varse
2023-09-15 05:30:44 +00:00
Trident101
ff21a3948d NPC additions to Piscatoris fishing colony
(Partially) Added Franklin Caranos's dialogue
Added Herman Caranos's dialogue
Added a spawn location for Herman Caranos
Added npc movement to Franklin Caranos
Added Skeleton mage config
2023-09-15 02:34:21 +00:00
Ceikry
c99dfe7031 Interface Developer Tools
Implemented fully functioning interface decoders referenced from the client
Added ::iftriggers command that gives visibility of all the varp/varc triggers on an interface
Added ::listifmodels command that gives visibility of all the models present on an interface
Added ::listiftext command that gives visibility of all the text present on an interface
2023-09-14 08:43:22 +00:00
Zerken
e60eecc6bf Rewrote "emptying" contents of many items
Implemented emptying plant cure
Rewrote DFS handler
Corrected DFS max hit to be 25 instead of 26
Corrected DFS attack cooldown to be 2 mintues instead of 30 secs
Implemented the animation when emptying charges from the DFS
Implemented a server config (better_dfs) to preserve previous functionality (enabled by default)
2023-09-12 03:02:03 +00:00
Oven Bread
0028be9cda
Implemented more Keldagrim
Gave Ordan a full dialogue revamp for dialogue and un-noting
Gave Blast Furnace Foreman a full dialogue including a tutorial for the blast furnace
Fixed the boating routes
Added the train tunnel (but not the train)
Relocated and implemented NPCs in Keldagrim
2023-09-11 07:44:09 +00:00
Player Name
4520a05636
"your pet is getting hungry" and "your pet is starving, feed it before it runs off" now always fire before pets run off 2023-09-10 16:24:22 +00:00
Oven Bread
b80c98acd6
Implemented Troll Stronghold quest 2023-09-10 16:01:09 +00:00
Trident101
c269949986
Implemented cooking curry and pita bread 2023-09-10 15:41:43 +00:00
Zerken
cbeb422411
Fixed the mining level requirement of perfect gold ore to be 40 instead of 46
Resolved a issue where gold rock scenery was rewarding perfect gold ore on gold rocks outside of the Witchaven dungeon
Familiars are no longer allowed in some places they shouldn't be
The Grand Tree mine's roots now properly animate and play the correct sound when pushing them
The correct thieving level is now required for Varrock pickpocket diary task
Added the correct dialogue message to inspecting the cactus with the red scarf from tourist trap
Corrected Dagganoth Prime talisman drops
Arctic pines now reward 40 xp authentic to Jan of 2009 instead of Sept of 2009
All farming patch tree chop rates have been corrected
Fixed an issue where the player would continue to chop farming patch trees after they get chopped down
Fixed the typo in the word Jenkiins -> Jenkins
2023-09-10 15:24:56 +00:00
Zerken
ac5c31747f
The AntiMacro timer now properly pauses for Administrators
Modified the ::revent command to unpause the AntiMacro timer for admins and display a chat message
2023-09-10 14:43:56 +00:00
Ceikry
99e83a57e3
Fixed Jatizso ferry regression 2023-09-09 01:42:39 +00:00
Player Name
7383454728
Rewrote the barrows reward chest for authenticity
Removed inauthentic potions
Remove the inauthentic restriction that the chest may only be looted after all brothers have been killed
Each brother killed now awards an additional roll for the chest
2023-09-09 01:26:33 +00:00
bushtail
42f0b7c3b2
Refactored lunar spellbook code
Rewrote humidify spell
2023-09-07 06:47:10 +00:00
Ceikry
6cd35dc482
Removed rune crossbow from ice warrior drops 2023-09-07 06:32:06 +00:00
Ceikry
a26c886586
Fixed summoning bug where pets could get stuck until relog 2023-09-05 13:59:54 +00:00
Kennynes
ee94ba03c2
Fixed issue where Uri did not see Dueling Ring (1) as a Dueling Ring to proceed with medium clue 2023-09-05 12:08:08 +00:00
Mihoshika
049920b3fc
Opening a quest journal now closes any open interface before opening the new one, thus fixing unimplemented quest journals displaying incorrectly when another is already open 2023-09-05 06:33:00 +00:00
Ceikry
895c41756a
Rewrote stiles
Added a new ContentAPI function, animationCycles, that returns the exact number of cycles an animation lasts for (useful for forced movement)
Added a new function to Vector objects that allows convertion into Direction objects (useful for transforming locations)
2023-09-04 06:46:10 +00:00
Zerken
d4e62c0e96
Fixed a regression causing broken NPC range and magic attacks 2023-09-04 05:06:26 +00:00
Ceikry
544487218a
Fixed an issue in replaceSlot logic causing visual bugs with pizza 2023-09-04 03:13:28 +00:00
Trident101
fa45bcfe70
Corrected RPDT employee inauthenticities 2023-09-04 01:30:21 +00:00
Zerken
1ab6773910
Random event improvements
Implemented smoke puff sound when random event npcs disappear
Fixed smoke puff repeating
Admins will no longer get random events
Can no longer talk to a random event NPC if they are leaving
Rewrote Drill Demon event:
The event can no longer be avoided and Sergeant Damien automatically teleports you to the event
The player can no longer escape the event by logging out
Sergeant Damien now walks around the area in a circle as he should authentically
Corrected all of Sergeant Damien's dialogue to be authentic
Implemented the authentic item dialogues that show the player the picture of the sign to exercise at
Implemented all the exercise sounds
Evil Bob's Island:
Rewrote all uses of pulses to scripts
Fixed evil bob not teleporting players when in combat
Fixed the reward dialogue
Freaky Forester:
Rewrote the freaky forester teleport to a script instead of a pulse
Fixed an issue where nearby players could talk to the NPC
Genie Event:
Rewrote most of the event
The genie now leaves after completing the dialogue
Implemented the genie appearing sound
Evil Chicken:
Now uses the correct attack sound
Misc:
Added admin command ::barrage [radius] that new barrage command hits all the players in the radius defines with a custom weak ice barrage. It will play the ice barrage sound, display graphics and hit the player for a random 0-3 damage. A fail safe has been added so the command will hit 0 if the player is low on health so this command will not accidentally kill players
2023-09-03 13:33:26 +00:00
bushtail
72853d225d
Removed osrs references from bot names 2023-09-01 12:47:27 +00:00
Avi Weinstock
12eaa1e05a
Fixed antipoison not working in some scenarios
Added new ::timers admin command
2023-09-01 12:29:12 +00:00
bushtail
3b0360eb01
Locked claw smithing behind Death Plateau quest 2023-09-01 12:19:53 +00:00
Zerken
abe55aa7f3
Shops will no longer charge if inventory is full
The ::shop can no longer be opened if the player is movement or interaction locked
Rogues now drop the proper coin
Rewrote the canoe station chop down as a soft script to be uninterruptible
Fixed the player locks for Rellekka trapped chest and better handled the case when inventory is full
Corrected the examine text of the armadyl plateskirt
Fixed the dialogue for lady of the lake
The player is now locked and can't interrupt stepping stone shortcuts
2023-09-01 12:11:16 +00:00
Danewolf
0c6b6540f4
Improved accuracy of stats for minotaur familiars 2023-09-01 12:02:19 +00:00
Roysten
9e4f94867e
Fixed typos in Romeo & Juliet 2023-09-01 11:51:26 +00:00
bushtail
081f14b5e8 Fixed Doric's Quest's log appearing blank 2023-08-31 08:34:08 +00:00
Zerken
2747eb61ec Implemented a new Teleport zone restriction and added a check to the teleport manager to see if the player is teleport zone restricted
The firemaking cape will no longer be deleted when logging out in a darkzone
The Stronghold of Security Gift of Peace, Grain of Plenty, and Box of Health will now add coins to already existing stack of coins if inventory is full
The Cradle of Life will now unlock emotes from all previous Stronghold of Security levels if completed (This was added for older accounts which have completed the stronghold of security but are missing the emotes)
Implemented an Entrana allowed item check
If skillcape perks are active then the player is allowed to bring the runecrafting cape(s) to entrana
The teleport block in fishing trawler now only applies while on the boat and is cleared upon logout/leave
Fixed an issue where you could teleport out of the sunk fishing trawler
Fixed an issue where a logout listener was not being removed after failing the fishing trawler causing the player to be teleported to port khazard after their next login
Added a check to to see if the player has items banned on entrana
Blue dragon scales have had their respawn timer corrected to 18 seconds
Fixed the warriors guild cyclops room logout listener to properly be removed when leaving
Players will no longer get stuck if logging out during agility obstacles
Enchanted jewellery teleports now close any open interface
Players can no longer complete the Falador medium diary goal of pickpocketing a guard without 40 thieving
2023-08-31 08:23:39 +00:00
Ceikry
8116cae7df Fixed performance issue where entities could have multiple movement operations running at a time 2023-08-30 06:54:28 +00:00
Avi Weinstock
a0435fb890 Deep wilderness threats now continue at next login if present when logging out
Decreased brawler gloves and PvP gear drop rate from ordinary deep wilderness NPCs (does not apply to revenants or chaos elemental)
Brawler gloves and PvP gear drops from ordinary deep wilderness NPCs now require at least 100k high alchemy risk (does not apply to revenants or chaos elemental)
2023-08-29 07:41:59 +00:00
Ceikry
4276ed731d Corrected some inauthenticities in the script processor
Soft queued scripts no longer remove weak scripts
Soft queued scripts now delay logout until processed
2023-08-29 01:29:09 +00:00
Woahscam
93082bc94a Fixed issue where eating/firemaking/decanting replaced item from incorrect inventory slot
Corrected potion decanting and bank pin interface sounds
2023-08-28 13:08:45 +00:00
Mihoshika
1d775bd2d3 Fixed visual issue when displaying female characters in tutorial island's character customisation 2023-08-28 05:27:35 +00:00
Avi Weinstock
032cb2e900 Implemented applying weapon poison to crossbow bolts and Morrigan's javelins 2023-08-28 05:15:33 +00:00
Player Name
ad8f77c33e Ring of the Star Sprite teleport no longer gives a wilderness warning for bounty hunter star (as it's not in the wilderness zone and has a bank available) 2023-08-28 05:06:30 +00:00
Ceikry
50dce880c1 Rewrote blast furnace 2023-08-27 13:35:14 +00:00
Player Name
e9fa9d0d41 Construction improvements
Relaxed constraint on room rotation to allow for blind walls
Prevent the room snapping into a different rotation than the one specified
2023-08-25 09:39:10 +00:00
Avi Weinstock
e84192d985 Implemented special attacks for Morrigan's throwing axes and javelins 2023-08-25 09:28:30 +00:00
Avi Weinstock
10a6a19e9e Fixed weapon interface and attack animations on Vesta's longsword 2023-08-25 02:34:03 +00:00
Kennynes
0200ff058e Corrected banshee drop table
Added requirements to some heraldic (construction) equipment
2023-08-24 14:21:09 +00:00
Zerken
c52e02936d Audio refactor continued
Implemented admin audio command ::audio audioId loops[optional]
Implemented admin globalaudio command ::globalaudio audioId radius playername (plays from that players location) or can be used by coords ::globalaudio audioId radius x y z
Refactored the following sounds:
Tribal totem quest Cromperty teleport (fixed looping)
Vinesweeper tool leprechaun teleport sound (Corrected this sound so it does not loop 10 times)
Antifire and poision immunity 30 seconds remaining tick tock sounds and sound of the potions expiring (Fixed it so it plays the correct number of tick tocks)
Sound when summoning a familiar (All familiars were using the summon unicorn sound. It is now defaulted to the normal summoning sound instead of the unicorn summon sound. All familiars on first summon have a their own sounds that will need to be implemented later)
Door and gate sounds
Bank interface sounds
Unicorn stallion special move sound
Agility pyramid rolling block sounds
Prayer book sounds
Lunar stat spy
Hunter falconry
Picking items in a field like potatoes
Ectophial teleport and refill
Summoning pouch creation and renewing points
Runecrafting at altar sound
Making finished and unfinished potions
Cutting gems
Entering giant mole area
Praying at an altar
Warriors guild animator sounds
Chiseling limestone
Spirit wolf special move sound
Telegrab spell sound
Glassblowing sound
Strong of security opening reward chest creaking sound
Butterfly net sound
Desert rug travel rise and descend sound
Enchanting bolts
Woodcutting tree falling and chopping sound
Hunter setting up dismantling traps and pitfall sounds
Explorers ring run energy restore sound
Farming: Raking, adding compost to patch, picking from fruit trees, seed dibb, using plant cure on patch, opening/closing/adding to/from compost bin
Mage training arena alchemy spell sounds
Breaking bones to peaches/bananas tab sound
Casting silver sickle bloom
Entrana magic door teleport
Cabbage teleport
Teleother cast sound
Fairy ring teleport sound
Lunar vengeance spells
Running out of prayer sound
Lunar (non teleport) spells
Super heat and bones to bananas normal spell book sounds
Equip/unequip item sound
Revenant combat sounds
Herb cleaning sound
Emptying buckets/bowls/jugs of water
Making cannonballs at a furnace
Digging with a spade
Peer the seer fremmenik trials challenge: heating items on the range
Blessing a spirit shield at a POH altar
ContentAPI function stun sound
Picking up items off the ground
Eating food sound
Cooking and intentionally burning food
Drinking a potion
Warriors guild catapult
Pulling wilderness teleport levers
Offering bones on a POH altar
Slashing spider webs in Varrock sewers
Entering POH portal teleport sound
GE exchanging item set sound
Jumping wilderness ditch
Dragon axe special
Digging up a farming patch
Lunar heal spells
Chaos elemental projectile impact sounds
Mounted glory teleport
Lunar share and boost potion spell
Dwarf multi cannon setup, rotate, and firing sounds
NPC attacking sound
Enchanted bolt effect combat sound
2023-08-24 13:58:19 +00:00
Player Name
00af62e449 Pets no longer count as summoning for split combat level calculation 2023-08-23 09:11:47 +00:00
Danewolf
9290d67000 Antipoison effects now trigger for the correct durations 2023-08-23 07:20:48 +00:00
Zerken
9cee4dd38a Fixed (for real) Jeremy missing in Fight Arena 2023-08-22 06:08:28 +00:00
Ceikry
3d9a3615f8 Fixed bug in fight quest where Jeremy was teleported incorrectly 2023-08-20 13:20:29 +00:00
Zerken
a105821427 Audio Refactor
1st of many audio refactors, the end goal is removing AudioManager.java and using contentAPI functions for all sound
Refactored playAudio
Refactored playGlobalAudio
Fixed lunar teleport sounds to not play if teleblocked
Refactored the following sounds:
All the special attack and DFS sounds defaulting to new API radius of 8 instead of 5
Dropping coins, item, and destroying object sounds fixed
Ectophial refill sound
Agility pyramid sounds
Emptying a fishbowl
Enchanted jewellery teleport sound
Enchanted jewellery enchant tab sound
All the sounds for Elemental Workshop 1 listeners
The sound when getting experience from a lamp
Blessing and repairing a grave
Hunter pitfall sounds
Hunter sound when catching a kebbit with a noose
Lunar cure me and cure group spell sound
High and low alchemy spells
Silver crafting at a furnace
Spinning at a spinning wheel
Drinking from a waterskin in the desert
Sound when being blessed by drezel in nature's spirit quest
Sound when poison immunity has 30 seconds left and when your immunity expires
Shearing regular sheep and the penguin sheep at lumbridge
Sound when regular spell book charge spell expires
GE sounds: making 0 coin offer when buying, not having enough money, placing a buy offer, not enough room in inventory
Sound when filling vessels from a water source
Regular and ancient combat spells
2023-08-20 07:21:24 +00:00
Player Name
7a585796be Fixed incorrect message when trying to use teleport levers while teleblocked 2023-08-20 03:40:36 +00:00
Ceikry
f8cdb5cff5 Players now can't attack deep wilderness threats focused on other players 2023-08-20 02:51:45 +00:00
Ceikry
e424478a1c Improved teleblock condition checking 2023-08-20 02:27:21 +00:00
Woahscam
5cb9ef8511 Added new camera API methods (including shake and reset)
Added new admin commands for testing camera movements (::poscam, ::movcam, ::rotcam, ::shakecam, ::resetcam)
2023-08-19 15:45:54 +00:00
bushtail
1b4e0aafaa Code cleanup
Reorganised imports
Removed redundant qualifiers
2023-08-19 15:07:23 +00:00
Player Name
0eca9521bc Spiritual warriors and spiritual rangers now correctly drop hard clue scrolls 2023-08-18 02:21:19 +00:00
ceikry
d666317a68 Fix edge case save parsing issue for poison 2023-08-17 22:15:36 +00:00
Player Name
162cfe3d6b Obelisk improvements
Made the wilderness teleport obelisks roll the destination obelisk fairly
Improved obelisk teleport positioning logic
Made the obelisk teleport capture a 3-by-3 bounding box of players, in accordance with the teleport animation
2023-08-17 12:55:32 +00:00
Ceikry
11ebc0c0c4 Fixed regression causing random events to trigger for bots 2023-08-17 12:27:20 +00:00
Zerken
dd017c85d2 More sounds + audio refactoring
Modified default audio radius default parameter to be safer, 8 tiles instead of 15
Improved location/direction based sounds
Fixed the way sounds are handled for magic spells (All modern and ancient combat spells. All lunar teleport spells.)
Magic spells now correctly fade in volume the further away you are from a target/player casting or being hit by a spell. The sound starts to fade after a few tiles until it cant be heard anymore
Refactored lunar teleport sounds to use playGlobalAudio
Humidfy now can be heard globally by other players
Fixed Lunar fertile soil spell graphics and animation to be authentic
Weapon attack sounds now start to fade after a few tiles until it cant be heard anymore
NPC attack sound now fades with distance
NPC hurt sound now fades with distance
NPC death sound now fades with distance
Fixed combat punching sound when no weapon is equipped so it can be heard globally
Fixed a issue where you would hear a punching sound when casting any combat spell
Fixed male player hurt sounds when in combat
Implemented female player hurt sounds when in combat
Failing agility obstacles will now play the correct hurt sound based on gender
Fixed low wall agility pyramid sound
Fixed taking damage from dying of thirst in the desert to use correct sounds
Fixed the sound of drinking from a waterskin in the desert
Implemented sound when attaching godsword blades to a hilt
Fixed rune essence mine teleport sound so it no longer loops 10 times and plays authentically
Implemented undead tree attack sound at Draynor manor
Implemented all ectofunctus bone grinder sounds and the sound when offering to the ectofunctus
Implemented mort myre ghast attack and player hurt sounds
Fixed thieving pickpocket fail sounds
Implemented falador guards combat sounds
Implemented varrock guards combat sounds
Implemented draynor market guard combat sounds
Implemented cyclops combat sounds (warriors guild cyclops)
Implemented animated armor combat sounds (all warriors guild animated armors)
Implemented white wolf/big wolf/wolf combat sounds (wolves on white wolf mountain)
2023-08-15 14:30:41 +00:00
Roger
3d2c0f2baa Added Dockerfile 2023-08-14 14:40:45 +00:00
Player Name
232cae454a Fixed typo in "the poison has worn off" message 2023-08-14 14:31:51 +00:00
Ceikry
86a25dd76f Fixed issue where unequip listeners did not fire on death 2023-08-14 14:14:38 +00:00
Ceikry
678d25dacd Timers can be flagged for removal on death (fixes deep wilderness threats attacking for brief period after respawn)
Fixed an issue with the skill restore timer that caused overheals to be reset to normal hp
2023-08-14 13:22:53 +00:00
Ceikry
a3e6df109d Random event manager rewrite
Time until next random event now persists across logins
Events will no longer spawn while the player has an interface like the bank open
Replaced the slurry of random event commands with a singular ::revent admin command
Random events now support being associated with multiple skills
Random event selection is now more robust
Players will no longer get skill-based random events if more than 2.5 minutes have passed since training the skill
2023-08-14 12:56:35 +00:00
Oven Bread
bb21ad533b Implemented Clock Tower quest 2023-08-12 08:39:53 +00:00
Dark Sage
6112abf673 Combat sounds overhaul
Sound effects for every ancient spell have been corrected
Every special attack weapon currently accessible has had sound added or implementation modified:
Dragon Battleaxe
Excalibur & Enhanced Excalibur
Dragon Halberd
Dragon 2h
Rune Thrownaxe
Vesta's Spear
Ancient Mace
Bandos Godsword
Bone Dagger
Darklight
Dorgeshuun Crossbow
Dragon Scimitar
Statius's Warhammer
Seercull
Armadyl Godsword
Dragon Longsword
Dragon Mace
Magic Longbow
Magic Comp Bow
Rune Claws
Vesta's Longsword
Dark Bow
Dragon Claws
Dragon Dagger
Granite Maul
Magic Shortbow
Saradomin Sword
Dragon Spear
Zamorakian Spear
Zamorak Godsword
Dragonfire Shield
2023-08-12 08:31:15 +00:00
Ceikry
95012b9ca5 Fixed bug where players couldn't log in after logging out after being frozen 2023-08-12 02:08:19 +00:00
Ceikry
35f9a92aef Fixed an issue causing erroneous persistence of graves 2023-08-12 00:30:35 +00:00
Ceikry
2e70a9714a Fixed regression causing GE to eat noted items 2023-08-12 00:21:25 +00:00
Ceikry
418f239261 Fixed item dupe in GE 2023-08-11 13:09:35 +00:00
Ceikry
98a5b95407 Fixed combat movement regression that occurred when fighting large NPCs 2023-08-11 01:30:58 +00:00
Ceikry
6a3e91f13c Deep wilderness threat balancing
Killing the hostile event now removes all built up threat
Hostile event can now follow the player up/down stairs, through cave entrances, etc.
Hostile event now applies disease status for 25 hits when killed
Reduced the threat gained by killing NPCs by 5x
Increased the threat gained by brawlers drops by 3.75x
PvP gear drops now award maximum threat (30 minutes to return to zero)
In summary, the hostile event will trigger less often but will be more dangerous
2023-08-11 00:09:07 +00:00
Danewolf
1be9335815 Added droptrick check to Sir Pyrsin dialogue for silverlight 2023-08-10 07:45:32 +00:00
Ceikry
0f908a1544 Deep wilderness balancing
Added a threat system to the deep wilderness that increases as a player kills NPCs to add balance to lucrative drop rates of PvP items in the deep wilderness
Threat decreases with time
Threat only increases in the deep wilderness
As threat increases, the risk of encountering hostile wilderness events increases
Hostile wilderness events may spawn anywhere in the wilderness
Improved the safety checks on items dropped in PvP
Untradeable items dropped in PvP will now yield an amount of coins proportional to the item's high alchemy value, and delete the item. This amount is halved if the killer doesn't have the level for high alchemy. An additional 250 gp is deducted (after halving, if applicable) from all items to account for the hypothetical cost of a nature rune
Added admin command to view threat level ::dwthreat
2023-08-09 04:02:18 +00:00
ceikry
8b6678d4ee Batched grafana writes into 30 second intervals 2023-08-07 05:00:18 +00:00
Danewolf
d14b2c7d09 Made it possible to get multiple Silverlights after completing Demon Slayer
Made it possible to craft Darklight with black ink after completing The Golem quest
2023-08-07 03:26:55 +00:00
Oven Bread
dd6909908c Converted goblin village population sign into listener 2023-08-07 03:11:35 +00:00
Ceikry
ab17ef11a1 Fixed regression - wilderness levers and obelisk teleports 2023-08-07 02:59:29 +00:00
Zerken
c6cd12703f Fixed regression - the restless ghost is now able to be completed by adding the skull to the coffin
Fixed regression - house teleport and teletabs not working due to being teleblocked by the cast
Fixed regression - WildernessGateHandler now only prompts the player and applies the skull when interacting with the gates in the wilderness and not other gates
2023-08-07 02:43:58 +00:00
Ceikry
1b996b9b82 Fixed unreachable grand exchange NPC exchange option 2023-08-07 02:28:32 +00:00
Ceikry
c23051db93 Fixed quest tests not using the correct startup procedure 2023-08-06 13:35:19 +00:00
Zerken
604925f513 Implemented Evil Bob's Island random event
Added admin command ::bob to start random event
2023-08-06 13:03:45 +00:00
Kennynes
31e865759e Hard clue equipment audit
Blue D'hide Body (g) - 40 Def and 50 Ranged req fixed
Blue D'hide Body (t) - 40 Def and 50 Ranged req fixed
Zamorak Chaps - Added 40 Def req
Guthix Chaps - Added 40 def req
Saradomin Chaps - Added 40 def req
Heraldic rune equipment - Added requirements
2023-08-06 12:54:40 +00:00
Ceikry
16a7640e56 Greatly improved server performance by limiting the max wander radius return-to-spawn behavior applies to, and ensuring only one return-to-spawn movement pulse triggers at a time 2023-08-06 12:30:13 +00:00
Player Name
6cf0e03177 Star sprite ring teleport can now be used in the wilderness up to level 20 2023-08-06 11:03:47 +00:00
Player Name
b34e99d156 Fixed inappropriate inventory full message when woodcutting 2023-08-04 07:22:37 +00:00
Zerken
cf8b56c0f4 Fixed enchanted lyre teleport bypassing teleblock 2023-08-04 07:12:34 +00:00
Ceikry
0ca2b8d99c Fixed wilderness teleblock bug 2023-08-03 13:36:07 +00:00
Ceikry
4098f2bf0b Fixed an issue causing a build up of pulses when regions are unloaded and npcs are still navigating back to their spawns 2023-08-03 13:26:40 +00:00
Player Name
255fc9eca6 Fixed Teleport to House to teleport the player inside the house, rather than outside the entrance portal
Removed HouseTeleportPlugin.java deadcode
2023-08-02 07:39:45 +00:00
Zerken
9f7e633c2b Fixed stronghold of player safety reward regression 2023-08-02 03:54:28 +00:00
Oven Bread
e7fa5b576d Fixed unnoting of ore by Ordan
Corrected Ordan's and Jorzik's dialogue and faces
2023-08-02 01:25:23 +00:00
Ceikry
fd5998453d Fixed infinite lunar cast range 2023-08-02 00:52:19 +00:00
Ceikry
6d23ec5234 Added farming patch safety checks 2023-08-02 00:39:04 +00:00
Ceikry
105f7d5b86 Made familiar code more testable
Fixed an issue with the bloated leech "blood drain" ability
2023-07-31 15:08:47 +00:00
Ceikry
ee79b0750c Grafana Integration + Unified SQLite Boilerplate + Fixed bot movement performance regression 2023-07-31 14:59:53 +00:00
Ceikry
ac0da92a58 Fixed desert wyrm node search 2023-07-31 03:58:09 +00:00
Ceikry
6147293431 Improved the performance of drop table rolling
Chromatic Dragon eggs now only drop at a 1/1000 rate if the player has 99 summoning, impossible to obtain otherwise
2023-07-31 03:03:03 +00:00
Ceikry
bf26faf2a2 Fixed damage scaling issue with chinchompas. 2023-07-30 21:57:51 +00:00
Ceikry
aa038882e8 Fix plugin-sourced movement walking the player to the same tile as the NPC/Player/etc 2023-07-30 19:38:49 +00:00
Oven Bread
d76b99c77a Improved how books are handled
Implemented admin model viewer ::models
2023-07-30 08:33:40 +00:00
bushtail
3cf73ba09a Rewrote Doric's Quest 2023-07-30 08:24:22 +00:00
Zerken
9b08f2175b Implemented Freaky Forester random event
Added admin ::freak command to trigger Freaky Forester
2023-07-30 02:52:45 +00:00
Player Name
32e1111fc7 Fixed a bug where shooting star xp was awarded incorrectly on the last stardust of a level 2023-07-30 02:23:33 +00:00
Zerken
686a2c9141 Immersive sound update
Fixed all skills to play their correct level up jingles
All skills except agility have 2 level up jingles
Most skills play a different jingle for new unlocks
Some skills have specific jingles based on level/range (Strength, Hitpoints, Hunter, Construction, Summoning)
Implemented furnace sound when crafting silver and gold jewelry at a furnace using moulds
Implemented emptying sound for fishbowls
Fixed cow milking sound so it plays for more than one bucket
Implemented sound when pushing a canoe into the water from a canoe station
Fixed quest complete jingles to play a random 1 of 3 quest jingles
Implemented jingle that plays when changing clothes at Thessalia in Varrock
Implemented jingle that plays when spying on a penguin
Implemented jingle that plays on login with completed grand exchange offers
Implemented sound when spinning items at a spinning wheel
2023-07-29 05:14:11 +00:00
Pine Stone
421c419f69 Fixed deadlock regression in bots
Added some runecrafting player scripts
2023-07-29 05:02:38 +00:00
Ceikry
661390e66f Implemented timer subsystem to eventually replace pulses
Authentic subsystem supports saving/loading arbitrary data and resuming timer countdowns
Lots of documented CAPI functions for working with these new timers
Converted poison to new timers
Converted disease to new timers
Converted farming to new timers (CropGrowth and Compost)
Farming now syncs with 5 minute intervals on realtime clocks (authentic)
Converted seedling growth to new timers
Converted shooting star mining bonus to new timers
Converted entity freezing to new timers
Converted incubation to new timers
Incubation now supports using both incubators (so 2 eggs at once)
Converted miasmic states to the new timers
Converted god spell charged state to new timers
Converted teleblock to new timers
Converted skulled state to new timers
Converted Enhanced Excalibur special attack effect to new timers
Converted passive stat restoration to timers
Converted multicannon firing and decay to a timer
2023-07-29 04:51:06 +00:00
Oven Bread
bda000f220 Added admin commands for getting and setting attributes
::getattribute [playername] attributename
::setattribute [playername] attributename value
2023-07-29 04:25:23 +00:00
Oven Bread
af3ee7fe09 Connected trollweiss mountains and dungeons, implemented NPCs 2023-07-29 04:09:06 +00:00
Ceikry
cf07fc3787 Fixed a bug that resulted in infinite death if more than one entity died in the same tick 2023-07-29 03:55:13 +00:00
Oven Bread
cb34966f38 Burthorpe Immersion Improvements
Harrallak Menarous isn't sliding around the floor now
Corrected Bernald's Dialogue to be the the one before Garden of Tranquility's quest
Swapped Ocga and Penda's Dialogue (minor) because Penda is the crazy one in the bar
Added drops for killing the Servant
Made Eadburg the chef drops (bones only) and adjusted fighting values
Adjusted guards attack animation
Added Sam and Rachael the gamesroom barmaids
Moved Bernald and Tostig's dialogue from Taverley to Burthorpe
Swapped out default archers on level 2 castle to Burthorpe archers instead
Reserve one archer on level 2 for Death Plateau later
Added more examine texts
Added Unferth as the new spawn and moved Ocga out of that house
Updated Hild's dialogue
2023-07-23 14:49:09 +00:00
Zerken
defe780c39 Agility Pyramid Fixes
Can now properly fail the jump and cross gap obstacles
Fixed an issue when failing the the 2nd level north cross gap obstacle when going west causing the player to get stuck inside the pyramid
Fixed jump/cross gap obstacle sounds
Fixed moving block obstacle audio so the sliding sound plays for all players within 3-4 tiles of the block when it moves
Implemented music/jingle that plays when you get the pyramid top
Updated all agility pyramid sounds to use the new playAudio ContentAPI function and constlib
Added inauthentic gold reward from selling pyramid tops to Simon Templeton based on agility level. GP reward = 1000 + ((agility level / 99) * 9000). Can be toggled with server config option better_agility_pyramid_gp
2023-07-23 14:40:08 +00:00
Ceikry
36dc23ae38 Implemented safer fallback woodcutting rates 2023-07-23 14:26:03 +00:00
bushtail
58fff59f1b Minor quest function refactors
Quest journal text improvements
2023-07-23 14:08:18 +00:00
Ceikry
2e6eed69e6 Switched shooting star ring over to new quest requirement system 2023-07-23 13:45:28 +00:00
Zerken
942fd2876e Shantay quick-pass now functions authentically 2023-07-17 08:59:35 +00:00
Zerken
6de25bd7e1 Implemented entrance to grand tree mine 2023-07-17 08:40:45 +00:00
Ceikry
845d8b383b Exception fixes
Fixed a bug that could occasionally cause the sandwich lady interface to become unresponsive
Fixed an issue that could cause shade random events to not spawn for max-level players
Fixed an issue that could cause zombie random events to not spawn for max-level players
Fixed a widespread book issue that resulted from not resetting the current page index when closing a book, and then trying to open another book with less pages.
Converted bogrog pouch swap to the generic item select interface, and removed relevant code from the grand exchange code
Fixed an issue that could occasionally prevent exchange of item sets
Fixed an issue with Diango's reclaim interface that could result in items other than the ones you clicked being claimed
Made incubation moderately more reliable, and incubation timers now pass even while offline
Fixed an issue that prevented the leather crafting dialogue from accepting tokenized amounts (e.g. 100k)
Fixed an issue that prevented the tool leprechaun interface from allowing tokenized amounts
Fixed an issue that prevented players from using tokenized amounts in the ogleroot purchase dialogue for vinesweeper
Fixed an issue that prevented Zaff's batttlestaff dialogue from accepting tokenized amounts
Fixed an issue that prevented shop buy-x options from accepting tokenized amounts
Various shop-related exception fixes
Added some ingame player messages for when a Hunter "catch" option isn't being handled properly
Fixed some exceptions being thrown by lunar spells
Pyramid Plunder is now better at detecting when a player is in the minigame erroneously and kicking them out
Fixed an issue that would lead to incorrect Kalphite Queen behavior when killing her with multiple players in the room
Fixed an issue that could cause the Bedabin Nomad's dialogue to hang during Tourist Trap
Fixed several more issues with Fight Arena cutscenes
Fixed an issue that could prevent the dwarf dialogue from opening while trying to enter the mountain shortcut before finishing Fishing Contest
Fixed an issue that could cause dialogue option hangs in certain unusual circumstances
Fixed an issue that could result in non-movement for interactions where the override location was the same as the target node's location and there was no destination flag set
Fixed an issue where setting invalid node data could cause issues with NPC rendering
Server can now detect when a session is sending up multiple invalid packets and automatically disconnect the player
Fixed an issue that could lead to unintended saving of varps/varbits
Fixed an issue that could cause some interactions in shops to silently fail. The user will now receive a relevant message when these situations occur
Users may now find they could occasionally receive a very snarky response when incorrectly using commands
Users now receive messages when they try to make use of unimplemented friends/clan/etc features.
Errors in string parsing will no longer result in "dead" inputs when attempting to add friends/update clan ranks/etc
Fixed an issue that could lead to loss of some alerts in the Discord integration. Discord integration will now detect problems and queue the failed messages to be resent later.
Added more safety checks to item-on-grounditem packet handling to prevent throwing exceptions
Exceptions in string parsing for command packets will now inform the user that something went wrong, and ask them to try again.
Improved drop table parsing and fixed incorrect drop tables
2023-07-17 08:12:57 +00:00
bushtail
0372937353 Added admin command ::expression <id> for previewing facial expressions 2023-07-14 10:14:23 +00:00
Oven Bread
ab552ce387 Wilderness data updates
Added level 14 scorpions to scorpion pit
Added bones and headless arrow spawns to scorpion pit
Fixed magic axes in small building and made them move (and replaced a mistaken snake in there too)
2023-07-14 09:55:08 +00:00
Ceikry
fa1f7296f2 Implemented the herblore skill cape perk as described on the website - 15% chance to make a 4-dose potion 2023-07-14 09:42:11 +00:00
SudoSauce
ca242c056c Updated readme to refer people to forums for support instead of discord 2023-07-10 05:35:28 +00:00
Player Name
c9e3ad4335 Only consume daily Ring of the Star Sprite teleport if the teleport succeeds 2023-07-10 02:17:32 +00:00
Ceikry
d58d4857b0 removeItem now validates item quantities prior to attempting removal 2023-07-09 04:51:10 +00:00
bushtail
6d96611d69 Removed erroneous print line in server startup 2023-07-09 04:25:37 +00:00
ceikry
caad0ceaf9 Improved performance of champion's challenge scroll handling 2023-07-09 03:58:38 +00:00
zsrv
417db14d5c Implemented split combat levels
A split combat level (e.g. 50+5) will be displayed for a player when the player is on a PvP world and does not have a summoning pouch or a familiar summoned.
A split combat level will also be shown if the player is on a world with wilderness PvP enabled, the player is in the wilderness, and does not have a summoning pouch or a familiar summoned.
If the world is a PvP world, display other players' combat levels in white if they are outside of combat range, or shades of green/yellow/orange/red if they are within combat range.
If the world is not a PvP world, always display other players' combat levels in shades of green/yellow/orange/red.
2023-07-09 03:54:31 +00:00
SZUMASTER
a6d5961226 Fixed disappearing key with full inventory in waterfall quest 2023-07-08 15:12:56 +00:00
bushtail
45bedcf1cb Added periods to the EnchantedJewellery destinations 2023-07-08 13:55:47 +00:00
szumaster
2f74cdaff8 Added Sin'keth's diary 2023-07-01 06:34:37 +00:00
Player Name
788a9ca405 Any barrows brother not yet killed is now able to now spawn in the tunnels 2023-07-01 06:20:37 +00:00
szumaster
1ab2b9db01 Removed void spawns for flesh crawler and zombie 2023-07-01 06:11:55 +00:00
Ceikry
cb16fe4305 Reintroduced PvP to level 49 deep wilderness and above (beyond the gate)
Traveling into the PvP area will auto-skull the player, but only whilst they remain in the area
PvP in the deep wilderness does not apply a hard skull
Deep wilderness soft skull is removed immediately upon leaving the deep wilderness
Gates into the deep wilderness now give a warning about the danger of entering
Gates allowing exit from the deep wilderness will not allow a player to leave if they are in combat
The obelisk teleporter in the deep wilderness will not allow a player to use it if they are in combat
All NPCs in the deep wilderness now drop PvP gear and brawlers
The drop rate of PvP gear and brawlers in the deep wilderness has been boosted
Fixed an issue that allowed PvP outside of explicit PvP scenarios
2023-06-29 11:10:25 +00:00
szumaster
9b822d1dff Fixed incorrect slayer requirements on spiny helmet 2023-06-29 08:46:51 +00:00
Trident101
e7eec2ebf7 Implemented gnomish drinks
Fixed cocktail drinking animation
2023-06-29 08:38:31 +00:00
Trident101
64aae6ca6b Fixed Dragon Slayer quest typos 2023-06-29 07:55:21 +00:00
Ceikry
06e8279f2a Refactored movement pulse
Fixed bug with Vinesweeper gnomes not checking flags
Fixed hunter tracking
2023-06-29 01:46:00 +00:00
Zerken
da33c89a70 Implemented summoning skillcape perk
Pet Mastery: With your mastery of summoning familiars you have also learned the ability to teach pets to fend for themselves - they no longer rely on you for food. While the summoning cape is equipped your pet's hunger no longer increases (applies to all pets).
2023-06-28 07:31:42 +00:00
szumaster
e965b8bb41 Added missing face expression to Greldo 2023-06-27 13:12:37 +00:00
Oven Bread
2f4781e4ce Implemented Death Plateau quest 2023-06-27 12:28:04 +00:00
Trident101
c7e8c54068 Added melee animation for jail guard 2023-06-27 00:27:44 +00:00
szumaster
a09a35ed5c Locked moss giant pipe achievement behind requirements 2023-06-25 14:01:58 +00:00
Zerken
89cbbe2765 Peer the Seer fixes
Players can no longer enter with any items in inventory or equipped
The full vase is now removed from the player's inventory when placing it on the frozen table
2023-06-25 13:45:11 +00:00
Trident101
e9a373e328 Corrected fancy dress shop items
Added item config for key given during Prince Ali Rescue quest
2023-06-25 13:30:49 +00:00
Bart Ribbers
02e06a9591 Aggie is no longer looking so mean 2023-06-23 15:40:30 +00:00
Zerken
e0f99de75b Implemented a new playAudio function in ContentAPI.kt
Implemented a new Send function in AudioManager.java
Implemented KBD lair teleport levers lever operating sound using the new playAudio function
Implemented KBD lair teleport levers pulling animation
2023-06-21 15:12:24 +00:00
Zerken
cef956722a Implemented water filling sounds for filling water vessels from all water sources
Implemented specific bucket water filling sound when filling from a well
Implemented emptying sounds for emptying vessels
Implemented cow milking sound
Implemented sound when smelting at a furnace
Implemented sound when smelting cannonballs at a furnace
Implemented sound when glassblowing
Fixed herb cleaning sound
Fixed regular wood door opening and closing sounds
Implemented metal door/gate opening and closing sounds
Implemented fence opening and closing sounds
Added Camelot castle main gate in door_configs.json
Fixed Sinclair mansion main gate to be a metal type door in door_configs.json
Implemented drinking sound when drinking from a waterskin in the desert
Implemented desert magic carpet travel take off and landing sound
Implemented desert magic carpet travel jingle/music
Fence around Falador cow farm is now properly identified as a fence and opens correctly
Fence id 34780 is now properly identified as a fence in door_configs.json so it opens correctly
Fence id 8810 is now properly identified as a fence in door_configs.json so it opens correctly
Fence id 2050-2051 is now properly identified as a fence in door_configs.json so it opens correctly
Fence id 1553 now has the correct open id in door_configs.json so it opens correctly
Fixed music tracks Relleka(289), Saga(290), and Borderlands(291) so they now play in their correct locations
Implemented jingle/music for sailing/chartering a ship(Trader crewmembers)
Implemented jingle/music for sailing/chartering a ship from/to Port Sarim/Karamja
Implemented jingle/music for sailing/chartering a ship from/to Port Sarim/Entrana
Implemented jingle/music for sailing/chartering a ship from/to Relleka/Neitiznot
Implemented jingle/music for sailing/chartering a ship from/to Relleka/Jatizso
Implemented jingle/music for sailing/chartering a ship from/to Ardougne/Brimmhaven
Implemented jingle/music for sailing/chartering a ship from/to Port Sarim/Pest control
Fixed the music player to be more authentic. Now when songs end they will repeat instead of playing a random inauthentic song. The loop function now works correctly so the currently playing song will play endlessly without changing as the player moves.
Implemented playJingle function in contentAPI.kt
2023-06-21 14:57:01 +00:00
szumaster
1672646e87 Added attack requirement to Zuriel's Staff
Added missing requirements for items received from treasure trails
Delete unused range weapon configs
Fixed inverted requirements for enchanted hat and top
2023-06-21 14:37:27 +00:00
Oven Bread
30c9a752bf Dialogues updated for non-quest NPCs in Burthorpe:
Breoca
Ceolburg
Hygd
Ocga
Penda
Wistan the shopkeeper
Servant
2023-06-16 11:35:21 +00:00
szumaster
2a3ac5ffab Corrected Shaikahan animations and examine text 2023-06-16 11:17:44 +00:00
szumaster
eb65c4c78b Implemented 3 unique books for Wise Old Man's house, books are located in the bookshelves in his house
New Wise Old Man dialogue trees for books
Implemented book for digsite quest
2023-06-16 11:04:40 +00:00
ceikry
3d8857e01c Fixed issue causing canoe stations to permanently lock players when interrupted 2023-06-16 09:07:59 +00:00
szumaster
f26a4660ea Corrected Fist of Guthix item requirements 2023-06-16 08:41:08 +00:00
Ceikry
2f234cc589 Fixed bug where combat level didn't update after leveling a combat skill 2023-06-16 07:48:09 +00:00
Ceikry
aab37414c3 Fixed an edge case when working with varbits that encapsulate the 31st bit of a varp
Fixed health check of whiteberry bush
2023-06-16 07:04:20 +00:00
Zerken
d04302c99f Hunter sound improvements
Implemented setup, dismantle, and catching sound for bird snares
Implemented setup, dismantle, and catching sound for box traps
Implemented setup, dismantle, and catching sound for net traps
Implemented setup, dismantle, and catching sound for dead falls
Implemented setup and dismantle sound for rabbit snares
Implemented butterfly net swing sound
Implemented falconry fly and catch sound
Implemented noose sound when catching kebbits
Implemented setup, dismantle, catching, teasing, jumping over, and npc jumping over pitfall sound to pitfalls
Implemented appropriate player lock time to setting up net traps and deadfalls to avoid players from interrupting the action
Implemented appropriate player lock time to dismantling bird snares, box traps, net traps, rabbit snares and deadfalls to avoid players from interrupting the action
Implemented a new function to play sound at a location
2023-06-16 06:28:40 +00:00
Zerken
22776e7bb3 Unicorn stallion pouches now cost 140 shards instead of 203
Hydra, Spirit Dagannoth, Unicorn Stallion, Wolpertinger, and Pack Yak pouches now consume pouches when created at an obelisk
Implemented the song Animal Apogee to play at Taverly summoning obelisk, Piscatoris summoning obelisk, Natures Grotto obelisk
2023-06-16 05:58:46 +00:00
szumaster
51ab17e3aa added champion challenge 2023-06-13 12:17:48 +00:00
Oven Bread
7997fbb0b0 Implemented the thieving skillcape
Removed inauthentic HAM robes pickpocket buff
2023-06-11 08:05:16 +00:00
Danewolf
4bd97d002f Now able to empty poison, brews and serums 2023-06-11 05:47:29 +00:00
Ceikry
330d66918a Improved clamping for force movement, fixes client crashes in Nature Spirit 2023-06-10 08:29:51 +00:00
Zerken
c58309e685 Implemented Piscatoris washbasin water bucket filling 2023-06-09 15:42:42 +00:00
Ceikry
7ca0493190 Temporarily evaluate all soft requirements as hard requirements (until the quest system is refined enough to properly leverage soft requirements), fixes inability to meet requirements when prayer is low 2023-06-09 15:33:58 +00:00
Ryan
74380b039b Removed obsolete GE files 2023-06-09 15:05:30 +00:00
szumaster
33064660cf Fight Arena bug fixes
Added access to fightslave conversation through the prison wall
Added drop for Khazard guards and General Khazard
Added face location for each npc
Added missing dialogues for each npc
Corrected the quest complete interface
Corrected quest journal text
Fixed barman who didn't sell Khali Brew after completing quest
Fixed center doors to arena (player no longer gets stuck in cutscene) and corrected walking through the door
Fixed small head in dialogues for General Khazard
Increased the time of dissapearing for Ogre, Scoprion and Bouncer 144 -> 300 ticks
Lazy guard falls asleep and leaves the keys after being given khali brew
Can get replacement keys if lost
Sped up the camera movement for the bouncer and scorpion cutscene
The sequence of entering the cell after the fight with the ogre has been sped up
2023-06-09 14:11:36 +00:00
Ceikry
bd12800cca Fixed some issues with incorrectly reading varbit values
Fixed Dwarf Cannon quest
Improved varp/varbit interface and handling
2023-06-06 09:31:16 +00:00
Ceikry
f613fb13cd Implemented drop summoning pets 2023-06-06 09:19:23 +00:00
Ceikry
c20770fcb3 Fixed Sophanem southeast entrance requirements 2023-06-06 09:06:02 +00:00
Ceikry
f6cd646205 Made it possible to claim Fremennik diary rewards 2023-06-06 08:16:07 +00:00
Ceikry
f5711fcf8f Fixed plank make without sufficient funds
Fixed potions not taking doses in some cases
2023-06-06 08:02:55 +00:00
ceikry
3d20bb97d0 Fixed an exploit in surprise exam 2023-06-06 07:35:31 +00:00
Ceikry
c1b2fdf597 Autocasting defensive spells now awards correct XP 2023-06-06 07:34:00 +00:00
Ceikry
b6d02cce17 Fixed bug causing Puro Puro implings to cluster in the north east corner 2023-06-06 03:11:15 +00:00
Ceikry
810528dfb4 Removed vinesweeper rabbits' telekinetic powers 2023-06-06 02:31:55 +00:00
Ceikry
37fe071041 Fixed a bug that allowed use-with interactions to interrupt locks
Fixed a bug that resulted in loss of seeds when interrupting planting
2023-06-06 02:23:26 +00:00
Ceikry
df5b260f5f Clamp forcemovement values in packet to avoid divide-by-zero errors in the client 2023-06-06 02:08:53 +00:00
Ceikry
c3d48ff36e Added configurable limit for GE bot offers, now set by world.botstock_limit config (defaults to 5000) 2023-06-06 00:19:18 +00:00
AshLilly
3d8a6c6e5a Fixed a typo in Captain Lawgof's dialogue 2023-06-05 06:58:11 +00:00
Pine Stone
048a745371 Allow_aggro now persists across sessions 2023-06-05 06:48:57 +00:00
Ceikry
c1007683a5 Fixed an off-by-one error in quest point checking 2023-06-02 16:04:28 +00:00
szumaster
047a2b818a Implemented some books
Abyssal book
Astronomy book
Gianne's cook book
Instruction manual
Binding book
Shaman's tome book
Nulodion's notes
2023-06-02 10:51:43 +00:00
szumaster
bf91e47ddc Improved taunting the lesser demon in the Wizards' Tower 2023-06-02 10:41:46 +00:00
Oven Bread
8bbe8cf57d Fixed dialogue hang in Plague City 2023-06-02 10:28:02 +00:00
szumaster
d492500812 Added missing scrolls
King's message
Iorwerth's message
Crumpled scroll
Tattered scroll
Dusty scroll
2023-06-02 10:04:24 +00:00
Oven Bread
fc9f23385f Fixed tutorial island's run tutorial not recognising the run button 2023-06-02 09:55:20 +00:00
Oven Bread
d5222bad1e Burthorpe immersion improvements
Implemented the roaming Burthorpe soldiers dialogues, including random Latin insults
Implemented the other soldiers/sergeants/archers/guards busy messages.
All 10 soldiers in the square now face north towards their sergeant
2023-06-02 09:17:29 +00:00
szumaster
0a41704490 Implemented Plague City quest
Added dwellberries spawns to McGrubor's Wood
2023-06-02 09:09:08 +00:00
Danewolf
48cc5048af Implemented poison for bone dagger 2023-06-02 08:47:30 +00:00
Avi Weinstock
aec9476438 Ensure corporeal beast takes half-damage from non-spears
Ensure familiars enter the corporeal beast arena
Corrected Vesta's spear attack rate
2023-06-02 08:35:34 +00:00
Trident101
c266e9ecaa Barbarian super restore mix now consumable 2023-06-02 04:46:33 +00:00
Avi Weinstock
a313c227d5 Implemented Falador cannonball bot that contributes stock to the GE 2023-06-02 02:15:13 +00:00
Ceikry
9a25c2a87d Improved logout handling 2023-06-02 01:34:01 +00:00
bushtail
817d2f0ec2 Fixed a bug where farming assistant Githan would spawn for bots 2023-06-01 01:21:33 +00:00
Oven Bread
0c54348f69 Created a new ScrollInterface similar to BookInterface
Implemented KnightsNotes in the new scroll interface
2023-05-31 09:09:12 +00:00
Ceikry
cb4c94f3ab Improved lamp xp calculation
Improved shop restrictions
Fixed bugged Cyclops room teleport
2023-05-31 08:58:40 +00:00
zsrv
9150137c47 Fixed Entrana glassblowing pipe house ladder where a player would get stuck between a ladder, chair, and desk 2023-05-31 08:45:33 +00:00
Ceikry
7b0c1b0b9b Player Stock is now cleared from the general store at an interval defined by world.playerstock_clear_mins (defaults to 180 minutes)
Player Stock can now be recirculated back onto the GE as bot offers when cleared if world.playerstock_bot_offers is true (defaults to true)
2023-05-31 08:35:50 +00:00
zsrv
47576b63f0 Added Team-21 cape to William's Wilderness Cape Shop 2023-05-31 08:26:28 +00:00
Ceikry
cb630e7043 Requirements Audit
Added a new quest requirement system
Ensured that all implemented rewards are obtainable, even if all requirements are not implemented
Rewards that should have higher requirements than what is currently obtainable will have those requirements automatically increase as more quests are added
The requirements for any quest can be viewed at any time by clicking it in the quest list
Things that were previously locked/unavailable but are now available (with prereqs) are:
- It is now possible to obtain and equip Barrow's Gloves with the Recipe for Disaster prereqs
- It is now possible to obtain and equip an Ancient Staff with the Desert Treasure prereqs
- It is now possible to enchant your secateurs into Magic Secateurs with the Fairy Tale I - Growing Pains prereqs and 40k gold
- It is now possible to equip the Ancient Mace with the Another Slice of H.A.M prereqs
- It is now possible to get Suqahs as a task from Duradel with the Lunar Diplomacy prereqs
- It is now possible to obtain a Seal of Passage by speaking with Chieftan Brundt after meeting the Lunar Diplomacy prereqs
- It is now possible to obtain Ancient Staves by killing the level 96 and 103 mummies in the Ancient Pyramid (1/500)
Things that were freely available but are now locked include:
- Sophanem now requires/requires the prereqs of Icthlarin's Little Helper
- Pharaoh's Sceptre requires the same^
- Equipping god books now requires Horror from the Deep/its prereqs
- Neitiznot helmet now requires the Fremennik Isles prereqs rather than just Fremennik Trials
- Cape of Legends now correctly requires the full possible prereqs for Legend's Quest rather than just 55 QP
- Dragon Scimitar now correctly requires the Monkey Madness prereqs
- Ape Atoll teleport now correctly requires the Monkey Madness prereqs
- Slayer Helmet and the Slayer Rewards Shop in general now correctly require the Smoking Kills prereqs (not high)
- Dragon Halberd now requires the Regicide prereqs
- Climbing Boots now require the Death Plateau prereqs
- Dragon SQ Shield now requires the Legend's Quest prereqs to equip (source available in sourcecode)
- Initiate Armour now requires the Recruitment Drive prereqs
- Proselyte Armour now requires the Slug Menace prereqs
- Access to Piscatoris now requires the Swan Song prereqs (effectively Quest Cape here.)
- The disease-free herb patch in Trollheim now requires the My Arm's Big Adventure prereqs.
- Ardougne Teleport now requires the Plague City prereqs
- Watchtower Teleport now requires the Watchtower prereqs
- Trollheim Teleport now requires the Eadgar's Ruse prereqs
- The Lunar spellbook now requires the Lunar Diplomacy prereqs
- The Ancient spellbook now requires the Desert Treasure prereqs
- Crafting Astral Runes now requires the Lunar Diplomacy prereqs
- Crafting Death Runes now requires the Mourning's End Part II prereqs
- Crafting Blood Runes now requires the Legacy of Seergaze prereqs
- Access to Cave Horrors now requires the Cabin Fever prereqs
- Sorceress' Garden now requires Prince Ali Rescue
- Access to the Heroes' Guild now requires the Heroes' Quest prereqs
- Access to GWD now requires the Troll Stronghold prereqs
- Access to Neitiznot and Jatizso now requires Fremennik Trials
- Access to Shilo Villa now requires the Shilo Village prereqs
- The Keldagrim cart system now requires The Giant Dwarf prereqs
- Fairy Rings now require the full Fairy Tale I - Growing Pains prereqs
- Ectophial now requires the Ghosts Ahoy prereqs
- Access to Tormented Demons now requires the While Guthix Sleeps prereqs
- Access to the Halberd Shop and the ability to equip Dragon Halberds now requires the Regicide prereqs
- Access to Lletya now requires the Mourning's End Part I prereqs
- Access to Corporeal Beast now requires the Summer's End prereqs
- Chivalry and Piety prayers now require the King's Ransom prereqs
- Ali Morrisane's rune shop now requires the The Feud prereqs
- Armoured Zombies now require the Defender of Varrock prereqs
- Experiments now require the Creature of Fenkenstrain prereqs
- The carpet to Sophanem now requires the Icthlarin's Little Helper prereqs
- The carpet to Uzer now requires The Golem
- The carpet to Bedabin Camp now requires The Tourist Trap
- The bank in Sophanem now requires the Contact! prereqs
- The Dragon Battleaxe now requires the prereqs of Heroes' Quest to equip.
- The Dragon Mace now requires the prereqs of Heroes' Quest to equip.
- Spirit shields of all varieties (improved, blessed, unblessed) now require the prereqs of Summer's End to equip.
- Bork access now requires What Lies Below
2023-05-30 09:03:05 +00:00
Ceikry
5404ef849d Made ironman icons visible in clan and global chat (requires world.ironman_icons to be true)
Authentic tormented demon safe spotting
Added cannon restriction to tormented demon area
2023-05-27 13:59:48 +00:00
Trident101
c3c836de4d Added new field to item configs for overriding alchemy flag
Fixed alchemy for Fremennik items
2023-05-27 12:57:04 +00:00
zsrv
6dcec3c42f Made the Sheep Shearer wool collected count persist between logins
Reorganised, expanded, and corrected the Sheep Shearer quest dialogue
2023-05-26 09:12:09 +00:00
Trident101
f7941f80ab Added Dagannoth hide to the Dagannoth drop table, same weight as Flattened hide and Stretched hide
Changed Dagannoth drop "Oyster pearls" to "Oyster pearl"
2023-05-26 09:03:41 +00:00
Trident101
f9657b75f6 Implemented jug of bad wine 2023-05-25 15:16:37 +00:00
Ceikry
2cb8d82648 Rewrote all the logic, encoding, etc for player/npc rendering masks (Animations, force movements, etc.)
Groundwork for modular 578 support has now been laid (at least in regards to render masks)
Introduced an improved and more accurate API for using force movement (the old API is still around, all of its methods marked as deprecated)
Converted a couple example cases to using the new force movement API just as a proof of concept
Added a method to tick/time conversion methods to convert between client cycles and ticks
Added all authentically-named buffer read/write methods to the buffer class
2023-05-25 14:58:40 +00:00
Trident101
9329d9d008 Fixed the melee, defence and death animation of Port Sarim thief NPC 2023-05-25 14:47:35 +00:00
RiL
47d9c6c4b1 Fixed inaccurate dragon fire damage when shielded 2023-05-25 14:32:59 +00:00
Ceikry
6eed461162 Added some bot debugging support via the "Request Assist" option on bots
Found and fixed the issue causing bots to get stuck or only interact with one thing
Added some additional safety checks in the script processor
2023-05-25 04:33:27 +00:00
RiL
b995436ea4 Removed unkillable dogs from slayer task 2023-05-22 05:02:45 +00:00
Ceikry
f7b707c3da Fixed an issue that was leading to unreliable respawn mechanics on multi-behavior NPCs 2023-05-16 12:42:22 +00:00
RiL
c04ee0f821 Improved handling of skewered food 2023-05-16 12:22:07 +00:00
Ceikry
767117f54e Implemented the proper interaction for low-alchemy option on the Explorer's Ring
Implemented a generic item selection ContentAPI method
Added ContentAPI method for running CS2 scripts
Added development command for running CS2 scripts
2023-05-16 12:08:32 +00:00
RiL
a04191b11e Fixed bots putting inaccessible noted items on GE 2023-05-15 12:49:32 +00:00
bushtail
9f6e7b49be Improved credit gain/loss message 2023-05-15 12:32:28 +00:00
bushtail
2ee8e19668 Expanded the zone for the "Jump for joy at the beehives" treasure trail clue 2023-05-13 12:08:54 +00:00
Ceikry
e7ccab2ad9 Fixed construction issue that would cause objects to become inaccessible (note this does not fix a similar issue related to rotation)
Simplified the region contract for construction
2023-05-09 14:31:43 +00:00
RiL
52633544ff Implemented ::addxp command (admin), add xp to a skill
Implemented ::charge command (admin), get and set the charge of an item
Implemented ::setslayertask command (admin), set the slayer task npc with optional quantity
2023-05-09 00:02:51 +00:00
szumaster
69f4f11bc7 Can no longer water scarecrows 2023-05-07 07:22:34 +00:00
szumaster
c885ebb7e8 Removed Dorgeshuun crossbow requirements 2023-05-07 03:44:20 +00:00
bushtail
6bebd1d53a Teleport fishing spots properly 2023-05-07 03:30:28 +00:00
szumaster
d0ae674155 Fixed facial expression in Onglewip dialogue
Removed Seth from the game
Fixed lamp text
Added missing cow spawns
2023-05-07 03:04:01 +00:00
szumaster
ce7f249880 Added Hazelmere's Scroll 2023-05-07 02:43:29 +00:00
szumaster
2fc98ad0df Implemented Draynor Manor agility shortcut 2023-05-07 02:15:26 +00:00
Oven Bread
bb41f61263 Removed DestroyItemPlugin and bundled functionality into DropListener 2023-05-05 14:50:23 +00:00
Oven Bread
130d2c5af0 Converted Warriors Guild shot put hand dusting to kotlin 2023-05-04 14:41:45 +00:00
szumaster
1f270ae8f0 Removed some inaccessible NPCs 2023-05-04 14:16:42 +00:00
szumaster
9854e207ae Implemented Falador diary task - place scarecrow 2023-05-04 13:59:57 +00:00
Avi Weinstock
572ebeef84 Fixed regression preventing potion decanting 2023-05-04 11:41:10 +00:00
John Liebentritt
a9a6c07c1a Fixed a regression in the Witch's House where the fountain could not be searched after reading the book 2023-05-02 02:08:57 +00:00
szumaster
b43d84295c Corrected examine texts for some raw fish/meats 2023-04-27 10:50:25 +00:00
szumaster
1f38c8fc8c Added missing animation to mountain trolls 2023-04-25 14:36:58 +00:00
RiL
05da44aa52 Optimised, fixed and refactored container (bank/inventory/equipment) checks 2023-04-25 14:21:00 +00:00
Ceikry
0af42c77c8 Demoted logging of long pathfinding attempts to "fine"
Actually abort pathfinding excessively long paths
2023-04-24 16:20:38 +00:00
Ryan
068b252db6 Moved to release version of kotlin 1.8.20 2023-04-24 15:34:22 +00:00
szumaster
35d3b371d2 Added missing dialogue and facial expressions to Gertrude's Cat quest 2023-04-24 15:21:27 +00:00
szumaster
f9fb929b45 Improved Al Kharid dialogues
AliTheFarmer now spawns
AliTheGuard now spawns
Improved chicken farm spawns
2023-04-24 15:08:35 +00:00
szumaster
0fe5de8206 Implemented Varrock diary task for GE shortcut
Implemented Varrock diary task for pickpocketing a guard
Implemented Varrock diary task for browsing Oziach's store
2023-04-24 14:49:58 +00:00
Oven Bread
323c653275 Implemented a generic book interface
Converted all books to new book interface
Converted stats command to use the new book interface
2023-04-24 14:32:52 +00:00
Ceikry
4b20cdd001 Refactored components of the ScriptAPI to more efficiently utilize pathfinding
Implemented a global limit on pathfinding distance (server.max_pathfind_dist)
Pathfinding limit is enforced at the packet level as well as elsewhere (ContentAPI, etc)
2023-04-24 14:16:59 +00:00
xmomoz
5aded2b349 Can no longer sell to full general store 2023-04-23 08:51:44 +00:00
szumaster
24ff23b148 Implemented many medium and hard Fremennik diary tasks
Added catch messages for pitfall trap
Added Fremmenik milk bucket spawn
Implemented sea boots effect when recharging lyre
2023-04-23 08:26:59 +00:00
Ceikry
99425f0991 Reworked skill-based random event logic 2023-04-22 13:37:59 +00:00
Ceikry
9619f5b3a7 Improved pathfinding to stationary targets to not unnecessarily recalculate the path
Fixed an issue where end-of-movement was not being considered properly
Added admin command for drawing chunk boundaries ::drawchunks
Added admin command for drawing region boundaries ::drawregions
Added admin command for drawing the current route ::drawroute
Fixed impling IndexOutOfBoundsException
2023-04-21 16:19:23 +00:00
szumaster
f92fde2800 Improved authenticity of dialogue on tutorial island 2023-04-20 12:41:06 +00:00
Ceikry
f6096e3020 Rewrote impling system
Fixed static impling spawns
Fixed impling spawn ratio
Reworked Puro-Puro, much more authentic
Imp defenders now work properly
Crop circles now appear
Added admin command ::implings to list active implings (excludes implings from Puro-Puro)
Fixed bug where you could add to a finished compost bin
2023-04-20 12:16:21 +00:00
RiL
41c970efd4 Authenticity improvement for cooking burn rates 2023-04-20 01:57:18 +00:00
Ceikry
1323684153 Fixed The Grand Tree quest black demon boss respawning 2023-04-19 13:54:01 +00:00
xmomoz
642d946c17 Fixed Inferno Adze not awarding xp 2023-04-19 08:44:40 +00:00
Ceikry
d4565fd728 Added back the missing success message when fishing 2023-04-19 00:44:15 +00:00
szumaster
75d99e17f0 Fixed Karamja diary task for mining red topaz 2023-04-18 14:58:11 +00:00
Ceikry
cb92ad0577 Unified dragonfire protection logic
Fixed KBD's attack range resulting in only certain spots allowing him to melee
2023-04-18 08:44:03 +00:00
szumaster
4ded3b90de Replaced the lock interface for Tribal Totem quest with the correct/authentic one 2023-04-18 08:17:08 +00:00
RiL
957540c362 Implemented all Fist of Guthix glove effects
Fixed inaccurate salve amulets boost, bonus for enchanted version now implemented
Fixed inaccurate black/slayer mask + slayer cape interaction, now always gives the highest bonus when wearing mask + cape
2023-04-17 00:59:54 +00:00
Avi Weinstock
2025949265 Fixed excessive tick delay for drinks 2023-04-15 05:35:02 +00:00
Ceikry
7a4fdfb410 Fixed bouncer cutscene getting stuck in Fight Arena 2023-04-14 03:18:11 +00:00
downthecrop
fed72384ba Implemented The Grand Tree quest 2023-04-14 01:27:54 +00:00
Dan Ginovker
034cc75a61 Started implementing Castle Wars (not ready to enable yet) 2023-04-10 07:13:54 +00:00
RiL
dd3c957f8b Fixed hardleather crafting typo 2023-04-09 16:12:43 +00:00
RiL
fc28c97400 Added ge_announcement_limit configuration for setting minimum high alchemy value required for bot GE items to be announced 2023-04-02 08:41:43 +00:00
RiL
dcdeefe85e Implemented interaction for magic secateurs on trees 2023-04-02 08:28:27 +00:00
Ceikry
c0ffe59d47 Fixed live console spam caused by ResetInterface not being listed as a valid outgoing packet 2023-04-01 05:16:06 +00:00
bushtail
af99895168 Refactored some fishing code
Converted some fishing code to kotlin
Implemented crayfish fishing
2023-04-01 04:57:58 +00:00
Ceikry
2273550fea Rewrote and unified potion decanting, fixes decanting bugs
Replaced Zahur's and Bob Barter's methods of decanting
2023-04-01 02:33:38 +00:00
Oven Bread
d4af3421ba Merge the only two toys in DiangoItems into toy listeners
Fixed spinning plate animation
2023-03-31 14:19:58 +00:00
Ceikry
d431fec1ed Fixed bug relating to tracking current slayer task 2023-03-31 00:04:59 +00:00
Ceikry
ebebb05af3 Improved Miscellania and Etceteria tree handling 2023-03-30 23:39:01 +00:00
Ceikry
8d0493bf9d Converted bat bone drop handler to a listener, fixes Merlin's Crystal 2023-03-30 23:02:02 +00:00
Ceikry
b1ed4461af Fixed incorrect teleporting to house portal on logout
House now kicks guests when owner leaves
More aggressively unload old house regions (experiment)
Added DEBUG log type (currently unused, but shows up in cyan when used and the world is in development mode)
2023-03-30 22:39:42 +00:00
Oven Bread
757b13544a Stroking/petting kittens is now fully animated 2023-03-30 22:18:43 +00:00
Ceikry
91ec97220b Addressed some exploitable hunter and herblore issues
Temporarily disabled puro puro, grenwalls pending fixes
2023-03-29 23:19:38 +00:00
Oven Bread
9f85619334 Converted CasketPlugin to CasketListener 2023-03-28 13:42:10 +00:00
Ryan
374ad2f2e5 Implemented unit testing in gitlab CI/CD pipeline
Contributors: If you run unit tests locally, you will need to import Server/db_exports/testuser.sql to set up the unit test user in your local database server (or change the credentials used for unit testing in Server/src/test/resources/test.conf)
2023-03-27 09:19:49 +00:00
Kennynes
a52af89cad Added animations to Falador guards 2023-03-26 14:22:18 +00:00
Avi Weinstock
b9050c0e3c Implemented A* pathfinding for SmartPathfinder 2023-03-26 03:59:07 +00:00
RiL
ffb7486a01 Implemented a loot message for the reward from Fishing trawler
Optimised junk item removal from Fishing trawler loot
2023-03-26 03:52:13 +00:00
Manapart
3c2b852473 Added admin command to change appearance 2023-03-26 03:25:33 +00:00
RiL
a9214486cf Fixed retrieving last fruit/produce from basket/sack 2023-03-26 03:11:22 +00:00
Sam
76f128343e Added tablet functionality for lv6 enchanting (onyx)
Fixed enchant tablets consuming the whole stack each use
2023-03-26 03:03:48 +00:00
RiL
c342baa138 Fixod Zaff selling no battlestaffs when having no Varrock dairies done 2023-03-25 15:42:33 +00:00
Zerken
353bbbd61a Lumbridge immersion update
Added sound to shearing sheep
Added sound to failing to shear the penguin sheep
Added sound to picking up field items (wheat, potato, etc.)
Added 3 missing chicken(1017) spawns to farmer freds farm
Removed 1 incorrect chicken(41) spawn from farmer freds farm
Added 1 missing sheep(43) spawns at farmer freds farm
Added 2 missing sheep(1765) spawns at farmer freds farm
Added 2 missing sheep(5156) spawns at farmer freds farm
Added 2 missing sheep(5157) spawns at farmer freds farm
Added 2 missing sheep(5160) spawns at farmer freds farm
Added 1 missing ram(3673) spawn at farmer freds farm
Added all combat sounds to ram(5168,3673)
Added 1 missing mugger(175) spawn behind lumbridge by logs
Added all combat sounds to mugger(175)
Added 2 missing sheep(42) spawns behind lumbridge by logs
Removed 6 incorrect giant rat(86) spawns at southwest corner of lumbridge castle
Added 2 giant rat (86) spawns at southwest corner of lumbridge castle
Added 1 giant rat (4942) spawn at southwest corner of lumbridge castle
Added 10 missing rat(47) spawn at southwest corner of lumbridge castle
Removed 24 incorrect goblin spawn(all 3267,3264) between lumbridge and draynor
Added 3 goblin(2278) spawn between lumbridge and draynor to east section
Added 1 goblin(1772) spawn between lumbridge and draynor to east section
Added 1 goblin(1770) spawn between lumbridge and draynor to east section
Added 2 goblin(1771) spawn between lumbridge and draynor to east section
Added 3 goblin(2279) spawn between lumbridge and draynor to east section
Added 2 goblin(2281) spawn between lumbridge and draynor to east section
Added 1 goblin(2278) spawn between lumbridge and draynor to west section
Added 1 goblin(1772) spawn between lumbridge and draynor to west section
Added 1 goblin(1770) spawn between lumbridge and draynor to west section
Added 1 goblin(1771) spawn between lumbridge and draynor to west section
Added 1 goblin(2279) spawn between lumbridge and draynor to west section
Added 1 goblin(2280) spawn between lumbridge and draynor to west section
Added 2 goblin(2279) spawn between lumbridge and draynor to north section
Added 1 goblin(1770) spawn between lumbridge and draynor to north section
Added 1 goblin(1771) spawn between lumbridge and draynor to north section
Added 1 goblin(2278) spawn between lumbridge and draynor to north section
Removed 2 incorrect giant spider(59) spawns at ham trapdoor
Added 5 giant spider(59) spawn at ham trapdoor
Removed 3 incorrect giant spider(59) spawns around well
Added 3 giant spider(59) spawn at well
Removed 1 incorrect spider(59) at giant rats spawn near lumbridge by logs
Added 1 missing giant spider(59)spawn next to tree patch
2023-03-25 15:24:57 +00:00
Zerken
27661f711f Fixed standard spell book sounds
Fixed spell hit and miss sounds not working
Changed several existing spell sounds to use constlib
Corrected confuse cast sound and added hit sound
Corrected weaken cast sound and added hit sound
Corrected curse cast sound and added hit sound
Corrected vulnerability cast sound and added hit sound
Corrected enfeeble cast sound and added hit sound
Corrected stun cast sound and added hit sound
Corrected crumble undead hit sound
Added bind hit sound
Corrected snare cast sound and added hit sound
Corrected entangle cast sound and added hit sound
Added sound for enchanting crossbow bolts
Added saradomin strike hit and miss sounds
Added claws of guthix hit and miss sounds
Added flames of zamorak hit and miss sounds
Fixed teleother sound
Added ibans blast cast and hit sound
Corrected superheat ore sound
2023-03-25 15:12:14 +00:00
RiL
0cb814d26e Fixed animation for harvesting willow branches 2023-03-21 04:13:08 +00:00
Ceikry
7ec901297b Fixed some error spam about a nullref in animateWoodcutting
Fixed a general script processing oversight that could cause error-throwing scripts to continue executing
Scripts being processed now automatically cancel if the interaction-target-node is no longer active (fixes object could not be replaced spam)
Fixed the stopExecuting() spam
Fixed a CME in the disconnection queue (only affected server shutdown)
Future-proofed the ground spawn parser to work with the format Zaros now outputs
Added in proper SKILLING global clock for use with the script system - addresses some quirks and brings us closer to authenticity
2023-03-21 03:50:27 +00:00
Skal Fate
48805eea66 Improved Varrock sword shop NPC movement 2023-03-21 03:13:49 +00:00
Sam
ed708b5fb8 Added handling for full inventory on silverware stage of Lost Tribe quest 2023-03-21 02:58:24 +00:00
Ryan
d9245b8aee Added gitlab rule for running pipelines in MRs 2023-03-21 02:46:59 +00:00
Sam
459b360897 Fixed regression causing Highwayman to drop unusable coins 2023-03-16 03:59:23 +00:00
Sam
ab2842af14 Fixed bug blocking entry to Black Knights' Fortress 2023-03-16 03:45:06 +00:00
Ceikry
8b62e42323 Fixed a bug that prevented progression in tutorial island
Fixed a bug that caused woodcutting to take slightly longer
Fixed a bug that caused the woodcutting axe message to print more often than it should
Fixed a bug that caused fishing to not print its fishing attempt message
Fixed a bug that caused fishing to take slightly longer
Fixed a bug that would cause nechryaels to lose interest in the player when their minions attacked
Made sure the grand exchange tests always clean up the GEDB
2023-03-16 03:27:30 +00:00
Sam
c3cfecb5fa Fixed some NPCs dropping unstackable broad arrows 2023-03-09 15:35:13 +00:00
Zerken
55c619bf87 Significant Stronghold of Security immersion improvements
Added the command ::jingle to play music jingles by id
2023-03-08 03:28:10 +00:00
Ceikry
ff18f69dd0 Fixed a bug that was causing players to get stuck logged in
Fixed a bug that would cause players to get stuck in a client crash loop when logging out inside of a POH
Fixed a bug that let players reach objects that shouldn't be reachable
General disconnection reliability improvements
Adjusted the color of global chat for HD mode, the new color is #f1b04c
2023-03-05 11:00:06 +00:00
Ceikry
c2cb359bf7 Fixed a null reference exception due to misuse of combat callbacks to update interfaces 2023-03-03 12:54:45 +00:00
Sam
e03187920b Fixed random variation on tablet teleport to house
Corrected drop table for hero
Rewrote tablet teleports in kotlin as listener
Added new ::runekit admin command, which gives 1k of each Rune type to make testing easier
2023-03-03 02:32:46 +00:00
Avi Weinstock
eeedafe637 Improved accuracy of player wealth calculation 2023-03-03 02:15:52 +00:00
Sam
f1e2083506 Converted Seamen plugin to listener 2023-03-03 01:28:04 +00:00
Ceikry
b6fa73d94c Disconnecting while dying no longer results in improper death handling in safe zones (e.g. fight caves) 2023-03-03 01:13:38 +00:00
ryannathans
0546d7e8b9 Made pipelines even faster with slim version of maven docker image 2023-03-02 13:47:11 +00:00
Skal Fate
d91f569aff Another round of dialogue fixes
Fixed grammatical errors with: Duke of Lumbridge, Falador Squire, poison salesman, slayer masters, Varrock East bartender, mage of Zamorack, Sedridor, trader Stan, Varrock information clerk
Fixed animation for Varrock East bartender
Fixed some stuck dialogues
2023-03-02 13:46:44 +00:00
Ryan
17d1a9619c Moved jq installation to run on json verification gitlab pipeline only 2023-03-02 13:35:47 +00:00
Skal Fate
72204740df Black Knights' Fortress Bug Fixes
Fixed facial expressions for Sir Amik, listen scene characters, fortress guard
Fixed door needing uniform from inside to leave
Big door now opens from the inside
2023-03-02 13:22:23 +00:00
Kennynes
745f8b63b0 Implemented drop table for Entrana zombies, thus now finally giving them the correct bronze axe drop rate 2023-03-02 13:07:27 +00:00
Ceikry
97f4fa91ca Added support to fire off a discord alert to a webhook (set in server config as server.openrsc_integration_webhook) when Wormbrain's map piece is collected so that rsc plate pures are possible 2023-03-02 12:53:12 +00:00
szumaster
35e1477c24 Fight Arena Bug Fixes
Fixed HD related issues during hengrad cutscene
Fixed dialogue after entering the hengrad cell
Fixed doors that were not visually open when opened by the bouncer in the cutscene
Refactored guard dialogue
Fixed some exceptions
2023-03-02 12:42:29 +00:00
Logg
c42daa5dba Fixed sequence rune pouches are dropped in 2023-03-02 12:26:19 +00:00
Ceikry
214ba50ecc Implemented support for overriding daily account limits via new config file Server/data/configs/account_limit_exceptions.conf (this file is hot reloaded automatically upon modification) 2023-03-02 12:14:28 +00:00
Skal Fate
64a12fe5c8 Even more NPC dialogue fixes
Dialogue animations fixed for Doric's Quest Omglewip in Wizards' Tower
Sawmill operator options handler is now kotlin listener, fixes unreachable bug
Mining guild entrance dwarf grammar fixed
Farsight seer expression and grammar fixed
Zeke of Al Kharid grammar fixed
Chompy bird grammar fixed
Prince Ali grammar fixed
Minecart driver grammar fixed
Reldo from Lost Tribe now ends dialogue correctly when talking about the book
2023-03-01 08:58:12 +00:00
Skal Fate
276cb0f7c6 Corrected facial expressions and dialogue for many NPCs
Lumbridge: Explorer Jack grammar errors, fishing tutor expressions, prayer tutor expressions
Falador: Makeover mage expressions, castle squire dialogue error, Rising Sun bartenders expressions
Varrock: Thessalia expressions, head chef expressions
Taverly: Kaquemeex and Sanfew expressions
Port Sarim: Thaki The Dwarf dialogue was sending a bad player expression causing it to break animation, bartender expressions, Klarence expressions
Rimmington: Hetty expressions
Karmaja: Luthas expressions and dialogue added, fixed Man character speaking the player's dialogue
Brimhaven: Bartender expressions, Davon the amulet seller expressions
2023-03-01 08:46:34 +00:00
bushtail
9020d1e474 Rewrote hunter kit spell in kotlin 2023-03-01 08:35:00 +00:00
Zerken
bcb2a9386d Fixed crafting level requirements and xp reward for studded body 2023-03-01 08:22:47 +00:00
Skal Fate
adcdf9bd6a Can now speak to Wormbrain through the jail cell
Fixed some Wormbrain typos
2023-03-01 08:12:48 +00:00
Ceikry
88a2f354b4 Added support for varying log levels configurable in the server config (see log_level in default.conf)
Error logs now properly print to stderr when possible
Colour-coded logs
Addressed a scenario in which outgoing packet writes could get hung up
Fixed interface incorrect definition message on server startup
2023-03-01 08:01:14 +00:00
Avi Weinstock
e1faa64af7 God spells now properly drain stats
Charge spell no longer null-dereferences when attempting to refresh it
Manually casting spells no longer changes attack style
2023-03-01 07:48:31 +00:00
Zerken
6d182a5984 Wrapped oomlie now have the correct burn chance and experience reward 2023-03-01 07:35:33 +00:00
Ceikry
8202d44051 Fixed master crafter's dialogue not opening 2023-03-01 07:23:17 +00:00
Ceikry
9a4b933976 Implemented ContentInterface-based NPC Scripting
Obsoleted AbstractNPC
Implemented desert bandits
Rewrote a handful of existing NPCs into NPCBehaviors (e.g. rock slugs, nechryaels, water fiend and more)
2023-03-01 06:42:25 +00:00
Zerken
f0d7b82bf9 Added the HAM robe set and monk's robes to the allowed items for Entrana 2023-03-01 03:37:20 +00:00
Ceikry
a5f94d736a Fixed incorrect xp calculation that would occur in some circumstances when training magic 2023-03-01 03:24:17 +00:00
Zerken
81321e44e1 Added missing sounds to agility pyramid 2023-03-01 02:45:09 +00:00
Kennynes
716fcb7209 Implemented crocodile drop tables 2023-03-01 01:01:58 +00:00
Skal Fate
09f553d998 Varrock Museum Curator Haig Hele no longer gets stuck in endless "please waiting"
Achievement diary no longer gets completed on every repeated interaction with the Varrock Museum Curator
Grammar fixes for shield of arrav quest
2023-03-01 00:42:17 +00:00
Skal Fate
f00fd246b9 Leela in Prince Ali Rescue no longer provides duplicate keys
Misc. dialogue fixes for Prince Ali Rescue
2023-03-01 00:30:29 +00:00
Skal Fate
35a97946ac Fixed bug where feathers could be used to fletch wood 2023-03-01 00:15:36 +00:00
Ceikry
3445b792c8 Implemented Global Chat
Added global chat feature, so players can still maintain global communication while being in their own clan chat
An individual player can opt out of global chat by using the ::muteglobal command
Implemented automatic message splitting for clan and global chat
Implemented colour selection for global chat (prefix your message with hex colour code, e.g. //%690420 before the message)
2023-03-01 00:02:12 +00:00
Ceikry
124eeab893 Implement Authentic Interaction Subsystem
Implemented authentic script/interaction queues
This does now mean we have a total of 3 interaction systems, but this additional system is necessary to fix certain categories of bug and implement some authentic features
Converted mining to new system
Converted fishing to new system
Converted woodcutting to new system
Provided an example of soft-queued scripts with GrandTreePodListener
Implemented tick-eating (it is now possible to eat a shark, drink a potion, and eat a karambwan all on the same tick)
Can now eat and drop items while stunned
2023-02-28 23:41:14 +00:00
Ceikry
5206c99151 Improved handling of chat message packets
More improvements and fixes relating to dynamic regions and constructions
2023-02-28 23:04:52 +00:00
bushtail
dcaa980822 Rewrote PrayerEffect into kotlin
Corrected calculation used for prayer restoring effects
2023-02-22 08:25:16 +00:00
Skal Fate
50a9580505 Fixed the dragonfire shield recharge animation to only play when it needs charging 2023-02-22 08:13:49 +00:00
Skal Fate
06632a6918 Elvarg improvements
Elvarg fight is now authentic
Max hit up to 60 w/o shield, with anti-dragonfire shield up to 12, and max combat damage based on defense level
Separated potion and shield effects to not stack
Fixed quest log typo
Fixed dragon-fire message to show correct text based on the player's protection
2023-02-22 07:59:27 +00:00
Zerken
f9dbfe9a77 Implemented blast furnace sink fill-bucket option 2023-02-22 07:45:40 +00:00
Swizey
4d652e7f02 Cooking on a fire that burns out will now stop any active cooking actions 2023-02-22 04:38:43 +00:00
Ceikry
cc2e5f8775 Bump compiler to Kotlin 1.8.20-Beta to fix incremental build 2023-02-22 03:52:21 +00:00
Kennynes
aa0632d274 Reimplemented Bogrog summoning shop 2023-02-21 07:23:34 +00:00
Sam
e8522b1e62 Cleaned up summoning scroll code
Fixed thieving fingers scroll level requirements (level 167 -> 47)
2023-02-21 07:12:03 +00:00
Kennynes
7ade40ace2 Implemented Oomlie drop table 2023-02-21 07:00:54 +00:00
Sam
73cbc9f11e Removed inauthentic vial smash after completing bar crawl miniquest (this is an osrs-only feature) 2023-02-21 06:49:02 +00:00
Sam
6c9458cdac Fixed a bug causing runecrafting animations to play twice 2023-02-21 06:38:34 +00:00
Sam
0fa8a1c87e Converted plugin for making gem tipped bolt tips and bolts to listener 2023-02-21 06:25:56 +00:00
Swizey
a88fde30ed Converted abyssal titan to kotlin
Abyssal titan is now a beast of burden
Fixed issue with abyssal titan that could result in lost essence when bank is full
2023-02-21 01:57:11 +00:00
Ceikry
675d576c58 Updated kotlin to 1.8.0
Updated kotlin target to java 11
Fixed build errors when targeting 1.8.0
2023-02-18 09:18:24 +00:00
Ceikry
86405d89f4 Fixed blast furnace crashing the entire server when using "take all"
Fixed blast furnace bar duplication when using "take all"
2023-02-18 07:04:59 +00:00
Skal Fate
4ee6f3f752 Port Phasmatys ghosts now UwU when spoken to without ghostspeak amulet 2023-02-18 04:02:59 +00:00
Skal Fate
7600ac8b49 Enchanting tiaras no longer removes incorrect items from the player's inventory
Talisman type is now checked correctly when enchanting tiaras
2023-02-18 03:52:20 +00:00
Ryan
8bad573568 Increased memory limit to 3G for java heap on gitlab pipeline builds 2023-02-18 03:41:19 +00:00
Ryan
c4ef6401a4 Pipelines now print their memory breakdown before builds 2023-02-18 03:27:22 +00:00
bushtail
7a42de63dc Players can now cut down jungle bushes while wielding a machete
Added inEquipmentOrInventory function to content API
2023-02-18 02:36:12 +00:00
Kennynes
4f600b2a59 Fixed an issue where wizards would drop two bones 2023-02-18 02:21:25 +00:00
Sam
097615cc7d Corrected NPC stats for some trolls 2023-02-18 01:55:20 +00:00
Ceikry
cecd6f1947 Fixed many non-critical exceptions
Fixed an issue that could result in server hang
Added a new command ::npcsearch for searching for NPC IDs
2023-02-18 01:37:30 +00:00
Ceikry
d75e40b98c Doubled max memory allocation for compiler to 2GB to fix heap allocation exceptions during build 2023-02-18 01:17:33 +00:00
Ceikry
17db0f27ef Simultaneous logins now possible on servers using in-memory account storage 2023-02-17 04:51:14 +00:00
Skal Fate
52b8100c09 Priest in Peril fixes
Journal entry now shows 50 rune essence
Fixed grammar errors
2023-02-17 03:20:57 +00:00
Kennynes
e016d55630 Added drop table for jail guards in Draynor 2023-02-17 02:35:36 +00:00
bushtail
254089d34e Rewrote fruit cutting plugin as listener 2023-02-17 02:12:41 +00:00
bushtail
7f6752ba8a Mr. Bones' Wild Ride admin command now accepts a player name argument 2023-02-17 00:12:56 +00:00
John Liebentritt
6b90e17f1c Impling changes
Young impling puro xp 25 -> 20
Magpie impling world xp 46 -> 216
Ninja impling world xp 52 -> 240
Magpie impling unstrung diamond amulet -> strung diamond amulet
Dragon impling unstrung dragonstone amulet -> strung dragonstone amulet
Dragon impling baby dragon bones weight 1-25 -> 100-300
Dragon impling dragon bones weight 1-25 -> 50-100
2023-02-16 23:09:11 +00:00
Swizey
34f8db2557 Implemented authentic dragon axe special attack and enabled it by default, osrs style is toggle via worldprop world config dragon_axe_use_osrs_spec = true 2023-02-16 22:47:18 +00:00
Skal Fate
f243293e8c Fixed construction issue relating to incorrect isloaded checks causing null scenery
Fixed construction issue relating to houseregionid getting registered for dunegon id
Fixed construction issue relating to teleports in houses
2023-02-16 22:16:46 +00:00
Swizey
79696dfdde Overhauled the Lumbridge jobs system to be more authentic
Added new class of job - bone burying
Made the Task List item functional
Overhauled the dialogues of all of the applicable employers to be more authentic to 2009
Players must now return to the employer who gave them the job to turn it in
Added development command ::clearjob to clear the player's current job
2023-02-14 05:30:03 +00:00
bushtail
0d127b109a Re-enabled access to blast furnace 2023-02-13 02:41:21 +00:00
bushtail
d608f9aeb6 Converted lunar spellbook energy transfer to kotlin 2023-02-13 01:50:26 +00:00
Swizey
5962459ca1 Added attack sounds for bronze to dragon axes 2023-02-13 01:23:55 +00:00
Sam
0ee77026ba Cats can now be fed cooked fish 2023-02-12 01:40:29 +00:00
Ceikry
39251fc75f Implemented blast furnace ore shop 2023-02-12 01:08:34 +00:00
bushtail
69f950eb57 Blast furnace code refactored 2023-02-11 12:36:36 +00:00
Sam
0236874a2e Random event teleport now stops player's action 2023-02-10 05:48:48 +00:00
szumaster
c85400b3e2 Removed random chicken near tutorial island
Swapped ogre NPCs near glider at Feldip Hills
Chaos temple now has the authentic number and variety of monks
Removed NPCs spawning in the void
Adding missing zogre and skogre config, including adding to the respective slayer task
Added missing crozier config
Added training sword sound effects
2023-02-10 00:36:57 +00:00
itsmedoggo
e091a45931 Fixed Lumbridge milling achievement 2023-02-09 23:34:41 +00:00
Ceikry
e5336f4438 Removed old degrading system for crystal bows 2023-02-09 23:30:33 +00:00
Ceikry
4971985d44 Fixed lag caused by repetitive region parsing from bot activity 2023-02-09 23:02:45 +00:00
Ceikry
8dadaa5089 Fixed a concurrent modification exception in event dispatch 2023-02-09 06:55:01 +00:00
Skal Fate
97c7e7e3d4 Shopkeepers across Gielinor now have correct facial expressions, areas with improvements include Lumbrdige, Varrock, Draynor, Falador, Edgeville, Al-Kharid, Ardougne, Catherby and Mortaniya
Fixed typos in the dialogues of various shopkeepers
Individualized Varrock, Lumbridge, and Port Phastmys General Store to their own file
Marked Fairy Shopkeeper as a shopkeeper so players can interact with her too (previously only the assistant was working)
2023-02-08 03:24:19 +00:00
Sam
7646bbaccd Deleted disabled interaction related to unimplemented minigame 2023-02-08 02:52:04 +00:00
Skal Fate
e1fa33b4dd Fixed Varrock sword shop shopkeeper and his assistant not being able to speak
Catherby's Vannessa no longer double prompts players about what they want to buy
Varrock sword shop staff and Catherby's Vannessa now have correct facial expressions
2023-02-04 09:14:47 +00:00
szumaster
9fc92f52f4 Implemented Fight Arena quest 2023-02-04 08:54:59 +00:00
Swizey
c112794ede Updated Ancient and Lunar home teleports to use the correct animation 2023-02-04 08:12:10 +00:00
Sam
710671eb99 Fixed highwaymen dropping noted bones 2023-02-03 15:48:09 +00:00
Sam
df345d782f Fixed bug preventing tipping/finishing of crossbow bolts with full inventory 2023-02-03 15:30:29 +00:00
Swizey
406552fae4 Falador medium achievement diary task for lighting bullseye lantern can now be obtained 2023-02-03 13:54:52 +00:00
Swizey
c54f03d8cc West Ardougne anvils now work 2023-02-03 12:25:33 +00:00
John Liebentritt
798c357291 Fixed a regression where high and low alchemy spells no longer played any sound effect 2023-02-03 12:04:27 +00:00
Sam
05b414fdf6 Disabled interaction related to unimplemented minigame that was causing crashes 2023-02-03 11:52:05 +00:00
Ceikry
3940f3bd47 Fixed bug causing penguins to not load 2023-02-03 11:39:20 +00:00
Ceikry
cc1eca5237 Improved packet writing, should improve responsiveness when many players are online 2023-01-30 23:21:37 +00:00
Swizey
e8c22249a2 Added combat sound effects to battleaxes
Corrected crush animation for a few battleaxes
2023-01-30 22:50:37 +00:00
ceikry
4008f78433 Fixed some issues that lead to indefinite shutdown times 2023-01-30 03:50:23 +00:00
kuanoni
1a1da2b71b Fixed autocast turning off after equipment swap 2023-01-30 02:35:24 +00:00
2449 changed files with 176125 additions and 174113 deletions

1
.gitignore vendored
View file

@ -31,3 +31,4 @@ gradle
**/*.swo
build/kotlin/sessions/
**/*.iml
Server/hasRan.txt

View file

@ -1,16 +1,20 @@
variables:
# This will suppress any download for dependencies and plugins or upload messages which would clutter the console log.
# `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true -Xmx1024m"
MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true -Xmx3g"
# As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used
# when running from the command line.
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-fast --show-version"
# This template uses jdk8 for verifying and deploying images
image: maven:3-openjdk-11
image: maven:3-openjdk-11-slim
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
before_script:
- apt-get update -qq && apt-get install -qq -y --no-install-recommends jq
- 'free -mh'
- 'apt-get update -q'
# Cache downloaded dependencies and plugins between builds.
# To keep cache across branches add 'key: "$CI_JOB_NAME"'
@ -22,7 +26,7 @@ verify:jdk11:
stage: build
script:
- 'cd Server'
- 'mvn $MAVEN_CLI_OPTS verify -DskipTests'
- 'mvn $MAVEN_CLI_OPTS verify'
except:
variables:
- $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
@ -30,6 +34,7 @@ verify:jdk11:
test:json:
stage: test
script:
- 'apt-get install -q -y --no-install-recommends jq'
- 'find . -name \*.json -type f -print0 | xargs -0 -n1 -P8 jq empty'
except:
variables:

20
Dockerfile Normal file
View file

@ -0,0 +1,20 @@
# Starting out with the openjdk-11-slim image
FROM maven:3-openjdk-11-slim
# Set working directory to /app
WORKDIR /app
# Update apt; install git and git-lfs
RUN apt-get update && apt-get -qq -y install git git-lfs
# Clone the 2009scape repository
RUN git clone --depth=1 https://gitlab.com/2009scape/2009scape.git
# Fake it til you make it - let's go home
WORKDIR /app/2009scape
# Make sure ./run has permissions
RUN chmod +x run
# Run it
CMD ["./run"]

View file

@ -72,7 +72,7 @@ There are many ways everyone can contribute! From the most seasoned programmers
* **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/rs09-thanos-tool/-/jobs/artifacts/master/raw/build/libs/thanostool.jar?job=build).
* **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).
@ -131,7 +131,7 @@ We use the AGPL 3.0 license, which can be found [here](https://www.gnu.org/licen
### 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 in the Discord.**
**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
@ -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
View file

@ -2,6 +2,7 @@ bin/**
out/**
data/logs/**
data/profile/**
data/playerstats/**
.idea/**
/bin
.DS_Store**

View file

@ -22,8 +22,10 @@
<ObjectAction mode="add" id="39242" x="2955" y="3273" z="0" direction="w"/>
<ObjectAction mode="add" id="39241" x="2955" y="3274" z="0" />
<ObjectAction mode="add" id="20987" x="2821" y="2996" z="0" direction="s"/>
<ObjectAction mode="add" id="9472" x="3353" y="3951" z="0" direction="s"/>
<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>

View file

@ -13,7 +13,7 @@
"This is my own dialogue",
"@name run.",
"@name you cant hide from me.",
"jajajajajaja",
"Jajajajajaja",
"How do i get to Varrock @name?",
"How do i get to Camelot @name?",
"How do i get to Taverly @name?",
@ -21,17 +21,17 @@
"How do i get to Yanille @name?",
"How do i get to Catherby @name?",
"Gotta go srry.",
"wiggle wiggle wiggle yeah",
"Wiggle wiggle wiggle yeah",
"@name lookin goofy",
"@name lookin stoopid",
"@name lookin like a red bracket",
"@name get yo weasel lookin ass outta here",
"@name lookin like some sort of twocan sam",
" /hop world 1 got a noob here!",
"woot",
"Woot",
"Hows your day been @name?",
"heyy @name :)",
"gtg srry",
"Heyy @name :)",
"Gtg srry",
"I wont answer your questions @name",
"Stop asking questions @name",
"Roflmao",
@ -48,7 +48,7 @@
"Nice Armor @name!",
"Nice Weapon @name!",
"Venezuela #1",
"2009Scape and chill @name?",
"2009scape and chill @name?",
"@name is my girlfriend",
"Buying gf",
"Bank sale pm me for info",
@ -61,14 +61,14 @@
"Fuckin sit @name.",
"Error: Botting client broken tell Evilwaffles.",
"@name bots all the time",
"report @name",
"apparently @name bots",
"Report @name",
"Apparently @name bots",
"@name hates kermit",
"There are no mods on to help you",
"Report me, you wont",
"Yes, Im botting. And?",
"ERROR: BOTSCRIPT 404. REPORT TO BOT OWNER (Evilwaffles)",
"flash2:wave: FUCK",
"Flash2:wave: FUCK",
"I love 2009Scape!",
"Ja Ja Ja Ja",
"This is fun!",
@ -105,9 +105,9 @@
"Trade me @name",
"LOL",
"How do I get to lumbrich",
"bruh",
"poggers",
"shitpost",
"Bruh",
"Poggers",
"Shitpost",
"I wish i could find an RS Gf",
"Where do you find runite ore @name?",
"Where is the best coal location @name?",
@ -135,41 +135,39 @@
"Im not a bot",
"Nah Im a real person",
"Bruh are you even a real person lol?",
"e",
"E",
"Hellooooo @name",
"wc lvl @name?",
"fletching level @name?",
"firemaking level @name?",
"Wc lvl @name?",
"Fletching level @name?",
"Firemaking level @name?",
"Have you seen the dude in the ge?",
"Wonderful weather today @name",
"Lowkey drunk af rn",
"I am so tired",
"Wassup @name",
"follow me @name!",
"Follow me @name!",
"Server goes brrrr",
"bruh i am not a bot",
"Bruh i am not a bot",
"I think @name is a bot",
"Are you a bot @name?",
"insert spiderman meme here",
"pot calling the kettle black etc",
"ooh, a piece of candy",
"Insert spiderman meme here",
"Pot calling the kettle black etc",
"Ooh, a piece of candy",
"I love woodcutting",
"Im going to go level up later",
"I love mining shooting stars",
" /this @name looks dumb",
"AAAAAAAAAAAAAAAAAAAAAAAAHHHHHH!!!",
"como estas @name",
"Summer = always the best community manaer",
"so how about that ceikry guy",
"so how about that kermit dude",
"woah is an abusive mod",
"Como estas @name",
"So how about that ceikry guy",
"So how about that kermit dude",
"Woah is an abusive mod",
"I heard Woah and Ceikry are dating now",
"House party in Yanille!",
"Can i have some gp @name?",
"Where do i find partyhats?",
"Why do mobs drop boxes?",
"What exp rate do you play on @name?",
"Have you met Summer?",
"Hey @name",
"Hey @name",
"Hey @name",
@ -190,33 +188,33 @@
"NobodyCLP has big feet",
"Chicken tendies for dindin",
"Spicey Chicken tendies is litty as a mf titty",
"red bracket stinky",
"ra ra rasputin",
"lover of the russian queen",
"Red bracket stinky",
"Ra ra rasputin",
"Lover of the russian queen",
"Whens the next update coming out?",
"How many players are maxed?",
"I dont use discord @name",
"I dont use the CC @name",
"Why should i use discord?",
"2009Scape is life",
"brb gotta make dinner",
"Brb gotta make dinner",
"I need to go to the GE",
"@name can i have a ge tele?",
"lol @name shut up",
"Lol @name shut up",
"Where are teak trees?",
"How do i make planks @name?",
"Idk about that scraggley ass alex guy.",
"Rusty? More like Crusty af lmfao.",
"I need to sell some stuff on the ge",
"I have so many logs to sell lol",
"nah",
"yes",
"Nah",
"Yes",
"Where can i mine iron?",
"Where can i mine tin?",
"Where can i mine copper?",
"Where can i mine clay?",
"Where can i mine coal?",
"no",
"No",
"We are no strangers to love",
"You know the rules and so do I",
"A full commitment's what I'm thinking of",
@ -230,10 +228,10 @@
"Never gonna make you cry",
"Never gonna say goodbye",
"Never gonna tell a lie and hurt you",
"why",
"why",
"why",
"why",
"Why",
"Why",
"Why",
"Why",
"Why does it not show your messages in the chatbox?",
"Why do you not show up in chat?",
"Why do you not show up in chat @name?",
@ -241,7 +239,7 @@
"When did you start playing @name?",
"When did you start on this server @name?",
"When did you first get here @name?",
"russias greatest love machine",
"Russias greatest love machine",
"Never gonna run around and desert you",
"Two things are infinite, the universe & @names stupidity",
"If you tell the truth, you dont have to remember anything.",
@ -259,7 +257,7 @@
"What do you think @name?",
"How does that sound @name?",
"That sounds great @name.",
"Im learning English.",
"I'm learning English.",
"I don't understand.",
"Could you repeat that please @name?",
"Could you please talk slower @name?",
@ -283,26 +281,26 @@
"@name?",
"@name how long have you played",
"@name world 1 or world 2?",
"what is your main world @name?",
"What is your main world @name?",
"I prefer world 1 tbh",
"I prefer world 2 tbh",
"@name world 1 for life",
"@name fog bots when?",
"damn somalian pirates",
"bracket more like brrrrrr acket",
"why the racket bracket",
"Damn somalian pirates",
"Bracket more like brrrrrr acket",
"Why the racket bracket",
"Hi @name I am dad",
"@name likes dad jokes",
"ur nuts @name",
"lootshare go brr",
"partay with froggay",
"Ur nuts @name",
"Lootshare go brr",
"Partay with froggay",
"Know what else is lame? Not being able to play 2009scape right now",
"Can you even grind on osrs",
"i botted to 88 fishing",
"I botted to 88 fishing",
"Do not forget to vote in running polls!",
"Always check announcments",
"we thrivin",
"ship @name",
"We thrivin",
"Ship @name",
"Dont forget to vote 2009scape!",
"Kermit is too legit 2 quit",
"Out here on the range we are having fun",
@ -312,11 +310,11 @@
"I dont like him @name",
"I dont like it @name",
"Im an American.",
"ima go pickup my lady ting",
"that portuguese dude is something else",
"Ima go pickup my lady ting",
"That portuguese dude is something else",
"@name!! @name!!",
"bowdi boy",
"i love bowdi... sometimes",
"Bowdi boy",
"I love bowdi... sometimes",
"@name = @name",
"I'm bacon.. go on dad... say it",
"I'm going to leave.",
@ -340,7 +338,7 @@
"I couldn't agree more @name",
"It cost me a fortune @name",
"I am dog tired",
"Dont take it personally",
"Don't take it personally",
"We will be having a good time",
"Same as always @name",
"No problem",
@ -362,40 +360,23 @@
"530 gang for life",
"@name, have you read the rules?",
"@name, have you checked out the forums?",
"why are the leprechauns moving?",
"Why are the leprechauns moving?",
"I am beyond the point of no return!",
"Nothin' personnel, kid.",
"All your base are belong to us",
"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!",
@ -412,7 +393,7 @@
"Fluff",
"Bwuh",
"I'm literally just mothin' bro",
"Certified 2009scape classic.",
"Certified 2009Scape Classic.",
"Make sure to like, comment and subscribe @name it really helps",
"Real 2009scape hours!!! Murder that like if you up!!!!",
"W00t!",
@ -426,32 +407,32 @@
"Drip check",
"Uhuhuhuhuhuhuhuhu",
"Ahhhhhhhhhhhhhhhh",
"yall got any deez?",
"Yall got any deez?",
"Deez nuts",
"When she give you that yoinky sploinky",
"Sir, this is a 2009scape.",
"Sir, this is a 2009Scape.",
"Oh dear! You are dead!",
"Cor blimey, mate! What are ye doing in me pockets?",
"yeah i got funnies",
"read muv luv",
"Yeah i got funnies",
"Read muv luv",
"Why doesn't she love me bros?",
"@name is off the goop don't listen to the clown",
"do yall got laptops",
"cfunny play the alien warp sound effect",
"Do yall got laptops",
"Cfunny play the alien warp sound effect",
"Ware to all whom doom hither, where cope is all yet constant.",
"Who wants to come G W D?",
"How do I make money?",
"Ironmen stand alone together!",
"based",
"where is she",
"Based",
"Where is she",
"*S N I I I I I I I I I F F F F F F F F F F F*",
"Hey @name, who was in Paris?",
"Huh whuh?",
"who's lone?",
"who *is* he?",
"Who's lone?",
"Who *is* he?",
"Hi @name, I'm Dad!",
"anyone wanna play melty blood after I high alch these bows?",
"buru nyaaaa",
"Anyone wanna play melty blood after I high alch these bows?",
"Buru nyaaaa",
"Number 15, Taverley Dungeon Black Dragons.",
"House party at Rimmington! Host: @name!",
"Spending 200m! Trade me, no junk!",
@ -461,19 +442,19 @@
"Nice outfit @name, does it come in children's size 12?",
":)",
":D",
"die screaming",
"Die screaming",
"Only on Tuesdays",
"we stan 2009scape",
"We stan 2009scape",
"There is no spoon",
"Where's the cow level?",
"Join 2009scape Clan Chat!",
"Join 2009scape Cc!",
"Chop chop!",
"Runescape rox my sox!!!!!!1",
"2009Scape rox my sox!!!!!!1",
"Type ::scripts for all 99s",
"Help I just died to Evil Chicken and I lost my stuff!",
"Can you fight Bandos in this game?",
"one bad gloop",
"One bad gloop",
"@name is not cute or funny",
"You have committed crimes against Gielinor and her people. What say you?",
"Barrows trauma",
@ -488,7 +469,7 @@
"Praise Andrew Gower",
"Please help me I can't stop playing 2009scape",
"Are you ignoring me, @name?!",
"i agree with this rfc can we put it in the game please",
"I agree with this rfc can we put it in the game please",
"@name, we've been trying to reach you about your car's extended warranty",
"Trimming armour, 25k gp",
"Hey why does my furniture disappear?",
@ -498,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",
"Cant we get you on Mastermind, @name? Next contestant @name from Lumbridge. Special subject the bleedin obvious.",
"Oh, youre German! Im sorry, I thought there was something wrong with you.",
"Listen, dont mention the war! I mentioned it once, but I think I got away with it all right.",
"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!!!",
@ -523,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.",
@ -596,7 +1081,7 @@
"Rusty = the grinch, @name = santa",
"@name the red nose reindeer",
"Put one foot in front of the other",
"and soon you will be walking out the doooor",
"And soon you will be walking out the doooor",
"Elf on the shelf time",
"@name loves pinecones",
"I love the smell of pinecones",
@ -695,21 +1180,21 @@
"Woah got those roofies strapped",
"Why is my drink cloudy?",
"@name and woah be wrestlin",
"bekky want sum fuk?",
"Bekky want sum fuk?",
"Damn @name you got an ass",
"Is that a footlong in your pants or are you happy to see me?",
"@name so hot i gotta change my pants",
"@name is a sex god",
"bruh we hype today",
"dont be silly wrap the willy @name!",
"wrap it before you smack it @name",
"can i get a reeeeee @name?",
"valentines day is the best day",
"Bruh we hype today",
"Dont be silly wrap the willy @name!",
"Wrap it before you smack it @name",
"Can i get a reeeeee @name?",
"Valentines day is the best day",
"@name shut up before i smack you with my crusty sock",
"Valentines day, more like me and my hand day smh",
"If you think these quotes are wild just wait @name",
"All im saying is we have never seen @name and biden in the same room",
"red rocket, red rocket!",
"Red rocket, red rocket!",
"Woahs favourite game is red rocket",
"@name sexy af today",
"Happy Valentines day @name!!!",
@ -754,4 +1239,4 @@
"@name and i are going to look for the easter bunny!!",
"Hint for anyone who sees this you must dig above eagles peak"
]
}
}

File diff suppressed because it is too large Load diff

BIN
Server/data/cache/main_file_cache.dat2 (Stored with Git LFS) vendored

Binary file not shown.

BIN
Server/data/cache/main_file_cache.idx19 (Stored with Git LFS) vendored

Binary file not shown.

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

Binary file not shown.

View file

@ -0,0 +1,2 @@
[exceptions]
"127.0.0.1" = 5

View file

@ -389,31 +389,31 @@
{
"minAmount": 1,
"weight": "5",
"id": 10666,
"id": 7334,
"maxAmount": 1
},
{
"minAmount": 1,
"weight": "5",
"id": 10669,
"id": 7340,
"maxAmount": 1
},
{
"minAmount": 1,
"weight": "5",
"id": 10672,
"id": 7346,
"maxAmount": 1
},
{
"minAmount": 1,
"weight": "5",
"id": 10675,
"id": 7352,
"maxAmount": 1
},
{
"minAmount": 1,
"weight": "5",
"id": 10678,
"id": 7358,
"maxAmount": 1
},
{
@ -949,7 +949,7 @@
{
"minAmount": 1,
"weight": "5",
"id": 10667,
"id": 7336,
"maxAmount": 1
},
{
@ -961,7 +961,7 @@
{
"minAmount": 1,
"weight": "5",
"id": 10670,
"id": 7342,
"maxAmount": 1
},
{
@ -973,7 +973,7 @@
{
"minAmount": 1,
"weight": "5",
"id": 10673,
"id": 7348,
"maxAmount": 1
},
{
@ -985,7 +985,7 @@
{
"minAmount": 1,
"weight": "5",
"id": 10676,
"id": 7354,
"maxAmount": 1
},
{
@ -997,7 +997,7 @@
{
"minAmount": 1,
"weight": "5",
"id": 10679,
"id": 7360,
"maxAmount": 1
},
{

View file

@ -73,7 +73,7 @@
},
{
"id": "92",
"replaceId": "17317",
"replaceId": "91",
"fence": "false",
"metal": "false"
},
@ -193,7 +193,7 @@
},
{
"id": "1553",
"replaceId": "1552",
"replaceId": "1556",
"fence": "true",
"metal": "false"
},
@ -301,7 +301,7 @@
},
{
"id": "2025",
"replaceId": "1534",
"replaceId": "2026",
"fence": "false",
"metal": "false"
},
@ -312,14 +312,14 @@
"metal": "false"
},
{
"id": "2036",
"id": "1530",
"replaceId": "1531",
"fence": "false",
"metal": "false"
},
{
"id": "2039",
"replaceId": "1561",
"replaceId": "1560",
"fence": "false",
"metal": "true"
},
@ -332,13 +332,13 @@
{
"id": "2050",
"replaceId": "15511",
"fence": "false",
"fence": "true",
"metal": "false"
},
{
"id": "2051",
"replaceId": "15513",
"fence": "false",
"fence": "true",
"metal": "false"
},
{
@ -896,12 +896,12 @@
{
"id": "3725",
"replaceId": "3727",
"fence": "false",
"fence": "true",
"metal": "false"
},
{
"id": "3726",
"replaceId": "3727",
"replaceId": "3728",
"fence": "true",
"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"
},
@ -979,19 +979,19 @@
},
{
"id": "4423",
"replaceId": "4429",
"replaceId": "4425",
"fence": "false",
"metal": "false"
},
{
"id": "4424",
"replaceId": "11382",
"replaceId": "4426",
"fence": "false",
"metal": "false"
},
{
"id": "4427",
"replaceId": "11380",
"replaceId": "4429",
"fence": "false",
"metal": "false"
},
@ -1238,12 +1238,12 @@
{
"id": "7049",
"replaceId": "7051",
"fence": "false",
"fence": "true",
"metal": "false"
},
{
"id": "7050",
"replaceId": "23919",
"replaceId": "7052",
"fence": "true",
"metal": "false"
},
@ -1340,7 +1340,7 @@
{
"id": "8810",
"replaceId": "8812",
"fence": "false",
"fence": "true",
"metal": "false"
},
{
@ -1759,7 +1759,7 @@
},
{
"id": "14245",
"replaceId": "14248",
"replaceId": "14246",
"fence": "true",
"metal": "false"
},
@ -1983,7 +1983,15 @@
"id": "20391",
"replaceId": "28518",
"fence": "false",
"metal": "true"
"metal": "true",
"autowalk": "true"
},
{
"id": "28514",
"replaceId": "28518",
"fence": "false",
"metal": "true",
"autowalk": "true"
},
{
"id": "21065",
@ -2144,13 +2152,13 @@
{
"id": "24369",
"replaceId": "24373",
"fence": "true",
"fence": "false",
"metal": "false"
},
{
"id": "24370",
"replaceId": "24374",
"fence": "true",
"fence": "false",
"metal": "false"
},
{
@ -2177,18 +2185,6 @@
"fence": "false",
"metal": "false"
},
{
"id": "24560",
"replaceId": "15515",
"fence": "false",
"metal": "false"
},
{
"id": "24561",
"replaceId": "15517",
"fence": "false",
"metal": "false"
},
{
"id": "24565",
"replaceId": "36316",
@ -2357,11 +2353,25 @@
"fence": "false",
"metal": "true"
},
{
"id": "26081",
"replaceId": "26083",
"fence": "false",
"metal": "true",
"autowalk": "true"
},
{
"id": "26082",
"replaceId": "26084",
"fence": "false",
"metal": "true",
"autowalk": "true"
},
{
"id": "26130",
"replaceId": "26132",
"fence": "false",
"metal": "false"
"metal": "true"
},
{
"id": "26131",
@ -2507,12 +2517,6 @@
"fence": "false",
"metal": "false"
},
{
"id": "28514",
"replaceId": "28518",
"fence": "true",
"metal": "true"
},
{
"id": "28589",
"replaceId": "28588",
@ -2671,7 +2675,7 @@
},
{
"id": "31815",
"replaceId": "31816",
"replaceId": "31817",
"fence": "false",
"metal": "false"
},
@ -2798,7 +2802,7 @@
{
"id": "34780",
"replaceId": "34778",
"fence": "false",
"fence": "true",
"metal": "false"
},
{

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
[
{
"id": "5",
"interfaceType": "1",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
@ -25,7 +25,49 @@
},
{
"id": "24",
"interfaceType": "1",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "34",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "38",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "42",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "46",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "57",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "58",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "59",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
@ -53,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",
@ -125,6 +191,12 @@
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "139",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "140",
"interfaceType": "4",
@ -137,6 +209,12 @@
"walkable": "true",
"tabIndex": "3"
},
{
"id": "169",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "172",
"interfaceType": "4",
@ -197,9 +275,33 @@
"walkable": "true",
"tabIndex": "6"
},
{
"id": "194",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "195",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "196",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "198",
"interfaceType": "1",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "209",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
@ -257,6 +359,12 @@
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "240",
"interfaceType": "3",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "241",
"interfaceType": "4",
@ -281,6 +389,36 @@
"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",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "259",
"interfaceType": "2",
@ -371,6 +509,12 @@
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "328",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "336",
"interfaceType": "3",
@ -395,6 +539,12 @@
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "377",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "380",
"interfaceType": "1",
@ -449,12 +599,24 @@
"walkable": "true",
"tabIndex": "4"
},
{
"id": "418",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "421",
"interfaceType": "4",
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "428",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "430",
"interfaceType": "2",
@ -473,6 +635,30 @@
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "485",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "486",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "487",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "488",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "498",
"interfaceType": "0",
@ -493,7 +679,7 @@
},
{
"id": "532",
"interfaceType": "1",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
@ -605,9 +791,15 @@
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "653",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
{
"id": "656",
"interfaceType": "1",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
},
@ -721,7 +913,7 @@
},
{
"id": "809",
"interfaceType": "1",
"interfaceType": "8",
"walkable": "true",
"tabIndex": "-1"
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,62 @@
[
{
"id": "98",
"borders": "{3072,3456,3135,3519,[3076,3456,3085,3458]~,[3082,3459,3085,3460]}"
},
{
"id": "141",
"borders": "{3072,3392,3135,3455,[3076,3452,3085,3455]}"
},
{
"id": "228",
"borders": "{2896,5446,2919,5462}"
},
{
"id": "229",
"borders": "{2921,5456,2937,5479}"
},
{
"id": "230",
"borders": "{2904,5481,2927,5497}"
},
{
"id": "231",
"borders": "{2886,5464,2902,5487}"
},
{
"id": "386",
"borders": "{2820,5312,2849,5369}-{2849,5349,2880,5374}"
},
{
"id": "391",
"borders": "{2879,5340,2944,5366}-{2909,5316,2944,5340}"
},
{
"id": "399",
"borders": "{2816,5248,2943,5375,[2823,5250,2844,5310]~,[2844,5250,2878,5280]~,[2879,5340,2944,5366]~,[2909,5316,2944,5340]~,[2820,5312,2849,5369]~,[2849,5349,2880,5374]~,[2885,5253,2934,5278]~,[2913,5278,2937,5306]}"
},
{
"id": "404",
"borders": "{2823,5250,2844,5310}-{2844,5250,2878,5276}"
},
{
"id": "408",
"borders": "{2885,5253,2934,5278}-{2913,5278,2937,5306}"
},
{
"id": "459",
"borders": "{3137,5442,3192,5564}-{3193,5442,3198,5472}-{3193,5507,3198,5564}"
},
{
"id": "467",
"borders": "{3199,5441,3262,5564}-{3193,5482,3198,5497}"
},
{
"id": "488",
"borders": "{3263,5441,3327,5566}"
},
{
"id": "492",
"borders": "{3076,3452,3085,3460,[3076,3459,3081,3460]}"
}
]

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -145,7 +145,7 @@
},
{
"examine": "Used for storage.",
"ids": "63,64"
"ids": "63,64,36351,36352"
},
{
"examine": "Surprisingly sturdy looking.",
@ -968,7 +968,7 @@
"ids": "573"
},
{
"examine": "A carving of a figure from the history of RuneScape.",
"examine": "A carving of a figure from the history of 2009Scape.",
"ids": "574,575,576,577,578"
},
{
@ -1753,7 +1753,7 @@
},
{
"examine": "Danger!",
"ids": "1032,5127,29373"
"ids": "1032,5127"
},
{
"examine": "This tells you which way is which.",
@ -2148,7 +2148,7 @@
"ids": "1231"
},
{
"examine": "One of the most common trees in RuneScape.",
"examine": "One of the most common trees in 2009Scape.",
"ids": "1276"
},
{
@ -2601,7 +2601,7 @@
},
{
"examine": "I can climb this.",
"ids": "1729"
"ids": "1729,36347,36363,36644"
},
{
"examine": "Dare I go up?",
@ -3584,7 +3584,7 @@
"ids": "2375"
},
{
"examine": "Soil",
"examine": "Soil. Dug up!",
"ids": "2376,2377,2378"
},
{
@ -3641,7 +3641,7 @@
},
{
"examine": "I can climb down this.",
"ids": "2408"
"ids": "2408,36693,36694"
},
{
"examine": "A commonly found tree.",
@ -4964,7 +4964,7 @@
"ids": "3032"
},
{
"examine": "One of the most common trees in RuneScape.",
"examine": "One of the most common trees in 2009Scape.",
"ids": "3033,3034,3035,3036"
},
{
@ -6384,12 +6384,12 @@
"ids": "4131"
},
{
"examine": "These doors look very ominous. A sign says 'To the tombs'.",
"ids": "4132,4133"
"examine": "This tells you which way is which.",
"ids": "4132,4133,4134,4135"
},
{
"examine": "Large doors set into the hillside.",
"ids": "4134,4135,4136,4137"
"examine": "These doors look very ominous. A sign says 'To the tombs'.",
"ids": "4136,4137"
},
{
"examine": "Items are for sale here.",
@ -6777,7 +6777,7 @@
},
{
"examine": "A solid stone staircase.",
"ids": "4415,4416,4417,4418,4419,4420"
"ids": "4415,4416,4417,4418,4419,4420,36480,36481,36484,36495,36521,36523,36532,36540"
},
{
"examine": "A spiky barricade.",
@ -7609,7 +7609,7 @@
},
{
"examine": "I can climb down this.",
"ids": "4911,4912"
"ids": "4911,4912,36349,36365"
},
{
"examine": "It looks cramped and dark.",
@ -8592,7 +8592,7 @@
"ids": "5789,5790"
},
{
"examine": "A carving of a figure from the history of RuneScape.",
"examine": "A carving of a figure from the history of 2009Scape.",
"ids": "5791,36749,36751"
},
{
@ -12788,7 +12788,7 @@
"ids": "8972"
},
{
"examine": "One of the most common trees in RuneScape.",
"examine": "One of the most common trees in 2009Scape.",
"ids": "8973"
},
{
@ -14100,7 +14100,7 @@
"ids": "10080"
},
{
"examine": "One of the most common trees in RuneScape.",
"examine": "One of the most common trees in 2009Scape.",
"ids": "10081"
},
{
@ -15964,7 +15964,7 @@
"ids": "11354,11355"
},
{
"examine": "A gateway back to RuneScape.",
"examine": "A gateway back to 2009Scape.",
"ids": "11356"
},
{
@ -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"
},
{
@ -16564,7 +16564,7 @@
"ids": "11759"
},
{
"examine": "A carving of a figure from the history of RuneScape.",
"examine": "A carving of a figure from the history of 2009Scape.",
"ids": "11761"
},
{
@ -16741,7 +16741,7 @@
},
{
"examine": "Better not eat them!",
"ids": "12003"
"ids": "12003,12128"
},
{
"examine": "It's going to be a tight squeeze!",
@ -16881,7 +16881,7 @@
},
{
"examine": "A wall jutting out into the path.",
"ids": "12127,12128,12129,12130"
"ids": "12127,12129,12130"
},
{
"examine": "Spooky.",
@ -18728,7 +18728,7 @@
"ids": "13409,13410"
},
{
"examine": "One of the most common trees in RuneScape.",
"examine": "One of the most common trees in 2009Scape.",
"ids": "13411,13412"
},
{
@ -18996,11 +18996,11 @@
"ids": "13525"
},
{
"examine": "A map of RuneScape.",
"examine": "A map of 2009Scape.",
"ids": "13526"
},
{
"examine": "A map of RuneScape including major cave systems.",
"examine": "A map of 2009Scape including major cave systems.",
"ids": "13527"
},
{
@ -20007,6 +20007,46 @@
"examine": "Why do I never take time to look at the grass?",
"ids": "14003"
},
{
"examine": "Well, I have the logs in place, now to get something to boil.",
"ids": "14005"
},
{
"examine": "Covered in a thick layer of grease.",
"ids": "14006"
},
{
"examine": "I'm glad this isn't for dinner.",
"ids": "14007"
},
{
"examine": "This smells so very, very bad...",
"ids": "14008"
},
{
"examine": "It seems to have all boiled away.",
"ids": "14009"
},
{
"examine": "Stop examining signs! You're in the Wilderness now!",
"ids": "14503"
},
{
"examine": "Danger, Wilderness up ahead. Last chance to turn back...",
"ids": "14504"
},
{
"examine": "Danger, Wilderness up ahead. Watch out for the Beast!",
"ids": "14505"
},
{
"examine": "Danger, Wilderness up ahead. Beware of stray magma.",
"ids": "14506"
},
{
"examine": "Danger, Wilderness up ahead. Almost certain death!",
"ids": "14507"
},
{
"examine": "Home sweet home?",
"ids": "15477"
@ -20019,10 +20059,30 @@
"examine": "Home sweet home?",
"ids": "15748"
},
{
"examine": "Danger - Possibly deadly creatures below!",
"ids": "16083,16151,16117"
},
{
"examine": "Large urn.",
"ids": "17362"
},
{
"examine": "A large fish.",
"ids": "18482"
},
{
"examine": "A sign on a cactus.",
"ids": "18876"
},
{
"examine": "Dead and half-buried.",
"ids": "19996"
},
{
"examine": "Dead animal head. Lovely.",
"ids": "19997"
},
{
"examine": "Might be worth opening?",
"ids": "21299"
@ -20127,10 +20187,18 @@
"examine": "Contains traces of summoning energy.",
"ids": "29939,29943,29944,29945,29947,29951,29952,29953,29954"
},
{
"examine": "An interesting sign.",
"ids": "31297,31298,31299,31300,31301"
},
{
"examine": "I wonder what this spooky contains.",
"ids": "37051"
},
{
"examine": "The mine has collapsed.",
"ids": "37634"
},
{
"examine": "It really was this big!",
"ids": "40043"
@ -20195,6 +20263,14 @@
"examine": "A wooden crate.",
"ids": "15031"
},
{
"examine": "A sealed barrel with a warning sign on it.",
"ids": "17296"
},
{
"examine": "A barrel with a warning sign on it.",
"ids": "17297"
},
{
"examine": "A beautiful landscape.",
"ids": "24184"
@ -20275,6 +20351,10 @@
"examine": "Technically a bed.",
"ids": "32031"
},
{
"examine": "Now that's what I call slimline!",
"ids": "32072"
},
{
"examine": "A really bad portrait of the King.",
"ids": "32326"
@ -20293,7 +20373,7 @@
},
{
"examine": "A wooden barrel for storage.",
"ids": "31136,36798"
"ids": "17308,31136,36798"
},
{
"examine": "A home for baby creatures.",
@ -20519,10 +20599,6 @@
"examine": "Popular on sandy beaches where fruity cocktails may be found.",
"ids": "18856"
},
{
"examine": "Stop examining signs! You're in the Wilderness now!",
"ids": "14503"
},
{
"examine": "Looks like part of the entrance is blocked by rubble.",
"ids": "15767"
@ -20602,5 +20678,41 @@
{
"examine": "Keeps the puppies out of trouble.",
"ids": "28341"
},
{
"examine": "Warning! Danger of death.",
"ids": "29373"
},
{
"examine": "There are some toolboxes on this table.",
"ids": "36573,36580"
},
{
"examine": "There's some rock I can use with the catapult here.",
"ids": "36574,36581"
},
{
"examine": "There are some barricades here.",
"ids": "36575,36582"
},
{
"examine": "There is some rope here.",
"ids": "36576,36583"
},
{
"examine": "There are some explosive potions here.",
"ids": "36577,36584"
},
{
"examine": "There are some pickaxes on this table.",
"ids": "36578,36585"
},
{
"examine": "There are some bandages on this table.",
"ids": "36579,36586"
},
{
"examine": "Rough but adequate.",
"ids": "14918"
}
]

View file

@ -15,7 +15,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9236,13280"
"ammunition": "877,878,6061,6062,879,9236"
},
{
"itemId": "800",
@ -294,7 +294,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9236,13280"
"ammunition": "877,878,6061,6062,879,9236"
},
{
"itemId": "839",
@ -1095,7 +1095,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "8882,877,878,6061,6062,879,9236"
"ammunition": "8882,877,878,6061,6062,879,9236,9139,9286,9293,9300,9140,9287,9294,9237,9145,9301,9292,9299,9306,9335,880,9238"
},
{
"itemId": "9174",
@ -1104,7 +1104,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9236,13280"
"ammunition": "877,878,6061,6062,879,9236"
},
{
"itemId": "9176",
@ -1113,7 +1113,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,9140,879,9139,9236,13280"
"ammunition": "877,878,6061,6062,879,9139,9236,9286,9293,9300,9335,9237"
},
{
"itemId": "9177",
@ -1122,7 +1122,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9236,9139,9140,9287,9294,9301,880,9238,9145,13280"
"ammunition": "877,878,6061,6062,879,9236,9139,9140,9287,9294,9301,880,9238,9145,9286,9293,9300,9292,9299,9306,9335,9237"
},
{
"itemId": "9179",
@ -1131,7 +1131,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9139,9140,9236,9141,9288,9295,9302,9336,9239,9145,13280"
"ammunition": "877,878,6061,6062,879,9139,9140,9236,9141,9288,9295,9302,9336,9239,9145,9286,9293,9300,9287,9294,9301,9292,9299,9306,9335,9237,880,9238"
},
{
"itemId": "9181",
@ -1140,7 +1140,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9236,9141,9288,9295,9302,9336,9239,13083,13084,13085,13086,9142,9289,9296,9303,9337,9240,9338,9145,9139,9140,9241,13280"
"ammunition": "877,878,6061,6062,879,9236,9141,9288,9295,9302,9336,9239,13083,13084,13085,13086,9142,9289,9296,9303,9337,9240,9338,9145,9139,9140,9241,9286,9293,9300,9140,9287,9294,9301,9292,9299,9306,9335,9237,880,9238,13083,13084,13085,13086"
},
{
"itemId": "9183",
@ -1149,7 +1149,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9236,9139,9141,9288,9295,9302,9336,9239,13083,13084,13085,13086,9142,9289,9296,9303,9337,9240,9338,9241,9145,9143,9290,9297,9304,9339,9242,9340,9243,13280"
"ammunition": "877,878,6061,6062,879,9236,9139,9141,9288,9295,9302,9336,9239,13083,13084,13085,13086,9142,9289,9296,9303,9337,9240,9338,9241,9145,9143,9290,9297,9304,9339,9242,9340,9243,9286,9293,9300,9140,9287,9294,9301,9292,9299,9306,9335,9237,880,9238,13083,13084,13085,13086"
},
{
"itemId": "9185",
@ -1158,7 +1158,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9236,9139,9141,9288,9295,9302,9336,9239,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9145,13083,13084,13085,13086,9142,9289,9296,9303,9337,9240,9338,9241,9143,9290,9297,9304,9339,9242,9340,9243,9144,9291,9298,9305,9341,9244,9342,9245,9140,13280"
"ammunition": "877,878,6061,6062,879,9236,9139,9141,9288,9295,9302,9336,9239,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9145,13083,13084,13085,13086,9142,9289,9296,9303,9337,9240,9338,9241,9143,9290,9297,9304,9339,9242,9340,9243,9144,9291,9298,9305,9341,9244,9342,9245,9140,13280,9139,9286,9293,9300,9287,9294,9301,9292,9299,9306,9335,9237,880,13083,13084,13085,13086"
},
{
"itemId": "9705",
@ -1293,7 +1293,7 @@
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9236,9141,9288,9295,9302,9140,9336,9239,13083,13084,13085,13086,13280"
"ammunition": "877,878,6061,6062,879,9139,9140,9236,9141,9288,9295,9302,9336,9239,9145,9286,9293,9300,9287,9294,9301,9292,9299,9306,9335,9237,880,9238,13083,13084,13085,13086"
},
{
"itemId": "13405",
@ -1502,69 +1502,6 @@
"drop_ammo": "true",
"ammunition": "882,883,5616,5622,598,884,885,5617,5623,2532,886,887,5618,5624,2534,888,889,5619,5625,2536,890,891,5620,5626,2538,892,893,5621,5627,2540,78,4160"
},
{
"itemId": "14671",
"name": "Armadyl crossbow",
"ammo_slot": "13",
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9236,9141,9288,9295,9302,9336,9239,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,13083,13084,13085,13086,9142,9289,9296,9303,9337,9240,9338,9241,9143,9290,9297,9304,9339,9242,9340,9243,9144,9291,9298,9305,9341,9244,9342,9245,9140,13280"
},
{
"itemId": "14684",
"name": "Odium ward",
"ammo_slot": "13",
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "8882,877,878,6061,6062,879,9236,9141,9288,9295,9302,9336,9239,13083,13084,13085,13086,9142,9289,9296,9303,9337,9240,9338,9241,9143,9290,9297,9304,9339,9242,9340,9243"
},
{
"itemId": "14685",
"name": "Odium shard 1",
"ammo_slot": "13",
"weapon_type": "1",
"animation": "4230",
"drop_ammo": "true",
"ammunition": "877,878,6061,6062,879,9236"
},
{
"itemId": "14803",
"name": "Dark bow",
"ammo_slot": "13",
"weapon_type": "2",
"animation": "426",
"drop_ammo": "true",
"ammunition": "882,883,5616,5622,598,884,885,5617,5623,2532,886,887,5618,5624,2534,888,889,5619,5625,2536,890,891,5620,5626,2538,892,893,5621,5627,2540,11212,11227,11228,11229,11217,78,4160"
},
{
"itemId": "14804",
"name": "Dark bow",
"ammo_slot": "13",
"weapon_type": "2",
"animation": "426",
"drop_ammo": "true",
"ammunition": "882,883,5616,5622,598,884,885,5617,5623,2532,886,887,5618,5624,2534,888,889,5619,5625,2536,890,891,5620,5626,2538,892,893,5621,5627,2540,11212,11227,11228,11229,11217,78,4160"
},
{
"itemId": "14805",
"name": "Dark bow",
"ammo_slot": "13",
"weapon_type": "2",
"animation": "426",
"drop_ammo": "true",
"ammunition": "882,883,5616,5622,598,884,885,5617,5623,2532,886,887,5618,5624,2534,888,889,5619,5625,2536,890,891,5620,5626,2538,892,893,5621,5627,2540,11212,11227,11228,11229,11217,78,4160"
},
{
"itemId": "14806",
"name": "Dark bow",
"ammo_slot": "13",
"weapon_type": "2",
"animation": "426",
"drop_ammo": "true",
"ammunition": "882,883,5616,5622,598,884,885,5617,5623,2532,886,887,5618,5624,2534,888,889,5619,5625,2536,890,891,5620,5626,2538,892,893,5621,5627,2540,11212,11227,11228,11229,11217,78,4160"
},
{
"itemId": "14192",
"name": "Bow (class 1)",

View file

@ -45,22 +45,13 @@
"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}"
},
{
"npcs": "590",
"npcs": "590,591",
"high_alch": "0",
"currency": "995",
"general_store": "true",
"id": "6",
"title": "Aemad's Adventuring Supplies Store",
"stock": "{227,300,100}-{1265,10,100}-{1349,10,100}-{2142,10,100}-{590,10,100}-{1759,100,100}-{882,1000,100}-{954,10,100}-{970,10,100}-{946,10,100}-{1935,10,100}"
},
{
"npcs": "591",
"high_alch": "0",
"currency": "995",
"general_store": "true",
"id": "7",
"title": "Kortan 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}"
"title": "Aemad's Adventuring Supplies",
"stock": "{227,10,100}-{1265,10,100}-{1349,10,100}-{2142,10,100}-{590,10,100}-{1759,100,100}-{882,1000,100}-{954,10,100}-{970,10,100}-{946,10,100}-{1935,10,100}"
},
{
"npcs": "971",
@ -222,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",
@ -519,7 +510,7 @@
"general_store": "false",
"id": "59",
"title": "Fancy Clothes Store",
"stock": "{1949,10,100}-{958,10,100}-{948,10,100}-{1733,10,100}-{1734,1000,100}-{1059,30,100}-{1061,10,100}-{1757,10,100}-{1013,10,100}-{1025,10,100}-{10088,0,100}-{10090,0,100}-{10091,0,100}-{10089,0,100}-{10087,0,100}-{11525,0,100}"
"stock": "{1949,0,100}-{579,10,100}-{1023,10,100}-{958,10,100}-{948,10,100}-{1733,10,100}-{1734,1000,100}-{1059,30,100}-{1061,10,100}-{428,10,100}-{426,10,100}-{1757,10,100}-{1013,10,100}-{1015,10,100}-{1011,10,100}-{1007,10,100}-{1025,10,100}-{10088,0,100}-{10090,0,100}-{10091,0,100}-{10089,0,100}-{10087,0,100}-{11525,0,100}"
},
{
"npcs": "548",
@ -573,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",
@ -1112,7 +1103,7 @@
"currency": "995",
"general_store": "false",
"id": "126",
"title": "Pickaxe-is-mine",
"title": "Pickaxe-Is-Mine",
"stock": "{1265,10,100}-{1269,10,100}-{1273,10,100}-{1271,10,100}-{1275,10,100}"
},
{
@ -1251,13 +1242,13 @@
"stock": "{12204,10,100}-{12207,10,100}-{12210,10,100}-{12213,10,100}-{12216,10,100}-{12219,10,100}-{12222,10,100}-{12183,125000,100}-{12155,5000,100}"
},
{
"npcs": "6996",
"npcs": "4472",
"high_alch": "0",
"currency": "995",
"general_store": "false",
"id": "142",
"title": "Bogrog's Summoning Shop",
"stock": "{12204,10,100}-{12207,10,100}-{12210,10,100}-{12213,10,100}-{12216,10,100}-{12219,10,100}-{12222,10,100}-{12183,125000,100}-{12155,5000,100}"
"stock": "{12204,10,100}-{12207,10,100}-{12210,0,100}-{12213,0,100}-{12216,0,100}-{12219,0,100}-{12222,0,100}-{12183,65000,100}-{12155,5000,100}"
},
{
"npcs": "3671",
@ -1266,7 +1257,7 @@
"general_store": "false",
"id": "143",
"title": "Fortunato's Fine Wine",
"stock": "{1993,10,100}-{1937,10,100}-{7919,10,100}-{1935,10,100}"
"stock": "{1993,10,100}-{7810,10,100}-{7919,10,100}-{1935,10,100}"
},
{
"npcs": "558",
@ -1476,7 +1467,7 @@
"stock": "{8794,10,100}-{8790,300,100}-{4819,300,100}-{4820,300,100}-{1539,300,100}"
},
{
"npcs": "1079",
"npcs": "1079,1357,1358",
"high_alch": "0",
"currency": "995",
"general_store": "false",
@ -1608,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": "",
@ -1662,7 +1653,7 @@
"general_store": "false",
"id": "187",
"title": "William's Wilderness Cape Shop",
"stock": "{4315,100,100}-{4335,100,100}-{4375,100,100}-{4395,100,100}"
"stock": "{4315,100,100}-{4335,100,100}-{4355,100,100}-{4375,100,100}-{4395,100,100}"
},
{
"npcs": "1779",
@ -1842,7 +1833,7 @@
"general_store": "false",
"id": "216",
"title": "Ore Store",
"stock": "{436,20,100}-{438,10,100}-{440,10,100}-{442,5,100}-{453,10,100}-{444,5,100}-{447,0,100}-{449,0,100}"
"stock": "{436,10,100}-{438,10,100}-{440,0,100}-{442,0,100}-{453,0,100}-{444,0,100}-{447,0,100}-{449,0,100}"
},
{
"npcs": "596",
@ -1891,12 +1882,13 @@
},
{
"npcs": "2564",
"force_shared": "true",
"high_alch": "0",
"currency": "995",
"general_store": "false",
"id": "222",
"title": "Ore Shop\b",
"stock": "{436,1500,100}-{438,1500,100}-{440,1500,100}-{442,1500,100}-{444,1500,100}-{447,1500,100}-{453,1500,100}"
"stock": "{436,0,0}-{438,0,0}-{440,0,0}-{442,0,0}-{444,0,0}-{447,0,0}-{453,0,0}"
},
{
"npcs": "603",
@ -2176,5 +2168,32 @@
"id": "254",
"title": "Gabooty's Tai Bwo Wannai Drinky Store",
"stock": "{2084,0,100}-{2092,0,100}-{2048,0,100}-{2054,0,100}-{2064,0,100}-{2074,0,100}"
},
{
"npcs": "1526",
"high_alch": "0",
"currency": "4067",
"general_store": "false",
"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

4
Server/data/eco/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View file

@ -1,69 +0,0 @@
{
"offers": [
{
"__comment" : "coal",
"item" : "453",
"qty" : "1000"
},
{
"__comment" : "vial",
"item" : "227",
"qty" : "10000"
},
{
"__comment" : "water vial",
"item" : "229",
"qty" : "10000"
},
{
"__comment" : "cooked lobster",
"item" : "379",
"qty" : "10000"
},
{
"__comment" : "Ashes",
"item" : "592",
"qty" : "1000"
},
{
"__comment" : "Mort myre fungi",
"item" : "2970",
"qty" : "1000"
},
{
"__comment" : "Poison ivy berries",
"item" : "6018",
"qty" : "1000"
},
{
"__comment" : "Potato cactus",
"item" : "3138",
"qty" : "1000"
},
{
"__comment" : "Unicorn horn",
"item" : "237",
"qty" : "1000"
},
{
"__comment" : "Red spider eggs",
"item" : "223",
"qty" : "1000"
},
{
"__comment" : "Bird nest",
"item" : "6693",
"qty" : "1000"
},
{
"__comment" : "Chocolate dust",
"item" : "1975",
"qty" : "1000"
},
{
"__comment" : "Limpwurt root",
"item" : "225",
"qty" : "10000"
}
]
}

View file

@ -1 +0,0 @@
<EFBFBD><EFBFBD>

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,7 @@
CREATE DATABASE global;
USE global;
-- phpMyAdmin SQL Dump
-- version 5.0.2
-- https://www.phpmyadmin.net/

View file

@ -0,0 +1,539 @@
{
"__inputs": [
{
"name": "DS_SQLITE",
"label": "SQLite",
"description": "",
"type": "datasource",
"pluginId": "frser-sqlite-datasource",
"pluginName": "SQLite"
}
],
"__elements": {},
"__requires": [
{
"type": "datasource",
"id": "frser-sqlite-datasource",
"name": "SQLite",
"version": "3.3.0"
},
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "10.0.1"
},
{
"type": "panel",
"id": "timeseries",
"name": "Time series",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": null,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "${DS_SQLITE}"
},
"description": "",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "misc_pulses"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "purple",
"mode": "fixed"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "other"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "dark-red",
"mode": "fixed"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "packet_incoming"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "super-light-red",
"mode": "fixed"
}
}
]
}
]
},
"gridPos": {
"h": 9,
"w": 24,
"x": 0,
"y": 0
},
"id": 1,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "10.0.1",
"targets": [
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "${DS_SQLITE}"
},
"queryText": "SELECT * FROM tick_lengths",
"queryType": "table",
"rawQueryText": "SELECT * FROM tick_lengths",
"refId": "A",
"timeColumns": [
"ts"
]
}
],
"title": "Tick Time",
"type": "timeseries"
},
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "${DS_SQLITE}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 13,
"w": 13,
"x": 0,
"y": 9
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "10.0.1",
"targets": [
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "${DS_SQLITE}"
},
"queryText": "select * from top_pulses;",
"queryType": "table",
"rawQueryText": "select * from top_pulses;",
"refId": "A",
"timeColumns": [
"time",
"ts"
]
}
],
"title": "Tick Time By Pulse (Total)",
"transformations": [
{
"id": "extractFields",
"options": {
"format": "json",
"jsonPaths": [
{
"path": "pulses"
}
],
"keepTime": false,
"replace": false,
"source": "pulse_info"
}
},
{
"id": "extractFields",
"options": {
"source": "pulses"
}
}
],
"type": "timeseries"
},
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "${DS_SQLITE}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 11,
"x": 13,
"y": 9
},
"id": 4,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "${DS_SQLITE}"
},
"queryText": "SELECT * FROM high_volume_pulses;",
"queryType": "table",
"rawQueryText": "SELECT * FROM high_volume_pulses;",
"refId": "A",
"timeColumns": [
"time",
"ts"
]
}
],
"title": "High Volume Pulses",
"transformations": [
{
"id": "extractFields",
"options": {
"format": "json",
"source": "pulse_info"
}
},
{
"id": "extractFields",
"options": {
"source": "pulses"
}
}
],
"type": "timeseries"
},
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "${DS_SQLITE}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "stepBefore",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 4,
"w": 11,
"x": 13,
"y": 18
},
"id": 3,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "${DS_SQLITE}"
},
"queryText": "SELECT * FROM bot_counts;",
"queryType": "table",
"rawQueryText": "SELECT * FROM bot_counts;",
"refId": "A",
"timeColumns": [
"time",
"ts"
]
}
],
"title": "Bot Population",
"type": "timeseries"
}
],
"refresh": "1h",
"schemaVersion": 38,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-5m",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Main",
"uid": "ffccf845-00a2-46f2-b0c0-a8b88032c701",
"version": 10,
"weekStart": ""
}

View file

@ -0,0 +1,2 @@
CREATE USER IF NOT EXISTS 2009scapetest@localhost IDENTIFIED BY '2009scapetest';
GRANT ALL PRIVILEGES ON global.* TO 2009scapetest@localhost;

View file

@ -285,7 +285,7 @@ exceptions:
- 'Throwable'
allowedExceptionNameRegex: '_|(ignore|expected).*'
TooGenericExceptionThrown:
active: true
active: false
exceptionNames:
- 'Error'
- 'Exception'
@ -437,7 +437,7 @@ potential-bugs:
- '*.CanIgnoreReturnValue'
ignoreFunctionCall: []
ImplicitDefaultLocale:
active: true
active: false
ImplicitUnitReturnType:
active: false
allowExplicitReturnType: true
@ -609,7 +609,7 @@ style:
ObjectLiteralToLambda:
active: true
OptionalAbstractKeyword:
active: true
active: false
OptionalUnit:
active: false
OptionalWhenBraces:
@ -696,9 +696,9 @@ style:
UseOrEmpty:
active: true
UseRequire:
active: true
active: false
UseRequireNotNull:
active: true
active: false
UselessCallOnNotNull:
active: true
UtilityClassWithPublicConstructor:

View file

@ -7,8 +7,8 @@
<properties>
<project.mainClassName>core.Server</project.mainClassName>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
<kotlin.version>1.6.21</kotlin.version>
<kotlin.comipler.jvmTarget>1.6</kotlin.comipler.jvmTarget>
<kotlin.version>1.8.20</kotlin.version>
<kotlin.compiler.jvmTarget>11</kotlin.compiler.jvmTarget>
<junit.version>5.7.0</junit.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
@ -16,7 +16,7 @@
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
<scope>compile</scope>
</dependency>
@ -195,7 +195,7 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<maxmem>1024m</maxmem>
<maxmem>2048m</maxmem>
<useIncrementalCompilation>false</useIncrementalCompilation>
<compilerArgs>
<arg>-XDcompilePolicy=simple</arg>

View file

@ -30,11 +30,6 @@ public enum BossKillCounter {
8355, 8356, 8357, 8358, 8359, 8360,
8361, 8362, 8363, 8364, 8365, 8366,
}, "Tormented demon", -1),
CALLISTO(new int[] { 8610 }, "Callisto", 14658),
SCORPIA(new int[] { 8611 }, "Scorpia", 14661),
VENENATIS(new int[] { 8612 }, "Venenatis", 14657),
VETION(new int[] { 8613 }, "Vet'ion", 14659),
KRAKEN(new int[] { 8614 }, "Cave Kraken", 14651),
;

View file

@ -0,0 +1,80 @@
package content.data
import core.api.toIntArray
import core.cache.def.impl.ItemDefinition
import org.rs09.consts.Items
/**
* Represents a distinct charged item, i.e. items with (#).
* Not to be confused with items with internal charge, like degradation.
* @author RiL
*/
enum class ChargedItem(val ids: IntArray) {
AMULET_OF_GLORY((Items.AMULET_OF_GLORY4_1712 downTo Items.AMULET_OF_GLORY_1704 step 2).toIntArray()),
RING_OF_DUELLING((Items.RING_OF_DUELLING8_2552..Items.RING_OF_DUELLING1_2566 step 2).toIntArray()),
GAMES_NECKLACE((Items.GAMES_NECKLACE8_3853..Items.GAMES_NECKLACE1_3867 step 2).toIntArray()),
BROODOO_SHIELDA((Items.BROODOO_SHIELD_10_6215..Items.BROODOO_SHIELD_6235 step 2).toIntArray()),
BROODOO_SHIELDB((Items.BROODOO_SHIELD_10_6237..Items.BROODOO_SHIELD_6257 step 2).toIntArray()),
BROODOO_SHIELDC((Items.BROODOO_SHIELD_10_6259..Items.BROODOO_SHIELD_6279 step 2).toIntArray()),
ROD_OF_IVANDIS((Items.ROD_OF_IVANDIS10_7639..Items.ROD_OF_IVANDIS1_7648).toIntArray()),
BLACK_MASK((Items.BLACK_MASK_10_8901..Items.BLACK_MASK_8921 step 2).toIntArray()),
AMULET_OF_GLORYT((Items.AMULET_OF_GLORYT4_10354..Items.AMULET_OF_GLORYT_10362 step 2).toIntArray()),
CASTLEWAR_BRACE((Items.CASTLEWAR_BRACE3_11079..Items.CASTLEWAR_BRACE1_11083 step 2).toIntArray()),
FORINTHRY_BRACE((Items.FORINTHRY_BRACE5_11095..Items.FORINTHRY_BRACE1_11103 step 2).toIntArray()),
SKILLS_NECKLACE((Items.SKILLS_NECKLACE4_11105..Items.SKILLS_NECKLACE_11113 step 2).toIntArray()),
COMBAT_BRACELET((Items.COMBAT_BRACELET4_11118..Items.COMBAT_BRACELET_11126 step 2).toIntArray()),
DIGSITE_PENDANT((Items.DIGSITE_PENDANT_5_11194 downTo Items.DIGSITE_PENDANT_1_11190).toIntArray()),
VOID_SEAL((Items.VOID_SEAL8_11666..Items.VOID_SEAL1_11673).toIntArray()),
AMULET_OF_FARMING((Items.AMULET_OF_FARMING8_12622 downTo Items.AMULET_OF_FARMING1_12608 step 2).toIntArray()),
IVANDIS_FLAIL((Items.IVANDIS_FLAIL_30_13117..Items.IVANDIS_FLAIL_1_13146).toIntArray()),
RING_OF_SLAYING((Items.RING_OF_SLAYING8_13281..Items.RING_OF_SLAYING1_13288).toIntArray()),
RING_OF_WEALTH((Items.RING_OF_WEALTH4_14646 downTo Items.RING_OF_WEALTH_14638 step 2).toIntArray());
/**
* Get the item id for a specific [charge].
* If [charge] is outside the valid range, return the item id with the closest charge.
*/
fun forCharge(charge: Int): Int {
return ids[maxCharge() - if (charge < 1) 1 + maxCharge() - ids.size else if (charge > maxCharge()) maxCharge() else charge]
}
/**
* Get the max charge of this ChargedItem.
*/
fun maxCharge(): Int = maxCharges[ordinal]
companion object {
private val CHARGE_REGEX = Regex("""\(\D?(\d+)\)""")
private val idMap = HashMap<Int, ChargedItem>()
private val maxCharges = IntArray(values().size)
init {
values().forEach { chargedItem ->
maxCharges[chargedItem.ordinal] = getMaxCharge(chargedItem)
chargedItem.ids.forEach { idMap[it] = chargedItem }
}
}
private fun getMaxCharge(chargedItem: ChargedItem): Int {
return CHARGE_REGEX.find(ItemDefinition.forId(chargedItem.ids.first()).name)!!.groups[1]!!.value.toInt()
}
/**
* Check if the item id is a charged item.
*/
fun contains(id: Int): Boolean = idMap.containsKey(id)
/**
* Get the ChargedItem enum for an item id, or null if it's not a charged item.
*/
fun forId(id: Int): ChargedItem? = idMap[id]
/**
* Get the charge value of an item id, or null if it's not a charged item.
*/
fun getCharge(id: Int): Int? {
val chargedItem = forId(id) ?: return null
return chargedItem.maxCharge() - chargedItem.ids.indexOf(id)
}
}
}

View file

@ -2,11 +2,13 @@ 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
import core.game.interaction.QueueStrength
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager
import core.game.node.entity.player.link.audio.Audio
import core.game.node.item.Item
import core.game.system.task.Pulse
import core.game.world.map.Location
@ -14,11 +16,12 @@ import core.game.world.update.flag.context.Animation
import core.game.world.update.flag.context.Graphics
import org.rs09.consts.Items
import core.game.world.GameWorld.Pulser
import org.rs09.consts.Sounds
import java.util.*
/**
* Represents an enchanted jewellery.
* @author Vexia & downthecrop
* @author Vexia, downthecrop, Player Name
*/
enum class EnchantedJewellery(
@ -70,10 +73,10 @@ enum class EnchantedJewellery(
),
AMULET_OF_GLORY(
arrayOf(
"Edgeville",
"Karamja",
"Draynor Village",
"Al-Kharid",
"Edgeville.",
"Karamja.",
"Draynor Village.",
"Al-Kharid.",
"Nowhere."
),
arrayOf(
@ -103,7 +106,7 @@ enum class EnchantedJewellery(
"Barbarian Outpost.",
"Clan Wars.",
"Wilderness Volcano.",
"Corporeal Beast"
"Corporeal Beast."
),
arrayOf(
Location.create(2899, 3563, 0),
@ -135,10 +138,10 @@ enum class EnchantedJewellery(
),
COMBAT_BRACELET(
arrayOf(
"Champions' Guild",
"Monastery",
"Ranging Guild",
"Warriors' Guild",
"Champions' Guild.",
"Monastery.",
"Ranging Guild.",
"Warriors' Guild.",
"Nowhere."
),
arrayOf(
@ -155,10 +158,10 @@ enum class EnchantedJewellery(
),
SKILLS_NECKLACE(
arrayOf(
"Fishing Guild",
"Mining Guild",
"Crafting Guild",
"Cooking Guild",
"Fishing Guild.",
"Mining Guild.",
"Crafting Guild.",
"Cooking Guild.",
"Nowhere."
),
arrayOf(
@ -175,7 +178,7 @@ enum class EnchantedJewellery(
),
RING_OF_WEALTH(
arrayOf(
"Grand Exchange",
"Grand Exchange.",
"Nowhere."
),
arrayOf(
@ -186,6 +189,13 @@ enum class EnchantedJewellery(
Items.RING_OF_WEALTH2_14642,
Items.RING_OF_WEALTH1_14640,
Items.RING_OF_WEALTH_14638
),
RING_OF_LIFE(arrayOf<String>(),
arrayOf(
Location.create(ServerConstants.HOME_LOCATION)
),
true,
Items.RING_OF_LIFE_2570
);
val isCrumble: Boolean = crumble
@ -199,7 +209,7 @@ enum class EnchantedJewellery(
constructor(options: Array<String>, locations: Array<Location>, vararg ids: Int) : this(options, locations, false, *ids)
/**
* Method used to teleport the player to the desired location.
* Method used when the player "Use"s the jewellery piece.
* @param player the player.
* @param item the used jewellery item.
* @param buttonID the button id.
@ -212,38 +222,52 @@ enum class EnchantedJewellery(
}
return
}
attemptTeleport(player, item, buttonID, isEquipped)
}
/**
* Method used to actually teleport the player to the desired location.
* @param player the player.
* @param item the used jewellery item.
* @param buttonID the button id.
* @param isEquipped If the player is operating.
*/
fun attemptTeleport(player: Player, item: Item, buttonID: Int, isEquipped: Boolean): Boolean {
val itemIndex = getItemIndex(item)
val nextJewellery = Item(getNext(itemIndex))
if (canTeleport(player, nextJewellery)) {
Pulser.submit(object : Pulse(0) {
private var count = 0
private var location = getLocation(buttonID)
override fun pulse(): Boolean {
when (count) {
0 -> {
lock(player,4)
visualize(player, ANIMATION, GRAPHICS)
playAudio(player, AUDIO, true)
player.impactHandler.disabledTicks = 4
}
3 -> {
teleport(player,location)
resetAnimator(player)
if (isLastItemIndex(itemIndex)) {
if (isCrumble) crumbleJewellery(player, item, isEquipped)
} else {
replaceJewellery(player, item, nextJewellery, isEquipped)
}
unlock(player)
player.dispatch(TeleportEvent(TeleportManager.TeleportType.NORMAL, TeleportMethod.JEWELRY, item, location))
return true
}
}
count += 1
return false
}
})
if (!canTeleport(player, nextJewellery)) {
return false
}
Pulser.submit(object : Pulse(0) {
private var count = 0
private var location = getLocation(buttonID)
override fun pulse(): Boolean {
when (count) {
0 -> {
lock(player,4)
visualize(player, ANIMATION, GRAPHICS)
playGlobalAudio(player.location, Sounds.TELEPORT_ALL_200)
player.impactHandler.disabledTicks = 4
closeInterface(player)
}
3 -> {
teleport(player,location)
resetAnimator(player)
if (isLastItemIndex(itemIndex)) {
if (isCrumble) crumbleJewellery(player, item, isEquipped)
} else {
replaceJewellery(player, item, nextJewellery, isEquipped)
}
unlock(player)
player.dispatch(TeleportEvent(TeleportManager.TeleportType.NORMAL, TeleportMethod.JEWELRY, item, location))
return true
}
}
count += 1
return false
}
})
return true
}
private fun replaceJewellery(player: Player, item: Item, nextJewellery: Item, isEquipped: Boolean) {
@ -261,8 +285,11 @@ enum class EnchantedJewellery(
removeItem(player, item)
}
if (isSlayerRing(item)) {
addItem(player, Items.ENCHANTED_GEM_4155)
sendMessage(player, "Your Ring of Slaying reverts back into a regular enchanted gem.")
queueScript(player, 1, QueueStrength.SOFT) {
addItemOrDrop(player, Items.ENCHANTED_GEM_4155)
sendMessage(player, "Your Ring of Slaying reverts back into a regular enchanted gem.")
return@queueScript stopExecuting(player)
}
}
}
@ -274,14 +301,14 @@ enum class EnchantedJewellery(
val slayerManager = getInstance(player)
if (!slayerManager.hasTask()) {
sendNPCDialogue(player, slayerManager.master!!.npc, "You need something new to hunt. Come and " +
"see me When you can and I'll give you a new task.", core.game.dialogue.FacialExpression.HALF_GUILTY)
"see me when you can and I'll give you a new task.", core.game.dialogue.FacialExpression.HALF_GUILTY)
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
setVarbit(player, 2502, 0, slayerManager.flags.taskFlags shr 4)
setVarp(player, 2502, slayerManager.flags.taskFlags shr 4)
}
private fun canTeleport(player: Player, item: Item): Boolean {
@ -325,7 +352,6 @@ enum class EnchantedJewellery(
companion object {
private val ANIMATION = Animation(714)
private val AUDIO = Audio(200)
private val GRAPHICS = Graphics(308, 100, 50)
val idMap = HashMap<Int, EnchantedJewellery>()
@ -335,4 +361,4 @@ enum class EnchantedJewellery(
}
}
}
}
}

View file

@ -3,6 +3,8 @@ package content.data;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import static core.api.ContentAPIKt.hasRequirement;
/**
* A god book.
* @author Vexia
@ -98,6 +100,8 @@ public enum GodBook {
* @param page the page.
*/
public void insertPage(Player player, Item book, Item page) {
if (!hasRequirement(player, Quests.HORROR_FROM_THE_DEEP))
return;
if (hasPage(player, book, page)) {
player.sendMessage("The book already has that page.");
return;

View file

@ -22,6 +22,8 @@ public enum Lamps {
L_ACHIEVEMENT_2(new Item(11186), 1000, 30),
L_ACHIEVEMENT_3(new Item(11187), 1500, 35),
MYSTERIOUS_LAMP(new Item(13227), 10000, 30),
FALLY_ACHIEVEMENT_1(new Item(14580), 1000, 30),
FALLY_ACHIEVEMENT_2(new Item(14581), 5000, 40),
FALLY_ACHIEVEMENT_3(new Item(14582), 10000, 50),

View 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
}
}

View file

@ -2,15 +2,17 @@ package content.data.consumables;
import content.data.consumables.effects.*;
import core.game.consumable.*;
import org.rs09.consts.Items;
import core.game.node.entity.player.link.diary.DiaryType;
import core.game.node.entity.state.EntityState;
import core.game.world.update.flag.context.Animation;
import core.game.node.entity.skill.Skills;
import content.data.consumables.effects.KegOfBeerEffect;
import core.game.world.update.flag.context.Animation;
import org.rs09.consts.Items;
import java.util.ArrayList;
import java.util.HashMap;
import static core.tools.TickUtilsKt.minutesToTicks;
import static core.tools.TickUtilsKt.secondsToTicks;
/**
* Represents a repository of active consumables in the framework.
*/
@ -28,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))),
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 */
@ -108,8 +110,8 @@ public enum Consumables {
MINT_CAKE(new Food(new int[] {9475}, new EnergyEffect(50))),
/** Vegetables */
POTATO(new Food(new int[] {1942}, new HealingEffect(1))),
BAKED_POTATO(new Food(new int[] {6701}, new HealingEffect(2))),
POTATO(new Food(new int[] {1942}, new HealingEffect(1), "You eat the potato. Yuck!")),
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))),
@ -126,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))),
@ -145,16 +147,16 @@ 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))),
PINEAPPLE_RING(new Food(new int[] {2118}, new HealingEffect(2))),
DWELLBERRIES(new Food(new int[] {2126}, new HealingEffect(2))),
JANGERBERRIES(new Food(new int[] {247}, new MultiEffect(new SkillEffect(Skills.ATTACK, 2, 0), new SkillEffect(Skills.STRENGTH, 1, 0), new PrayerEffect(1, 0), new SkillEffect(Skills.DEFENCE, -1, 0)))),
JANGERBERRIES(new Food(new int[] {247}, new MultiEffect(new SkillEffect(Skills.ATTACK, 2, 0), new SkillEffect(Skills.STRENGTH, 1, 0), new PrayerEffect(1, 0), new SkillEffect(Skills.DEFENCE, -1, 0)), "You eat the jangerberries.", "They taste very bitter.")),
STRAWBERRY(new Food(new int[] {5504}, new MultiEffect(new HealingEffect(1), new PercentageHealthEffect(6)))),
TOMATO(new Food(new int[] {1982}, new HealingEffect(2))),
WATERMELON(new FakeConsumable(5982, new String[] {"Try using a knife to slice it into pieces."})),
WATERMELON(new FakeConsumable(5982, new String[] {"You can't eat it whole; maybe you should cut it up."})),
WATERMELON_SLICE(new Food(new int[] {5984}, new PercentageHealthEffect(5))),
LEMON(new Food(new int[] {2102}, new HealingEffect(2))),
LEMON_CHUNKS(new Food(new int[] {2104}, new HealingEffect(2))),
@ -164,11 +166,11 @@ public enum Consumables {
LIME_SLICES(new Food(new int[] {2124}, new HealingEffect(2))),
PEACH(new Food(new int[] {6883}, new HealingEffect(8))),
WHITE_TREE_FRUIT(new Food(new int[] {6469}, new MultiEffect(new RandomEnergyEffect(5, 10), new HealingEffect(3)))),
STRANGE_FRUIT(new Food(new int[] {464}, new MultiEffect(new RemoveStateEffect(EntityState.POISONED.ordinal()), new EnergyEffect(30)))),
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))),
@ -244,40 +246,48 @@ public enum Consumables {
/** Cocktails */
FRUIT_BLAST(new Drink(new int[] {2084, 2026}, new HealingEffect(9))),
PREMADE_FR_BLAST(new Food(new int[] {2034, 2026}, new HealingEffect(9))),
PREMADE_FR_BLAST(new Drink(new int[] {2034, 2026}, new HealingEffect(9))),
CRAFTED_FR_BLAST(new Drink(new int[] {9514, 2026}, new HealingEffect(9))),
PINEAPPLE_PUNCH(new Drink(new int[] {2048, 2026}, new HealingEffect(9), "You drink the cocktail. It tastes great.")),
PREMADE_P_PUNCH(new Drink(new int[] {2036, 2026}, new HealingEffect(9), "You drink the cocktail. It tastes great.")),
CRAFTED_P_PUNCH(new Drink(new int[] {9512, 2026}, new HealingEffect(9))),
WIZARD_BLIZZARD(new Drink(new int[] {2054, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 6, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
PREMADE_WIZ_BLZD(new Drink(new int[] {2040, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 6, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
CRAFTED_WIZ_BLZD(new Drink(new int[]{9508, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 6, 0),new SkillEffect(Skills.ATTACK, -4, 0 )))),
SHORT_GREEN_GUY(new Drink(new int[] {2080, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 4, 0), new SkillEffect(Skills.ATTACK, -3, 0)))),
PREMADE_SGG(new Drink(new int[] {2038, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 4, 0), new SkillEffect(Skills.ATTACK, -3, 0)))),
CRAFTED_SGG(new Drink(new int[]{9510, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 4, 0), new SkillEffect(Skills.ATTACK, -3,0)))),
DRUNK_DRAGON(new Drink(new int[] {2092, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 7, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
PREMADE_DR_DRAGON(new Drink(new int[] {2032, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 7, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
CRAFTED_DR_DRAGON(new Drink(new int[] {9516, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 7, 0), new SkillEffect(Skills.ATTACK, -4,0)))),
CHOC_SATURDAY(new Drink(new int[] {2074, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 7, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
PREMADE_CHOC_SDY(new Drink(new int[] {2030, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 7, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
CRAFTED_CHOC_SDY(new Drink(new int[] {9518, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 7,0), new SkillEffect(Skills.ATTACK, -4,0)))),
BLURBERRY_SPECIAL(new Drink(new int[] {2064, 2026}, new MultiEffect(new HealingEffect(6), new SkillEffect(Skills.STRENGTH, 6, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
PREMADE_BLURB_SP(new Drink(new int[] {2028, 2026}, new MultiEffect(new HealingEffect(6), new SkillEffect(Skills.STRENGTH, 6, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
CRAFTED_BLURB_SP(new Drink(new int[] {9520, 2026}, new MultiEffect(new HealingEffect(6), new SkillEffect(Skills.STRENGTH,6,0), new SkillEffect(Skills.ATTACK, -4,0)))),
/** Bottled Drinks */
KARAMJAN_RUM(new Drink(new int[] {431}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 5, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
BRAINDEATH_RUM(new Drink(new int[] {7157}, new MultiEffect(new SkillEffect(Skills.DEFENCE, 0, -0.1), new SkillEffect(Skills.ATTACK, 0, -0.05), new SkillEffect(Skills.PRAYER, 0, -0.05), new SkillEffect(Skills.RANGE, 0, -0.05), new SkillEffect(Skills.MAGIC, 0, -0.05), new SkillEffect(Skills.HERBLORE, 0, -0.05), new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.MINING, 1, 0)), "With a sense of impending doom you drink the 'rum'. You try very hard not to die.")),
RUM_TROUBLE_BREWING_RED(new Drink(new int[] {8940, 8940}, new TroubleBrewingRumEffect("Oh gods! It tastes like burning!"), new Animation(9605))),
RUM_TROUBLE_BREWING_BLUE(new Drink(new int[] {8941, 8941}, new TroubleBrewingRumEffect("My Liver! My Liver is melting!"), new Animation(9604))),
VODKA(new Drink(new int[] {2015}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.ATTACK, -3, 0)))),
VODKA(new Drink(new int[] {2015}, new MultiEffect(new HealingEffect(2), new SkillEffect(Skills.ATTACK, -4, 0), new SkillEffect(Skills.STRENGTH, 4, 0)))),
GIN(new Drink(new int[] {2019}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 1, 0), new SkillEffect(Skills.ATTACK, 4, 0), new RandomHealthEffect(3, 4)))),
BRANDY(new Drink(new int[] {2021}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.ATTACK, 4, 0)))),
WHISKY(new Drink(new int[] {2017}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
BOTTLE_OF_WINE(new Drink(new int[] {2015, 7921}, new MultiEffect(new HealingEffect(14), new SkillEffect(Skills.ATTACK, -3, 0)))),
BOTTLE_OF_WINE(new Drink(new int[] {7919, 7921}, new MultiEffect(new HealingEffect(14), new SkillEffect(Skills.ATTACK, -3, 0)))),
/** Wine */
JUG_OF_WINE(new Drink(new int[] {1993, 1935}, new MultiEffect(new HealingEffect(11), new SkillEffect(Skills.ATTACK, -2, 0)))),
HALF_FULL_WINE_JUG(new Drink(new int[] {1989, 1935}, new HealingEffect(7))),
JUG_OF_BAD_WINE(new Drink(new int[] {1991,1935}, new SkillEffect(Skills.ATTACK, -3, 0))),
/** Tea */
CUP_OF_TEA(new Drink(new int[] {712, 1980}, new MultiEffect(new HealingEffect(3), new SkillEffect(Skills.ATTACK, 3, 0)), "Aaah, nothing like a nice cuppa tea!")),
CUP_OF_TEA_NETTLE(new Drink(new int[] {4242, 1980}, new EnergyEffect(10))),
CUP_OF_TEA_MILKY_NETTLE(new Drink(new int[] {4243, 1980}, new EnergyEffect(10))),
NETTLE_TEA(new Drink(new int[] {4239, 1980}, new NettleTeaEffect())),
NETTLE_TEA(new Drink(new int[] {4239, 1923}, new NettleTeaEffect())),
NETTLE_TEA_MILKY(new Drink(new int[] {4240, 1980}, new NettleTeaEffect())),
CUP_OF_TEA_CLAY(new Drink(new int[] {7730, 7728}, new SkillEffect(Skills.CONSTRUCTION, 1, 0), "You feel refreshed and ready for more building.")),
CUP_OF_TEA_CLAY_MILKY(new Drink(new int[] {7731, 7728}, new SkillEffect(Skills.CONSTRUCTION, 1, 0))),
@ -297,8 +307,9 @@ 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.")),
/** Special Events */
PUMPKIN(new Food(new int[] {1959}, new HealingEffect(14))),
@ -308,43 +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))),
ANTIPOISON(new Potion(new int[] {2446, 175, 177, 179}, new MultiEffect(new SetAttributeEffect("poison:immunity", 143), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
ANTIPOISON_(new Potion(new int[] {5943, 5945, 5947, 5949}, new MultiEffect(new SetAttributeEffect("poison:immunity", 863), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
ANTIPOISON__(new Potion(new int[] {5952, 5954, 5956, 5958}, new MultiEffect(new SetAttributeEffect("poison:immunity", 2000), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
SUPER_ANTIP(new Potion(new int[] {2448, 181, 183, 185}, new MultiEffect(new SetAttributeEffect("poison:immunity", 1000), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
RELICYM(new Potion(new int[] {4842, 4844, 4846, 4848}, new MultiEffect(new SetAttributeEffect("disease:immunity", 300), new RemoveStateEffect("disease")))),
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 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))),
GUTH_REST(new Potion(new int[] {4417, 4419, 4421, 4423}, new MultiEffect(new RemoveStateEffect(EntityState.POISONED.ordinal()), new EnergyEffect(5), new HealingEffect(5)))),
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 RemoveStateEffect(EntityState.POISONED.ordinal()), new RemoveStateEffect("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 RemoveStateEffect(EntityState.POISONED.ordinal()), new SetAttributeEffect("poison:immunity", 143), new HealingEffect(3)))),
RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new RemoveStateEffect("disease"), new SetAttributeEffect("disease:immunity", 300), 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 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)))),
ENERGY_MIX(new BarbarianMix(new int[] {11453, 11455}, new MultiEffect(new EnergyEffect(10), new HealingEffect(6)))),
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(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)))),
@ -353,6 +365,9 @@ public enum Consumables {
SUPER_ENERGY_MIX(new BarbarianMix(new int[] {11481, 11483}, new MultiEffect(new EnergyEffect(20), new HealingEffect(6)))),
HUNTING_MIX(new BarbarianMix(new int[] {11517, 11519}, new MultiEffect(new SkillEffect(Skills.HUNTER, 3, 0), new HealingEffect(6)))),
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))),
@ -364,24 +379,28 @@ public enum Consumables {
SC_MAGIC(new Potion(new int[] {14267, 14269, 14271, 14273, 14275}, new SkillEffect(Skills.MAGIC, 3, 0.1))),
SC_SUMMONING(new Potion(new int[] {14277, 14279, 14281, 14283, 14285}, new SummoningEffect(7, 0.25)));
public static HashMap<Integer,Consumable> consumables = new HashMap<>();
public static HashMap<Integer,Consumables> consumables = new HashMap<>();
public static ArrayList<Integer> potions = new ArrayList<>();
private final Consumable consumable;
public boolean isIgnoreMainClock = false;
Consumables(Consumable consumable) {
this.consumable = consumable;
}
Consumables(Consumable consumable, boolean isIgnoreMainClock) {this.consumable = consumable; this.isIgnoreMainClock = isIgnoreMainClock;}
public Consumable getConsumable() {
return consumable;
}
public static Consumable getConsumableById(final int itemId) {
public static Consumables getConsumableById(final int itemId) {
return consumables.get(itemId);
}
public static void add(final Consumable consumable) {
for (int id : consumable.getIds()) {
public static void add(final Consumables consumable) {
for (int id : consumable.consumable.getIds()) {
consumables.putIfAbsent(id, consumable);
}
}
@ -391,7 +410,12 @@ public enum Consumables {
*/
static {
for (Consumables consumable : Consumables.values()) {
add(consumable.consumable);
add(consumable);
if (consumable.consumable instanceof Potion) {
for (int pot : consumable.consumable.getIds()) {
potions.add(pot);
}
}
}
}
}

View file

@ -0,0 +1,15 @@
package content.data.consumables.effects
import core.api.registerTimer
import core.api.removeTimer
import core.api.spawnTimer
import core.game.consumable.ConsumableEffect
import core.game.node.entity.player.Player
class AddTimerEffect (val identifier: String, vararg val args: Any) : ConsumableEffect() {
override fun activate (p: Player) {
removeTimer (p, identifier)
val timer = spawnTimer (identifier, *args) ?: return
registerTimer (p, timer)
}
}

View file

@ -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.")
}
}
}
}

View file

@ -1,19 +0,0 @@
package content.data.consumables.effects;
import core.game.consumable.ConsumableEffect;
import core.game.node.entity.player.Player;
import core.game.node.entity.skill.Skills;
public class PrayerEffect extends ConsumableEffect {
double base, bonus;
public PrayerEffect(double base, double bonus){
this.base = base;
this.bonus = bonus;
}
@Override
public void activate(Player p) {
int level = p.getSkills().getStaticLevel(Skills.PRAYER);
double amt = base + (level * bonus);
p.getSkills().incrementPrayerPoints(amt);
}
}

View file

@ -0,0 +1,20 @@
package content.data.consumables.effects
import core.api.*
import core.game.consumable.ConsumableEffect
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import org.rs09.consts.Items
import kotlin.math.floor
class PrayerEffect(var base: Double, var bonus: Double) : ConsumableEffect() {
override fun activate(player: Player?) {
if(player == null) return
val level = getStatLevel(player, Skills.PRAYER)
var b = bonus
if(inInventory(player, Items.HOLY_WRENCH_6714))
b += 0.02 // Leaving this in for futureproofing. Current update is for properly rounding down.
val amount = floor(base + (level * b))
modPrayerPoints(player, amount)
}
}

View file

@ -1,25 +0,0 @@
package content.data.consumables.effects;
import core.game.consumable.ConsumableEffect;
import core.game.node.entity.player.Player;
import core.game.node.entity.state.EntityState;
public class RemoveStateEffect extends ConsumableEffect {
int state = -1;
String statekey;
@Deprecated
public RemoveStateEffect(int state){
this.state = state;
}
public RemoveStateEffect(String key){
statekey = key;
}
@Override
public void activate(Player p) {
if(state == -1){
p.clearState(statekey);
return;
}
p.getStateManager().remove(EntityState.values()[state]);
}
}

View file

@ -0,0 +1,11 @@
package content.data.consumables.effects
import core.api.*
import core.game.consumable.ConsumableEffect
import core.game.node.entity.player.Player
class RemoveTimerEffect (val identifier: String) : ConsumableEffect() {
override fun activate (p: Player) {
removeTimer (p, identifier)
}
}

View file

@ -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);
}
}
}

View file

@ -3,13 +3,13 @@ package content.data.tables;
import core.api.StartupListener;
import core.game.node.item.Item;
import core.game.node.item.WeightedChanceItem;
import core.tools.Log;
import core.tools.RandomFunction;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import core.ServerConstants;
import core.tools.SystemLogger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@ -18,7 +18,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static core.tools.SystemLogger.logInfo;
import static core.api.ContentAPIKt.log;
/**
* Handles the allotment seed drop table.
@ -57,11 +57,11 @@ public final class AllotmentSeedDropTable implements StartupListener {
@Override
public void startup() {
if(ServerConstants.ASDT_DATA_PATH != null && !new File(ServerConstants.ASDT_DATA_PATH).exists()){
SystemLogger.logErr(this.getClass(), "Can't locate ASDT file at " + ServerConstants.ASDT_DATA_PATH);
log(this.getClass(), Log.ERR, "Can't locate ASDT file at " + ServerConstants.ASDT_DATA_PATH);
return;
}
parse(ServerConstants.ASDT_DATA_PATH);
logInfo(this.getClass(), "Initialized Allotment Seed Drop Table from " + ServerConstants.ASDT_DATA_PATH);
log(this.getClass(), Log.FINE, "Initialized Allotment Seed Drop Table from " + ServerConstants.ASDT_DATA_PATH);
}
/**

View file

@ -8,6 +8,9 @@ import core.game.node.item.GroundItemManager;
import core.game.node.item.Item;
import core.tools.RandomFunction;
import core.tools.StringUtils;
import org.rs09.consts.Sounds;
import static core.api.ContentAPIKt.playAudio;
/**
* Represents a birds nest.
@ -93,7 +96,7 @@ public enum BirdNest {
*/
public static void drop(final Player player) {
final BirdNest nest = getRandomNest(false);
player.getAudioManager().send(1997);
playAudio(player, Sounds.CUCKOO_1_1997);
GroundItemManager.create(nest.getNest(), player);
player.getPacketDispatch().sendMessage("<col=FF0000>A bird's nest falls out of the tree.");
}

View file

@ -4,7 +4,7 @@ import core.api.StartupListener;
import core.ServerConstants;
import core.game.node.item.Item;
import core.game.node.item.WeightedChanceItem;
import core.tools.SystemLogger;
import core.tools.Log;
import core.tools.RandomFunction;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@ -18,7 +18,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static core.tools.SystemLogger.logInfo;
import static core.api.ContentAPIKt.log;
/**
* Handles the Chaos Elemental's minor drop table. It is supposed to roll this table alongside its standard major drops on the main table.
@ -57,11 +57,11 @@ public final class CELEMinorTable implements StartupListener {
@Override
public void startup() {
if(ServerConstants.CELEDT_DATA_PATH != null && !new File(ServerConstants.CELEDT_DATA_PATH).exists()){
SystemLogger.logErr(this.getClass(), "Can't locate CELEDT file at " + ServerConstants.CELEDT_DATA_PATH);
log(this.getClass(), Log.ERR, "Can't locate CELEDT file at " + ServerConstants.CELEDT_DATA_PATH);
return;
}
parse(ServerConstants.CELEDT_DATA_PATH);
logInfo(this.getClass(), "Loaded up Chaos Elemental drop table from " + ServerConstants.CELEDT_DATA_PATH);
log(this.getClass(), Log.FINE, "Loaded up Chaos Elemental drop table from " + ServerConstants.CELEDT_DATA_PATH);
}
/**

View file

@ -3,13 +3,13 @@ package content.data.tables;
import core.api.StartupListener;
import core.game.node.item.Item;
import core.game.node.item.WeightedChanceItem;
import core.tools.Log;
import core.tools.RandomFunction;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import core.ServerConstants;
import core.tools.SystemLogger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@ -18,7 +18,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static core.tools.SystemLogger.logInfo;
import static core.api.ContentAPIKt.log;
/**
* Handles the gem drop table.
@ -57,11 +57,11 @@ public final class GemDropTable implements StartupListener {
@Override
public void startup() {
if(ServerConstants.GDT_DATA_PATH != null && !new File(ServerConstants.GDT_DATA_PATH).exists()){
SystemLogger.logErr(this.getClass(), "Can't locate GDT file at " + ServerConstants.GDT_DATA_PATH);
log(this.getClass(), Log.ERR, "Can't locate GDT file at " + ServerConstants.GDT_DATA_PATH);
return;
}
parse(ServerConstants.GDT_DATA_PATH);
logInfo(this.getClass(), "Initialized Gem Drop Table from " + ServerConstants.GDT_DATA_PATH);
log(this.getClass(), Log.FINE, "Initialized Gem Drop Table from " + ServerConstants.GDT_DATA_PATH);
}
/**

View file

@ -3,13 +3,13 @@ package content.data.tables;
import core.api.StartupListener;
import core.game.node.item.Item;
import core.game.node.item.WeightedChanceItem;
import core.tools.Log;
import core.tools.RandomFunction;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import core.ServerConstants;
import core.tools.SystemLogger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@ -18,7 +18,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static core.tools.SystemLogger.logInfo;
import static core.api.ContentAPIKt.log;
/**
* Handles the herb drop table.
@ -57,11 +57,11 @@ public final class HerbDropTable implements StartupListener {
@Override
public void startup() {
if(ServerConstants.HDT_DATA_PATH != null && !new File(ServerConstants.HDT_DATA_PATH).exists()){
SystemLogger.logErr(this.getClass(), "Can't locate HDT file at " + ServerConstants.HDT_DATA_PATH);
log(this.getClass(), Log.ERR, "Can't locate HDT file at " + ServerConstants.HDT_DATA_PATH);
return;
}
parse(ServerConstants.HDT_DATA_PATH);
logInfo(this.getClass(), "Initialized Herb Drop Table from " + ServerConstants.HDT_DATA_PATH);
log(this.getClass(), Log.FINE, "Initialized Herb Drop Table from " + ServerConstants.HDT_DATA_PATH);
}
/**

View file

@ -2,15 +2,15 @@ package content.data.tables
import core.ServerConstants
import core.api.StartupListener
import core.api.log
import core.api.shouldRemoveNothings
import core.api.utils.WeightBasedTable
import core.api.utils.WeightedItem
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.tools.Log
import core.tools.RandomFunction
import core.tools.SystemLogger.logErr
import core.tools.SystemLogger.logInfo
import org.rs09.consts.Items
import org.w3c.dom.Element
import org.w3c.dom.Node
@ -26,11 +26,11 @@ import javax.xml.parsers.ParserConfigurationException
class RareDropTable : StartupListener {
override fun startup() {
if (ServerConstants.RDT_DATA_PATH != null && !File(ServerConstants.RDT_DATA_PATH).exists()) {
logErr(this.javaClass, "Can't locate RDT file at " + ServerConstants.RDT_DATA_PATH)
log(this::class.java, Log.ERR, "Can't locate RDT file at " + ServerConstants.RDT_DATA_PATH)
return
}
parse(ServerConstants.RDT_DATA_PATH)
logInfo(this.javaClass, "Initialized Rare Drop Table from " + ServerConstants.RDT_DATA_PATH)
log(this::class.java, Log.FINE, "Initialized Rare Drop Table from " + ServerConstants.RDT_DATA_PATH)
}
companion object {

View file

@ -3,13 +3,13 @@ package content.data.tables;
import core.api.StartupListener;
import core.game.node.item.Item;
import core.game.node.item.WeightedChanceItem;
import core.tools.Log;
import core.tools.RandomFunction;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import core.ServerConstants;
import core.tools.SystemLogger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@ -18,7 +18,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static core.tools.SystemLogger.logInfo;
import static core.api.ContentAPIKt.log;
/**
* Handles the rare seed drop table.
@ -57,11 +57,11 @@ public final class RareSeedDropTable implements StartupListener {
@Override
public void startup() {
if(ServerConstants.RSDT_DATA_PATH != null && !new File(ServerConstants.RSDT_DATA_PATH).exists()){
SystemLogger.logErr(this.getClass(), "Can't locate RSDT file at " + ServerConstants.RSDT_DATA_PATH);
log(this.getClass(), Log.ERR, "Can't locate RSDT file at " + ServerConstants.RSDT_DATA_PATH);
return;
}
parse(ServerConstants.RSDT_DATA_PATH);
logInfo(this.getClass(), "Initialized Rare Seed Drop Table from " + ServerConstants.RSDT_DATA_PATH);
log(this.getClass(), Log.FINE, "Initialized Rare Seed Drop Table from " + ServerConstants.RSDT_DATA_PATH);
}
/**

View file

@ -3,13 +3,13 @@ package content.data.tables;
import core.api.StartupListener;
import core.game.node.item.Item;
import core.game.node.item.WeightedChanceItem;
import core.tools.Log;
import core.tools.RandomFunction;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import core.ServerConstants;
import core.tools.SystemLogger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@ -18,7 +18,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static core.tools.SystemLogger.logInfo;
import static core.api.ContentAPIKt.log;
/**
* Handles the uncommon seed drop table.
@ -57,11 +57,11 @@ public final class UncommonSeedDropTable implements StartupListener {
@Override
public void startup() {
if(ServerConstants.USDT_DATA_PATH != null && !new File(ServerConstants.USDT_DATA_PATH).exists()){
SystemLogger.logErr(this.getClass(), "Can't locate USDT file at " + ServerConstants.USDT_DATA_PATH);
log(this.getClass(), Log.ERR, "Can't locate USDT file at " + ServerConstants.USDT_DATA_PATH);
return;
}
parse(ServerConstants.USDT_DATA_PATH);
logInfo(this.getClass(), "Initialized Uncommon Seed Drop Table from " + ServerConstants.USDT_DATA_PATH);
log(this.getClass(), Log.FINE, "Initialized Uncommon Seed Drop Table from " + ServerConstants.USDT_DATA_PATH);
}
/**

View file

@ -0,0 +1,229 @@
package content.global.activity.cchallange
import content.global.activity.cchallange.npc.EarthWarriorChampionNPC.Companion.spawnEarthWarriorChampion
import content.global.activity.cchallange.npc.GhoulChampionNPC.Companion.spawnGhoulChampion
import content.global.activity.cchallange.npc.GiantChampionNPC.Companion.spawnGiantChampion
import content.global.activity.cchallange.npc.GoblinChampionNPC.Companion.spawnGoblinChampion
import content.global.activity.cchallange.npc.HobgoblinChampionNPC.Companion.spawnHobgoblinChampion
import content.global.activity.cchallange.npc.ImpChampionNPC.Companion.spawnImpChampion
import content.global.activity.cchallange.npc.JogreChampionNPC.Companion.spawnJogreChampion
import content.global.activity.cchallange.npc.LesserDemonChampionNPC.Companion.spawnLesserDemonChampion
import content.global.activity.cchallange.npc.SkeletonChampionNPC.Companion.spawnSkeletonChampion
import content.global.activity.cchallange.npc.ZombieChampionNPC.Companion.spawnZombieChampion
import core.api.*
import core.game.global.action.DoorActionHandler
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.player.Player
import core.game.node.item.Item
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
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
/**
* Represents the Champion challenge.
*/
class ChampionChallengeListener : InteractionListener, MapArea {
val EARTH_WARRIOR_SCROLL = Items.CHAMPION_SCROLL_6798
val GHOUL_SCROLL = Items.CHAMPION_SCROLL_6799
val GIANT_SCROLL = Items.CHAMPION_SCROLL_6800
val GOBLIN_SCROLL = Items.CHAMPION_SCROLL_6801
val HOBGOBLIN_SCROLL = Items.CHAMPION_SCROLL_6802
val IMP_SCROLL = Items.CHAMPION_SCROLL_6803
val JOGRE_SCROLL = Items.CHAMPION_SCROLL_6804
val LESSER_DEMON_SCROLL = Items.CHAMPION_SCROLL_6805
val SKELETON_SCROLL = Items.CHAMPION_SCROLL_6806
val ZOMBIE_SCROLL = Items.CHAMPION_SCROLL_6807
val MESSAGE_SCROLL = 222
private val IMP_SCROLL_TEXT = arrayOf(
"How about picking on someone your own size? I'll",
"see you at the Champion's Guild.",
"",
"Champion of Imps"
)
private val GOBLIN_SCROLL_TEXT = arrayOf(
"Fight me if you think you can human, I'll wait",
"for you in the Champion's Guild.",
"",
"Champion of Goblins"
)
private val SKELETON_SCROLL_TEXT = arrayOf(
"I'll be waiting at the Champions' Guild to",
"collect your bones.",
"",
"Champion of Skeletons"
)
private val ZOMBIE_SCROLL_TEXT = arrayOf(
"You come to Champions' Guild, you fight me,",
"I squish you, I get brains!",
"",
"Champion of Zombies"
)
private val GIANT_SCROLL_TEXT = arrayOf(
"Get yourself to the Champions' Guild, if you",
"dare to face me puny human.",
"",
"Champion of Giants"
)
private val HOBGOBLIN_SCROLL_TEXT = arrayOf(
"You won't defeat me, though you're welcome to",
"try at the Champions' Guild.",
"",
"Champion of Hobgoblins"
)
private val GHOUL_SCROLL_TEXT = arrayOf(
"Come and duel me at the Champions' Guild, I'll",
"make sure nothing goes to waste.",
"",
"Champion of Ghouls"
)
private val EARTH_WARRIOR_TEXT = arrayOf(
"I challenge you to a duel, come to the arena beneath",
"the Champion's Guild and fight me if you dare.",
"",
"Champion of Earth Warriors"
)
private val JOGRE_SCROLL_TEXT = arrayOf(
"You think you can defeat me? Come to the",
"Champion's Guild and prove it!",
"",
"Champion of Jogres"
)
private val LESSER_DEMON_SCROLL_TEXT = arrayOf(
"Come to the Champion's Guild so I can banish",
"you mortal!",
"",
"Champion of Lesser Demons"
)
private val PORTCULLIS = Scenery.PORTCULLIS_10553
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
private val TRAPDOOR_OPEN = Scenery.TRAPDOOR_10559
private val LARXUS = NPCs.LARXUS_3050
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
}
on(ChampionScrollsDropHandler.SCROLLS, IntType.ITEM, "read") { player, node ->
updateAndReadScroll(player, node.asItem())
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, -1, node.location)
return@on true
}
on(CHAMPION_STATUE_CLOSED, IntType.SCENERY, "open") { _, node ->
replaceScenery(node.asScenery(), CHAMPION_STATUE_OPEN, 100, node.location)
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.")
} else {
lock(player, 3)
submitWorldPulse(object : Pulse() {
var counter = 0
override fun pulse(): Boolean {
when (counter++) {
1 -> {
player.familiarManager.dismiss()
}
2 -> DoorActionHandler.handleDoor(player, node.asScenery())
3 -> when{
removeItem(player, IMP_SCROLL) -> spawnImpChampion(player)
removeItem(player, GOBLIN_SCROLL) -> spawnGoblinChampion(player)
removeItem(player, SKELETON_SCROLL) -> spawnSkeletonChampion(player)
removeItem(player, ZOMBIE_SCROLL) -> spawnZombieChampion(player)
removeItem(player, GIANT_SCROLL) -> spawnGiantChampion(player)
removeItem(player, HOBGOBLIN_SCROLL) -> spawnHobgoblinChampion(player)
removeItem(player, GHOUL_SCROLL) -> spawnGhoulChampion(player)
removeItem(player, EARTH_WARRIOR_SCROLL) -> {
spawnEarthWarriorChampion(player)
player.prayer.reset()
}
removeItem(player, JOGRE_SCROLL) -> spawnJogreChampion(player)
removeItem(player, LESSER_DEMON_SCROLL) -> spawnLesserDemonChampion(player)
}
}
return false
}
})
}
return@on true
}
}
private fun updateAndReadScroll(player: Player, item: Item) {
val id = item.id
openInterface(player, MESSAGE_SCROLL).also {
when (id) {
IMP_SCROLL -> setInterfaceText(player, IMP_SCROLL_TEXT.joinToString("<br>"), MESSAGE_SCROLL, 4)
GOBLIN_SCROLL -> setInterfaceText(player, GOBLIN_SCROLL_TEXT.joinToString("<br>"), MESSAGE_SCROLL, 4)
SKELETON_SCROLL -> setInterfaceText(player, SKELETON_SCROLL_TEXT.joinToString("<br>"), MESSAGE_SCROLL, 4)
ZOMBIE_SCROLL -> setInterfaceText(player, ZOMBIE_SCROLL_TEXT.joinToString("<br>"), MESSAGE_SCROLL, 4)
GIANT_SCROLL -> setInterfaceText(player, GIANT_SCROLL_TEXT.joinToString("<br>"), MESSAGE_SCROLL, 4)
HOBGOBLIN_SCROLL -> setInterfaceText(player, HOBGOBLIN_SCROLL_TEXT.joinToString("<br>"), MESSAGE_SCROLL, 4)
GHOUL_SCROLL -> setInterfaceText(player, GHOUL_SCROLL_TEXT.joinToString("<br>"), MESSAGE_SCROLL, 4)
EARTH_WARRIOR_SCROLL -> setInterfaceText(player, EARTH_WARRIOR_TEXT.joinToString("<br>"), MESSAGE_SCROLL, 4)
JOGRE_SCROLL -> setInterfaceText(player, JOGRE_SCROLL_TEXT.joinToString("<br>"), MESSAGE_SCROLL, 4)
LESSER_DEMON_SCROLL -> setInterfaceText(player, LESSER_DEMON_SCROLL_TEXT.joinToString("<br>"), MESSAGE_SCROLL, 4)
}
}
}
override fun defineAreaBorders(): Array<ZoneBorders> {
return arrayOf(getRegionBorders(ARENA_ZONE))
}
override fun getRestrictions(): Array<ZoneRestriction> {
return arrayOf(
ZoneRestriction.CANNON,
ZoneRestriction.FIRES,
ZoneRestriction.RANDOM_EVENTS
)
}
}

View file

@ -0,0 +1,279 @@
package content.global.activity.cchallange
import core.api.sendMessage
import core.api.sendNews
import core.game.event.NPCKillEvent
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.item.GroundItemManager
import core.game.node.item.Item
import core.tools.*
import core.game.world.GameWorld
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Handles the drop for champion challenge.
* @authors Phil, Skelsoft, Ceikry
*/
class ChampionScrollsDropHandler : ChampionScrollsEventHookBase() {
companion object {
private val IMPS = intArrayOf(
NPCs.IMP_708, NPCs.IMP_709, NPCs.IMP_1531, NPCs.IMP_6211
)
private val GOBLINS = intArrayOf(
NPCs.GOBLIN_100, NPCs.GOBLIN_101, NPCs.GOBLIN_102, NPCs.GOBLIN_444, NPCs.GOBLIN_445,
NPCs.GOBLIN_1769, NPCs.GOBLIN_1770, NPCs.GOBLIN_1771, NPCs.GOBLIN_1772, NPCs.GOBLIN_1773,
NPCs.GOBLIN_1774, NPCs.GOBLIN_1775, NPCs.GOBLIN_1776, NPCs.GOBLIN_2274, NPCs.GOBLIN_2275,
NPCs.GOBLIN_2276, NPCs.GOBLIN_2277, NPCs.GOBLIN_2278, NPCs.GOBLIN_2279, NPCs.GOBLIN_2280,
NPCs.GOBLIN_2281, NPCs.GOBLIN_2678, NPCs.GOBLIN_2679, NPCs.GOBLIN_2680, NPCs.GOBLIN_2681,
NPCs.GOBLIN_3264, NPCs.GOBLIN_3265, NPCs.GOBLIN_3266, NPCs.GOBLIN_3267, NPCs.GOBLIN_3726,
NPCs.GOBLIN_4261, NPCs.GOBLIN_4262, NPCs.GOBLIN_4263, NPCs.GOBLIN_4264, NPCs.GOBLIN_4265,
NPCs.GOBLIN_4266, NPCs.GOBLIN_4267, NPCs.GOBLIN_4268, NPCs.GOBLIN_4269, NPCs.GOBLIN_4270,
NPCs.GOBLIN_4271, NPCs.GOBLIN_4272, NPCs.GOBLIN_4273, NPCs.GOBLIN_4274, NPCs.GOBLIN_4275,
NPCs.GOBLIN_4276, NPCs.GOBLIN_4407, NPCs.GOBLIN_4408, NPCs.GOBLIN_4409, NPCs.GOBLIN_4410,
NPCs.GOBLIN_4411, NPCs.GOBLIN_4412, NPCs.GOBLIN_4479, NPCs.GOBLIN_4480, NPCs.GOBLIN_4481,
NPCs.GOBLIN_4482, NPCs.GOBLIN_4483, NPCs.GOBLIN_4484, NPCs.GOBLIN_4485, NPCs.GOBLIN_4486,
NPCs.GOBLIN_4487, NPCs.GOBLIN_4488, NPCs.GOBLIN_4489, NPCs.GOBLIN_4490, NPCs.GOBLIN_4491,
NPCs.GOBLIN_4492, NPCs.GOBLIN_4499, NPCs.GOBLIN_4633, NPCs.GOBLIN_4634, NPCs.GOBLIN_4635,
NPCs.GOBLIN_4636, NPCs.GOBLIN_4637, NPCs.GOBLIN_5855, NPCs.GOBLIN_5856, NPCs.GOBLIN_6125,
NPCs.GOBLIN_6126, NPCs.GOBLIN_6132, NPCs.GOBLIN_6133, NPCs.GOBLIN_6279, NPCs.GOBLIN_6280,
NPCs.GOBLIN_6281, NPCs.GOBLIN_6282, NPCs.GOBLIN_6283, NPCs.GOBLIN_6284, NPCs.GOBLIN_6402,
NPCs.GOBLIN_6403, NPCs.GOBLIN_6404, NPCs.GOBLIN_6405, NPCs.GOBLIN_6406, NPCs.GOBLIN_6407,
NPCs.GOBLIN_6408, NPCs.GOBLIN_6409, NPCs.GOBLIN_6410, NPCs.GOBLIN_6411, NPCs.GOBLIN_6412,
NPCs.GOBLIN_6413, NPCs.GOBLIN_6414, NPCs.GOBLIN_6415, NPCs.GOBLIN_6416, NPCs.GOBLIN_6417,
NPCs.GOBLIN_6418, NPCs.GOBLIN_6419, NPCs.GOBLIN_6420, NPCs.GOBLIN_6421, NPCs.GOBLIN_6422,
NPCs.GOBLIN_6423, NPCs.GOBLIN_6424, NPCs.GOBLIN_6425, NPCs.GOBLIN_6426, NPCs.GOBLIN_6427,
NPCs.GOBLIN_6428, NPCs.GOBLIN_6429, NPCs.GOBLIN_6430, NPCs.GOBLIN_6431, NPCs.GOBLIN_6432,
NPCs.GOBLIN_6433, NPCs.GOBLIN_6434, NPCs.GOBLIN_6435, NPCs.GOBLIN_6436, NPCs.GOBLIN_6437,
NPCs.GOBLIN_6438, NPCs.GOBLIN_6439, NPCs.GOBLIN_6440, NPCs.GOBLIN_6441, NPCs.GOBLIN_6442,
NPCs.GOBLIN_6443, NPCs.GOBLIN_6444, NPCs.GOBLIN_6445, NPCs.GOBLIN_6446, NPCs.GOBLIN_6447,
NPCs.GOBLIN_6448, NPCs.GOBLIN_6449, NPCs.GOBLIN_6450, NPCs.GOBLIN_6451, NPCs.GOBLIN_6452,
NPCs.GOBLIN_6453, NPCs.GOBLIN_6454, NPCs.GOBLIN_6455, NPCs.GOBLIN_6456, NPCs.GOBLIN_6457,
NPCs.GOBLIN_6458, NPCs.GOBLIN_6459, NPCs.GOBLIN_6460, NPCs.GOBLIN_6461, NPCs.GOBLIN_6462,
NPCs.GOBLIN_6463, NPCs.GOBLIN_6464, NPCs.GOBLIN_6465, NPCs.GOBLIN_6466, NPCs.GOBLIN_6467,
NPCs.GOBLIN_6490, NPCs.GOBLIN_6491, NPCs.GOBLIN_6492, NPCs.GOBLIN_6493, NPCs.GOBLIN_6494,
NPCs.GOBLIN_6495, NPCs.GOBLIN_7964, NPCs.GOBLIN_7965,
NPCs.CAVE_GOBLIN_1822, NPCs.CAVE_GOBLIN_1823, NPCs.CAVE_GOBLIN_1824, NPCs.CAVE_GOBLIN_1825,
NPCs.CAVE_GOBLIN_5752, NPCs.CAVE_GOBLIN_5753, NPCs.CAVE_GOBLIN_5754, NPCs.CAVE_GOBLIN_5755,
NPCs.CAVE_GOBLIN_5756, NPCs.CAVE_GOBLIN_5757, NPCs.CAVE_GOBLIN_5758, NPCs.CAVE_GOBLIN_5759,
NPCs.CAVE_GOBLIN_5760, NPCs.CAVE_GOBLIN_5761, NPCs.CAVE_GOBLIN_5762, NPCs.CAVE_GOBLIN_5763,
NPCs.CAVE_GOBLIN_5764, NPCs.CAVE_GOBLIN_5765, NPCs.CAVE_GOBLIN_5766, NPCs.CAVE_GOBLIN_5767,
NPCs.CAVE_GOBLIN_5768, NPCs.CAVE_GOBLIN_5769, NPCs.CAVE_GOBLIN_5783, NPCs.CAVE_GOBLIN_5785,
NPCs.CAVE_GOBLIN_5873, NPCs.CAVE_GOBLIN_5874, NPCs.CAVE_GOBLIN_5875, NPCs.CAVE_GOBLIN_5876,
NPCs.CAVE_GOBLIN_5877, NPCs.CAVE_GOBLIN_5878, NPCs.CAVE_GOBLIN_8451,
NPCs.CAVE_GOBLIN_GUARD_2073, NPCs.CAVE_GOBLIN_GUARD_2074,
NPCs.GOBLIN_GUARD_489, NPCs.GOBLIN_GUARD_6496, NPCs.GOBLIN_GUARD_6497,
NPCs.SERGEANT_GRIMSPIKE_6265,
NPCs.SERGEANT_STEELWILL_6263,
NPCs.SERGEANT_STRONGSTACK_6261
)
private val SKELETONS = intArrayOf(
NPCs.SKELETON_90, NPCs.SKELETON_91, NPCs.SKELETON_92, NPCs.SKELETON_93,
NPCs.SKELETON_459,
NPCs.SKELETON_1471, NPCs.SKELETON_2036, NPCs.SKELETON_2037, NPCs.SKELETON_2715,
NPCs.SKELETON_3151, NPCs.SKELETON_3152, NPCs.SKELETON_3291, NPCs.SKELETON_3581,
NPCs.SKELETON_4384, NPCs.SKELETON_4385, NPCs.SKELETON_4386, NPCs.SKELETON_5332,
NPCs.SKELETON_5333, NPCs.SKELETON_5334, NPCs.SKELETON_5335, NPCs.SKELETON_5336,
NPCs.SKELETON_5337, NPCs.SKELETON_5338, NPCs.SKELETON_5339, NPCs.SKELETON_5340,
NPCs.SKELETON_5341, NPCs.SKELETON_5365, NPCs.SKELETON_5366, NPCs.SKELETON_5367,
NPCs.SKELETON_5368, NPCs.SKELETON_5381, NPCs.SKELETON_5385, NPCs.SKELETON_5386,
NPCs.SKELETON_5387, NPCs.SKELETON_5388, NPCs.SKELETON_5389, NPCs.SKELETON_5390,
NPCs.SKELETON_5391, NPCs.SKELETON_5392, NPCs.SKELETON_5411, NPCs.SKELETON_5412,
NPCs.SKELETON_5422, NPCs.SKELETON_5423, NPCs.SKELETON_6091, NPCs.SKELETON_6092,
NPCs.SKELETON_6093, NPCs.SKELETON_6764, NPCs.SKELETON_6765, NPCs.SKELETON_6766,
NPCs.SKELETON_6767, NPCs.SKELETON_6768, NPCs.SKELETON_7774, NPCs.SKELETON_7775,
NPCs.SKELETON_7776, NPCs.SKELETON_7777, NPCs.SKELETON_7778, NPCs.SKELETON_7779,
NPCs.SKELETON_7788, NPCs.SKELETON_7815, NPCs.GIANT_SKELETON_1973,
NPCs.GIANT_SKELETON_5359, NPCs.GIANT_SKELETON_5384, NPCs.SKELETON_HELLHOUND_1575,
NPCs.SKELETON_MAGE_94, NPCs.SKELETON_MAGE_2717, NPCs.SKELETON_MAGE_3844,
NPCs.SKELETON_MAGE_3850, NPCs.SKELETON_MAGE_3851,
NPCs.SKELETON_HERO_6103, NPCs.SKELETON_BRUTE_6104, NPCs.SKELETON_WARLORD_6105,
NPCs.SKELETON_HEAVY_6106, NPCs.SKELETON_THUG_6107,
NPCs.NAZASTAROOL_508,
NPCs.UNDEAD_ONE_5353, NPCs.UNDEAD_ONE_5354, NPCs.UNDEAD_ONE_5355,
NPCs.UNDEAD_ONE_5356, NPCs.UNDEAD_ONE_5357, NPCs.UNDEAD_ONE_5358,
)
private val ZOMBIES = intArrayOf(
NPCs.ZOMBIE_73, NPCs.ZOMBIE_74, NPCs.ZOMBIE_75, NPCs.ZOMBIE_76, NPCs.ZOMBIE_419,
NPCs.ZOMBIE_420, NPCs.ZOMBIE_421, NPCs.ZOMBIE_422, NPCs.ZOMBIE_423, NPCs.ZOMBIE_424,
NPCs.ZOMBIE_1826, NPCs.ZOMBIE_2714, NPCs.ZOMBIE_2863, NPCs.ZOMBIE_2866, NPCs.ZOMBIE_2869,
NPCs.ZOMBIE_2878, NPCs.ZOMBIE_3622, NPCs.ZOMBIE_3623, NPCs.ZOMBIE_4392, NPCs.ZOMBIE_4393,
NPCs.ZOMBIE_4394, NPCs.ZOMBIE_5293, NPCs.ZOMBIE_5294, NPCs.ZOMBIE_5295, NPCs.ZOMBIE_5296,
NPCs.ZOMBIE_5297, NPCs.ZOMBIE_5298, NPCs.ZOMBIE_5299, NPCs.ZOMBIE_5300, NPCs.ZOMBIE_5301,
NPCs.ZOMBIE_5302, NPCs.ZOMBIE_5303, NPCs.ZOMBIE_5304, NPCs.ZOMBIE_5305, NPCs.ZOMBIE_5306,
NPCs.ZOMBIE_5307, NPCs.ZOMBIE_5308, NPCs.ZOMBIE_5309, NPCs.ZOMBIE_5310, NPCs.ZOMBIE_5311,
NPCs.ZOMBIE_5312, NPCs.ZOMBIE_5313, NPCs.ZOMBIE_5314, NPCs.ZOMBIE_5315, NPCs.ZOMBIE_5316,
NPCs.ZOMBIE_5317, NPCs.ZOMBIE_5318, NPCs.ZOMBIE_5319, NPCs.ZOMBIE_5320, NPCs.ZOMBIE_5321,
NPCs.ZOMBIE_5322, NPCs.ZOMBIE_5323, NPCs.ZOMBIE_5324, NPCs.ZOMBIE_5325, NPCs.ZOMBIE_5326,
NPCs.ZOMBIE_5327, NPCs.ZOMBIE_5328, NPCs.ZOMBIE_5329, NPCs.ZOMBIE_5330, NPCs.ZOMBIE_5331,
NPCs.ZOMBIE_5375, NPCs.ZOMBIE_5376, NPCs.ZOMBIE_5377, NPCs.ZOMBIE_5378, NPCs.ZOMBIE_5379,
NPCs.ZOMBIE_5380, NPCs.ZOMBIE_5393, NPCs.ZOMBIE_5394, NPCs.ZOMBIE_5395, NPCs.ZOMBIE_5396,
NPCs.ZOMBIE_5397, NPCs.ZOMBIE_5398, NPCs.ZOMBIE_5399, NPCs.ZOMBIE_5400, NPCs.ZOMBIE_5401,
NPCs.ZOMBIE_5402, NPCs.ZOMBIE_5403, NPCs.ZOMBIE_5404, NPCs.ZOMBIE_5405, NPCs.ZOMBIE_5406,
NPCs.ZOMBIE_5407, NPCs.ZOMBIE_5408, NPCs.ZOMBIE_5409, NPCs.ZOMBIE_5410, NPCs.ZOMBIE_6099,
NPCs.ZOMBIE_6100, NPCs.ZOMBIE_6131, NPCs.ZOMBIE_7789, NPCs.ZOMBIE_7790, NPCs.ZOMBIE_7791,
NPCs.ZOMBIE_7792, NPCs.ZOMBIE_7817, NPCs.ZOMBIE_7818, NPCs.ZOMBIE_7819, NPCs.ZOMBIE_7820,
NPCs.ZOMBIE_8142, NPCs.ZOMBIE_8143, NPCs.ZOMBIE_8144, NPCs.ZOMBIE_8145,
NPCs.ZOMBIE_PIRATE_2837, NPCs.ZOMBIE_PIRATE_2838, NPCs.ZOMBIE_PIRATE_2839,
NPCs.ZOMBIE_PIRATE_2840, NPCs.ZOMBIE_PIRATE_2841, NPCs.ZOMBIE_PIRATE_2842,
NPCs.ZOMBIE_PIRATE_5629, NPCs.ZOMBIE_PIRATE_5630, NPCs.ZOMBIE_PIRATE_5631,
NPCs.ZOMBIE_PIRATE_5632, NPCs.ZOMBIE_PIRATE_5633, NPCs.ZOMBIE_PIRATE_5634,
NPCs.ZOMBIE_PIRATE_5635, NPCs.ZOMBIE_PIRATE_5636, NPCs.ZOMBIE_PIRATE_5637,
NPCs.ZOMBIE_PIRATE_5638, NPCs.ZOMBIE_PIRATE_5639, NPCs.ZOMBIE_PIRATE_5640,
NPCs.ZOMBIE_PIRATE_5641, NPCs.ZOMBIE_PIRATE_5642, NPCs.ZOMBIE_PIRATE_5643,
NPCs.ZOMBIE_PIRATE_5644, NPCs.ZOMBIE_PIRATE_5645, NPCs.ZOMBIE_PIRATE_5646,
NPCs.ZOMBIE_PIRATE_5647, NPCs.ZOMBIE_PIRATE_5648, NPCs.ZOMBIE_PIRATE_5649,
NPCs.ZOMBIE_PIRATE_5650, NPCs.ZOMBIE_PIRATE_5651, NPCs.ZOMBIE_PIRATE_5652,
NPCs.ZOMBIE_PIRATE_5653, NPCs.ZOMBIE_PIRATE_5654, NPCs.ZOMBIE_PIRATE_5655,
NPCs.ZOMBIE_PIRATE_5656, NPCs.ZOMBIE_PIRATE_5657, NPCs.ZOMBIE_PIRATE_5658,
NPCs.ZOMBIE_PIRATE_5659, NPCs.ZOMBIE_PIRATE_5660, NPCs.ZOMBIE_PIRATE_5661,
NPCs.ZOMBIE_PIRATE_5662, NPCs.ZOMBIE_PIRATE_5663, NPCs.ZOMBIE_PIRATE_5664,
NPCs.ZOMBIE_PIRATE_5665,
NPCs.ZOMBIE_SWAB_2843, NPCs.ZOMBIE_SWAB_2845,
NPCs.ZOMBIE_SWAB_2846, NPCs.ZOMBIE_SWAB_2847,
NPCs.ZOMBIE_SWAB_2848,
NPCs.NAZASTAROOL_507,
NPCs.SLASH_BASH_2060, NPCs.SOREBONES_5627, NPCs.SOREBONES_5628,
NPCs.UNDEAD_LUMBERJACK_1524,
NPCs.UNDEAD_ONE_502, NPCs.UNDEAD_ONE_503, NPCs.UNDEAD_ONE_504, NPCs.UNDEAD_ONE_505,
NPCs.ZOGRE_2044, NPCs.ZOGRE_2045, NPCs.ZOGRE_2046, NPCs.ZOGRE_2047, NPCs.ZOGRE_2048,
NPCs.ZOGRE_2049, NPCs.ZOGRE_2051, NPCs.ZOGRE_2052, NPCs.ZOGRE_2053, NPCs.ZOGRE_2054,
NPCs.ZOGRE_2055,
NPCs.UNDEAD_LUMBERJACK_1524, NPCs.UNDEAD_LUMBERJACK_1525, NPCs.UNDEAD_LUMBERJACK_5678,
NPCs.UNDEAD_LUMBERJACK_5679, NPCs.UNDEAD_LUMBERJACK_5680, NPCs.UNDEAD_LUMBERJACK_5681,
NPCs.UNDEAD_LUMBERJACK_5682, NPCs.UNDEAD_LUMBERJACK_5683, NPCs.UNDEAD_LUMBERJACK_5684,
NPCs.UNDEAD_LUMBERJACK_5685, NPCs.UNDEAD_LUMBERJACK_5686, NPCs.UNDEAD_LUMBERJACK_5687,
NPCs.UNDEAD_LUMBERJACK_5688, NPCs.UNDEAD_LUMBERJACK_5689, NPCs.UNDEAD_LUMBERJACK_5690,
NPCs.UNDEAD_LUMBERJACK_5691, NPCs.UNDEAD_LUMBERJACK_5692, NPCs.UNDEAD_LUMBERJACK_5693,
NPCs.UNDEAD_LUMBERJACK_5694, NPCs.UNDEAD_LUMBERJACK_5695, NPCs.UNDEAD_LUMBERJACK_5696,
NPCs.UNDEAD_LUMBERJACK_5697, NPCs.UNDEAD_LUMBERJACK_5698, NPCs.UNDEAD_LUMBERJACK_5699,
NPCs.UNDEAD_LUMBERJACK_5700, NPCs.UNDEAD_LUMBERJACK_5701, NPCs.UNDEAD_LUMBERJACK_5702,
NPCs.UNDEAD_LUMBERJACK_5703, NPCs.UNDEAD_LUMBERJACK_5704, NPCs.UNDEAD_LUMBERJACK_5705,
NPCs.UNDEAD_LUMBERJACK_5706, NPCs.UNDEAD_LUMBERJACK_5707, NPCs.UNDEAD_LUMBERJACK_5708,
NPCs.UNDEAD_LUMBERJACK_5709, NPCs.UNDEAD_LUMBERJACK_5710, NPCs.UNDEAD_LUMBERJACK_5711,
NPCs.UNDEAD_LUMBERJACK_5712, NPCs.UNDEAD_LUMBERJACK_5713, NPCs.UNDEAD_LUMBERJACK_5714,
NPCs.UNDEAD_LUMBERJACK_5715, NPCs.UNDEAD_LUMBERJACK_5716, NPCs.UNDEAD_LUMBERJACK_5717,
NPCs.UNDEAD_LUMBERJACK_5718, NPCs.UNDEAD_LUMBERJACK_5719, NPCs.UNDEAD_LUMBERJACK_5720,
NPCs.UNDEAD_LUMBERJACK_5721, NPCs.UNDEAD_LUMBERJACK_5722, NPCs.UNDEAD_LUMBERJACK_5723,
NPCs.UNDEAD_LUMBERJACK_5724, NPCs.UNDEAD_LUMBERJACK_5725, NPCs.UNDEAD_LUMBERJACK_5726,
NPCs.UNDEAD_LUMBERJACK_5727, NPCs.UNDEAD_LUMBERJACK_5728, NPCs.UNDEAD_LUMBERJACK_5729,
NPCs.UNDEAD_LUMBERJACK_5730, NPCs.UNDEAD_LUMBERJACK_5731, NPCs.UNDEAD_LUMBERJACK_5732,
NPCs.UNDEAD_LUMBERJACK_5733, NPCs.UNDEAD_LUMBERJACK_5734, NPCs.UNDEAD_LUMBERJACK_5735,
NPCs.UNDEAD_LUMBERJACK_5736, NPCs.UNDEAD_LUMBERJACK_5737, NPCs.UNDEAD_LUMBERJACK_5738,
NPCs.UNDEAD_LUMBERJACK_5739, NPCs.UNDEAD_LUMBERJACK_5740, NPCs.UNDEAD_LUMBERJACK_5741,
NPCs.UNDEAD_LUMBERJACK_5742, NPCs.UNDEAD_LUMBERJACK_5743, NPCs.UNDEAD_LUMBERJACK_5744,
NPCs.UNDEAD_LUMBERJACK_5745, NPCs.UNDEAD_LUMBERJACK_5746, NPCs.UNDEAD_LUMBERJACK_5747,
)
private val GIANTS = intArrayOf(
NPCs.HILL_GIANT_117, NPCs.HILL_GIANT_4689, NPCs.HILL_GIANT_4690, NPCs.HILL_GIANT_4691,
NPCs.HILL_GIANT_4692, NPCs.HILL_GIANT_4693,
NPCs.FIRE_GIANT_110, NPCs.FIRE_GIANT_1582, NPCs.FIRE_GIANT_1583, NPCs.FIRE_GIANT_1584,
NPCs.FIRE_GIANT_1585, NPCs.FIRE_GIANT_1586, NPCs.FIRE_GIANT_7003, NPCs.FIRE_GIANT_7004,
NPCs.MOSS_GIANT_112, NPCs.MOSS_GIANT_1587, NPCs.MOSS_GIANT_1588, NPCs.MOSS_GIANT_1681,
NPCs.MOSS_GIANT_4534, NPCs.MOSS_GIANT_4688, NPCs.MOSS_GIANT_4706,
NPCs.ICE_GIANT_111, NPCs.ICE_GIANT_3072, NPCs.ICE_GIANT_4685, NPCs.ICE_GIANT_4686,
NPCs.ICE_GIANT_4687,
NPCs.BLACK_KNIGHT_TITAN_221,
NPCs.CYCLOPS_116, NPCs.CYCLOPS_4291, NPCs.CYCLOPS_4292, NPCs.CYCLOPS_6078,
NPCs.CYCLOPS_6079, NPCs.CYCLOPS_6080, NPCs.CYCLOPS_6081, NPCs.CYCLOPS_6082,
NPCs.CYCLOPS_6083, NPCs.CYCLOPS_6269, NPCs.CYCLOPS_6270,
)
private val HOBGOBLINS = intArrayOf(
NPCs.HOBGOBLIN_122, NPCs.HOBGOBLIN_123, NPCs.HOBGOBLIN_2685, NPCs.HOBGOBLIN_2686,
NPCs.HOBGOBLIN_2687, NPCs.HOBGOBLIN_2688, NPCs.HOBGOBLIN_3583, NPCs.HOBGOBLIN_4898,
NPCs.HOBGOBLIN_6275,
)
private val GHOUL = NPCs.GHOUL_1218
private val EARTH_WARRIOR = NPCs.EARTH_WARRIOR_124
private val JOGRES = intArrayOf(NPCs.JOGRE_113, NPCs.JOGRE_6268)
private val LESSER_DEMONS = intArrayOf(
NPCs.LESSER_DEMON_82, NPCs.LESSER_DEMON_4694, NPCs.LESSER_DEMON_4695,
NPCs.LESSER_DEMON_4696, NPCs.LESSER_DEMON_4697, NPCs.LESSER_DEMON_6101,
)
private val ZAKLN = NPCs.ZAKLN_GRITCH_6206
val SCROLLS = intArrayOf(
Items.CHAMPION_SCROLL_6803, Items.CHAMPION_SCROLL_6801, Items.CHAMPION_SCROLL_6806,
Items.CHAMPION_SCROLL_6807, Items.CHAMPION_SCROLL_6800, Items.CHAMPION_SCROLL_6802,
Items.CHAMPION_SCROLL_6799, Items.CHAMPION_SCROLL_6798, Items.CHAMPION_SCROLL_6804,
Items.CHAMPION_SCROLL_6805
)
val idMap = HashMap<Int, Int>()
init {
for (id in IMPS)
idMap[id] = 0
for (id in GOBLINS)
idMap[id] = 1
for (id in SKELETONS)
idMap[id] = 2
for (id in ZOMBIES)
idMap[id] = 3
for (id in GIANTS)
idMap[id] = 4
for (id in HOBGOBLINS)
idMap[id] = 5
for (id in JOGRES)
idMap[id] = 8
for (id in LESSER_DEMONS)
idMap[id] = 9
idMap[GHOUL] = 6
idMap[EARTH_WARRIOR] = 7
}
}
override fun onNpcKilled(player: Player, event: NPCKillEvent) {
if (player.isArtificial) return
if (player.questRepository.points >= 32) {
val scrollType = idMap[event.npc.id] ?: return
rollForScroll (player, scrollType, event.npc)
}
}
private fun rollForScroll(player: Player, scroll: Int, npc: NPC) {
val scrollID = SCROLLS[scroll]
val roll = RandomFunction.roll(if (GameWorld.settings!!.isDevMode) 5 else 5000)
if (roll) {
GroundItemManager.create(Item(scrollID), npc.location, player)
sendMessage(player, colorize("%RA Champion's scroll falls to the ground as you slay your opponent."))
}
}
}

View file

@ -0,0 +1,39 @@
package content.global.activity.cchallange
import core.api.LoginListener
import core.game.event.Event
import core.game.event.EventHook
import core.game.event.NPCKillEvent
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
/**
* Manages the champion scrolls drop.
* @authors Phil, Skelsoft.
*/
abstract class ChampionScrollsEventHookBase : LoginListener {
protected companion object {
private fun <T> forEligibleEntityDo(entity: Entity, event: T, handler: (Player, T) -> Unit) {
if (entity !is Player) return
if (entity.isArtificial) return
handler(entity, event)
}
}
class EventHandler<T : Event>(
private val owner: ChampionScrollsEventHookBase,
private val handler: (Player, T) -> Unit) : EventHook<T> {
override fun process(entity: Entity, event: T) {
forEligibleEntityDo(entity, event, handler)
}
}
final override fun login(player: Player) {
player.hook(core.api.Event.NPCKilled, EventHandler(this, ::onNpcKilled))
}
protected open fun onNpcKilled(player: Player, event: NPCKillEvent) {}
}

View file

@ -0,0 +1,72 @@
package content.global.activity.cchallange
import core.api.*
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
import core.plugin.Initializable
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the dialogue plugin used for the larxus npc.
* @author 'Vexia
* @version 1.1
*/
@Initializable
class LarxusDialogue(val ChallengeStart: Boolean = false) : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
val scrolls = intArrayOf(Items.CHAMPION_SCROLL_6798, Items.CHAMPION_SCROLL_6799, Items.CHAMPION_SCROLL_6800, Items.CHAMPION_SCROLL_6801, Items.CHAMPION_SCROLL_6802, Items.CHAMPION_SCROLL_6803, Items.CHAMPION_SCROLL_6804, Items.CHAMPION_SCROLL_6805, Items.CHAMPION_SCROLL_6806, Items.CHAMPION_SCROLL_6807,)
npc = NPC(NPCs.LARXUS_3050)
if (ChallengeStart) {
when (stage) {
0 -> {
face(findNPC(NPCs.LARXUS_3050)!!, player!!, 1)
for (i in scrolls)when{
inInventory(player!!,Items.CHAMPION_SCROLL_6798) -> npcl("So you want to accept the challenge huh? Well there are some specific rules for these Champion fights. For this fight you're not allowed to use prayer's. Do you still want to proceed?").also { stage = 1 }
inInventory(player!!,Items.CHAMPION_SCROLL_6799) -> npcl("So you want to accept the challenge huh? Well there are some specific rules for these Champion fights. For this fight you're allowed to use only weapons. Do you still want to proceed?").also { stage = 1 }
inInventory(player!!,Items.CHAMPION_SCROLL_6800) -> npcl("So you want to accept the challenge huh? Well there are some specific rules for these Champion fights. For this fight you're allowed to use only melee combat skill. Do you still want to proceed?").also { stage = 1 }
inInventory(player!!,Items.CHAMPION_SCROLL_6801) -> npcl("So you want to accept the challenge huh? Well there are some specific rules for these Champion fights. For this fight you're allowed to use only magic skill. Do you still want to proceed?").also { stage = 1 }
inInventory(player!!,Items.CHAMPION_SCROLL_6802) -> npcl("So you want to accept the challenge huh? Well there are some specific rules for these Champion fights. For this fight you're not allowed to use melee combat skills. Do you still want to proceed?").also { stage = 1 }
inInventory(player!!,Items.CHAMPION_SCROLL_6803) -> npcl("So you want to accept the challenge huh? Well there are some specific rules for these Champion fights. For this fight you're not allowed to use weapons with special attack. Do you still want to proceed?").also { stage = 1 }
inInventory(player!!,Items.CHAMPION_SCROLL_6804) -> npcl("So you want to accept the challenge huh? Well there are some specific rules for these Champion fights. For this fight you're not allowed to use ranged skill. Do you still want to proceed?").also { stage = 1 }
inInventory(player!!,Items.CHAMPION_SCROLL_6805) -> npcl("So you want to accept the challenge huh? Well there are some specific rules for these Champion fights. For this fight you're allowed to use only equipment. Do you still want to proceed?").also { stage = 1 }
inInventory(player!!,Items.CHAMPION_SCROLL_6806) -> npcl("So you want to accept the challenge huh? Well there are some specific rules for these Champion fights. For this fight you're allowed to use only ranged skill. Do you still want to proceed?").also { stage = 1 }
inInventory(player!!,Items.CHAMPION_SCROLL_6807) -> npcl("So you want to accept the challenge huh? Well there are some specific rules for these Champion fights. For this fight you're not allowed to use magic skill. Do you still want to proceed?").also { stage = 1 }
else -> {
sendMessage(player!!, "Nothing interesting happens.").also { stage = END_DIALOGUE } }
}
}
1 -> options("Yes, let me at him!", "No, thanks I'll pass.").also { stage = 2 }
2 -> when (buttonID) {
1 -> playerl("Yes, let me at him!").also { stage = 3 }
2 -> playerl("No, thanks I'll pass.").also { stage = END_DIALOGUE }
}
3 -> npcl("Your challenger is ready, please go down through the trapdoor when you're ready.").also { stage = 4 }
4 -> {
end()
setAttribute(player!!, "championsarena:start", true)
}
}
} else {
when (stage) {
START_DIALOGUE -> {
face(findNPC(NPCs.LARXUS_3050)!!, player!!, 1)
npcl(FacialExpression.NEUTRAL, "Is there something I can help you with?").also { stage = 1 }
}
1 -> options("I was given a challenge, what now?", "What is this place?", "Nothing thanks.").also { stage = 2 }
2 -> when (buttonID) {
1 -> playerl("I was given a challenge, what now?").also { stage = 3 }
2 -> playerl("What is this place?").also { stage = 4 }
3 -> playerl("Nothing thanks.").also { stage = END_DIALOGUE }
}
3 -> npcl("Well pass it here and we'll get you started.").also { stage = END_DIALOGUE }
4 -> npcl("This is the champions' arena, the champions of various, races use it to duel those they deem worthy of the, honour.").also { stage = END_DIALOGUE }
}
}
}
}

View file

@ -0,0 +1,114 @@
package content.global.activity.cchallange.npc
import core.api.*
import core.game.node.entity.Entity
import core.game.node.entity.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the Earth warrior champion NPC for Champions challenge.
*/
@Initializable
class EarthWarriorChampionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var clearTime = 0
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return EarthWarriorChampionNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.EARTH_WARRIOR_CHAMPION_3057)
}
override fun handleTickActions() {
super.handleTickActions()
if (clearTime++ > 288) poofClear(this)
}
companion object {
fun spawnEarthWarriorChampion(player: Player) {
val champion = EarthWarriorChampionNPC(NPCs.EARTH_WARRIOR_CHAMPION_3057)
champion.location = location(3170, 9758, 0)
champion.isWalks = true
champion.isAggressive = true
champion.isActive = false
if (champion.asNpc() != null && champion.isActive) {
champion.properties.teleportLocation = champion.properties.spawnLocation
}
champion.isActive = true
GameWorld.Pulser.submit(object : Pulse(0, champion) {
override fun pulse(): Boolean {
val prayerItems = intArrayOf(
Items.PRAYER_POTION1_143, Items.PRAYER_POTION1_144,
Items.PRAYER_POTION2_141, Items.PRAYER_POTION2_142,
Items.PRAYER_POTION3_139, Items.PRAYER_POTION3_140,
Items.PRAYER_POTION4_2434, Items.PRAYER_POTION4_2435,
Items.SUPER_RESTORE1_3030, Items.SUPER_RESTORE1_3031,
Items.SUPER_RESTORE2_3028, Items.SUPER_RESTORE2_3029,
Items.SUPER_RESTORE3_3026, Items.SUPER_RESTORE3_3027,
Items.SUPER_RESTORE4_3024, Items.SUPER_RESTORE4_3025,
Items.PRAYER_CAPE_9759, Items.PRAYER_CAPET_9760,
Items.PRAYER_HOOD_9761, Items.PRAYER_CAPE_10643,
Items.PRAYER_POTION4_14209, Items.PRAYER_POTION4_14210,
Items.PRAYER_POTION3_14211, Items.PRAYER_POTION3_14212,
Items.PRAYER_POTION2_14213, Items.PRAYER_POTION2_14214,
Items.PRAYER_POTION1_14215, Items.PRAYER_POTION1_14216,
Items.FALADOR_SHIELD_1_14577, Items.FALADOR_SHIELD_2_14578,
Items.FALADOR_SHIELD_3_14579,
Items.PRAYER_MIX1_11467, Items.PRAYER_MIX1_11468,
Items.PRAYER_MIX2_11465, Items.PRAYER_MIX2_11466,
Items.SUP_RESTORE_MIX1_11495, Items.SUP_RESTORE_MIX1_11496,
Items.SUP_RESTORE_MIX2_11493, Items.SUP_RESTORE_MIX2_11494,
)
if (player.inventory.containsAtLeastOneItem(prayerItems) || player.equipment.containsAtLeastOneItem(
prayerItems
)
) {
sendNPCDialogue(player, NPCs.LARXUS_3050, "For this fight you're not allowed to use prayers!")
teleport(player, Location.create(3182, 9758, 0)) // Behind Doors.
} else {
champion.init()
registerHintIcon(player, champion)
champion.attack(player)
}
return true
}
})
}
}
override fun finalizeDeath(killer: Entity?) {
if (killer is Player) {
lock(killer, 2)
runTask(killer, 1) {
openInterface(killer, 63)
setInterfaceText(killer, "Well done, you defeated the Earth Warrior Champion!", 63, 2)
killer.packetDispatch.sendItemZoomOnInterface(Items.CHAMPION_SCROLL_6798, 260, 63, 3)
setInterfaceText(killer, "432 Slayer Xp", 63, 6)
setInterfaceText(killer, "432 Hitpoint Xp", 63, 7)
}
setVarbit(killer, 1452, 1, true)
rewardXP(killer, Skills.HITPOINTS, 432.0)
rewardXP(killer, Skills.SLAYER, 432.0)
removeAttribute("championsarena:start")
clearHintIcon(killer)
}
clear()
super.finalizeDeath(killer)
}
}

View file

@ -0,0 +1,105 @@
package content.global.activity.cchallange.npc
import core.api.*
import core.game.container.impl.EquipmentContainer
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.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.node.item.Item
import core.game.system.config.ItemConfigParser
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the Ghoul champion NPC for Champions challenge.
*/
@Initializable
class GhoulChampionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var clearTime = 0
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return GhoulChampionNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.GHOUL_CHAMPION_3059)
}
override fun handleTickActions() {
super.handleTickActions()
if (clearTime++ > 288) poofClear(this)
}
companion object {
fun spawnGhoulChampion(player: Player) {
val champion = GhoulChampionNPC(NPCs.GHOUL_CHAMPION_3059)
champion.location = location(3170, 9758, 0)
champion.isWalks = true
champion.isAggressive = true
champion.isActive = false
if (champion.asNpc() != null && champion.isActive) {
champion.properties.teleportLocation = champion.properties.spawnLocation
}
champion.isActive = true
GameWorld.Pulser.submit(object : Pulse(0, champion) {
override fun pulse(): Boolean {
champion.init()
registerHintIcon(player, champion)
champion.attack(player)
return true
}
})
}
}
override fun checkImpact(state: BattleState) {
super.checkImpact(state)
val player = state.attacker
if (player is Player) {
val i: Item = player.equipment[EquipmentContainer.SLOT_WEAPON].id.asItem()
if (i.definition.getConfiguration(ItemConfigParser.TWO_HANDED, false) == true && state.style == CombatStyle.MELEE) {
state.neutralizeHits()
state.estimatedHit = state.maximumHit
}
if (state.style == CombatStyle.MAGIC) {
sendMessage(player, "You can use only weapons in this challenge.")
if (state.estimatedHit > -1) {
state.estimatedHit = 0
return
}
if (state.secondaryHit > -1) {
state.secondaryHit = 0
return
}
}
}
}
override fun finalizeDeath(killer: Entity?) {
if (killer is Player) {
lock(killer, 2)
runTask(killer, 1) {
openInterface(killer, 63)
setInterfaceText(killer, "Well done, you defeated the Ghoul Champion!", 63, 2)
killer.packetDispatch.sendItemZoomOnInterface(Items.CHAMPION_SCROLL_6799, 260, 63, 3)
setInterfaceText(killer, "400 Slayer Xp", 63, 6)
setInterfaceText(killer, "400 Hitpoint Xp", 63, 7)
}
setVarbit(killer, 1453, 1, true)
rewardXP(killer, Skills.HITPOINTS, 400.0)
rewardXP(killer, Skills.SLAYER, 400.0)
removeAttribute("championsarena:start")
clearHintIcon(killer)
}
clear()
super.finalizeDeath(killer)
}
}

View file

@ -0,0 +1,103 @@
package content.global.activity.cchallange.npc
import core.api.*
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.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the Giant champion NPC for Champions challenge.
*/
@Initializable
class GiantChampionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var clearTime = 0
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return GiantChampionNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.GIANT_CHAMPION_3058)
}
override fun handleTickActions() {
super.handleTickActions()
if (clearTime++ > 288) poofClear(this)
}
companion object {
fun spawnGiantChampion(player: Player) {
val champion = GiantChampionNPC(NPCs.GIANT_CHAMPION_3058)
champion.location = location(3170, 9758, 0)
champion.isWalks = true
champion.isAggressive = true
champion.isActive = false
if (champion.asNpc() != null && champion.isActive) {
champion.properties.teleportLocation = champion.properties.spawnLocation
}
champion.isActive = true
GameWorld.Pulser.submit(object : Pulse(0, champion) {
override fun pulse(): Boolean {
champion.init()
registerHintIcon(player, champion)
champion.attack(player)
return true
}
})
}
}
override fun checkImpact(state: BattleState) {
super.checkImpact(state)
val player = state.attacker
if (player is Player) {
if (state.style == CombatStyle.MELEE) {
state.neutralizeHits()
state.estimatedHit = state.maximumHit
}
if (state.style == CombatStyle.RANGE || state.style == CombatStyle.MAGIC) {
sendMessage(player, "You can use only melee in this challenge.")
if (state.estimatedHit > -1) {
state.estimatedHit = 0
return
}
if (state.secondaryHit > -1) {
state.secondaryHit = 0
return
}
}
}
}
override fun finalizeDeath(killer: Entity?) {
if (killer is Player) {
lock(killer, 2)
runTask(killer, 1) {
openInterface(killer, 63)
setInterfaceText(killer, "Well done, you defeated the Giant Champion!", 63, 2)
killer.packetDispatch.sendItemZoomOnInterface(Items.CHAMPION_SCROLL_6800, 260, 63, 3)
setInterfaceText(killer, "280 Slayer Xp", 63, 6)
setInterfaceText(killer, "280 Hitpoint Xp", 63, 7)
}
setVarbit(killer, 1454, 1, true)
rewardXP(killer, Skills.HITPOINTS, 280.0)
rewardXP(killer, Skills.SLAYER, 280.0)
removeAttribute("championsarena:start")
clearHintIcon(killer)
}
clear()
super.finalizeDeath(killer)
}
}

View file

@ -0,0 +1,101 @@
package content.global.activity.cchallange.npc
import core.api.*
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.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the Goblin champion NPC for Champions challenge.
*/
@Initializable
class GoblinChampionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var clearTime = 0
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return GoblinChampionNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.GOBLIN_CHAMPION_3060)
}
override fun handleTickActions() {
super.handleTickActions()
if (clearTime++ > 288) poofClear(this)
}
companion object {
fun spawnGoblinChampion(player: Player) {
val champion = GoblinChampionNPC(NPCs.GOBLIN_CHAMPION_3060)
champion.location = location(3170, 9758, 0)
champion.isWalks = true
champion.isAggressive = true
champion.isActive = false
if (champion.asNpc() != null && champion.isActive) {
champion.properties.teleportLocation = champion.properties.spawnLocation
}
champion.isActive = true
GameWorld.Pulser.submit(object : Pulse(0, champion) {
override fun pulse(): Boolean {
champion.init()
registerHintIcon(player, champion)
champion.attack(player)
return true
}
})
}
}
override fun checkImpact(state: BattleState) {
super.checkImpact(state)
val player = state.attacker
if (player is Player) {
if (state.style == CombatStyle.MAGIC) {
state.neutralizeHits()
state.estimatedHit = state.maximumHit
}
if (state.style == CombatStyle.MELEE || state.style == CombatStyle.RANGE) {
sendMessage(player, "You can use only spells in this challenge.")
if (state.estimatedHit > -1) {
state.estimatedHit = 0
return
}
if (state.secondaryHit > -1) {
state.secondaryHit = 0
return
}
}
}
}
override fun finalizeDeath(killer: Entity?) {
if (killer is Player) {
lock(killer, 2)
runTask(killer, 1) {
openInterface(killer, 63)
setInterfaceText(killer, "Well done, you defeated the Goblin Champion!", 63, 2)
killer.packetDispatch.sendItemZoomOnInterface(Items.CHAMPION_SCROLL_6801, 260, 63, 3)
setInterfaceText(killer, "128 Slayer Xp", 63, 6)
setInterfaceText(killer, "128 Hitpoint Xp", 63, 7)
}
setVarbit(killer, 1455, 1, true)
rewardXP(killer, Skills.HITPOINTS, 128.0)
rewardXP(killer, Skills.SLAYER, 128.0)
removeAttribute("championsarena:start")
clearHintIcon(killer)
}
clear()
super.finalizeDeath(killer)
}
}

View file

@ -0,0 +1,103 @@
package content.global.activity.cchallange.npc
import core.api.*
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.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the Hobgoblin champion NPC for Champions challenge.
*/
@Initializable
class HobgoblinChampionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var clearTime = 0
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return HobgoblinChampionNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.HOBGOBLIN_CHAMPION_3061)
}
override fun handleTickActions() {
super.handleTickActions()
if (clearTime++ > 288) poofClear(this)
}
companion object {
fun spawnHobgoblinChampion(player: Player) {
val champion = HobgoblinChampionNPC(NPCs.HOBGOBLIN_CHAMPION_3061)
champion.location = location(3170, 9758, 0)
champion.isWalks = true
champion.isAggressive = true
champion.isActive = false
if (champion.asNpc() != null && champion.isActive) {
champion.properties.teleportLocation = champion.properties.spawnLocation
}
champion.isActive = true
GameWorld.Pulser.submit(object : Pulse(0, champion) {
override fun pulse(): Boolean {
champion.init()
registerHintIcon(player, champion)
champion.attack(player)
return true
}
})
}
}
override fun checkImpact(state: BattleState) {
super.checkImpact(state)
val player = state.attacker
if (player is Player) {
if (state.style == CombatStyle.MAGIC || state.style == CombatStyle.RANGE) {
state.neutralizeHits()
state.estimatedHit = state.maximumHit
}
if (state.style == CombatStyle.MELEE) {
sendMessage(player, "You cannot use melee in this challenge.")
if (state.estimatedHit > -1) {
state.estimatedHit = 0
return
}
if (state.secondaryHit > -1) {
state.secondaryHit = 0
return
}
}
}
}
override fun finalizeDeath(killer: Entity?) {
if (killer is Player) {
lock(killer, 2)
runTask(killer, 1) {
openInterface(killer, 63)
setInterfaceText(killer, "Well done, you defeated the Hobgoblin Champion!", 63, 2)
killer.packetDispatch.sendItemZoomOnInterface(Items.CHAMPION_SCROLL_6802, 260, 63, 3)
setInterfaceText(killer, "232 Slayer Xp", 63, 6)
setInterfaceText(killer, "232 Hitpoint Xp", 63, 7)
}
setVarbit(killer, 1456, 1, true)
rewardXP(killer, Skills.HITPOINTS, 232.0)
rewardXP(killer, Skills.SLAYER, 232.0)
removeAttribute("championsarena:start")
clearHintIcon(killer)
}
clear()
super.finalizeDeath(killer)
}
}

View file

@ -0,0 +1,104 @@
package content.global.activity.cchallange.npc
import core.api.*
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.equipment.WeaponInterface
import core.game.node.entity.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the Imp champion NPC for Champions challenge.
*/
@Initializable
class ImpChampionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var clearTime = 0
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return ImpChampionNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.IMP_CHAMPION_3062)
}
override fun handleTickActions() {
super.handleTickActions()
if (clearTime++ > 288) poofClear(this)
}
companion object {
fun spawnImpChampion(player: Player) {
val champion = ImpChampionNPC(NPCs.IMP_CHAMPION_3062)
champion.location = location(3170, 9758, 0)
champion.isWalks = true
champion.isAggressive = true
champion.isActive = false
if (champion.asNpc() != null && champion.isActive) {
champion.properties.teleportLocation = champion.properties.spawnLocation
}
champion.isActive = true
GameWorld.Pulser.submit(object : Pulse(0, champion) {
override fun pulse(): Boolean {
champion.init()
registerHintIcon(player, champion)
champion.attack(player)
return true
}
})
}
}
override fun checkImpact(state: BattleState) {
super.checkImpact(state)
val player = state.attacker
if (player is Player) {
val w = player.getExtension<WeaponInterface>(WeaponInterface::class.java)
if (state.style == CombatStyle.MELEE || state.style == CombatStyle.MAGIC || state.style == CombatStyle.RANGE) {
state.neutralizeHits()
state.estimatedHit = state.maximumHit
}
if (w.weaponInterface.interfaceId == 10) {
sendMessage(player, "You cannot use special attack in this challenge.")
if (state.estimatedHit > -1) {
state.estimatedHit = 0
return
}
if (state.secondaryHit > -1) {
state.secondaryHit = 0
return
}
}
}
}
override fun finalizeDeath(killer: Entity?) {
if (killer is Player) {
lock(killer, 2)
runTask(killer, 1) {
openInterface(killer, 63)
setInterfaceText(killer, "Well done, you defeated the Imp Champion!", 63, 2)
killer.packetDispatch.sendItemZoomOnInterface(Items.CHAMPION_SCROLL_6803, 260, 63, 3)
setInterfaceText(killer, "160 Slayer Xp", 63, 6)
setInterfaceText(killer, "160 Hitpoint Xp", 63, 7)
}
setVarbit(killer, 1457, 1, true)
rewardXP(killer, Skills.HITPOINTS, 160.0)
rewardXP(killer, Skills.SLAYER, 160.0)
removeAttribute("championsarena:start")
clearHintIcon(killer)
}
clear()
super.finalizeDeath(killer)
}
}

View file

@ -0,0 +1,102 @@
package content.global.activity.cchallange.npc
import core.api.*
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.equipment.Weapon
import core.game.node.entity.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the Jogre champion NPC for Champions challenge.
*/
@Initializable
class JogreChampionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var clearTime = 0
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return JogreChampionNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.JOGRE_CHAMPION_3063)
}
override fun handleTickActions() {
super.handleTickActions()
if (clearTime++ > 288) poofClear(this)
}
companion object {
fun spawnJogreChampion(player: Player) {
val champion = JogreChampionNPC(NPCs.JOGRE_CHAMPION_3063)
champion.location = location(3170, 9758, 0)
champion.isWalks = true
champion.isAggressive = true
champion.isActive = false
if (champion.asNpc() != null && champion.isActive) {
champion.properties.teleportLocation = champion.properties.spawnLocation
}
champion.isActive = true
GameWorld.Pulser.submit(object : Pulse(0, champion) {
override fun pulse(): Boolean {
champion.init()
registerHintIcon(player, champion)
champion.attack(player)
return true
}
})
}
}
override fun checkImpact(state: BattleState) {
super.checkImpact(state)
val player = state.attacker
if (player is Player) {
if (state.style == CombatStyle.MAGIC || state.style == CombatStyle.MELEE) {
state.neutralizeHits()
state.estimatedHit = state.maximumHit
}
if (state.weapon.type == Weapon.WeaponType.DEGRADING || state.style == CombatStyle.RANGE) {
sendMessage(player, "You cannot use ranged weapons.")
if (state.estimatedHit > -1) {
state.estimatedHit = 0
return
}
if (state.secondaryHit > -1) {
state.secondaryHit = 0
return
}
}
}
}
override fun finalizeDeath(killer: Entity?) {
if (killer is Player) {
lock(killer, 2)
runTask(killer, 1) {
openInterface(killer, 63)
setInterfaceText(killer, "Well done, you defeated the Jogre Champion!", 63, 2)
killer.packetDispatch.sendItemZoomOnInterface(Items.CHAMPION_SCROLL_6804, 260, 63, 3)
setInterfaceText(killer, "480 Slayer Xp", 63, 6)
setInterfaceText(killer, "480 Hitpoint Xp", 63, 7)
}
setVarbit(killer, 1458, 1, true)
rewardXP(killer, Skills.HITPOINTS, 480.0)
rewardXP(killer, Skills.SLAYER, 480.0)
removeAttribute("championsarena:start")
clearHintIcon(killer)
}
clear()
super.finalizeDeath(killer)
}
}

View file

@ -0,0 +1,102 @@
package content.global.activity.cchallange.npc
import core.api.*
import core.game.container.impl.EquipmentContainer
import core.game.global.action.EquipHandler
import core.game.node.entity.Entity
import core.game.node.entity.combat.BattleState
import core.game.node.entity.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the Lesser demon champion NPC for Champions challenge.
*/
@Initializable
class LesserDemonChampionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var clearTime = 0
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return LesserDemonChampionNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.LESSER_DEMON_CHAMPION_3064)
}
override fun handleTickActions() {
super.handleTickActions()
if (clearTime++ > 288) poofClear(this)
}
companion object {
fun spawnLesserDemonChampion(player: Player) {
val champion = LesserDemonChampionNPC(NPCs.LESSER_DEMON_CHAMPION_3064)
champion.location = location(3170, 9758, 0)
champion.isWalks = true
champion.isAggressive = true
champion.isActive = false
if (champion.asNpc() != null && champion.isActive) {
champion.properties.teleportLocation = champion.properties.spawnLocation
}
champion.isActive = true
GameWorld.Pulser.submit(object : Pulse(0, champion) {
override fun pulse(): Boolean {
champion.init()
registerHintIcon(player, champion)
champion.attack(player)
return true
}
})
}
}
override fun checkImpact(state: BattleState) {
super.checkImpact(state)
val player = state.attacker
if (player is Player) {
if (!player.equipment[3].hasItemPlugin()) {
state.neutralizeHits()
state.estimatedHit = state.maximumHit
} else {
EquipHandler.unequip(player, EquipmentContainer.SLOT_WEAPON, id)
sendMessage(player, "You cannot use weapons in this challenge.")
if (state.estimatedHit > -1) {
state.estimatedHit = 0
return
}
if (state.secondaryHit > -1) {
state.secondaryHit = 0
return
}
}
}
}
override fun finalizeDeath(killer: Entity?) {
if (killer is Player) {
lock(killer, 2)
runTask(killer, 1) {
openInterface(killer, 63)
setInterfaceText(killer, "Well done, you defeated the Lesser Demon Champion!", 63, 2)
killer.packetDispatch.sendItemZoomOnInterface(Items.CHAMPION_SCROLL_6805, 260, 63, 3)
setInterfaceText(killer, "592 Slayer Xp", 63, 6)
setInterfaceText(killer, "592 Hitpoint Xp", 63, 7)
}
setVarbit(killer, 1459, 1, true)
rewardXP(killer, Skills.HITPOINTS, 592.0)
rewardXP(killer, Skills.SLAYER, 592.0)
removeAttribute("championsarena:start")
clearHintIcon(killer)
}
clear()
super.finalizeDeath(killer)
}
}

View file

@ -0,0 +1,103 @@
package content.global.activity.cchallange.npc
import core.api.*
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.equipment.Weapon
import core.game.node.entity.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the Skeleton champion NPC for Champions challenge.
*/
@Initializable
class SkeletonChampionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var clearTime = 0
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return SkeletonChampionNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.SKELETON_CHAMPION_3065)
}
override fun handleTickActions() {
super.handleTickActions()
if (clearTime++ > 288) poofClear(this)
}
companion object {
fun spawnSkeletonChampion(player: Player) {
val champion = SkeletonChampionNPC(NPCs.SKELETON_CHAMPION_3065)
champion.location = location(3170, 9758, 0)
champion.isWalks = true
champion.isAggressive = true
champion.isActive = false
if (champion.asNpc() != null && champion.isActive) {
champion.properties.teleportLocation = champion.properties.spawnLocation
}
champion.isActive = true
GameWorld.Pulser.submit(object : Pulse(0, champion) {
override fun pulse(): Boolean {
champion.init()
animate(champion, 259, true)
registerHintIcon(player, champion)
champion.attack(player)
return true
}
})
}
}
override fun checkImpact(state: BattleState) {
super.checkImpact(state)
val player = state.attacker
if (player is Player) {
if (state.style == CombatStyle.RANGE && state.weapon.type == Weapon.WeaponType.DEGRADING && state.weapon.type == Weapon.WeaponType.DOUBLE_SHOT) {
state.neutralizeHits()
state.estimatedHit = state.maximumHit
}
if (state.style == CombatStyle.MAGIC || state.style == CombatStyle.MELEE) {
sendMessage(player, "You can use only ranged weapons in this challenge.")
if (state.estimatedHit > -1) {
state.estimatedHit = 0
return
}
if (state.secondaryHit > -1) {
state.secondaryHit = 0
return
}
}
}
}
override fun finalizeDeath(killer: Entity?) {
if (killer is Player) {
lock(killer, 2)
runTask(killer, 1) {
openInterface(killer, 63)
setInterfaceText(killer, "Well done, you defeated the Skeleton Champion!", 63, 2)
killer.packetDispatch.sendItemZoomOnInterface(Items.CHAMPION_SCROLL_6806, 260, 63, 3)
setInterfaceText(killer, "232 Slayer Xp", 63, 6)
setInterfaceText(killer, "232 Hitpoint Xp", 63, 7)
}
setVarbit(killer, 1460, 1, true)
rewardXP(killer, Skills.HITPOINTS, 232.0)
rewardXP(killer, Skills.SLAYER, 232.0)
removeAttribute("championsarena:start")
clearHintIcon(killer)
}
clear()
super.finalizeDeath(killer)
}
}

View file

@ -0,0 +1,102 @@
package content.global.activity.cchallange.npc
import core.api.*
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.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* Represents the Zombie champion NPC for Champions challenge.
*/
@Initializable
class ZombieChampionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var clearTime = 0
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return ZombieChampionNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.ZOMBIES_CHAMPION_3066)
}
override fun handleTickActions() {
super.handleTickActions()
if (clearTime++ > 288) poofClear(this)
}
companion object {
fun spawnZombieChampion(player: Player) {
val champion = ZombieChampionNPC(NPCs.ZOMBIES_CHAMPION_3066)
champion.location = location(3170, 9758, 0)
champion.isWalks = true
champion.isAggressive = true
champion.isActive = false
if (champion.asNpc() != null && champion.isActive) {
champion.properties.teleportLocation = champion.properties.spawnLocation
}
champion.isActive = true
GameWorld.Pulser.submit(object : Pulse(0, champion) {
override fun pulse(): Boolean {
champion.init()
registerHintIcon(player, champion)
champion.attack(player)
return true
}
})
}
}
override fun checkImpact(state: BattleState) {
super.checkImpact(state)
val player = state.attacker
if (player is Player) {
if (state.style == CombatStyle.MELEE || state.style == CombatStyle.RANGE) {
state.estimatedHit = state.maximumHit
state.neutralizeHits()
}
if (state.style == CombatStyle.MAGIC) {
sendMessage(player, "You cannot use spells in this challenge.")
if (state.estimatedHit > -1) {
state.estimatedHit = 0
return
}
if (state.secondaryHit > -1) {
state.secondaryHit = 0
return
}
}
}
}
override fun finalizeDeath(killer: Entity?) {
if (killer is Player) {
lock(killer, 2)
runTask(killer, 1) {
openInterface(killer, 63)
setInterfaceText(killer, "Well done, you defeated the Zombie Champion!", 63, 2)
killer.packetDispatch.sendItemZoomOnInterface(Items.CHAMPION_SCROLL_6807, 260, 63, 3)
setInterfaceText(killer, "240 Slayer Xp", 63, 6)
setInterfaceText(killer, "240 Hitpoint Xp", 63, 7)
}
setVarbit(killer, 1461, 1, true)
rewardXP(killer, Skills.HITPOINTS, 240.0)
rewardXP(killer, Skills.SLAYER, 240.0)
removeAttribute("championsarena:start")
clearHintIcon(killer)
}
clear()
super.finalizeDeath(killer)
}
}

View file

@ -1,83 +0,0 @@
package content.global.activity.jobs
import core.api.*
import content.global.activity.jobs.impl.GatheringJobs
import content.global.activity.jobs.impl.SlayingJobs
import core.game.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
import core.game.node.item.Item
import org.rs09.consts.Items
import core.game.dialogue.DialogueFile
import core.game.dialogue.Topic
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
class CancelJobDialogueFile : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
START_DIALOGUE -> showTopics(
Topic(core.game.dialogue.FacialExpression.HALF_ASKING, "How am I doing on my job?", 1),
Topic(core.game.dialogue.FacialExpression.HALF_GUILTY, "I'd like to cancel my job.", 10)
)
1 -> {
val jobType = JobType.values()[getAttribute(player!!, "jobs:type", 0)]
val jobId = getAttribute(player!!, "jobs:id", 0)
val needed = getAttribute(player!!, "jobs:amount", 0)
when (jobType) {
JobType.GATHERING -> {
sendItemDialogue(
player!!,
Item(GatheringJobs.values()[jobId].itemId),
"You still need to gather $needed more."
)
}
JobType.SLAYING -> {
sendDialogue(
player!!,
"You still need to kill $needed more ${NPC(SlayingJobs.values()[jobId].ids[0]).name.lowercase()}"
)
}
}
stage = END_DIALOGUE
}
10 -> npc("It will cost 500 coins.")
.also { stage++ }
11 -> showTopics(
Topic(core.game.dialogue.FacialExpression.HAPPY, "Yes, please.", 20),
Topic(core.game.dialogue.FacialExpression.NEUTRAL, "No, thanks.", 30)
)
20 -> npc("Alright then, hand over the money.")
.also { stage++ }
21 -> if (inInventory(player!!, Items.COINS_995, 500)) {
player("Here you go.")
removeItem(player!!, Item(Items.COINS_995, 500))
removeAttribute(player!!, "jobs:id")
removeAttribute(player!!, "jobs:amount")
removeAttribute(player!!, "jobs:original_amount")
removeAttribute(player!!, "jobs:type")
stage = END_DIALOGUE
} else {
player(
core.game.dialogue.FacialExpression.HALF_WORRIED,
"Oh, I don't seem to have the money..."
).also { stage++ }
}
22 -> npc("Ah, that sucks! Get to work.")
.also { stage = END_DIALOGUE }
30 -> npc("Alright then, get to work!")
.also { stage = END_DIALOGUE }
}
}
}

View file

@ -0,0 +1,174 @@
package content.global.activity.jobs
import content.global.activity.jobs.impl.BoneBuryingJobs
import content.global.activity.jobs.impl.CombatJobs
import content.global.activity.jobs.impl.ProductionJobs
import core.api.addItem
import core.api.amountInInventory
import core.api.hasAnItem
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.game.dialogue.IfTopic
import core.game.dialogue.Topic
import core.game.node.entity.npc.NPC
import core.game.node.item.Item
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
import core.tools.StringUtils
import org.rs09.consts.Items
/**
* The dialogue file to handle a player asking about work with the employer that assigned them
* their current job.
*/
class CheckJobDialogueFile : DialogueFile() {
companion object {
const val TURN_IN_ITEMS_1 = 1
const val TURN_IN_ITEMS_2 = 2
const val TURN_IN_ITEMS_3 = 3
const val TURN_IN_ITEMS_4 = 4
const val TURN_IN_ITEMS_5 = 5
const val REMIND_JOB = 101
const val GET_TASK_LIST = 201
const val GET_NEW_JOB_1 = 301
const val GET_NEW_JOB_2 = 302
const val GET_NEW_JOB_3 = 303
const val GET_NEW_JOB_4 = 304
const val GET_NEW_JOB_5 = 305
const val GET_NEW_JOB_NONE = 306
const val GET_NEW_JOB_REACHED_LIMIT = 307
}
override fun handle(componentID: Int, buttonID: Int) {
val playerJobManager: JobManager = JobManager.getInstance(player!!)
val job = playerJobManager.job ?: return
val originalAmount = playerJobManager.jobOriginalAmount
when (stage) {
START_DIALOGUE -> showTopics(
IfTopic(
FacialExpression.HAPPY,
"I have the items you wanted.",
TURN_IN_ITEMS_1,
(job.type == JobType.PRODUCTION && amountInInventory(player!!, (job as ProductionJobs).itemId) > 0)
), Topic(
FacialExpression.HALF_ASKING, "Can you remind me what job you gave me?", REMIND_JOB
), Topic(
FacialExpression.HALF_ASKING, "Can I have a task list to remind me of my job?", GET_TASK_LIST
), Topic(
FacialExpression.HALF_GUILTY, "I'd like a new job please.", GET_NEW_JOB_1
)
)
TURN_IN_ITEMS_1 -> {
job as ProductionJobs
val itemName = Item(job.itemId).name.lowercase()
val itemNamePluralized = if (playerJobManager.jobAmount > 1) StringUtils.plusS(itemName) else itemName
npcl("Splendid! Now, I needed $originalAmount $itemNamePluralized.")
stage = TURN_IN_ITEMS_2
}
TURN_IN_ITEMS_2 -> {
if (playerJobManager.jobAmount == originalAmount) {
npcl("So far, you haven't brought me any, so I'm waiting for ${playerJobManager.jobAmount}.")
} else {
npcl("So far, you have brought me ${originalAmount - playerJobManager.jobAmount}, so I'm waiting for ${playerJobManager.jobAmount}.")
}
stage = TURN_IN_ITEMS_3
}
TURN_IN_ITEMS_3 -> {
if (amountInInventory(player!!, (job as ProductionJobs).itemId) >= playerJobManager.jobAmount) {
npcl("I can see that you have plenty, would you like to hand some over to complete your job?")
} else {
npcl("I can see that you have some, would you like to hand them over?")
}
stage = TURN_IN_ITEMS_4
}
TURN_IN_ITEMS_4 -> showTopics(
Topic("Yes, I'll give you what I have.", TURN_IN_ITEMS_5, skipPlayer = true),
Topic("No, I'll keep hold of it for now.", END_DIALOGUE, skipPlayer = true)
)
TURN_IN_ITEMS_5 -> {
playerJobManager.turnInItems()
if (playerJobManager.jobAmount == 0) {
playerJobManager.rewardPlayer()
npcl("There you go, thanks for your help. You're quite a skilled worker!")
} else {
npcl("Thanks for your help. Come back when you've got more!")
}
stage = END_DIALOGUE
}
REMIND_JOB -> {
when (job.type) {
JobType.PRODUCTION -> {
job as ProductionJobs
val itemName = Item(job.itemId).name.lowercase()
val itemNamePluralized =
if (playerJobManager.jobAmount > 1) StringUtils.plusS(itemName) else itemName
npcl("You still need to gather ${playerJobManager.jobAmount} more $itemNamePluralized.")
}
JobType.BONE_BURYING -> {
job as BoneBuryingJobs
val boneName = Item(job.boneIds.first()).name.lowercase()
val boneNamePluralized =
if (playerJobManager.jobAmount > 1) StringUtils.plusS(boneName) else boneName
npcl("You still need to bury ${playerJobManager.jobAmount} more $boneNamePluralized in the ${job.buryArea.title}.")
}
JobType.COMBAT -> {
job as CombatJobs
val monsterName = NPC(job.monsterIds.first()).name.lowercase()
val monsterNamePluralized =
if (playerJobManager.jobAmount > 1) StringUtils.plusS(monsterName) else monsterName
npcl("You still need to kill ${playerJobManager.jobAmount} more $monsterNamePluralized.")
}
}
stage = END_DIALOGUE
}
GET_TASK_LIST -> {
if (hasAnItem(player!!, Items.TASK_LIST_13464).exists()) {
npcl("You already have one of those!")
} else {
when (addItem(player!!, Items.TASK_LIST_13464)) {
true -> npcl("Here you go then.")
false -> dialogue("You don't have enough space in your inventory.")
}
}
stage = END_DIALOGUE
}
GET_NEW_JOB_1 -> npcl("Let me see if I've got any work for you.").also {
if (playerJobManager.hasReachedJobLimit()) {
stage = GET_NEW_JOB_REACHED_LIMIT
} else {
playerJobManager.generate(npc!!)
stage = if (playerJobManager.hasJob()) GET_NEW_JOB_2 else GET_NEW_JOB_NONE
}
}
GET_NEW_JOB_2 -> npcl(playerJobManager.getAssignmentMessage()).also { stage = GET_NEW_JOB_3 }
// Historically, the player would also have the option to ask for an easier task
GET_NEW_JOB_3 -> playerl("Okay, off I go!").also { stage = GET_NEW_JOB_4 }
GET_NEW_JOB_4 -> npcl("There, I've updated your task list to show your new job. Best of luck!").also {
stage = GET_NEW_JOB_5
}
GET_NEW_JOB_5 -> playerl("Thanks.").also { stage = END_DIALOGUE }
GET_NEW_JOB_NONE -> npcl("I'm sorry, I don't currently have any jobs that you're qualified for.").also {
stage = END_DIALOGUE
}
GET_NEW_JOB_REACHED_LIMIT -> npcl("You've hit your limit for the day. Come back tomorrow!").also {
stage = END_DIALOGUE
}
}
}
}

View file

@ -0,0 +1,23 @@
package content.global.activity.jobs
import content.global.activity.jobs.impl.Employers
import core.tools.RandomFunction
/**
* The interface for a job that a player can be assigned.
*
* TODO: Once player data is stored in a database with support for migrations, implement a per-player field to store
* the player's current employer, so that multiple employers can assign the same job, but the player will only be
* able to turn the job into the employer that assigned it to them.
*/
interface Job {
val type: JobType
val lower: Int
val upper: Int
val employer: Employers
fun getAmount(): Int {
return RandomFunction.random(lower, upper + 1)
}
}

View file

@ -1,114 +1,215 @@
package content.global.activity.jobs
import content.global.activity.jobs.impl.BoneBuryingJobs
import content.global.activity.jobs.impl.CombatJobs
import content.global.activity.jobs.impl.ProductionJobs
import core.ServerStore
import core.ServerStore.Companion.getInt
import core.api.*
import content.global.activity.jobs.impl.GatheringJobs
import content.global.activity.jobs.impl.SlayingJobs
import core.game.event.BoneBuryEvent
import core.game.event.EventHook
import core.game.event.JobAssignmentEvent
import core.game.event.NPCKillEvent
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.tools.StringUtils
import org.json.simple.JSONObject
import org.rs09.consts.Items
import core.ServerStore
import core.ServerStore.Companion.getInt
import java.lang.Integer.min
object JobManager {
@JvmStatic
fun updateJobRemaining(player: Player, amount: Int = 0) {
val cur = getAttribute(player, "jobs:amount", 0)
val new = cur - amount
val jobType = JobType.values()[getAttribute(player, "jobs:type", 0)]
val jobId = getAttribute(player, "jobs:id", 0)
/**
* Manages the player's job data & progression.
*
* @source https://runescape.wiki/w/Jobs?oldid=831782
*/
class JobManager(val player: Player? = null) : LoginListener, PersistPlayer {
var job: Job? = null
var jobAmount: Int = 0
var jobOriginalAmount: Int = 0
when (jobType) {
JobType.GATHERING -> { }
private fun hasLevelRequirement(job: ProductionJobs): Boolean {
if (player == null) return false
if (player.isArtificial) return false
JobType.SLAYING -> {
val job = SlayingJobs.values()[jobId]
if (new % 5 == 0 && new > 0) {
sendMessage(
player,
"You have $new ${NPC(job.ids[0]).name.lowercase()} left to go."
)
} else if (new == 0) {
sendMessage(
player,
"<col=00AA00>You have completed your job.</col>"
)
}
}
}
setAttribute(player, "jobs:amount", new)
return getStatLevel(player, job.skill) >= job.lvlReq
}
@JvmStatic
fun rewardPlayer(player: Player, npc: NPC) {
val amt = getAttribute(player, "jobs:original_amount", 0)
val jobType = JobType.values()[getAttribute(player, "jobs:type", 0)]
val jobId = getAttribute(player, "jobs:id", 0)
fun hasJob(): Boolean = this.job != null
when (jobType) {
JobType.GATHERING -> {
val it = Item(GatheringJobs.values()[jobId].itemId)
var amount = amountInInventory(player, it.id)
val needed = getAttribute(player, "jobs:amount", 0)
// Historically the job limit would be 6 jobs per hour of play-time, using 3 per day for balance purposes
fun hasReachedJobLimit(): Boolean = player?.let { getStoreFile().getInt(it.username.lowercase()) >= 3 } ?: false
if (amount == 0) {
openDialogue(player, CancelJobDialogueFile(), npc)
return
}
fun generate(npc: NPC) {
if (player == null) return
if (player.isArtificial) return
if (amount < needed) {
sendItemDialogue(
player,
GatheringJobs.values()[jobId].itemId,
"You still need to gather ${needed - amount} more."
)
val instance = getInstance(player)
removeItem(player, Item(it.id, amount))
setAttribute(player, "jobs:amount", needed - amount)
return
}
if (amount > needed) {
amount = needed
}
removeItem(player, Item(it.id, amount))
}
JobType.SLAYING -> {
val needed = getAttribute(player, "jobs:amount", 0)
if (needed > 0) {
sendDialogue(
player,
"You still need to kill $needed more ${NPC(SlayingJobs.values()[jobId].ids[0]).name.lowercase()}."
)
return
}
sendDialogue(
player,
"Excellent work, thank you! Here's your reward."
// Create a list of jobs that the player can do and are given by the NPC being interacted with
val potentialJobs: List<Job> = (
ProductionJobs.values().filter { hasLevelRequirement(it) }
+ BoneBuryingJobs.values()
+ CombatJobs.values()
)
}
}
.filter { job -> job.employer.npcId == npc.id }
addItemOrDrop(player, Items.COINS_995, 250 * amt)
val job = potentialJobs.randomOrNull() ?: return
removeAttribute(player, "jobs:id")
removeAttribute(player, "jobs:amount")
removeAttribute(player, "jobs:original_amount")
removeAttribute(player, "jobs:type")
instance.job = job
this.jobAmount = job.getAmount()
this.jobOriginalAmount = instance.jobAmount
player.dispatch(JobAssignmentEvent(job.type, npc))
getStoreFile()[player.username.lowercase()] = getStoreFile().getInt(player.username.lowercase()) + 1
}
fun getStoreFile(): JSONObject {
return ServerStore.getArchive("daily-jobs-tracking")
fun getAssignmentMessage(): String? {
if (player == null) return null
if (player.isArtificial) return null
val instance = getInstance(player)
val job = instance.job ?: return null
return when (job.type) {
JobType.PRODUCTION -> {
job as ProductionJobs
val itemName = Item(job.itemId).name.lowercase()
val itemNamePluralized = if (this.jobAmount > 1) StringUtils.plusS(itemName) else itemName
"Okay, your job is to bring me ${this.jobAmount} $itemNamePluralized."
}
JobType.BONE_BURYING -> {
job as BoneBuryingJobs
val boneName = Item(job.boneIds.first()).name.lowercase()
val boneNamePluralized = if (this.jobAmount > 1) StringUtils.plusS(boneName) else boneName
"Okay, your job is to bury ${this.jobAmount} $boneNamePluralized in the ${job.buryArea.title}."
}
JobType.COMBAT -> {
job as CombatJobs
val monsterName = NPC(job.monsterIds.first()).name.lowercase()
val monsterNamePluralized = if (this.jobAmount > 1) StringUtils.plusS(monsterName) else monsterName
"Okay, your job is to kill ${this.jobAmount} $monsterNamePluralized."
}
}
}
/**
* TODO: Allow players to turn-in noted items (authentic to 2009)
*/
fun turnInItems() {
if (player == null) return
if (player.isArtificial) return
val instance = getInstance(player)
val job = instance.job ?: return
if (job.type != JobType.PRODUCTION) return
val itemId = (job as ProductionJobs).itemId
val amountHeld = amountInInventory(player, itemId)
val amountToTurnIn = min(amountHeld, instance.jobAmount)
removeItem(player, Item(itemId, amountToTurnIn))
instance.jobAmount -= amountToTurnIn
}
fun rewardPlayer() {
if (player == null) return
if (player.isArtificial) return
val instance = getInstance(player)
addItemOrDrop(player, Items.COINS_995, 250 * instance.jobOriginalAmount)
instance.job = null
instance.jobAmount = -1
instance.jobOriginalAmount = -1
}
override fun login(player: Player) {
if (player.isArtificial) return
val jobManager = JobManager(player)
setAttribute(player, "job-manager", jobManager)
player.hook(Event.BoneBuried, object : EventHook<BoneBuryEvent> {
override fun process(entity: Entity, event: BoneBuryEvent) {
if (entity !is Player) return
if (entity.isArtificial) return
val instance = getInstance(entity)
if (!instance.hasJob()) return
if (instance.job?.type != JobType.BONE_BURYING) return
if (instance.jobAmount == 0) return
val job = (instance.job as BoneBuryingJobs)
if (inBorders(entity, job.buryArea.zoneBorder) && event.boneId in job.boneIds) {
instance.jobAmount--
}
}
})
player.hook(Event.NPCKilled, object : EventHook<NPCKillEvent> {
override fun process(entity: Entity, event: NPCKillEvent) {
if (entity !is Player) return
if (entity.isArtificial) return
val instance = getInstance(entity)
if (!instance.hasJob()) return
if (instance.job?.type != JobType.COMBAT) return
if (instance.jobAmount == 0) return
val job = (instance.job as CombatJobs)
if (event.npc.id in job.monsterIds) {
instance.jobAmount--
}
}
})
}
// TODO: Implement proper saving of job data to JSONObject once player save migration is possible
override fun savePlayer(player: Player, save: JSONObject) {
val instance = getInstance(player)
val jobId: Int = instance.job?.let {
when (it.type) {
JobType.PRODUCTION -> ProductionJobs.values().indexOf(it)
JobType.COMBAT -> CombatJobs.values().indexOf(it)
JobType.BONE_BURYING -> BoneBuryingJobs.values().indexOf(it)
}
} ?: -1
setAttribute(player, "/save:jobs:id", jobId)
setAttribute(player, "/save:jobs:type", instance.job?.type?.ordinal ?: -1)
setAttribute(player, "/save:jobs:amount", instance.jobAmount)
setAttribute(player, "/save:jobs:original_amount", instance.jobOriginalAmount)
}
// TODO: Implement proper loading of job data from JSONObject once player save migration is possible
override fun parsePlayer(player: Player, data: JSONObject) {
val instance = getInstance(player)
val jobId = getAttribute(player, "jobs:id", -1)
val jobType = getAttribute(player, "jobs:type", -1)
instance.job = when (JobType.values().getOrNull(jobType)) {
JobType.PRODUCTION -> ProductionJobs.values().getOrNull(jobId)
JobType.COMBAT -> CombatJobs.values().getOrNull(jobId)
JobType.BONE_BURYING -> BoneBuryingJobs.values().getOrNull(jobId)
else -> null
}
instance.jobAmount = getAttribute(player, "jobs:amount", -1)
instance.jobOriginalAmount = getAttribute(player, "jobs:original_amount", -1)
}
companion object {
@JvmStatic
fun getInstance(player: Player): JobManager {
return player.getAttribute("job-manager", JobManager(player))
}
fun getStoreFile(): JSONObject {
return ServerStore.getArchive("daily-jobs-tracking")
}
}
}

View file

@ -1,6 +1,13 @@
package content.global.activity.jobs
/**
* An enum of the different types of jobs that a player can be assigned.
*
* Note: Due to how player save files keep track of the player's current job, it is essential that
* new entries are only appended to the end of this enum, and the ordering of existing entries is not changed.
*/
enum class JobType {
GATHERING,
SLAYING
PRODUCTION,
COMBAT,
BONE_BURYING
}

View file

@ -0,0 +1,139 @@
package content.global.activity.jobs
import content.global.activity.jobs.impl.BoneBuryingJobs
import content.global.activity.jobs.impl.CombatJobs
import content.global.activity.jobs.impl.ProductionJobs
import core.api.addItem
import core.api.hasAnItem
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.game.dialogue.Topic
import core.game.node.entity.npc.NPC
import core.game.node.item.Item
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
import core.tools.StringUtils
import org.rs09.consts.Items
/**
* The dialogue file to handle a player asking about work with any employer which they aren't currently working for.
*/
class StartJobDialogueFile : DialogueFile() {
companion object {
const val GET_TASK_LIST_1 = 1
const val GET_TASK_LIST_2 = 2
const val GET_TASK_LIST_YES = 3
const val GET_JOB_1 = 101
const val GET_JOB_2 = 102
const val GET_JOB_3 = 103
const val GET_JOB_4 = 104
const val GET_JOB_5 = 105
const val GET_JOB_NONE = 201
const val GET_JOB_EMPLOYED_1 = 301
const val GET_JOB_EMPLOYED_2 = 302
const val GET_JOB_LIMIT_REACHED = 401
}
override fun handle(componentID: Int, buttonID: Int) {
val playerJobManager: JobManager = JobManager.getInstance(player!!)
when (stage) {
START_DIALOGUE -> playerl(FacialExpression.ASKING, "Do you have any jobs for me?").also {
stage = if (hasAnItem(player!!, Items.TASK_LIST_13464).exists()) {
if (playerJobManager.hasJob()) {
GET_JOB_EMPLOYED_1
} else {
GET_JOB_1
}
} else {
GET_TASK_LIST_1
}
}
GET_TASK_LIST_1 -> npcl("Well, first of all, I can see that you don't have a task list to remind you about your current job. Would you like a task list now?").also {
stage = GET_TASK_LIST_2
}
GET_TASK_LIST_2 -> showTopics(
Topic("Yes, please.", GET_TASK_LIST_YES),
Topic("No, thanks.", if (playerJobManager.hasJob()) GET_JOB_EMPLOYED_1 else GET_JOB_1)
)
GET_TASK_LIST_YES -> {
when (addItem(player!!, Items.TASK_LIST_13464)) {
true -> npcl("Here you go then.").also {
stage = if (playerJobManager.hasJob()) GET_JOB_EMPLOYED_1 else GET_JOB_1
}
false -> dialogue("You don't have enough space in your inventory.").also { stage = END_DIALOGUE }
}
}
GET_JOB_1 -> npcl("Let me see if I've got any work for you.").also {
if (playerJobManager.hasReachedJobLimit()) {
stage = GET_JOB_LIMIT_REACHED
} else {
playerJobManager.generate(npc!!)
stage = if (playerJobManager.hasJob()) GET_JOB_2 else GET_JOB_NONE
}
}
GET_JOB_2 -> npcl(playerJobManager.getAssignmentMessage()).also { stage = GET_JOB_3 }
// Historically, the player would also have the option to ask for an easier task
GET_JOB_3 -> playerl("Okay, off I go!").also { stage = GET_JOB_4 }
GET_JOB_4 -> npcl("There, I've updated your task list to show your new job. Best of luck!").also {
stage = GET_JOB_5
}
GET_JOB_5 -> playerl("Thanks.").also { stage = END_DIALOGUE }
GET_JOB_EMPLOYED_1 -> {
val job = playerJobManager.job ?: return
val employerName = NPC(job.employer.npcId).name
val amount = playerJobManager.jobAmount
val originalAmount = playerJobManager.jobOriginalAmount
if (amount == 0) {
npcl("Hang about. Aren't you working for $employerName? It looks like you've complete their job, return to them for your reward.")
stage = END_DIALOGUE
} else {
when (job.type) {
JobType.PRODUCTION -> {
job as ProductionJobs
val itemName = Item(job.itemId).name.lowercase()
val itemNamePluralized = if (originalAmount > 1) StringUtils.plusS(itemName) else itemName
npcl("Hang about. Aren't you working for $employerName? You were asked for $originalAmount $itemNamePluralized and still have $amount more to go.")
}
JobType.BONE_BURYING -> {
job as BoneBuryingJobs
val boneName = Item(job.boneIds.first()).name.lowercase()
val boneNamePluralized = if (originalAmount > 1) StringUtils.plusS(boneName) else boneName
npcl("Hang about. Aren't you working for $employerName? You were asked to bury $originalAmount $boneNamePluralized in the ${job.buryArea.title} and still have $amount more to go.")
}
JobType.COMBAT -> {
job as CombatJobs
val monsterName = NPC(job.monsterIds.first()).name.lowercase()
val monsterNamePluralized = if (originalAmount > 1) StringUtils.plusS(monsterName) else monsterName
npcl("Hang about. Aren't you working for $employerName? You were asked to kill $originalAmount $monsterNamePluralized and still have $amount more to go.")
}
}
stage = GET_JOB_EMPLOYED_2
}
}
GET_JOB_EMPLOYED_2 -> showTopics(
Topic("Oh yes. I better go and finish their job first.", END_DIALOGUE),
Topic("I'd like a new job instead, please.", GET_JOB_1)
)
GET_JOB_NONE -> npcl("I'm sorry, I don't currently have any jobs that you're qualified for.").also {
stage = END_DIALOGUE
}
GET_JOB_LIMIT_REACHED -> npcl("You've hit your limit for the day. Come back tomorrow!").also {
stage = END_DIALOGUE
}
}
}
}

View file

@ -0,0 +1,70 @@
package content.global.activity.jobs
import content.global.activity.jobs.impl.BoneBuryingJobs
import content.global.activity.jobs.impl.CombatJobs
import content.global.activity.jobs.impl.ProductionJobs
import core.api.sendDialogue
import core.api.sendItemDialogue
import core.api.sendNPCDialogue
import core.game.interaction.InteractionListener
import core.game.node.entity.npc.NPC
import core.game.node.item.Item
import core.tools.StringUtils
import org.rs09.consts.Items
/**
* Handles the read option of the Task List item.
*/
class TaskListReadListener : InteractionListener {
override fun defineListeners() {
on(Items.TASK_LIST_13464, ITEM, "read") { player, _ ->
val playerJobManager: JobManager = JobManager.getInstance(player)
val job = playerJobManager.job
val amount = playerJobManager.jobAmount
if (job == null) {
sendDialogue(player, "I have not been assigned a job!")
return@on false
}
if(amount == 0) {
sendDialogue(
player, "I have completed my job. I should return to ${NPC(job.employer.npcId).name} for my reward."
)
return@on true
}
when (job.type) {
JobType.PRODUCTION -> {
job as ProductionJobs
val itemName = Item(job.itemId).name.lowercase()
val itemNamePluralized = if (amount > 1) StringUtils.plusS(itemName) else itemName
sendItemDialogue(
player, job.itemId, "My job is to gather $amount more $itemNamePluralized."
)
}
JobType.BONE_BURYING -> {
job as BoneBuryingJobs
val boneName = Item(job.boneIds.first()).name.lowercase()
val boneNamePluralized = if (amount > 1) StringUtils.plusS(boneName) else boneName
sendItemDialogue(
player,
job.boneIds.first(),
"My job is to bury $amount more $boneNamePluralized in the ${job.buryArea.title}."
)
}
JobType.COMBAT -> {
job as CombatJobs
val monsterName = NPC(job.monsterIds.first()).name.lowercase()
val monsterNamePluralized = if (amount > 1) StringUtils.plusS(monsterName) else monsterName
sendNPCDialogue(
player, job.monsterIds.first(), "My job is to kill $amount more $monsterNamePluralized."
)
}
}
return@on true
}
}
}

View file

@ -1,224 +1,45 @@
package content.global.activity.jobs
import content.global.activity.jobs.impl.GatheringJobs
import content.global.activity.jobs.impl.SlayingJobs
import core.api.*
import core.game.event.EventHook
import core.game.event.JobAssignmentEvent
import core.game.event.NPCKillEvent
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.item.Item
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import core.ServerStore.Companion.getInt
import core.api.Event
import core.game.interaction.InteractionListener
import content.global.activity.jobs.impl.Employers
import core.api.openDialogue
import core.api.sendNPCDialogue
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.npc.NPC
/**
* Handles the work-for actions for the NPCs
* @author Ceikry
* @author vddCore
*/
class WorkForInteractionListener : InteractionListener, LoginListener {
companion object {
private val WEAPON_ICONS = arrayListOf(
Items.BRONZE_SCIMITAR_1321,
Items.STEEL_SCIMITAR_1325,
Items.RUNE_SCIMITAR_1333,
Items.BRONZE_MACE_1422,
Items.MITHRIL_WARHAMMER_1343
)
private val EMPLOYERS_AND_JOBS = mapOf(
NPCs.HANS_0 to listOf(
GatheringJobs.AIR_RUNE,
GatheringJobs.COWHIDES,
GatheringJobs.WATER_RUNE
),
NPCs.AGGIE_922 to listOf(
GatheringJobs.ASHES,
GatheringJobs.AIR_RUNE,
GatheringJobs.WATER_RUNE
),
NPCs.GILLIE_GROATS_3807 to listOf(
GatheringJobs.COWHIDES
),
NPCs.COOKING_TUTOR_4899 to listOf(
GatheringJobs.CAKE,
GatheringJobs.ANCHOVY_PIZZA,
GatheringJobs.COOKED_SALMON,
GatheringJobs.COOKED_TROUT,
GatheringJobs.MEAT_PIE,
GatheringJobs.MEAT_PIZZA,
GatheringJobs.PLAIN_PIZZA
),
NPCs.FISHING_TUTOR_4901 to listOf(
GatheringJobs.RAW_SALMON,
GatheringJobs.RAW_SHRIMP,
GatheringJobs.RAW_TROUT
),
NPCs.MINING_TUTOR_4902 to listOf(
GatheringJobs.COPPER_ORE,
GatheringJobs.TIN_ORE,
GatheringJobs.COAL,
GatheringJobs.IRON_ORE,
GatheringJobs.SILVER_ORE,
GatheringJobs.GOLD_ORE
),
NPCs.PRAYER_TUTOR_4903 to listOf(
GatheringJobs.SILVER_ORE
),
NPCs.SMELTING_TUTOR_4904 to listOf(
GatheringJobs.BRONZE_BAR,
GatheringJobs.IRON_BAR,
GatheringJobs.STEEL_BAR
),
NPCs.WOODCUTTING_TUTOR_4906 to listOf(
GatheringJobs.LOG,
GatheringJobs.OAK,
GatheringJobs.WILLOW
)
)
private val EMPLOYER_JOB_TYPES = mapOf(
NPCs.HANS_0 to JobType.GATHERING,
NPCs.MELEE_TUTOR_705 to JobType.SLAYING,
NPCs.AGGIE_922 to JobType.GATHERING,
NPCs.RANGED_TUTOR_1861 to JobType.SLAYING,
NPCs.GILLIE_GROATS_3807 to JobType.GATHERING,
NPCs.MAGIC_TUTOR_4707 to JobType.SLAYING,
NPCs.COOKING_TUTOR_4899 to JobType.GATHERING,
NPCs.FISHING_TUTOR_4901 to JobType.GATHERING,
NPCs.MINING_TUTOR_4902 to JobType.GATHERING,
NPCs.PRAYER_TUTOR_4903 to JobType.GATHERING,
NPCs.SMELTING_TUTOR_4904 to JobType.GATHERING,
NPCs.WOODCUTTING_TUTOR_4906 to JobType.GATHERING
)
private val EMPLOYER_IDS = EMPLOYER_JOB_TYPES.keys.toIntArray()
}
override fun login(player: Player) {
val remaining = getAttribute(player, "jobs:amount", -1)
val jobType = JobType.values()[getAttribute(player, "jobs:type", 0)]
if (jobType == JobType.SLAYING && remaining > 0) {
player.hook(Event.NPCKilled, JobKillHook)
}
}
class WorkForInteractionListener : InteractionListener {
override fun defineListeners() {
on(EMPLOYER_IDS, IntType.NPC, "work-for") { player, node ->
if (JobManager.getStoreFile().getInt(player.username.lowercase()) == 3) {
sendNPCDialogue(player, node.id, "You've hit your limit for the day. Come back tomorrow!")
on(
Employers.values().map { employer -> employer.npcId }.toIntArray(),
IntType.NPC,
"work-for"
) { player, node ->
val playerJobManager = JobManager.getInstance(player)
val job = playerJobManager.job
// Check if the player is talking to the NPC that gave them their job
if (job != null && job.employer.npcId == node.id) {
if (playerJobManager.jobAmount == 0) {
playerJobManager.rewardPlayer()
sendNPCDialogue(
player,
job.employer.npcId,
"There you go, thanks for your help. You're quite a skilled worker!"
)
} else {
openDialogue(player, CheckJobDialogueFile(), node as NPC)
}
return@on true
}
if (getAttribute(player, "jobs:id", -1) != -1) {
JobManager.rewardPlayer(player, node.asNpc())
return@on true
}
var amount: Int
val jobType = EMPLOYER_JOB_TYPES[node.id] ?: return@on false
val jobId = when (jobType) {
JobType.GATHERING -> {
val job = EMPLOYERS_AND_JOBS[node.id]?.filter { checkRequirement(player, it) }?.randomOrNull()
if (job == null) {
sendNPCDialogue(
player,
node.id,
"I'm sorry, I don't currently have any jobs that you're qualified for.",
core.game.dialogue.FacialExpression.HALF_THINKING
)
return@on true
}
amount = job.getAmount()
job.ordinal
}
JobType.SLAYING -> {
SlayingJobs.values().random().ordinal.also {
amount = SlayingJobs.values()[it].getAmount()
}
}
}
when (jobType) {
JobType.GATHERING -> {
val job = GatheringJobs.values()[jobId]
sendItemDialogue(
player,
job.itemId,
"You are assigned to gather $amount ${Item(job.itemId).name.lowercase()}"
)
}
JobType.SLAYING -> {
val job = SlayingJobs.values()[jobId]
sendItemDialogue(
player,
WEAPON_ICONS.random(),
"You are assigned to kill $amount ${NPC(job.ids[0]).name.lowercase()}"
)
player.unhook(JobKillHook) //try to unhook just in case they already had it hooked, unlikely but possible.
player.hook(Event.NPCKilled, JobKillHook)
}
}
setAttribute(player, "/save:jobs:id", jobId)
setAttribute(player, "/save:jobs:amount", amount)
setAttribute(player, "/save:jobs:original_amount", amount)
setAttribute(player, "/save:jobs:type", jobType.ordinal)
player.dispatch(JobAssignmentEvent(jobType, node.asNpc()))
openDialogue(player, StartJobDialogueFile(), node as NPC)
return@on true
}
}
private fun checkRequirement(player: Player, jobs: GatheringJobs?): Boolean {
jobs ?: return true
if (getStatLevel(player, jobs.skill) < jobs.lvlReq) {
return false
}
return true
}
private object JobKillHook : EventHook<NPCKillEvent> {
override fun process(entity: Entity, event: NPCKillEvent) {
if (entity !is Player) return
if (entity.isArtificial) return
val job = getAttribute(entity, "jobs:id", -1)
if (job !in 0 until SlayingJobs.values().size) {
return
}
val ids = SlayingJobs.values()[job].ids
if (event.npc.id in ids) {
JobManager.updateJobRemaining(entity, 1)
}
}
}
}

View file

@ -0,0 +1,30 @@
package content.global.activity.jobs.impl
import content.global.activity.jobs.Job
import content.global.activity.jobs.JobType
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items
/**
* An enum of the possible bone-burying jobs that can be assigned to a player.
*
* Note: Due to how player save files keep track of the player's current job, it is essential that
* new entries are only appended to the end of this enum, and the ordering of existing entries is not changed.
*/
enum class BoneBuryingJobs(val buryArea: BuryArea, val boneIds: List<Int>, override val employer: Employers) : Job {
BURY_DRAYNOR(BuryArea.DRAYNOR_WHEAT_FIELD, Bones.BONES, Employers.PRAYER_TUTOR),
BURY_LUMBRIDGE_GRAVEYARD(BuryArea.LUMBRIDGE_GRAVEYARD, Bones.BONES, Employers.PRAYER_TUTOR);
override val type = JobType.BONE_BURYING
override val lower = 22
override val upper = 26
enum class BuryArea(val zoneBorder: ZoneBorders, val title: String) {
DRAYNOR_WHEAT_FIELD(ZoneBorders(3107, 3265, 3132, 3293), "wheat field east of Draynor Village"),
LUMBRIDGE_GRAVEYARD(ZoneBorders(3238, 3191, 3252, 3204), "Lumbridge Graveyard");
}
object Bones {
val BONES = listOf(Items.BONES_526, Items.BONES_2530)
}
}

View file

@ -0,0 +1,209 @@
package content.global.activity.jobs.impl
import content.global.activity.jobs.Job
import content.global.activity.jobs.JobType
import org.rs09.consts.NPCs
/**
* An enum of the possible combat jobs that can be assigned to a player.
*
* Note: Due to how player save files keep track of the player's current job, it is essential that
* new entries are only appended to the end of this enum, and the ordering of existing entries is not changed.
*/
enum class CombatJobs(val monsterIds: List<Int>, override val employer: Employers) : Job {
CHICKENS(Monsters.CHICKENS, Employers.RANGED_TUTOR),
COWS(Monsters.COWS, Employers.MAGIC_TUTOR),
GIANT_SPIDERS(Monsters.GIANT_SPIDERS, Employers.MAGIC_TUTOR),
SCORPIONS(Monsters.SCORPIONS, Employers.MELEE_TUTOR),
GOBLINS(Monsters.GOBLINS, Employers.MELEE_TUTOR);
override val type = JobType.COMBAT
override val lower = 22
override val upper = 28
object Monsters {
val GIANT_SPIDERS = listOf(NPCs.GIANT_SPIDER_59, NPCs.GIANT_SPIDER_60)
val SCORPIONS = listOf(NPCs.SCORPION_107, NPCs.SCORPION_1477, NPCs.SCORPION_4402, NPCs.SCORPION_4403)
val GOBLINS = listOf(
NPCs.GOBLIN_100,
NPCs.GOBLIN_101,
NPCs.GOBLIN_102,
NPCs.GOBLIN_1769,
NPCs.GOBLIN_1770,
NPCs.GOBLIN_1771,
NPCs.GOBLIN_1772,
NPCs.GOBLIN_1773,
NPCs.GOBLIN_1774,
NPCs.GOBLIN_1775,
NPCs.GOBLIN_1776,
NPCs.GOBLIN_2274,
NPCs.GOBLIN_2275,
NPCs.GOBLIN_2276,
NPCs.GOBLIN_2277,
NPCs.GOBLIN_2278,
NPCs.GOBLIN_2279,
NPCs.GOBLIN_2280,
NPCs.GOBLIN_2281,
NPCs.GOBLIN_2678,
NPCs.GOBLIN_2679,
NPCs.GOBLIN_2680,
NPCs.GOBLIN_2681,
NPCs.GOBLIN_3264,
NPCs.GOBLIN_3265,
NPCs.GOBLIN_3266,
NPCs.GOBLIN_3267,
NPCs.GOBLIN_3726,
NPCs.GOBLIN_4261,
NPCs.GOBLIN_4262,
NPCs.GOBLIN_4263,
NPCs.GOBLIN_4264,
NPCs.GOBLIN_4265,
NPCs.GOBLIN_4266,
NPCs.GOBLIN_4267,
NPCs.GOBLIN_4268,
NPCs.GOBLIN_4269,
NPCs.GOBLIN_4270,
NPCs.GOBLIN_4271,
NPCs.GOBLIN_4272,
NPCs.GOBLIN_4273,
NPCs.GOBLIN_4274,
NPCs.GOBLIN_4275,
NPCs.GOBLIN_4276,
NPCs.GOBLIN_4407,
NPCs.GOBLIN_4408,
NPCs.GOBLIN_4409,
NPCs.GOBLIN_4410,
NPCs.GOBLIN_4411,
NPCs.GOBLIN_4412,
NPCs.GOBLIN_444,
NPCs.GOBLIN_445,
NPCs.GOBLIN_4479,
NPCs.GOBLIN_4480,
NPCs.GOBLIN_4481,
NPCs.GOBLIN_4482,
NPCs.GOBLIN_4483,
NPCs.GOBLIN_4484,
NPCs.GOBLIN_4485,
NPCs.GOBLIN_4486,
NPCs.GOBLIN_4487,
NPCs.GOBLIN_4488,
NPCs.GOBLIN_4489,
NPCs.GOBLIN_4490,
NPCs.GOBLIN_4491,
NPCs.GOBLIN_4492,
NPCs.GOBLIN_4499,
NPCs.GOBLIN_4633,
NPCs.GOBLIN_4634,
NPCs.GOBLIN_4635,
NPCs.GOBLIN_4636,
NPCs.GOBLIN_4637,
NPCs.GOBLIN_5855,
NPCs.GOBLIN_5856,
NPCs.GOBLIN_6125,
NPCs.GOBLIN_6126,
NPCs.GOBLIN_6132,
NPCs.GOBLIN_6133,
NPCs.GOBLIN_6279,
NPCs.GOBLIN_6280,
NPCs.GOBLIN_6281,
NPCs.GOBLIN_6282,
NPCs.GOBLIN_6283,
NPCs.GOBLIN_6284,
NPCs.GOBLIN_6402,
NPCs.GOBLIN_6403,
NPCs.GOBLIN_6404,
NPCs.GOBLIN_6405,
NPCs.GOBLIN_6406,
NPCs.GOBLIN_6407,
NPCs.GOBLIN_6408,
NPCs.GOBLIN_6409,
NPCs.GOBLIN_6410,
NPCs.GOBLIN_6411,
NPCs.GOBLIN_6412,
NPCs.GOBLIN_6413,
NPCs.GOBLIN_6414,
NPCs.GOBLIN_6415,
NPCs.GOBLIN_6416,
NPCs.GOBLIN_6417,
NPCs.GOBLIN_6418,
NPCs.GOBLIN_6419,
NPCs.GOBLIN_6420,
NPCs.GOBLIN_6421,
NPCs.GOBLIN_6422,
NPCs.GOBLIN_6423,
NPCs.GOBLIN_6424,
NPCs.GOBLIN_6425,
NPCs.GOBLIN_6426,
NPCs.GOBLIN_6427,
NPCs.GOBLIN_6428,
NPCs.GOBLIN_6429,
NPCs.GOBLIN_6430,
NPCs.GOBLIN_6431,
NPCs.GOBLIN_6432,
NPCs.GOBLIN_6433,
NPCs.GOBLIN_6434,
NPCs.GOBLIN_6435,
NPCs.GOBLIN_6436,
NPCs.GOBLIN_6437,
NPCs.GOBLIN_6438,
NPCs.GOBLIN_6439,
NPCs.GOBLIN_6440,
NPCs.GOBLIN_6441,
NPCs.GOBLIN_6442,
NPCs.GOBLIN_6443,
NPCs.GOBLIN_6444,
NPCs.GOBLIN_6445,
NPCs.GOBLIN_6446,
NPCs.GOBLIN_6447,
NPCs.GOBLIN_6448,
NPCs.GOBLIN_6449,
NPCs.GOBLIN_6450,
NPCs.GOBLIN_6451,
NPCs.GOBLIN_6452,
NPCs.GOBLIN_6453,
NPCs.GOBLIN_6454,
NPCs.GOBLIN_6455,
NPCs.GOBLIN_6456,
NPCs.GOBLIN_6457,
NPCs.GOBLIN_6458,
NPCs.GOBLIN_6459,
NPCs.GOBLIN_6460,
NPCs.GOBLIN_6461,
NPCs.GOBLIN_6462,
NPCs.GOBLIN_6463,
NPCs.GOBLIN_6464,
NPCs.GOBLIN_6465,
NPCs.GOBLIN_6466,
NPCs.GOBLIN_6467,
NPCs.GOBLIN_6490,
NPCs.GOBLIN_6491,
NPCs.GOBLIN_6492,
NPCs.GOBLIN_6493,
NPCs.GOBLIN_6494,
NPCs.GOBLIN_6495,
NPCs.GOBLIN_7964,
NPCs.GOBLIN_7965
)
val COWS = listOf(
NPCs.COW_81,
NPCs.COW_397,
NPCs.COW_955,
NPCs.COW_1767,
NPCs.COW_3309,
NPCs.COW_CALF_1766,
NPCs.COW_CALF_1768,
NPCs.COW_CALF_2310
)
val CHICKENS = listOf(
NPCs.CHICKEN_1017,
NPCs.CHICKEN_1401,
NPCs.CHICKEN_1402,
NPCs.CHICKEN_2313,
NPCs.CHICKEN_2314,
NPCs.CHICKEN_2315,
NPCs.CHICKEN_288,
NPCs.CHICKEN_41,
NPCs.CHICKEN_951,
)
}
}

View file

@ -0,0 +1,24 @@
package content.global.activity.jobs.impl
import org.rs09.consts.NPCs
/**
* An enum of NPCs that can assign the player a job.
*
* TODO: Add the rest of the era-correct employers
*/
enum class Employers(val npcId: Int) {
WOODCUTTING_TUTOR(NPCs.WOODCUTTING_TUTOR_4906),
MAGIC_TUTOR(NPCs.MAGIC_TUTOR_4707),
MELEE_TUTOR(NPCs.MELEE_TUTOR_705),
RANGED_TUTOR(NPCs.RANGED_TUTOR_1861),
COOKING_TUTOR(NPCs.COOKING_TUTOR_4899),
CRAFTING_TUTOR(NPCs.CRAFTING_TUTOR_4900),
FISHING_TUTOR(NPCs.FISHING_TUTOR_4901),
MINING_TUTOR(NPCs.MINING_TUTOR_4902),
SMELTING_TUTOR(NPCs.SMELTING_TUTOR_4904),
PRAYER_TUTOR(NPCs.PRAYER_TUTOR_4903),
HANS(NPCs.HANS_0),
GILLIE_GROATS(NPCs.GILLIE_GROATS_3807),
AGGIE(NPCs.AGGIE_922);
}

View file

@ -1,68 +0,0 @@
package content.global.activity.jobs.impl
import core.game.node.entity.skill.Skills
import core.tools.RandomFunction
enum class GatheringJobs(val lower: Int, val upper: Int, val lvlReq: Int, val itemId: Int,val skill: Int) {
LOG(20, 28, 1, 1511, Skills.WOODCUTTING),
COWHIDES(20, 28, 1, 1739, 0),
OAK(22, 28, 15, 1521, Skills.WOODCUTTING),
WATER_RUNE(20, 28, 5, 555, Skills.RUNECRAFTING),
EARTH_RUNE(20, 28, 9, 557, Skills.RUNECRAFTING),
FIRE_RUNE(20, 28, 14, 554, Skills.RUNECRAFTING),
AIR_RUNE(20, 28, 1, 556, Skills.RUNECRAFTING),
RUNE_ESS(20, 28, 1, 1436, Skills.MINING),
BALL_OF_WOOL(20, 28, 1, 1759, Skills.CRAFTING),
LEATHER_GLOVE(20, 28, 1, 1059, Skills.CRAFTING),
WILLOW(22, 28, 30, 1519, Skills.WOODCUTTING),
LEATHER_BOOT(24, 24, 1, 1061, Skills.CRAFTING),
BRONZE_DAGGER(24, 24, 1, 1205, Skills.SMITHING),
BRONZE_HELMS(22, 22, 1, 1139, Skills.SMITHING),
BRONZE_FULL_HELM(10, 10, 7, 1155, Skills.SMITHING),
BRONZE_CHAINBODY(10, 10, 11, 1103, Skills.SMITHING),
BRONZE_2H(10, 10, 14, 1307, Skills.SMITHING),
BRONZE_SCIM(10, 10, 5, 1321, Skills.SMITHING),
BRONZE_PLATEBODY(9, 10, 18, 1117, Skills.SMITHING),
BRONZE_PLATELEGS(9, 10, 16, 1075, Skills.SMITHING),
BRONZE_PLATESKIRTS(9, 10, 16, 1087, Skills.SMITHING),
BRONZE_WARHAMMER(9, 9, 9, 1337, Skills.SMITHING),
IRON_DAGGER(13, 13, 15, 1203, Skills.SMITHING),
IRON_CHAINBODY(10, 10, 26, 1101, Skills.SMITHING),
IRON_2H(9, 9, 29, 1309, Skills.SMITHING),
STEEL_BATTLEAXE(9, 9, 40, 1365, Skills.SMITHING),
STEEL_SCIMITAR(9, 9, 35, 1325, Skills.SMITHING),
STEEL_PLATEBODY(9, 10, 48, 1119, Skills.SMITHING),
STEEL_WARHAMMER(9, 10, 39, 1339, Skills.SMITHING),
LEATHER_CHAPS(22, 28, 18, 1095, Skills.CRAFTING),
LEATHER_BODY(22, 28, 14, 1129, Skills.CRAFTING),
LEATHER_COWL(22, 28, 9, 1167, Skills.CRAFTING),
LEATHER_COIF(22, 28, 38, 1169, Skills.CRAFTING),
RAW_SHRIMP(22, 28, 1, 317, Skills.FISHING),
COOKED_SHRIMP(22, 28, 1, 315, Skills.COOKING),
RAW_CRAYFISH(22, 28, 1, 13435, Skills.FISHING),
COOKED_CRAYFISH(22, 28, 1, 13433, Skills.COOKING),
RAW_TROUT(22, 28, 20, 335, Skills.FISHING),
COOKED_TROUT(22, 28, 15, 333, Skills.COOKING),
RAW_SALMON(22, 28, 30, 331, Skills.FISHING),
COOKED_SALMON(22, 28, 25, 329, Skills.COOKING),
CAKE(12, 16, 40, 1891, Skills.COOKING),
MEAT_PIE(12, 16, 20, 2327, Skills.COOKING),
PLAIN_PIZZA(12, 16, 35, 2289, Skills.COOKING),
MEAT_PIZZA(12, 16, 45, 2293, Skills.COOKING),
ANCHOVY_PIZZA(12, 16, 55, 2297, Skills.COOKING),
REDBERRY_PIE(12, 16, 10, 2325, Skills.COOKING),
COPPER_ORE(22, 28, 1, 436, Skills.MINING),
TIN_ORE(23, 26, 1, 438, Skills.MINING),
IRON_ORE(24, 24, 15, 440, Skills.MINING),
SILVER_ORE(22, 28, 20, 442, Skills.MINING),
COAL(22, 26, 30, 453, Skills.MINING),
GOLD_ORE(22, 24, 40, 444, Skills.MINING),
BRONZE_BAR(10, 12, 1, 2349, Skills.SMITHING),
IRON_BAR(22, 28, 15, 2351, Skills.SMITHING),
STEEL_BAR(22, 28, 30, 2353, Skills.SMITHING),
ASHES(26, 26, 1, 592, 0);
fun getAmount(): Int {
return RandomFunction.random(lower,upper + 1)
}
}

View file

@ -0,0 +1,80 @@
package content.global.activity.jobs.impl
import content.global.activity.jobs.Job
import content.global.activity.jobs.JobType
import core.game.node.entity.skill.Skills
/**
* An enum of the possible production jobs that can be assigned to a player.
*
* Note: Due to how player save files keep track of the player's current job, it is essential that
* new entries are only appended to the end of this enum, and the ordering of existing entries is not changed.
*/
enum class ProductionJobs(
override val lower: Int,
override val upper: Int,
val lvlReq: Int,
val itemId: Int,
val skill: Int,
override val employer: Employers
) : Job {
LOG(20, 28, 1, 1511, Skills.WOODCUTTING, Employers.WOODCUTTING_TUTOR),
COWHIDES(20, 28, 1, 1739, 0, Employers.HANS),
OAK(22, 28, 15, 1521, Skills.WOODCUTTING, Employers.WOODCUTTING_TUTOR),
WATER_RUNE(20, 28, 5, 555, Skills.RUNECRAFTING, Employers.HANS),
EARTH_RUNE(20, 28, 9, 557, Skills.RUNECRAFTING, Employers.AGGIE),
FIRE_RUNE(20, 28, 14, 554, Skills.RUNECRAFTING, Employers.AGGIE),
AIR_RUNE(20, 28, 1, 556, Skills.RUNECRAFTING, Employers.HANS),
RUNE_ESS(20, 28, 1, 1436, Skills.MINING, Employers.MINING_TUTOR),
BALL_OF_WOOL(20, 28, 1, 1759, Skills.CRAFTING, Employers.GILLIE_GROATS),
LEATHER_GLOVE(20, 28, 1, 1059, Skills.CRAFTING, Employers.GILLIE_GROATS),
WILLOW(22, 28, 30, 1519, Skills.WOODCUTTING, Employers.WOODCUTTING_TUTOR),
LEATHER_BOOT(24, 24, 1, 1061, Skills.CRAFTING, Employers.HANS),
BRONZE_DAGGER(24, 24, 1, 1205, Skills.SMITHING, Employers.SMELTING_TUTOR),
BRONZE_HELMS(22, 22, 1, 1139, Skills.SMITHING, Employers.SMELTING_TUTOR),
BRONZE_FULL_HELM(10, 10, 7, 1155, Skills.SMITHING, Employers.SMELTING_TUTOR),
BRONZE_CHAINBODY(10, 10, 11, 1103, Skills.SMITHING, Employers.SMELTING_TUTOR),
BRONZE_2H(10, 10, 14, 1307, Skills.SMITHING, Employers.SMELTING_TUTOR),
BRONZE_SCIM(10, 10, 5, 1321, Skills.SMITHING, Employers.SMELTING_TUTOR),
BRONZE_PLATEBODY(9, 10, 18, 1117, Skills.SMITHING, Employers.SMELTING_TUTOR),
BRONZE_PLATELEGS(9, 10, 16, 1075, Skills.SMITHING, Employers.SMELTING_TUTOR),
BRONZE_PLATESKIRTS(9, 10, 16, 1087, Skills.SMITHING, Employers.SMELTING_TUTOR),
BRONZE_WARHAMMER(9, 9, 9, 1337, Skills.SMITHING, Employers.SMELTING_TUTOR),
IRON_DAGGER(13, 13, 15, 1203, Skills.SMITHING, Employers.SMELTING_TUTOR),
IRON_CHAINBODY(10, 10, 26, 1101, Skills.SMITHING, Employers.SMELTING_TUTOR),
IRON_2H(9, 9, 29, 1309, Skills.SMITHING, Employers.SMELTING_TUTOR),
STEEL_BATTLEAXE(9, 9, 40, 1365, Skills.SMITHING, Employers.SMELTING_TUTOR),
STEEL_SCIMITAR(9, 9, 35, 1325, Skills.SMITHING, Employers.SMELTING_TUTOR),
STEEL_PLATEBODY(9, 10, 48, 1119, Skills.SMITHING, Employers.SMELTING_TUTOR),
STEEL_WARHAMMER(9, 10, 39, 1339, Skills.SMITHING, Employers.SMELTING_TUTOR),
LEATHER_CHAPS(22, 28, 18, 1095, Skills.CRAFTING, Employers.CRAFTING_TUTOR),
LEATHER_BODY(22, 28, 14, 1129, Skills.CRAFTING, Employers.CRAFTING_TUTOR),
LEATHER_COWL(22, 28, 9, 1167, Skills.CRAFTING, Employers.CRAFTING_TUTOR),
LEATHER_COIF(22, 28, 38, 1169, Skills.CRAFTING, Employers.CRAFTING_TUTOR),
RAW_SHRIMP(22, 28, 1, 317, Skills.FISHING, Employers.FISHING_TUTOR),
COOKED_SHRIMP(22, 28, 1, 315, Skills.COOKING, Employers.COOKING_TUTOR),
RAW_CRAYFISH(22, 28, 1, 13435, Skills.FISHING, Employers.FISHING_TUTOR),
COOKED_CRAYFISH(22, 28, 1, 13433, Skills.COOKING, Employers.COOKING_TUTOR),
RAW_TROUT(22, 28, 20, 335, Skills.FISHING, Employers.FISHING_TUTOR),
COOKED_TROUT(22, 28, 15, 333, Skills.COOKING, Employers.COOKING_TUTOR),
RAW_SALMON(22, 28, 30, 331, Skills.FISHING, Employers.FISHING_TUTOR),
COOKED_SALMON(22, 28, 25, 329, Skills.COOKING, Employers.COOKING_TUTOR),
CAKE(12, 16, 40, 1891, Skills.COOKING, Employers.GILLIE_GROATS),
MEAT_PIE(12, 16, 20, 2327, Skills.COOKING, Employers.COOKING_TUTOR),
PLAIN_PIZZA(12, 16, 35, 2289, Skills.COOKING, Employers.COOKING_TUTOR),
MEAT_PIZZA(12, 16, 45, 2293, Skills.COOKING, Employers.COOKING_TUTOR),
ANCHOVY_PIZZA(12, 16, 55, 2297, Skills.COOKING, Employers.COOKING_TUTOR),
REDBERRY_PIE(12, 16, 10, 2325, Skills.COOKING, Employers.GILLIE_GROATS),
COPPER_ORE(22, 28, 1, 436, Skills.MINING, Employers.MINING_TUTOR),
TIN_ORE(23, 26, 1, 438, Skills.MINING, Employers.MINING_TUTOR),
IRON_ORE(24, 24, 15, 440, Skills.MINING, Employers.MINING_TUTOR),
SILVER_ORE(22, 28, 20, 442, Skills.MINING, Employers.PRAYER_TUTOR),
COAL(22, 26, 30, 453, Skills.MINING, Employers.MINING_TUTOR),
GOLD_ORE(22, 24, 40, 444, Skills.MINING, Employers.MINING_TUTOR),
BRONZE_BAR(10, 12, 1, 2349, Skills.SMITHING, Employers.SMELTING_TUTOR),
IRON_BAR(22, 28, 15, 2351, Skills.SMITHING, Employers.SMELTING_TUTOR),
STEEL_BAR(22, 28, 30, 2353, Skills.SMITHING, Employers.SMELTING_TUTOR),
ASHES(26, 26, 1, 592, 0, Employers.AGGIE);
override val type = JobType.PRODUCTION
}

View file

@ -1,15 +0,0 @@
package content.global.activity.jobs.impl
import core.tools.RandomFunction
enum class SlayingJobs(val lower: Int, val upper: Int, vararg val ids: Int) {
CHICKEN(25,26,41,1017),
COW(25,25,397,1766,81,1767),
GIANT_SPIDER(22,25,59,60),
SCORPION(25,25,107,108,109,144,4402,4403),
GOBLIN(25,25,100,101,102,298,299,444,445,489,745,1769,1770,1771,1772,1773,1774,1775,1776,2274,2275,2276,2277,2278,2279,2280,2281,2678,2679,2680,2681,3060,3264,3265,3266,3267);
fun getAmount(): Int {
return RandomFunction.random(lower,upper + 1)
}
}

View file

@ -74,7 +74,7 @@ class LarryHandler(player: Player? = null) : core.game.dialogue.DialoguePlugin(p
}
val level = getStatLevel(player, skill)
System.out.println("Level: $level")
val expGained = points?.toDouble()?.times((level * 25))
System.out.print("exp: $expGained")
player.skills.addExperience(skill,expGained!!)

View file

@ -1,39 +1,19 @@
package content.global.activity.penguinhns
import org.json.simple.JSONObject
import core.ServerStore
import core.game.worldevents.PluginSet
import core.game.worldevents.WorldEvent
import core.game.world.GameWorld
import core.api.StartupListener
import core.api.log
import core.plugin.ClassScanner
import core.tools.Log
import org.json.simple.JSONObject
class PenguinHNSEvent : WorldEvent("penguin-hns"){
class PenguinHNSEvent : StartupListener {
val manager = PenguinManager()
var lastTrigger: Int = 0
var tickDelay = if(GameWorld.settings?.isDevMode == true) 100 else 100000
override fun checkActive(): Boolean {
return true //this event is always active.
}
override fun checkTrigger(): Boolean {
return PenguinManager.penguins.isEmpty()
}
override fun initialize() {
plugins = PluginSet(
LarryHandler(),
NotebookHandler(),
)
super.initialize()
fireEvent()
log("Penguin HNS initialized.")
}
override fun fireEvent() {
log("Loading penguins...")
override fun startup() {
manager.rebuildVars()
lastTrigger = GameWorld.ticks
log("Penguins loaded.")
ClassScanner.definePlugins(LarryHandler(), NotebookHandler())
log(this::class.java, Log.FINE, "Penguin HNS initialized.")
}
companion object {

View file

@ -7,6 +7,8 @@ import core.game.world.map.Location
import org.json.simple.JSONArray
import org.json.simple.JSONObject
import core.ServerStore.Companion.toJSONArray
import core.api.log
import core.tools.Log
import java.util.*
class PenguinManager{
@ -31,7 +33,7 @@ class PenguinManager{
private fun updateStoreFile(){
val jsonTags = JSONArray()
tagMapping.filter { it.value.isNotEmpty() }.forEach { (ordinal,taggers) ->
SystemLogger.logInfo(this::class.java, "$ordinal - ${taggers.first()}")
log(this::class.java, Log.FINE, "$ordinal - ${taggers.first()}")
val tag = JSONObject()
tag["ordinal"] = ordinal
tag["taggers"] = taggers
@ -64,8 +66,4 @@ class PenguinManager{
penguins = spawnedOrdinals.toMutableList()
}
}
fun log(message: String){
SystemLogger.logInfo(this::class.java, "[Penguins] $message")
}
}

View file

@ -1,5 +1,6 @@
package content.global.activity.penguinhns
import core.api.*
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.system.task.Pulse
@ -17,6 +18,7 @@ class PenguinSpyingHandler : InteractionListener {
player.sendMessage("You've already tagged this penguin.")
} else {
GameWorld.submit(SpyPulse(player, npc))
playJingle(player, 345)
}
return@on true
}

View file

@ -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
@ -26,12 +27,12 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
"Brimhaven mining site" to Location.create(2743, 3143, 0), // Brimhaven mining site
"South Crandor mining site" to Location.create(2822, 3239, 0), // South Crandor mining site (requires Dragon Slayer)
"Karamja mining site" to Location.create(2854, 3032, 0), // Karamja mining site
"Shilo Village mining site" to Location.create(2826, 2997, 0), // Shilo Village mining site/Gem rocks
"Shilo Village mining site" to Location.create(2826, 2997, 0), // Shilo Village mining site/Gem rocks (requires Shilo Village prereqs)
"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 Trials)
//"Lunar Isle mine" to Location.create(2140, 3939, 0), // Lunar Isle mine (requires Lunar Diplomacy?)
//"Miscellania coal mine" to Location.create(2529, 3887, 0), // Miscellania coal mine (requires Fremennik Trials)
//"Neitiznot runite mine" to Location.create(2376, 3835, 0), // Near the Neitiznot runite mine (requires Fremennik Trials) currently inaccessible as bridge does not work
"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 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)
"Kandarin Coal trucks" to Location.create(2589, 3485, 0), // Kandarin Coal trucks
@ -48,11 +49,11 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
"South-west Varrock mine" to Location.create(3176, 3362, 0), // South-west Varrock mine / Champion's Guild mine
"Varrock east bank" to Location.create(3259, 3407, 0), // Varrock east bank / Rune shop
"Lumbridge Swamp south-east mine" to Location.create(3227, 3150, 0), // Lumbridge Swamp south-east mine
//"Burgh de Rott bank" to Location.create(3500, 3219, 0), // Burgh de Rott bank (requires Quest to enter)
//"Burgh de Rott bank" to Location.create(3500, 3219, 0), // Burgh de Rott bank (requires quest to enter)
"Canifis Bank" to Location.create(3504, 3487, 0), // Canifis bank
"Mos Le'Harmless bank" to Location.create(3687, 2969, 0), // Mos Le'Harmless bank (requires Quest to enter but is currently accessible for Slayer)
"Mos Le'Harmless bank" to Location.create(3687, 2969, 0), // Mos Le'Harmless bank (requires quest to enter but is currently accessible for Slayer)
"Gnome stronghold Bank" to Location.create(2460, 3432, 0), // Gnome stronghold bank
"Lletya bank" to Location.create(2329, 3163, 0), // Lletya bank (requires Roving Elves?)
"Lletya bank" to Location.create(2329, 3163, 0), // Lletya bank (requires MEP1 prereqs)
"Piscatoris mining site" to Location.create(2336, 3636, 0), // Piscatoris mining site
"North Edgeville mining site" to Location.create(3101, 3569, 0), // Wilderness Steel mine / Zamorak mage mine
"Southern wilderness mine" to Location.create(3025, 3591, 0), // Wilderness skeleton mine
@ -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) {
@ -122,38 +115,55 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
selfBots.filter { it.isIdle() }.forEach { it.activate(true) }
}
isSpawned = true
Repository.sendNews("A shooting star level ${level.ordinal + 1} just crashed near ${location.toLowerCase()}!")
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
}
/**
@ -220,4 +231,4 @@ enum class ShootingStarType(val objectId: Int, val exp: Int, val totalStardust:
LEVEL_7(38662, 114, 40, 0.80),
LEVEL_8(38661, 145, 25, 0.85),
LEVEL_9(38660, 210, 15, 0.95);
}
}

View file

@ -48,9 +48,10 @@ class ShootingStarMiningPulse(player: Player?, node: Scenery?, val star: Shootin
val bonusXp = 75 * player.skills.getStaticLevel(Skills.MINING)
player.incrementAttribute("/save:shooting-star:bonus-xp", bonusXp)
Repository.sendNews(player.username + " is the discoverer of the crashed star near " + star.location + "!")
player.sendMessage("You have ${player.skills.experienceMutiplier * player.getAttribute("shooting-star:bonus-xp", 0).toDouble()} bonus xp towards mining stardust.")
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
}
@ -83,14 +84,13 @@ class ShootingStarMiningPulse(player: Player?, node: Scenery?, val star: Shootin
if (GameWorld.settings?.isDevMode == true) {
star.dustLeft = 1
}
star.decDust()
val bonusXp = player.getAttribute("shooting-star:bonus-xp", 0).toDouble()
var xp = star.level.exp.toDouble()
if(bonusXp > 0) {
val delta = Math.min(bonusXp, xp)
player.incrementAttribute("/save:shooting-star:bonus-xp", (-delta).toInt())
xp += delta;
xp += delta
if(player.getAttribute("shooting-star:bonus-xp", 0) <= 0) {
player.sendMessage("You have obtained all of your bonus xp from the star.")
}
@ -103,6 +103,8 @@ class ShootingStarMiningPulse(player: Player?, node: Scenery?, val star: Shootin
if(!inInventory(player, Items.ANCIENT_BLUEPRINT_14651) && !inBank(player, Items.ANCIENT_BLUEPRINT_14651)){
rollBlueprint(player)
}
star.decDust()
return false
}

View file

@ -12,10 +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) {
@ -26,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() {
@ -65,34 +82,52 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com
return@on true
}
val condition: (Player) -> Boolean = when(star.location.toLowerCase()){
"canifis bank" -> { p -> p.questRepository.isComplete("Priest in Peril")}
//"Burgh de Rott bank" -> { p -> p.questRepository.isComplete("Priest in Peril")} // for now, require this as it is in Morytania. remove when appropriate quests added - Crash
"crafting guild" -> {p -> hasLevelStat(p, Skills.CRAFTING, 40) }
"lletya bank" -> {p -> p.questRepository.isComplete("Roving Elves")}
"jatizso mine" -> {p -> p.questRepository.isComplete("Fremennik Trials")}
"south crandor mining site" -> {p -> p.questRepository.isComplete("Dragon Slayer")}
else -> {_ -> true}
class RingDialogue(val star: ShootingStar) : DialogueFile() {
val shouldWarn = when (star.location) {
"North Edgeville mining site",
"Southern wilderness mine",
"Wilderness hobgoblin mine",
"Pirates' Hideout mine",
"Lava Maze mining site",
"Mage Arena bank" -> true
else -> false
}
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, 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)) {
sendDialogue(player,"Magical forces prevent your teleportation.")
} else if (teleport(player, star.crash_locations[star.location]!!.transform(0, -1, 0), TeleportManager.TeleportType.MINIGAME)) {
getRingStoreFile()[player.username.toLowerCase()] = true
}
}
when (stage) {
0 -> dialogue(if (star.spriteSpawned) "The star sprite has already been freed." else "The star sprite is still trapped.").also { if (shouldWarn) stage++ else stage += 2 }
1 -> dialogue("WARNING: The star is located in the wilderness.").also { stage++ }
2 -> player.dialogueInterpreter.sendOptions("Teleport to the star?", "Yes", "No").also { stage++ }
3 -> when (buttonID) {
1 -> end().also { teleportToStar(player) }
2 -> end()
}
}
}
}
if(!condition.invoke(player) || player.skullManager.isWilderness){
sendDialogue(player, "Magical forces prevent your teleportation.")
return@on true
}
val shouldWarn = when(star.location){
"North Edgeville mining site",
"Southern wilderness mine",
"Wilderness Volcano bank",
"Wilderness hobgoblin mine",
"Pirates' Hideout mine",
"Lava Maze mining site",
"Mage Arena bank" -> true
else -> false
}
openDialogue(player, RingDialogue(shouldWarn, star))
openDialogue(player, RingDialogue(star))
return@on true
}
}
@ -103,6 +138,7 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com
}
define("submit", Privilege.ADMIN) { _, _ ->
star.rebuildVars()
star.fire()
}
@ -112,30 +148,11 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com
}
override fun startup() {
SystemLogger.logInfo(this::class.java, "Shooting Stars initialized.")
log(this::class.java, Log.FINE, "Shooting Stars initialized.")
}
private data class ScoreboardEntry(val player: String, val time: Int)
private class RingDialogue(val shouldWarn: Boolean, val star: ShootingStar) : DialogueFile(){
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> dialogue(if (star.spriteSpawned) "The star sprite has already been freed." else "The star sprite is still trapped.").also { if (shouldWarn) stage++ else stage += 2 }
1 -> dialogue("WARNING: The star is located in the wilderness.").also { stage++ }
2 -> player!!.dialogueInterpreter.sendOptions("Teleport to the star?", "Yes", "No").also { stage++ }
3 -> when (buttonID) {
1 -> teleport(player!!, star).also { end() }
2 -> end()
}
}
}
fun teleport(player: Player, star: ShootingStar){
teleport(player, star.crash_locations[star.location]!!.transform(0, -1, 0), TeleportManager.TeleportType.MINIGAME)
getRingStoreFile()[player.username.toLowerCase()] = true
}
}
companion object {
private val star = ShootingStar()
private val tickDelay = if(GameWorld.settings?.isDevMode == true) 200 else 25000

View file

@ -1,47 +0,0 @@
package content.global.activity.shootingstar
import core.game.node.entity.player.Player
import core.game.node.entity.state.PlayerState
import core.game.node.entity.state.State
import core.game.system.task.Pulse
import core.tools.ticksToSeconds
import org.json.simple.JSONObject
@PlayerState("shooting-star")
class ShootingStarState(player: Player? = null) : State(player) {
var ticksLeft = 1500
override fun save(root: JSONObject) {
root["ticksLeft"] = ticksLeft
}
override fun parse(_data: JSONObject) {
if(_data.containsKey("ticksLeft")){
ticksLeft = _data["ticksLeft"].toString().toInt()
}
}
override fun newInstance(player: Player?): State {
return ShootingStarState(player)
}
override fun createPulse() {
player ?: return
if(ticksLeft <= 0) return
pulse = object : Pulse(){
override fun pulse(): Boolean {
val minutes = ticksToSeconds(ticksLeft) / 60.0
if(minutes % 5.0 == 0.0){
player.sendMessage("<col=f0f095>You have $minutes minutes of your mining bonus left</col>")
}
if(ticksLeft-- <= 0){
player.sendMessage("<col=FF0000>Your mining bonus has run out!</col>")
pulse = null
return true
}
return false
}
}
}
}

View file

@ -0,0 +1,28 @@
package content.global.activity.shootingstar
import core.api.*
import core.game.system.timer.*
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import org.json.simple.*
class StarBonus : PersistTimer (1, "shootingstar:bonus") {
var ticksLeft = 1500
override fun save (root: JSONObject, entity: Entity) {
root["ticksLeft"] = ticksLeft.toString()
}
override fun parse (root: JSONObject, entity: Entity) {
ticksLeft = root["ticksLeft"].toString().toInt()
}
override fun run (entity: Entity) : Boolean {
if (entity is Player && ticksLeft == 500) {
entity.sendMessage("<col=f0f095>You have 5 minutes of your mining bonus left</col>")
} else if (entity is Player && ticksLeft == 0) {
entity.sendMessage("<col=FF0000>Your mining bonus has run out!</col>")
}
return ticksLeft-- > 0
}
}

View file

@ -82,7 +82,7 @@ class StarSpriteDialogue(player: Player? = null) : core.game.dialogue.DialoguePl
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage) {
0 -> {
npc("I'm a star sprite! I Was in my star in the sky, when it", "lost control and crashed into the ground. With half my", "star sticking into the ground, I became stuck.", "Fortunately, I was mined out by the kind creatures of")
npc("I'm a star sprite! I was in my star in the sky, when it", "lost control and crashed into the ground. With half my", "star sticking into the ground, I became stuck.", "Fortunately, I was mined out by the kind creatures of")
stage++
}
1 -> {
@ -198,7 +198,8 @@ class StarSpriteDialogue(player: Player? = null) : core.game.dialogue.DialoguePl
getStoreFile()[player.username.toLowerCase()] = true //flag daily as completed
player.registerState("shooting-star")?.init()
val timer = getOrStartTimer <StarBonus> (player)
timer.ticksLeft = 1500
if(wearingRing){
val item = intArrayOf(Items.COSMIC_RUNE_564, Items.ASTRAL_RUNE_9075, Items.GOLD_ORE_445, Items.COINS_995).random()
@ -263,8 +264,8 @@ class StarSpriteDialogue(player: Player? = null) : core.game.dialogue.DialoguePl
fun rollForRingBonus(player: Player, bonusId: Int, bonusBaseAmt: Int){
if(RandomFunction.roll(3)){
val state = player.states["shooting-star"] as? ShootingStarState ?: return
state.ticksLeft += secondsToTicks(TimeUnit.MINUTES.toSeconds(5).toInt())
var bonus = getOrStartTimer <StarBonus> (player)
bonus.ticksLeft += 500
sendMessage(player, colorize("%RYour ring shines dimly as if imbued with energy."))
} else if(RandomFunction.roll(5)){
addItem(player, bonusId, bonusBaseAmt)

View file

@ -3,6 +3,7 @@ package content.global.activity.ttrail;
import core.game.component.Component;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.tools.Log;
import core.tools.SystemLogger;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBorders;
@ -15,6 +16,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static core.api.ContentAPIKt.log;
/**
* Represents a clue scroll plugin.
* @author Vexia
@ -138,7 +141,7 @@ public abstract class ClueScrollPlugin extends MapZone implements Plugin<Object>
if(clue.getClueId() == 2681)
return;
if (CLUE_SCROLLS.containsKey(clue.getClueId())) {
SystemLogger.logErr(this.getClass(), "Error! Plugin already registered with clue id - " + clue.getClueId() + ", trying to register " + clue.getClass().getCanonicalName() + " the real plugin using the id is " + CLUE_SCROLLS.get(clue.getClueId()).getClass().getCanonicalName() + "!");
log(this.getClass(), Log.ERR, "Error! Plugin already registered with clue id - " + clue.getClueId() + ", trying to register " + clue.getClass().getCanonicalName() + " the real plugin using the id is " + CLUE_SCROLLS.get(clue.getClueId()).getClass().getCanonicalName() + "!");
return;
}
List<ClueScrollPlugin> organized = (List<ClueScrollPlugin>) ORGANIZED.get(clue.getLevel());
@ -169,7 +172,7 @@ public abstract class ClueScrollPlugin extends MapZone implements Plugin<Object>
public static Item getClue(ClueLevel clueLevel) {
List<ClueScrollPlugin> clues = ORGANIZED.get(clueLevel);
if (clues == null) {
SystemLogger.logErr(ClueScrollPlugin.class, "Error! There are no clues for level " + clueLevel + "!");
log(ClueScrollPlugin.class, Log.ERR, "Error! There are no clues for level " + clueLevel + "!");
return null;
}
ClueScrollPlugin clue = clues.get(RandomFunction.random(clues.size()));
@ -189,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;
}

View file

@ -57,7 +57,7 @@ public final class EmoteCluePlugin extends EmoteClueScroll {
public Plugin<Object> newInstance(Object arg) throws Throwable {
Emotes emote = Emotes.BECKON;
register(new EmoteCluePlugin("digsite-beckon", 2677, ClueLevel.MEDIUM, emote, Emotes.BOW, new int[][] { { 6328 }, { 1267 }, { 658 } }, "Beckon in the Digsite, near the<br>eastern winch. Bow or curtsy<br>before you talk to me.<br>Equip a green gnome hat,<br>snakeskin boots and an<br>iron pickaxe.", new ZoneBorders(3368, 3425, 3371, 3429)));
register(new EmoteCluePlugin("tai-bwo-beckon", 2678, ClueLevel.MEDIUM, emote, Emotes.CLAP, new int[][] { { 1099 }, { 2552, 2554, 2556, 2558, 2560, 2562, 2564, 2568 }, { 1143 } }, "Beckon in Tai Bwo<br>Wannai. Clap before<br>you talk to me.<br>Equip green<br>dragonhide chaps, a<br>ring of dueling and a<br>mithril medium helmet.", new ZoneBorders(2771, 3053, 2814, 3074)));
register(new EmoteCluePlugin("tai-bwo-beckon", 2678, ClueLevel.MEDIUM, emote, Emotes.CLAP, new int[][] { { 1099 }, { 2552, 2554, 2556, 2558, 2560, 2562, 2564, 2566, 2568 }, { 1143 } }, "Beckon in Tai Bwo<br>Wannai. Clap before<br>you talk to me.<br>Equip green<br>dragonhide chaps, a<br>ring of dueling and a<br>mithril medium helmet.", new ZoneBorders(2771, 3053, 2814, 3074)));
emote = Emotes.BLOW_KISS;
//register(new EmoteCluePlugin("shilo-kiss", 2681, ClueLevel.HARD, emote, new int[][] { { 4089 }, { 5016 }, { 1127 } }, "Blow a kiss between<br>the tables in Shilo<br>Village bank. Beware<br>of double agents!<br>Equip a blue mystic<br>hat, bone spear and<br>rune plate body.", new ZoneBorders(2849, 2950, 2855, 2957)));
emote = Emotes.BOW;
@ -99,7 +99,7 @@ public final class EmoteCluePlugin extends EmoteClueScroll {
//Fixed JFJ and Laugh Clues
//When Vexia emote is removed below.
//emote = Emotes.JUMP_FOR_JOY;
register(new EmoteCluePlugin("beehive-jump", 2703, ClueLevel.EASY, Emotes.JUMP_FOR_JOY, new int[][] { { 1833 }, { 648 }, { 1353 } }, "Jump for joy at the beehives.<br>Equip a desert shirt, green<br>gnome robe bottoms and a<br>steel axe.", new ZoneBorders(2762, 3439, 2764, 3441)));
register(new EmoteCluePlugin("beehive-jump", 2703, ClueLevel.EASY, Emotes.JUMP_FOR_JOY, new int[][] { { 1833 }, { 648 }, { 1353 } }, "Jump for joy at the beehives.<br>Equip a desert shirt, green<br>gnome robe bottoms and a<br>steel axe.", new ZoneBorders(2752, 3437,2766, 3450)));
// And emote, is replaced with what it is shortcutting Emotes.JUMP_FOR_JOY
// the clues work perfect. It seems to only be a problem with multiple emote clues.
// If you look around EmoteCluePlugin you will see there are multiple emote, shortcuts

View 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")
}

Some files were not shown because too many files have changed in this diff Show more