import { ModifierRange , PROPERTIES , RUNEWORDS , SET_ITEMS , SKILL_TABS , UNIQUE_ITEMS , } from "../../../game-data" ; import { Item } from "../types/Item" ; import { ItemQuality } from "../types/ItemQuality" ; import { getBase } from "../getBase" ; import { Modifier } from "../types/Modifier" ; function checkRange ( { prop , min , max , param } , modifiers , callback ) { const { stats } = PROPERTIES [ prop ] ; for ( const { stat , type } of stats ) { if ( type === "other" || ( type === "param" && ! param ) ) { let condition = ( mod ) => mod . stat === stat ; if ( prop === "skill" ) { condition = ( mod ) => "param" in mod && mod . param === param && mod . stat === stat ; } else if ( prop === "skilltab" ) { const skillTab = SKILL_TABS [ Number ( param ) ] ?. id ; condition = ( mod ) => "param" in mod && mod . param === skillTab && mod . stat === stat ; } const modifier = modifiers ?. find ( condition ) ; if ( ( prop === "dmg-min" || prop === "dmg-max" ) && typeof modifier === "undefined" ) { continue ; } if ( modifier ) { modifier . range = [ min ! , max ! ] ; } callback ( modifier ?. value ?? 0 , min ! , max ! ) ; } else if ( type === "all" ) { const modifier = modifiers ?. find ( ( mod ) => mod . stat === stat ) ; if ( modifier ) { modifier . range = [ min ! , max ! ] ; } } } } export function computePerfectionScore ( item ) { if ( ! item . modifiers ) return 0 ; let ranges ; let allModifiers = item . modifiers ; if ( item . runeword ) { ranges = RUNEWORDS [ item . runewordId ! ] . modifiers ; } else if ( item . quality === ItemQuality . UNIQUE ) { ranges = UNIQUE_ITEMS [ item . unique ! ] . modifiers ; } else if ( item . quality === ItemQuality . SET ) { ranges = [ ... SET_ITEMS [ item . unique ! ] . baseModifiers , ... SET_ITEMS [ item . unique ! ] . setModifiers . flat ( ) , ] ; allModifiers = [ ... item . modifiers , ... item . setItemModifiers ! . flat ( ) ] ; } else { throw new Error ( "Only uniques, sets and runewords have a perfection score." ) ; } ranges = ranges . filter ( ( { prop } ) => prop !== "bloody" ) ; const base = getBase ( item ) ; let score = 0 ; let nbProps = 0 ; function addProp ( value , min , max ) { if ( min === max ) { return ; } score = ( nbProps * score + ( value - min ) / ( max - min ) ) / ++ nbProps ; } for ( const range of ranges ) { if ( range . min === range . max ) { continue ; } if ( range . prop === "sock" ) { item . socketsRange = [ range . min ! , Math . min ( range . max ! , base . maxSockets ) ] ; addProp ( item . sockets ! , ... item . socketsRange ) ; continue ; } checkRange ( range , allModifiers , addProp ) ; } if ( ( item . quality === ItemQuality . UNIQUE || item . quality === ItemQuality . SET ) && "def" in base && ! ranges . some ( ( { prop } ) => prop === "ac%" ) ) { const defense = item . defense ?? 0 ; const bonus = item . ethereal ? 1.5 : 1 ; item . defenseRange = [ Math . floor ( base . def [ 0 ] * bonus ) , Math . floor ( base . def [ 1 ] * bonus ) , ] ; addProp ( defense , ... item . defenseRange ) ; } item . perfectionScore = nbProps === 0 ? 100 : Math . floor ( 100 * score ) ; }