From f940121ea873519a1ca6879500d627eddbbeae98 Mon Sep 17 00:00:00 2001 From: GC <30398469+gc@users.noreply.github.com> Date: Wed, 28 Feb 2024 01:18:22 +1100 Subject: [PATCH 1/4] Scurrius (#5731) --- package.json | 2 +- src/lib/combat_achievements/easy.ts | 26 ++++++++ src/lib/combat_achievements/medium.ts | 34 +++++++++++ src/lib/data/Collections.ts | 6 ++ src/lib/data/CollectionsExport.ts | 3 +- src/lib/data/creatablesTable.txt | 6 ++ src/lib/data/createables.ts | 24 ++++++++ .../data/killableMonsters/bosses/misc.ts | 13 ++++ src/lib/slayer/slayerUtil.ts | 2 +- src/lib/slayer/tasks/turaelTasks.ts | 3 +- tests/integration/commands/sacrifice.test.ts | 12 ++-- .../unit/snapshots/banksnapshots.test.ts.snap | 61 +++++++++++++++++++ tests/unit/snapshots/clsnapshots.test.ts.snap | 7 ++- yarn.lock | 8 +-- 14 files changed, 191 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 384b99a0da..f337a9a10e 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "murmurhash": "^2.0.1", "node-cron": "^3.0.3", "node-fetch": "^2.6.7", - "oldschooljs": "^2.5.0", + "oldschooljs": "^2.5.1", "p-queue": "^6.6.2", "piscina": "^4.3.2", "random-js": "^2.1.0", diff --git a/src/lib/combat_achievements/easy.ts b/src/lib/combat_achievements/easy.ts index 98af025d46..2b5cd47f66 100644 --- a/src/lib/combat_achievements/easy.ts +++ b/src/lib/combat_achievements/easy.ts @@ -4,6 +4,7 @@ import { warmGear } from '../data/filterables'; import { SkillsEnum } from '../skilling/types'; import { Requirements } from '../structures/Requirements'; import getOSItem from '../util/getOSItem'; +import resolveItems from '../util/resolveItems'; import { isCertainMonsterTrip } from './caUtils'; import { type CombatAchievement } from './combatAchievements'; @@ -413,5 +414,30 @@ export const easyCombatAchievements: CombatAchievement[] = [ [Monsters.Wyrm.id]: 1 } }) + }, + { + id: 34, + name: 'Sit Rat', + type: 'restriction', + monster: 'Scurrius', + desc: 'Finish off Scurrius with a ratbane weapon.', + rng: { + chancePerKill: 1, + hasChance: (data, user) => + isCertainMonsterTrip(Monsters.Scurrius.id)(data) && + [resolveItems(['Bone mace', 'Bone staff', 'Bone shortbow'])].some(i => user.hasEquipped(i)) + } + }, + { + id: 35, + name: 'Scurrius Novice', + type: 'kill_count', + monster: 'Scurrius', + desc: 'Kill Scurrius once.', + requirements: new Requirements().add({ + kcRequirement: { + [Monsters.Scurrius.id]: 1 + } + }) } ]; diff --git a/src/lib/combat_achievements/medium.ts b/src/lib/combat_achievements/medium.ts index 5c8d4381ad..cbbc56bc37 100644 --- a/src/lib/combat_achievements/medium.ts +++ b/src/lib/combat_achievements/medium.ts @@ -491,5 +491,39 @@ export const mediumCombatAchievements: CombatAchievement[] = [ wintertodt: 10 } }) + }, + { + id: 141, + name: 'Scurrius Champion', + type: 'kill_count', + monster: 'Scurrius', + desc: 'Kill Scurrius 10 times.', + requirements: new Requirements().add({ + kcRequirement: { + [Monsters.Scurrius.id]: 10 + } + }) + }, + { + id: 142, + name: 'Perfect Scurrius', + type: 'perfection', + monster: 'Scurrius', + desc: 'Kill Scurrius in a private instance without taking damage from the following attacks: Tail Swipe and Falling Bricks. Pray correctly against the following attacks: Flying Fur and Bolts of Electricity.', + rng: { + chancePerKill: 10, + hasChance: isCertainMonsterTrip(Monsters.Scurrius.id) + } + }, + { + id: 143, + name: 'Efficient Pest Control', + type: 'mechanical', + monster: 'Scurrius', + desc: "Kill 6 Giant Rats within Scurrius' lair in 3 seconds.", + rng: { + chancePerKill: 10, + hasChance: isCertainMonsterTrip(Monsters.Scurrius.id) + } } ]; diff --git a/src/lib/data/Collections.ts b/src/lib/data/Collections.ts index 51126cbb27..6e4629136c 100644 --- a/src/lib/data/Collections.ts +++ b/src/lib/data/Collections.ts @@ -434,6 +434,12 @@ export const allCollectionLogs: ICollection = { items: scorpiaCL, fmtProg: kcProg(Monsters.Scorpia) }, + Scurrius: { + alias: Monsters.Scurrius.aliases, + allItems: Monsters.Scurrius.allItems, + items: resolveItems(['Scurry', "Scurrius' spine"]), + fmtProg: kcProg(Monsters.Scurrius) + }, Skotizo: { alias: Monsters.Skotizo.aliases, allItems: Monsters.Skotizo.allItems, diff --git a/src/lib/data/CollectionsExport.ts b/src/lib/data/CollectionsExport.ts index 983b9a773d..c5a30bb7bd 100644 --- a/src/lib/data/CollectionsExport.ts +++ b/src/lib/data/CollectionsExport.ts @@ -1559,7 +1559,8 @@ export const allPetsCL = resolveItems([ 'Wisp', "Lil'viathan", 'Butch', - 'Baron' + 'Baron', + 'Scurry' ]); export const camdozaalCL = resolveItems([ 'Barronite mace', diff --git a/src/lib/data/creatablesTable.txt b/src/lib/data/creatablesTable.txt index 69b54cc5fe..a54295b717 100644 --- a/src/lib/data/creatablesTable.txt +++ b/src/lib/data/creatablesTable.txt @@ -179,6 +179,12 @@ ╟─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────╢ ║ Webweaver bow (u) │ 500,000x Coins, 1x Craw's bow (u), 1x Fangs of venenatis │ 1x Webweaver bow (u) │ 0 ║ ╟─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────╢ +║ Bone mace │ 1x Rune mace, 1x Scurrius' spine │ 1x Bone mace │ 0 ║ +╟─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────╢ +║ Bone shortbow │ 1x Yew shortbow, 1x Scurrius' spine │ 1x Bone shortbow │ 0 ║ +╟─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────╢ +║ Bone staff │ 1,000x Chaos rune, 1x Battlestaff, 1x Scurrius' spine │ 1x Bone staff │ 0 ║ +╟─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────╢ ║ Revert tanzanite fang │ 1x Tanzanite fang │ 20,000x Zulrah's scales │ 0 ║ ╟─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────╢ ║ Revert toxic blowpipe (empty) │ 1x Toxic blowpipe (empty) │ 20,000x Zulrah's scales │ 0 ║ diff --git a/src/lib/data/createables.ts b/src/lib/data/createables.ts index 7b43682d1b..c0c495618f 100644 --- a/src/lib/data/createables.ts +++ b/src/lib/data/createables.ts @@ -2342,6 +2342,30 @@ const Createables: Createable[] = [ 'Webweaver bow (u) ': 1 }) }, + { + name: 'Bone mace', + inputItems: new Bank().add('Rune mace').add("Scurrius' spine"), + outputItems: new Bank().add('Bone mace'), + requiredSkills: { + smithing: 35 + } + }, + { + name: 'Bone shortbow', + inputItems: new Bank().add('Yew shortbow').add("Scurrius' spine"), + outputItems: new Bank().add('Bone shortbow'), + requiredSkills: { + fletching: 35 + } + }, + { + name: 'Bone staff', + inputItems: new Bank().add('Battlestaff').add('Chaos rune', 1000).add("Scurrius' spine"), + outputItems: new Bank().add('Bone staff'), + requiredSkills: { + crafting: 35 + } + }, ...Reverteables, ...crystalTools, ...ornamentKits, diff --git a/src/lib/minions/data/killableMonsters/bosses/misc.ts b/src/lib/minions/data/killableMonsters/bosses/misc.ts index 09e8f953d3..d211c2ba0c 100644 --- a/src/lib/minions/data/killableMonsters/bosses/misc.ts +++ b/src/lib/minions/data/killableMonsters/bosses/misc.ts @@ -447,6 +447,19 @@ const killableBosses: KillableMonster[] = [ messages.push('You got a Charged ice for killing the Phantom Muspah in under 3 minutes!'); }, healAmountNeeded: 150 + }, + { + id: Monsters.Scurrius.id, + name: Monsters.Scurrius.name, + aliases: Monsters.Scurrius.aliases, + timeToFinish: Time.Minute * 2, + table: Monsters.Scurrius, + notifyDrops: resolveItems(['Scurry']), + qpRequired: 0, + levelRequirements: { + prayer: 43 + }, + defaultAttackStyles: [SkillsEnum.Attack] } ]; diff --git a/src/lib/slayer/slayerUtil.ts b/src/lib/slayer/slayerUtil.ts index d18c50a9d9..e743d12838 100644 --- a/src/lib/slayer/slayerUtil.ts +++ b/src/lib/slayer/slayerUtil.ts @@ -283,7 +283,7 @@ export async function getUsersCurrentSlayerInfo(id: string) { } const slayerMaster = slayerMasters.find(master => master.id === currentTask.slayer_master_id); - const assignedTask = slayerMaster!.tasks.find(m => m.monster.id === currentTask.monster_id)!; + const assignedTask = slayerMaster?.tasks.find(m => m.monster.id === currentTask.monster_id); if (!assignedTask || !slayerMaster) { logError( diff --git a/src/lib/slayer/tasks/turaelTasks.ts b/src/lib/slayer/tasks/turaelTasks.ts index 1aa36e7c3a..06d5fc171d 100644 --- a/src/lib/slayer/tasks/turaelTasks.ts +++ b/src/lib/slayer/tasks/turaelTasks.ts @@ -187,7 +187,8 @@ export const turaelTasks: AssignableSlayerTask[] = [ Monsters.DungeonRat.id, Monsters.CryptRat.id, Monsters.ZombieRat.id, - Monsters.BrineRat.id + Monsters.BrineRat.id, + Monsters.Scurrius.id ], unlocked: true }, diff --git a/tests/integration/commands/sacrifice.test.ts b/tests/integration/commands/sacrifice.test.ts index 8d722b100b..dbbd87cfba 100644 --- a/tests/integration/commands/sacrifice.test.ts +++ b/tests/integration/commands/sacrifice.test.ts @@ -18,28 +18,28 @@ describe('Sacrifice Command', async () => { expect(result).toEqual( `${Emoji.Incinerator} **Your Sacrifice Stats** ${Emoji.Incinerator}\n\n` + `**Current Minion Icon:** ${Emoji.Minion}\n` + - '**Sacrificed Value:** 1,922 GP\n' + + '**Sacrificed Value:** 1,909 GP\n' + '**Unique Items Sacrificed:** 2 items' ); }); test('No items provided', async () => { const result = await user.runCommand(sacrificeCommand, { items: 'aaaa' }); - expect(result).toEqual('No items were provided.\nYour current sacrificed value is: 1,922 (1.92k)'); + expect(result).toEqual('No items were provided.\nYour current sacrificed value is: 1,909 (1.91k)'); }); test('Successful', async () => { await user.addItemsToBank({ items: new Bank().add('Trout').add('Coal', 10) }); const result = await user.runCommand(sacrificeCommand, { items: '1 trout, 10 coal' }); expect(result).toEqual( - 'You sacrificed 10x Coal, 1x Trout, with a value of 1,922gp (1.92k). Your total amount sacrificed is now: 3,844. ' + 'You sacrificed 10x Coal, 1x Trout, with a value of 1,909gp (1.91k). Your total amount sacrificed is now: 3,818. ' ); const stats = await user.fetchStats({ sacrificed_bank: true }); expect(user.bank.equals(new Bank())).toBe(true); expect(new Bank(stats.sacrificed_bank as ItemBank).equals(new Bank().add('Coal', 20).add('Trout', 2))).toBe( true ); - expect(user.user.sacrificedValue).toEqual(BigInt(3844)); + expect(user.user.sacrificedValue).toEqual(BigInt(3818)); const clientSettings = await mahojiClientSettingsFetch({ economyStats_sacrificedBank: true }); expect( new Bank(clientSettings.economyStats_sacrificedBank as ItemBank).equals( @@ -49,7 +49,7 @@ describe('Sacrifice Command', async () => { await user.addItemsToBank({ items: new Bank().add('Trout').add('Cake') }); const res = await user.runCommand(sacrificeCommand, { items: '1 trout, 1 cake' }); expect(res).toEqual( - 'You sacrificed 1x Trout, 1x Cake, with a value of 169gp (169). Your total amount sacrificed is now: 4,013. ' + 'You sacrificed 1x Trout, 1x Cake, with a value of 156gp (156). Your total amount sacrificed is now: 3,974. ' ); await user.sync(); expect(user.bank.equals(new Bank())).toBe(true); @@ -57,7 +57,7 @@ describe('Sacrifice Command', async () => { expect( new Bank(stats2.sacrificed_bank as ItemBank).equals(new Bank().add('Coal', 20).add('Trout', 3).add('Cake')) ).toBe(true); - expect(user.user.sacrificedValue).toEqual(BigInt(4013)); + expect(user.user.sacrificedValue).toEqual(BigInt(3974)); const clientSettings2 = await mahojiClientSettingsFetch({ economyStats_sacrificedBank: true }); expect( diff --git a/tests/unit/snapshots/banksnapshots.test.ts.snap b/tests/unit/snapshots/banksnapshots.test.ts.snap index c41d2361c2..eb9e6117bd 100644 --- a/tests/unit/snapshots/banksnapshots.test.ts.snap +++ b/tests/unit/snapshots/banksnapshots.test.ts.snap @@ -8656,6 +8656,67 @@ exports[`OSB Creatables 1`] = ` "frozen": false, }, }, + { + "cantHaveItems": undefined, + "inputItems": Bank { + "bank": { + "1432": 1, + "28798": 1, + }, + "frozen": false, + }, + "name": "Bone mace", + "outputItems": Bank { + "bank": { + "28792": 1, + }, + "frozen": false, + }, + "requiredSkills": { + "smithing": 35, + }, + }, + { + "cantHaveItems": undefined, + "inputItems": Bank { + "bank": { + "28798": 1, + "857": 1, + }, + "frozen": false, + }, + "name": "Bone shortbow", + "outputItems": Bank { + "bank": { + "28794": 1, + }, + "frozen": false, + }, + "requiredSkills": { + "fletching": 35, + }, + }, + { + "cantHaveItems": undefined, + "inputItems": Bank { + "bank": { + "1391": 1, + "28798": 1, + "562": 1000, + }, + "frozen": false, + }, + "name": "Bone staff", + "outputItems": Bank { + "bank": { + "28796": 1, + }, + "frozen": false, + }, + "requiredSkills": { + "crafting": 35, + }, + }, { "cantHaveItems": undefined, "inputItems": Bank { diff --git a/tests/unit/snapshots/clsnapshots.test.ts.snap b/tests/unit/snapshots/clsnapshots.test.ts.snap index 3cb60240be..2ce32f4fd1 100644 --- a/tests/unit/snapshots/clsnapshots.test.ts.snap +++ b/tests/unit/snapshots/clsnapshots.test.ts.snap @@ -5,7 +5,7 @@ exports[`OSB Collection Log Groups/Categories 1`] = ` Achievement Diary (48) Aerial Fishing (9) Alchemical Hydra (11) -All Pets (56) +All Pets (57) Barbarian Assault (11) Barrows Chests (25) Beginner Treasure Trails (16) @@ -25,7 +25,7 @@ Chompy Birds (19) Commander Zilyana (8) Corporeal Beast (7) Crazy archaeologist (3) -Creatables (643) +Creatables (646) Creature Creation (7) Cyclopes (8) Dagannoth Kings (10) @@ -79,6 +79,7 @@ Rogues' Den (5) Rooftop Agility (7) Sarachnis (4) Scorpia (3) +Scurrius (2) Shades of Mort'ton (14) Shared Treasure Trail Rewards (49) Shayzien Armour (25) @@ -1279,6 +1280,8 @@ Saradomin's light Scarred tablet Scorpia's offspring Scribbled note +Scurrius' spine +Scurry Scythe of vitur (uncharged) Seed box Seercull diff --git a/yarn.lock b/yarn.lock index a37086c2a8..1243bc14d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4027,10 +4027,10 @@ obliterator@^2.0.1: resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== -oldschooljs@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/oldschooljs/-/oldschooljs-2.5.0.tgz#a490a8b11f9630621ac05fde858dde51c75c0da0" - integrity sha512-zTSKe/tfFQ3BAs6bJRLrTeacOuAltYIehSJgRLqXR0NBTsSmjJjrVxJbKZXURptzWVwQTB8incT2oizzwacubQ== +oldschooljs@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/oldschooljs/-/oldschooljs-2.5.1.tgz#d152841ad6690c66ad7f3e4e2db046c0f0b45010" + integrity sha512-MAJnQQcD3Ofq0GjLZ+ZrmeQ6VLw7p0I3bH42OZTxIHaEBX+z6UFVxDszj8wPRNKFwZxKDgLTXOAc5O7L3JR57w== dependencies: deepmerge "^4.3.1" e "^0.2.32" From fb9889964bfd7954b9dcf67aae670259ba5960f6 Mon Sep 17 00:00:00 2001 From: gc <30398469+gc@users.noreply.github.com> Date: Wed, 28 Feb 2024 02:41:10 +1100 Subject: [PATCH 2/4] Update robochimp schema --- prisma/robochimp.prisma | 3 +++ 1 file changed, 3 insertions(+) diff --git a/prisma/robochimp.prisma b/prisma/robochimp.prisma index 9e237177e2..28c623bb44 100644 --- a/prisma/robochimp.prisma +++ b/prisma/robochimp.prisma @@ -57,6 +57,9 @@ model User { store_bitfield Int[] + testing_points Float @default(0) + testing_points_balance Float @default(0) + @@map("user") } From 3baa510e64bab3a6ba9ce1984cff5ca5b2685939 Mon Sep 17 00:00:00 2001 From: gc <30398469+gc@users.noreply.github.com> Date: Wed, 28 Feb 2024 02:42:10 +1100 Subject: [PATCH 3/4] Add manual analytics tick command --- src/mahoji/commands/rp.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/mahoji/commands/rp.ts b/src/mahoji/commands/rp.ts index 9b653f75c6..865218b7b8 100644 --- a/src/mahoji/commands/rp.ts +++ b/src/mahoji/commands/rp.ts @@ -9,6 +9,7 @@ import { Bank } from 'oldschooljs'; import { Item } from 'oldschooljs/dist/meta/types'; import { ADMIN_IDS, OWNER_IDS, production, SupportServer } from '../../config'; +import { analyticsTick } from '../../lib/analytics'; import { BitField, Channel } from '../../lib/constants'; import { GearSetupType } from '../../lib/gear/types'; import { GrandExchange } from '../../lib/grandExchange'; @@ -78,6 +79,12 @@ export const rpCommand: OSBMahojiCommand = { name: 'view_all_items', description: 'View all item IDs present in banks/cls.', options: [] + }, + { + type: ApplicationCommandOptionType.Subcommand, + name: 'analytics_tick', + description: 'analyticsTick.', + options: [] } ] }, @@ -309,6 +316,7 @@ export const rpCommand: OSBMahojiCommand = { validate_ge?: {}; patreon_reset?: {}; view_all_items?: {}; + analytics_tick?: {}; }; player?: { viewbank?: { user: MahojiUserOption; json?: boolean }; @@ -355,6 +363,10 @@ export const rpCommand: OSBMahojiCommand = { } return 'Something was invalid. Check logs!'; } + if (options.action?.analytics_tick) { + await analyticsTick(); + return 'Finished.'; + } if (options.action?.view_all_items) { const result = await prisma.$queryRawUnsafe< From ea735c1b49441ada20db33a25957521c5a9f4605 Mon Sep 17 00:00:00 2001 From: gc <30398469+gc@users.noreply.github.com> Date: Wed, 28 Feb 2024 02:47:01 +1100 Subject: [PATCH 4/4] Fix bigint bug --- src/lib/analytics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/analytics.ts b/src/lib/analytics.ts index 1d60da2474..629e2a067d 100644 --- a/src/lib/analytics.ts +++ b/src/lib/analytics.ts @@ -40,7 +40,7 @@ export async function analyticsTick() { await Promise.all( [ 'SELECT COUNT(*)::int FROM users WHERE "minion.hasBought" = true;', - 'SELECT SUM("sacrificedValue")::int AS count FROM users;', + 'SELECT SUM("sacrificedValue") AS count FROM users;', 'SELECT COUNT(*)::int FROM users WHERE "minion.ironman" = true;', 'SELECT SUM("GP") AS count FROM users;' ].map(query => prisma.$queryRawUnsafe(query))