From 21cb776e87d65a56a1fe5acc855b67e07343bf16 Mon Sep 17 00:00:00 2001 From: TastyPumPum Date: Mon, 16 Oct 2023 21:12:33 +0100 Subject: [PATCH] Remove Revenants Command and Activity Move revenants into the normal minionKill/monsterActivity files, this will help streamline wildy slayer. Allows quantity to be defined for revenants now. Adds salve amulet boost, which is huge for revs. Changed salve/blackmask/dragon hunter boosts to check for equipped gear if wilderness activties. --- .../20231016194554_feghg/migration.sql | 900 ++++++++++++++++++ prisma/migrations/migration_lock.toml | 3 + prisma/schema.prisma | 1 - src/lib/Task.ts | 2 - src/lib/minions/data/killableMonsters/revs.ts | 122 ++- src/lib/types/minions.ts | 11 - src/lib/util/minionStatus.ts | 9 - src/lib/util/repeatStoredTrip.ts | 7 - .../lib/abstracted_commands/minionKill.ts | 174 +++- .../lib/abstracted_commands/revsCommand.ts | 149 --- src/tasks/minions/monsterActivity.ts | 22 +- src/tasks/minions/revenantsActivity.ts | 138 --- 12 files changed, 1142 insertions(+), 396 deletions(-) create mode 100644 prisma/migrations/20231016194554_feghg/migration.sql create mode 100644 prisma/migrations/migration_lock.toml delete mode 100644 src/mahoji/lib/abstracted_commands/revsCommand.ts delete mode 100644 src/tasks/minions/revenantsActivity.ts diff --git a/prisma/migrations/20231016194554_feghg/migration.sql b/prisma/migrations/20231016194554_feghg/migration.sql new file mode 100644 index 0000000000..a32e27482a --- /dev/null +++ b/prisma/migrations/20231016194554_feghg/migration.sql @@ -0,0 +1,900 @@ +-- CreateEnum +CREATE TYPE "GearSetupType" AS ENUM ('melee', 'range', 'mage', 'misc', 'skilling', 'wildy', 'fashion', 'other'); + +-- CreateEnum +CREATE TYPE "bank_sort_method_enum" AS ENUM ('value', 'alch', 'name', 'quantity'); + +-- CreateEnum +CREATE TYPE "XpGainSource" AS ENUM ('TombsOfAmascut', 'UnderwaterAgilityThieving', 'ChambersOfXeric', 'TheatreOfBlood', 'NightmareZone', 'AshSanctifier', 'OfferingBones', 'TempleTrekking', 'DarkAltar', 'MotherlodeMine', 'Birdhouses', 'GuardiansOfTheRift', 'BuryingBones', 'ScatteringAshes', 'Zalcano', 'Wintertodt', 'FishingTrawler', 'Tempoross', 'TearsOfGuthix', 'ShadesOfMorton', 'PuroPuro', 'MahoganyHomes', 'AerialFishing', 'CleaningHerbsWhileFarming'); + +-- CreateEnum +CREATE TYPE "loot_track_type" AS ENUM ('Monster', 'Minigame', 'Skilling'); + +-- CreateEnum +CREATE TYPE "economy_transaction_type" AS ENUM ('trade', 'giveaway', 'duel', 'gri'); + +-- CreateEnum +CREATE TYPE "CropUpgradeType" AS ENUM ('compost', 'supercompost', 'ultracompost'); + +-- CreateEnum +CREATE TYPE "command_usage_status" AS ENUM ('Unknown', 'Success', 'Error', 'Inhibited'); + +-- CreateEnum +CREATE TYPE "activity_type_enum" AS ENUM ('Agility', 'Cooking', 'MonsterKilling', 'GroupMonsterKilling', 'ClueCompletion', 'Fishing', 'Mining', 'Smithing', 'Woodcutting', 'Questing', 'Firemaking', 'Runecraft', 'TiaraRunecraft', 'Smelting', 'Crafting', 'Burying', 'Scattering', 'Offering', 'FightCaves', 'Wintertodt', 'Tempoross', 'TitheFarm', 'Fletching', 'Pickpocket', 'Herblore', 'Hunter', 'Birdhouse', 'Alching', 'AnimatedArmour', 'Cyclops', 'Sawmill', 'Butler', 'Nightmare', 'Sepulchre', 'Plunder', 'FishingTrawler', 'Zalcano', 'Farming', 'Construction', 'Enchanting', 'Casting', 'GloryCharging', 'WealthCharging', 'BarbarianAssault', 'AgilityArena', 'ChampionsChallenge', 'AerialFishing', 'DriftNet', 'MahoganyHomes', 'GnomeRestaurant', 'SoulWars', 'RoguesDenMaze', 'Gauntlet', 'CastleWars', 'MageArena', 'Raids', 'Collecting', 'MageTrainingArena', 'CutLeapingFish', 'MotherlodeMining', 'BlastFurnace', 'MageArena2', 'BigChompyBirdHunting', 'DarkAltar', 'Trekking', 'PestControl', 'VolcanicMine', 'KourendFavour', 'Inferno', 'TearsOfGuthix', 'TheatreOfBlood', 'LastManStanding', 'BirthdayEvent', 'TokkulShop', 'Nex', 'TroubleBrewing', 'PuroPuro', 'Easter', 'ShootingStars', 'GiantsFoundry', 'GuardiansOfTheRift', 'HalloweenEvent', 'NightmareZone', 'ShadesOfMorton', 'TombsOfAmascut', 'UnderwaterAgilityThieving', 'StrongholdOfSecurity', 'SpecificQuest'); + +-- CreateEnum +CREATE TYPE "xp_gains_skill_enum" AS ENUM ('agility', 'cooking', 'fishing', 'mining', 'smithing', 'woodcutting', 'firemaking', 'runecraft', 'crafting', 'prayer', 'fletching', 'farming', 'herblore', 'thieving', 'hunter', 'construction', 'attack', 'defence', 'strength', 'ranged', 'magic', 'hitpoints', 'slayer'); + +-- CreateEnum +CREATE TYPE "AutoFarmFilterEnum" AS ENUM ('AllFarm', 'Replant'); + +-- CreateEnum +CREATE TYPE "GEListingType" AS ENUM ('Buy', 'Sell'); + +-- CreateTable +CREATE TABLE "activity" ( + "id" SERIAL NOT NULL, + "user_id" BIGINT NOT NULL, + "start_date" TIMESTAMP(6) NOT NULL, + "finish_date" TIMESTAMP(6) NOT NULL, + "duration" INTEGER NOT NULL, + "completed" BOOLEAN NOT NULL, + "group_activity" BOOLEAN NOT NULL, + "type" "activity_type_enum" NOT NULL, + "channel_id" BIGINT NOT NULL, + "data" JSON NOT NULL, + + CONSTRAINT "activity_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "analytics_table" ( + "timestamp" BIGINT NOT NULL, + "guildsCount" BIGINT, + "membersCount" BIGINT, + "clueTasksCount" INTEGER, + "minigameTasksCount" INTEGER, + "monsterTasksCount" INTEGER, + "skillingTasksCount" INTEGER, + "minionsCount" INTEGER, + "ironMinionsCount" INTEGER, + "totalSacrificed" BIGINT, + "totalGP" BIGINT, + "dicingBank" BIGINT, + "duelTaxBank" BIGINT, + "dailiesAmount" BIGINT, + "gpSellingItems" BIGINT, + "gpPvm" BIGINT, + "gpAlching" BIGINT, + "gpPickpocket" BIGINT, + "gpDice" BIGINT, + "gpOpen" BIGINT, + "gpDaily" BIGINT, + "gpLuckypick" BIGINT, + "gpSlots" BIGINT, + "gpHotCold" BIGINT, + + CONSTRAINT "analytics_table_pkey" PRIMARY KEY ("timestamp") +); + +-- CreateTable +CREATE TABLE "clientStorage" ( + "id" VARCHAR(19) NOT NULL, + "userBlacklist" VARCHAR(19)[], + "guildBlacklist" VARCHAR(19)[], + "commandStats" JSON NOT NULL DEFAULT '{}', + "totalCommandsUsed" INTEGER NOT NULL DEFAULT 0, + "prices" JSON NOT NULL DEFAULT '{}', + "sold_items_bank" JSON NOT NULL DEFAULT '{}', + "herblore_cost_bank" JSON NOT NULL DEFAULT '{}', + "construction_cost_bank" JSON NOT NULL DEFAULT '{}', + "farming_cost_bank" JSON NOT NULL DEFAULT '{}', + "farming_loot_bank" JSON NOT NULL DEFAULT '{}', + "buy_cost_bank" JSON NOT NULL DEFAULT '{}', + "buy_loot_bank" JSON NOT NULL DEFAULT '{}', + "magic_cost_bank" JSON NOT NULL DEFAULT '{}', + "crafting_cost" JSON NOT NULL DEFAULT '{}', + "gnome_res_cost" JSON NOT NULL DEFAULT '{}', + "gnome_res_loot" JSON NOT NULL DEFAULT '{}', + "rogues_den_cost" JSON NOT NULL DEFAULT '{}', + "gauntlet_loot" JSON NOT NULL DEFAULT '{}', + "cox_cost" JSON NOT NULL DEFAULT '{}', + "cox_loot" JSON NOT NULL DEFAULT '{}', + "collecting_cost" JSON NOT NULL DEFAULT '{}', + "collecting_loot" JSON NOT NULL DEFAULT '{}', + "mta_cost" JSON NOT NULL DEFAULT '{}', + "bf_cost" JSON NOT NULL DEFAULT '{}', + "mage_arena_cost" JSON NOT NULL DEFAULT '{}', + "hunter_cost" JSON NOT NULL DEFAULT '{}', + "hunter_loot" JSON NOT NULL DEFAULT '{}', + "revs_cost" JSON NOT NULL DEFAULT '{}', + "revs_loot" JSON NOT NULL DEFAULT '{}', + "inferno_cost" JSON NOT NULL DEFAULT '{}', + "dropped_items" JSON NOT NULL DEFAULT '{}', + "runecraft_cost" JSON NOT NULL DEFAULT '{}', + "smithing_cost" JSON NOT NULL DEFAULT '{}', + "economyStats.dicingBank" INTEGER NOT NULL DEFAULT 0, + "economyStats.duelTaxBank" INTEGER NOT NULL DEFAULT 0, + "economyStats.dailiesAmount" INTEGER NOT NULL DEFAULT 0, + "economyStats.itemSellTaxBank" INTEGER NOT NULL DEFAULT 0, + "economyStats.bankBgCostBank" JSON NOT NULL DEFAULT '{}', + "economyStats.sacrificedBank" JSON NOT NULL DEFAULT '{}', + "economyStats.wintertodtCost" JSON NOT NULL DEFAULT '{}', + "economyStats.wintertodtLoot" JSON NOT NULL DEFAULT '{}', + "economyStats.fightCavesCost" JSON NOT NULL DEFAULT '{}', + "economyStats.PVMCost" JSON NOT NULL DEFAULT '{}', + "economyStats.thievingCost" JSON NOT NULL DEFAULT '{}', + "gp_sell" BIGINT NOT NULL DEFAULT 0, + "gp_pvm" BIGINT NOT NULL DEFAULT 0, + "gp_alch" BIGINT NOT NULL DEFAULT 0, + "gp_pickpocket" BIGINT NOT NULL DEFAULT 0, + "gp_dice" BIGINT NOT NULL DEFAULT 0, + "gp_open" BIGINT NOT NULL DEFAULT 0, + "gp_daily" BIGINT NOT NULL DEFAULT 0, + "gp_luckypick" BIGINT NOT NULL DEFAULT 0, + "gp_slots" BIGINT NOT NULL DEFAULT 0, + "gp_hotcold" BIGINT NOT NULL DEFAULT 0, + "custom_prices" JSON NOT NULL DEFAULT '{}', + "nightmare_cost" JSON NOT NULL DEFAULT '{}', + "create_cost" JSON NOT NULL DEFAULT '{}', + "create_loot" JSON NOT NULL DEFAULT '{}', + "tob_cost" JSON NOT NULL DEFAULT '{}', + "tob_loot" JSON NOT NULL DEFAULT '{}', + "nex_cost" JSON NOT NULL DEFAULT '{}', + "nex_loot" JSON NOT NULL DEFAULT '{}', + "degraded_items_cost" JSON NOT NULL DEFAULT '{}', + "tks_cost" JSON NOT NULL DEFAULT '{}', + "tks_loot" JSON NOT NULL DEFAULT '{}', + "disabled_commands" VARCHAR(32)[], + "gp_tax_balance" BIGINT NOT NULL DEFAULT 0, + "gotr_cost" JSON NOT NULL DEFAULT '{}', + "gotr_loot" JSON NOT NULL DEFAULT '{}', + "gf_cost" JSON NOT NULL DEFAULT '{}', + "gf_loot" JSON NOT NULL DEFAULT '{}', + "nmz_cost" JSON NOT NULL DEFAULT '{}', + "toa_cost" JSON NOT NULL DEFAULT '{}', + "toa_loot" JSON NOT NULL DEFAULT '{}', + "grand_exchange_is_locked" BOOLEAN NOT NULL DEFAULT false, + "grand_exchange_total_tax" BIGINT NOT NULL DEFAULT 0, + "grand_exchange_tax_bank" BIGINT NOT NULL DEFAULT 0, + + CONSTRAINT "clientStorage_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "buy_command_transaction" ( + "id" UUID NOT NULL, + "date" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "user_id" BIGINT NOT NULL, + "cost_gp" BIGINT NOT NULL, + "cost_bank_excluding_gp" JSON, + "loot_bank" JSON, + + CONSTRAINT "buy_command_transaction_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "gear_presets" ( + "user_id" VARCHAR(19) NOT NULL, + "name" VARCHAR(24) NOT NULL, + "two_handed" INTEGER, + "body" INTEGER, + "cape" INTEGER, + "feet" INTEGER, + "hands" INTEGER, + "head" INTEGER, + "legs" INTEGER, + "neck" INTEGER, + "ring" INTEGER, + "shield" INTEGER, + "weapon" INTEGER, + "ammo" INTEGER, + "ammo_qty" INTEGER, + "emoji_id" VARCHAR(19), + "times_equipped" INTEGER NOT NULL DEFAULT 0, + "pinned_setup" "GearSetupType", + + CONSTRAINT "gear_presets_pkey" PRIMARY KEY ("user_id","name") +); + +-- CreateTable +CREATE TABLE "giveaway" ( + "id" INTEGER NOT NULL, + "user_id" VARCHAR(19) NOT NULL, + "start_date" TIMESTAMP(6) NOT NULL, + "finish_date" TIMESTAMP(6) NOT NULL, + "duration" INTEGER NOT NULL, + "completed" BOOLEAN NOT NULL, + "channel_id" VARCHAR(19) NOT NULL, + "loot" JSON NOT NULL, + "message_id" VARCHAR(19) NOT NULL, + "reaction_id" VARCHAR(19), + "users_entered" TEXT[], + + CONSTRAINT "giveaway_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "guilds" ( + "id" VARCHAR(19) NOT NULL, + "disabledCommands" TEXT[], + "jmodComments" VARCHAR(19), + "petchannel" VARCHAR(19), + "tweetchannel" VARCHAR(19), + "staffOnlyChannels" VARCHAR(19)[], + + CONSTRAINT "guilds_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "new_users" ( + "id" VARCHAR(19) NOT NULL, + "username" VARCHAR(32), + "pizazz_points" INTEGER NOT NULL DEFAULT 0, + "minigame_id" INTEGER, + + CONSTRAINT "new_users_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "pingable_roles" ( + "id" SERIAL NOT NULL, + "role_id" VARCHAR(19) NOT NULL, + "name" VARCHAR(32) NOT NULL, + + CONSTRAINT "pingable_roles_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "poh" ( + "user_id" VARCHAR(19) NOT NULL, + "background_id" INTEGER NOT NULL DEFAULT 1, + "altar" INTEGER, + "throne" INTEGER, + "mounted_cape" INTEGER, + "mounted_fish" INTEGER, + "mounted_head" INTEGER, + "mounted_item" INTEGER, + "jewellery_box" INTEGER, + "prayer_altar" INTEGER, + "spellbook_altar" INTEGER, + "guard" INTEGER, + "torch" INTEGER, + "dungeon_decoration" INTEGER, + "prison" INTEGER, + "pool" INTEGER, + "teleport" INTEGER, + "garden_decoration" INTEGER, + "amulet" INTEGER, + + CONSTRAINT "poh_pkey" PRIMARY KEY ("user_id") +); + +-- CreateTable +CREATE TABLE "slayer_tasks" ( + "id" SERIAL NOT NULL, + "created_at" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "quantity" SMALLINT NOT NULL, + "quantity_remaining" SMALLINT NOT NULL, + "slayer_master_id" SMALLINT NOT NULL, + "monster_id" INTEGER NOT NULL, + "skipped" BOOLEAN NOT NULL, + "user_id" VARCHAR(19) NOT NULL, + + CONSTRAINT "slayer_tasks_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "users" ( + "id" VARCHAR(19) NOT NULL, + "last_command_date" TIMESTAMP(6), + "minion_bought_date" TIMESTAMP(6), + "minion.hasBought" BOOLEAN NOT NULL DEFAULT false, + "minion.ironman" BOOLEAN NOT NULL DEFAULT false, + "premium_balance_tier" INTEGER, + "premium_balance_expiry_date" BIGINT, + "RSN" TEXT, + "pets" JSON NOT NULL DEFAULT '{}', + "sacrificedValue" BIGINT NOT NULL DEFAULT 0, + "GP" BIGINT NOT NULL DEFAULT 0, + "QP" INTEGER NOT NULL DEFAULT 0, + "bank" JSON NOT NULL DEFAULT '{}', + "collectionLogBank" JSONB NOT NULL DEFAULT '{}', + "blowpipe" JSON NOT NULL DEFAULT '{"scales":0,"dartID":null,"dartQuantity":0}', + "ironman_alts" TEXT[], + "main_account" TEXT, + "slayer.unlocks" INTEGER[], + "slayer.blocked_ids" INTEGER[], + "slayer.last_task" INTEGER NOT NULL DEFAULT 0, + "badges" INTEGER[], + "bitfield" INTEGER[], + "temp_cl" JSON NOT NULL DEFAULT '{}', + "last_temp_cl_reset" TIMESTAMP(6), + "minion.equippedPet" INTEGER, + "minion.farmingContract" JSON, + "minion.birdhouseTraps" JSON, + "finished_quest_ids" INTEGER[], + "minion.defaultCompostToUse" "CropUpgradeType" NOT NULL DEFAULT E'compost', + "auto_farm_filter" "AutoFarmFilterEnum" NOT NULL DEFAULT E'AllFarm', + "favoriteItems" INTEGER[], + "favorite_alchables" INTEGER[], + "favorite_food" INTEGER[], + "minion.defaultPay" BOOLEAN NOT NULL DEFAULT false, + "minion.icon" TEXT, + "minion.name" TEXT, + "bank_bg_hex" TEXT, + "bankBackground" INTEGER NOT NULL DEFAULT 1, + "attack_style" TEXT[], + "combat_options" INTEGER[], + "slayer.remember_master" TEXT, + "slayer.autoslay_options" INTEGER[], + "bank_sort_method" VARCHAR(16), + "bank_sort_weightings" JSON NOT NULL DEFAULT '{}', + "gambling_lockout_expiry" TIMESTAMP(3), + "skills.agility" BIGINT NOT NULL DEFAULT 0, + "skills.cooking" BIGINT NOT NULL DEFAULT 0, + "skills.fishing" BIGINT NOT NULL DEFAULT 0, + "skills.mining" BIGINT NOT NULL DEFAULT 0, + "skills.smithing" BIGINT NOT NULL DEFAULT 0, + "skills.woodcutting" BIGINT NOT NULL DEFAULT 0, + "skills.firemaking" BIGINT NOT NULL DEFAULT 0, + "skills.runecraft" BIGINT NOT NULL DEFAULT 0, + "skills.crafting" BIGINT NOT NULL DEFAULT 0, + "skills.prayer" BIGINT NOT NULL DEFAULT 0, + "skills.fletching" BIGINT NOT NULL DEFAULT 0, + "skills.thieving" BIGINT NOT NULL DEFAULT 0, + "skills.farming" BIGINT NOT NULL DEFAULT 0, + "skills.herblore" BIGINT NOT NULL DEFAULT 0, + "skills.hunter" BIGINT NOT NULL DEFAULT 0, + "skills.construction" BIGINT NOT NULL DEFAULT 0, + "skills.magic" BIGINT NOT NULL DEFAULT 0, + "skills.ranged" BIGINT NOT NULL DEFAULT 0, + "skills.attack" BIGINT NOT NULL DEFAULT 0, + "skills.strength" BIGINT NOT NULL DEFAULT 0, + "skills.defence" BIGINT NOT NULL DEFAULT 0, + "skills.slayer" BIGINT NOT NULL DEFAULT 0, + "skills.hitpoints" BIGINT NOT NULL DEFAULT 1154, + "gear.melee" JSON, + "gear.mage" JSON, + "gear.range" JSON, + "gear.misc" JSON, + "gear.skilling" JSON, + "gear.wildy" JSON, + "gear.fashion" JSON, + "gear.other" JSON, + "tentacle_charges" INTEGER NOT NULL DEFAULT 0, + "sang_charges" INTEGER NOT NULL DEFAULT 0, + "celestial_ring_charges" INTEGER NOT NULL DEFAULT 0, + "ash_sanctifier_charges" INTEGER NOT NULL DEFAULT 0, + "serp_helm_charges" INTEGER NOT NULL DEFAULT 0, + "blood_fury_charges" INTEGER NOT NULL DEFAULT 0, + "tum_shadow_charges" INTEGER NOT NULL DEFAULT 0, + "blood_essence_charges" INTEGER NOT NULL DEFAULT 0, + "trident_charges" INTEGER NOT NULL DEFAULT 0, + "scythe_of_vitur_charges" INTEGER NOT NULL DEFAULT 0, + "lms_points" INTEGER NOT NULL DEFAULT 0, + "volcanic_mine_points" INTEGER NOT NULL DEFAULT 0, + "nmz_points" INTEGER NOT NULL DEFAULT 0, + "carpenter_points" INTEGER NOT NULL DEFAULT 0, + "zeal_tokens" INTEGER NOT NULL DEFAULT 0, + "slayer.points" INTEGER NOT NULL DEFAULT 0, + "completed_ca_task_ids" INTEGER[], + "farmingPatches.herb" JSON, + "farmingPatches.fruit tree" JSON, + "farmingPatches.tree" JSON, + "farmingPatches.allotment" JSON, + "farmingPatches.hops" JSON, + "farmingPatches.cactus" JSON, + "farmingPatches.bush" JSON, + "farmingPatches.spirit" JSON, + "farmingPatches.hardwood" JSON, + "farmingPatches.seaweed" JSON, + "farmingPatches.vine" JSON, + "farmingPatches.calquat" JSON, + "farmingPatches.redwood" JSON, + "farmingPatches.crystal" JSON, + "farmingPatches.celastrus" JSON, + "farmingPatches.hespori" JSON, + "farmingPatches.flower" JSON, + "farmingPatches.mushroom" JSON, + "farmingPatches.belladonna" JSON, + "kourend_favour" JSON, + + CONSTRAINT "users_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "reclaimable_item" ( + "user_id" VARCHAR(19) NOT NULL, + "key" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "date" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "item_id" INTEGER NOT NULL, + "quantity" INTEGER NOT NULL, + + CONSTRAINT "reclaimable_item_pkey" PRIMARY KEY ("user_id","key") +); + +-- CreateTable +CREATE TABLE "webhook_table" ( + "channel_id" VARCHAR(19) NOT NULL, + "webhook_id" VARCHAR(19) NOT NULL, + "webhook_token" VARCHAR(100) NOT NULL, + + CONSTRAINT "webhook_table_pkey" PRIMARY KEY ("channel_id") +); + +-- CreateTable +CREATE TABLE "xp_gains" ( + "id" SERIAL NOT NULL, + "user_id" BIGINT NOT NULL, + "date" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "skill" "xp_gains_skill_enum" NOT NULL, + "xp" INTEGER NOT NULL, + "artificial" BOOLEAN, + "post_max" BOOLEAN NOT NULL DEFAULT false, + "source" "XpGainSource", + + CONSTRAINT "xp_gains_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "metrics" ( + "timestamp" BIGINT NOT NULL, + "eventLoopDelayMin" REAL NOT NULL, + "eventLoopDelayMax" REAL NOT NULL, + "eventLoopDelayMean" REAL NOT NULL, + "memorySizeTotal" BIGINT NOT NULL, + "memorySizeUsed" BIGINT NOT NULL, + "memorySizeExternal" BIGINT NOT NULL, + "memorySizeRSS" BIGINT NOT NULL, + "cpuUser" REAL NOT NULL, + "cpuSystem" REAL NOT NULL, + "cpuPercent" REAL NOT NULL, + "qps" REAL, + "prisma_query_total_queries" INTEGER, + "prisma_pool_active_connections" INTEGER, + "prisma_pool_idle_connections" INTEGER, + "prisma_pool_wait_count" INTEGER, + "prisma_query_active_transactions" INTEGER, + + CONSTRAINT "metrics_pkey" PRIMARY KEY ("timestamp") +); + +-- CreateTable +CREATE TABLE "minigames" ( + "id" SERIAL NOT NULL, + "user_id" VARCHAR(19) NOT NULL, + "tithe_farm" INTEGER NOT NULL DEFAULT 0, + "wintertodt" INTEGER NOT NULL DEFAULT 0, + "tempoross" INTEGER NOT NULL DEFAULT 0, + "sepulchre" INTEGER NOT NULL DEFAULT 0, + "fishing_trawler" INTEGER NOT NULL DEFAULT 0, + "barb_assault" INTEGER NOT NULL DEFAULT 0, + "pyramid_plunder" INTEGER NOT NULL DEFAULT 0, + "agility_arena" INTEGER NOT NULL DEFAULT 0, + "champions_challenge" INTEGER NOT NULL DEFAULT 0, + "mahogany_homes" INTEGER NOT NULL DEFAULT 0, + "gnome_restaurant" INTEGER NOT NULL DEFAULT 0, + "soul_wars" INTEGER NOT NULL DEFAULT 0, + "rogues_den" INTEGER NOT NULL DEFAULT 0, + "gauntlet" INTEGER NOT NULL DEFAULT 0, + "corrupted_gauntlet" INTEGER NOT NULL DEFAULT 0, + "castle_wars" INTEGER NOT NULL DEFAULT 0, + "raids" INTEGER NOT NULL DEFAULT 0, + "raids_challenge_mode" INTEGER NOT NULL DEFAULT 0, + "magic_training_arena" INTEGER NOT NULL DEFAULT 0, + "big_chompy_bird_hunting" INTEGER NOT NULL DEFAULT 0, + "temple_trekking" INTEGER NOT NULL DEFAULT 0, + "pest_control" INTEGER NOT NULL DEFAULT 0, + "inferno" INTEGER NOT NULL DEFAULT 0, + "volcanic_mine" INTEGER NOT NULL DEFAULT 0, + "tears_of_guthix" INTEGER NOT NULL DEFAULT 0, + "tob" INTEGER NOT NULL DEFAULT 0, + "tob_hard" INTEGER NOT NULL DEFAULT 0, + "lms" INTEGER NOT NULL DEFAULT 0, + "trouble_brewing" INTEGER NOT NULL DEFAULT 0, + "puro_puro" INTEGER NOT NULL DEFAULT 0, + "giants_foundry" INTEGER NOT NULL DEFAULT 0, + "guardians_of_the_rift" INTEGER NOT NULL DEFAULT 0, + "nmz" INTEGER NOT NULL DEFAULT 0, + "shades_of_morton" INTEGER NOT NULL DEFAULT 0, + "tombs_of_amascut" INTEGER NOT NULL DEFAULT 0, + + CONSTRAINT "minigames_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "command_usage" ( + "id" SERIAL NOT NULL, + "date" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "user_id" BIGINT NOT NULL, + "command_name" VARCHAR(32) NOT NULL, + "status" "command_usage_status" NOT NULL DEFAULT E'Unknown', + "is_continue" BOOLEAN NOT NULL DEFAULT false, + "flags" JSONB, + "inhibited" BOOLEAN DEFAULT false, + "is_mention_command" BOOLEAN NOT NULL DEFAULT false, + "args" JSON, + "channel_id" BIGINT, + "guild_id" BIGINT, + "continue_delta_millis" BIGINT, + + CONSTRAINT "command_usage_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "loot_track" ( + "id" UUID NOT NULL, + "key" VARCHAR(32) NOT NULL, + "type" "loot_track_type" NOT NULL, + "total_duration" INTEGER NOT NULL, + "total_kc" INTEGER NOT NULL, + "loot" JSON NOT NULL DEFAULT '{}', + "cost" JSON NOT NULL DEFAULT '{}', + "user_id" BIGINT, + + CONSTRAINT "loot_track_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "economy_item" ( + "item_id" INTEGER NOT NULL, + "quantity" BIGINT NOT NULL, + "date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "economy_item_pkey" PRIMARY KEY ("item_id","date") +); + +-- CreateTable +CREATE TABLE "lms_games" ( + "id" SERIAL NOT NULL, + "user_id" BIGINT NOT NULL, + "date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "position" SMALLINT NOT NULL, + "kills" SMALLINT NOT NULL, + + CONSTRAINT "lms_games_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "economy_transaction" ( + "id" UUID NOT NULL, + "date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "sender" BIGINT NOT NULL, + "recipient" BIGINT NOT NULL, + "guild_id" BIGINT, + "type" "economy_transaction_type" NOT NULL, + "items_sent" JSON DEFAULT '{}', + "items_received" JSON DEFAULT '{}', + + CONSTRAINT "economy_transaction_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "stash_unit" ( + "stash_id" INTEGER NOT NULL, + "user_id" BIGINT NOT NULL, + "items_contained" INTEGER[], + "has_built" BOOLEAN NOT NULL +); + +-- CreateTable +CREATE TABLE "user_stats" ( + "user_id" BIGINT NOT NULL, + "sell_gp" BIGINT NOT NULL DEFAULT 0, + "items_sold_bank" JSON NOT NULL DEFAULT '{}', + "puropuro_implings_bank" JSON NOT NULL DEFAULT '{}', + "passive_implings_bank" JSON NOT NULL DEFAULT '{}', + "create_cost_bank" JSON NOT NULL DEFAULT '{}', + "create_loot_bank" JSON NOT NULL DEFAULT '{}', + "bird_eggs_offered_bank" JSON NOT NULL DEFAULT '{}', + "scattered_ashes_bank" JSON NOT NULL DEFAULT '{}', + "gf_weapons_made" JSON NOT NULL DEFAULT '{}', + "gf_cost" JSON NOT NULL DEFAULT '{}', + "gf_loot" JSON NOT NULL DEFAULT '{}', + "ash_sanctifier_prayer_xp" BIGINT NOT NULL DEFAULT 0, + "gotr_rift_searches" INTEGER NOT NULL DEFAULT 0, + "farming_plant_cost_bank" JSON NOT NULL DEFAULT '{}', + "farming_harvest_loot_bank" JSON NOT NULL DEFAULT '{}', + "cl_array" INTEGER[], + "cl_array_length" INTEGER NOT NULL DEFAULT 0, + "buy_cost_bank" JSON NOT NULL DEFAULT '{}', + "buy_loot_bank" JSON NOT NULL DEFAULT '{}', + "shades_of_morton_cost_bank" JSON NOT NULL DEFAULT '{}', + "gp_from_agil_pyramid" INTEGER NOT NULL DEFAULT 0, + "random_event_completions_bank" JSON NOT NULL DEFAULT '{}', + "toa_attempts" INTEGER NOT NULL DEFAULT 0, + "toa_cost" JSON NOT NULL DEFAULT '{}', + "toa_loot" JSON NOT NULL DEFAULT '{}', + "total_toa_points" INTEGER NOT NULL DEFAULT 0, + "toa_raid_levels_bank" JSON NOT NULL DEFAULT '{}', + "total_toa_duration_minutes" INTEGER NOT NULL DEFAULT 0, + "deaths" INTEGER NOT NULL DEFAULT 0, + "pk_evasion_exp" INTEGER NOT NULL DEFAULT 0, + "dice_wins" INTEGER NOT NULL DEFAULT 0, + "dice_losses" INTEGER NOT NULL DEFAULT 0, + "duel_losses" INTEGER NOT NULL DEFAULT 0, + "duel_wins" INTEGER NOT NULL DEFAULT 0, + "fight_caves_attempts" INTEGER NOT NULL DEFAULT 0, + "firecapes_sacrificed" INTEGER NOT NULL DEFAULT 0, + "tithe_farms_completed" INTEGER NOT NULL DEFAULT 0, + "tithe_farm_points" INTEGER NOT NULL DEFAULT 0, + "pest_control_points" INTEGER NOT NULL DEFAULT 0, + "inferno_attempts" INTEGER NOT NULL DEFAULT 0, + "infernal_cape_sacrifices" INTEGER NOT NULL DEFAULT 0, + "tob_attempts" INTEGER NOT NULL DEFAULT 0, + "foundry_reputation" INTEGER NOT NULL DEFAULT 0, + "tob_hard_attempts" INTEGER NOT NULL DEFAULT 0, + "total_cox_points" INTEGER NOT NULL DEFAULT 0, + "honour_level" INTEGER NOT NULL DEFAULT 1, + "high_gambles" INTEGER NOT NULL DEFAULT 0, + "honour_points" INTEGER NOT NULL DEFAULT 0, + "slayer_task_streak" INTEGER NOT NULL DEFAULT 0, + "slayer_superior_count" INTEGER NOT NULL DEFAULT 0, + "slayer_unsired_offered" INTEGER NOT NULL DEFAULT 0, + "slayer_chewed_offered" INTEGER NOT NULL DEFAULT 0, + "tob_cost" JSONB NOT NULL DEFAULT '{}', + "tob_loot" JSONB NOT NULL DEFAULT '{}', + "creature_scores" JSONB NOT NULL DEFAULT '{}', + "monster_scores" JSONB NOT NULL DEFAULT '{}', + "laps_scores" JSONB NOT NULL DEFAULT '{}', + "sacrificed_bank" JSONB NOT NULL DEFAULT '{}', + "openable_scores" JSONB NOT NULL DEFAULT '{}', + "gp_luckypick" BIGINT NOT NULL DEFAULT 0, + "gp_dice" BIGINT NOT NULL DEFAULT 0, + "gp_slots" BIGINT NOT NULL DEFAULT 0, + "gp_hotcold" BIGINT NOT NULL DEFAULT 0, + "total_gp_traded" BIGINT NOT NULL DEFAULT 0, + "last_daily_timestamp" BIGINT NOT NULL DEFAULT 0, + "last_tears_of_guthix_timestamp" BIGINT NOT NULL DEFAULT 0, + + CONSTRAINT "user_stats_pkey" PRIMARY KEY ("user_id") +); + +-- CreateTable +CREATE TABLE "farmed_crop" ( + "id" SERIAL NOT NULL, + "user_id" VARCHAR(19) NOT NULL, + "date_planted" TIMESTAMP(3) NOT NULL, + "date_harvested" TIMESTAMP(3), + "item_id" INTEGER NOT NULL, + "quantity_planted" INTEGER NOT NULL, + "upgrade_type" "CropUpgradeType", + "was_autofarmed" BOOLEAN NOT NULL, + "paid_for_protection" BOOLEAN NOT NULL, + + CONSTRAINT "farmed_crop_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "bot_item_sell" ( + "id" UUID NOT NULL, + "date" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "item_id" INTEGER NOT NULL, + "quantity" INTEGER NOT NULL, + "gp_received" BIGINT NOT NULL, + "user_id" VARCHAR(19) NOT NULL, + + CONSTRAINT "bot_item_sell_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "pinned_trip" ( + "id" TEXT NOT NULL, + "user_id" VARCHAR(19) NOT NULL, + "activity_id" INTEGER NOT NULL, + "emoji_id" VARCHAR(19), + "activity_type" "activity_type_enum" NOT NULL, + "data" JSON, + "custom_name" VARCHAR(32), + + CONSTRAINT "pinned_trip_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "historical_data" ( + "user_id" VARCHAR(19) NOT NULL, + "date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "cl_global_rank" SMALLINT NOT NULL, + "cl_completion_percentage" DECIMAL(5,2) NOT NULL, + "cl_completion_count" SMALLINT NOT NULL, + "GP" DECIMAL(13,0) NOT NULL, + "total_xp" DECIMAL(13,0) NOT NULL, + + CONSTRAINT "historical_data_pkey" PRIMARY KEY ("user_id","date") +); + +-- CreateTable +CREATE TABLE "ge_listing" ( + "id" SERIAL NOT NULL, + "type" "GEListingType" NOT NULL, + "userfacing_id" TEXT NOT NULL, + "user_id" VARCHAR(19), + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "cancelled_at" TIMESTAMP(3), + "fulfilled_at" TIMESTAMP(3), + "gp_refunded" BIGINT NOT NULL DEFAULT 0, + "item_id" INTEGER NOT NULL, + "asking_price_per_item" BIGINT NOT NULL, + "total_quantity" INTEGER NOT NULL, + "quantity_remaining" INTEGER NOT NULL, + + CONSTRAINT "ge_listing_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ge_transaction" ( + "id" SERIAL NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "quantity_bought" INTEGER NOT NULL, + "price_per_item_before_tax" BIGINT NOT NULL, + "price_per_item_after_tax" BIGINT NOT NULL, + "tax_rate_percent" SMALLINT NOT NULL, + "total_tax_paid" BIGINT NOT NULL, + "buy_listing_id" INTEGER NOT NULL, + "sell_listing_id" INTEGER NOT NULL, + + CONSTRAINT "ge_transaction_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ge_bank" ( + "item_id" INTEGER NOT NULL, + "quantity" BIGINT NOT NULL, + + CONSTRAINT "ge_bank_pkey" PRIMARY KEY ("item_id") +); + +-- CreateTable +CREATE TABLE "bingo" ( + "id" SERIAL NOT NULL, + "creator_id" VARCHAR(19) NOT NULL, + "is_global" BOOLEAN NOT NULL DEFAULT false, + "organizers" TEXT[], + "start_date" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "duration_days" INTEGER NOT NULL, + "team_size" INTEGER NOT NULL, + "title" TEXT NOT NULL, + "notifications_channel_id" VARCHAR(19) NOT NULL, + "ticket_price" BIGINT NOT NULL, + "bingo_tiles" JSONB[], + "was_finalized" BOOLEAN NOT NULL DEFAULT false, + "guild_id" VARCHAR(19) NOT NULL, + "extra_gp" BIGINT NOT NULL DEFAULT 0, + "trophies_apply" BOOLEAN NOT NULL DEFAULT false, + + CONSTRAINT "bingo_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "bingo_team" ( + "id" SERIAL NOT NULL, + "bingo_id" INTEGER NOT NULL, + + CONSTRAINT "bingo_team_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "bingo_participant" ( + "tickets_bought" INTEGER NOT NULL, + "bingo_id" INTEGER NOT NULL, + "user_id" VARCHAR(19) NOT NULL, + "bingo_team_id" INTEGER NOT NULL, + "cl" JSON NOT NULL DEFAULT '{}' +); + +-- CreateIndex +CREATE UNIQUE INDEX "activity_id_key" ON "activity"("id"); + +-- CreateIndex +CREATE INDEX "activity_user_id_finish_date_idx" ON "activity"("user_id", "finish_date"); + +-- CreateIndex +CREATE INDEX "activity_group_activity_idx" ON "activity"("group_activity"); + +-- CreateIndex +CREATE INDEX "activity_completed_idx" ON "activity"("completed"); + +-- CreateIndex +CREATE INDEX "activity_user_id_type_idx" ON "activity"("user_id", "type"); + +-- CreateIndex +CREATE INDEX "activity_finish_date_idx" ON "activity"("finish_date"); + +-- CreateIndex +CREATE INDEX "giveaway_completed_finish_date_idx" ON "giveaway"("completed", "finish_date"); + +-- CreateIndex +CREATE UNIQUE INDEX "new_users_minigame_id_key" ON "new_users"("minigame_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "pingable_roles_role_id_key" ON "pingable_roles"("role_id"); + +-- CreateIndex +CREATE INDEX "slayer_tasks_user_id_quantity_remaining_idx" ON "slayer_tasks"("user_id", "quantity_remaining"); + +-- CreateIndex +CREATE INDEX "users_id_last_command_date_idx" ON "users"("id", "last_command_date"); + +-- CreateIndex +CREATE UNIQUE INDEX "reclaimable_item_user_id_key_key" ON "reclaimable_item"("user_id", "key"); + +-- CreateIndex +CREATE INDEX "xp_gains_date_skill_idx" ON "xp_gains"("date", "skill"); + +-- CreateIndex +CREATE UNIQUE INDEX "minigames_user_id_key" ON "minigames"("user_id"); + +-- CreateIndex +CREATE INDEX "minigames_user_id_idx" ON "minigames"("user_id"); + +-- CreateIndex +CREATE INDEX "loot_track_key_user_id_idx" ON "loot_track"("key", "user_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "stash_unit_stash_id_user_id_key" ON "stash_unit"("stash_id", "user_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "ge_listing_id_key" ON "ge_listing"("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "ge_transaction_id_key" ON "ge_transaction"("id"); + +-- CreateIndex +CREATE INDEX "ge_transaction_sell_listing_id_idx" ON "ge_transaction"("sell_listing_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "bingo_id_key" ON "bingo"("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "bingo_team_id_key" ON "bingo_team"("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "bingo_participant_user_id_bingo_id_key" ON "bingo_participant"("user_id", "bingo_id"); + +-- AddForeignKey +ALTER TABLE "new_users" ADD CONSTRAINT "new_users_minigame_id_fkey" FOREIGN KEY ("minigame_id") REFERENCES "minigames"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "slayer_tasks" ADD CONSTRAINT "slayer_tasks_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "new_users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "farmed_crop" ADD CONSTRAINT "farmed_crop_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "bot_item_sell" ADD CONSTRAINT "bot_item_sell_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "pinned_trip" ADD CONSTRAINT "pinned_trip_activity_id_fkey" FOREIGN KEY ("activity_id") REFERENCES "activity"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "pinned_trip" ADD CONSTRAINT "pinned_trip_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "historical_data" ADD CONSTRAINT "historical_data_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ge_listing" ADD CONSTRAINT "ge_listing_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ge_transaction" ADD CONSTRAINT "ge_transaction_buy_listing_id_fkey" FOREIGN KEY ("buy_listing_id") REFERENCES "ge_listing"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ge_transaction" ADD CONSTRAINT "ge_transaction_sell_listing_id_fkey" FOREIGN KEY ("sell_listing_id") REFERENCES "ge_listing"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "bingo" ADD CONSTRAINT "bingo_creator_id_fkey" FOREIGN KEY ("creator_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "bingo_team" ADD CONSTRAINT "bingo_team_bingo_id_fkey" FOREIGN KEY ("bingo_id") REFERENCES "bingo"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "bingo_participant" ADD CONSTRAINT "bingo_participant_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "bingo_participant" ADD CONSTRAINT "bingo_participant_bingo_id_fkey" FOREIGN KEY ("bingo_id") REFERENCES "bingo"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "bingo_participant" ADD CONSTRAINT "bingo_participant_bingo_team_id_fkey" FOREIGN KEY ("bingo_team_id") REFERENCES "bingo_team"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000000..fbffa92c2b --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2f3321871d..a16a66aa00 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -896,7 +896,6 @@ enum activity_type_enum { BigChompyBirdHunting DarkAltar Trekking - Revenants PestControl VolcanicMine KourendFavour diff --git a/src/lib/Task.ts b/src/lib/Task.ts index 5a46133d42..c2db0c4f2f 100644 --- a/src/lib/Task.ts +++ b/src/lib/Task.ts @@ -69,7 +69,6 @@ import { buryingTask } from '../tasks/minions/PrayerActivity/buryingActivity'; import { offeringTask } from '../tasks/minions/PrayerActivity/offeringActivity'; import { scatteringTask } from '../tasks/minions/PrayerActivity/scatteringActivity'; import { questingTask } from '../tasks/minions/questingActivity'; -import { revenantsTask } from '../tasks/minions/revenantsActivity'; import { runecraftTask } from '../tasks/minions/runecraftActivity'; import { sawmillTask } from '../tasks/minions/sawmillActivity'; import { shootingStarTask } from '../tasks/minions/shootingStarsActivity'; @@ -150,7 +149,6 @@ export const tasks: MinionTask[] = [ motherlodeMiningTask, runecraftTask, sawmillTask, - revenantsTask, woodcuttingTask, wealthChargeTask, tokkulShopTask, diff --git a/src/lib/minions/data/killableMonsters/revs.ts b/src/lib/minions/data/killableMonsters/revs.ts index 1bfd7ff969..f1923e29ff 100644 --- a/src/lib/minions/data/killableMonsters/revs.ts +++ b/src/lib/minions/data/killableMonsters/revs.ts @@ -1,5 +1,5 @@ import { Time } from 'e'; -import { Monsters } from 'oldschooljs'; +import { Bank, Monsters } from 'oldschooljs'; import { KillableMonster } from '../../types'; @@ -8,132 +8,188 @@ export const revenantMonsters: KillableMonster[] = [ id: Monsters.RevenantCyclops.id, name: Monsters.RevenantCyclops.name, aliases: Monsters.RevenantCyclops.aliases, - timeToFinish: Time.Second * 50, + timeToFinish: Time.Second * 82, table: Monsters.RevenantCyclops, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 6, - pkBaseDeathChance: 5 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantDarkBeast.id, name: Monsters.RevenantDarkBeast.name, aliases: Monsters.RevenantDarkBeast.aliases, - timeToFinish: Time.Second * 70, + timeToFinish: Time.Second * 114, table: Monsters.RevenantDarkBeast, wildy: true, difficultyRating: 9, qpRequired: 0, pkActivityRating: 9, - pkBaseDeathChance: 4 + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantDemon.id, name: Monsters.RevenantDemon.name, aliases: Monsters.RevenantDemon.aliases, - timeToFinish: Time.Second * 50, + timeToFinish: Time.Second * 82, table: Monsters.RevenantDemon, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 6, - pkBaseDeathChance: 5 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantDragon.id, name: Monsters.RevenantDragon.name, aliases: Monsters.RevenantDragon.aliases, - timeToFinish: Time.Second * 90, + timeToFinish: Time.Second * 147, table: Monsters.RevenantDragon, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 8, - pkBaseDeathChance: 7 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantGoblin.id, name: Monsters.RevenantGoblin.name, aliases: Monsters.RevenantGoblin.aliases, - timeToFinish: Time.Second * 25, + timeToFinish: Time.Second * 41, table: Monsters.RevenantGoblin, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 5, - pkBaseDeathChance: 5 + pkActivityRating: 8, + pkBaseDeathChance: 8, + canBePked: true }, { id: Monsters.RevenantHellhound.id, name: Monsters.RevenantHellhound.name, aliases: Monsters.RevenantHellhound.aliases, - timeToFinish: Time.Second * 55, + timeToFinish: Time.Second * 90, table: Monsters.RevenantHellhound, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 6, - pkBaseDeathChance: 5 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantHobgoblin.id, name: Monsters.RevenantHobgoblin.name, aliases: Monsters.RevenantHobgoblin.aliases, - timeToFinish: Time.Second * 45, + timeToFinish: Time.Second * 74, table: Monsters.RevenantHobgoblin, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 5, - pkBaseDeathChance: 5 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantImp.id, name: Monsters.RevenantImp.name, aliases: Monsters.RevenantImp.aliases, - timeToFinish: Time.Second * 20, + timeToFinish: Time.Second * 33, table: Monsters.RevenantImp, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 4, - pkBaseDeathChance: 3 + pkActivityRating: 8, + pkBaseDeathChance: 8, + canBePked: true }, { id: Monsters.RevenantKnight.id, name: Monsters.RevenantKnight.name, aliases: Monsters.RevenantKnight.aliases, - timeToFinish: Time.Second * 75, + timeToFinish: Time.Second * 123, table: Monsters.RevenantKnight, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 8, - pkBaseDeathChance: 6 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantOrk.id, name: Monsters.RevenantOrk.name, aliases: Monsters.RevenantOrk.aliases, - timeToFinish: Time.Second * 65, + timeToFinish: Time.Second * 106, table: Monsters.RevenantOrk, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 7, - pkBaseDeathChance: 6 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true }, { id: Monsters.RevenantPyrefiend.id, name: Monsters.RevenantPyrefiend.name, aliases: Monsters.RevenantPyrefiend.aliases, - timeToFinish: Time.Second * 40, + timeToFinish: Time.Second * 65, table: Monsters.RevenantPyrefiend, wildy: true, difficultyRating: 9, qpRequired: 0, - pkActivityRating: 7, - pkBaseDeathChance: 5 + pkActivityRating: 9, + pkBaseDeathChance: 8, + itemCost: { + itemCost: new Bank().add('Blighted super restore (4)', 1), + qtyPerMinute: 0.17, + alternativeConsumables: [{ itemCost: new Bank().add('Prayer potion (4)', 1), qtyPerMinute: 0.17 }] + }, + canBePked: true } ]; diff --git a/src/lib/types/minions.ts b/src/lib/types/minions.ts index 2119d22897..d7f823fa16 100644 --- a/src/lib/types/minions.ts +++ b/src/lib/types/minions.ts @@ -129,16 +129,6 @@ export interface MonsterActivityTaskOptions extends ActivityTaskOptions { hasWildySupplies?: boolean; } -export interface RevenantOptions extends ActivityTaskOptions { - type: 'Revenants'; - monsterID: number; - quantity: number; - died: boolean; - fakeDuration: number; - usingPrayerPots: boolean; - skulled: boolean; - style: 'melee' | 'range' | 'mage'; -} export interface ClueActivityTaskOptions extends ActivityTaskOptions { type: 'ClueCompletion'; @@ -574,7 +564,6 @@ export type ActivityTaskData = | MiningActivityTaskOptions | MotherlodeMiningActivityTaskOptions | PlunderActivityTaskOptions - | RevenantOptions | SmithingActivityTaskOptions | SmeltingActivityTaskOptions | TiaraRunecraftActivityTaskOptions diff --git a/src/lib/util/minionStatus.ts b/src/lib/util/minionStatus.ts index 801cfa3b74..f053b9f2e1 100644 --- a/src/lib/util/minionStatus.ts +++ b/src/lib/util/minionStatus.ts @@ -1,6 +1,5 @@ import { toTitleCase } from '@oldschoolgg/toolkit'; import { increaseNumByPercent, reduceNumByPercent } from 'e'; -import { Monsters } from 'oldschooljs'; import { SkillsEnum } from 'oldschooljs/dist/constants'; import { collectables } from '../../mahoji/lib/abstracted_commands/collectCommand'; @@ -64,7 +63,6 @@ import { PickpocketActivityTaskOptions, PlunderActivityTaskOptions, RaidsOptions, - RevenantOptions, RunecraftActivityTaskOptions, SawmillActivityTaskOptions, ScatteringActivityTaskOptions, @@ -545,13 +543,6 @@ export function minionStatus(user: MUser) { case 'Trekking': { return `${name} is currently Temple Trekking. ${formattedDuration}`; } - case 'Revenants': { - const data = currentTask as RevenantOptions; - const durationRemaining = data.finishDate - data.duration + data.fakeDuration - Date.now(); - return `${data.skulled ? `${Emoji.OSRSSkull} ` : ''} ${name} is currently killing ${data.quantity}x ${ - Monsters.get(data.monsterID)!.name - } in the wilderness. If they don't die, the trip should take ${formatDuration(durationRemaining)}.`; - } case 'PestControl': { const data = currentTask as MinigameActivityTaskOptionsWithNoChanges; return `${name} is currently doing ${data.quantity} games of Pest Control. ${formattedDuration}`; diff --git a/src/lib/util/repeatStoredTrip.ts b/src/lib/util/repeatStoredTrip.ts index 452e7491a9..5387f1b1eb 100644 --- a/src/lib/util/repeatStoredTrip.ts +++ b/src/lib/util/repeatStoredTrip.ts @@ -44,7 +44,6 @@ import { PickpocketActivityTaskOptions, PuroPuroActivityTaskOptions, RaidsOptions, - RevenantOptions, RunecraftActivityTaskOptions, SawmillActivityTaskOptions, ScatteringActivityTaskOptions, @@ -451,12 +450,6 @@ export const tripHandlers = { } }) }, - [activity_type_enum.Revenants]: { - commandName: 'k', - args: (data: RevenantOptions) => ({ - name: autocompleteMonsters.find(i => i.id === data.monsterID)?.name ?? data.monsterID.toString() - }) - }, [activity_type_enum.RoguesDenMaze]: { commandName: 'minigames', args: () => ({ diff --git a/src/mahoji/lib/abstracted_commands/minionKill.ts b/src/mahoji/lib/abstracted_commands/minionKill.ts index 7f7db986f3..d0a5675661 100644 --- a/src/mahoji/lib/abstracted_commands/minionKill.ts +++ b/src/mahoji/lib/abstracted_commands/minionKill.ts @@ -38,7 +38,12 @@ import { } from '../../../lib/minions/data/combatConstants'; import { revenantMonsters } from '../../../lib/minions/data/killableMonsters/revs'; import { Favours, gotFavour } from '../../../lib/minions/data/kourendFavour'; -import { AttackStyles, calculateMonsterFood, resolveAttackStyles } from '../../../lib/minions/functions'; +import { + AttackStyles, + calculateMonsterFood, + convertAttackStylesToSetup, + resolveAttackStyles +} from '../../../lib/minions/functions'; import reducedTimeFromKC from '../../../lib/minions/functions/reducedTimeFromKC'; import removeFoodFromUser from '../../../lib/minions/functions/removeFoodFromUser'; import { Consumable } from '../../../lib/minions/types'; @@ -46,6 +51,7 @@ import { calcPOHBoosts } from '../../../lib/poh'; import { SkillsEnum } from '../../../lib/skilling/types'; import { SlayerTaskUnlocksEnum } from '../../../lib/slayer/slayerUnlocks'; import { determineBoostChoice, getUsersCurrentSlayerInfo } from '../../../lib/slayer/slayerUtil'; +import { maxOffenceStats } from '../../../lib/structures/Gear'; import { Peak } from '../../../lib/tickers'; import { MonsterActivityTaskOptions } from '../../../lib/types/minions'; import { @@ -68,6 +74,7 @@ import { calcMaxTripLength } from '../../../lib/util/calcMaxTripLength'; import { calcWildyPKChance, increaseWildEvasionXp } from '../../../lib/util/calcWildyPkChance'; import { generateChart } from '../../../lib/util/chart'; import findMonster from '../../../lib/util/findMonster'; +import getOSItem from '../../../lib/util/getOSItem'; import { handleMahojiConfirmation } from '../../../lib/util/handleMahojiConfirmation'; import { updateBankSetting } from '../../../lib/util/updateBankSetting'; import { hasMonsterRequirements, resolveAvailableItemBoosts } from '../../mahojiSettings'; @@ -75,13 +82,18 @@ import { nexCommand } from './nexCommand'; import { nightmareCommand } from './nightmareCommand'; import { getPOH } from './pohCommand'; import { quests } from './questCommand'; -import { revsCommand } from './revsCommand'; import { temporossCommand } from './temporossCommand'; import { wintertodtCommand } from './wintertodtCommand'; import { zalcanoCommand } from './zalcanoCommand'; const invalidMonsterMsg = "That isn't a valid monster.\n\nFor example, `/k name:zulrah quantity:5`"; +const revSpecialWeapons = { + melee: getOSItem("Viggora's chainmace"), + range: getOSItem("Craw's bow"), + mage: getOSItem("Thammaron's sceptre") +} as const; + function formatMissingItems(consumables: Consumable[], timeToFinish: number) { const str = []; @@ -126,6 +138,9 @@ export async function minionKillCommand( return 'Your minion is busy.'; } const { minionName } = user; + const wildyGear = user.gear.wildy; + const style = convertAttackStylesToSetup(user.user.attack_style); + const key = ({ melee: 'attack_crush', mage: 'attack_magic', range: 'attack_ranged' } as const)[style]; const boosts = []; let messages: string[] = []; @@ -138,11 +153,17 @@ export async function minionKillCommand( if (name.toLowerCase().includes('nightmare')) return nightmareCommand(user, channelID, name); if (name.toLowerCase().includes('wintertodt')) return wintertodtCommand(user, channelID); - if (revenantMonsters.some(i => i.aliases.some(a => stringMatches(a, name)))) { - return revsCommand(user, channelID, interaction, name); + let monster = findMonster(name); + let revenants = false; + + const matchedRevenantMonster = revenantMonsters.find(monster => + monster.aliases.some(alias => stringMatches(alias, name)) + ); + if (matchedRevenantMonster) { + monster = matchedRevenantMonster; + revenants = true; } - const monster = findMonster(name); if (!monster) return invalidMonsterMsg; const usersTask = await getUsersCurrentSlayerInfo(user.id); @@ -155,6 +176,20 @@ export async function minionKillCommand( return `You can't kill ${monster.name}, because you're not on a slayer task.`; } + const wildyGearStat = wildyGear.getStats()[key]; + const revGearPercent = Math.max(0, calcWhatPercent(wildyGearStat, maxOffenceStats[key])); + + if (revenants) { + const weapon = wildyGear.equippedWeapon(); + if (!weapon) { + return 'You have no weapon equipped in your Wildy outfit.'; + } + + if (weapon.equipment![key] < 10) { + return `Your weapon is terrible, you can't kill Revenants. You should have ${style} gear equipped in your wildy outfit, as this is what you're currently training. You can change this using \`/minion train\``; + } + } + // Set chosen boost based on priority: const myCBOpts = user.combatOptions; const boostChoice = determineBoostChoice({ @@ -210,21 +245,6 @@ export async function minionKillCommand( const monsterHP = osjsMon?.data.hitpoints ?? 100; - // Removed vorkath because he has a special boost. - if (monster.name.toLowerCase() !== 'vorkath' && osjsMon?.data?.attributes?.includes(MonsterAttribute.Dragon)) { - if ( - user.hasEquippedOrInBank('Dragon hunter lance') && - !attackStyles.includes(SkillsEnum.Ranged) && - !attackStyles.includes(SkillsEnum.Magic) - ) { - timeToFinish = reduceNumByPercent(timeToFinish, 15); - boosts.push('15% for Dragon hunter lance'); - } else if (user.hasEquippedOrInBank('Dragon hunter crossbow') && attackStyles.includes(SkillsEnum.Ranged)) { - timeToFinish = reduceNumByPercent(timeToFinish, 15); - boosts.push('15% for Dragon hunter crossbow'); - } - } - // Black mask and salve don't stack. const oneSixthBoost = 16.67; let blackMaskBoost = 0; @@ -232,31 +252,90 @@ export async function minionKillCommand( let salveAmuletBoost = 0; let salveAmuletBoostMsg = ''; - // Calculate Slayer helmet boost on task if they have black mask or similar - if (attackStyles.includes(SkillsEnum.Ranged) || attackStyles.includes(SkillsEnum.Magic)) { - if (isOnTask && user.hasEquippedOrInBank('Black mask (i)')) { + const dragonBoost = 15; // Common boost percentage for dragon-related gear + + const isUndead = osjsMon?.data?.attributes?.includes(MonsterAttribute.Undead); + const isDragon = osjsMon?.data?.attributes?.includes(MonsterAttribute.Dragon); + + function applyDragonBoost() { + const hasDragonLance = monster?.canBePked + ? wildyGear.hasEquipped('Dragon hunter lance') + : user.hasEquippedOrInBank('Dragon hunter lance'); + const hasDragonCrossbow = monster?.canBePked + ? wildyGear.hasEquipped('Dragon hunter crossbow') + : user.hasEquippedOrInBank('Dragon hunter crossbow'); + + if ( + (hasDragonLance && !attackStyles.includes(SkillsEnum.Ranged) && !attackStyles.includes(SkillsEnum.Magic)) || + (hasDragonCrossbow && attackStyles.includes(SkillsEnum.Ranged)) + ) { + const boostMessage = hasDragonLance ? '15% for Dragon hunter lance' : '15% for Dragon hunter crossbow'; + timeToFinish = reduceNumByPercent(timeToFinish, dragonBoost); + boosts.push(boostMessage); + } + } + + function applyBlackMaskBoost() { + const hasBlackMask = monster?.canBePked + ? wildyGear.hasEquipped('Black mask') + : user.hasEquippedOrInBank('Black mask'); + const hasBlackMaskI = isOnTask + ? wildyGear.hasEquipped('Black mask (i)') + : user.hasEquippedOrInBank('Black mask (i)'); + + if (attackStyles.includes(SkillsEnum.Ranged) || attackStyles.includes(SkillsEnum.Magic)) { + if (hasBlackMaskI) { + blackMaskBoost = oneSixthBoost; + blackMaskBoostMsg = `${blackMaskBoost}% for Black mask (i) on non-melee task`; + } + } else if (hasBlackMask) { blackMaskBoost = oneSixthBoost; - blackMaskBoostMsg = `${blackMaskBoost}% for Black mask (i) on non-melee task`; + blackMaskBoostMsg = `${blackMaskBoost}% for Black mask on melee task`; } - } else if (isOnTask && user.hasEquippedOrInBank('Black mask')) { - blackMaskBoost = oneSixthBoost; - blackMaskBoostMsg = `${blackMaskBoost}% for Black mask on melee task`; - } - - // Calculate Salve amulet boost on task if the monster is undead or similar - const undeadMonster = osjsMon?.data?.attributes?.includes(MonsterAttribute.Undead); - if (undeadMonster && (attackStyles.includes(SkillsEnum.Ranged) || attackStyles.includes(SkillsEnum.Magic))) { - if (user.hasEquippedOrInBank('Salve amulet(i)')) { - const enhancedBoost = user.hasEquippedOrInBank('Salve amulet(ei)'); - salveAmuletBoost = enhancedBoost ? 20 : oneSixthBoost; - salveAmuletBoostMsg = `${salveAmuletBoost}% for Salve amulet${ - enhancedBoost ? '(ei)' : '(i)' - } on non-melee task`; + } + + function calculateSalveAmuletBoost() { + let salveBoost = false; + let salveEnhanced = false; + const style = attackStyles[0]; + if (style === 'ranged' || style === 'magic') { + salveBoost = monster?.canBePked + ? wildyGear.hasEquipped('Salve amulet(i)') + : user.hasEquippedOrInBank('Salve amulet (i)'); + salveEnhanced = monster?.canBePked + ? wildyGear.hasEquipped('Salve amulet(ei)') + : user.hasEquippedOrInBank('Salve amulet (ei)'); + if (salveBoost) { + salveAmuletBoost = salveEnhanced ? 20 : oneSixthBoost; + salveAmuletBoostMsg = `${salveAmuletBoost}% for Salve amulet${ + salveEnhanced ? '(ei)' : '(i)' + } on non-melee task`; + } + } else { + salveBoost = monster?.canBePked + ? wildyGear.hasEquipped('Salve amulet') + : user.hasEquippedOrInBank('Salve amulet'); + salveEnhanced = monster?.canBePked + ? wildyGear.hasEquipped('Salve amulet (e)') + : user.hasEquippedOrInBank('Salve amulet (e)'); + if (salveBoost) { + salveAmuletBoost = salveEnhanced ? 20 : oneSixthBoost; + salveAmuletBoostMsg = `${salveAmuletBoost}% for Salve amulet${ + salveEnhanced ? ' (e)' : '' + } on melee task`; + } } - } else if (undeadMonster && user.hasEquippedOrInBank('Salve amulet')) { - const enhancedBoost = user.hasEquippedOrInBank('Salve amulet(e)'); - salveAmuletBoost = enhancedBoost ? 20 : oneSixthBoost; - salveAmuletBoostMsg = `${salveAmuletBoost}% for Salve amulet${enhancedBoost ? ' (e)' : ''} on melee task`; + } + if (isDragon && monster.name.toLowerCase() !== 'vorkath') { + applyDragonBoost(); + } + + if (isOnTask) { + applyBlackMaskBoost(); + } + + if (isUndead) { + calculateSalveAmuletBoost(); } // Only choose greater boost: @@ -270,6 +349,17 @@ export async function minionKillCommand( } } + if (revenants) { + timeToFinish = reduceNumByPercent(timeToFinish, revGearPercent / 4); + boosts.push(`${(revGearPercent / 4).toFixed(2)}% (out of a possible 25%) for ${key}`); + + const specialWeapon = revSpecialWeapons[style]; + if (wildyGear.hasEquipped(specialWeapon.name)) { + timeToFinish = reduceNumByPercent(timeToFinish, 35); + boosts.push(`${35}% for ${specialWeapon.name}`); + } + } + // Initialize consumable costs before any are calculated. const consumableCosts: Consumable[] = []; diff --git a/src/mahoji/lib/abstracted_commands/revsCommand.ts b/src/mahoji/lib/abstracted_commands/revsCommand.ts deleted file mode 100644 index fd918057b2..0000000000 --- a/src/mahoji/lib/abstracted_commands/revsCommand.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { ChatInputCommandInteraction } from 'discord.js'; -import { calcWhatPercent, randInt, reduceNumByPercent, Time } from 'e'; -import { CommandResponse } from 'mahoji/dist/lib/structures/ICommand'; -import { Bank } from 'oldschooljs'; - -import { Emoji } from '../../../lib/constants'; -import { trackLoot } from '../../../lib/lootTrack'; -import { revenantMonsters } from '../../../lib/minions/data/killableMonsters/revs'; -import { convertAttackStylesToSetup } from '../../../lib/minions/functions'; -import { SkillsEnum } from '../../../lib/skilling/types'; -import { maxDefenceStats, maxOffenceStats } from '../../../lib/structures/Gear'; -import { RevenantOptions } from '../../../lib/types/minions'; -import { formatDuration, percentChance, stringMatches } from '../../../lib/util'; -import addSubTaskToActivityTask from '../../../lib/util/addSubTaskToActivityTask'; -import { calcMaxTripLength } from '../../../lib/util/calcMaxTripLength'; -import { getWildEvasionPercent, increaseWildEvasionXp } from '../../../lib/util/calcWildyPkChance'; -import getOSItem from '../../../lib/util/getOSItem'; -import { handleMahojiConfirmation } from '../../../lib/util/handleMahojiConfirmation'; -import { updateBankSetting } from '../../../lib/util/updateBankSetting'; - -const specialWeapons = { - melee: getOSItem("Viggora's chainmace"), - range: getOSItem("Craw's bow"), - mage: getOSItem("Thammaron's sceptre") -} as const; - -export async function revsCommand( - user: MUser, - channelID: string, - interaction: ChatInputCommandInteraction | null, - name: string -): CommandResponse { - const style = convertAttackStylesToSetup(user.user.attack_style); - const userGear = user.gear.wildy; - - const boosts = []; - const monster = revenantMonsters.find( - m => - stringMatches(m.name, name) || - m.aliases.some(a => stringMatches(a, name)) || - m.name.split(' ').some(a => stringMatches(a, name)) - ); - if (!monster || !name) { - return `That's not a valid Revenant. The valid Revenants are: ${revenantMonsters.map(m => m.name).join(', ')}.`; - } - - const key = ({ melee: 'attack_crush', mage: 'attack_magic', range: 'attack_ranged' } as const)[style]; - const gearStat = userGear.getStats()[key]; - const gearPercent = Math.max(0, calcWhatPercent(gearStat, maxOffenceStats[key])); - - const weapon = userGear.equippedWeapon(); - if (!weapon) { - return 'You have no weapon equipped in your Wildy outfit.'; - } - - if (weapon.equipment![key] < 10) { - return `Your weapon is terrible, you can't kill Revenants. You should have ${style} gear equipped in your wildy outfit, as this is what you're currently training. You can change this using \`/minion train\``; - } - - let timePerMonster = monster.timeToFinish; - timePerMonster = reduceNumByPercent(timePerMonster, gearPercent / 4); - boosts.push(`${(gearPercent / 4).toFixed(2)}% (out of a possible 25%) for ${key}`); - - const specialWeapon = specialWeapons[style]; - if (userGear.hasEquipped(specialWeapon.name)) { - timePerMonster = reduceNumByPercent(timePerMonster, 35); - boosts.push(`${35}% for ${specialWeapon.name}`); - } - - const quantity = Math.floor(calcMaxTripLength(user, 'Revenants') / timePerMonster); - let duration = quantity * timePerMonster; - - const cost = new Bank(); - - let hasPrayerPots = true; - if (user.bank.amount('Prayer potion(4)') < 5) { - hasPrayerPots = false; - if (interaction) { - await handleMahojiConfirmation( - interaction, - 'Are you sure you want to kill revenants without prayer potions? You should bring at least 5 Prayer potion(4).' - ); - } - } else { - cost.add('Prayer potion(4)', 5); - } - - updateBankSetting('economyStats_PVMCost', cost); - await transactItems({ userID: user.id, itemsToRemove: cost }); - if (cost.length > 0) { - await trackLoot({ - id: monster.name, - totalCost: cost, - type: 'Monster', - changeType: 'cost', - users: [ - { - id: user.id, - cost - } - ] - }); - } - - let deathChance = 5; - let defLvl = user.skillLevel(SkillsEnum.Defence); - let deathChanceFromDefenceLevel = (100 - (defLvl === 99 ? 100 : defLvl)) / 4; - deathChance += deathChanceFromDefenceLevel; - - const defensiveGearPercent = Math.max( - 0, - calcWhatPercent(userGear.getStats().defence_magic, maxDefenceStats['defence_magic']) - ); - let deathChanceFromGear = Math.max(20, 100 - defensiveGearPercent) / 4; - deathChance += deathChanceFromGear; - - const evasionDeathReduction = await getWildEvasionPercent(user); - deathChance = reduceNumByPercent(deathChance, evasionDeathReduction); - - const died = percentChance(deathChance); - - await increaseWildEvasionXp(user, duration); - - await addSubTaskToActivityTask({ - monsterID: monster.id, - userID: user.id, - channelID: channelID.toString(), - quantity, - fakeDuration: duration, - duration: died ? randInt(Math.min(Time.Minute * 3, duration), duration) : duration, - type: 'Revenants', - died, - skulled: true, - style, - usingPrayerPots: hasPrayerPots - }); - - let response = `${user.minionName} is now killing ${quantity}x ${monster.name}, it'll take around ${formatDuration( - duration - )} to finish. -${Emoji.OSRSSkull} Skulled -**Death Chance:** ${deathChance.toFixed(2)}% (${deathChanceFromGear.toFixed(2)}% from magic def${ - deathChanceFromDefenceLevel > 0 ? `, ${deathChanceFromDefenceLevel.toFixed(2)}% from defence level` : '' - } + 5% as default chance).${cost.length > 0 ? `\nRemoved from bank: ${cost}` : ''}${ - boosts.length > 0 ? `\nBoosts: ${boosts.join(', ')}` : '' - }`; - - return response; -} diff --git a/src/tasks/minions/monsterActivity.ts b/src/tasks/minions/monsterActivity.ts index 6ffe396072..487eb2409a 100644 --- a/src/tasks/minions/monsterActivity.ts +++ b/src/tasks/minions/monsterActivity.ts @@ -6,6 +6,7 @@ import { Emoji } from '../../lib/constants'; import { KourendKebosDiary, userhasDiaryTier } from '../../lib/diaries'; import { trackLoot } from '../../lib/lootTrack'; import killableMonsters from '../../lib/minions/data/killableMonsters'; +import { revenantMonsters } from '../../lib/minions/data/killableMonsters/revs'; import { addMonsterXP } from '../../lib/minions/functions'; import announceLoot from '../../lib/minions/functions/announceLoot'; import { prisma } from '../../lib/settings/prisma'; @@ -36,7 +37,18 @@ export const monsterTask: MinionTask = { pkEncounters, hasWildySupplies } = data; - const monster = killableMonsters.find(mon => mon.id === monsterID)!; + + let monster = killableMonsters.find(mon => mon.id === monsterID)!; + let revenants = false; + + const matchedRevenantMonster = revenantMonsters.find(mon => mon.id === monsterID)!; + if (matchedRevenantMonster) { + monster = matchedRevenantMonster; + revenants = true; + } + + let skulled = false; + if (revenants) skulled = true; const messages: string[] = []; @@ -77,7 +89,7 @@ export const monsterTask: MinionTask = { if (pkEncounters && pkEncounters > 0) { // Handle lost kc quantity because of pkers - const lostQuantity = Math.max( + let lostQuantity = Math.max( Math.round((quantity / (Math.round(duration / Time.Minute) * (died ? 1 : 2))) * pkEncounters), 1 ); @@ -85,7 +97,9 @@ export const monsterTask: MinionTask = { quantity -= lostQuantity; quantity = Math.max(0, quantity); messages.push( - `You missed out on ${lostQuantity}x kills because of pk encounters${died ? ' and death' : ''}` + `You missed out on ${Math.max(1, lostQuantity)}x kills because of pk encounters${ + died ? ' and death' : '' + }` ); } @@ -101,7 +115,7 @@ export const monsterTask: MinionTask = { smited: hasPrayerLevel && !protectItem, protectItem: hasPrayerLevel, after20wilderness: monster.pkBaseDeathChance && monster.pkBaseDeathChance >= 5 ? true : false, - skulled: false + skulled }); let reEquipedItems = false; diff --git a/src/tasks/minions/revenantsActivity.ts b/src/tasks/minions/revenantsActivity.ts deleted file mode 100644 index 0b7bb0f0dc..0000000000 --- a/src/tasks/minions/revenantsActivity.ts +++ /dev/null @@ -1,138 +0,0 @@ -import type { Prisma } from '@prisma/client'; -import { deepClone, roll } from 'e'; -import { Bank } from 'oldschooljs'; - -import { generateGearImage } from '../../lib/gear/functions/generateGearImage'; -import { trackLoot } from '../../lib/lootTrack'; -import { revenantMonsters } from '../../lib/minions/data/killableMonsters/revs'; -import announceLoot from '../../lib/minions/functions/announceLoot'; -import { SkillsEnum } from '../../lib/skilling/types'; -import { Gear } from '../../lib/structures/Gear'; -import type { RevenantOptions } from '../../lib/types/minions'; -import { hasSkillReqs } from '../../lib/util'; -import calculateGearLostOnDeathWilderness from '../../lib/util/calculateGearLostOnDeathWilderness'; -import { handleTripFinish } from '../../lib/util/handleTripFinish'; -import { makeBankImage } from '../../lib/util/makeBankImage'; -import { updateBankSetting } from '../../lib/util/updateBankSetting'; - -export const revenantsTask: MinionTask = { - type: 'Revenants', - async run(data: RevenantOptions) { - const { monsterID, userID, channelID, quantity, died, skulled, duration } = data; - const monster = revenantMonsters.find(mon => mon.id === monsterID)!; - const user = await mUserFetch(userID); - if (died) { - // 1 in 20 to get smited without prayer potions and 1 in 300 if the user has prayer potions - const hasPrayerLevel = hasSkillReqs(user, { [SkillsEnum.Prayer]: 25 })[0]; - const protectItem = roll(data.usingPrayerPots ? 300 : 20) ? false : hasPrayerLevel; - const userGear = { ...deepClone(user.gear.wildy.raw()) }; - - const calc = calculateGearLostOnDeathWilderness({ - gear: userGear, - smited: hasPrayerLevel && !protectItem, - protectItem: hasPrayerLevel, - after20wilderness: true, - skulled - }); - - const image = await generateGearImage(user, new Gear(calc.newGear), 'wildy', null); - await user.update({ - gear_wildy: calc.newGear as Prisma.InputJsonObject - }); - - updateBankSetting('revs_cost', calc.lostItems); - // Track items lost - await trackLoot({ - totalCost: calc.lostItems, - id: monster.name, - type: 'Monster', - changeType: 'cost', - users: [ - { - id: user.id, - cost: calc.lostItems - } - ] - }); - // Track loot (For duration) - await trackLoot({ - totalLoot: new Bank(), - id: monster.name, - type: 'Monster', - changeType: 'loot', - duration, - kc: quantity, - users: [ - { - id: user.id, - loot: new Bank(), - duration - } - ] - }); - - handleTripFinish( - user, - channelID, - `${user} ${ - hasPrayerLevel && !protectItem - ? `Oh no! While running for your life, you panicked, got smited ${ - skulled ? 'and lost everything!' : "and couldn't protect a 4th item." - }` - : '' - } You died, you lost all your loot, and these equipped items: ${ - calc.lostItems - }.\nHere is what you saved:`, - image, - data, - null - ); - return; - } - - const { newKC } = await user.incrementKC(monsterID, quantity); - - const loot = monster.table.kill(quantity, { skulled }); - let str = - `${user}, ${user.minionName} finished killing ${quantity} ${monster.name}.` + - ` Your ${monster.name} KC is now ${newKC}.\n`; - - announceLoot({ - user, - monsterID: monster.id, - loot, - notifyDrops: monster.notifyDrops - }); - - const { previousCL, itemsAdded } = await transactItems({ - userID: user.id, - itemsToAdd: loot, - collectionLog: true - }); - - await trackLoot({ - totalLoot: itemsAdded, - id: monster.name, - type: 'Monster', - changeType: 'loot', - duration, - kc: quantity, - users: [ - { - id: user.id, - loot: itemsAdded, - duration - } - ] - }); - - const image = await makeBankImage({ - bank: itemsAdded, - title: `Loot From ${quantity} ${monster.name} (${skulled ? 'skulled' : 'unskulled'}):`, - user, - previousCL - }); - - handleTripFinish(user, channelID, str, image.file.attachment, data, itemsAdded); - } -};