diff --git a/desktop/package-lock.json b/desktop/package-lock.json index dd52c9d..33f10f7 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -1,12 +1,12 @@ { "name": "simc-lab", - "version": "1.35.0", + "version": "1.35.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "simc-lab", - "version": "1.35.0", + "version": "1.35.1", "license": "GPL-3.0-or-later", "dependencies": { "electron-updater": "^6.8.9" diff --git a/desktop/package.json b/desktop/package.json index 3e28475..ac7266d 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -2,7 +2,7 @@ "name": "simc-lab", "productName": "SimC Lab", "desktopName": "simc-lab.desktop", - "version": "1.35.0", + "version": "1.35.1", "description": "Local SimulationCraft workbench with upgrade finder and tank simulation.", "author": "Roburmaster", "private": true, diff --git a/lib/engine.mjs b/lib/engine.mjs index fb9e7f6..a312eb8 100644 --- a/lib/engine.mjs +++ b/lib/engine.mjs @@ -106,6 +106,8 @@ export async function prepare(request,catalog,talentData,season) { if(!Array.isArray(scenarios)||!scenarios.length||scenarios.length>8) throw new Error('Choose 1–8 scenarios.'); // The Silvermoon dummies are always five, so a target matrix collapses to one fight there. scenarios=scenarios.filter((s,i)=>!isDummyStyle(s?.style)||scenarios.findIndex(o=>o?.style===s.style&&(o.duration??null)===(s.duration??null)&&(o.dummyHealth?.mode??'held')===(s.dummyHealth?.mode??'held'))===i); + // A Mythic+ route has no boss to survive, so a tank on one is ranked on DPS alone. + if(scenarios.length&&scenarios.every(s=>isRouteStyle(s?.style)))settings.tank=null; const unique=new Set();let routes=null; for(const s of scenarios) { if(!fightStyles.includes(s.style)) throw new Error('Unknown fight style.'); diff --git a/package-lock.json b/package-lock.json index bfc0c01..d237574 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "simc-lab", - "version": "1.35.0", + "version": "1.35.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "simc-lab", - "version": "1.35.0", + "version": "1.35.1", "license": "GPL-3.0-or-later", "devDependencies": { "luaparse": "^0.3.1", diff --git a/package.json b/package.json index 998747c..7947d28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "simc-lab", - "version": "1.35.0", + "version": "1.35.1", "private": true, "type": "module", "scripts": { diff --git a/public/app.js b/public/app.js index 0a845af..3027e83 100644 --- a/public/app.js +++ b/public/app.js @@ -86,7 +86,7 @@ function syncFightStyle(){ } // Choosing the dummies starts from nothing; what the user turns on afterwards is kept. $('#bleed-tail-on').addEventListener('change',()=>{$('#bleed-tail-hint').hidden=!$('#bleed-tail-on').checked;}); -$('#fight-style').addEventListener('change',()=>{syncFightStyle();if(dummyStyles[$('#fight-style').value])environment.bare();});syncFightStyle(); +$('#fight-style').addEventListener('change',()=>{syncFightStyle();tank.forRoute($('#fight-style').value===routeStyle);if(dummyStyles[$('#fight-style').value])environment.bare();});syncFightStyle(); $$('.settings input,.settings select,input[name=combine]').forEach(el=>el.addEventListener('change',updateCount)); async function runJob(){ try{notice('');$('#run').disabled=true;if(!['weapons','trinkets'].includes(mode)&&(!profile||importedText!==$('#profile').value))await importProfile();const data=request();const preview=await api('/api/preview',data);$('#run-summary').textContent=`Starting ${preview.total} runs …`;const job=await api('/api/jobs',data);activity.refresh();await watchJob(job.id);$('#results').scrollIntoView({behavior:'smooth',block:'start'});}catch(e){notice(e.message);}finally{$('#run').disabled=false;updateCount();} diff --git a/public/tank.js b/public/tank.js index 7373add..bed156d 100644 --- a/public/tank.js +++ b/public/tank.js @@ -4,11 +4,11 @@ const fields=[['pressure','Sustained damage (% health / sec)',0.5,20,0.5],['bust export const signed=(n,digits=2)=>`${n>=0?'+':''}${n.toFixed(digits)}`; export function tankUI({updateCount}){ - let presets=null,active=false,weapons=false; + let presets=null,active=false,weapons=false,route=false; $('#results').insertAdjacentHTML('beforebegin',``); // The same settings serve one imported tank and every tank specialization in a Weapon Lab job. function scope(){ - $('#tank-panel').hidden=!(active||weapons); + $('#tank-panel').hidden=route||!(active||weapons); $('#tank-scope').textContent=weapons?'Every tank specialization':'Tank specialization'; $('#tank-intro').textContent=weapons?'Tank specializations are ranked on DPS and survival. A boss is calibrated once for each of their reference profiles, then every weapon fights that boss.':'Tanks are ranked on DPS and survival. A boss is calibrated to your imported gear once per job, then every build fights the same boss.'; } @@ -27,8 +27,10 @@ export function tankUI({updateCount}){ init(options){presets=options.tankPresets;render();}, show(profile){active=!!profile?.isTank;scope();}, forWeapons(on){weapons=!!on;scope();}, + // A Mythic+ route has no boss to survive, so a tank is ranked on DPS alone there. + forRoute(on){route=!!on;scope();}, settings(){ - if(!(active||weapons)||!presets)return undefined; + if(route||!(active||weapons)||!presets)return undefined; const result={preset:$('#tank-preset').value,weight:Number($('#tank-weight').value)}; for(const [key] of fields){const value=$(`[data-tank="${key}"]`).value;if(value!=='')result[key]=Number(value);} return result;