@@ -578,36 +578,47 @@ class ChainSolver {
578578 if ( m . gemType ) {
579579 const gemData = typeof GEMS !== 'undefined' ? GEMS . find ( g => g . name === m . gemType ) : null ;
580580 let gemVal = gemData ?. value || 0 ;
581- // Find best gem processing
582- let bestProcessed = gemVal ;
581+
582+ // Chain gem processing in correct order:
583+ // 1. Single-input processors (gem_cutter: multiply 1.4x)
584+ // 2. Flat modifiers (polisher: +$10) — before percentages to maximize
585+ // 3. Same-type combines (prismatic: gem+gem combine 1.15x)
586+ // 4. QA (percent 1.2x) — last for max effect
587+
588+ // Step 1: Find and apply single-input gem processors (multiply/flat)
589+ let processed = gemVal ;
590+ const skipEff = new Set ( [ "chance" , "transport" , "split" , "overflow" , "filter" , "gate" , "duplicate" , "preserve" , "set" , "combine" ] ) ;
583591 for ( const [ procId , procM ] of this . registry . machines ) {
584592 if ( ! this . registry . isAvailable ( procId , this . config ) ) continue ;
585- if ( ! procM . inputs ) continue ;
586- const acceptsGem = procM . inputs . some ( inp =>
587- inp === "gem" || inp . split ( "|" ) . includes ( "gem" ) || inp === "any"
588- ) ;
589- if ( ! acceptsGem ) continue ;
590- const skipEff = new Set ( [ "chance" , "transport" , "split" , "overflow" , "filter" , "gate" , "duplicate" , "preserve" , "set" ] ) ;
593+ if ( ! procM . inputs || procM . inputs . length !== 1 ) continue ;
591594 if ( skipEff . has ( procM . effect ) ) continue ;
592- if ( procM . inputs . length > 1 ) {
593- const allGem = procM . inputs . every ( inp => inp === "gem" || inp . split ( "|" ) . includes ( "gem" ) ) ;
594- if ( ! allGem ) continue ;
595- }
596- let processed = gemVal ;
597- if ( procM . effect === "flat" ) processed += procM . value ;
598- else if ( procM . effect === "multiply" ) processed *= procM . value ;
599- else if ( procM . effect === "combine" ) {
600- processed = gemVal * procM . inputs . length * procM . value / procM . inputs . length ;
601- }
602- if ( processed > bestProcessed ) bestProcessed = processed ;
595+ const acceptsGem = procM . inputs . some ( inp => inp === "gem" || inp . split ( "|" ) . includes ( "gem" ) ) ;
596+ if ( ! acceptsGem ) continue ;
597+ if ( procM . effect === "multiply" ) processed *= procM . value ;
598+ else if ( procM . effect === "flat" ) processed += procM . value ;
603599 }
604- // Stack QA + polisher if safe
605- if ( this . _oreChainTags ?. has ( "Polished" ) ) bestProcessed += 10 ;
600+
601+ // Step 2: Polisher (+$10 flat) — before combines/QA so they amplify it
602+ if ( this . _oreChainTags ?. has ( "Polished" ) ) processed += 10 ;
603+
604+ // Step 3: Same-type combines (prismatic: gem+gem → 1.15x combined)
605+ for ( const [ combId , combM ] of this . registry . machines ) {
606+ if ( ! this . registry . isAvailable ( combId , this . config ) ) continue ;
607+ if ( combM . effect !== "combine" ) continue ;
608+ const allGem = ( combM . inputs || [ ] ) . every ( inp => inp === "gem" || inp . split ( "|" ) . includes ( "gem" ) ) ;
609+ if ( ! allGem ) continue ;
610+ const inputCount = ( combM . inputs || [ ] ) . length ;
611+ // Combined value per gem input: (N gems × value) × multiplier / N
612+ processed = processed * inputCount * ( combM . value || 1 ) / inputCount ;
613+ }
614+
615+ // Step 4: QA (1.2x percent) — last
606616 const qa = this . registry . get ( "quality_assurance" ) ;
607617 if ( qa && this . registry . isAvailable ( "quality_assurance" , this . config ) ) {
608- bestProcessed *= ( 1 + qa . value ) ;
618+ processed *= ( 1 + qa . value ) ;
609619 }
610- byproductValue = bestProcessed * ds ;
620+
621+ byproductValue = processed * ds ;
611622 } else if ( m . byproducts ?. [ 0 ] ?. type ) {
612623 const bpResult = this . _solve ( m . byproducts [ 0 ] . type , baseOreValue ) ;
613624 byproductValue = bpResult ?. value || 0 ;
0 commit comments