Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

warn on empty blowpipe import #396

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
"fmt": "next lint --fix",
"analyse": "ANALYSE=true next build",
"test": "jest",
"cdn-docker": "yarn build-docker-scraper && docker run --rm -it -v $(pwd)/cdn:/srv/cdn -v $(pwd)/src/lib/EquipmentAliases.ts:/srv/src/lib/EquipmentAliases.ts weirdgloop/osrs-dps-calc:scraper",
"cdn-docker-base": "docker run --rm -it -v $(pwd)/scripts:/srv/scripts -v $(pwd)/cdn:/srv/cdn -v $(pwd)/src/lib/EquipmentAliases.ts:/srv/src/lib/EquipmentAliases.ts weirdgloop/osrs-dps-calc:scraper",
"cdn-docker": "yarn build-docker-scraper && yarn cdn-docker-base",
"cdn-docker-aliases": "yarn cdn-docker-base python generateEquipmentAliases.py",
"cdn-docker-equipment": "yarn cdn-docker-base python generateEquipment.py",
"cdn-docker-monsters": "yarn cdn-docker-base python generateMonsters.py",
"cdn-dispatch": "gh workflow run regenerate.yml"
},
"dependencies": {
Expand Down
25 changes: 24 additions & 1 deletion src/app/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import type { NextPage } from 'next';
import MonsterContainer from '@/app/components/monster/MonsterContainer';
import { Tooltip } from 'react-tooltip';
import React, { Suspense, useEffect } from 'react';
import React, { Suspense, useEffect, useMemo } from 'react';
import { observer } from 'mobx-react-lite';
import { useStore } from '@/state';
import { ToastContainer } from 'react-toastify';
Expand All @@ -18,6 +18,11 @@ import DebugPanels from '@/app/components/results/DebugPanels';
import { IconAlertTriangle } from '@tabler/icons-react';
import NPCVersusPlayerResultsContainer from '@/app/components/results/NPCVersusPlayerResultsContainer';
import { CalcProvider, useCalc } from '@/worker/CalcWorker';
import UserIssueType from '@/enums/UserIssueType';

const GLOBAL_ISSUE_TYPES: UserIssueType[] = [
UserIssueType.IMPORT_MISSING_DATA,
];

const Home: NextPage = observer(() => {
const calc = useCalc();
Expand Down Expand Up @@ -91,6 +96,23 @@ const Home: NextPage = observer(() => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const globalIssues = useMemo(() => {
const issues = store.userIssues.filter((is) => GLOBAL_ISSUE_TYPES.includes(is.type));
return (
<>
{issues.map((is) => (
<div
key={`${is.loadout || 'global'}/${is.message}`}
className="w-full bg-orange-500 text-white px-4 py-1 text-sm border-b border-orange-400 flex items-center gap-1"
>
<IconAlertTriangle className="text-orange-200" />
{`${is.loadout ? `Loadout ${is.loadout}: ` : ''}${is.message}`}
</div>
))}
</>
);
}, [store.userIssues]);

return (
<div>
{store.prefs.manualMode && (
Expand All @@ -103,6 +125,7 @@ const Home: NextPage = observer(() => {
Manual mode is enabled! Some things may not function correctly. Click here to disable it.
</button>
)}
{globalIssues}
<Suspense>
<InitialLoad />
</Suspense>
Expand Down
2 changes: 2 additions & 0 deletions src/enums/UserIssueType.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
enum UserIssueType {
EQUIPMENT_MISSING_AMMO = 'equipment_slot_ammo_missing',
EQUIPMENT_WRONG_AMMO = 'equipment_slot_ammo_wrong',
EQUIPMENT_WEAPON_EMPTY = 'equipment_slot_weapon_empty',
EQUIPMENT_SET_EFFECT_UNSUPPORTED = 'equipment_slot_body_unsupported_set_effect',
SPELL_WRONG_WEAPON = 'spell_wrong_weapon',
SPELL_WRONG_MONSTER = 'spell_wrong_monster',
MONSTER_UNIQUE_EFFECTS = 'monster_overall_unique_effects',
IMPORT_MISSING_DATA = 'runelite_import_missing_data',
}

export default UserIssueType;
39 changes: 31 additions & 8 deletions src/lib/BaseCalc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { EquipmentPiece, Player } from '@/types/Player';
import { Monster } from '@/types/Monster';
import { AmmoApplicability, ammoApplicability, getCanonicalEquipment } from '@/lib/Equipment';
import {
AmmoApplicability,
ammoApplicability,
EMPTY_BLOWPIPE,
getCanonicalEquipment,
} from '@/lib/Equipment';
import UserIssueType from '@/enums/UserIssueType';
import { MonsterAttribute } from '@/enums/MonsterAttribute';
import { CAST_STANCES } from '@/lib/constants';
Expand Down Expand Up @@ -58,6 +63,8 @@ export default class BaseCalc {

userIssues: UserIssue[] = [];

protected fatal: boolean = false;

constructor(player: Player, monster: Monster, opts: CalcOpts = {}) {
this.opts = {
...DEFAULT_OPTS,
Expand Down Expand Up @@ -532,8 +539,14 @@ export default class BaseCalc {
]);
}

protected addIssue(type: UserIssueType, message: string) {
this.userIssues.push({ type, message, loadout: this.opts.loadoutName });
protected addIssue(type: UserIssueType, message: string, severity: UserIssue['severity'] = 'warn') {
this.userIssues.push({
type,
severity,
message,
loadout: this.opts.loadoutName,
});
this.fatal ||= severity === 'fatal';
}

private sanitizeInputs() {
Expand All @@ -558,11 +571,12 @@ export default class BaseCalc {
};
}

if (this.player.style.stance !== 'Manual Cast' && ammoApplicability(eq.weapon?.id, eq.ammo?.id) === AmmoApplicability.INVALID) {
if (ammoApplicability(eq.weapon?.id, eq.ammo?.id) === AmmoApplicability.INVALID) {
const severity = this.player.style.stance === 'Manual Cast' ? 'warn' : 'fatal';
if (eq.ammo?.name) {
this.addIssue(UserIssueType.EQUIPMENT_WRONG_AMMO, 'This ammo does not work with your current weapon.');
this.addIssue(UserIssueType.EQUIPMENT_WRONG_AMMO, 'This ammo does not work with your current weapon.', severity);
} else {
this.addIssue(UserIssueType.EQUIPMENT_MISSING_AMMO, 'Your weapon requires ammo to use.');
this.addIssue(UserIssueType.EQUIPMENT_MISSING_AMMO, 'Your weapon requires ammo to use.', severity);
}
}

Expand All @@ -579,7 +593,7 @@ export default class BaseCalc {
...this.player,
spell: null,
};
this.addIssue(UserIssueType.SPELL_WRONG_WEAPON, 'This spell needs a specific weapon equipped to cast.');
this.addIssue(UserIssueType.SPELL_WRONG_WEAPON, 'This spell needs a specific weapon equipped to cast.', 'fatal');
}

// Certain spells can only be cast on specific monsters
Expand All @@ -591,7 +605,7 @@ export default class BaseCalc {
...this.player,
spell: null,
};
this.addIssue(UserIssueType.SPELL_WRONG_MONSTER, 'This spell cannot be cast on the selected monster.');
this.addIssue(UserIssueType.SPELL_WRONG_MONSTER, 'This spell cannot be cast on the selected monster.', 'fatal');
}

// Some set effects are currently not accounted for
Expand All @@ -601,5 +615,14 @@ export default class BaseCalc {
) {
this.addIssue(UserIssueType.EQUIPMENT_SET_EFFECT_UNSUPPORTED, 'The calculator currently does not account for your equipment set effect.');
}

if (this.wearing(['Toxic blowpipe', 'Blazing blowpipe'])) {
const severity = this.player.style.stance === 'Manual Cast' ? 'warn' : 'fatal';
if (eq.weapon?.version === 'Empty') {
this.addIssue(UserIssueType.EQUIPMENT_WEAPON_EMPTY, 'An empty weapon cannot be used.', severity);
} else if (eq.weapon?.bonuses?.ranged_str === EMPTY_BLOWPIPE?.bonuses?.ranged_str) {
this.addIssue(UserIssueType.IMPORT_MISSING_DATA, 'The import data did not specify darts for the blowpipe equipped', severity);
}
}
}
}
3 changes: 3 additions & 0 deletions src/lib/Equipment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export type EquipmentBonuses = Pick<Player, 'bonuses' | 'offensive' | 'defensive
* All available equipment that a player can equip.
*/
export const availableEquipment = equipment as EquipmentPiece[];
export const EMPTY_BLOWPIPE = availableEquipment.find(
(e) => e.name === 'Toxic blowpipe' && e.version === 'Charged',
);

export const noStatExceptions = [
'Castle wars bracelet',
Expand Down
12 changes: 6 additions & 6 deletions src/lib/PlayerVsNPCCalc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -707,12 +707,8 @@ export default class PlayerVsNPCCalc extends BaseCalc {
* Get the max hit for this loadout, which is based on the player's current combat style
*/
private getMaxHit(): MinMax {
if (this.player.style.stance !== 'Manual Cast') {
const weaponId = this.player.equipment.weapon?.id;
const ammoId = this.player.equipment.ammo?.id;
if (ammoApplicability(weaponId, ammoId) === AmmoApplicability.INVALID) {
return [0, 0];
}
if (this.fatal) {
return [0, 0];
}

const style = this.player.style.type;
Expand Down Expand Up @@ -818,6 +814,10 @@ export default class PlayerVsNPCCalc extends BaseCalc {
}

private getDistributionImpl(): AttackDistribution {
if (this.fatal) {
return new AttackDistribution([new HitDistribution([new WeightedHit(1.0, [new Hitsplat(0, false)])])]);
}

const mattrs = this.monster.attributes;
const acc = this.getHitChance();
const [min, max] = this.getMaxHit();
Expand Down
1 change: 1 addition & 0 deletions src/types/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DetailEntry } from '@/lib/CalcDetails';

export interface UserIssue {
type: UserIssueType;
severity: 'warn' | 'fatal';
message: string;
loadout?: string;
}
Expand Down
Loading