diff --git a/docs/public/dark.webp b/docs/public/dark.webp
new file mode 100644
index 0000000000..8850416b9a
Binary files /dev/null and b/docs/public/dark.webp differ
diff --git a/docs/public/dayv.webp b/docs/public/dayv.webp
new file mode 100644
index 0000000000..5e14cd369d
Binary files /dev/null and b/docs/public/dayv.webp differ
diff --git a/docs/public/felris.webp b/docs/public/felris.webp
new file mode 100644
index 0000000000..62d5feb2f7
Binary files /dev/null and b/docs/public/felris.webp differ
diff --git a/docs/public/fishy.webp b/docs/public/fishy.webp
new file mode 100644
index 0000000000..e1650bac62
Binary files /dev/null and b/docs/public/fishy.webp differ
diff --git a/docs/public/images/osbbingo3.png b/docs/public/images/osbbingo3.png
deleted file mode 100644
index 7c95c22ed0..0000000000
Binary files a/docs/public/images/osbbingo3.png and /dev/null differ
diff --git a/docs/src/content/docs/getting-started/changelog.md b/docs/src/content/docs/getting-started/changelog.md
index 3abac3ec2c..12948144a8 100644
--- a/docs/src/content/docs/getting-started/changelog.md
+++ b/docs/src/content/docs/getting-started/changelog.md
@@ -4,6 +4,71 @@ sidebar:
order: 3
---
+## Update 13/11/2024 [[4fbfe429e9a1bdf817175cf497177e47fefc6be6...e03afd628fd7e1aa460acc417d822c2d697f9087]]
+
+- Hacktoberfest has finished, and everyone has been sent out their custom merch and other prizes! Thank you to all who participated.
+- OSB Bingo #3 has finished! Read the page for it for more information: [OSB Bingo #3](/osb/miscelleanous/bingo/#osb-bingo-3-finished)
+
+### [[gc]]
+
+- Lowered the food cost for araxytes
+- The BiS amulet for nightmare is now the [[Amulet of rancour]]
+
+### [[00justas]]
+
+- Added Nid to the pets CL
+- Allow buying genie lamps with frog tokens
+- You can now create these items: [[Strange skull]] [[Skull sceptre]] [[Runed sceptre]] [[Skull sceptre(i)]]
+
+### [[DayV-git]]
+
+- Fix araxxor boss task requirements
+- Allow buying genie lamps with frog tokens
+- Fixed a bug with agility-alching sometimes picking the wrong item
+- Improved the formatting of some messages
+- Allow global gear presets equip command to use similar items
+- The bot now shows loot as pictures when using implings in [[/clue]]
+- Fixed wildy rev weapon boost
+- Added total kc and kc/h to tempoross/wintertodt return message
+- Added task and catacomb modifiers to [[/kill]] simulation command
+- Added missing Graceful creates / reverts (Add Brimhaven and Dark graceful revert and individual item reverts for Brimhaven, Dark and Varlamore - same as every other graceful recolour)
+- Solo nex drops now are spoilered if you get a purple
+- Superiors now always drop brimstone keys on konar tasks
+
+### [[Felris]]
+
+- Added error message when trying to use twitcher gloves without having them equipped
+- Added boost to zulrah for zul-andra teleports (uses 1 tele per 4 kills for a 10% boost)
+- Added boost to cerberus for keymaster teleports (uses 1 tele per 10 kills for a 10% boost)
+- Added boost to tormented demons for Guthixian temple teleports (uses 1 tele per 20 kills for a 10% boost)
+- Added boost to revs for Guthixian temple teleports (uses 1 tele per 20 kills for a 5% boost)
+- You can now create a Corrupted Youngllef from a Youngllef if you have atleast 1 CG kc
+- Added [Armoured zombie](https://oldschool.runescape.wiki/w/Armoured_zombie) as a killable monster
+ - Added Broken zombie axe to misc CL page
+ - Added [[Zombie axe]] to [[/create]]
+
+### [[nwjgit]]
+
+- Updated the wyrm agility pet droprate
+- Add the ability to create [[Forester's ration]]
+- Fixed ash sanctifier not giving proper XP and removing ashes
+
+### [[Lajnux]]
+
+- Balanced the construction xp/hr rates (Some things are slower/faster now)
+- Updated/fixed some mining code
+
+### [[TastyPumPum]]
+
+- Added the combat achievements for all 4 DT2 bosses
+
+### [[DarkWorldsArtist]]
+
+- Added [Crab](https://oldschool.runescape.wiki/w/Crab) killable monster
+ - Added [[Fresh crab claw]] [[Fresh crab shell]] to misc CL
+ - Added [[Diving apparatus]] [[Fishbowl helmet]] to [[/buy]]
+ - Added [[Crab helmet]] [[Crab claw]] to [[/create]]
+
## Update 16/10/2024 [[68b130088f5e365ec2a341cae48bc5b353ccc2ff...4fbfe429e9a1bdf817175cf497177e47fefc6be6]]
Bingo! We are running the 3rd official OSB bingo. See the [Bingo Page](/getting-started/bingo) for information.
diff --git a/docs/src/content/docs/getting-started/wiki.md b/docs/src/content/docs/getting-started/wiki.md
index af540805ed..fefc43a754 100644
--- a/docs/src/content/docs/getting-started/wiki.md
+++ b/docs/src/content/docs/getting-started/wiki.md
@@ -229,7 +229,7 @@ This is an automatically generated list of pages with possible issues to be look
[/bso/Skills/divination.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/divination.md): Doesnt use the new command formatting
-[/bso/Skills/Dungeoneering.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/Dungeoneering.md): Doesnt use the new command formatting
+[/bso/Skills/dungeoneering.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/dungeoneering.md): Doesnt use the new command formatting
[/bso/Skills/farming.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/farming.md): Doesnt use the new command formatting
@@ -251,9 +251,9 @@ This is an automatically generated list of pages with possible issues to be look
[/bso/Skills/runecraft.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/runecraft.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. `
`)
-[/bso/Skills/slayer/README.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/slayer/README.md): Doesnt use the new command formatting
+[/bso/Skills/Slayer/README.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/Slayer/README.md): Doesnt use the new command formatting
-[/bso/Skills/slayer/slayer-masks-helms.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/slayer/slayer-masks-helms.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. `
`)
+[/bso/Skills/Slayer/slayer-masks-helms.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/Slayer/slayer-masks-helms.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. `
`)
[/bso/Skills/smithing.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Skills/smithing.md): Doesnt use the new command formatting
@@ -269,8 +269,6 @@ This is an automatically generated list of pages with possible issues to be look
[/bso/Tames/monkey-tame.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/bso/Tames/monkey-tame.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. `
`)
-[/getting-started/bingo.mdx](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/getting-started/bingo.mdx): Doesnt use the new command formatting
-
[/getting-started/BSO.mdx](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/getting-started/BSO.mdx): Doesnt use the new command formatting
[/getting-started/changelog.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/getting-started/changelog.md): Doesnt use the new command formatting
@@ -279,8 +277,6 @@ This is an automatically generated list of pages with possible issues to be look
[/getting-started/FAQ.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/getting-started/FAQ.md): Doesnt use the new command formatting
-[/getting-started/hackertoberfest.mdx](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/getting-started/hackertoberfest.mdx): Doesnt use the new command formatting
-
[/getting-started/ironman-mode.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/getting-started/ironman-mode.md): Doesnt use the new command formatting
[/getting-started/randomizer.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/getting-started/randomizer.md): Doesnt use the new command formatting
@@ -365,7 +361,7 @@ This is an automatically generated list of pages with possible issues to be look
[/osb/Miscelleanous/achievement-diaries.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Miscelleanous/achievement-diaries.md): Doesnt use the new command formatting
-[/osb/Miscelleanous/bingo.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Miscelleanous/bingo.md): Doesnt use the new command formatting
+[/osb/Miscelleanous/bingo.mdx](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Miscelleanous/bingo.mdx): Doesnt use the new command formatting
[/osb/Miscelleanous/buyables.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Miscelleanous/buyables.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. `
`)
@@ -379,6 +375,8 @@ This is an automatically generated list of pages with possible issues to be look
[/osb/Miscelleanous/god-capes.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Miscelleanous/god-capes.md): Doesnt use the new command formatting
+[/osb/Miscelleanous/hackertoberfest.mdx](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Miscelleanous/hackertoberfest.mdx): Doesnt use the new command formatting
+
[/osb/Miscelleanous/music-cape.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Miscelleanous/music-cape.md): Doesnt use the new command formatting
[/osb/Miscelleanous/nightmare-zone.md](https://github.com/oldschoolgg/oldschoolbot/blob/master/docs/src/content/docs/osb/Miscelleanous/nightmare-zone.md): Doesnt use the new command formatting, Contains unintended HTML (e.g. `
`)
diff --git a/docs/src/content/docs/osb/Miscelleanous/bingo.md b/docs/src/content/docs/osb/Miscelleanous/bingo.md
deleted file mode 100644
index 0b4998e971..0000000000
--- a/docs/src/content/docs/osb/Miscelleanous/bingo.md
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: "Bingo"
----
-
-You can run community bingo's using the `/bingo` command, and the bot will automatically handle all of it for you.
-
-## Notes
-
-- Ironmen can join bingos for free. They cannot be given GP prizes, or create bingos.
-- Upon the bingo finishing, the creator of the bingo needs to do `/bingo finalize` to receive the GP pool. The creator of the bingo is responsible for handing out the GP, based on whatever split you have decided. You do not need to finalize the bingo on time, the bingo will automatically finish at the exact second it needs to, the finalize command just does some final things, and hands out the gp.
-- A person can participate in several bingos at once.
-- Bingos are private to the server they were made in. In other words, you can only join it from that server. Global bingos are limited to the official bingos. However, for any bingo, the commands/trips the players do (to get loot) can be done anywhere.
-
-## Creating a Bingo
-
-To create a bingo, you need to input the following things:
-
-- Title
-- Duration in days(7 = 7 days)
-- Start Date unix seconds. Use [https://hammertime.cyou/?tz=Etc%2FGMT](https://hammertime.cyou/?tz=Etc%2FGMT) to find this number. It's the last in the list, and is just a plain number that looks like this: `1695859800`. This indicates the exact time at which your bingo starts.
-- Ticket price: The ticket price per person. Each person must pay this when making their team. If the team disbands, the GP is refunded.
-- Team size: Size of the teams.
-- Organizers: people who are allowed to manage the bingo (Add tiles, etc)
-
-## Managing your Bingo
-
-Commands for managing the bingo are in `/bingo manage`. You can add/remove tiles, add extra GP to the prize pool, and more.
-
-### Adding Tiles
-
-You can add tiles in 2 ways.
-
-1. Add global tiles. You can select global tiles to add, which are tiles that are premade for you to use.
-2. Add custom tiles. You can add 2 kinds of tiles. AND tiles, OR tiles. Example:
- 1. `add_tile:coal+egg+trout` Adds a tile where you have to receive a coal, egg AND trout.
- 2. `add_tile:coal|egg|trout` Adds a tile where you have to receive a coal, or egg, or a trout.
diff --git a/docs/src/content/docs/getting-started/bingo.mdx b/docs/src/content/docs/osb/Miscelleanous/bingo.mdx
similarity index 59%
rename from docs/src/content/docs/getting-started/bingo.mdx
rename to docs/src/content/docs/osb/Miscelleanous/bingo.mdx
index 5af6f56910..3f78d347e6 100644
--- a/docs/src/content/docs/getting-started/bingo.mdx
+++ b/docs/src/content/docs/osb/Miscelleanous/bingo.mdx
@@ -1,33 +1,77 @@
---
-title: "OSB Bingo #3"
-sidebar:
- order: 4
+title: "Bingo"
---
-import Time from "../../../components/Time.astro";
+import Time from "../../../../components/Time.astro";
-Start Date:
+You can run community bingo's using the `/bingo` command, and the bot will automatically handle all of it for you.
-Finish Date:
+## Notes
+
+- Ironmen can join bingos for free. They cannot be given GP prizes, or create bingos.
+- Upon the bingo finishing, the creator of the bingo needs to do `/bingo finalize` to receive the GP pool. The creator of the bingo is responsible for handing out the GP, based on whatever split you have decided. You do not need to finalize the bingo on time, the bingo will automatically finish at the exact second it needs to, the finalize command just does some final things, and hands out the gp.
+- A person can participate in several bingos at once.
+- Bingos are private to the server they were made in. In other words, you can only join it from that server. Global bingos are limited to the official bingos. However, for any bingo, the commands/trips the players do (to get loot) can be done anywhere.
+
+## Creating a Bingo
+
+To create a bingo, you need to input the following things:
+
+- Title
+- Duration in days(7 = 7 days)
+- Start Date unix seconds. Use [https://hammertime.cyou/?tz=Etc%2FGMT](https://hammertime.cyou/?tz=Etc%2FGMT) to find this number. It's the last in the list, and is just a plain number that looks like this: `1695859800`. This indicates the exact time at which your bingo starts.
+- Ticket price: The ticket price per person. Each person must pay this when making their team. If the team disbands, the GP is refunded.
+- Team size: Size of the teams.
+- Organizers: people who are allowed to manage the bingo (Add tiles, etc)
+
+## Managing your Bingo
-We are hosting the 3rd OSB Bingo! You can compete for a chance of winning some GP, and a guaranteed chance of getting a trophy.
+Commands for managing the bingo are in `/bingo manage`. You can add/remove tiles, add extra GP to the prize pool, and more.
-## Information
-- When completing tiles, the bot automatically tracks and handles it for you. Your team "shares" tiles, so if one person completes a tile, it counts for the whole team.
-- Ironmen can join teams and participate, no entry free is required, but they will not be eligible for item/GP rewards.
-- Each player pays a 250m entry fee (when joining a team) which goes into the prize pool.
+### Adding Tiles
-## How to Join
-1. Gather 4 friends (for a team of 5), OR find people from our server to make a team.
-1. Ensure all 5 people have the 250m entry free, and are ready to confirm.
-1. Use this command in the main discord server: [[/bingo make_team bingo\:OSB Bingo #3]], and everyone click the confirm button.
+You can add tiles in 2 ways.
-## Bingo Channels
-- Receive info/announcements/updates about the bingo: [[# bingo-info:1039869985989861466]]
-- Discuss the bingo: [[# bingo-discussion:1039870142651301979]]
-- Look for a team: [[# bingo-looking-4-team:1149907771937001522]]
+1. Add global tiles. You can select global tiles to add, which are tiles that are premade for you to use.
+2. Add custom tiles. You can add 2 kinds of tiles. AND tiles, OR tiles. Example:
+ 1. `add_tile:coal+egg+trout` Adds a tile where you have to receive a coal, egg AND trout.
+ 2. `add_tile:coal|egg|trout` Adds a tile where you have to receive a coal, or egg, or a trout.
-## Prizes
+## OSB Bingo #3 (Finished)
+Start Date:
+
+Finish Date:
+OSB Bingo #3 has finished!
+
+**1st**: @vKoko @delman @Merisorax @Huśtajdupa @Prztynkinista
+(Prize Pool 22.825b)
+
+**2nd** Place @Ironici @Ecto @TheItchIsReal @CrankItUp @drunkenbeer
+(Prize Pool 12.450b)
+
+**3rd:** @papi @ImZ @Southernz @yekzerr @mikehunt
+(Prize Pool 6.225b)
+
+The Below Winner is the OSB Bingo #3 MvP which has won the following:
+- 2b Coins
+- 1m Sunfire Splinters
+- 2 x Scythe of Vitur (uncharged)
+- 3k Vial of Blood
+- 2 x Ancestral Robes Set
+- Justiciar Armour Set
+- Ghrazi Rapier
+- 2 x Sanguinesti Staff (uncharged)
+- 2 x Kodai Wand
+- 2 x Dragon Claws
+- Spectral Spirit Shield
+- Thammarons Sceptre (u)
+- Zaryte Crossbow
+Donated by Loot Game Event Team
+
+**MvP:** Garousse with 13!!! Solo Tiles
+
+
+Prizes
You can see the actual GP prize pool with the bingo command.
- 1st Place team - 55% of GP Prize Pool, Bingo Winner role
@@ -35,9 +79,10 @@ You can see the actual GP prize pool with the bingo command.
- 3rd Place team - 15% of GP Prize Pool
*More rewards may be added later*
+
-## Trophies
-
+
+Trophies
You can earn a Trophy (an item you get in your bank) by your performance. You get each one either by being in a certain percentile, or guaranteed if you complete a certain number of tiles.
- Bronze - 100% - Guaranteed at 1 Tile
@@ -47,11 +92,10 @@ You can earn a Trophy (an item you get in your bank) by your performance. You ge
- Adamant - top 20% - Guaranteed at 16 Tiles
- Rune - top 10% - Guaranteed at 22 Tiles
- Dragon - top 5% - Guaranteed at 28 Tiles
+
-[[osbbingo3.png]]
-
-## Tiles
-
+
+Tiles
1. Receive A Skilling Pet - Receive Any Pet From The Skilling Pet CL (No Exclusions)
1. Receive Any Nightmare Orb - Receive Any of The Following - Eldritch Orb, Volatile Orb, Harmonised Orb
1. Receive Any Sigil From The Corporeal Beast - Receive Any of The Following - Spectral Sigil, Arcane Sigil, Elysian Sigil
@@ -80,3 +124,4 @@ You can earn a Trophy (an item you get in your bank) by your performance. You ge
1. Receive a Boss Pet - Receive Any of The Following - Pet dagannoth supreme, Pet dagannoth prime, Pet dagannoth rex, Pet kree'arra, Pet general graardor, Pet zilyana, Pet k'ril tsutsaroth, Baby mole, Prince black dragon, Kalphite princess, Pet smoke devil, Pet kraken, Pet dark core, Pet snakeling, Venenatis spiderling, Callisto cub, Vet'ion jr., Scorpia's offspring, Hellpuppy, Olmlet, Noon, Vorki, Lil' zik, Ikkle hydra, Sraracha, Little nightmare, Nexling, Tumeken's guardian, Muphin, Wisp, Butch, Lil'viathan, Baron, Nid, Scurry
1. Receive a Boss Jar - Receive Any Jar (Excluding Jar or Darkness + Jar of Miasma)
1. Receive a Tormented Demon Unique - Receive Any of The Following - Burning Claw or Tormented Synapse
+
\ No newline at end of file
diff --git a/docs/src/content/docs/getting-started/hackertoberfest.mdx b/docs/src/content/docs/osb/Miscelleanous/hackertoberfest.mdx
similarity index 100%
rename from docs/src/content/docs/getting-started/hackertoberfest.mdx
rename to docs/src/content/docs/osb/Miscelleanous/hackertoberfest.mdx
diff --git a/docs/src/content/docs/osb/Skills/mining.md b/docs/src/content/docs/osb/Skills/mining.md
index 4c3c82666c..2247334300 100644
--- a/docs/src/content/docs/osb/Skills/mining.md
+++ b/docs/src/content/docs/osb/Skills/mining.md
@@ -114,7 +114,7 @@ The only other thing unidentified minerals can be used to purchase are:
| [[440]] | 58,000 | No |
| [[442]] | 58,000 | Yes |
| [[442]] | 53,000 | No |
-| [[453]] | 45,000 | Yes |
+| [[453]] | 44,000 | Yes |
| [[444]] | 42,000 | Yes |
| [[444]] | 40,000 | No |
| [[453]] | 38,000 | No |
@@ -131,9 +131,9 @@ The only other thing unidentified minerals can be used to purchase are:
| [[436]] | 19,000 | No |
| [[438]] | 19,000 | No |
| [[451]] | 13,000 | Yes |
+| [[451]] | 13,000 | No |
| [[21622]] | 13,000 | Yes |
| [[21622]] | 13,000 | No |
-| [[451]] | 12,000 | No |
| [[434]] | 11,000 | Yes |
| [[24706]] | 10,000 | Yes |
| [[24706]] | 10,000 | No |
diff --git a/docs/src/plugins/authors.ts b/docs/src/plugins/authors.ts
index 7938c295de..797aae826a 100644
--- a/docs/src/plugins/authors.ts
+++ b/docs/src/plugins/authors.ts
@@ -14,8 +14,12 @@ const authors: Author[] = [
{ gitIDs: ['Arodab'], displayName: 'Arodab' },
{ gitIDs: ['DaughtersOfNyx'], displayName: 'Keres', avatar: 'DaughtersOfNyx.webp' },
{ gitIDs: ['TastyPumPum'], displayName: 'TastyPumPum', avatar: 'tasty.webp' },
- { gitIDs: ['00justas'], displayName: '00justas' },
- { gitIDs: ['themrrobert'], displayName: 'Cyr' }
+ { gitIDs: ['00justas'], displayName: 'Justas' },
+ { gitIDs: ['themrrobert'], displayName: 'Cyr' },
+ { gitIDs: ['DayV-git'], displayName: 'DayV', avatar: 'dayv.webp' },
+ { gitIDs: ['Felris'], displayName: 'Felris', avatar: 'felris.webp' },
+ { gitIDs: ['Lajnux'], displayName: 'Fishy', avatar: 'fishy.webp' },
+ { gitIDs: ['DarkWorldsArtist'], displayName: 'DarkWorldsArtist', avatar: 'dark.webp' }
];
export const authorsMap = new Map();
diff --git a/package.json b/package.json
index 7839d9c087..225d2389c7 100644
--- a/package.json
+++ b/package.json
@@ -62,7 +62,7 @@
"murmurhash": "^2.0.1",
"node-cron": "^3.0.3",
"node-fetch": "^2.6.7",
- "oldschooljs": "git+https://github.com/oldschoolgg/oldschooljs.git#7094eb4a53e5301fb401adadb25f6993448b1c83",
+ "oldschooljs": "git+https://github.com/oldschoolgg/oldschooljs.git#7deb56970f6458aed87f314dd18da6916a0e732c",
"p-queue": "^6.6.2",
"piscina": "^4.7.0",
"postgres": "^3.4.4",
diff --git a/src/lib/clues/clueTiers.ts b/src/lib/clues/clueTiers.ts
index f71e477b84..fd312d3b49 100644
--- a/src/lib/clues/clueTiers.ts
+++ b/src/lib/clues/clueTiers.ts
@@ -53,7 +53,7 @@ export const ClueTiers: ClueTier[] = [
table: Beginner,
id: 23_245,
scrollID: 23_182,
- timeToFinish: Time.Minute * 2.5,
+ timeToFinish: Time.Minute * 2.8,
mimicChance: false,
allItems: BeginnerCasket.allItems,
stashUnits: beginnerStashes,
@@ -66,7 +66,7 @@ export const ClueTiers: ClueTier[] = [
table: Easy,
id: 20_546,
scrollID: 2677,
- timeToFinish: Time.Minute * 5.5,
+ timeToFinish: Time.Minute * 3.2,
milestoneReward: {
itemReward: itemID('Large spade'),
scoreNeeded: 500
@@ -83,7 +83,7 @@ export const ClueTiers: ClueTier[] = [
table: Medium,
id: 20_545,
scrollID: 2801,
- timeToFinish: Time.Minute * 7,
+ timeToFinish: Time.Minute * 5.1,
milestoneReward: {
itemReward: itemID('Clueless scroll'),
scoreNeeded: 400
@@ -100,7 +100,7 @@ export const ClueTiers: ClueTier[] = [
table: Hard,
id: 20_544,
scrollID: 2722,
- timeToFinish: Time.Minute * 12.5,
+ timeToFinish: Time.Minute * 8.5,
mimicChance: false,
allItems: HardCasket.allItems,
stashUnits: hardStashes,
@@ -113,7 +113,7 @@ export const ClueTiers: ClueTier[] = [
table: Elite,
id: 20_543,
scrollID: 12_073,
- timeToFinish: Time.Minute * 14,
+ timeToFinish: Time.Minute * 8.5,
milestoneReward: {
itemReward: itemID('Heavy casket'),
scoreNeeded: 200
@@ -130,7 +130,7 @@ export const ClueTiers: ClueTier[] = [
table: Master,
id: 19_836,
scrollID: 19_835,
- timeToFinish: Time.Minute * 19.3,
+ timeToFinish: Time.Minute * 19.5,
milestoneReward: {
itemReward: itemID('Scroll sack'),
scoreNeeded: 100
diff --git a/src/lib/data/cox.ts b/src/lib/data/cox.ts
index 88c98d274b..8e5a76595a 100644
--- a/src/lib/data/cox.ts
+++ b/src/lib/data/cox.ts
@@ -629,9 +629,12 @@ export async function calcCoxDuration(
// Track degradeable items (fakemass works properly with this code, it wont remove 5x charges):
const degradeableItems: { item: Item; user: MUser; chargesToDegrade: number }[] = [];
+ const uniqueUsers = new Map();
for (const u of team) {
let userPercentChange = 0;
+ const isUserReal = !uniqueUsers.has(u.id);
+ uniqueUsers.set(u.id, true);
// Reduce time for gear
const { total } = calculateUserGearPercents(u);
@@ -656,7 +659,7 @@ export async function calcCoxDuration(
const canDegrade = checkUserCanUseDegradeableItem(testItem);
if (canDegrade.hasEnough) {
userPercentChange += item.boost;
- degradeableItems.push(testItem);
+ if (isUserReal) degradeableItems.push(testItem);
break;
}
}
@@ -670,7 +673,7 @@ export async function calcCoxDuration(
const canDegrade = checkUserCanUseDegradeableItem(testItem);
if (canDegrade.hasEnough) {
userPercentChange += item.boost;
- degradeableItems.push(testItem);
+ if (isUserReal) degradeableItems.push(testItem);
break;
}
}
diff --git a/src/mahoji/commands/clue.ts b/src/mahoji/commands/clue.ts
index e421e6d0fb..c0f903fd7a 100644
--- a/src/mahoji/commands/clue.ts
+++ b/src/mahoji/commands/clue.ts
@@ -2,65 +2,48 @@ import type { CommandResponse, CommandRunOptions } from '@oldschoolgg/toolkit/ut
import { ApplicationCommandOptionType } from 'discord.js';
import { Time, notEmpty, randInt } from 'e';
import { Bank } from 'oldschooljs';
-import type { Item, ItemBank } from 'oldschooljs/dist/meta/types';
+import type { ItemBank } from 'oldschooljs/dist/meta/types';
import type { ClueTier } from '../../lib/clues/clueTiers';
import { ClueTiers } from '../../lib/clues/clueTiers';
import { BitField } from '../../lib/constants';
import { allOpenables, getOpenableLoot } from '../../lib/openables';
import { getPOHObject } from '../../lib/poh';
+import { SkillsEnum } from '../../lib/skilling/types';
import type { ClueActivityTaskOptions } from '../../lib/types/minions';
import { formatDuration, isWeekend, stringMatches } from '../../lib/util';
import addSubTaskToActivityTask from '../../lib/util/addSubTaskToActivityTask';
import { calcMaxTripLength } from '../../lib/util/calcMaxTripLength';
-import getOSItem, { getItem } from '../../lib/util/getOSItem';
+import { getItem } from '../../lib/util/getOSItem';
import { makeBankImage } from '../../lib/util/makeBankImage';
+import { getParsedStashUnits } from '../../mahoji/lib/abstracted_commands/stashUnitsCommand';
import { getPOH } from '../lib/abstracted_commands/pohCommand';
import type { OSBMahojiCommand } from '../lib/util';
import { addToOpenablesScores, getMahojiBank, mahojiUsersSettingsFetch } from '../mahojiSettings';
-function reducedClueTime(clueTier: ClueTier, score: number) {
- // Every 3 hours become 1% better to a cap of 10%
- const percentReduced = Math.min(Math.floor(score / ((Time.Hour * 3) / clueTier.timeToFinish)), 10);
- const amountReduced = (clueTier.timeToFinish * percentReduced) / 100;
- const reducedTime = clueTier.timeToFinish - amountReduced;
+async function getStashBoost(userID: string, tierName: string): Promise {
+ const parsedUnits = await getParsedStashUnits(userID);
- return [reducedTime, percentReduced];
-}
+ // Filter parsed units based on the found stash tier
+ const tierSpecificUnits = parsedUnits.filter(unit => unit.tier.tier === tierName);
+ const filledUnits = tierSpecificUnits.filter(
+ unit => unit.builtUnit !== undefined && unit.builtUnit.items_contained.length > 0
+ ).length;
+ const totalUnits = tierSpecificUnits.length;
+ const percentageFilled = totalUnits > 0 ? (filledUnits / totalUnits) * 100 : 0;
-function shouldApplyBoost(clueTier: ClueTier, item: string, hasAchievementDiaryCape: boolean) {
- switch (clueTier.name) {
- case 'Elite':
- return (item !== 'Kandarin headgear 4' && item !== 'Fremennik sea boots 4') || !hasAchievementDiaryCape;
- case 'Master':
- return item !== 'Kandarin headgear 4' || !hasAchievementDiaryCape;
- case 'Hard':
- return item !== 'Wilderness sword 3' || !hasAchievementDiaryCape;
- default:
- return true;
- }
-}
+ const boost = Math.min((percentageFilled / 100) * 15, 15);
-interface ClueBoost {
- item: Item;
- boost: string;
- durationMultiplier: number;
+ return boost;
}
-function applyClueBoosts(user: MUser, boostList: ClueBoost[], boosts: string[], duration: number, clueTier: ClueTier) {
- let hasAchievementDiaryCape = false;
- for (const boost of boostList) {
- if (user.hasEquippedOrInBank(boost.item.name)) {
- if (shouldApplyBoost(clueTier, boost.item.name, hasAchievementDiaryCape)) {
- boosts.push(boost.boost);
- duration *= boost.durationMultiplier;
- }
- if (boost.item.name === 'Achievement diary cape') {
- hasAchievementDiaryCape = true;
- }
- }
- }
- return { duration, boosts };
+function reducedClueTime(clueTier: ClueTier, score: number) {
+ // Every 2 hours become 1% better to a cap of 25%
+ const percentReduced = Math.min(Math.floor(score / ((Time.Hour * 2) / clueTier.timeToFinish)), 25);
+ const amountReduced = (clueTier.timeToFinish * percentReduced) / 100;
+ const reducedTime = clueTier.timeToFinish - amountReduced;
+
+ return [reducedTime, percentReduced];
}
export const clueCommand: OSBMahojiCommand = {
@@ -155,6 +138,30 @@ export const clueCommand: OSBMahojiCommand = {
const hasOrnateJewelleryBox = poh.jewellery_box === getPOHObject('Ornate jewellery box').id;
const hasJewelleryBox = poh.jewellery_box !== null;
const hasXericTalisman = poh.amulet === getPOHObject("Mounted xeric's talisman").id;
+ const hasAchievementDiaryCape = user.hasEquippedOrInBank('Achievement diary cape');
+
+ // Stash Unit boost
+ const stashBoost = await getStashBoost(userID, clueTier.name);
+ boosts.push(`${stashBoost.toFixed(2)}% for built STASH Units`);
+ duration *= 1 - stashBoost / 100;
+
+ // Combat stats boost
+ if (['Hard', 'Elite', 'Master'].includes(clueTier.name)) {
+ const totalCombatStats =
+ user.skillLevel(SkillsEnum.Attack) +
+ user.skillLevel(SkillsEnum.Strength) +
+ user.skillLevel(SkillsEnum.Ranged);
+ let combatBoost = (totalCombatStats / (3 * 99)) * 100;
+
+ if (combatBoost < 50) {
+ combatBoost = combatBoost - 50;
+ } else {
+ combatBoost = Math.min(10, combatBoost / 6.5);
+ }
+
+ boosts.push(`${combatBoost.toFixed(2)}% for combat stats`);
+ duration *= 1 - combatBoost / 100;
+ }
// Global Boosts
const globalBoosts = [
@@ -182,6 +189,11 @@ export const clueCommand: OSBMahojiCommand = {
condition: () => !hasOrnateJewelleryBox && hasJewelleryBox,
boost: '5% for Basic/Fancy jewellery box',
durationMultiplier: 0.95
+ },
+ {
+ condition: () => hasAchievementDiaryCape,
+ boost: '10% for Achievement diary cape',
+ durationMultiplier: 0.9
}
];
@@ -192,138 +204,164 @@ export const clueCommand: OSBMahojiCommand = {
}
}
- // Xeric's Talisman boost
- if (clueTier.name === 'Medium' && hasXericTalisman) {
- boosts.push("2% for Mounted Xeric's Talisman");
- duration *= 0.98;
- }
-
- // Specific boosts
- const clueTierBoosts: Record = {
+ // Specific tier boosts
+ const clueTierBoosts: Record<
+ ClueTier['name'],
+ { condition: () => boolean; boost: string; durationMultiplier: number }[]
+ > = {
Beginner: [
{
- item: getOSItem('Ring of the elements'),
+ condition: () => user.hasEquippedOrInBank('Ring of the elements'),
boost: '10% for Ring of the elements',
durationMultiplier: 0.9
+ },
+ {
+ condition: () => user.hasEquippedOrInBank('Skull sceptre'),
+ boost: '5% for Skull sceptre',
+ durationMultiplier: 0.95
}
],
Easy: [
{
- item: getOSItem('Achievement diary cape'),
- boost: '10% for Achievement diary cape',
+ condition: () => user.hasEquippedOrInBank('Ring of the elements'),
+ boost: '10% for Ring of the elements',
durationMultiplier: 0.9
},
{
- item: getOSItem('Ring of the elements'),
- boost: '6% for Ring of the elements',
- durationMultiplier: 0.94
+ condition: () => user.hasEquippedOrInBank('Skull sceptre'),
+ boost: '5% for Skull sceptre',
+ durationMultiplier: 0.95
+ },
+ {
+ condition: () => user.hasEquippedOrInBank('Music cape'),
+ boost: '5% for Music cape',
+ durationMultiplier: 0.95
}
],
Medium: [
{
- item: getOSItem('Ring of the elements'),
- boost: '8% for Ring of the elements',
- durationMultiplier: 0.92
+ condition: () => hasXericTalisman,
+ boost: "5% for Mounted Xeric's Talisman",
+ durationMultiplier: 0.95
+ },
+ {
+ condition: () => user.hasEquippedOrInBank('Ring of the elements'),
+ boost: '10% for Ring of the elements',
+ durationMultiplier: 0.9
+ },
+ {
+ condition: () => user.hasEquippedOrInBank('Skull sceptre'),
+ boost: '5% for Skull sceptre',
+ durationMultiplier: 0.95
+ },
+ {
+ condition: () => user.hasEquippedOrInBank('Music cape'),
+ boost: '5% for Music cape',
+ durationMultiplier: 0.95
}
],
Hard: [
{
- item: getOSItem('Achievement diary cape'),
- boost: '10% for Achievement diary cape',
- durationMultiplier: 0.9
+ condition: () => user.hasEquippedOrInBank('Book of the dead'),
+ boost: '5% for Book of the dead',
+ durationMultiplier: 0.95
},
{
- item: getOSItem('Wilderness sword 3'),
- boost: '8% for Wilderness sword 3',
- durationMultiplier: 0.92
+ condition: () => user.hasEquippedOrInBank('Wilderness sword 3') && !hasAchievementDiaryCape,
+ boost: '5% for Wilderness sword 3',
+ durationMultiplier: 0.95
},
{
- item: getOSItem('Royal seed pod'),
- boost: '6% for Royal seed pod',
- durationMultiplier: 0.94
+ condition: () => user.hasEquippedOrInBank('Royal seed pod'),
+ boost: '5% for Royal seed pod',
+ durationMultiplier: 0.95
},
{
- item: getOSItem('Eternal teleport crystal'),
- boost: '4% for Eternal teleport crystal',
- durationMultiplier: 0.96
+ condition: () => user.hasEquippedOrInBank('Eternal teleport crystal'),
+ boost: '5% for Eternal teleport crystal',
+ durationMultiplier: 0.95
},
{
- item: getOSItem("Pharaoh's sceptre"),
- boost: "4% for Pharaoh's sceptre",
- durationMultiplier: 0.96
+ condition: () => user.hasEquippedOrInBank("Pharaoh's sceptre"),
+ boost: "5% for Pharaoh's sceptre",
+ durationMultiplier: 0.95
},
{
- item: getOSItem('Toxic blowpipe'),
- boost: '4% for Toxic blowpipe',
- durationMultiplier: 0.96
+ condition: () => user.hasEquippedOrInBank('Toxic blowpipe'),
+ boost: '5% for Toxic blowpipe',
+ durationMultiplier: 0.95
}
],
Elite: [
{
- item: getOSItem('Achievement diary cape'),
- boost: '10% for Achievement diary cape',
- durationMultiplier: 0.9
+ condition: () => user.hasEquippedOrInBank('Book of the dead'),
+ boost: '5% for Book of the dead',
+ durationMultiplier: 0.95
},
{
- item: getOSItem('Kandarin headgear 4'),
- boost: '7% for Kandarin headgear 4',
- durationMultiplier: 0.93
+ condition: () => user.hasEquippedOrInBank("Pharaoh's sceptre"),
+ boost: "5% for Pharaoh's sceptre",
+ durationMultiplier: 0.95
},
{
- item: getOSItem('Fremennik sea boots 4'),
- boost: '3% for Fremennik sea boots 4',
- durationMultiplier: 0.97
+ condition: () => user.hasEquippedOrInBank('Kandarin headgear 4') && !hasAchievementDiaryCape,
+ boost: '5% for Kandarin headgear 4',
+ durationMultiplier: 0.95
},
{
- item: getOSItem("Pharaoh's sceptre"),
- boost: "4% for Pharaoh's sceptre",
- durationMultiplier: 0.96
+ condition: () => user.hasEquippedOrInBank('Fremennik sea boots 4') && !hasAchievementDiaryCape,
+ boost: '3% for Fremennik sea boots 4',
+ durationMultiplier: 0.97
},
{
- item: getOSItem('Toxic blowpipe'),
+ condition: () => user.hasEquippedOrInBank('Toxic blowpipe'),
boost: '4% for Toxic blowpipe',
durationMultiplier: 0.96
}
],
Master: [
{
- item: getOSItem('Achievement diary cape'),
- boost: '10% for Achievement diary cape',
- durationMultiplier: 0.9
- },
- {
- item: getOSItem('Kandarin headgear 4'),
+ condition: () => user.hasEquippedOrInBank('Kandarin headgear 4') && !hasAchievementDiaryCape,
boost: '6% for Kandarin headgear 4',
durationMultiplier: 0.94
},
{
- item: getOSItem('Music cape'),
+ condition: () => user.hasEquippedOrInBank('Book of the dead'),
+ boost: '5% for Book of the dead',
+ durationMultiplier: 0.95
+ },
+ {
+ condition: () => user.hasEquippedOrInBank('Music cape'),
boost: '5% for Music cape',
durationMultiplier: 0.95
},
{
- item: getOSItem('Eternal teleport crystal'),
+ condition: () => user.hasEquippedOrInBank('Eternal teleport crystal'),
boost: '3% for Eternal teleport crystal',
durationMultiplier: 0.97
},
{
- item: getOSItem('Toxic blowpipe'),
+ condition: () => user.hasEquippedOrInBank('Toxic blowpipe'),
boost: '2% for Toxic blowpipe',
durationMultiplier: 0.98
},
{
- item: getOSItem('Dragon claws'),
+ condition: () => user.hasEquippedOrInBank('Dragon claws'),
boost: '1% for Dragon claws',
durationMultiplier: 0.99
}
]
};
- const clueTierName = clueTier.name;
- const boostList = clueTierBoosts[clueTierName];
- const result = applyClueBoosts(user, boostList, boosts, duration, clueTier);
+ for (const tierBoost of clueTierBoosts[clueTier.name]) {
+ const { condition, boost, durationMultiplier } = tierBoost;
+ if (condition()) {
+ boosts.push(boost);
+ duration *= durationMultiplier;
+ }
+ }
- timeToFinish = result.duration;
+ timeToFinish = duration;
const response: Awaited = {};
@@ -396,7 +434,7 @@ export const clueCommand: OSBMahojiCommand = {
response.content = `${user.minionName} is now completing ${quantity}x ${
clueTier.name
- } clues, it'll take around ${formatDuration(duration)} to finish.${
+ } clues, it'll take around ${formatDuration(duration)} to finish (${((quantity / duration) * 3600000).toFixed(1)}/hr).${
boosts.length > 0 ? `\n\n**Boosts:** ${boosts.join(', ')}.` : ''
}${implingLootString}`;
return response;
diff --git a/src/mahoji/commands/leaderboard.ts b/src/mahoji/commands/leaderboard.ts
index e67e15bab0..82406616a1 100644
--- a/src/mahoji/commands/leaderboard.ts
+++ b/src/mahoji/commands/leaderboard.ts
@@ -687,8 +687,8 @@ async function globalLb(interaction: ChatInputCommandInteraction, user: MUser, c
}[]
>`SELECT id::text, osb_total_xp, bso_total_xp,
(osb_total_xp / (200000000.0 * 23) * 100) as osb_xp_percent,
- (bso_total_xp / (5000000000.0 * 25) * 100) as bso_xp_percent,
- (((osb_total_xp / (200000000.0 * 23) * 100) + (bso_total_xp / (5000000000.0 * 25) * 100)) / 2) as average_percentage
+ (bso_total_xp / (5000000000.0 * 26) * 100) as bso_xp_percent,
+ (((osb_total_xp / (200000000.0 * 23) * 100) + (bso_total_xp / (5000000000.0 * 26) * 100)) / 2) as average_percentage
FROM public.user
WHERE osb_total_xp IS NOT NULL AND bso_total_xp IS NOT NULL
ORDER BY average_percentage DESC
diff --git a/src/mahoji/lib/abstracted_commands/coxCommand.ts b/src/mahoji/lib/abstracted_commands/coxCommand.ts
index 85f5ba450b..93d24031f5 100644
--- a/src/mahoji/lib/abstracted_commands/coxCommand.ts
+++ b/src/mahoji/lib/abstracted_commands/coxCommand.ts
@@ -204,13 +204,16 @@ export async function coxCommand(
}
};
const channel = globalClient.channels.cache.get(channelID.toString());
- if (!channelIsSendable(channel)) return 'No channel found.';
let users: MUser[] = [];
+ let isFakeMass = false;
+
const fakeUsers = Math.min(maxSizeInput ?? 5, maxSize);
if (type === 'fakemass') {
users = new Array(fakeUsers).fill(user);
+ isFakeMass = true;
} else if (type === 'mass') {
+ if (!channelIsSendable(channel)) return 'No channel found.';
users = (await setupParty(channel, user, partyOptions)).filter(u => !u.minionIsBusy);
} else {
users = [user];
@@ -240,7 +243,6 @@ export async function coxCommand(
let debugStr = '';
const isSolo = users.length === 1;
- const isFakeMass = users.length > 1 && new Set(users).size === 1;
for (const d of degradeables) {
d.chargesToDegrade *= quantity;
diff --git a/src/mahoji/lib/abstracted_commands/nightmareCommand.ts b/src/mahoji/lib/abstracted_commands/nightmareCommand.ts
index 27f0cea1cd..c98648ac3a 100644
--- a/src/mahoji/lib/abstracted_commands/nightmareCommand.ts
+++ b/src/mahoji/lib/abstracted_commands/nightmareCommand.ts
@@ -46,7 +46,7 @@ const inquisitorItems = resolveItems([
const phosaniBISGear = new Gear({
head: "Inquisitor's great helm",
- neck: 'Amulet of torture',
+ neck: 'Amulet of rancour',
body: "Inquisitor's hauberk",
cape: 'Infernal cape',
hands: 'Ferocious gloves',
diff --git a/tests/integration/pvm/cox.test.ts b/tests/integration/pvm/cox.test.ts
new file mode 100644
index 0000000000..cc9ceed076
--- /dev/null
+++ b/tests/integration/pvm/cox.test.ts
@@ -0,0 +1,59 @@
+import { expect, test } from 'vitest';
+
+import { COXMaxMageGear, COXMaxMeleeGear, COXMaxRangeGear } from '../../../src/lib/data/cox';
+import { Bank, itemID, resolveItems } from '../../../src/lib/util';
+import { raidCommand } from '../../../src/mahoji/commands/raid';
+import { mockClient, mockUser } from '../util';
+
+test('CoX ', async () => {
+ const client = await mockClient();
+
+ const user = await mockUser({
+ rangeGear: resolveItems(['Venator bow']),
+ rangeLevel: 70,
+ venatorBowCharges: 1000,
+ slayerLevel: 70
+ });
+ await user.max();
+
+ await user.update({
+ tum_shadow_charges: 10000,
+ scythe_of_vitur_charges: 100,
+ gear_mage: COXMaxMageGear.raw() as any,
+ gear_melee: COXMaxMeleeGear.raw() as any,
+ gear_range: {
+ ...(COXMaxRangeGear.raw() as any),
+ ammo: {
+ item: itemID('Dragon arrow'),
+ quantity: 10000
+ }
+ },
+ bank: new Bank()
+ .add('Shark', 10000)
+ .add('Stamina potion(4)', 10000)
+ .add('Super restore(4)', 10000)
+ .add('Saradomin brew(4)', 10000)
+ .toJSON()
+ });
+ await user.equip('melee', resolveItems(['Scythe of vitur']));
+ const res = await user.runCommand(
+ raidCommand,
+ {
+ cox: {
+ start: {
+ type: 'fakemass',
+ max_team_size: 5
+ }
+ }
+ },
+ true
+ );
+ expect(res).toContain('the total trip will take');
+ await user.processActivities(client);
+ await user.sync();
+ expect(user.bank.amount('Scythe of vitur (uncharged)')).toBe(1);
+ expect(user.bank.amount('Scythe of vitur')).toBe(0);
+ expect(user.gear.melee.weapon?.item).toBeUndefined();
+ expect(user.allItemsOwned.amount('Scythe of vitur (uncharged)')).toBe(1);
+ expect(user.allItemsOwned.amount('Scythe of vitur')).toBe(0);
+});
diff --git a/tests/unit/snapshots/bank.OSB.png b/tests/unit/snapshots/bank.OSB.png
index 2128ff40dd..1b582259e1 100644
Binary files a/tests/unit/snapshots/bank.OSB.png and b/tests/unit/snapshots/bank.OSB.png differ
diff --git a/tests/unit/snapshots/chatHead.OSB.png b/tests/unit/snapshots/chatHead.OSB.png
index 044f00874f..b67ed3a8ce 100644
Binary files a/tests/unit/snapshots/chatHead.OSB.png and b/tests/unit/snapshots/chatHead.OSB.png differ
diff --git a/tests/unit/snapshots/cl.OSB.png b/tests/unit/snapshots/cl.OSB.png
index 361ff018cc..2b309efbb3 100644
Binary files a/tests/unit/snapshots/cl.OSB.png and b/tests/unit/snapshots/cl.OSB.png differ
diff --git a/tests/unit/snapshots/cox.OSB.png b/tests/unit/snapshots/cox.OSB.png
index 6ffddf5eb9..159861f526 100644
Binary files a/tests/unit/snapshots/cox.OSB.png and b/tests/unit/snapshots/cox.OSB.png differ
diff --git a/tests/unit/snapshots/poh.OSB.png b/tests/unit/snapshots/poh.OSB.png
index 440675860b..058c5b8a63 100644
Binary files a/tests/unit/snapshots/poh.OSB.png and b/tests/unit/snapshots/poh.OSB.png differ
diff --git a/tests/unit/snapshots/toa.OSB.png b/tests/unit/snapshots/toa.OSB.png
index 7a56694dc6..c2473774df 100644
Binary files a/tests/unit/snapshots/toa.OSB.png and b/tests/unit/snapshots/toa.OSB.png differ
diff --git a/yarn.lock b/yarn.lock
index 5aedde13ef..703980b46f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4362,9 +4362,9 @@ __metadata:
languageName: node
linkType: hard
-"oldschooljs@git+https://github.com/oldschoolgg/oldschooljs.git#7094eb4a53e5301fb401adadb25f6993448b1c83":
+"oldschooljs@git+https://github.com/oldschoolgg/oldschooljs.git#7deb56970f6458aed87f314dd18da6916a0e732c":
version: 0.0.0
- resolution: "oldschooljs@https://github.com/oldschoolgg/oldschooljs.git#commit=7094eb4a53e5301fb401adadb25f6993448b1c83"
+ resolution: "oldschooljs@https://github.com/oldschoolgg/oldschooljs.git#commit=7deb56970f6458aed87f314dd18da6916a0e732c"
dependencies:
e: "npm:^0.2.33"
node-fetch: "npm:2.6.7"
@@ -5171,7 +5171,7 @@ __metadata:
node-cron: "npm:^3.0.3"
node-fetch: "npm:^2.6.7"
nodemon: "npm:^3.1.7"
- oldschooljs: "git+https://github.com/oldschoolgg/oldschooljs.git#7094eb4a53e5301fb401adadb25f6993448b1c83"
+ oldschooljs: "git+https://github.com/oldschoolgg/oldschooljs.git#7deb56970f6458aed87f314dd18da6916a0e732c"
p-queue: "npm:^6.6.2"
piscina: "npm:^4.7.0"
postgres: "npm:^3.4.4"