Skip to content

Commit

Permalink
Add Crystal Impling Hunting (#5771)
Browse files Browse the repository at this point in the history
  • Loading branch information
TastyPumPum authored Apr 25, 2024
1 parent 21b13c1 commit 882f61e
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 18 deletions.
26 changes: 24 additions & 2 deletions src/lib/skilling/functions/calcsHunter.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Time } from 'e';
import LootTable from 'oldschooljs/dist/structures/LootTable';

import { percentChance } from '../../util';
Expand All @@ -6,12 +7,33 @@ import { Creature } from '../types';
export function calcLootXPHunting(
currentLevel: number,
creature: Creature,
quantity: number
quantity: number,
usingStaminaPotion: boolean,
graceful: boolean,
experienceScore: number
): [number, number, number] {
let xpReceived = 0;
let successful = 0;

const chanceOfSuccess = creature.slope * currentLevel + creature.intercept;
let chanceOfSuccess = creature.slope * currentLevel + creature.intercept;

if (creature.name === 'Crystal impling') {
chanceOfSuccess = 20;
if (graceful) {
chanceOfSuccess *= 1.05;
}
if (usingStaminaPotion) {
chanceOfSuccess *= 1.2;
}

const timeInSeconds = creature.catchTime * Time.Second;
const experienceFactor = experienceScore / (Time.Hour / timeInSeconds);

const maxPercentIncrease = 10;
let percentIncrease = Math.min(Math.floor(experienceFactor), maxPercentIncrease);

chanceOfSuccess += chanceOfSuccess * (percentIncrease / 100);
}

for (let i = 0; i < quantity; i++) {
if (!percentChance(chanceOfSuccess)) {
Expand Down
12 changes: 12 additions & 0 deletions src/lib/skilling/skills/hunter/creatures/butterflyNetting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ const butterflyNettingCreatures: Creature[] = [
catchTime: 5,
slope: 1.35,
intercept: 35
},
{
name: 'Crystal impling',
id: 37,
aliases: ['cimp', 'crystal imp', 'c imp', 'crystal impling'],
level: 80,
hunterXP: 280,
table: new LootTable().every('Crystal impling jar'),
huntTechnique: HunterTechniqueEnum.ButterflyNetting,
catchTime: 180,
slope: 0,
intercept: 0
}
];

Expand Down
7 changes: 7 additions & 0 deletions src/lib/util/activityInArea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { soteSkillRequirements } from '../skilling/functions/questRequirements';
import {
ActivityTaskData,
AgilityActivityTaskOptions,
HunterActivityTaskOptions,
MonsterActivityTaskOptions,
PickpocketActivityTaskOptions,
WoodcuttingActivityTaskOptions
Expand Down Expand Up @@ -51,6 +52,12 @@ const WorldLocationsChecker = [
return true;
}
}
if (
activity.type === 'Hunter' &&
(activity as HunterActivityTaskOptions).creatureName === 'Crystal impling'
) {
return true;
}

return false;
}
Expand Down
37 changes: 30 additions & 7 deletions src/mahoji/commands/hunt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import { Bank } from 'oldschooljs';
import { HERBIBOAR_ID, RAZOR_KEBBIT_ID } from '../../lib/constants';
import { hasWildyHuntGearEquipped } from '../../lib/gear/functions/hasWildyHuntGearEquipped';
import { trackLoot } from '../../lib/lootTrack';
import { soteSkillRequirements } from '../../lib/skilling/functions/questRequirements';
import creatures from '../../lib/skilling/skills/hunter/creatures';
import Hunter from '../../lib/skilling/skills/hunter/hunter';
import { HunterTechniqueEnum, SkillsEnum } from '../../lib/skilling/types';
import { Peak } from '../../lib/tickers';
import { HunterActivityTaskOptions } from '../../lib/types/minions';
import { formatDuration, itemID } from '../../lib/util';
import { formatDuration, hasSkillReqs, itemID } from '../../lib/util';
import addSubTaskToActivityTask from '../../lib/util/addSubTaskToActivityTask';
import { calcMaxTripLength } from '../../lib/util/calcMaxTripLength';
import { updateBankSetting } from '../../lib/util/updateBankSetting';
Expand Down Expand Up @@ -118,6 +119,18 @@ export const huntCommand: OSBMahojiCommand = {
}
}

let crystalImpling = creature.name === 'Crystal impling';

if (crystalImpling) {
const [hasReqs, reason] = hasSkillReqs(user, soteSkillRequirements);
if (!hasReqs) {
return `To hunt ${creature.name}, you need: ${reason}.`;
}
if (user.QP < 150) {
return `To hunt ${creature.name}, you need 150 QP.`;
}
}

// Reduce time if user is experienced hunting the creature, every hour become 1% better to a cap of 10% or 20% if tracking technique.
let [percentReduced, catchTime] = [
Math.min(
Expand Down Expand Up @@ -158,10 +171,20 @@ export const huntCommand: OSBMahojiCommand = {
const maxTripLength = calcMaxTripLength(user, 'Hunter');

let { quantity } = options;
if (!quantity) quantity = Math.floor(maxTripLength / ((catchTime * Time.Second) / traps));
if (!quantity) {
if (crystalImpling) {
quantity = Math.floor(maxTripLength / Time.Minute);
} else {
quantity = Math.floor(maxTripLength / ((catchTime * Time.Second) / traps));
}
}

let duration = Math.floor(((quantity * catchTime) / traps) * Time.Second);

if (crystalImpling) {
duration = Math.floor(quantity * Time.Minute);
}

if (duration > maxTripLength) {
return `${user.minionName} can't go on trips longer than ${formatDuration(
maxTripLength
Expand All @@ -188,9 +211,9 @@ export const huntCommand: OSBMahojiCommand = {

// If creatures Herbiboar or Razor-backed kebbit use Stamina potion(4)
if (usingStaminaPotion) {
if (creature.id === HERBIBOAR_ID || creature.id === RAZOR_KEBBIT_ID) {
if (creature.id === HERBIBOAR_ID || creature.id === RAZOR_KEBBIT_ID || crystalImpling) {
let staminaPotionQuantity =
creature.id === HERBIBOAR_ID
creature.id === HERBIBOAR_ID || crystalImpling
? Math.round(duration / (9 * Time.Minute))
: Math.round(duration / (18 * Time.Minute));

Expand Down Expand Up @@ -256,9 +279,9 @@ export const huntCommand: OSBMahojiCommand = {
type: 'Hunter'
});

let response = `${user.minionName} is now ${creature.huntTechnique} ${quantity}x ${
creature.name
}, it'll take around ${formatDuration(duration)} to finish.`;
let response = `${user.minionName} is now ${crystalImpling ? 'hunting' : `${creature.huntTechnique}`} ${
crystalImpling ? '' : ` ${quantity}x `
}${creature.name}, it'll take around ${formatDuration(duration)} to finish.`;

if (boosts.length > 0) {
response += `\n\n**Boosts:** ${boosts.join(', ')}.`;
Expand Down
38 changes: 29 additions & 9 deletions src/tasks/minions/HunterActivity/hunterActivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { roll, skillingPetDropRate, stringMatches } from '../../../lib/util';
import { handleTripFinish } from '../../../lib/util/handleTripFinish';
import itemID from '../../../lib/util/itemID';
import { updateBankSetting } from '../../../lib/util/updateBankSetting';
import { userHasGracefulEquipped } from '../../../mahoji/mahojiSettings';
import { BLACK_CHIN_ID, HERBIBOAR_ID } from './../../../lib/constants';

const riskDeathNumbers = [
Expand All @@ -34,7 +35,8 @@ const riskDeathNumbers = [
export const hunterTask: MinionTask = {
type: 'Hunter',
async run(data: HunterActivityTaskOptions) {
const { creatureName, quantity, userID, channelID, usingHuntPotion, wildyPeak, duration } = data;
const { creatureName, quantity, userID, channelID, usingHuntPotion, wildyPeak, duration, usingStaminaPotion } =
data;
const user = await mUserFetch(userID);
const userBank = user.bank;
const currentLevel = user.skillLevel(SkillsEnum.Hunter);
Expand All @@ -53,12 +55,29 @@ export const hunterTask: MinionTask = {

if (!creature) return;

let crystalImpling = creature.name === 'Crystal impling';

let graceful = false;
if (userHasGracefulEquipped(user)) {
graceful = true;
}

const experienceScore = await user.getCreatureScore(creature.id);

let [successfulQuantity, xpReceived] = calcLootXPHunting(
Math.min(Math.floor(currentLevel + (usingHuntPotion ? 2 : 0)), MAX_LEVEL),
creature,
quantity
quantity,
usingStaminaPotion,
graceful,
experienceScore
);

if (crystalImpling) {
// Limit it to a max of 22 crystal implings per hour
successfulQuantity = Math.min(successfulQuantity, Math.round((21 / 60) * duration) + 1);
}

if (creature.wildy) {
let riskPkChance = creature.id === BLACK_CHIN_ID ? 100 : 200;
riskPkChance +=
Expand Down Expand Up @@ -136,6 +155,7 @@ export const hunterTask: MinionTask = {
});
}
}

const loot = new Bank();
for (let i = 0; i < successfulQuantity - pkedQuantity; i++) {
loot.add(creatureTable.roll());
Expand All @@ -156,13 +176,13 @@ export const hunterTask: MinionTask = {
duration
});

let str = `${user}, ${user.minionName} finished hunting ${
creature.name
} ${quantity}x times, due to clever creatures you missed out on ${
quantity - successfulQuantity
}x catches. ${xpStr}`;

str += `\n\nYou received: ${loot}.${magicSecStr.length > 1 ? magicSecStr : ''}`;
let str = `${user}, ${user.minionName} finished hunting ${creature.name}${
crystalImpling
? '.'
: `${quantity}x times, due to clever creatures you missed out on ${
quantity - successfulQuantity
}x catches. `
}${xpStr}\n\nYou received: ${loot}.${magicSecStr.length > 1 ? magicSecStr : ''}`;

if (gotPked && !died) {
str += `\n${pkStr}`;
Expand Down

0 comments on commit 882f61e

Please sign in to comment.