@vault-tec/pip-boy 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as e from"@angular/core";import{input as t,ViewChild as a,Component as n,signal as o,Injectable as i,effect as r,inject as l,EventEmitter as s,Output as d,Input as m,computed as c,output as u,HostListener as p}from"@angular/core";import b from"gsap";import{CommonModule as g}from"@angular/common";import f from"jszip";class h{replayTimeoutSeconds=t(8,...ngDevMode?[{debugName:"replayTimeoutSeconds"}]:[]);screen=t.required(...ngDevMode?[{debugName:"screen"}]:[]);scanSpeedSeconds=t(5,...ngDevMode?[{debugName:"scanSpeedSeconds"}]:[]);tailLengthPx=t(300,...ngDevMode?[{debugName:"tailLengthPx"}]:[]);scanlineRef;scanTween=null;resizeObserver=null;ngAfterViewInit(){if(window.matchMedia("(prefers-reduced-motion: reduce)").matches)return;const e=this.scanlineRef.nativeElement,t=this.screen(),a=()=>{e.style.height=`${this.tailLengthPx()}px`;const a=t.clientHeight,n=e.offsetHeight;if(a<=0||n<=0)return;const o=-n,i=a+n;this.scanTween&&(this.scanTween.kill(),this.scanTween=null),b.set(e,{y:o});const r=this.replayTimeoutSeconds(),l=r>0?Math.random()*r:0;this.scanTween=b.to(e,{y:i,duration:this.scanSpeedSeconds(),ease:"none",repeat:-1,repeatDelay:r,delay:l})};a(),this.resizeObserver=new ResizeObserver(()=>{a()}),this.resizeObserver.observe(t)}ngOnDestroy(){this.scanTween&&(this.scanTween.kill(),this.scanTween=null),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:h,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.1.0",version:"21.0.8",type:h,isStandalone:!0,selector:"pip-boy-screen-scan-lines",inputs:{replayTimeoutSeconds:{classPropertyName:"replayTimeoutSeconds",publicName:"replayTimeoutSeconds",isSignal:!0,isRequired:!1,transformFunction:null},screen:{classPropertyName:"screen",publicName:"screen",isSignal:!0,isRequired:!0,transformFunction:null},scanSpeedSeconds:{classPropertyName:"scanSpeedSeconds",publicName:"scanSpeedSeconds",isSignal:!0,isRequired:!1,transformFunction:null},tailLengthPx:{classPropertyName:"tailLengthPx",publicName:"tailLengthPx",isSignal:!0,isRequired:!1,transformFunction:null}},viewQueries:[{propertyName:"scanlineRef",first:!0,predicate:["scanline"],descendants:!0,static:!0}],ngImport:e,template:'<div #scanline class="screen-scanline" aria-hidden="true"></div>\n',styles:['.screen>:not(.screen-scanline){position:relative;z-index:1}.screen-scanline{position:absolute;left:0;right:0;top:0;height:140px;z-index:0;pointer-events:none;background:linear-gradient(to bottom,#3ad03a00,#3ad03a0a 35%,#3ad03a1f 65%,#3ad03a29 85%);mix-blend-mode:screen;opacity:.5;filter:blur(5px)}.screen-scanline:after{content:"";position:absolute;left:0;right:0;bottom:8px;height:2px}\n']})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:h,decorators:[{type:n,args:[{selector:"pip-boy-screen-scan-lines",template:'<div #scanline class="screen-scanline" aria-hidden="true"></div>\n',styles:['.screen>:not(.screen-scanline){position:relative;z-index:1}.screen-scanline{position:absolute;left:0;right:0;top:0;height:140px;z-index:0;pointer-events:none;background:linear-gradient(to bottom,#3ad03a00,#3ad03a0a 35%,#3ad03a1f 65%,#3ad03a29 85%);mix-blend-mode:screen;opacity:.5;filter:blur(5px)}.screen-scanline:after{content:"";position:absolute;left:0;right:0;bottom:8px;height:2px}\n']}]}],propDecorators:{replayTimeoutSeconds:[{type:e.Input,args:[{isSignal:!0,alias:"replayTimeoutSeconds",required:!1}]}],screen:[{type:e.Input,args:[{isSignal:!0,alias:"screen",required:!0}]}],scanSpeedSeconds:[{type:e.Input,args:[{isSignal:!0,alias:"scanSpeedSeconds",required:!1}]}],tailLengthPx:[{type:e.Input,args:[{isSignal:!0,alias:"tailLengthPx",required:!1}]}],scanlineRef:[{type:a,args:["scanline",{static:!0}]}]}});class y{static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:y,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"21.0.8",type:y,isStandalone:!0,selector:"pip-boy-2000-mk-vi",ngImport:e,template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"],dependencies:[{kind:"component",type:h,selector:"pip-boy-screen-scan-lines",inputs:["replayTimeoutSeconds","screen","scanSpeedSeconds","tailLengthPx"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:y,decorators:[{type:n,args:[{selector:"pip-boy-2000-mk-vi",standalone:!0,imports:[h],template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"]}]}]});class v{static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:v,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"21.0.8",type:v,isStandalone:!0,selector:"pip-boy-3000a",ngImport:e,template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"],dependencies:[{kind:"component",type:h,selector:"pip-boy-screen-scan-lines",inputs:["replayTimeoutSeconds","screen","scanSpeedSeconds","tailLengthPx"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:v,decorators:[{type:n,args:[{selector:"pip-boy-3000a",standalone:!0,imports:[h],template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"]}]}]});class I{static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:I,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"21.0.8",type:I,isStandalone:!0,selector:"pip-boy-3000-mk-iv",ngImport:e,template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"],dependencies:[{kind:"component",type:h,selector:"pip-boy-screen-scan-lines",inputs:["replayTimeoutSeconds","screen","scanSpeedSeconds","tailLengthPx"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:I,decorators:[{type:n,args:[{selector:"pip-boy-3000-mk-iv",standalone:!0,imports:[h],template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"]}]}]});class w{primary=o("STATS",...ngDevMode?[{debugName:"primary"}]:[]);secondary=o("STATUS",...ngDevMode?[{debugName:"secondary"}]:[]);tertiary=o("CND",...ngDevMode?[{debugName:"tertiary"}]:[]);selectPrimary(e){if(this.primary()!==e)switch(this.primary.set(e),e){case"STATS":this.secondary.set("STATUS"),this.tertiary.set("CND");break;case"ITEMS":this.secondary.set("WEAPONS"),this.tertiary.set(null);break;case"DATA":this.secondary.set("LOCAL MAP"),this.tertiary.set(null);break;default:throw new Error(`Unhandled primary tab selection: ${e}`)}}selectSecondary(e){this.secondary.set(e),"STATS"!==this.primary()||"STATUS"!==e?this.tertiary.set(null):null===this.tertiary()&&this.tertiary.set("CND")}selectTertiary(e){"STATS"===this.primary()&&"STATUS"===this.secondary()&&this.tertiary.set(e)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:w,deps:[],target:e.ɵɵFactoryTarget.Injectable});static"ɵprov"=e.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:w})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:w,decorators:[{type:i}]});class x{dbPromise=this.openDb();imageUrls=o({},...ngDevMode?[{debugName:"imageUrls"}]:[]);loading=new Set;getImageUrl(e){if(!e)return null;const t=this.imageUrls()[e];return t||(this.loadImageUrl(e),null)}async saveFile(e){const t=this.createId(),a={id:t,fileName:e.name,mime:e.type||"application/octet-stream"};return await this.putRecord({...a,blob:e}),this.cacheUrl(t,URL.createObjectURL(e)),a}async saveBlobWithId(e,t,a,n){await this.putRecord({id:e,blob:t,fileName:a,mime:n}),this.cacheUrl(e,URL.createObjectURL(t))}async saveDataUrlWithId(e,t){const a=await fetch(t),n=await a.blob(),o=n.type||"application/octet-stream",i=`image-${e}${this.extensionFromMime(o)}`;await this.saveBlobWithId(e,n,i,o)}async getRecord(e){const t=await this.dbPromise;return new Promise((a,n)=>{const o=t.transaction("images","readonly").objectStore("images").get(e);o.onsuccess=()=>{a(o.result??null)},o.onerror=()=>n(o.error)})}async getBlob(e){const t=await this.getRecord(e);return t?.blob??null}extensionFromMime(e){switch(e){case"image/png":return".png";case"image/jpeg":return".jpg";case"image/webp":return".webp";case"image/gif":return".gif";case"image/svg+xml":return".svg";default:return""}}generateId(){return this.createId()}cacheUrl(e,t){this.imageUrls.update(a=>({...a,[e]:t}))}async loadImageUrl(e){if(!this.loading.has(e)){this.loading.add(e);try{const t=await this.getBlob(e);if(!t)return;this.cacheUrl(e,URL.createObjectURL(t))}finally{this.loading.delete(e)}}}async putRecord(e){const t=await this.dbPromise;return new Promise((a,n)=>{const o=t.transaction("images","readwrite").objectStore("images").put(e);o.onsuccess=()=>a(),o.onerror=()=>n(o.error)})}openDb(){return new Promise((e,t)=>{const a=indexedDB.open("pipBoy3000Images",1);a.onupgradeneeded=()=>{const e=a.result;e.objectStoreNames.contains("images")||e.createObjectStore("images",{keyPath:"id"})},a.onsuccess=()=>e(a.result),a.onerror=()=>t(a.error)})}createId(){return"undefined"!=typeof crypto&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:x,deps:[],target:e.ɵɵFactoryTarget.Injectable});static"ɵprov"=e.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:x,providedIn:"root"})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:x,decorators:[{type:i,args:[{providedIn:"root"}]}]});const k=[{formId:"0003C345",editorId:"AntMeat",name:"Ant Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00031020",editorId:"AntNectar",name:"Ant Nectar",nonPlayable:!1,wg:.25,val:20,effects:"INT +2,CHA +2,STR +4,Usage Monitor Effect 20"},{formId:"00033068",editorId:"AntQueenPheromones",name:"Ant Queen Pheromones",nonPlayable:!1,wg:1,val:75,effects:"CHA +3,INT +3,PER +3"},{formId:"00015197",editorId:"Beer",name:"Beer",nonPlayable:!1,wg:1,val:2,effects:"INT +1,STR +1,CHA +1"},{formId:"000BF7C6",editorId:"MS15Mentat02",name:"Berry Mentats",nonPlayable:!1,wg:0,val:20,effects:"INT +5"},{formId:"0008C556",editorId:"BlamcoMacandCheese",name:"Blamco Mac and Cheese",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0007C10D",editorId:"BloatflyMeat",name:"Bloatfly Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00034051",editorId:"BloodPack",name:"Blood Pack",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 19,Restore Health 1"},{formId:"00015198",editorId:"BrahminSteak",name:"Brahmin Steak",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0008C560",editorId:"Bubblegum",name:"Bubblegum",nonPlayable:!1,wg:1,val:1,effects:"Restore Health 1,Restore Health 1,Damage Rads 1"},{formId:"00015163",editorId:"Buffout",name:"Buffout",nonPlayable:!1,wg:0,val:20,effects:"STR +2,END +3,Increased Health - Buffout 60,Usage Monitor Effect 30"},{formId:"00038E0C",editorId:"CaveFungus",name:"Cave Fungus",nonPlayable:!1,wg:1,val:50,effects:"Restore Health 5,Restore Rads 10"},{formId:"0008C552",editorId:"Cram",name:"Cram",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00031948",editorId:"SquirrelBits",name:"Crispy Squirrel Bits",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0001519C",editorId:"Mutfruit1",name:"Crunchy Mutfruit",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0008C554",editorId:"DandyBoyApples",name:"Dandy Boy Apples",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"000151A4",editorId:"WaterUnpurified",name:"Dirty Water",nonPlayable:!1,wg:1,val:10,effects:"Restore Health 10,Restore Health 2,Damage Rads 6"},{formId:"00034050",editorId:"DogMeat",name:"Dog Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0008C55A",editorId:"FancyLadsSnackCakes",name:"Fancy Lads Snack Cakes",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00085ABB",editorId:"MS04FireAntNectar",name:"Fire Ant Nectar",nonPlayable:!1,wg:1,val:20,effects:"AGL +4,INT +3,Increased Fire Resistance 25"},{formId:"00015196",editorId:"Apple",name:"Fresh Apple",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 10"},{formId:"00015199",editorId:"Carrot",name:"Fresh Carrot",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 10"},{formId:"0001519F",editorId:"Pear",name:"Fresh Pear",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 10"},{formId:"000151A0",editorId:"Potato",name:"Fresh Potato",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 10"},{formId:"000BF7C5",editorId:"MS15Mentat01",name:"Grape Mentats",nonPlayable:!1,wg:0,val:20,effects:"CHA +5"},{formId:"0008C564",editorId:"RadioactiveGumDrops",name:"Gum Drops",nonPlayable:!1,wg:1,val:2,effects:"Restore Health 1,Damage Rads 1,Restore Health 1"},{formId:"00065175",editorId:"MirelurkMeatHatchling",name:"Hatchling Mirelurk Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0003404F",editorId:"HumanFlesh",name:"Human Flesh",nonPlayable:!1,wg:1,val:0,effects:"Restore Health 25,Restore Health 5,Damage Rads 10"},{formId:"00040DCB",editorId:"MS05IceNukaCola",name:"Ice Cold Nuka-Cola",nonPlayable:!1,wg:1,val:20,effects:"Restore Health 20,Nuka-Cola Add Cap Effect,Restore Health 4,Damage Rads 3"},{formId:"0001519A",editorId:"IguanaBits",name:"Iguana Bits",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0001519B",editorId:"IguanaOnAStick",name:"Iguana on a Stick",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0008C558",editorId:"InstaMash",name:"InstaMash",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00015164",editorId:"Jet",name:"Jet",nonPlayable:!1,wg:0,val:20,effects:"Increase Action Points - Jet 30,Usage Monitor Effect 30"},{formId:"0003359C",editorId:"JunkFood",name:"Junk Food",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00050F8F",editorId:"Morphine",name:"Med-X",nonPlayable:!1,wg:0,val:20,effects:"Increase Damage Resistance - Psycho 25,Usage Monitor Effect 30"},{formId:"00015165",editorId:"Mentats",name:"Mentats",nonPlayable:!1,wg:0,val:20,effects:"INT +5,PER +5,Usage Monitor Effect 30"},{formId:"0003404D",editorId:"MirelurkCakes",name:"Mirelurk Cakes",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0003404E",editorId:"MirelurkMeat",name:"Mirelurk Meat",nonPlayable:!1,wg:1,val:20,effects:"Restore Health 20,Restore Health 4,Damage Rads 3"},{formId:"00049076",editorId:"MS05FinNukaPie",name:"Miss. Quantum Pie",nonPlayable:!1,wg:1,val:20,effects:"STR +1,INT +1,Increased Action Points 20,Damage Rads 5"},{formId:"0003404C",editorId:"MoleRatMeat",name:"Mole Rat Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"000ABD17",editorId:"MoleRatWonderMeat",name:"Mole Rat Wonder Meat",nonPlayable:!1,wg:1,val:20,effects:"Restore Health 20,Restore Health 4,Damage Rads 3"},{formId:"00034049",editorId:"Mutfruit2",name:"Mutfruit",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0001519D",editorId:"Noodles",name:"Noodles",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"000284F9",editorId:"MS05NukaColaQtm",name:"Nuka-Cola Quantum",nonPlayable:!1,wg:1,val:30,effects:"Nuka-Cola Add Cap Effect,Increased Action Points 20,Damage Rads 10,Usage Monitor Effect 12"},{formId:"0001519E",editorId:"NukaCola",name:"Nuka-Cola",nonPlayable:!1,wg:1,val:20,effects:"Restore Health 10,Nuka-Cola Add Cap Effect,Restore Health 2,Damage Rads 3"},{formId:"00095F48",editorId:"MS05NukalurkMeat",name:"NukaLurk Meat",nonPlayable:!1,wg:1,val:7,effects:"Restore Health 20,Restore Health 4,Increased Action Points 10,Damage Rads 5"},{formId:"000BF7C7",editorId:"MS15Mentat03",name:"Orange Mentats",nonPlayable:!1,wg:0,val:20,effects:"PER +5"},{formId:"0008C55E",editorId:"PorkNBeans",name:"Pork N' Beans",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0008C562",editorId:"PotatoCrisps",name:"Potato Crisps",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00015166",editorId:"Psycho",name:"Psycho",nonPlayable:!1,wg:0,val:20,effects:"Damage +25%,Usage Monitor Effect 30"},{formId:"000151A3",editorId:"WaterPurified",name:"Purified Water",nonPlayable:!1,wg:1,val:20,effects:"Restore Health 20"},{formId:"00015167",editorId:"RadAway",name:"RadAway",nonPlayable:!1,wg:0,val:20,effects:"Restore Rads 50"},{formId:"0009C957",editorId:"RadroachMeat",name:"Radroach Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00015168",editorId:"RadX",name:"Rad-X",nonPlayable:!1,wg:0,val:20,effects:"Increased Radiation Resistance 25"},{formId:"000293A9",editorId:"SalisburySteak",name:"Salisbury Steak",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"000151A1",editorId:"Scotch",name:"Scotch",nonPlayable:!1,wg:1,val:10,effects:"STR +1,INT +1,CHA +1"},{formId:"000552CE",editorId:"MirelurkMeatSoftshell",name:"Softshell Mirelurk Meat",nonPlayable:!1,wg:1,val:30,effects:"Restore Health 30,Restore Health 6,Damage Rads 3"},{formId:"00031949",editorId:"SquirrelOnAStick",name:"Squirrel on a Stick",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0003194A",editorId:"SquirrelStew",name:"Squirrel Stew",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00043E94",editorId:"StealthBoy",name:"Stealth Boy",nonPlayable:!1,wg:1,val:100,effects:"Stealth Field 75,Increased Sneak 100,Stealth Field Stop Combat"},{formId:"00015169",editorId:"Stimpak",name:"Stimpak",nonPlayable:!1,wg:0,val:25,effects:"Restore Health & Conditions 30,Restore Health & Conditions 36"},{formId:"0007E173",editorId:"StrangeMeatPie",name:"Strange Meat Pie",nonPlayable:!1,wg:1,val:2,effects:"Restore Health 5,Damage Rads 3,Restore Health 1"},{formId:"0002E376",editorId:"StrangeMeat",name:"Strange Meat",nonPlayable:!1,wg:1,val:2,effects:"Restore Health 5,Damage Rads 3,Restore Health 1"},{formId:"0008C551",editorId:"SugarBombs01",name:"Sugar Bombs",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00030A23",editorId:"CG02Sweetroll",name:"Sweetroll",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1"},{formId:"000C9CF4",editorId:"MS09Ultrajet",name:"Ultrajet",nonPlayable:!1,wg:0,val:50,effects:"Increase Action Points - Jet 40,Usage Monitor Effect 12"},{formId:"00032C74",editorId:"Vodka",name:"Vodka",nonPlayable:!1,wg:1,val:20,effects:"STR +1,INT +1,CHA +1"},{formId:"00032C75",editorId:"Whiskey",name:"Whiskey",nonPlayable:!1,wg:1,val:10,effects:"STR +1,INT +1,CHA +1"},{formId:"0003404A",editorId:"Wine",name:"Wine",nonPlayable:!1,wg:1,val:10,effects:"STR +1,INT +1,CHA +1"},{formId:"0003404B",editorId:"YaoGuaiMeat",name:"Yao Guai Meat",nonPlayable:!1,wg:1,val:30,effects:"Restore Health 10,Restore Health 2,Damage Rads 10,Damage +10%"},{formId:"0008C55C",editorId:"YumYumDeviledEggs",name:"YumYum Deviled Eggs",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"}],S=[{formId:"0006B53C",editorId:"Ammo308Caliber",name:".308 Caliber Round",nonPlayable:!1,wg:0,val:3},{formId:"000207F7",editorId:"Ammo32Caliber",name:".32 Caliber Round",nonPlayable:!1,wg:0,val:1},{formId:"0002937E",editorId:"Ammo44magnum",name:".44 Round, Magnum",nonPlayable:!1,wg:0,val:2},{formId:"00004241",editorId:"Ammo10mm",name:"10mm Round",nonPlayable:!1,wg:0,val:1},{formId:"00004240",editorId:"Ammo556mm",name:"5.56mm Round",nonPlayable:!1,wg:0,val:1},{formId:"00078CC4",editorId:"Ammo556mmRobot",name:"5.56mm Round",nonPlayable:!1,wg:0,val:0},{formId:"000615A8",editorId:"Ammo5mmRobot",name:"5mm Round",nonPlayable:!1,wg:0,val:1},{formId:"0006B53D",editorId:"Ammo5mm",name:"5mm Round",nonPlayable:!1,wg:0,val:1},{formId:"00029364",editorId:"AmmoAlienPowerCell",name:"Alien Power Cell",nonPlayable:!1,wg:0,val:10},{formId:"0002935B",editorId:"AmmoBB",name:"BB",nonPlayable:!1,wg:0,val:1},{formId:"0002936E",editorId:"AmmoDart",name:"Dart",nonPlayable:!1,wg:0,val:1},{formId:"00047419",editorId:"AmmoBloasflyDart",name:"Dart",nonPlayable:!1,wg:0,val:1},{formId:"000615AF",editorId:"AmmoElectronChargePackRobot",name:"Electron Charge Pack",nonPlayable:!1,wg:0,val:1},{formId:"0006B53E",editorId:"AmmoElectronChargePack",name:"Electron Charge Pack",nonPlayable:!1,wg:0,val:1},{formId:"00020772",editorId:"AmmoSmallEnergyCell",name:"Energy Cell",nonPlayable:!1,wg:0,val:2},{formId:"00078CC2",editorId:"AmmoSmallEnergyCellRobot",name:"Energy Cell",nonPlayable:!1,wg:0,val:0},{formId:"00029371",editorId:"AmmoFlamerFuel",name:"Flamer Fuel",nonPlayable:!1,wg:0,val:1},{formId:"00078CC1",editorId:"AmmoFlamerFuelRobot",name:"Flamer Fuel",nonPlayable:!1,wg:0,val:0},{formId:"0006A80D",editorId:"AmmoMesmetronPowerCell",name:"Mesmetron Power Cell",nonPlayable:!1,wg:0,val:10},{formId:"00004485",editorId:"AmmoMicroFusionCell",name:"Microfusion Cell",nonPlayable:!1,wg:0,val:3},{formId:"00078CC3",editorId:"AmmoMicroFusionCellRobot",name:"Microfusion Cell",nonPlayable:!1,wg:0,val:0},{formId:"00020799",editorId:"ammoFatMan",name:"Mini Nuke",nonPlayable:!1,wg:0,val:250},{formId:"00029383",editorId:"AmmoMissile",name:"Missile",nonPlayable:!1,wg:0,val:50},{formId:"0005F706",editorId:"AmmoCentaurSpit",name:"Missile",nonPlayable:!1,wg:0,val:1},{formId:"00078CC5",editorId:"AmmoMissileRobot",name:"Missile",nonPlayable:!1,wg:0,val:50},{formId:"000B8791",editorId:"AmmoAntSpit",name:"Missile",nonPlayable:!1,wg:0,val:1},{formId:"00029384",editorId:"AmmoRailwaySpikes",name:"Railway Spikes",nonPlayable:!1,wg:0,val:2},{formId:"00028EEA",editorId:"AmmoShotgunShell",name:"Shotgun Shell",nonPlayable:!1,wg:0,val:2},{formId:"0004C5F9",editorId:"AmmoShotgunShellRobot",name:"Shotgun Shell",nonPlayable:!1,wg:0,val:2},{formId:"00056634",editorId:"AmmoMirelurkKing",name:"Sonic Energy",nonPlayable:!1,wg:0,val:10}],P=[{formId:"000CB5F9",editorId:"ArmorUniqueTeslaPower",name:'"Robo-Thor" Armor',nonPlayable:!1,dr:40,wg:45,val:820,cnd:3e3},{formId:"000CB5F8",editorId:"ArmorUniqueTeslaHelmet",name:'"Robo-Thor" Helmet',nonPlayable:!1,dr:8,wg:5,val:120,cnd:125},{formId:"0003307A",editorId:"ArmorRadiationSuitAdvanced",name:"Advanced Radiation Suit",nonPlayable:!1,dr:8,wg:7,val:100,cnd:25},{formId:"000CB605",editorId:"OutfitUniqueEnclaveScientist",name:"All-Purpose Science Suit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000CB5F6",editorId:"ArmorUniqueMetal",name:"Apocalypse Gladiator Armor",nonPlayable:!1,dr:36,wg:30,val:460,cnd:1200},{formId:"000CB5F7",editorId:"ArmorUniqueMetalHelmet",name:"Apocalypse Gladiator Helmet",nonPlayable:!1,dr:5,wg:3,val:70,cnd:75},{formId:"00034121",editorId:"MS03VaultSuit101Armored",name:"Armored Vault 101 Jumpsuit",nonPlayable:!1,dr:12,wg:15,val:180,cnd:100},{formId:"0006C587",editorId:"MountedVaultSuit101Armored",name:"Armored Vault 101 Jumpsuit",nonPlayable:!1,dr:12,wg:15,val:180,cnd:100},{formId:"00061A72",editorId:"ArmorPowerArmy",name:"Army Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"000340FB",editorId:"KIDOutfitWastelandChild04",name:"Athlete of the Wastes Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"00028FFA",editorId:"OutfitWastelandHat04",name:"Ballcap with Glasses",nonPlayable:!1,dr:1,wg:1,val:6,cnd:10},{formId:"00073D57",editorId:"OutfitWastelandHat05",name:"Bandana",nonPlayable:!1,dr:2,wg:1,val:6,cnd:10},{formId:"0009B188",editorId:"OutfitWastelandHat03",name:"Biker Goggles",nonPlayable:!1,dr:1,wg:1,val:6,cnd:10},{formId:"0007CFEF",editorId:"CG00BirthSkirt",name:"BirthSkirt",nonPlayable:!1,dr:0,wg:0,val:0,cnd:100},{formId:"0007494C",editorId:"KIDOutfitWastelandChild05Hat",name:"Blast Off Helmet",nonPlayable:!1,dr:1,wg:1,val:30,cnd:100},{formId:"0005B6EA",editorId:"KIDOutfitWastelandChild05",name:"Blast Off Pajamas",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"0008F775",editorId:"LLFFArmorRaider03Helmet",name:"Boogeyman's Hood",nonPlayable:!1,dr:8,wg:3,val:110,cnd:100},{formId:"00018DE5",editorId:"OutfitWasteland01",name:"Brahmin-Skin Outfit",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"00075201",editorId:"ArmorPowerBrotherhoodOfSteel",name:"Brotherhood Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"00075203",editorId:"ArmorPowerHelmetBrotherhoodOfSteel",name:"Brotherhood Power Helmet",nonPlayable:!1,dr:8,wg:5,val:110,cnd:75},{formId:"000854CF",editorId:"OutfitBoSScribe",name:"Brotherhood Scribe Robe",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"0008A6DD",editorId:"MS15ButtonsWig",name:"Button's Wig",nonPlayable:!1,dr:1,wg:1,val:20,cnd:100},{formId:"0007CFF0",editorId:"CG00SurgicalMask",name:"",nonPlayable:!1,dr:0,wg:1,val:30,cnd:100},{formId:"0007C109",editorId:"ChildBlastoffHelmet",name:"ChildBlastoffHelmet",nonPlayable:!1,dr:0,wg:0,val:0,cnd:25},{formId:"00078646",editorId:"OutfitChineseCommandoHat",name:"Chinese Commando Hat",nonPlayable:!1,dr:1,wg:1,val:6,cnd:15},{formId:"000340D2",editorId:"OutfitChineseCommandoJumpsuit",name:"Chinese Jumpsuit",nonPlayable:!1,dr:6,wg:2,val:10,cnd:100},{formId:"0005157E",editorId:"OutfitColonelAutumn",name:"Colonel Autumn's Uniform",nonPlayable:!1,dr:10,wg:3,val:12,cnd:100},{formId:"00020420",editorId:"ArmorCombat",name:"Combat Armor",nonPlayable:!1,dr:32,wg:25,val:390,cnd:400},{formId:"00020426",editorId:"ArmorCombatHelmet",name:"Combat Helmet",nonPlayable:!1,dr:5,wg:3,val:50,cnd:50},{formId:"000CB544",editorId:"UniqueArmorCommando",name:"Commando Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"000CB5FA",editorId:"ArmorUniqueRecon",name:"Composite Recon Armor",nonPlayable:!1,dr:28,wg:20,val:180,cnd:600},{formId:"000CB5FB",editorId:"ArmorUniqueReconHelmet",name:"Composite Recon Helmet",nonPlayable:!1,dr:4,wg:3,val:40,cnd:70},{formId:"000B17A0",editorId:"HelmetEyebotCaravanSpecial",name:"Crow's Eyebot Helmet",nonPlayable:!1,dr:5,wg:10,val:20,cnd:25},{formId:"00079F09",editorId:"VaultSuitUtilityDad",name:"Dad's Wasteland Outfit",nonPlayable:!1,dr:2,wg:20,val:6,cnd:100},{formId:"000CB543",editorId:"UniqueArmorDefender",name:"Defender Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"000340D3",editorId:"OutfitChineseCommandoJumpsuitOld",name:"Dirty Chinese Jumpsuit",nonPlayable:!1,dr:6,wg:2,val:6,cnd:50},{formId:"000CB603",editorId:"OutfitUniqueChineseCommandoJumpsuitOld",name:"Dirty Chinese Jumpsuit",nonPlayable:!1,dr:6,wg:2,val:6,cnd:50},{formId:"0005C682",editorId:"OutfitPrewarBusinesswearDirty",name:"Dirty Pre-War Businesswear",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000340CF",editorId:"OutfitPrewarCasualwearDirty",name:"Dirty Pre-War Casualwear",nonPlayable:!1,dr:3,wg:2,val:6,cnd:100},{formId:"000340C4",editorId:"KIDOutfitPrewarChildOld",name:"Dirty Pre-War Kid's Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"0005BB70",editorId:"OutfitPrewarSpring2Dirty",name:"Dirty Pre-War Parkstroller Outfit",nonPlayable:!1,dr:3,wg:10,val:5,cnd:100},{formId:"0005BB6F",editorId:"OutfitPrewarCasualwear2Dirty",name:"Dirty Pre-War Relaxedwear",nonPlayable:!1,dr:3,wg:5,val:6,cnd:100},{formId:"000340D1",editorId:"OutfitPrewarSpringDirty",name:"Dirty Pre-War Spring Outfit",nonPlayable:!1,dr:3,wg:2,val:5,cnd:100},{formId:"00066C71",editorId:"FollowersOutfitClover",name:"Dirty Pre-War Spring Outfit",nonPlayable:!1,dr:4,wg:2,val:40,cnd:100},{formId:"0005C9A0",editorId:"GlassesDoctorLi",name:"Doctor Li's Glasses",nonPlayable:!1,dr:1,wg:0,val:6,cnd:100},{formId:"000340DA",editorId:"OutfitDoctorLi",name:"Doctor Li's Outfit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"00087274",editorId:"OutfitElderLyons",name:"Elder Lyons' Robe",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"00078647",editorId:"OutfitEnclaveOfficer01Hat",name:"Enclave Officer Hat",nonPlayable:!1,dr:1,wg:1,val:6,cnd:15},{formId:"000340DE",editorId:"OutfitEnclaveOfficer01",name:"Enclave Officer Uniform",nonPlayable:!1,dr:5,wg:3,val:8,cnd:100},{formId:"00023B62",editorId:"RavenRockCorpseArmorEnclave",name:"Enclave Power Armor",nonPlayable:!1,dr:40,wg:45,val:780,cnd:1200},{formId:"0004443E",editorId:"ArmorEnclave",name:"Enclave Power Armor",nonPlayable:!1,dr:40,wg:45,val:780,cnd:1200},{formId:"0004443F",editorId:"ArmorEnclaveHelmet",name:"Enclave Power Helmet",nonPlayable:!1,dr:9,wg:5,val:110,cnd:75},{formId:"0001B5BD",editorId:"OutfitEnclaveScientist",name:"Enclave Scientist Outfit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000CB5F3",editorId:"ArmorUniqueEnclave",name:"Enclave Shocktrooper Armor",nonPlayable:!1,dr:40,wg:45,val:900,cnd:1500},{formId:"000CB5F4",editorId:"ArmorUniqueEnclaveHelmet",name:"Enclave Shocktrooper Helmet",nonPlayable:!1,dr:7,wg:5,val:150,cnd:125},{formId:"000C09D4",editorId:"MS03EnvironmentSuit",name:"Environment Suit",nonPlayable:!1,dr:6,wg:5,val:100,cnd:25},{formId:"00034126",editorId:"OutfitEulogyJonesHat",name:"Eulogy Jones' Hat",nonPlayable:!1,dr:1,wg:1,val:6,cnd:15},{formId:"00034125",editorId:"OutfitEulogyJones",name:"Eulogy Jones' Suit",nonPlayable:!1,dr:2,wg:3,val:6,cnd:100},{formId:"000CB549",editorId:"ArmorUniqueExplorer",name:"Explorer's Gear",nonPlayable:!1,dr:12,wg:3,val:50,cnd:100},{formId:"0004E6A0",editorId:"HelmetEyebot",name:"Eyebot Helmet",nonPlayable:!1,dr:5,wg:3,val:20,cnd:25},{formId:"000340FD",editorId:"GlassesBlackrimmed",name:"Eyeglasses",nonPlayable:!1,dr:1,wg:0,val:8,cnd:150},{formId:"0001DC1C",editorId:"MS12GhoulMask",name:"Ghoul Mask",nonPlayable:!1,dr:3,wg:1,val:50,cnd:100},{formId:"0005DC82",editorId:"GlassesReadingChild",name:"GlassesReadingChild",nonPlayable:!1,dr:0,wg:0,val:12,cnd:150},{formId:"000B1056",editorId:"OutfitPrewarBusinesswearDirtyDARK",name:"Grimy Pre-War Businesswear",nonPlayable:!1,dr:3,wg:2,val:6,cnd:100},{formId:"000CB5FE",editorId:"ArmorUniqueRaider02",name:"Hand-Me-Down Raider Armor",nonPlayable:!1,dr:15,wg:15,val:180,cnd:100},{formId:"000BF6FD",editorId:"OutfitJumpsuitTLHandyman",name:"Handyman Jumpsuit",nonPlayable:!1,dr:2,wg:1,val:6,cnd:100},{formId:"000CB604",editorId:"OutfitUniqueChineseCommandoHat",name:"Hat of the People",nonPlayable:!1,dr:1,wg:1,val:30,cnd:20},{formId:"00074296",editorId:"HeadWrap01",name:"Head Wrap",nonPlayable:!1,dr:1,wg:0,val:0,cnd:10},{formId:"00074334",editorId:"HeadWrap04",name:"Head Wrap",nonPlayable:!1,dr:1,wg:0,val:0,cnd:10},{formId:"00074335",editorId:"HeadWrap03",name:"Head Wrap",nonPlayable:!1,dr:1,wg:0,val:0,cnd:10},{formId:"00074336",editorId:"HeadWrap02",name:"Head Wrap",nonPlayable:!1,dr:1,wg:0,val:0,cnd:10},{formId:"000CB5FF",editorId:"ArmorUniqueRaider04",name:"Highway Scar Armor",nonPlayable:!1,dr:15,wg:15,val:180,cnd:100},{formId:"00033598",editorId:"HelmetHockeyMask",name:"Hockey Mask",nonPlayable:!1,dr:3,wg:1,val:10,cnd:15},{formId:"000340F9",editorId:"KIDOutfitWastelandChild02",name:"Junior Officer Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"0009B185",editorId:"KIDOutfitWastelandChild04Hat",name:"Kid's Ballcap with Glasses",nonPlayable:!1,dr:1,wg:1,val:30,cnd:100},{formId:"000340C1",editorId:"KIDHatPrewarCapKid",name:"Kid's Baseball Cap",nonPlayable:!1,dr:1,wg:1,val:40,cnd:150},{formId:"000340E4",editorId:"KIDOutfitLittleLamplighter01",name:"Kid's Cave Rat Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"00078643",editorId:"KIDOutfitLittleLamplighter01Hat",name:"Kid's Murray the Mole Hat",nonPlayable:!1,dr:2,wg:1,val:30,cnd:100},{formId:"00028FF8",editorId:"KIDHatPartyChild",name:"Kid's Party Hat",nonPlayable:!1,dr:1,wg:1,val:5,cnd:10},{formId:"000340E1",editorId:"KIDHatPoliceChild",name:"Kid's Police Hat",nonPlayable:!1,dr:1,wg:1,val:40,cnd:150},{formId:"000340D7",editorId:"OutfitProjectPurityDoctor",name:"Lab Technician Outfit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"00020423",editorId:"ArmorLeather",name:"Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"0002DC05",editorId:"ArmorLeatherUnplayable",name:"Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"00066C72",editorId:"FollowersOutfitJericho",name:"Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"00066C74",editorId:"FollowersOutfitCharon",name:"Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"0007401C",editorId:"MSMiniLedouxsMask",name:"Ledoux's Hockey Mask",nonPlayable:!1,dr:4,wg:1,val:100,cnd:25},{formId:"000C24F9",editorId:"MS04LeskosLabCoat",name:"Lesko's Lab Coat",nonPlayable:!1,dr:5,wg:1,val:150,cnd:200},{formId:"0004445B",editorId:"MS06LincolnsHat",name:"Lincoln's Hat",nonPlayable:!1,dr:1,wg:1,val:40,cnd:50},{formId:"00070877",editorId:"MS10LindensOutcastPowerArmor",name:"Linden's Outcast Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"000CB54B",editorId:"UniqueGlassesLuckyShades",name:"Lucky Shades",nonPlayable:!1,dr:1,wg:1,val:40,cnd:150},{formId:"00061A73",editorId:"ArmorPowerLyons",name:"Lyons' Pride Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"0002D11B",editorId:"HelmetMayorMacCready",name:"MacCready's Helmet",nonPlayable:!1,dr:6,wg:1,val:60,cnd:15},{formId:"000C111A",editorId:"Vault106GasMask",name:"Makeshift Gas Mask",nonPlayable:!1,dr:3,wg:2,val:40,cnd:25},{formId:"0005A6CA",editorId:"MS10RewardOutfitOasisDruid",name:"Maple's Garb",nonPlayable:!1,dr:15,wg:2,val:200,cnd:150},{formId:"000340E7",editorId:"KIDOutfitMayorMacCready",name:"Mayor MacCready's Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"00034124",editorId:"OutfitMerc03",name:"Merc Adventurer Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000CB608",editorId:"OutfitUniqueMerc03",name:"Merc Adventurer Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"00034122",editorId:"OutfitMerc01",name:"Merc Charmer Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000CB606",editorId:"OutfitUniqueMerc01",name:"Merc Charmer Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000C5D34",editorId:"OutfitMerc06",name:"Merc Cruiser Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000CB60B",editorId:"OutfitUniqueMerc06",name:"Merc Cruiser Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000A3045",editorId:"OutfitMerc05",name:"Merc Grunt Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000CB60A",editorId:"OutfitUniqueMerc05",name:"Merc Grunt Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"00034123",editorId:"OutfitMerc02",name:"Merc Troublemaker Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000CB607",editorId:"OutfitUniqueMerc02",name:"Merc Troublemaker Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"0008C83C",editorId:"OutfitMerc04",name:"Merc Veteran Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"0003307F",editorId:"ArmorMetal",name:"Metal Armor",nonPlayable:!1,dr:36,wg:30,val:460,cnd:500},{formId:"00033080",editorId:"ArmorMetalHelmet",name:"Metal Helmet",nonPlayable:!1,dr:5,wg:3,val:70,cnd:50},{formId:"0007C17C",editorId:"MS16VaultSuit101Utility",name:"Modified Utility Jumpsuit",nonPlayable:!1,dr:1,wg:2,val:30,cnd:100},{formId:"0009B186",editorId:"OutfitWastelandHat01",name:"Motorcycle Helmet",nonPlayable:!1,dr:5,wg:1,val:6,cnd:10},{formId:"0006B467",editorId:"OutfitMysteriousStrangerHat",name:"Mysterious Stranger Hat",nonPlayable:!1,dr:2,wg:1,val:30,cnd:100},{formId:"0006696D",editorId:"OutfitMysteriousStranger",name:"Mysterious Stranger Outfit",nonPlayable:!1,dr:5,wg:3,val:40,cnd:100},{formId:"000C8E07",editorId:"MS04AmorousAttire",name:"Naughty Nightwear",nonPlayable:!1,dr:1,wg:1,val:200,cnd:100},{formId:"0009B18A",editorId:"OutfitOasisVillagerHood",name:"Oasis Druid Hood",nonPlayable:!1,dr:2,wg:1,val:6,cnd:10},{formId:"000C942D",editorId:"OutfitOasisExileHood",name:"Oasis Exile Hood",nonPlayable:!1,dr:2,wg:1,val:30,cnd:10},{formId:"000340E8",editorId:"OutfitOasisDruid",name:"Oasis Robe",nonPlayable:!1,dr:4,wg:3,val:30,cnd:100},{formId:"000340E9",editorId:"OutfitOasisVillager",name:"Oasis Villager Robe",nonPlayable:!1,dr:4,wg:2,val:6,cnd:100},{formId:"00060C70",editorId:"ArmorPowerOutcast",name:"Outcast Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"00060C72",editorId:"ArmorPowerHelmetOutcast",name:"Outcast Power Helmet",nonPlayable:!1,dr:8,wg:5,val:110,cnd:75},{formId:"000645EC",editorId:"ArmorReconOutcast",name:"Outcast Recon Armor",nonPlayable:!1,dr:28,wg:20,val:180,cnd:400},{formId:"000645ED",editorId:"ArmorReconHelmetOutcast",name:"Outcast Recon Helmet",nonPlayable:!1,dr:4,wg:3,val:40,cnd:40},{formId:"00050E44",editorId:"HatParty",name:"Party Hat",nonPlayable:!1,dr:1,wg:1,val:5,cnd:10},{formId:"000B75E2",editorId:"HatPartyStanley",name:"Party HatStanley",nonPlayable:!1,dr:0,wg:1,val:5,cnd:10},{formId:"000340FC",editorId:"MQ04SlasherMask",name:"Pint-Sized Slasher Mask",nonPlayable:!1,dr:6,wg:1,val:60,cnd:150},{formId:"00015038",editorId:"PipBoy",name:"Pip-Boy 3000",nonPlayable:!1,dr:0,wg:0,val:0,cnd:1e5},{formId:"000236D8",editorId:"PipBoyNPC",name:"Pip-Boy 3000",nonPlayable:!1,dr:0,wg:0,val:0,cnd:1e5},{formId:"00025B83",editorId:"PipBoyGlove",name:"Pip-Boy Glove",nonPlayable:!1,dr:0,wg:0,val:30,cnd:1e5},{formId:"000AB491",editorId:"HatPoliceAdult",name:"Police Hat",nonPlayable:!1,dr:1,wg:1,val:8,cnd:150},{formId:"0005A6CB",editorId:"MS10RewardOasisVillagerHood",name:"Poplar's Hood",nonPlayable:!1,dr:2,wg:1,val:100,cnd:50},{formId:"00014E13",editorId:"ArmorPower",name:"Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"00025083",editorId:"ArmorPowerUnplayable",name:"Power Armor",nonPlayable:!1,dr:40,wg:45,val:510,cnd:1e3},{formId:"00066C73",editorId:"FollowersOutfitCross",name:"Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1500},{formId:"00014C08",editorId:"ArmorPowerHelmet",name:"Power Helmet",nonPlayable:!1,dr:8,wg:5,val:110,cnd:75},{formId:"000CB60C",editorId:"OutfitUniquePrewarBusinesswearDirtyDARK",name:"Power-Suit Armor",nonPlayable:!1,dr:3,wg:2,val:12,cnd:100},{formId:"00028FF9",editorId:"HatPrewarBaseballCap",name:"Pre-War Baseball Cap",nonPlayable:!1,dr:1,wg:1,val:8,cnd:15},{formId:"000340CD",editorId:"HatPrewarBonnet",name:"Pre-War Bonnet",nonPlayable:!1,dr:1,wg:1,val:8,cnd:15},{formId:"0001EA6D",editorId:"OutfitPrewarCasualwear",name:"Pre-War Casualwear",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000CB60D",editorId:"OutfitUniquePrewarCasualwear",name:"Pre-War Casualwear",nonPlayable:!1,dr:3,wg:2,val:12,cnd:100},{formId:"000340C8",editorId:"HatPrewarHat",name:"Pre-War Hat",nonPlayable:!1,dr:1,wg:1,val:8,cnd:15},{formId:"000340C3",editorId:"KIDOutfitPrewarChild",name:"Pre-War Kid's Outfit",nonPlayable:!1,dr:1,wg:2,val:30,cnd:100},{formId:"0008198C",editorId:"KIDOutfitPrewarChildandWatch",name:"Pre-War Outfit and Watch",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"000ABBE2",editorId:"MQ04PlayerOutfit",name:"Pre-War Outfit and Watch",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"0005BB66",editorId:"OutfitPrewarSpring2",name:"Pre-War Parkstroller Outfit",nonPlayable:!1,dr:3,wg:2,val:6,cnd:100},{formId:"000CB60F",editorId:"OutfitUniquePrewarSpring2",name:"Pre-War Parkstroller Outfit",nonPlayable:!1,dr:3,wg:2,val:10,cnd:100},{formId:"0005BB63",editorId:"OutfitPrewarCasualwear2",name:"Pre-War Relaxedwear",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000340D0",editorId:"OutfitPrewarSpring",name:"Pre-War Spring Outfit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"0007836E",editorId:"MS14PowerArmorMorphine",name:"Prototype Medic Power Armor",nonPlayable:!1,dr:40,wg:45,val:1e3,cnd:1e3},{formId:"000CB600",editorId:"ArmorUniqueRaider04Helmet",name:"Pyro Helmet",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"00033078",editorId:"ArmorRadiationSuit",name:"Radiation Suit",nonPlayable:!1,dr:6,wg:5,val:60,cnd:15},{formId:"000340F8",editorId:"KIDOutfitWastelandChild01",name:"Ragamuffin Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"00074950",editorId:"KIDOutfitWastelandChild01Hat",name:"Ragamuffin Tophat",nonPlayable:!1,dr:1,wg:1,val:30,cnd:100},{formId:"00078644",editorId:"ArmorRaider02Helmet",name:"Raider Arclight Helmet",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"0003307D",editorId:"ArmorRaider03",name:"Raider Badlands Armor",nonPlayable:!1,dr:16,wg:15,val:180,cnd:100},{formId:"0003307E",editorId:"ArmorRaider04",name:"Raider Blastmaster Armor",nonPlayable:!1,dr:16,wg:15,val:180,cnd:100},{formId:"0005B6E8",editorId:"ArmorRaider04Helmet",name:"Raider Blastmaster Helmet",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"0002042F",editorId:"ArmorRaider01",name:"Raider Painspike Armor",nonPlayable:!1,dr:16,wg:15,val:180,cnd:100},{formId:"00020432",editorId:"ArmorRaider01Helmet",name:"Raider Psycho-Tic Helmet",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"0003307C",editorId:"ArmorRaider02",name:"Raider Sadist Armor",nonPlayable:!1,dr:16,wg:15,val:180,cnd:100},{formId:"00078645",editorId:"ArmorRaider03Helmet",name:"Raider Wastehound Helmet",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"00023030",editorId:"MS18RangerBattlearmor",name:"Ranger Battle Armor",nonPlayable:!1,dr:39,wg:27,val:430,cnd:1100},{formId:"00034105",editorId:"MS18RangerHelmet",name:"Ranger Battle Helmet",nonPlayable:!1,dr:6,wg:5,val:60,cnd:50},{formId:"0001C296",editorId:"GlassesReading",name:"Reading Glasses",nonPlayable:!1,dr:1,wg:0,val:12,cnd:150},{formId:"00028EAD",editorId:"ArmorReconHelmet",name:"Recon Armor Helmet",nonPlayable:!1,dr:4,wg:3,val:40,cnd:40},{formId:"0003064D",editorId:"ArmorRecon",name:"Recon Armor",nonPlayable:!1,dr:28,wg:20,val:180,cnd:400},{formId:"0003411B",editorId:"OutfitJumpsuitRedRacer",name:"Red Racer Jumpsuit",nonPlayable:!1,dr:2,wg:1,val:6,cnd:100},{formId:"000340EB",editorId:"MS01OutfitRedHat",name:"Red's Bandana",nonPlayable:!1,dr:2,wg:1,val:30,cnd:10},{formId:"000340EA",editorId:"MS01OutfitRed",name:"Red's Jumpsuit",nonPlayable:!1,dr:3,wg:1,val:40,cnd:100},{formId:"0003E54A",editorId:"RegulatorDuster",name:"Regulator Duster",nonPlayable:!1,dr:10,wg:3,val:70,cnd:150},{formId:"000239CB",editorId:"ArmorRivetCitySecurityHelmet",name:"Rivet City Security Helmet",nonPlayable:!1,dr:4,wg:3,val:50,cnd:25},{formId:"000239CC",editorId:"ArmorRivetCitySecurity",name:"Rivet City Security Uniform",nonPlayable:!1,dr:24,wg:20,val:330,cnd:100},{formId:"000CB5F5",editorId:"ArmorUniqueLeather",name:"Road Rascal Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"0003411A",editorId:"OutfitJumpsuitRobco",name:"RobCo Jumpsuit",nonPlayable:!1,dr:2,wg:1,val:6,cnd:100},{formId:"00078648",editorId:"OutfitWastelandMerchantHat",name:"Roving Trader Hat",nonPlayable:!1,dr:1,wg:1,val:6,cnd:10},{formId:"0002B385",editorId:"OutfitWastelandMerchant01",name:"Roving Trader Outfit",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"000340D9",editorId:"OutfitRivetCityScientist",name:"Scientist Outfit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000340E6",editorId:"OutfitPrewarNegligee",name:"Sexy Sleepwear",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"0007C17D",editorId:"MS03StealthHat",name:"Shady Hat",nonPlayable:!1,dr:1,wg:1,val:40,cnd:50},{formId:"000CB5FC",editorId:"ArmorUniqueRaider01",name:"Sharp-Dressed Raider's Armor",nonPlayable:!1,dr:15,wg:15,val:180,cnd:100},{formId:"000CB5EF",editorId:"ArmorUniqueCombat",name:"Shellshocked Combat Armor",nonPlayable:!1,dr:32,wg:25,val:390,cnd:400},{formId:"000CB5F0",editorId:"ArmorUniqueCombatHelmet",name:"Shellshocked Combat Helmet",nonPlayable:!1,dr:5,wg:3,val:50,cnd:50},{formId:"00020429",editorId:"OutfitLucasSimms",name:"Sheriff's Duster",nonPlayable:!1,dr:5,wg:3,val:35,cnd:150},{formId:"0002DD80",editorId:"OutfitLucasSimmsHat",name:"Sheriff's Hat",nonPlayable:!1,dr:1,wg:1,val:35,cnd:40},{formId:"0002F563",editorId:"SlaveCollar",name:"Slave Collar",nonPlayable:!1,dr:3,wg:5,val:50,cnd:150},{formId:"0003D1FE",editorId:"MS13Collar",name:"Slave Collar",nonPlayable:!1,dr:4,wg:5,val:100,cnd:400},{formId:"000CB60E",editorId:"OutfitUniquePrewarNegligee",name:"Sleepwear",nonPlayable:!1,dr:1,wg:1,val:10,cnd:100},{formId:"0009B189",editorId:"OutfitWastelandHat02",name:"Stormchaser Hat",nonPlayable:!1,dr:1,wg:1,val:6,cnd:10},{formId:"0005C99F",editorId:"GlassesShades",name:"Sunglasses",nonPlayable:!1,dr:1,wg:0,val:8,cnd:150},{formId:"0003E591",editorId:"MS03SurgicalMask",name:"Surgical Mask",nonPlayable:!1,dr:1,wg:1,val:6,cnd:10},{formId:"000A6F77",editorId:"ArmorPowerT51b",name:"T-51b Power Armor",nonPlayable:!1,dr:50,wg:40,val:1e3,cnd:2e3},{formId:"000A6F78",editorId:"ArmorPowerT51bHelmet",name:"T-51b Power Helmet",nonPlayable:!1,dr:10,wg:4,val:120,cnd:100},{formId:"000C72FB",editorId:"HatTakomaBaseballCap",name:"Takoma Park Little Leaguer Cap",nonPlayable:!1,dr:1,wg:1,val:60,cnd:15},{formId:"000A6F76",editorId:"ArmorCombatTalon",name:"Talon Combat Armor",nonPlayable:!1,dr:28,wg:25,val:275,cnd:300},{formId:"000CB5F2",editorId:"ArmorUniqueCombatTalon",name:"Talon Combat Armor",nonPlayable:!1,dr:32,wg:25,val:390,cnd:1e3},{formId:"000B0278",editorId:"ArmorCombatHelmetTalon",name:"Talon Combat Helmet",nonPlayable:!1,dr:4,wg:3,val:60,cnd:40},{formId:"000CB5F1",editorId:"ArmorUniqueCombatHelmetTalon",name:"Talon Combat Helmet",nonPlayable:!1,dr:5,wg:3,val:60,cnd:50},{formId:"0005B6EB",editorId:"ArmorTenpennyHelmet",name:"Tenpenny Security Helmet",nonPlayable:!1,dr:4,wg:1,val:50,cnd:25},{formId:"00034119",editorId:"ArmorTenpennySecurity",name:"Tenpenny Security Uniform",nonPlayable:!1,dr:24,wg:20,val:180,cnd:100},{formId:"00096CB7",editorId:"OutfitTenpenny",name:"Tenpenny's Suit",nonPlayable:!1,dr:2,wg:2,val:8,cnd:100},{formId:"0006B464",editorId:"ArmorTeslaPower",name:"Tesla Armor",nonPlayable:!1,dr:43,wg:45,val:820,cnd:1500},{formId:"0008F571",editorId:"ArmorTeslaPowerFX",name:"Tesla Armor",nonPlayable:!1,dr:40,wg:45,val:820,cnd:1500},{formId:"0006B465",editorId:"ArmorTeslaHelmet",name:"Tesla Helmet",nonPlayable:!1,dr:9,wg:5,val:120,cnd:100},{formId:"0003411D",editorId:"MS02SuitAntagonizer",name:"The AntAgonizer's Costume",nonPlayable:!1,dr:20,wg:15,val:120,cnd:100},{formId:"0003411F",editorId:"MS02SuitHelmetAntagonizer",name:"The AntAgonizer's Helmet",nonPlayable:!1,dr:6,wg:5,val:60,cnd:50},{formId:"000CB5FD",editorId:"ArmorUniqueRaider01Helmet",name:"The Devil's Pigtails",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"0003411E",editorId:"MS02SuitMechanist",name:"The Mechanist's Costume",nonPlayable:!1,dr:20,wg:15,val:30,cnd:100},{formId:"00034120",editorId:"MS02SuitHelmetMechanist",name:"The Mechanist's Helmet",nonPlayable:!1,dr:6,wg:5,val:60,cnd:50},{formId:"000C71E1",editorId:"RedRacerLabCoat",name:"The Surgeon's Lab Coat",nonPlayable:!1,dr:2,wg:1,val:30,cnd:100},{formId:"000ACDA4",editorId:"GlassesThreeDog",name:"Three Dog's Glasses",nonPlayable:!1,dr:1,wg:0,val:12,cnd:150},{formId:"00073FEC",editorId:"MQ02ThreeDogsHeadwrap",name:"Three Dog's Head Wrap",nonPlayable:!1,dr:2,wg:0,val:200,cnd:15},{formId:"0001C295",editorId:"GlassesReadingClr",name:"Tinted Reading Glasses",nonPlayable:!1,dr:1,wg:0,val:12,cnd:150},{formId:"000C7C4E",editorId:"ArmorTorcherMask",name:"Torcher's Mask",nonPlayable:!1,dr:2,wg:3,val:20,cnd:15},{formId:"0005C9A1",editorId:"GlassesTortiseshell",name:"Tortiseshell Glasses",nonPlayable:!1,dr:1,wg:0,val:8,cnd:150},{formId:"0002042E",editorId:"OutfitTunnelSnake01",name:"Tunnel Snake Outfit",nonPlayable:!1,dr:4,wg:2,val:8,cnd:100},{formId:"00061D98",editorId:"FollwerOutfitButch",name:"Tunnel Snake Outfit",nonPlayable:!1,dr:4,wg:3,val:40,cnd:100},{formId:"00089B52",editorId:"Underwear",name:"Underwear",nonPlayable:!1,dr:0,wg:1,val:2,cnd:100},{formId:"00083C5C",editorId:"MS09VancesOutfit",name:"Vance's Longcoat Outfit",nonPlayable:!1,dr:10,wg:4,val:100,cnd:100},{formId:"000340F2",editorId:"KIDVaultSuitChild101",name:"Vault 101 Child's Jumpsuit",nonPlayable:!1,dr:1,wg:2,val:5,cnd:100},{formId:"0000431E",editorId:"VaultSuit101",name:"Vault 101 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:8,cnd:100},{formId:"0001CBDD",editorId:"ArmorVault101Security",name:"Vault 101 Security Armor",nonPlayable:!1,dr:12,wg:15,val:70,cnd:100},{formId:"0003411C",editorId:"ArmorVault101SecurityHelmet",name:"Vault 101 Security Helmet",nonPlayable:!1,dr:3,wg:3,val:30,cnd:25},{formId:"000425BA",editorId:"VaultSuit101Utility",name:"Vault 101 Utility Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:10,cnd:100},{formId:"000B73F2",editorId:"VaultSuit106",name:"Vault 106 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"000B73F1",editorId:"VaultSuit108",name:"Vault 108 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"000340EF",editorId:"VaultSuit112",name:"Vault 112 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"000CAFBE",editorId:"VaultSuit77",name:"Vault 77 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"000340ED",editorId:"VaultSuit87",name:"Vault 87 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"000B73F3",editorId:"VaultSuit92",name:"Vault 92 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"0001CBDC",editorId:"VaultLabCoat",name:"Vault Lab Uniform",nonPlayable:!1,dr:2,wg:1,val:6,cnd:100},{formId:"000C7C54",editorId:"ArmorWanderersLeather",name:"Wanderer's Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"000340FE",editorId:"OutfitWastelandDoctor01",name:"Wasteland Doctor Fatigues",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"000CB609",editorId:"OutfitUniqueMerc04",name:"Wasteland Legend Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"00074952",editorId:"KIDOutfitWastelandChild03Hat",name:"Wasteland Scout Hat",nonPlayable:!1,dr:1,wg:1,val:30,cnd:100},{formId:"000340FA",editorId:"KIDOutfitWastelandChild03",name:"Wasteland Scout Uniform",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"0001CBDB",editorId:"OutfitWasteland03",name:"Wasteland Settler Outfit",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"000340FF",editorId:"OutfitWastelandDoctor02",name:"Wasteland Surgeon Outfit",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"0001BA00",editorId:"OutfitWasteland02",name:"Wasteland Wanderer Outfit",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"000CB545",editorId:"ArmorUniqueWastelander",name:"Wastelander's Gear",nonPlayable:!1,dr:12,wg:2,val:50,cnd:100}],M=[{formId:"0002B41B",editorId:"pool10ball",name:"10 Ball",nonPlayable:!1,wg:1,val:2},{formId:"0002B41D",editorId:"pool13ball",name:"13 Ball",nonPlayable:!1,wg:1,val:2},{formId:"0002B415",editorId:"pool2ball",name:"2 Ball",nonPlayable:!1,wg:1,val:2},{formId:"0002B417",editorId:"pool5ball",name:"5 Ball",nonPlayable:!1,wg:1,val:2},{formId:"0002B419",editorId:"pool8ball",name:"8 Ball",nonPlayable:!1,wg:1,val:2},{formId:"00022106",editorId:"AbraxoCleaner",name:"Abraxo Cleaner",nonPlayable:!1,wg:1,val:5},{formId:"00045258",editorId:"MS06ActionAbe",name:"Action Abe Action Figure",nonPlayable:!1,wg:1,val:5},{formId:"000C8503",editorId:"MS08AndroidComponent",name:"Android Component",nonPlayable:!1,wg:0,val:0},{formId:"0006AA59",editorId:"MS02AntResin",name:"Ant Resin",nonPlayable:!1,wg:1,val:3},{formId:"00045252",editorId:"MS06Pennies",name:"Antique Lincoln Coin Collection",nonPlayable:!1,wg:1,val:5},{formId:"000BF20F",editorId:"MS15PrizeVoucher",name:"Archives Prize Voucher",nonPlayable:!1,wg:1,val:0},{formId:"00034057",editorId:"Ashtray",name:"Ashtray",nonPlayable:!1,wg:1,val:1},{formId:"0002B410",editorId:"BaseballGlove",name:"Baseball Glove",nonPlayable:!1,wg:1,val:4},{formId:"0002B40B",editorId:"Baseball01",name:"Baseball",nonPlayable:!1,wg:1,val:2},{formId:"0002B40E",editorId:"Basketball",name:"Basketball",nonPlayable:!1,wg:1,val:1},{formId:"0005B6CA",editorId:"TinCan02",name:"Bent Tin Can",nonPlayable:!1,wg:1,val:1},{formId:"0005B640",editorId:"SpoonBig01",name:"Big Spoon",nonPlayable:!1,wg:1,val:1},{formId:"00003A82",editorId:"MS15BillofRightsRolled",name:"Bill of Rights",nonPlayable:!1,wg:1,val:0},{formId:"000504DA",editorId:"MS10TestTubeFull",name:"Birch's Sap",nonPlayable:!1,wg:1,val:0},{formId:"00028706",editorId:"PassCardBlue",name:"Blue Pass Card",nonPlayable:!1,wg:0,val:1},{formId:"000388E5",editorId:"BobbleheadAGL",name:"Bobblehead - Agility",nonPlayable:!1,wg:0,val:0},{formId:"000388F3",editorId:"BobbleheadBART",name:"Bobblehead - Barter",nonPlayable:!1,wg:0,val:0},{formId:"00038906",editorId:"BobbleheadBGUN",name:"Bobblehead - Big Guns",nonPlayable:!1,wg:0,val:0},{formId:"00038850",editorId:"BobbleheadCHA",name:"Bobblehead - Charisma",nonPlayable:!1,wg:0,val:0},{formId:"00038834",editorId:"BobbleheadEND",name:"Bobblehead - Endurance",nonPlayable:!1,wg:0,val:0},{formId:"0003892F",editorId:"BobbleheadERGW",name:"Bobblehead - Energy Weapons",nonPlayable:!1,wg:0,val:0},{formId:"00038930",editorId:"BobbleheadEXPL",name:"Bobblehead - Explosives",nonPlayable:!1,wg:0,val:0},{formId:"0003885C",editorId:"BobbleheadINT",name:"Bobblehead - Intelligence",nonPlayable:!1,wg:0,val:0},{formId:"00038931",editorId:"BobbleheadLOCK",name:"Bobblehead - Lockpick",nonPlayable:!1,wg:0,val:0},{formId:"000388E6",editorId:"BobbleheadLUK",name:"Bobblehead - Luck",nonPlayable:!1,wg:0,val:0},{formId:"00038950",editorId:"BobbleheadMEDI",name:"Bobblehead - Medicine",nonPlayable:!1,wg:0,val:0},{formId:"00038951",editorId:"BobbleheadMELE",name:"Bobblehead - Melee Weapons",nonPlayable:!1,wg:0,val:0},{formId:"00038833",editorId:"BobbleheadPER",name:"Bobblehead - Perception",nonPlayable:!1,wg:0,val:0},{formId:"00038952",editorId:"BobbleheadREPR",name:"Bobblehead - Repair",nonPlayable:!1,wg:0,val:0},{formId:"00038953",editorId:"BobbleheadSCNC",name:"Bobblehead - Science",nonPlayable:!1,wg:0,val:0},{formId:"00038954",editorId:"BobbleheadSGUN",name:"Bobblehead - Small Guns",nonPlayable:!1,wg:0,val:0},{formId:"00038955",editorId:"BobbleheadSNEK",name:"Bobblehead - Sneak",nonPlayable:!1,wg:0,val:0},{formId:"00038956",editorId:"BobbleheadSPCH",name:"Bobblehead - Speech",nonPlayable:!1,wg:0,val:0},{formId:"00038832",editorId:"BobbleheadSTR",name:"Bobblehead - Strength",nonPlayable:!1,wg:0,val:0},{formId:"00038958",editorId:"BobbleheadUARM",name:"Bobblehead - Unarmed",nonPlayable:!1,wg:0,val:0},{formId:"0000000A",editorId:"Lockpick",name:"Bobby Pin",nonPlayable:!1,wg:0,val:1},{formId:"000250A3",editorId:"SurgicalBonesaw01",name:"Bonesaw",nonPlayable:!1,wg:2,val:5},{formId:"0000000F",editorId:"Caps001",name:"Bottle Cap",nonPlayable:!1,wg:0,val:1},{formId:"0003406F",editorId:"BoxDetergent",name:"Box of Detergent",nonPlayable:!1,wg:1,val:1},{formId:"0003405E",editorId:"SkullBrahmin",name:"Brahmin Skull",nonPlayable:!1,wg:2,val:1},{formId:"0001EDC5",editorId:"FFDCBrotherhoodDogtag",name:"Brotherhood of Steel Holotag",nonPlayable:!1,wg:0,val:1},{formId:"0005B639",editorId:"Knife01",name:"Butter Knife",nonPlayable:!1,wg:1,val:1},{formId:"0005B63A",editorId:"Knife02",name:"Butter Knife",nonPlayable:!1,wg:1,val:1},{formId:"00034062",editorId:"Camera",name:"Camera",nonPlayable:!1,wg:1,val:5},{formId:"0006CA2F",editorId:"MS03LibraryCatalogueHolotape",name:"Card Catalog Holotape",nonPlayable:!1,wg:0,val:0},{formId:"00034068",editorId:"CigaretteCarton",name:"Carton of Cigarettes",nonPlayable:!1,wg:2,val:50},{formId:"000340A0",editorId:"PlateDinnerCeramic",name:"Ceramic Dinner Plate",nonPlayable:!1,wg:1,val:1},{formId:"00048467",editorId:"CG01Rattle",name:"",nonPlayable:!1,wg:1,val:1},{formId:"0003A17D",editorId:"CG01TeddyBear01",name:"",nonPlayable:!1,wg:1,val:1},{formId:"0003FCCE",editorId:"CG01ToyBlock",name:"",nonPlayable:!1,wg:1,val:1},{formId:"00063BF5",editorId:"CG01ToyCar",name:"",nonPlayable:!1,wg:1,val:1},{formId:"000291D7",editorId:"MQ04Chandelier",name:"Chandelier",nonPlayable:!1,wg:14,val:2},{formId:"0003713C",editorId:"FollowersCharonContract",name:"Charon's Employment Contract",nonPlayable:!1,wg:0,val:1},{formId:"00022108",editorId:"CherryBomb",name:"Cherry Bomb",nonPlayable:!1,wg:0,val:5},{formId:"0009A809",editorId:"Chessboard",name:"Chessboard",nonPlayable:!1,wg:1,val:1},{formId:"0005B52C",editorId:"Cigarette01",name:"Cigarette",nonPlayable:!1,wg:0,val:1},{formId:"0004525A",editorId:"MS06DraftPoster",name:"Civil War Draft Poster",nonPlayable:!1,wg:1,val:5},{formId:"00025238",editorId:"Clipboard02",name:"Clipboard",nonPlayable:!1,wg:1,val:1},{formId:"0003406C",editorId:"CoffeeMug01",name:"Coffee Mug",nonPlayable:!1,wg:1,val:1},{formId:"00025421",editorId:"CoffeeKettle",name:"Coffee Pot",nonPlayable:!1,wg:1,val:1},{formId:"0005B5A9",editorId:"MS15SecurityModule",name:"Computer Password Module",nonPlayable:!1,wg:0,val:0},{formId:"00022102",editorId:"Conductor",name:"Conductor",nonPlayable:!1,wg:5,val:30},{formId:"0008C214",editorId:"CapPresConstitutionRolled",name:"Constitution of the United States",nonPlayable:!1,wg:1,val:1},{formId:"0006C55A",editorId:"RRControlCollar",name:"Control Collar",nonPlayable:!1,wg:5,val:1},{formId:"000151DB",editorId:"BrassLanternPasswordAdder",name:"Crumpled Note",nonPlayable:!1,wg:1,val:1},{formId:"0001B01F",editorId:"Crutch",name:"Crutch",nonPlayable:!1,wg:2,val:5},{formId:"0002B41F",editorId:"poolcueball",name:"Cue Ball",nonPlayable:!1,wg:1,val:3},{formId:"0003407B",editorId:"DrinkingGlass01",name:"Cup",nonPlayable:!1,wg:1,val:1},{formId:"0003406E",editorId:"BoardCutting",name:"Cutting Board",nonPlayable:!1,wg:1,val:1},{formId:"0005B635",editorId:"GardenGnomeDestroyed01",name:"Damaged Garden Gnome",nonPlayable:!1,wg:4,val:1},{formId:"000C9403",editorId:"JournalGeneric",name:"Danielle's Book",nonPlayable:!1,wg:1,val:1},{formId:"0002210B",editorId:"DeathclawHand",name:"Deathclaw Hand",nonPlayable:!1,wg:1,val:25},{formId:"00003A7F",editorId:"MS15DeclarationRolled",name:"Declaration of Independence",nonPlayable:!1,wg:1,val:0},{formId:"0005B59F",editorId:"DinnerPlate01",name:"Dinner Plate",nonPlayable:!1,wg:1,val:1},{formId:"00034070",editorId:"BowlDog",name:"Dog Bowl",nonPlayable:!1,wg:1,val:1},{formId:"00070CD4",editorId:"MS18DonovansWrench",name:"Donovan's Wrench",nonPlayable:!1,wg:0,val:75},{formId:"000A8745",editorId:"AWMFFDoorComponent",name:"Door Component",nonPlayable:!1,wg:1,val:1},{formId:"0005B633",editorId:"DrinkingGlass02",name:"Drinking Glass",nonPlayable:!1,wg:1,val:1},{formId:"000604DD",editorId:"Ear",name:"Ear",nonPlayable:!1,wg:0,val:1},{formId:"00025237",editorId:"Clipboard03",name:"Earnings Clipboard",nonPlayable:!1,wg:1,val:1},{formId:"0008C215",editorId:"CapPresEmancRolled",name:"Emancipation Proclamation",nonPlayable:!1,wg:1,val:1},{formId:"00022103",editorId:"NukaColaBottle",name:"Empty Nuka-Cola Bottle",nonPlayable:!1,wg:1,val:2},{formId:"000504D7",editorId:"MS10TestTubeEmpty",name:"Empty Sap Container",nonPlayable:!1,wg:1,val:0},{formId:"0009AA4E",editorId:"SodaBottleEmpty01",name:"Empty Soda Bottle",nonPlayable:!1,wg:1,val:1},{formId:"000250A8",editorId:"SurgicalSyringe01",name:"Empty Syringe",nonPlayable:!1,wg:1,val:5},{formId:"0005B6CE",editorId:"WhiskeyBottle01Empty01",name:"Empty Whisky Bottle",nonPlayable:!1,wg:1,val:1},{formId:"000347DE",editorId:"FFEC09OfficerID",name:"Experimental Rho ID",nonPlayable:!1,wg:0,val:1},{formId:"000BAFBC",editorId:"FactoryID",name:"Factory Employee ID",nonPlayable:!1,wg:0,val:1},{formId:"00025236",editorId:"Clipboard04",name:"Finance Clipboard",nonPlayable:!1,wg:1,val:1},{formId:"000604DE",editorId:"Finger",name:"Finger",nonPlayable:!1,wg:0,val:1},{formId:"00022101",editorId:"FirehoseNozzle",name:"Firehose Nozzle",nonPlayable:!1,wg:1,val:5},{formId:"00033BC6",editorId:"FissionBattery",name:"Fission Battery",nonPlayable:!1,wg:10,val:75},{formId:"00074EE1",editorId:"Flour",name:"Flour",nonPlayable:!1,wg:1,val:2},{formId:"0002D3A5",editorId:"MS03Sanitizer",name:"Food Sanitizer",nonPlayable:!1,wg:7,val:150},{formId:"000250A7",editorId:"SurgicalForceps01",name:"Forceps",nonPlayable:!1,wg:1,val:5},{formId:"0006B192",editorId:"MS15DeclarationRolledForged",name:"Forged Declaration",nonPlayable:!1,wg:1,val:0},{formId:"00034078",editorId:"Fork01",name:"Fork",nonPlayable:!1,wg:.5,val:1},{formId:"0001A168",editorId:"MQ05Fuse",name:"Fuse",nonPlayable:!1,wg:0,val:0},{formId:"00014F81",editorId:"FusionPulseCharge",name:"Fusion Pulse Charge",nonPlayable:!1,wg:0,val:1},{formId:"0003D34D",editorId:"MQ08GECK",name:"G.E.C.K.",nonPlayable:!1,wg:5,val:0},{formId:"0003407A",editorId:"GnomeGarden",name:"Garden Gnome",nonPlayable:!1,wg:5,val:1},{formId:"00040D4D",editorId:"MS18FinGeomapper",name:"Geomapper Module",nonPlayable:!1,wg:1,val:20},{formId:"0008C216",editorId:"CapPresGettysburgRolled",name:"Gettysburg Address",nonPlayable:!1,wg:1,val:1},{formId:"0005B636",editorId:"GlassPitcher01",name:"Glass Pitcher",nonPlayable:!1,wg:1,val:1},{formId:"0005B63F",editorId:"Plate03",name:"Green Plate",nonPlayable:!1,wg:1,val:1},{formId:"0005B637",editorId:"Hammer01",name:"Hammer",nonPlayable:!1,wg:2,val:3},{formId:"0005B638",editorId:"Harmonica01",name:"Harmonica",nonPlayable:!1,wg:1,val:2},{formId:"0005FAE6",editorId:"MS08Note",name:"Holotape",nonPlayable:!1,wg:0,val:0},{formId:"0005516B",editorId:"HotPlate",name:"Hot Plate",nonPlayable:!1,wg:2,val:5},{formId:"0007C121",editorId:"HD00ExplorerTheme",name:"House: Explorer Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C125",editorId:"HD00Jukebox",name:"House: Jukebox",nonPlayable:!1,wg:0,val:500},{formId:"000C7AF0",editorId:"HD00LoveTheme",name:"House: Love Machine Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C128",editorId:"HD00Infirmary",name:"House: My First Infirmary",nonPlayable:!1,wg:0,val:1200},{formId:"0007C127",editorId:"HD00Lab",name:"House: My First Laboratory",nonPlayable:!1,wg:0,val:1200},{formId:"0007C126",editorId:"HD00NukaCola",name:"House: Nuka-Cola Machine",nonPlayable:!1,wg:0,val:500},{formId:"0007C123",editorId:"HD00PreWarTheme",name:"House: Pre-War Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C124",editorId:"HD00RaiderTheme",name:"House: Raider Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C120",editorId:"HD00ScienceTheme",name:"House: Scientist Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C122",editorId:"HD00BoSTheme",name:"House: Vault Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C11D",editorId:"HD00Workbench",name:"House: Workbench",nonPlayable:!1,wg:0,val:500},{formId:"00003AA2",editorId:"MS15Ink",name:"Ink Container",nonPlayable:!1,wg:0,val:0},{formId:"0005B634",editorId:"GardenGnome01",name:"Intact Garden Gnome",nonPlayable:!1,wg:5,val:1},{formId:"00034088",editorId:"Iron",name:"Iron",nonPlayable:!1,wg:5,val:2},{formId:"00045256",editorId:"MS06AssassinationPoster",name:"John Wilkes Booth Wanted Poster",nonPlayable:!1,wg:1,val:5},{formId:"000CAFA2",editorId:"JundersPlunkettFinger",name:"Junders Plunkett's Finger",nonPlayable:!1,wg:0,val:1},{formId:"000270F0",editorId:"MQ04Undies",name:"Lacy Underwear",nonPlayable:!1,wg:0,val:3},{formId:"000A9E6C",editorId:"BurnedBook05",name:"Large Burned Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E6F",editorId:"BurnedBook08",name:"Large Destroyed Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E6D",editorId:"BurnedBook06",name:"Large Ruined Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E6E",editorId:"BurnedBook07",name:"Large Scorched Book",nonPlayable:!1,wg:1,val:1},{formId:"0005B6CD",editorId:"WhiskeyBottle02",name:"Large Whiskey Bottle",nonPlayable:!1,wg:2,val:5},{formId:"0003E56A",editorId:"MS10Liniment",name:"Laurel's Liniment",nonPlayable:!1,wg:1,val:0},{formId:"00025E03",editorId:"LawnmowerBlade",name:"Lawn Mower Blade",nonPlayable:!1,wg:2,val:10},{formId:"00022100",editorId:"LeafBlower",name:"Leaf Blower",nonPlayable:!1,wg:2,val:15},{formId:"0002210C",editorId:"LeatherBelt",name:"Leather Belt",nonPlayable:!1,wg:1,val:5},{formId:"00028EE9",editorId:"MS06Poster",name:"Lincoln Memorial Poster",nonPlayable:!1,wg:1,val:0},{formId:"00045254",editorId:"MS06LincolnDiary",name:"Lincoln's Diary",nonPlayable:!1,wg:1,val:5},{formId:"00028EE6",editorId:"MS06Recording",name:"Lincoln's Voice",nonPlayable:!1,wg:2,val:5},{formId:"0002EDFB",editorId:"MS01Lucky8ball",name:"Lucky 8 Ball",nonPlayable:!1,wg:1,val:4},{formId:"0001890A",editorId:"MS09SealedEnvelope",name:"Lucy's Sealed Envelope",nonPlayable:!1,wg:0,val:0},{formId:"00022107",editorId:"Lunchbox",name:"Lunchbox",nonPlayable:!1,wg:1,val:3},{formId:"00003A80",editorId:"MS15MagnaCartaRolled",name:"Magna Carta",nonPlayable:!1,wg:1,val:0},{formId:"0006CA30",editorId:"MS03LibraryArchivesHolotape",name:"Media Archives Holotape",nonPlayable:!1,wg:0,val:0},{formId:"0002210D",editorId:"MedicalBrace",name:"Medical Brace",nonPlayable:!1,wg:2,val:10},{formId:"0003A73A",editorId:"MedicalBraceNew",name:"Medical Brace",nonPlayable:!1,wg:2,val:1},{formId:"00025235",editorId:"Clipboard01",name:"Medical Clipboard",nonPlayable:!1,wg:1,val:1},{formId:"0003409C",editorId:"PanCookingMetal",name:"Metal Cooking Pan",nonPlayable:!1,wg:1,val:5},{formId:"000340A7",editorId:"PotCookingMetal",name:"Metal Cooking Pot",nonPlayable:!1,wg:1,val:1},{formId:"000340BC",editorId:"Spoon01",name:"Metal Spoon",nonPlayable:!1,wg:.5,val:1},{formId:"0002920F",editorId:"MetroTicket",name:"Metro Ticket",nonPlayable:!1,wg:0,val:1},{formId:"000391B1",editorId:"MilitaryID",name:"Military ID",nonPlayable:!1,wg:0,val:1},{formId:"000296C0",editorId:"MQ04Brochure",name:"Military School Brochure",nonPlayable:!1,wg:0,val:0},{formId:"0005B63B",editorId:"Milkbottle01",name:"Milk Bottle",nonPlayable:!1,wg:1,val:1},{formId:"0003BD33",editorId:"MQ09FEVVial",name:"Modified FEV Virus",nonPlayable:!1,wg:1,val:0},{formId:"0008C217",editorId:"CapPresMonroeRolled",name:"Monroe Doctrine",nonPlayable:!1,wg:1,val:1},{formId:"000220FB",editorId:"MotorcycleGasTank",name:"Motorcycle Gas Tank",nonPlayable:!1,wg:5,val:25},{formId:"000220FE",editorId:"MotorcycleHandbrake",name:"Motorcycle Handbrake",nonPlayable:!1,wg:1,val:15},{formId:"00022419",editorId:"MS15MuseumToken",name:"Museum Token",nonPlayable:!1,wg:0,val:1},{formId:"0006EEE7",editorId:"BodyPart01",name:"Mutilated Arm",nonPlayable:!1,wg:2,val:0},{formId:"0006F2D8",editorId:"BodyPart02",name:"Mutilated Leg",nonPlayable:!1,wg:2,val:0},{formId:"0006F2D9",editorId:"BodyPart03",name:"Mutilated Organs",nonPlayable:!1,wg:2,val:0},{formId:"00074170",editorId:"BodyPart05",name:"Mutilated Skull",nonPlayable:!1,wg:2,val:0},{formId:"0006F2DA",editorId:"BodyPart04",name:"Mutilated Torso",nonPlayable:!1,wg:2,val:0},{formId:"000CADE6",editorId:"MS05NukaColaDisk",name:"Nuka-Cola Clear Formula",nonPlayable:!1,wg:1,val:150},{formId:"00029171",editorId:"NukaTruck",name:"Nuka-Cola Truck",nonPlayable:!1,wg:2,val:5},{formId:"00030663",editorId:"MS03Observer",name:"Observer",nonPlayable:!1,wg:1,val:0},{formId:"0003997E",editorId:"OfficeID",name:"Office Employee ID",nonPlayable:!1,wg:0,val:1},{formId:"0005F183",editorId:"Opthalmoscope",name:"Opthalmoscope",nonPlayable:!1,wg:1,val:4},{formId:"00034069",editorId:"CigarettePack",name:"Pack of Cigarettes",nonPlayable:!1,wg:.5,val:10},{formId:"0002210E",editorId:"PaintGun",name:"Paint Gun",nonPlayable:!1,wg:5,val:15},{formId:"0003409D",editorId:"Paperweight",name:"Paperweight",nonPlayable:!1,wg:1,val:1},{formId:"0005B63C",editorId:"Pencil01",name:"Pencil",nonPlayable:!1,wg:0,val:1},{formId:"000220FC",editorId:"PilotLight",name:"Pilot Light",nonPlayable:!1,wg:1,val:14},{formId:"000340A4",editorId:"Plunger",name:"Plunger",nonPlayable:!1,wg:1,val:1},{formId:"0002B412",editorId:"PoolBall",name:"Pool Ball",nonPlayable:!1,wg:1,val:2},{formId:"0002541B",editorId:"BigPot",name:"Pot",nonPlayable:!1,wg:2,val:0},{formId:"00022113",editorId:"PressureCooker",name:"Pressure Cooker",nonPlayable:!1,wg:5,val:15},{formId:"000943F2",editorId:"PreWarBook",name:"Pre-War Book",nonPlayable:!1,wg:1,val:5},{formId:"000C5D24",editorId:"BookGeneric01",name:"Pre-War Book",nonPlayable:!1,wg:1,val:1},{formId:"00034067",editorId:"PrewarMoney",name:"Pre-war Money",nonPlayable:!1,wg:0,val:10},{formId:"0002210F",editorId:"RadscorpionPoisonGland",name:"Radscorpion Poison Gland",nonPlayable:!1,wg:1,val:30},{formId:"000340AD",editorId:"Rake",name:"Rake",nonPlayable:!1,wg:2,val:1},{formId:"00028704",editorId:"PassCardRed",name:"Red Pass Card",nonPlayable:!1,wg:0,val:1},{formId:"0005B63E",editorId:"Plate02",name:"Red Plate",nonPlayable:!1,wg:1,val:1},{formId:"0002D3B3",editorId:"MS03HistoryHolotape",name:"Rivet City Historical Record",nonPlayable:!1,wg:1,val:0},{formId:"0002D3B4",editorId:"MS03TelemetryUnit",name:"RobCo Processor Widget",nonPlayable:!1,wg:1,val:0},{formId:"000285F8",editorId:"MQ04RollerSkate",name:"Rollerskate",nonPlayable:!1,wg:1,val:4},{formId:"000250A5",editorId:"SurgicalScalpel01",name:"Scalpel",nonPlayable:!1,wg:1,val:5},{formId:"000BAFFB",editorId:"SchematicsBottlecapMineItem",name:"Schematics - Bottlecap Mine",nonPlayable:!1,wg:0,val:300},{formId:"000BAFFA",editorId:"SchematicsDartGunItem",name:"Schematics - Dart Gun",nonPlayable:!1,wg:0,val:500},{formId:"000BAFFC",editorId:"SchematicsDeathclawGauntletItem",name:"Schematics - Deathclaw Gauntlet",nonPlayable:!1,wg:0,val:800},{formId:"000BAFFD",editorId:"SchematicsNukaCocktailItem",name:"Schematics - Nuka-Grenade",nonPlayable:!1,wg:0,val:300},{formId:"000BAFFE",editorId:"SchematicsRailwayRifleItem",name:"Schematics - Railway Rifle",nonPlayable:!1,wg:0,val:800},{formId:"000BAFFF",editorId:"SchematicsRockItLauncherItem",name:"Schematics - Rock-It Launcher",nonPlayable:!1,wg:0,val:800},{formId:"000BB000",editorId:"SchematicsShishkebabItem",name:"Schematics - Shishkebab",nonPlayable:!1,wg:0,val:500},{formId:"000250A4",editorId:"SurgicalScissors01",name:"Scissors",nonPlayable:!1,wg:1,val:3},{formId:"00031944",editorId:"SpareParts",name:"Scrap Metal",nonPlayable:!1,wg:1,val:1},{formId:"00022109",editorId:"SensorModule",name:"Sensor Module",nonPlayable:!1,wg:2,val:30},{formId:"0006835F",editorId:"MS17FinSheetMusicBook",name:"Sheet Music Book",nonPlayable:!1,wg:1,val:100},{formId:"000340B5",editorId:"ShotGlass01",name:"Shot glass",nonPlayable:!1,wg:1,val:1},{formId:"00022FF0",editorId:"MS13CollarMiscObj",name:"Slave Collar",nonPlayable:!1,wg:1,val:0},{formId:"000A9E70",editorId:"BurnedBook01",name:"Small Burned Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E6B",editorId:"BurnedBook04",name:"Small Destroyed Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E69",editorId:"BurnedBook02",name:"Small Ruined Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E6A",editorId:"BurnedBook03",name:"Small Scorched Book",nonPlayable:!1,wg:1,val:1},{formId:"000033FF",editorId:"MS17SoilStrad",name:"Soil Stradivarius",nonPlayable:!1,wg:3,val:0},{formId:"000340BB",editorId:"Spatula01",name:"Spatula",nonPlayable:!1,wg:1,val:1},{formId:"0005B641",editorId:"Spork01",name:"Spork",nonPlayable:!1,wg:.5,val:1},{formId:"00022112",editorId:"SteamGaugeAssembly",name:"Steam Gauge Assembly",nonPlayable:!1,wg:10,val:25},{formId:"00022111",editorId:"SurgicalTubing",name:"Surgical Tubing",nonPlayable:!1,wg:1,val:10},{formId:"0001F21F",editorId:"TeddyBear01",name:"Teddy Bear",nonPlayable:!1,wg:1,val:3},{formId:"00022104",editorId:"TinCan01",name:"Tin Can",nonPlayable:!1,wg:1,val:1},{formId:"0002541C",editorId:"Plate04",name:"Tin Plate",nonPlayable:!1,wg:1,val:1},{formId:"0009A807",editorId:"ToasterPostwar",name:"Toaster",nonPlayable:!1,wg:3,val:5},{formId:"0009A808",editorId:"ToasterPrewar",name:"Toaster",nonPlayable:!1,wg:3,val:5},{formId:"00022110",editorId:"ToyCar",name:"Toy Car",nonPlayable:!1,wg:1,val:5},{formId:"0002C5F6",editorId:"poolTriangle",name:"Triangle",nonPlayable:!1,wg:1,val:1},{formId:"00022105",editorId:"Turpentine",name:"Turpentine",nonPlayable:!1,wg:2,val:10},{formId:"000250A6",editorId:"SurgicalTweasers01",name:"Tweezers",nonPlayable:!1,wg:1,val:3},{formId:"0008C219",editorId:"CapPresDecWarChinaRolled",name:"U.S. Declaration of War on China",nonPlayable:!1,wg:1,val:1},{formId:"0008C218",editorId:"CapPresDecWarGermanyRolled",name:"U.S. Declaration of War on Germany",nonPlayable:!1,wg:1,val:1},{formId:"00039B5F",editorId:"UtilityID",name:"Utility Worker ID",nonPlayable:!1,wg:0,val:1},{formId:"000220FF",editorId:"VacuumCleaner",name:"Vacuum Cleaner",nonPlayable:!1,wg:10,val:20},{formId:"0001CFAF",editorId:"MS09VancesProposal",name:"Vance's Proposal",nonPlayable:!1,wg:0,val:0},{formId:"0002393C",editorId:"MQ02VirgoIIDish",name:"Virgo II Dish",nonPlayable:!1,wg:1,val:0},{formId:"0005A795",editorId:"xMS03survivalGuideBookItem",name:"Wasteland Survival Guide",nonPlayable:!1,wg:2,val:1},{formId:"0005B6CB",editorId:"WhetStone01",name:"Whet Stone",nonPlayable:!1,wg:2,val:1},{formId:"0005B63D",editorId:"Plate01",name:"White Plate",nonPlayable:!1,wg:1,val:1},{formId:"0002210A",editorId:"WonderGlue",name:"Wonderglue",nonPlayable:!1,wg:1,val:10},{formId:"0007CBCC",editorId:"WoodChipper",name:"Wood Chipper",nonPlayable:!1,wg:50,val:25},{formId:"0005B6D0",editorId:"Wrench01",name:"Wrench",nonPlayable:!1,wg:1,val:1},{formId:"0005A6CE",editorId:"MS10RewardBearCharm",name:"Yew's Bear Charm",nonPlayable:!1,wg:1,val:50}],A=[{formId:"00031DBA",editorId:"ActionBoy",name:"Action Boy",description:"With the Action Boy perk, you gain an additional 25 Action Points to use in V.A.T.S.",maxRanks:1,nonPlayable:!1},{formId:"0007B202",editorId:"ActionGirl",name:"Action Girl",description:"With the Action Girl perk, you gain an additional 25 Action Points to use in V.A.T.S.",maxRanks:1,nonPlayable:!1},{formId:"00094EC4",editorId:"AdamantiumSkeleton",name:"Adamantium Skeleton",description:"With the Adamantium Skeleton perk, your limbs only receive 50% of the damage they normally would.",maxRanks:1,nonPlayable:!1},{formId:"00031DB5",editorId:"AnimalFriend",name:"Animal Friend",description:"At the first rank of this perk, animals simply won't attack. At the second rank, they will actually come to your aid in combat, but never against another animal. This perk affects the Dog, Yao Guai, Mole Rat, and Brahmin. ",maxRanks:2,nonPlayable:!1},{formId:"000C1A6B",editorId:"MS04StrengthPerk",name:"Ant Might",description:"Your body has been genetically enhanced with the strength and flame resistance of the Grayditch Fire Ants! Your Strength has increased by 1 and you are now 25% resistant to fire.",maxRanks:1,nonPlayable:!1},{formId:"000C1A6C",editorId:"MS04PerceptionPerk",name:"Ant Sight",description:"Your body has been genetically enhanced with the perception and flame resistance of the Grayditch Fire Ants! Your Perception has increased by 1 and you are now 25% resistant to fire.",maxRanks:1,nonPlayable:!1},{formId:"00035E04",editorId:"MS10Barkskin",name:"Barkskin",description:"You've been exposed to Harold's mutation and your skin is now as hard as tree bark. As a result, you've gained a permanent +5% to Damage Resistance.",maxRanks:1,nonPlayable:!1},{formId:"00031DBB",editorId:"BetterCriticals",name:"Better Criticals",description:"With the Better Criticals perk, you gain a 50% damage bonus every time a critical hit is scored on an opponent.",maxRanks:1,nonPlayable:!1},{formId:"00094EB8",editorId:"BlackWidow",name:"Black Widow",description:"In combat, you do +10% damage against male opponents. Outside of combat, you'll sometimes have access to unique dialogue options when dealing with the opposite sex. ",maxRanks:1,nonPlayable:!1},{formId:"00094EBA",editorId:"BloodyMess",name:"Bloody Mess",description:"With the Bloody Mess perk, characters and creatures you kill will often explode into a red, gut-ridden, eyeball-strewn paste. Fun! Oh, and you'll do 5% extra damage with all weapons.",maxRanks:1,nonPlayable:!1},{formId:"00094EBC",editorId:"Cannibal",name:"Cannibal",description:"With the Cannibal perk, when you're in Sneak mode, you gain the option to eat a corpse to regain Health. But every time you feed, you lose Karma, and if the act is witnessed, it is considered a crime against nature.",maxRanks:1,nonPlayable:!1},{formId:"00099827",editorId:"ChemResistant",name:"Chem Resistant",description:"Having the Chem Resistant perk means you're 50% less likely to develop an addiction to chems, like Psycho or Jet.",maxRanks:1,nonPlayable:!1},{formId:"0009982D",editorId:"Chemist",name:"Chemist",description:"With the Chemist perk, any chems you take last twice as long.",maxRanks:1,nonPlayable:!1},{formId:"00003142",editorId:"ChildAtHeart",name:"Child at Heart",description:"The Child at Heart perk greatly improves your interactions with children, usually in the form of unique dialogue choices.",maxRanks:1,nonPlayable:!1},{formId:"00099828",editorId:"Commando",name:"Commando",description:"While using a rifle (or similar two-handed weapon), your accuracy in V.A.T.S. is significantly increased.",maxRanks:1,nonPlayable:!1},{formId:"00031DE1",editorId:"Comprehension",name:"Comprehension",description:"With the Comprehension perk, you gain one additional skill point whenever a skill book is read.",maxRanks:1,nonPlayable:!1},{formId:"00031DC4",editorId:"ComputerWhiz",name:"Computer Whiz",description:"Fail a hack attempt and get locked out of a computer? Not if you're a Computer Whiz! With this perk, you can attempt to re-hack any computer you were previously locked out of.",maxRanks:1,nonPlayable:!1},{formId:"00044CAF",editorId:"ConcentratedFire",name:"Concentrated Fire",description:"With Concentrated Fire, your accuracy to hit any body part in V.A.T.S. increases slightly with each subsequent hit on that body part.",maxRanks:1,nonPlayable:!1},{formId:"00044CA8",editorId:"ContractKiller",name:"Contract Killer",description:"Once you have the Contract Killer perk, any good character you kill will have an ear on their corpse. This ear can then be sold to a certain person (whose identity is disclosed when you take the perk) for caps and negative Karma. ",maxRanks:1,nonPlayable:!1},{formId:"00044CAB",editorId:"Cyborg",name:"Cyborg",description:"You've made permanent enhancements to your body! The Cyborg perk instantly adds +10% to your Damage, Poison, and Radiation Resistances, and 10 points to the Energy Weapons skill.",maxRanks:1,nonPlayable:!1},{formId:"00044948",editorId:"DaddysBoy",name:"Daddy's Boy",description:"Just like dear old Dad, you've devoted your time to intellectual pursuits. You gain an additional 5 points to both the Science and Medicine skills.",maxRanks:3,nonPlayable:!1},{formId:"00069310",editorId:"DaddysGirl",name:"Daddy's Girl",description:"Just like dear old Dad, you've devoted your time to intellectual pursuits. You gain an additional 5 points to both the Science and Medicine skills.",maxRanks:3,nonPlayable:!1},{formId:"00031DAB",editorId:"DemolitionExpert",name:"Demolition Expert",description:"With each rank of this perk, all of your explosive weapons do an additional 20% damage. ",maxRanks:3,nonPlayable:!1},{formId:"00030FEB",editorId:"MS03DreamCrusherPerk",name:"Dream Crusher",description:"Something about your presence dampens others' desires to exceed. Any enemy's chance of getting critical hits on you is reduced by 50%. ",maxRanks:1,nonPlayable:!1},{formId:"00031DD8",editorId:"Educated",name:"Educated",description:"With the Educated perk, you gain three more skill points every time you advance in level. This perk is best taken early on, to maximize its effectiveness.",maxRanks:1,nonPlayable:!1},{formId:"00031DD9",editorId:"Entomologist",name:"Entomologist",description:"With the Entomologist perk, you do an additional +50% damage every time you attack a mutated insect, like the Radroach, Giant Ant, or Radscorpion.",maxRanks:1,nonPlayable:!1},{formId:"00031DE5",editorId:"Explorer",name:"Explorer",description:"When you choose the Explorer perk, every location in the world is revealed on your map. So get out there and explore!",maxRanks:1,nonPlayable:!1},{formId:"00094EBF",editorId:"FastMetabolism",name:"Fast Metabolism",description:"With the Fast Metabolism perk, you gain a 20% Health bonus when using Stimpaks.",maxRanks:1,nonPlayable:!1},{formId:"00094EC1",editorId:"Finesse",name:"Finesse",description:"With the Finesse perk, you have a higher chance to score a critical hit on an opponent in combat, equivalent to 5 extra points of Luck.",maxRanks:1,nonPlayable:!1},{formId:"00031DE3",editorId:"FortuneFinder",name:"Fortune Finder",description:"With the Fortune Finder perk, you'll find considerably more Nuka-Cola caps in containers than you normally would. ",maxRanks:1,nonPlayable:!1},{formId:"00099834",editorId:"GrimReaperSprint",name:"Grim Reaper's Sprint",description:"If you kill a target in V.A.T.S., all your Action Points are restored upon exiting V.A.T.S.",maxRanks:1,nonPlayable:!1},{formId:"0004494E",editorId:"GunNut",name:"Gun Nut",description:"You're obsessed with using and maintaining a wide variety of conventional firearms. With each rank of the Gun Nut perk, you gain an additional 5 points to the Small Guns and Repair skills.",maxRanks:3,nonPlayable:!1},{formId:"00094EBB",editorId:"Gunslinger",name:"Gunslinger",description:"While using a pistol (or similar one-handed weapon), your accuracy in V.A.T.S. is significantly increased.",maxRanks:1,nonPlayable:!1},{formId:"00003131",editorId:"MS09Hematophage",name:"Hematophage",description:"This perk allows you to regain health by consuming Bloodpacks.",maxRanks:1,nonPlayable:!1},{formId:"00031DAC",editorId:"HereandNow",name:"Here and Now",description:"The Here and Now perk immediately grants an additional experience level, complete with all the advantages that brings.",maxRanks:1,nonPlayable:!1},{formId:"00044CAD",editorId:"ImpartialMediation",name:"Impartial Mediation",description:"With the Impartial Mediation perk, you gain an extra 30 points to Speech... so long as you maintain a Neutral Karma level.",maxRanks:1,nonPlayable:!1},{formId:"00044CB0",editorId:"Infiltrator",name:"Infiltrator",description:'With Infiltrator, if a lock is broken, and can\'t normally be picked again, you can attempt to pick it again one more time. This includes locks previously broken by a "Force Lock" attempt.',maxRanks:1,nonPlayable:!1},{formId:"00044CB1",editorId:"IntenseTraining",name:"Intense Training",description:"With the Intense Training perk, you can put a single point into any of your S.P.E.C.I.A.L. attributes.",maxRanks:10,nonPlayable:!1},{formId:"00031DDB",editorId:"IronFist",name:"Iron Fist",description:"With the Iron Fist perk, you do an additional 5 points of Unarmed damage per rank.",maxRanks:3,nonPlayable:!1},{formId:"0002D3A2",editorId:"MS03Perk1A",name:"Junior Survivor",description:"You've been tested in some of the most dangerous parts of the wastes, and you're still alive to tell the tale. You've gained +2% bonus to Poison Resistance and Radiation Resistance, and +5 points to maximum Health.",maxRanks:1,nonPlayable:!1},{formId:"000331D4",editorId:"MS03Perk1B",name:"Junior Survivor",description:"You've been tested in some of the most dangerous parts of the wastes, and you're still alive to tell the tale. You've gained +2% bonus to Poison Resistance and Radiation Resistance, and 2 points to both the Medicine and Science skills.",maxRanks:1,nonPlayable:!1},{formId:"000331D5",editorId:"MS03Perk1C",name:"Junior Survivor",description:"You've been tested in some of the most dangerous parts of the wastes, and you're still alive to tell the tale. You've gained +2% bonus to Poison Resistance, Radiation Resistance and Damage Resistance.",maxRanks:1,nonPlayable:!1},{formId:"000331D6",editorId:"MS03Perk1D",name:"Junior Survivor",description:"You've been tested in some of the most dangerous parts of the wastes, and you're still alive to tell the tale. You've gained +2% bonus to Poison Resistance & Radiation Resistance, and 2 points to both the Speech and Sneak skills.",maxRanks:1,nonPlayable:!1},{formId:"000331D7",editorId:"MS03Perk1E",name:"Junior Survivor",description:"You've been tested in some of the most dangerous parts of the wastes, and you're still alive to tell the tale. You've gained +2% bonus to Poison Resistance and Radiation Resistance, and a +1% bonus to Critical Chance.",maxRanks:1,nonPlayable:!1},{formId:"00094EB9",editorId:"LadyKiller",name:"Lady Killer",description:"In combat, you do +10% damage against female opponents. Outside of combat, you'll sometimes have access to unique dialogue options when dealing with the opposite sex. ",maxRanks:1,nonPlayable:!1},{formId:"00044CAC",editorId:"Lawbringer",name:"Lawbringer",description:"Once you have the Lawbringer perk, any evil character you kill will have a finger on their corpse. This finger can then be sold to a certain person (whose identity is disclosed when you take the perk) for caps and positive Karma. ",maxRanks:1,nonPlayable:!1},{formId:"00044CA9",editorId:"LeadBelly",name:"Lead Belly",description:"With the Lead Belly perk, you take 50% less radiation every time you drink from an irradiated water source.",maxRanks:1,nonPlayable:!1},{formId:"00031DB1",editorId:"LifeGiver",name:"Life Giver",description:"With the Life Giver perk, you gain an additional 30 Hit Points.",maxRanks:1,nonPlayable:!1},{formId:"00031DB7",editorId:"LightStep",name:"Light Step",description:"With the Light Step perk, you'll never set off an enemy's mines or floor-based traps.",maxRanks:1,nonPlayable:!1},{formId:"00014B97",editorId:"LittleLeaguer",name:"Little Leaguer",description:"Years as the Vault little league MVP have honed your hitting and throwing. With every rank, you gain 5 points of Melee Weapons skill and 5 points of Explosives skill.",maxRanks:3,nonPlayable:!1},{formId:"00031DB8",editorId:"MasterTrader",name:"Master Trader",description:"When you take the Master Trader perk, the price of every item you buy from a vendor is reduced by 25%.",maxRanks:1,nonPlayable:!1},{formId:"00031DAD",editorId:"MisterSandman",name:"Mister Sandman",description:"With the Mister Sandman perk, when you're in Sneak mode, you gain the option to silently kill any human or Ghoul while they're sleeping. And, all Mister Sandman kills earn bonus XP.",maxRanks:1,nonPlayable:!1},{formId:"00031DBC",editorId:"MysteriousStranger",name:"Mysterious Stranger",description:"You've gained your own personal guardian angel... armed with a fully loaded .44 Magnum. With this perk, the Mysterious Stranger will appear occasionally in V.A.T.S. mode to lend a hand, with deadly efficiency.",maxRanks:1,nonPlayable:!1},{formId:"00044CA7",editorId:"NerdRage",name:"Nerd Rage!",description:"You've been pushed around long enough! With the Nerd Rage! perk, your Strength is raised to 10 and you gain 50% to damage resistance whenever your Health drops to 20% or below.",maxRanks:1,nonPlayable:!1},{formId:"00094EBD",editorId:"NightPerson",name:"Night Person",description:'When the sun is down, a Night Person gains +2 to both Intelligence and Perception (up to a maximum of 10). This perk directly affects your "internal clock," and remains active both inside and outside.',maxRanks:1,nonPlayable:!1},{formId:"00031DCC",editorId:"Ninja",name:"Ninja",description:"The Ninja perk grants you the power of the fabled shadow warriors. When attacking with either Melee or Unarmed, you gain a +15% critical chance on every strike. Sneak attack criticals do 25% more damage than normal.",maxRanks:1,nonPlayable:!1},{formId:"00044CAA",editorId:"ParalyzingPalm",name:"Paralyzing Palm",description:"With Paralyzing Palm, you will sometimes perform a special V.A.T.S. palm strike that paralyzes your opponent for 30 seconds. Note that in order to perform the Paralyzing Palm, you must be completely unarmed.",maxRanks:1,nonPlayable:!1},{formId:"00058FDF",editorId:"PowerArmorTraining",name:"Power Armor Training",description:"You have received the specialized training needed to move in any form of Power Armor.",maxRanks:1,nonPlayable:!1},{formId:"0006835C",editorId:"PsychoPerk",name:"",description:"",maxRanks:1,nonPlayable:!1},{formId:"00031DB2",editorId:"Pyromaniac",name:"Pyromaniac",description:"With the Pyromaniac perk, you do +50% damage with fire-based weapons, like the Flamer and Shishkebab.",maxRanks:1,nonPlayable:!1},{formId:"0003066B",editorId:"MS03MutationPerk",name:"Rad Regeneration",description:"After an experimental treatment, intense radiation keeps your body operating at peak performance regardless of crippling injuries... right up until death. When you suffer from Advanced Radiation Poisoning, crippled limbs automatically regenerate.",maxRanks:1,nonPlayable:!1},{formId:"00031DA9",editorId:"RadResistance",name:"Rad Resistance",description:"Rad Resistance allows you to -- what else? -- resist radiation. This perk grants an additional 25% to Radiation Resistance.",maxRanks:1,nonPlayable:!1},{formId:"00031DC2",editorId:"RoboticsExpert",name:"Robotics Expert",description:"With the Robotics perk, you do an additional 25% damage to any robot. But, even better, sneaking up on a hostile robot undetected and activating it will put that robot into a permanent shutdown state.",maxRanks:1,nonPlayable:!1},{formId:"00044CA6",editorId:"Scoundrel",name:"Scoundrel",description:"Take the Scoundrel perk, and you can use your wily charms to influence people -- each rank raises your Speech and Barter skills by 5 points.",maxRanks:3,nonPlayable:!1},{formId:"00031DAA",editorId:"Scrounger",name:"Scrounger",description:"With the Scrounger perk, you'll find considerably more ammunition in containers than you normally would. ",maxRanks:1,nonPlayable:!1},{formId:"00031DB3",editorId:"SilentRunning",name:"Silent Running",description:"With the Silent Running perk, you gain an additional 10 points to Sneak, and running no longer factors into a successful sneak attempt.",maxRanks:1,nonPlayable:!1},{formId:"0009982E",editorId:"SizeMatters",name:"Size Matters",description:"You're obsessed with really big weapons. With each rank of this perk, you gain an additional 15 points to the Big Guns skill.",maxRanks:3,nonPlayable:!1},{formId:"00031DB4",editorId:"Sniper",name:"Sniper",description:"With the Sniper perk, your chance to hit an opponent's head in V.A.T.S. is significantly increased.",maxRanks:1,nonPlayable:!1},{formId:"00031DC5",editorId:"SolarPowered",name:"Solar Powered",description:"With the Solar Powered perk, you gain an additional 2 points to Strength when in direct sunlight, and slowly regenerate lost Health.",maxRanks:1,nonPlayable:!1},{formId:"00031DDE",editorId:"StrongBack",name:"Strong Back",description:"With the Strong Back perk, you can carry 50 more pounds of equipment.",maxRanks:1,nonPlayable:!1},{formId:"0002D3A1",editorId:"MS03Perk2A",name:"Survival Expert",description:"You've been tested in some of the most dangerous parts of the wastes, and you've not only survived - you've learned a few things. You've gained +4% bonus to Poison Resistance and Radiation Resistance, and +10 points to maximum Health.",maxRanks:1,nonPlayable:!1},{formId:"000331D8",editorId:"MS03Perk2B",name:"Survival Expert",description:"You've been tested in some of the most dangerous parts of the wastes, and you've not only survived - you've learned a few things. You've gained +4% bonus to Poison Resistance and Radiation Resistance, and 4 points to both the Medicine and Science skills.",maxRanks:1,nonPlayable:!1},{formId:"000331D9",editorId:"MS03Perk2C",name:"Survival Expert",description:"You've been tested in some of the most dangerous parts of the wastes, and you've not only survived - you've learned a few things. You've gained +4% bonus to Poison Resistance, Radiation Resistance and Damage Resistance.",maxRanks:1,nonPlayable:!1},{formId:"000331DA",editorId:"MS03Perk2D",name:"Survival Expert",description:"You've been tested in some of the most dangerous parts of the wastes, and you've not only survived - you've learned a few things. You've gained +4% bonus to Poison Resistance & Radiation Resistance, and 4 points to both the Speech and Sneak skills.",maxRanks:1,nonPlayable:!1},{formId:"000331DB",editorId:"MS03Perk2E",name:"Survival Expert",description:"You've been tested in some of the most dangerous parts of the wastes, and you've not only survived - you've learned a few things. You've gained +4% bonus to Poison Resistance and Radiation Resistance, and a +2% bonus to Critical Chance.",maxRanks:1,nonPlayable:!1},{formId:"0002D3A0",editorId:"MS03Perk3A",name:"Survival Guru",description:"You wrote the book on how to survive in the Wasteland, and have shared your secrets with humanity. You've gained +6% bonus to Poison Resistance and Radiation Resistance, and +15 points to maximum Health.",maxRanks:1,nonPlayable:!1},{formId:"000331DC",editorId:"MS03Perk3B",name:"Survival Guru",description:"You wrote the book on how to survive in the Wasteland, and have shared your secrets with humanity. You've gained +6% bonus to Poison Resistance and Radiation Resistance, and 6 points to both the Medicine and Science skills.",maxRanks:1,nonPlayable:!1},{formId:"000331DD",editorId:"MS03Perk3C",name:"Survival Guru",description:"You wrote the book on how to survive in the Wasteland, and have shared your secrets with humanity. You've gained +6% bonus to Poison Resistance, Radiation Resistance and Damage Resistance.",maxRanks:1,nonPlayable:!1},{formId:"000331DE",editorId:"MS03Perk3D",name:"Survival Guru",description:"You wrote the book on how to survive in the Wasteland, and have shared your secrets with humanity. You've gained +6% bonus to Poison Resistance & Radiation Resistance, and 6 points to both the Speech and Sneak skills.",maxRanks:1,nonPlayable:!1},{formId:"000331DF",editorId:"MS03Perk3E",name:"Survival Guru",description:"You wrote the book on how to survive in the Wasteland, and have shared your secrets with humanity. You've gained +6% bonus to Poison Resistance & Radiation Resistance, and +3% bonus to Critical Chance.",maxRanks:1,nonPlayable:!1},{formId:"00031DD3",editorId:"SwiftLearner",name:"Swift Learner",description:"With each rank in the Swift Learner perk, you gain an additional 10% to total Experience Points whenever Experience Points are earned.",maxRanks:3,nonPlayable:!1},{formId:"00031DBD",editorId:"Tag",name:"Tag!",description:"The Tag! perk allows you to select a fourth Skill to be a Tag skill, which instantly raises it by 15 points.",maxRanks:1,nonPlayable:!1},{formId:"00031DD6",editorId:"Thief",name:"Thief",description:"With each rank of the Thief perk, you gain an immediate bonus of 5 points to both the Sneak and Lockpick skills.",maxRanks:3,nonPlayable:!1},{formId:"00031DE0",editorId:"Toughness",name:"Toughness",description:"With the Toughness perk, you gain +10% to overall Damage Resistance, up to the maximum of 85%. ",maxRanks:1,nonPlayable:!1},{formId:"00061822",editorId:"WellRestedPerk",name:"Well Rested",description:"After sleeping in a safe bed, you will wake well rested. You earn 10% more experience points for several hours.",maxRanks:1,nonPlayable:!1},{formId:"00024D5C",editorId:"MS08RewardPerk",name:"Wired Reflexes",description:"Advanced technology from the Commonwealth has increased your reaction speed, giving you a higher chance to hit in V.A.T.S.",maxRanks:1,nonPlayable:!1},{formId:"000770CC",editorId:"YaoGuaiMeatPerk",name:"",description:"",maxRanks:1,nonPlayable:!1}].filter(e=>e.name&&e.description).map((e,t)=>({id:t+1,name:e.name,description:e.description,value:0})),D=[{id:1,name:"Barter",description:"Improves buying and selling prices.",value:0},{id:2,name:"Big Guns",description:"Accuracy and damage with heavy weapons.",value:0},{id:3,name:"Energy Weapons",description:"Accuracy and damage with energy weapons.",value:0},{id:4,name:"Explosives",description:"Damage with explosives and ability to disarm traps.",value:0},{id:5,name:"Lockpick",description:"Ability to pick locks.",value:0},{id:6,name:"Medicine",description:"Effectiveness of Stimpaks and healing.",value:0},{id:7,name:"Melee Weapons",description:"Damage with melee weapons.",value:0},{id:8,name:"Repair",description:"Ability to maintain and repair items.",value:0},{id:9,name:"Science",description:"Ability to hack terminals and use tech.",value:0},{id:10,name:"Small Guns",description:"Accuracy and damage with small firearms.",value:0},{id:11,name:"Sneak",description:"Ability to remain undetected.",value:0},{id:12,name:"Speech",description:"Effectiveness in dialogue and persuasion.",value:0},{id:13,name:"Unarmed",description:"Damage with fists and unarmed weapons.",value:0}],R=[{key:"Agility",short:"AGI",description:"Affects your Action Points and your ability to sneak and avoid detection."},{key:"Charisma",short:"CHA",description:"Affects your speech skills and how people react to you in conversation."},{key:"Endurance",short:"END",description:"Affects your total Health and resistance to physical punishment over time."},{key:"Intelligence",short:"INT",description:"Affects how many skill points you gain when leveling up."},{key:"Luck",short:"LCK",description:"Affects many things in small ways, and helps you succeed at random chances."},{key:"Perception",short:"PER",description:"Affects your ability to notice things and your accuracy in VATS."},{key:"Strength",short:"STR",description:"Affects how much you can carry and the damage you do with melee attacks."}].map((e,t)=>({id:t+1,name:e.key,description:e.description,value:5})),L=[{formId:"0000080A",editorId:"Weap32CaliberPistol",name:".32 Pistol",nonPlayable:!1,damage:6,health:100,value:110,weight:2},{formId:"00050F92",editorId:"MysteriousStranger44Magnum",name:".44 Magnum",nonPlayable:!1,damage:9e3,health:1e3,value:0,weight:3},{formId:"0000434F",editorId:"Weap10mmPistol",name:"10mm Pistol",nonPlayable:!1,damage:9,health:150,value:225,weight:3},{formId:"0001A334",editorId:"FollowersButch10mmPistol",name:"10mm Pistol",nonPlayable:!1,damage:9,health:150,value:30,weight:2},{formId:"0006F210",editorId:"SonoraCruzWeap10mmPistol",name:"10mm Pistol",nonPlayable:!1,damage:100,health:150,value:43590,weight:2},{formId:"00004321",editorId:"Weap10mmSubmachineGun",name:"10mm Submachine Gun",nonPlayable:!1,damage:7,health:250,value:330,weight:5},{formId:"0006B539",editorId:"WeapUniqueA321PlasmaRifle",name:"A3-21's Plasma Rifle",nonPlayable:!1,damage:50,health:1200,value:2200,weight:8},{formId:"0006E8CE",editorId:"QueenAnt2HL",name:"Acid Spit",nonPlayable:!1,damage:40,health:100,value:80,weight:1},{formId:"000B8793",editorId:"MS04QueenAnt2HL",name:"Acid Spit",nonPlayable:!1,damage:70,health:100,value:130,weight:1},{formId:"00004322",editorId:"WeapAlienBlaster",name:"Alien Blaster",nonPlayable:!1,damage:100,health:500,value:500,weight:2},{formId:"000C553E",editorId:"WeapUniqueAntSting",name:"Ant's Sting",nonPlayable:!1,damage:4,health:250,value:30,weight:1},{formId:"0001FFEC",editorId:"WeapAssaultRifle",name:"Assault Rifle",nonPlayable:!1,damage:8,health:300,value:300,weight:7},{formId:"0000421C",editorId:"WeapBaseballBat",name:"Baseball Bat",nonPlayable:!1,damage:9,health:400,value:55,weight:3},{formId:"00033D84",editorId:"TrapBaseball",name:"Baseball",nonPlayable:!1,damage:6,health:5,value:10,weight:4},{formId:"00004323",editorId:"WeapBBGun",name:"BB Gun",nonPlayable:!1,damage:4,health:50,value:36,weight:2},{formId:"000C0327",editorId:"CG02WeapBBGun",name:"BB Gun",nonPlayable:!1,damage:4,health:1e3,value:36,weight:2},{formId:"0006B535",editorId:"WeapUniqueBlackBartsBBGun",name:"Black Bart's Bane",nonPlayable:!1,damage:8,health:100,value:60,weight:2},{formId:"000303A2",editorId:"WeapUniqueBlackhawk",name:"Blackhawk",nonPlayable:!1,damage:55,health:360,value:500,weight:4},{formId:"00046BDD",editorId:"Bloatfly1HP",name:"",nonPlayable:!1,damage:5,health:100,value:20,weight:1},{formId:"000C310F",editorId:"WeapUniqueBoardOfEducation",name:"Board of Education",nonPlayable:!1,damage:12,health:150,value:60,weight:4},{formId:"0000433A",editorId:"WeapMineBottlecap",name:"Bottlecap Mine",nonPlayable:!1,damage:1,health:5,value:75,weight:.5},{formId:"00004324",editorId:"WeapBrassKnuckles",name:"Brass Knuckles",nonPlayable:!1,damage:6,health:200,value:20,weight:1},{formId:"000CB546",editorId:"WeapUniqueBreaker",name:"Breaker",nonPlayable:!1,damage:12,health:150,value:30,weight:4},{formId:"000C80BD",editorId:"WeapUniqueBurnmaster",name:"Burnmaster",nonPlayable:!1,damage:24,health:200,value:500,weight:15},{formId:"00078440",editorId:"WeapUniqueButchToothpick",name:"Butch's Toothpick",nonPlayable:!1,damage:10,health:150,value:50,weight:1},{formId:"0003BC6F",editorId:"MisterHandyBuzzsaw",name:"Buzzsaw",nonPlayable:!1,damage:20,health:100,value:250,weight:1},{formId:"0000080B",editorId:"WeapChineseAssaultRifle",name:"Chinese Assault Rifle",nonPlayable:!1,damage:11,health:400,value:500,weight:7},{formId:"00040840",editorId:"FollowersJerichoChineseAssaultRifle",name:"Chinese Assault Rifle",nonPlayable:!1,damage:11,health:200,value:340,weight:7},{formId:"0002B3CB",editorId:"WeapChineseOfficerSword",name:"Chinese Officer's Sword",nonPlayable:!1,damage:10,health:500,value:75,weight:3},{formId:"0006415D",editorId:"FollowersCloverChineseOfficerSword",name:"Chinese Officer's Sword",nonPlayable:!1,damage:10,health:500,value:75,weight:3},{formId:"00004325",editorId:"WeapChinesePistol",name:"Chinese Pistol",nonPlayable:!1,damage:4,health:150,value:190,weight:2},{formId:"000C80B8",editorId:"WeapUniqueCloversCleaver",name:"Clover's Cleaver",nonPlayable:!1,damage:15,health:500,value:100,weight:3},{formId:"0006B531",editorId:"WeapUniqueColAutumns10mmPistol",name:"Col. Autumn's 10mm Pistol",nonPlayable:!1,damage:13,health:225,value:325,weight:3},{formId:"000ABBE4",editorId:"MQ11AutumnLaserPistol",name:"Col. Autumn's Laser Pistol",nonPlayable:!1,damage:10,health:500,value:420,weight:2},{formId:"00004326",editorId:"WeapKnifeCombat",name:"Combat Knife",nonPlayable:!1,damage:7,health:450,value:50,weight:1},{formId:"00064093",editorId:"FollowersCharonCombatKnife",name:"Combat Knife",nonPlayable:!1,damage:7,health:450,value:50,weight:1},{formId:"00004327",editorId:"WeapShotgunCombat",name:"Combat Shotgun",nonPlayable:!1,damage:55,health:240,value:200,weight:7},{formId:"0003713D",editorId:"FollowersCharonShotgunScene",name:"Combat Shotgun",nonPlayable:!1,damage:20,health:150,value:90,weight:10},{formId:"000372B8",editorId:"FollowersCharonShotgun",name:"Combat Shotgun",nonPlayable:!1,damage:55,health:150,value:70,weight:10},{formId:"000C80BB",editorId:"WeapUniqueCursebreaker",name:"Curse Breaker",nonPlayable:!1,damage:13,health:600,value:75,weight:3},{formId:"0000432A",editorId:"WeapDartGun",name:"Dart Gun",nonPlayable:!1,damage:6,health:150,value:500,weight:3},{formId:"0000432B",editorId:"WeapDeathclawGauntlet",name:"Deathclaw Gauntlet",nonPlayable:!1,damage:20,health:600,value:150,weight:10},{formId:"00022FF1",editorId:"EyeBot1HP",name:"Electrical Zap",nonPlayable:!1,damage:5,health:100,value:110,weight:1},{formId:"0006B538",editorId:"WeapUniqueMS18Minigun",name:"Eugene",nonPlayable:!1,damage:7,health:1500,value:1500,weight:18},{formId:"000C80BC",editorId:"WeapUniqueExcalibat",name:"Excalibat",nonPlayable:!1,damage:13,health:600,value:75,weight:3},{formId:"0003422B",editorId:"WeapUniqueMIRV",name:"Experimental MIRV",nonPlayable:!1,damage:10,health:300,value:2500,weight:30},{formId:"0000432C",editorId:"WeapFatman",name:"Fat Man",nonPlayable:!1,damage:10,health:100,value:1e3,weight:30},{formId:"0007843F",editorId:"WeapUniqueFawkesSuperSledge",name:"Fawkes' Super Sledge",nonPlayable:!1,damage:32,health:1e3,value:300,weight:18},{formId:"00021367",editorId:"BehemothFireHydrant",name:"Fire Hydrant",nonPlayable:!1,damage:100,health:1e3,value:100,weight:300},{formId:"000C80BA",editorId:"WeapUniqueFirelance",name:"Firelance",nonPlayable:!1,damage:80,health:200,value:750,weight:2},{formId:"000CB601",editorId:"WeapUniquePowerFist",name:"Fisto!",nonPlayable:!1,damage:25,health:600,value:100,weight:6},{formId:"000001F4",editorId:"Fists",name:"",nonPlayable:!1,damage:0,health:2,value:0,weight:0},{formId:"0000432D",editorId:"WeapFlamer",name:"Flamer",nonPlayable:!1,damage:16,health:200,value:500,weight:15},{formId:"00039550",editorId:"MisterGutsyFlamer2HL",name:"Flamer",nonPlayable:!1,damage:6,health:100,value:210,weight:1},{formId:"00078C60",editorId:"MS04FireAntWorkerFlame2HL",name:"Flamer",nonPlayable:!1,damage:2,health:100,value:30,weight:1},{formId:"0007C10B",editorId:"FollowerRL3Flamer2HL",name:"Flamer",nonPlayable:!1,damage:6,health:100,value:210,weight:1},{formId:"0009E8DF",editorId:"MS04FireAntSoldierFlame2HL",name:"Flamer",nonPlayable:!1,damage:4,health:100,value:60,weight:1},{formId:"000A0C02",editorId:"MisterHandyFlamer2HL",name:"Flamer",nonPlayable:!1,damage:2,health:100,value:60,weight:1},{formId:"000C58EE",editorId:"MS04FireAntGuardFlame2HL",name:"Flamer",nonPlayable:!1,damage:6,health:100,value:60,weight:1},{formId:"00004330",editorId:"WeapGrenadeFrag",name:"Frag Grenade",nonPlayable:!1,damage:1,health:5,value:25,weight:.5},{formId:"0000433C",editorId:"WeapMineFrag",name:"Frag Mine",nonPlayable:!1,damage:1,health:5,value:25,weight:.5},{formId:"00028172",editorId:"MQ04Mine",name:"Frag Mine",nonPlayable:!1,damage:300,health:5,value:3900,weight:1},{formId:"000001F6",editorId:"GasTrapDummy",name:"GasTrap Dummy",nonPlayable:!1,damage:0,health:100,value:0,weight:0},{formId:"0000432E",editorId:"WeapGatlingLaser",name:"Gatling Laser",nonPlayable:!1,damage:8,health:1500,value:2e3,weight:18},{formId:"0001A333",editorId:"FollowersFawkesGatlingLaser",name:"Gatling Laser",nonPlayable:!1,damage:9,health:1500,value:611,weight:10},{formId:"00018B9E",editorId:"ProtectronHandLaser1HP",name:"Hand Laser",nonPlayable:!1,damage:30,health:100,value:360,weight:1},{formId:"00018B9F",editorId:"ProtectronHeadLaser2HL",name:"Head Laser",nonPlayable:!1,damage:30,health:100,value:100,weight:1},{formId:"00078442",editorId:"WeapUniqueHighwaymansFriendTireIron",name:"Highwayman's Friend",nonPlayable:!1,damage:10,health:500,value:75,weight:5},{formId:"00004333",editorId:"WeapHuntingRifle",name:"Hunting Rifle",nonPlayable:!1,damage:25,health:500,value:150,weight:6},{formId:"000C6E5B",editorId:"WeapUniqueJackTheRipper",name:"Jack",nonPlayable:!1,damage:30,health:800,value:200,weight:6},{formId:"00004334",editorId:"WeapKnife",name:"Knife",nonPlayable:!1,damage:4,health:100,value:20,weight:1},{formId:"00004335",editorId:"WeapLaserPistol",name:"Laser Pistol",nonPlayable:!1,damage:12,health:350,value:320,weight:3},{formId:"00063E8A",editorId:"FollowersCrossLaserPistol",name:"Laser Pistol",nonPlayable:!1,damage:12,health:350,value:320,weight:3},{formId:"000B4178",editorId:"ElderLyonsLaserPistol",name:"Laser Pistol",nonPlayable:!1,damage:9,health:300,value:420,weight:2},{formId:"00004336",editorId:"WeapLaserRifle",name:"Laser Rifle",nonPlayable:!1,damage:23,health:1e3,value:1e3,weight:8},{formId:"00074795",editorId:"DemoLaserRifle",name:"Laser Rifle",nonPlayable:!1,damage:22,health:1e3,value:1e3,weight:8},{formId:"00050ED0",editorId:"RobobrainLaser1HPRight",name:"Laser",nonPlayable:!1,damage:38,health:100,value:1310,weight:1},{formId:"0007B237",editorId:"Turret01Laser2HR",name:"Laser",nonPlayable:!1,damage:8,health:50,value:100,weight:1},{formId:"0007B239",editorId:"Turret02Laser2HR",name:"Laser",nonPlayable:!1,damage:9,health:100,value:180,weight:1},{formId:"0007B23A",editorId:"Turret03Laser2HR",name:"Laser",nonPlayable:!1,damage:10,health:150,value:290,weight:1},{formId:"0006B532",editorId:"WeapUniqueLawDog32CalPistol",name:"Law Dog",nonPlayable:!1,damage:9,health:150,value:210,weight:2},{formId:"00004337",editorId:"WeapLeadPipe",name:"Lead Pipe",nonPlayable:!1,damage:9,health:300,value:75,weight:3},{formId:"00033FE2",editorId:"LibertyPrimeLaser",name:"Liberty Laser",nonPlayable:!1,damage:1e3,health:100,value:9674e3,weight:0},{formId:"0005932F",editorId:"LibertyPrimeWeapBomb",name:"LibertyPrimeWeapBomb",nonPlayable:!1,damage:200,health:100,value:23730,weight:0},{formId:"0003C07A",editorId:"MS06LincolnsRifle",name:"Lincoln's Repeater",nonPlayable:!1,damage:50,health:600,value:500,weight:5},{formId:"000C80B9",editorId:"WeapUniqueLoveTap",name:"Love Tap",nonPlayable:!1,damage:8,health:100,value:20,weight:1},{formId:"00004339",editorId:"WeapMesmetron",name:"Mesmetron",nonPlayable:!1,damage:1,health:100,value:500,weight:2},{formId:"000BF5A4",editorId:"RobobrainMesmetron",name:"Mesmetron",nonPlayable:!1,damage:1,health:100,value:500,weight:2},{formId:"0000433F",editorId:"WeapMinigun",name:"Minigun",nonPlayable:!1,damage:5,health:1e3,value:1e3,weight:18},{formId:"00030664",editorId:"MS03BaitGrenade",name:"Mirelurk Bait Grenade",nonPlayable:!1,damage:0,health:5,value:5,weight:1},{formId:"000B2644",editorId:"WeapUniqueMissLauncher",name:"Miss Launcher",nonPlayable:!1,damage:20,health:100,value:400,weight:15},{formId:"00004340",editorId:"WeapMissileLauncher",name:"Missile Launcher",nonPlayable:!1,damage:20,health:100,value:500,weight:20},{formId:"00057E8F",editorId:"SentryBotMissileLauncher2HL",name:"Missile Launcher",nonPlayable:!1,damage:20,health:1e3,value:4300,weight:15},{formId:"00063FDC",editorId:"FollowersJerichoNailBoard",name:"Nail Board",nonPlayable:!1,damage:8,health:60,value:30,weight:4},{formId:"000A01DD",editorId:"WeapNailBoard",name:"Nail Board",nonPlayable:!1,damage:8,health:60,value:30,weight:4},{formId:"00004342",editorId:"WeapNukaCocktail",name:"Nuka-Grenade",nonPlayable:!1,damage:1,health:5,value:50,weight:.5},{formId:"000CB602",editorId:"WeapUniqueKnifeCombat",name:"Occam's Razor",nonPlayable:!1,damage:10,health:600,value:65,weight:1},{formId:"0007843D",editorId:"WeapUniqueOGradysPoliceBaton",name:"O'Grady's Peacemaker",nonPlayable:!1,damage:6,health:400,value:100,weight:2},{formId:"00066C76",editorId:"WeapUniqueOlPainless",name:"Ol' Painless",nonPlayable:!1,damage:30,health:500,value:250,weight:6},{formId:"00004332",editorId:"WeapGrenadePlasma",name:"Plasma Grenade",nonPlayable:!1,damage:1,health:5,value:50,weight:.5},{formId:"0003954F",editorId:"MisterGutsyPlasma1HP",name:"Plasma Gun",nonPlayable:!1,damage:60,health:400,value:7200,weight:1},{formId:"0007C10C",editorId:"FollowerRL3Plasma1HP",name:"Plasma Gun",nonPlayable:!1,damage:40,health:400,value:7200,weight:1},{formId:"0000433D",editorId:"WeapMinePlasma",name:"Plasma Mine",nonPlayable:!1,damage:1,health:5,value:50,weight:.5},{formId:"00004343",editorId:"WeapPlasmaPistol",name:"Plasma Pistol",nonPlayable:!1,damage:25,health:400,value:360,weight:3},{formId:"00004344",editorId:"WeapPlasmaRifle",name:"Plasma Rifle",nonPlayable:!1,damage:45,health:900,value:1800,weight:8},{formId:"000CAFA9",editorId:"WeapUniqueJundersBrassKnuckles",name:"Plunkett's Valid Points",nonPlayable:!1,damage:12,health:200,value:30,weight:1},{formId:"00004345",editorId:"WeapPoliceBaton",name:"Police Baton",nonPlayable:!1,damage:4,health:250,value:70,weight:2},{formId:"00004346",editorId:"WeapPoolCue",name:"Pool Cue",nonPlayable:!1,damage:3,health:50,value:15,weight:1},{formId:"00004347",editorId:"WeapPowerFist",name:"Power Fist",nonPlayable:!1,damage:20,health:500,value:100,weight:6},{formId:"000C553F",editorId:"WeapUniqueProtectronGaze",name:"Protectron's Gaze",nonPlayable:!1,damage:24,health:500,value:320,weight:3},{formId:"00004331",editorId:"WeapGrenadePulse",name:"Pulse Grenade",nonPlayable:!1,damage:1,health:5,value:40,weight:.5},{formId:"0000433E",editorId:"WeapMinePulse",name:"Pulse Mine",nonPlayable:!1,damage:1,health:5,value:40,weight:.5},{formId:"00058717",editorId:"CentaurSpitMissile",name:"Radioactive Spit",nonPlayable:!1,damage:30,health:1e3,value:130,weight:1},{formId:"00004348",editorId:"WeapRailwayRifle",name:"Railway Rifle",nonPlayable:!1,damage:30,health:200,value:200,weight:9},{formId:"0002D3B7",editorId:"MS03Repellent",name:"Repellent Stick",nonPlayable:!1,damage:1,health:100,value:120,weight:3},{formId:"00092966",editorId:"WeapUniqueReservistsRifle",name:"Reservist's Rifle",nonPlayable:!1,damage:40,health:150,value:500,weight:10},{formId:"00004349",editorId:"WeapRipper",name:"Ripper",nonPlayable:!1,damage:30,health:600,value:100,weight:6},{formId:"0000434B",editorId:"WeapRockItLauncher",name:"Rock-It Launcher",nonPlayable:!1,damage:50,health:300,value:200,weight:8},{formId:"00029769",editorId:"MQ04RollingPin",name:"Rolling Pin",nonPlayable:!1,damage:20,health:100,value:10,weight:2},{formId:"000B2943",editorId:"WeapRollingPin",name:"Rolling Pin",nonPlayable:!1,damage:3,health:100,value:10,weight:1},{formId:"0005DEEE",editorId:"SatcomNuclearStrike",name:"",nonPlayable:!1,damage:20,health:100,value:500,weight:20},{formId:"0000434C",editorId:"WeapShotgunSawedOff",name:"Sawed-Off Shotgun",nonPlayable:!1,damage:50,health:250,value:150,weight:4},{formId:"000AE8AE",editorId:"FollowersCloverShotgun",name:"Sawed-Off Shotgun",nonPlayable:!1,damage:50,health:100,value:190,weight:5},{formId:"0000434D",editorId:"Weap44MagnumScoped",name:"Scoped .44 Magnum",nonPlayable:!1,damage:35,health:240,value:300,weight:4},{formId:"000389AF",editorId:"SentryBotGatling2HH",name:"SentryBot Laser Gatling",nonPlayable:!1,damage:6,health:1e3,value:1070,weight:15},{formId:"00057E8E",editorId:"SentryBotMinigun2HR",name:"SentryBot Minigun",nonPlayable:!1,damage:9,health:1e3,value:1070,weight:15},{formId:"0000434E",editorId:"WeapShishkebab",name:"Shishkebab",nonPlayable:!1,damage:35,health:750,value:200,weight:3},{formId:"0007F598",editorId:"MirelurkSonic2HL",name:"Shriek",nonPlayable:!1,damage:10,health:100,value:40,weight:1},{formId:"00004350",editorId:"Weap10mmPistolSilenced",name:"Silenced 10mm Pistol",nonPlayable:!1,damage:8,health:80,value:250,weight:3},{formId:"0002869C",editorId:"MQ04SlasherKnife",name:"Slasher Knife",nonPlayable:!1,damage:50,health:1e3,value:50,weight:1},{formId:"00004351",editorId:"WeapSledgehammer",name:"Sledgehammer",nonPlayable:!1,damage:20,health:500,value:130,weight:12},{formId:"00063FA2",editorId:"FollowersFawkesSledgehammer",name:"Sledgehammer",nonPlayable:!1,damage:20,health:500,value:130,weight:12},{formId:"0006B536",editorId:"WeapUniqueSmugglersEndLaserPistol",name:"Smuggler's End",nonPlayable:!1,damage:18,health:500,value:450,weight:2},{formId:"00004353",editorId:"WeapSniperRifle",name:"Sniper Rifle",nonPlayable:!1,damage:40,health:100,value:300,weight:10},{formId:"00004354",editorId:"WeapSpikedKnuckles",name:"Spiked Knuckles",nonPlayable:!1,damage:9,health:300,value:25,weight:1},{formId:"000C80BE",editorId:"WeapUniqueStabhappy",name:"Stabhappy",nonPlayable:!1,damage:10,health:600,value:65,weight:1},{formId:"00004352",editorId:"WeapSuperSledge",name:"Super Sledge",nonPlayable:!1,damage:25,health:750,value:180,weight:20},{formId:"000B0E7C",editorId:"FollowersCrossSuperSledge",name:"Super Sledge",nonPlayable:!1,damage:25,health:250,value:130,weight:3},{formId:"000289C3",editorId:"WeapSwitchBlade",name:"Switchblade",nonPlayable:!1,damage:5,health:100,value:35,weight:1},{formId:"0006407F",editorId:"FollowersButchSwitchblade",name:"Switchblade",nonPlayable:!1,damage:5,health:100,value:50,weight:1},{formId:"00066346",editorId:"WeapUniqueSydneys10mmSubGunFollwerVersion",name:'Sydney\'s 10mm "Ultra" SMG',nonPlayable:!1,damage:9,health:250,value:430,weight:5},{formId:"0006E7CC",editorId:"WeapUniqueSydneys10mmSubGun",name:'Sydney\'s 10mm "Ultra" SMG',nonPlayable:!1,damage:9,health:250,value:430,weight:5},{formId:"00066C77",editorId:"WeapUniqueTheBreak",name:"The Break",nonPlayable:!1,damage:6,health:200,value:50,weight:1},{formId:"0006B53A",editorId:"WeapUniqueKneecapper",name:"The Kneecapper",nonPlayable:!1,damage:75,health:250,value:350,weight:5},{formId:"000BFF62",editorId:"WeapUniqueShocker",name:"The Shocker",nonPlayable:!1,damage:20,health:400,value:150,weight:6},{formId:"000A874B",editorId:"WeapUniqueTenderizer",name:"The Tenderizer",nonPlayable:!1,damage:30,health:750,value:230,weight:12},{formId:"0006B534",editorId:"WeapUniqueTerribleShotgun",name:"The Terrible Shotgun",nonPlayable:!1,damage:80,health:350,value:250,weight:10},{formId:"00004328",editorId:"WeapTireIron",name:"Tire Iron",nonPlayable:!1,damage:6,health:200,value:40,weight:3},{formId:"00018E53",editorId:"TurretGunCeiling02",name:"Turret Gun",nonPlayable:!1,damage:7,health:150,value:230,weight:7},{formId:"00018E54",editorId:"TurretGunCeiling03",name:"Turret Gun",nonPlayable:!1,damage:10,health:150,value:370,weight:7},{formId:"000A84BD",editorId:"TurretGunCeiling01",name:"Turret Gun",nonPlayable:!1,damage:5,health:150,value:140,weight:7},{formId:"00078441",editorId:"WeapUniqueVancesChineseSword",name:"Vampire's Edge",nonPlayable:!1,damage:15,health:750,value:100,weight:1},{formId:"000CB547",editorId:"WeapUniqueVengeance",name:"Vengeance",nonPlayable:!1,damage:11,health:2e3,value:2400,weight:18},{formId:"0003E5E2",editorId:"VertibirdBombGun",name:"Vertibird Bomb Gun",nonPlayable:!1,damage:10,health:30,value:1e3,weight:30},{formId:"00089C51",editorId:"VertibirdGun",name:"Vertibird Gun",nonPlayable:!1,damage:20,health:3e3,value:6040,weight:10},{formId:"000CB548",editorId:"WeapUniqueVictoryRifle",name:"Victory Rifle",nonPlayable:!1,damage:40,health:300,value:450,weight:10},{formId:"0006B533",editorId:"WeapUniqueWandaAssaultRifle",name:"Wanda",nonPlayable:!1,damage:12,health:450,value:500,weight:7},{formId:"00061793",editorId:"WeapUniqueWazerWifle",name:"Wazer Wifle",nonPlayable:!1,damage:28,health:1800,value:900,weight:8},{formId:"000C800E",editorId:"WeapUniqueXuanlongAssaultRifle",name:"Xuanlong Assault Rifle",nonPlayable:!1,damage:12,health:400,value:400,weight:7},{formId:"00060C2C",editorId:"WeapUniqueZhuRongChinesePistol",name:"Zhu-Rong v418 Chinese Pistol",nonPlayable:!1,damage:4,health:200,value:290,weight:2}],E="1.0.2",C="pipBoy3000Settings",N=e=>e.map(e=>({id:e.id,name:e.name,description:e.description,value:e.value,imageId:e.imageId}));class B{constructor(){this.loadFromLocalStorage(),r(()=>{this.userLevel(),this.userHealth(),this.userHealthMax(),this.userActionPoints(),this.userActionPointsMax(),this.userExperience(),this.userExperienceNextLevel(),this.userName(),this.stimpakLabel(),this.limbLabel(),this.radAwayLabel(),this.radXLabel(),this.equippedWeaponId(),this.equippedApparelId(),this.equippedAidId(),this.equippedMiscId(),this.equippedAmmoId(),this.weaponItems(),this.apparelItems(),this.aidItems(),this.miscItems(),this.ammoItems(),this.specialItems(),this.skillItems(),this.perkItems(),this.questItems(),this.generalItems(),this.notesItems(),this.radioItems(),this.selectedNotesItemId(),this.selectedRadioItemId(),this.effectItems(),this.localMapImage(),this.worldMapImage(),this.vaultBoyImages(),this.selectedVaultBoyImageIndex(),this.scanLinesEnabled(),this.editLockEnabled(),this.listFontScale(),this.secondaryTabSoundId(),this.mainTabSoundId(),this.clickSoundId(),this.saveToLocalStorage()})}imageStore=l(x);userLevel=o(1,...ngDevMode?[{debugName:"userLevel"}]:[]);userHealth=o(99,...ngDevMode?[{debugName:"userHealth"}]:[]);userHealthMax=o(100,...ngDevMode?[{debugName:"userHealthMax"}]:[]);userActionPoints=o(50,...ngDevMode?[{debugName:"userActionPoints"}]:[]);userActionPointsMax=o(100,...ngDevMode?[{debugName:"userActionPointsMax"}]:[]);userExperience=o(1,...ngDevMode?[{debugName:"userExperience"}]:[]);userExperienceNextLevel=o(100,...ngDevMode?[{debugName:"userExperienceNextLevel"}]:[]);userName=o("Vault Dweller",...ngDevMode?[{debugName:"userName"}]:[]);stimpakLabel=o("(4) Stimpak",...ngDevMode?[{debugName:"stimpakLabel"}]:[]);limbLabel=o("Limbs",...ngDevMode?[{debugName:"limbLabel"}]:[]);radAwayLabel=o("RadAway",...ngDevMode?[{debugName:"radAwayLabel"}]:[]);radXLabel=o("Rad-X",...ngDevMode?[{debugName:"radXLabel"}]:[]);equippedWeaponId=o(null,...ngDevMode?[{debugName:"equippedWeaponId"}]:[]);equippedApparelId=o(null,...ngDevMode?[{debugName:"equippedApparelId"}]:[]);equippedAidId=o(null,...ngDevMode?[{debugName:"equippedAidId"}]:[]);equippedMiscId=o(null,...ngDevMode?[{debugName:"equippedMiscId"}]:[]);equippedAmmoId=o(null,...ngDevMode?[{debugName:"equippedAmmoId"}]:[]);weaponItems=o([],...ngDevMode?[{debugName:"weaponItems"}]:[]);apparelItems=o([],...ngDevMode?[{debugName:"apparelItems"}]:[]);aidItems=o([],...ngDevMode?[{debugName:"aidItems"}]:[]);miscItems=o([],...ngDevMode?[{debugName:"miscItems"}]:[]);ammoItems=o([],...ngDevMode?[{debugName:"ammoItems"}]:[]);specialItems=o(N(R),...ngDevMode?[{debugName:"specialItems"}]:[]);skillItems=o(N(D),...ngDevMode?[{debugName:"skillItems"}]:[]);perkItems=o(N(A),...ngDevMode?[{debugName:"perkItems"}]:[]);generalItems=o([],...ngDevMode?[{debugName:"generalItems"}]:[]);questItems=o([{id:1,name:"Quest item",completed:!1,tasks:[{id:1,name:"Task 1",completed:!1},{id:2,name:"Task 2",completed:!1},{id:3,name:"Task 3",completed:!1}]}],...ngDevMode?[{debugName:"questItems"}]:[]);notesItems=o([],...ngDevMode?[{debugName:"notesItems"}]:[]);radioItems=o([],...ngDevMode?[{debugName:"radioItems"}]:[]);selectedNotesItemId=o(null,...ngDevMode?[{debugName:"selectedNotesItemId"}]:[]);selectedRadioItemId=o(null,...ngDevMode?[{debugName:"selectedRadioItemId"}]:[]);effectItems=o([],...ngDevMode?[{debugName:"effectItems"}]:[]);localMapImage=o(null,...ngDevMode?[{debugName:"localMapImage"}]:[]);worldMapImage=o(null,...ngDevMode?[{debugName:"worldMapImage"}]:[]);vaultBoyImages=o([null,null,null],...ngDevMode?[{debugName:"vaultBoyImages"}]:[]);selectedVaultBoyImageIndex=o(0,...ngDevMode?[{debugName:"selectedVaultBoyImageIndex"}]:[]);scanLinesEnabled=o(!0,...ngDevMode?[{debugName:"scanLinesEnabled"}]:[]);editLockEnabled=o(!1,...ngDevMode?[{debugName:"editLockEnabled"}]:[]);listFontScale=o(1.25,...ngDevMode?[{debugName:"listFontScale"}]:[]);secondaryTabSoundId=o(null,...ngDevMode?[{debugName:"secondaryTabSoundId"}]:[]);mainTabSoundId=o(null,...ngDevMode?[{debugName:"mainTabSoundId"}]:[]);clickSoundId=o(null,...ngDevMode?[{debugName:"clickSoundId"}]:[]);exportSettingsSnapshot(){return{userLevel:this.userLevel(),userHealth:this.userHealth(),userHealthMax:this.userHealthMax(),userActionPoints:this.userActionPoints(),userActionPointsMax:this.userActionPointsMax(),userExperience:this.userExperience(),userExperienceNextLevel:this.userExperienceNextLevel(),userName:this.userName(),stimpakLabel:this.stimpakLabel(),limbLabel:this.limbLabel(),radAwayLabel:this.radAwayLabel(),radXLabel:this.radXLabel(),equippedWeaponId:this.equippedWeaponId(),equippedApparelId:this.equippedApparelId(),equippedAidId:this.equippedAidId(),equippedMiscId:this.equippedMiscId(),equippedAmmoId:this.equippedAmmoId(),weaponItems:this.weaponItems(),apparelItems:this.apparelItems(),aidItems:this.aidItems(),miscItems:this.miscItems(),ammoItems:this.ammoItems(),specialItems:this.specialItems(),skillItems:this.skillItems(),perkItems:this.perkItems(),questItems:this.questItems(),generalItems:this.generalItems(),notesItems:this.notesItems(),radioItems:this.radioItems(),selectedNotesItemId:this.selectedNotesItemId(),selectedRadioItemId:this.selectedRadioItemId(),effectItems:this.effectItems(),localMapImage:this.localMapImage(),worldMapImage:this.worldMapImage(),vaultBoyImages:this.vaultBoyImages(),selectedVaultBoyImageIndex:this.selectedVaultBoyImageIndex(),scanLinesEnabled:this.scanLinesEnabled(),editLockEnabled:this.editLockEnabled(),listFontScale:this.listFontScale(),secondaryTabSoundId:this.secondaryTabSoundId(),mainTabSoundId:this.mainTabSoundId(),clickSoundId:this.clickSoundId()}}exportSettingsJson(){return JSON.stringify(this.exportSettingsSnapshot())}importSettingsJson(e){const t=JSON.parse(e);this.importSettingsSnapshot(t)}importSettingsSnapshot(e){if(this.setNumberSignal(this.userLevel,e.userLevel),this.setNumberSignal(this.userHealth,e.userHealth),this.setNumberSignal(this.userHealthMax,e.userHealthMax),this.setNumberSignal(this.userActionPoints,e.userActionPoints),this.setNumberSignal(this.userActionPointsMax,e.userActionPointsMax),this.setNumberSignal(this.userExperience,e.userExperience),this.setNumberSignal(this.userExperienceNextLevel,e.userExperienceNextLevel),"string"==typeof e.userName&&this.userName.set(e.userName),"string"==typeof e.stimpakLabel&&this.stimpakLabel.set(e.stimpakLabel),"string"==typeof e.limbLabel&&this.limbLabel.set(e.limbLabel),"string"==typeof e.radAwayLabel&&this.radAwayLabel.set(e.radAwayLabel),"string"==typeof e.radXLabel&&this.radXLabel.set(e.radXLabel),"number"==typeof e.equippedWeaponId?this.equippedWeaponId.set(e.equippedWeaponId):null===e.equippedWeaponId&&this.equippedWeaponId.set(null),"number"==typeof e.equippedApparelId?this.equippedApparelId.set(e.equippedApparelId):null===e.equippedApparelId&&this.equippedApparelId.set(null),"number"==typeof e.equippedAidId?this.equippedAidId.set(e.equippedAidId):null===e.equippedAidId&&this.equippedAidId.set(null),"number"==typeof e.equippedMiscId?this.equippedMiscId.set(e.equippedMiscId):null===e.equippedMiscId&&this.equippedMiscId.set(null),"number"==typeof e.equippedAmmoId?this.equippedAmmoId.set(e.equippedAmmoId):null===e.equippedAmmoId&&this.equippedAmmoId.set(null),this.weaponItems.set(this.normalizeItems(e.weaponItems)),this.apparelItems.set(this.normalizeItems(e.apparelItems)),this.aidItems.set(this.normalizeItems(e.aidItems)),this.miscItems.set(this.normalizeItems(e.miscItems)),this.ammoItems.set(this.normalizeItems(e.ammoItems)),this.specialItems.set(this.normalizeStatItems(e.specialItems,N(R))),this.skillItems.set(this.normalizeStatItems(e.skillItems,N(D))),this.perkItems.set(this.normalizeStatItems(e.perkItems,N(A))),this.generalItems.set(this.normalizeStatItems(e.generalItems,[])),this.questItems.set(this.normalizeQuestItems(e.questItems)),this.notesItems.set(this.normalizeAudioItems(e.notesItems)),this.radioItems.set(this.normalizeAudioItems(e.radioItems)),"number"==typeof e.selectedNotesItemId?this.selectedNotesItemId.set(e.selectedNotesItemId):null===e.selectedNotesItemId&&this.selectedNotesItemId.set(null),"number"==typeof e.selectedRadioItemId?this.selectedRadioItemId.set(e.selectedRadioItemId):null===e.selectedRadioItemId&&this.selectedRadioItemId.set(null),this.effectItems.set(this.normalizeEffectItems(e.effectItems)),"string"==typeof e.localMapImage?this.localMapImage.set(this.normalizeImageId(e.localMapImage)??null):null===e.localMapImage&&this.localMapImage.set(null),"string"==typeof e.worldMapImage?this.worldMapImage.set(this.normalizeImageId(e.worldMapImage)??null):null===e.worldMapImage&&this.worldMapImage.set(null),Array.isArray(e.vaultBoyImages)){const t=this.normalizeImageSlots(e.vaultBoyImages);if(this.vaultBoyImages.set(t),"number"==typeof e.selectedVaultBoyImageIndex&&Number.isFinite(e.selectedVaultBoyImageIndex)){const a=Math.min(Math.max(0,e.selectedVaultBoyImageIndex),Math.max(0,t.length-1));this.selectedVaultBoyImageIndex.set(a)}}if("boolean"==typeof e.scanLinesEnabled&&this.scanLinesEnabled.set(e.scanLinesEnabled),"boolean"==typeof e.editLockEnabled&&this.editLockEnabled.set(e.editLockEnabled),"number"==typeof e.listFontScale){const t=Math.min(1.875,Math.max(.625,e.listFontScale));Number.isFinite(t)&&this.listFontScale.set(t)}"string"==typeof e.secondaryTabSoundId?this.secondaryTabSoundId.set(e.secondaryTabSoundId):null===e.secondaryTabSoundId&&this.secondaryTabSoundId.set(null),"string"==typeof e.mainTabSoundId?this.mainTabSoundId.set(e.mainTabSoundId):null===e.mainTabSoundId&&this.mainTabSoundId.set(null),"string"==typeof e.clickSoundId?this.clickSoundId.set(e.clickSoundId):null===e.clickSoundId&&this.clickSoundId.set(null)}saveToLocalStorage(e=C){"undefined"!=typeof localStorage&&localStorage.setItem(e,this.exportSettingsJson())}loadFromLocalStorage(e=C){if("undefined"==typeof localStorage)return;const t=localStorage.getItem(e);t&&this.importSettingsJson(t)}resetToDefaults(){this.userLevel.set(1),this.userHealth.set(99),this.userHealthMax.set(100),this.userActionPoints.set(50),this.userActionPointsMax.set(100),this.userExperience.set(1),this.userExperienceNextLevel.set(100),this.userName.set("Vault Dweller"),this.stimpakLabel.set("(4) Stimpak"),this.limbLabel.set("Limbs"),this.radAwayLabel.set("RadAway"),this.radXLabel.set("Rad-X"),this.equippedWeaponId.set(null),this.equippedApparelId.set(null),this.equippedAidId.set(null),this.equippedMiscId.set(null),this.equippedAmmoId.set(null),this.weaponItems.set([]),this.apparelItems.set([]),this.aidItems.set([]),this.miscItems.set([]),this.ammoItems.set([]),this.specialItems.set(N(R)),this.skillItems.set(N(D)),this.perkItems.set(N(A)),this.generalItems.set([]),this.questItems.set([{id:1,name:"Quest item",completed:!1,tasks:[{id:1,name:"Task 1",completed:!1},{id:2,name:"Task 2",completed:!1},{id:3,name:"Task 3",completed:!1}]}]),this.notesItems.set([]),this.radioItems.set([]),this.selectedNotesItemId.set(null),this.selectedRadioItemId.set(null),this.effectItems.set([]),this.localMapImage.set(null),this.worldMapImage.set(null),this.vaultBoyImages.set([null,null,null]),this.selectedVaultBoyImageIndex.set(0),this.scanLinesEnabled.set(!0),this.editLockEnabled.set(!1),this.listFontScale.set(1.25),this.secondaryTabSoundId.set(null),this.mainTabSoundId.set(null),this.clickSoundId.set(null)}setNumberSignal(e,t){"number"==typeof t&&Number.isFinite(t)&&e.set(t)}normalizeItems(e){return Array.isArray(e)?e.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name).map(e=>({id:e.id,name:e.name,damage:"number"==typeof e.damage&&Number.isFinite(e.damage)?e.damage:void 0,imageId:this.normalizeImageId(e.imageId??e.image),effects:"string"==typeof e.effects?e.effects:void 0,quantity:"number"==typeof e.quantity&&Number.isFinite(e.quantity)?e.quantity:void 0,value:"number"==typeof e.value&&Number.isFinite(e.value)?e.value:void 0,weight:"number"==typeof e.weight&&Number.isFinite(e.weight)?e.weight:void 0})):[]}normalizeStatItems(e,t){return Array.isArray(e)?e.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name&&"string"==typeof e.description&&"number"==typeof e.value&&Number.isFinite(e.value)).map(e=>({id:e.id,name:e.name,description:e.description,value:e.value,imageId:this.normalizeImageId(e.imageId??e.image)})):t}normalizeAudioItems(e){return Array.isArray(e)?e.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name&&"string"==typeof e.soundId).map(e=>({id:e.id,name:e.name,soundId:e.soundId})):[]}normalizeEffectItems(e){return Array.isArray(e)?e.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name&&"string"==typeof e.description).map(e=>({id:e.id,name:e.name,description:e.description})):[]}normalizeQuestItems(e){return Array.isArray(e)?e.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name&&"boolean"==typeof e.completed&&Array.isArray(e.tasks)).map(e=>({id:e.id,name:e.name,completed:e.completed,tasks:e.tasks.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name&&"boolean"==typeof e.completed).map(e=>({id:e.id,name:e.name,completed:e.completed}))})):[]}normalizeImageSlots(e){if(!Array.isArray(e))return[];return e.map(e=>"string"!=typeof e?null:this.normalizeImageId(e)??null).slice(0,10)}normalizeImageId(e){if("string"==typeof e){if(e.startsWith("data:")){const t=this.imageStore.generateId();return this.imageStore.saveDataUrlWithId(t,e),t}return e}}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:B,deps:[],target:e.ɵɵFactoryTarget.Injectable});static"ɵprov"=e.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:B,providedIn:"root"})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:B,decorators:[{type:i,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});class F{static nextId=0;open=!1;title="";name="";nameLabel="Name";showName=!1;nameOptions=[];imageUrl=null;showImage=!1;fields=[];textFields=[];closeResult=new s;save=new s;nameChange=new s;values=o({},...ngDevMode?[{debugName:"values"}]:[]);draftName=o("",...ngDevMode?[{debugName:"draftName"}]:[]);draftImageUrl=o(null,...ngDevMode?[{debugName:"draftImageUrl"}]:[]);draftImageName=o(null,...ngDevMode?[{debugName:"draftImageName"}]:[]);draftImageFile=o(null,...ngDevMode?[{debugName:"draftImageFile"}]:[]);removedImage=o(!1,...ngDevMode?[{debugName:"removedImage"}]:[]);textValues=o({},...ngDevMode?[{debugName:"textValues"}]:[]);nameListId="stat-edit-name-"+F.nextId++;previewUrl=null;ngOnChanges(){if(this.open){this.draftName.set(this.name),this.draftImageUrl.set(this.imageUrl),this.draftImageName.set(null),this.draftImageFile.set(null),this.removedImage.set(!1),this.clearPreviewUrl();const e={};for(const t of this.fields)e[t.key]=t.value;this.values.set(e);const t={};for(const e of this.textFields)t[e.key]=e.value;this.textValues.set(t)}}closeModal(){this.clearPreviewUrl(),this.closeResult.emit()}updateName(e){this.draftName.set(e),this.nameChange.emit(e)}onImageSelected(e){const t=e.target,a=t.files?.[0]??null;this.draftImageName.set(a?a.name:null),a&&(this.removedImage.set(!1),this.draftImageFile.set(a),this.setPreviewUrl(URL.createObjectURL(a)),t.value="")}removeImage(){this.draftImageName.set(null),this.draftImageUrl.set(null),this.draftImageFile.set(null),this.removedImage.set(!0),this.clearPreviewUrl()}updateText(e,t){this.textValues.update(a=>({...a,[e]:t}))}onInput(e,t){const a=Number(t);this.values.update(t=>({...t,[e]:a}))}submit(e){e?.preventDefault(),this.save.emit({name:this.draftName(),values:this.values(),imageFile:this.draftImageFile(),removeImage:this.removedImage(),textValues:this.textValues()}),this.clearPreviewUrl()}setPreviewUrl(e){this.clearPreviewUrl(),this.previewUrl=e,this.draftImageUrl.set(e)}clearPreviewUrl(){this.previewUrl&&(URL.revokeObjectURL(this.previewUrl),this.previewUrl=null)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:F,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:F,isStandalone:!0,selector:"pip-boy-stat-edit-modal",inputs:{open:"open",title:"title",name:"name",nameLabel:"nameLabel",showName:"showName",nameOptions:"nameOptions",imageUrl:"imageUrl",showImage:"showImage",fields:"fields",textFields:"textFields"},outputs:{closeResult:"closeResult",save:"save",nameChange:"nameChange"},usesOnChanges:!0,ngImport:e,template:'@if (open) {\n <div\n class="stat-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="stat-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <form (submit)="submit($event)">\n <div class="stat-modal-body">\n @if (showName) {\n <label class="stat-modal-field">\n <span>{{ nameLabel }}</span>\n <input\n type="text"\n [attr.list]="nameOptions.length ? nameListId : null"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n @if (nameOptions.length) {\n <datalist [id]="nameListId">\n @for (name of nameOptions; track name) {\n <option [value]="name"></option>\n }\n </datalist>\n }\n }\n @for (field of fields; track field.key) {\n <label class="stat-modal-field">\n <span>{{ field.label }}</span>\n <input\n type="number"\n inputmode="numeric"\n [value]="values()[field.key]"\n (input)="onInput(field.key, $any($event.target).value)"\n />\n </label>\n }\n @for (field of textFields; track field.key) {\n <label\n class="stat-modal-field"\n [attr.for]="\'text-field-\' + field.key"\n >\n <span>{{ field.label }}</span>\n @if (field.multiline) {\n <textarea\n [id]="\'text-field-\' + field.key"\n rows="4"\n [value]="textValues()[field.key]"\n (input)="updateText(field.key, $any($event.target).value)"\n ></textarea>\n } @else {\n <input\n [id]="\'text-field-\' + field.key"\n type="text"\n [value]="textValues()[field.key]"\n (input)="updateText(field.key, $any($event.target).value)"\n />\n }\n </label>\n }\n @if (showImage) {\n <div class="stat-modal-image">\n <button\n type="button"\n class="stat-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="stat-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Item preview" />\n }\n </div>\n }\n </div>\n <div class="stat-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".stat-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.stat-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.stat-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.stat-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.stat-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.stat-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.stat-modal-field input,.stat-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.stat-modal-field input:focus,.stat-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.stat-modal-field input{height:2.5rem}.stat-modal-field textarea{min-height:6rem;resize:vertical;text-transform:none}.stat-modal-image{display:flex;flex-direction:column;gap:.75rem}.stat-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.stat-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:8rem;object-fit:contain;padding:.5rem}.stat-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.stat-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.stat-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.stat-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.stat-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"],dependencies:[{kind:"ngmodule",type:g}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:F,decorators:[{type:n,args:[{selector:"pip-boy-stat-edit-modal",standalone:!0,imports:[g],template:'@if (open) {\n <div\n class="stat-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="stat-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <form (submit)="submit($event)">\n <div class="stat-modal-body">\n @if (showName) {\n <label class="stat-modal-field">\n <span>{{ nameLabel }}</span>\n <input\n type="text"\n [attr.list]="nameOptions.length ? nameListId : null"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n @if (nameOptions.length) {\n <datalist [id]="nameListId">\n @for (name of nameOptions; track name) {\n <option [value]="name"></option>\n }\n </datalist>\n }\n }\n @for (field of fields; track field.key) {\n <label class="stat-modal-field">\n <span>{{ field.label }}</span>\n <input\n type="number"\n inputmode="numeric"\n [value]="values()[field.key]"\n (input)="onInput(field.key, $any($event.target).value)"\n />\n </label>\n }\n @for (field of textFields; track field.key) {\n <label\n class="stat-modal-field"\n [attr.for]="\'text-field-\' + field.key"\n >\n <span>{{ field.label }}</span>\n @if (field.multiline) {\n <textarea\n [id]="\'text-field-\' + field.key"\n rows="4"\n [value]="textValues()[field.key]"\n (input)="updateText(field.key, $any($event.target).value)"\n ></textarea>\n } @else {\n <input\n [id]="\'text-field-\' + field.key"\n type="text"\n [value]="textValues()[field.key]"\n (input)="updateText(field.key, $any($event.target).value)"\n />\n }\n </label>\n }\n @if (showImage) {\n <div class="stat-modal-image">\n <button\n type="button"\n class="stat-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="stat-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Item preview" />\n }\n </div>\n }\n </div>\n <div class="stat-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".stat-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.stat-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.stat-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.stat-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.stat-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.stat-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.stat-modal-field input,.stat-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.stat-modal-field input:focus,.stat-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.stat-modal-field input{height:2.5rem}.stat-modal-field textarea{min-height:6rem;resize:vertical;text-transform:none}.stat-modal-image{display:flex;flex-direction:column;gap:.75rem}.stat-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.stat-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:8rem;object-fit:contain;padding:.5rem}.stat-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.stat-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.stat-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.stat-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.stat-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],title:[{type:m}],name:[{type:m}],nameLabel:[{type:m}],showName:[{type:m}],nameOptions:[{type:m}],imageUrl:[{type:m}],showImage:[{type:m}],fields:[{type:m}],textFields:[{type:m}],closeResult:[{type:d}],save:[{type:d}],nameChange:[{type:d}]}});class T{state=l(w);settings=l(B);statModal=o(null,...ngDevMode?[{debugName:"statModal"}]:[]);statModalTitle=c(()=>{switch(this.statModal()){case"LVL":return"Edit Level";case"HP":return"Edit Health";case"AP":return"Edit Action Points";case"XP":return"Edit Experience";default:return""}},...ngDevMode?[{debugName:"statModalTitle"}]:[]);statModalFields=c(()=>{switch(this.statModal()){case"LVL":return[{key:"level",label:"Level",value:this.settings.userLevel()}];case"HP":return[{key:"current",label:"Current",value:this.settings.userHealth()},{key:"max",label:"Max",value:this.settings.userHealthMax()}];case"AP":return[{key:"current",label:"Current",value:this.settings.userActionPoints()},{key:"max",label:"Max",value:this.settings.userActionPointsMax()}];case"XP":return[{key:"current",label:"Current",value:this.settings.userExperience()},{key:"max",label:"Next Level",value:this.settings.userExperienceNextLevel()}];default:return[]}},...ngDevMode?[{debugName:"statModalFields"}]:[]);openStatModal(e){this.statModal.set(e)}closeStatModal(){this.statModal.set(null)}saveStatModal(e){const t=this.statModal();if(t){if("LVL"===t){const t=e.values.level;return Number.isFinite(t)&&this.settings.userLevel.set(t),void this.closeStatModal()}"HP"===t?this.applyPair(e.values,this.settings.userHealth,this.settings.userHealthMax):"AP"===t?this.applyPair(e.values,this.settings.userActionPoints,this.settings.userActionPointsMax):"XP"===t&&this.applyPair(e.values,this.settings.userExperience,this.settings.userExperienceNextLevel),this.closeStatModal()}}applyPair(e,t,a){Number.isFinite(e.current)&&t.set(e.current),Number.isFinite(e.max)&&a.set(e.max)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:T,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:T,isStandalone:!0,selector:"pip-boy-3000-header",ngImport:e,template:'<header>\n <div class="header-top">\n <div class="main-title">\n <div class="main-title-left-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="main-title-text">\n @if (state.primary() === \'STATS\') {\n STATS\n } @else if (state.primary() === \'ITEMS\') {\n ITEMS\n } @else if (state.primary() === \'DATA\') {\n DATA\n }\n </div>\n <div class="main-title-right-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n </div>\n <div class="hp-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="ap-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="xp-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n </div>\n <div class="header-content">\n <button\n type="button"\n class="stats stat-button"\n (click)="openStatModal(\'LVL\')"\n >\n <span>LVL</span> {{ settings.userLevel() }}\n </button>\n <button type="button" class="hp stat-button" (click)="openStatModal(\'HP\')">\n <span>HP</span>\n <span>{{ settings.userHealth() }} / {{ settings.userHealthMax() }}</span>\n </button>\n <button type="button" class="ap stat-button" (click)="openStatModal(\'AP\')">\n <span>AP</span>\n {{ settings.userActionPoints() }} / {{ settings.userActionPointsMax() }}\n </button>\n <button type="button" class="xp stat-button" (click)="openStatModal(\'XP\')">\n <span>XP</span>\n {{ settings.userExperience() }} /\n {{ settings.userExperienceNextLevel() }}\n </button>\n </div>\n</header>\n<pip-boy-stat-edit-modal\n (closeResult)="closeStatModal()"\n (save)="saveStatModal($event)"\n [fields]="statModalFields()"\n [open]="statModal() !== null"\n [title]="statModalTitle()"\n/>\n',styles:['.center-line{position:relative;height:100%;overflow:visible}.center-line:before{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:2px;background:#0fbb6b}.bottom-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.bottom-half-line:before{content:"";position:absolute;top:50%;bottom:-1.25rem;width:2px;z-index:2;background:linear-gradient(to bottom,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}header{width:100%;box-sizing:border-box;display:flex;flex-direction:column;flex:0 0 auto;min-height:0;padding:0 1rem}header>.header-top,header>.header-content{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.25rem;padding:0}header>.header-top{height:2.25rem;align-items:center;text-transform:uppercase;overflow:visible}header>.header-top>.main-title{display:flex;align-items:center;justify-content:center;gap:.5rem;height:100%;overflow:visible}header>.header-top>.main-title>.main-title-left-line,header>.header-top>.main-title>.main-title-right-line{flex-grow:1;min-width:2rem;height:100%;position:relative;overflow:visible}header>.header-top>.main-title>.main-title-text{font-size:clamp(1.25rem,1.25rem + (1.5rem - 1.25rem) * (100vw - 360px) / (1200px - 360px),1.5rem);flex-grow:0;letter-spacing:.1em;white-space:nowrap;line-height:1}header>.header-top .main-title-left-line .bottom-half-line:before{left:0}header>.header-top .main-title-right-line .bottom-half-line:before{right:0}header>.header-top .hp-title-line,header>.header-top .ap-title-line,header>.header-top .xp-title-line{overflow:visible}header>.header-top .hp-title-line .bottom-half-line:before,header>.header-top .ap-title-line .bottom-half-line:before,header>.header-top .xp-title-line .bottom-half-line:before{right:0}header>.header-content{box-sizing:border-box;margin-top:-.5rem;font-size:calc(clamp(.9rem,.9rem + .2rem * (100vw - 360px) / 840px,1.1rem) * (1 + (var(--list-font-scale, 1) - 1) * .6))}header>.header-content>.stats,header>.header-content>.hp,header>.header-content>.ap,header>.header-content>.xp{display:flex;justify-content:flex-end;padding:0 1rem;gap:1rem}header>.header-content>.stat-button{align-items:center;background:transparent;border:none;color:inherit;cursor:pointer;font:inherit;text-align:right;text-transform:uppercase}header>.header-content>.stat-button:hover{background:#0fbb6b14}\n'],dependencies:[{kind:"component",type:F,selector:"pip-boy-stat-edit-modal",inputs:["open","title","name","nameLabel","showName","nameOptions","imageUrl","showImage","fields","textFields"],outputs:["closeResult","save","nameChange"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:T,decorators:[{type:n,args:[{selector:"pip-boy-3000-header",standalone:!0,imports:[F],template:'<header>\n <div class="header-top">\n <div class="main-title">\n <div class="main-title-left-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="main-title-text">\n @if (state.primary() === \'STATS\') {\n STATS\n } @else if (state.primary() === \'ITEMS\') {\n ITEMS\n } @else if (state.primary() === \'DATA\') {\n DATA\n }\n </div>\n <div class="main-title-right-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n </div>\n <div class="hp-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="ap-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="xp-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n </div>\n <div class="header-content">\n <button\n type="button"\n class="stats stat-button"\n (click)="openStatModal(\'LVL\')"\n >\n <span>LVL</span> {{ settings.userLevel() }}\n </button>\n <button type="button" class="hp stat-button" (click)="openStatModal(\'HP\')">\n <span>HP</span>\n <span>{{ settings.userHealth() }} / {{ settings.userHealthMax() }}</span>\n </button>\n <button type="button" class="ap stat-button" (click)="openStatModal(\'AP\')">\n <span>AP</span>\n {{ settings.userActionPoints() }} / {{ settings.userActionPointsMax() }}\n </button>\n <button type="button" class="xp stat-button" (click)="openStatModal(\'XP\')">\n <span>XP</span>\n {{ settings.userExperience() }} /\n {{ settings.userExperienceNextLevel() }}\n </button>\n </div>\n</header>\n<pip-boy-stat-edit-modal\n (closeResult)="closeStatModal()"\n (save)="saveStatModal($event)"\n [fields]="statModalFields()"\n [open]="statModal() !== null"\n [title]="statModalTitle()"\n/>\n',styles:['.center-line{position:relative;height:100%;overflow:visible}.center-line:before{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:2px;background:#0fbb6b}.bottom-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.bottom-half-line:before{content:"";position:absolute;top:50%;bottom:-1.25rem;width:2px;z-index:2;background:linear-gradient(to bottom,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}header{width:100%;box-sizing:border-box;display:flex;flex-direction:column;flex:0 0 auto;min-height:0;padding:0 1rem}header>.header-top,header>.header-content{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.25rem;padding:0}header>.header-top{height:2.25rem;align-items:center;text-transform:uppercase;overflow:visible}header>.header-top>.main-title{display:flex;align-items:center;justify-content:center;gap:.5rem;height:100%;overflow:visible}header>.header-top>.main-title>.main-title-left-line,header>.header-top>.main-title>.main-title-right-line{flex-grow:1;min-width:2rem;height:100%;position:relative;overflow:visible}header>.header-top>.main-title>.main-title-text{font-size:clamp(1.25rem,1.25rem + (1.5rem - 1.25rem) * (100vw - 360px) / (1200px - 360px),1.5rem);flex-grow:0;letter-spacing:.1em;white-space:nowrap;line-height:1}header>.header-top .main-title-left-line .bottom-half-line:before{left:0}header>.header-top .main-title-right-line .bottom-half-line:before{right:0}header>.header-top .hp-title-line,header>.header-top .ap-title-line,header>.header-top .xp-title-line{overflow:visible}header>.header-top .hp-title-line .bottom-half-line:before,header>.header-top .ap-title-line .bottom-half-line:before,header>.header-top .xp-title-line .bottom-half-line:before{right:0}header>.header-content{box-sizing:border-box;margin-top:-.5rem;font-size:calc(clamp(.9rem,.9rem + .2rem * (100vw - 360px) / 840px,1.1rem) * (1 + (var(--list-font-scale, 1) - 1) * .6))}header>.header-content>.stats,header>.header-content>.hp,header>.header-content>.ap,header>.header-content>.xp{display:flex;justify-content:flex-end;padding:0 1rem;gap:1rem}header>.header-content>.stat-button{align-items:center;background:transparent;border:none;color:inherit;cursor:pointer;font:inherit;text-align:right;text-transform:uppercase}header>.header-content>.stat-button:hover{background:#0fbb6b14}\n']}]}]});class O{dbPromise=this.openDb();soundUrls=o({},...ngDevMode?[{debugName:"soundUrls"}]:[]);soundLabels=o({},...ngDevMode?[{debugName:"soundLabels"}]:[]);metaLoading=new Set;getSoundLabel(e){if(!e)return null;const t=this.soundLabels()[e];return t||(this.loadSoundMeta(e),null)}async playSound(e){if(!e)return;const t=this.soundUrls()[e];if(t){const e=new Audio(t);return void await e.play().catch(()=>{})}const a=await this.getRecord(e);if(!a)return;const n=URL.createObjectURL(a.blob);this.cacheUrl(e,n),this.cacheLabel(e,a.fileName);const o=new Audio(n);await o.play().catch(()=>{})}async saveFile(e){const t=this.createId(),a={id:t,fileName:e.name,mime:e.type||"application/octet-stream"};return await this.putRecord({...a,blob:e}),this.cacheUrl(t,URL.createObjectURL(e)),this.cacheLabel(t,a.fileName),a}async saveBlobWithId(e,t,a,n){await this.putRecord({id:e,blob:t,fileName:a,mime:n}),this.cacheUrl(e,URL.createObjectURL(t)),this.cacheLabel(e,a)}async getRecord(e){const t=await this.dbPromise;return new Promise((a,n)=>{const o=t.transaction("sounds","readonly").objectStore("sounds").get(e);o.onsuccess=()=>{a(o.result??null)},o.onerror=()=>n(o.error)})}extensionFromMime(e){switch(e){case"audio/mpeg":case"audio/mp3":return".mp3";case"audio/wav":case"audio/x-wav":case"audio/wave":return".wav";case"audio/ogg":return".ogg";case"audio/aac":return".aac";case"audio/mp4":case"audio/x-m4a":return".m4a";case"audio/webm":return".webm";default:return""}}cacheUrl(e,t){this.soundUrls.update(a=>({...a,[e]:t}))}cacheLabel(e,t){this.soundLabels.update(a=>({...a,[e]:t}))}async loadSoundMeta(e){if(!this.metaLoading.has(e)){this.metaLoading.add(e);try{const t=await this.getRecord(e);if(!t)return;this.cacheLabel(e,t.fileName)}finally{this.metaLoading.delete(e)}}}async putRecord(e){const t=await this.dbPromise;return new Promise((a,n)=>{const o=t.transaction("sounds","readwrite").objectStore("sounds").put(e);o.onsuccess=()=>a(),o.onerror=()=>n(o.error)})}openDb(){return new Promise((e,t)=>{const a=indexedDB.open("pipBoy3000Sounds",1);a.onupgradeneeded=()=>{const e=a.result;e.objectStoreNames.contains("sounds")||e.createObjectStore("sounds",{keyPath:"id"})},a.onsuccess=()=>e(a.result),a.onerror=()=>t(a.error)})}createId(){return"undefined"!=typeof crypto&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:O,deps:[],target:e.ɵɵFactoryTarget.Injectable});static"ɵprov"=e.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:O,providedIn:"root"})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:O,decorators:[{type:i,args:[{providedIn:"root"}]}]});class z{category="WEAPONS";settings=l(B);imageStore=l(x);soundStore=l(O);showStatEditModal=o(!1,...ngDevMode?[{debugName:"showStatEditModal"}]:[]);editMode=o("EDIT",...ngDevMode?[{debugName:"editMode"}]:[]);modalName=o("",...ngDevMode?[{debugName:"modalName"}]:[]);modalImageId=o(null,...ngDevMode?[{debugName:"modalImageId"}]:[]);modalValues=o({damage:0,weight:0,value:0,quantity:0},...ngDevMode?[{debugName:"modalValues"}]:[]);modalTextValues=o({},...ngDevMode?[{debugName:"modalTextValues"}]:[]);selectedItem=c(()=>{const e=this.getEquippedId();return null===e?null:this.getItems().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedItem"}]:[]);itemNames=c(()=>{const e=this.getSourceNames();return Array.from(new Set(e)).sort()},...ngDevMode?[{debugName:"itemNames"}]:[]);editStatModalTitle=c(()=>{if("ADD"===this.editMode())return this.modalTitle();const e=this.selectedItem();return e?`Edit ${e.name}`:"Edit Stats"},...ngDevMode?[{debugName:"editStatModalTitle"}]:[]);statEditFields=c(()=>{const e=this.modalValues();switch(this.category){case"WEAPONS":return[{key:"damage",label:"Damage",value:e.damage??0},{key:"weight",label:"Weight",value:e.weight??0},{key:"value",label:"Value",value:e.value??0}];case"APPAREL":return[{key:"damage",label:"DR",value:e.damage??0},{key:"weight",label:"WG",value:e.weight??0},{key:"value",label:"VAL",value:e.value??0},{key:"quantity",label:"QTY",value:e.quantity??0}];default:return[{key:"weight",label:"WG",value:e.weight??0},{key:"value",label:"VAL",value:e.value??0},{key:"quantity",label:"QTY",value:e.quantity??0}]}},...ngDevMode?[{debugName:"statEditFields"}]:[]);textEditFields=c(()=>{const e=this.modalTextValues();return"AID"===this.category?[{key:"effects",label:"Effects",value:e.effects??"",multiline:!0}]:[]},...ngDevMode?[{debugName:"textEditFields"}]:[]);statRows=c(()=>{const e=this.selectedItem();return e?"WEAPONS"===this.category?[{key:"damage",label:"Damage",value:e.damage??"--"},{key:"weight",label:"Weight",value:e.weight??"--"},{key:"value",label:"Value",value:e.value??"--"}]:"APPAREL"===this.category?[{key:"damage",label:"DR",value:e.damage??"--"},{key:"weight",label:"WG",value:e.weight??"--"},{key:"value",label:"VAL",value:e.value??"--"}]:"AID"===this.category?[{key:"effects",label:"Effects",value:e.effects??"--"},{key:"weight",label:"WG",value:e.weight??"--"},{key:"value",label:"VAL",value:e.value??"--"}]:[{key:"weight",label:"WG",value:e.weight??"--"},{key:"value",label:"VAL",value:e.value??"--"}]:[]},...ngDevMode?[{debugName:"statRows"}]:[]);modalTitle=c(()=>{switch(this.category){case"WEAPONS":return"Add Weapon";case"APPAREL":return"Add Apparel";case"AID":return"Add Aid";case"MISC":return"Add Misc";case"AMMO":return"Add Ammo";default:return"Add Item"}},...ngDevMode?[{debugName:"modalTitle"}]:[]);openAddModal(){this.settings.editLockEnabled()||(this.editMode.set("ADD"),this.modalName.set(""),this.modalImageId.set(null),this.modalValues.set({damage:0,weight:0,value:0,quantity:this.defaultQuantity()}),this.modalTextValues.set({}),this.showStatEditModal.set(!0))}openStatEditModal(){if(this.settings.editLockEnabled())return;if(!this.selectedItem())return;this.playClickSound();const e=this.selectedItem();e&&(this.modalName.set(e.name),this.modalImageId.set(e.imageId??null),this.modalValues.set({damage:e.damage??0,weight:e.weight??0,value:e.value??0,quantity:this.normalizeQuantity(e.quantity)}),this.modalTextValues.set({effects:e.effects??""})),this.editMode.set("EDIT"),this.showStatEditModal.set(!0)}closeStatEditModal(){this.showStatEditModal.set(!1)}selectItem(e){const t=this.getEquippedId();this.setEquippedId(t===e?null:e),this.playClickSound()}async saveStatEditModal(e){const t=e.name?.trim()??"";if(!t)return;const a=this.selectedItem();let n;if(e.removeImage)n=void 0;else if(e.imageFile){const t=await this.imageStore.saveFile(e.imageFile);n=t.id}else n=a?.imageId;if("ADD"===this.editMode()){const a=this.supportsQuantity()?this.normalizeQuantity(e.values.quantity):void 0,o=this.getNextItemId();return this.updateItems(i=>[...i,{id:o,name:t,damage:this.normalizeStatValue(e.values.damage),weight:this.normalizeStatValue(e.values.weight),value:this.normalizeStatValue(e.values.value),imageId:n,effects:e.textValues?.effects,...this.supportsQuantity()?{quantity:a}:{}}]),this.setEquippedId(o),void this.closeStatEditModal()}const o=this.getEquippedId();null!==o&&(this.updateItems(a=>a.map(a=>a.id!==o?a:{...a,name:t,damage:this.normalizeStatValue(e.values.damage,a.damage),weight:this.normalizeStatValue(e.values.weight,a.weight),value:this.normalizeStatValue(e.values.value,a.value),imageId:n,...this.supportsQuantity()?{quantity:this.normalizeQuantity(e.values.quantity)}:{},effects:e.textValues?.effects??("AID"===this.category?a.effects:void 0)})),this.closeStatEditModal())}handleNameChange(e){if(this.modalName.set(e),"ADD"!==this.editMode())return;const t=this.getDefaultsForName(e);t&&("number"==typeof t.damage&&this.modalValues.set({...this.modalValues(),damage:t.damage}),"number"==typeof t.weight&&this.modalValues.set({...this.modalValues(),weight:t.weight}),"number"==typeof t.value&&this.modalValues.set({...this.modalValues(),value:t.value}),"string"==typeof t.effects&&this.modalTextValues.set({...this.modalTextValues(),effects:t.effects}))}dropSelected(){if(this.settings.editLockEnabled())return;const e=this.getEquippedId();null!==e&&(this.updateItems(t=>t.filter(t=>t.id!==e)),this.setEquippedId(null))}moveSelected(e){if(this.settings.editLockEnabled())return;const t=this.getEquippedId();null!==t&&this.updateItems(a=>{const n=a.findIndex(e=>e.id===t);if(-1===n)return a;const o=n+e;if(o<0||o>=a.length)return a;const i=a.slice(),[r]=i.splice(n,1);return i.splice(o,0,r),i})}displayItemName(e){const t="number"==typeof e.quantity&&Number.isFinite(e.quantity)?e.quantity:0;return this.supportsQuantity()&&t>1?`${e.name} (${t})`:e.name}getItems(){switch(this.category){case"WEAPONS":return this.settings.weaponItems();case"APPAREL":return this.settings.apparelItems();case"AID":return this.settings.aidItems();case"MISC":return this.settings.miscItems();case"AMMO":return this.settings.ammoItems();default:return[]}}updateItems(e){switch(this.category){case"WEAPONS":this.settings.weaponItems.update(e);break;case"APPAREL":this.settings.apparelItems.update(e);break;case"AID":this.settings.aidItems.update(e);break;case"MISC":this.settings.miscItems.update(e);break;case"AMMO":this.settings.ammoItems.update(e)}}getEquippedId(){switch(this.category){case"WEAPONS":return this.settings.equippedWeaponId();case"APPAREL":return this.settings.equippedApparelId();case"AID":return this.settings.equippedAidId();case"MISC":return this.settings.equippedMiscId();case"AMMO":return this.settings.equippedAmmoId();default:return null}}setEquippedId(e){switch(this.category){case"WEAPONS":this.settings.equippedWeaponId.set(e);break;case"APPAREL":this.settings.equippedApparelId.set(e);break;case"AID":this.settings.equippedAidId.set(e);break;case"MISC":this.settings.equippedMiscId.set(e);break;case"AMMO":this.settings.equippedAmmoId.set(e)}}getSourceNames(){switch(this.category){case"WEAPONS":return L.map(e=>e.name).filter(e=>e);case"APPAREL":return P.map(e=>e.name).filter(e=>e);case"AID":return k.map(e=>e.name).filter(e=>e);case"MISC":return M.map(e=>e.name).filter(e=>e);case"AMMO":return S.map(e=>e.name).filter(e=>e);default:return[]}}getNextItemId(){return this.getItems().reduce((e,t)=>Math.max(e,t.id),0)+1}normalizeStatValue(e,t){return"number"==typeof e&&Number.isFinite(e)?e:t}normalizeQuantity(e){return"number"==typeof e&&Number.isFinite(e)?Math.max(1,Math.floor(e)):1}playClickSound(){this.soundStore.playSound(this.settings.clickSoundId())}supportsQuantity(){return"APPAREL"===this.category||"AID"===this.category||"MISC"===this.category||"AMMO"===this.category}defaultQuantity(){return this.supportsQuantity()?1:0}getDefaultsForName(e){if("WEAPONS"===this.category){const t=L.find(t=>t.name===e);return t?{damage:t.damage,weight:t.weight,value:t.value}:null}if("APPAREL"===this.category){const t=P.find(t=>t.name===e);return t?{damage:t.dr,weight:t.wg,value:t.val}:null}if("AID"===this.category){const t=k.find(t=>t.name===e);return t?{weight:t.wg,value:t.val,effects:t.effects}:null}if("MISC"===this.category){const t=M.find(t=>t.name===e);return t?{weight:t.wg,value:t.val}:null}if("AMMO"===this.category){const t=S.find(t=>t.name===e);return t?{weight:t.wg,value:t.val}:null}return null}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:z,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:z,isStandalone:!0,selector:"pip-boy-inventory-layout",inputs:{category:"category"},ngImport:e,template:'<div class="resource-layout">\n <div class="resource-list">\n <ul class="resource-list-items">\n @for (item of getItems(); track item.id) {\n <li>\n <button\n type="button"\n class="resource-list-item"\n [class.is-selected]="getEquippedId() === item.id"\n (click)="selectItem(item.id)"\n >\n {{ displayItemName(item) }}\n </button>\n </li>\n } @empty {\n <li class="is-empty">No items added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="inventory-actions">\n <button type="button" class="resource-add" (click)="openAddModal()">\n + Add\n </button>\n @if (getEquippedId() !== null) {\n <button\n type="button"\n class="resource-edit"\n (click)="openStatEditModal()"\n >\n Edit\n </button>\n <button type="button" class="resource-drop" (click)="dropSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="resources-detail">\n @if (getItems().length > 0 && selectedItem()) {\n <button\n type="button"\n class="resource-image"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openStatEditModal()"\n >\n @if (selectedItem()?.imageId) {\n <img\n [src]="imageStore.getImageUrl(selectedItem()?.imageId)"\n alt="Selected item"\n />\n }\n </button>\n <div class="resource-stats">\n @for (row of statRows(); track row.key) {\n <button\n type="button"\n class="resource-stat"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openStatEditModal()"\n >\n <span>{{ row.label }}</span>\n <span>{{ row.value }}</span>\n </button>\n }\n </div>\n }\n </div>\n</div>\n<pip-boy-stat-edit-modal\n (closeResult)="closeStatEditModal()"\n (nameChange)="handleNameChange($event)"\n (save)="saveStatEditModal($event)"\n [open]="showStatEditModal()"\n [title]="editStatModalTitle()"\n [name]="modalName()"\n nameLabel="Item Name"\n [nameOptions]="itemNames()"\n [showName]="true"\n [imageUrl]="imageStore.getImageUrl(modalImageId())"\n [showImage]="true"\n [textFields]="textEditFields()"\n [fields]="statEditFields()"\n/>\n',styles:[':host{width:100%;height:100%;display:block}.resource-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.resource-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.resource-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.resource-list-items li{margin:0;padding:0;font-size:inherit}.resource-list-items .is-empty{opacity:.6}.resource-list-item{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;width:100%}.resource-list-item:hover{background:#0fbb6b1f}.resource-list-item.is-selected{background:#0fbb6b2e}.resource-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.inventory-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.resource-add{background:#0fbb6b14;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-add:hover{background:#0fbb6b2e}.resource-edit{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-edit:hover{background:#0fbb6b1f}.resource-drop{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-drop:hover{background:#0fbb6b1f}.resource-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.resource-move:hover{background:#0fbb6b1f}.resources-detail{display:flex;flex:1 1 45%;flex-direction:column;gap:1rem;height:100%;justify-content:space-between;min-height:0}.resource-image{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1 1 auto;flex-direction:column;min-height:0;justify-content:flex-start;padding:1rem;text-transform:uppercase;width:100%}.resource-image span{margin-top:auto;opacity:.7}.resource-image img{align-self:center;max-height:100%;max-width:100%;object-fit:contain;padding:0}.resource-image.is-locked{cursor:default;pointer-events:none}.resource-stats{display:flex;flex-direction:column;gap:.5rem;margin-top:auto;padding:.75rem;font-size:calc(1.15rem * var(--list-font-scale, 1))}.resource-stat{background:transparent;border:1px solid transparent;color:#0fbb6b;cursor:pointer;display:flex;justify-content:space-between;padding:.2rem .35rem;text-align:left;text-transform:uppercase;width:100%;font-size:inherit}.resource-stat:hover{background:#0fbb6b1f}.resource-stat.is-locked{cursor:default;pointer-events:none}.resource-stat span{padding:.25rem}.resource-stat--name{font-size:calc(clamp(.9rem,.9rem + .15rem * (100vw - 360px) / 840px,1.05rem) * var(--list-font-scale, 1));letter-spacing:.04em}@media(max-width:720px),(max-height:560px){.inventory-actions{gap:.35rem;margin:0 .75rem .75rem}.resource-add,.resource-edit,.resource-drop{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.resource-move{flex:0 0 1.6rem;height:2.1rem}}\n'],dependencies:[{kind:"component",type:F,selector:"pip-boy-stat-edit-modal",inputs:["open","title","name","nameLabel","showName","nameOptions","imageUrl","showImage","fields","textFields"],outputs:["closeResult","save","nameChange"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:z,decorators:[{type:n,args:[{selector:"pip-boy-inventory-layout",standalone:!0,imports:[F],template:'<div class="resource-layout">\n <div class="resource-list">\n <ul class="resource-list-items">\n @for (item of getItems(); track item.id) {\n <li>\n <button\n type="button"\n class="resource-list-item"\n [class.is-selected]="getEquippedId() === item.id"\n (click)="selectItem(item.id)"\n >\n {{ displayItemName(item) }}\n </button>\n </li>\n } @empty {\n <li class="is-empty">No items added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="inventory-actions">\n <button type="button" class="resource-add" (click)="openAddModal()">\n + Add\n </button>\n @if (getEquippedId() !== null) {\n <button\n type="button"\n class="resource-edit"\n (click)="openStatEditModal()"\n >\n Edit\n </button>\n <button type="button" class="resource-drop" (click)="dropSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="resources-detail">\n @if (getItems().length > 0 && selectedItem()) {\n <button\n type="button"\n class="resource-image"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openStatEditModal()"\n >\n @if (selectedItem()?.imageId) {\n <img\n [src]="imageStore.getImageUrl(selectedItem()?.imageId)"\n alt="Selected item"\n />\n }\n </button>\n <div class="resource-stats">\n @for (row of statRows(); track row.key) {\n <button\n type="button"\n class="resource-stat"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openStatEditModal()"\n >\n <span>{{ row.label }}</span>\n <span>{{ row.value }}</span>\n </button>\n }\n </div>\n }\n </div>\n</div>\n<pip-boy-stat-edit-modal\n (closeResult)="closeStatEditModal()"\n (nameChange)="handleNameChange($event)"\n (save)="saveStatEditModal($event)"\n [open]="showStatEditModal()"\n [title]="editStatModalTitle()"\n [name]="modalName()"\n nameLabel="Item Name"\n [nameOptions]="itemNames()"\n [showName]="true"\n [imageUrl]="imageStore.getImageUrl(modalImageId())"\n [showImage]="true"\n [textFields]="textEditFields()"\n [fields]="statEditFields()"\n/>\n',styles:[':host{width:100%;height:100%;display:block}.resource-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.resource-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.resource-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.resource-list-items li{margin:0;padding:0;font-size:inherit}.resource-list-items .is-empty{opacity:.6}.resource-list-item{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;width:100%}.resource-list-item:hover{background:#0fbb6b1f}.resource-list-item.is-selected{background:#0fbb6b2e}.resource-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.inventory-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.resource-add{background:#0fbb6b14;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-add:hover{background:#0fbb6b2e}.resource-edit{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-edit:hover{background:#0fbb6b1f}.resource-drop{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-drop:hover{background:#0fbb6b1f}.resource-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.resource-move:hover{background:#0fbb6b1f}.resources-detail{display:flex;flex:1 1 45%;flex-direction:column;gap:1rem;height:100%;justify-content:space-between;min-height:0}.resource-image{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1 1 auto;flex-direction:column;min-height:0;justify-content:flex-start;padding:1rem;text-transform:uppercase;width:100%}.resource-image span{margin-top:auto;opacity:.7}.resource-image img{align-self:center;max-height:100%;max-width:100%;object-fit:contain;padding:0}.resource-image.is-locked{cursor:default;pointer-events:none}.resource-stats{display:flex;flex-direction:column;gap:.5rem;margin-top:auto;padding:.75rem;font-size:calc(1.15rem * var(--list-font-scale, 1))}.resource-stat{background:transparent;border:1px solid transparent;color:#0fbb6b;cursor:pointer;display:flex;justify-content:space-between;padding:.2rem .35rem;text-align:left;text-transform:uppercase;width:100%;font-size:inherit}.resource-stat:hover{background:#0fbb6b1f}.resource-stat.is-locked{cursor:default;pointer-events:none}.resource-stat span{padding:.25rem}.resource-stat--name{font-size:calc(clamp(.9rem,.9rem + .15rem * (100vw - 360px) / 840px,1.05rem) * var(--list-font-scale, 1));letter-spacing:.04em}@media(max-width:720px),(max-height:560px){.inventory-actions{gap:.35rem;margin:0 .75rem .75rem}.resource-add,.resource-edit,.resource-drop{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.resource-move{flex:0 0 1.6rem;height:2.1rem}}\n']}]}],propDecorators:{category:[{type:m}]}});class q{constructor(){r(()=>{this.open()&&(this.draftName.set(this.name()),this.draftDescription.set(this.description()),this.draftValue.set(this.value()),this.draftImageUrl.set(this.imageUrl()),this.draftImageName.set(null),this.draftImageFile.set(null),this.removedImage.set(!1),this.clearPreviewUrl())})}static nextId=0;open=t(!1,...ngDevMode?[{debugName:"open"}]:[]);title=t("Edit Entry",...ngDevMode?[{debugName:"title"}]:[]);name=t("",...ngDevMode?[{debugName:"name"}]:[]);itemNames=t([],...ngDevMode?[{debugName:"itemNames"}]:[]);description=t("",...ngDevMode?[{debugName:"description"}]:[]);value=t(0,...ngDevMode?[{debugName:"value"}]:[]);valueLabel=t("Value",...ngDevMode?[{debugName:"valueLabel"}]:[]);valueMin=t(null,...ngDevMode?[{debugName:"valueMin"}]:[]);valueMax=t(null,...ngDevMode?[{debugName:"valueMax"}]:[]);showValue=t(!0,...ngDevMode?[{debugName:"showValue"}]:[]);imageUrl=t(null,...ngDevMode?[{debugName:"imageUrl"}]:[]);closeResult=u();save=u();draftDescription=o("",...ngDevMode?[{debugName:"draftDescription"}]:[]);draftName=o("",...ngDevMode?[{debugName:"draftName"}]:[]);draftValue=o(0,...ngDevMode?[{debugName:"draftValue"}]:[]);draftImageName=o(null,...ngDevMode?[{debugName:"draftImageName"}]:[]);draftImageUrl=o(null,...ngDevMode?[{debugName:"draftImageUrl"}]:[]);draftImageFile=o(null,...ngDevMode?[{debugName:"draftImageFile"}]:[]);removedImage=o(!1,...ngDevMode?[{debugName:"removedImage"}]:[]);nameListId="stat-entry-name-"+q.nextId++;previewUrl=null;closeModal(){this.clearPreviewUrl(),this.closeResult.emit()}updateName(e){this.draftName.set(e.target.value)}updateDescription(e){this.draftDescription.set(e.target.value)}updateValue(e){const t=Number(e.target.value);Number.isFinite(t)&&this.draftValue.set(this.clampValue(t))}onImageSelected(e){const t=e.target,a=t.files?.[0]??null;this.draftImageName.set(a?a.name:null),a&&(this.removedImage.set(!1),this.draftImageFile.set(a),this.setPreviewUrl(URL.createObjectURL(a)),t.value="")}removeImage(){this.draftImageName.set(null),this.draftImageUrl.set(null),this.draftImageFile.set(null),this.removedImage.set(!0),this.clearPreviewUrl()}submit(e){e?.preventDefault();const t={name:this.draftName(),description:this.draftDescription(),imageFile:this.draftImageFile(),removeImage:this.removedImage()};this.showValue()&&(t.value=this.clampValue(this.draftValue())),this.clearPreviewUrl(),this.save.emit(t),this.closeResult.emit()}clampValue(e){let t=e;const a=this.valueMin(),n=this.valueMax();return"number"==typeof a&&(t=Math.max(a,t)),"number"==typeof n&&(t=Math.min(n,t)),t}setPreviewUrl(e){this.clearPreviewUrl(),this.previewUrl=e,this.draftImageUrl.set(e)}clearPreviewUrl(){this.previewUrl&&(URL.revokeObjectURL(this.previewUrl),this.previewUrl=null)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:q,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:q,isStandalone:!0,selector:"pip-boy-stat-entry-modal",inputs:{open:{classPropertyName:"open",publicName:"open",isSignal:!0,isRequired:!1,transformFunction:null},title:{classPropertyName:"title",publicName:"title",isSignal:!0,isRequired:!1,transformFunction:null},name:{classPropertyName:"name",publicName:"name",isSignal:!0,isRequired:!1,transformFunction:null},itemNames:{classPropertyName:"itemNames",publicName:"itemNames",isSignal:!0,isRequired:!1,transformFunction:null},description:{classPropertyName:"description",publicName:"description",isSignal:!0,isRequired:!1,transformFunction:null},value:{classPropertyName:"value",publicName:"value",isSignal:!0,isRequired:!1,transformFunction:null},valueLabel:{classPropertyName:"valueLabel",publicName:"valueLabel",isSignal:!0,isRequired:!1,transformFunction:null},valueMin:{classPropertyName:"valueMin",publicName:"valueMin",isSignal:!0,isRequired:!1,transformFunction:null},valueMax:{classPropertyName:"valueMax",publicName:"valueMax",isSignal:!0,isRequired:!1,transformFunction:null},showValue:{classPropertyName:"showValue",publicName:"showValue",isSignal:!0,isRequired:!1,transformFunction:null},imageUrl:{classPropertyName:"imageUrl",publicName:"imageUrl",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{closeResult:"closeResult",save:"save"},ngImport:e,template:'@if (open()) {\n <div\n class="stat-entry-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="stat-entry-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title() }}</header>\n <form (submit)="submit($event)">\n <div class="stat-entry-modal-body">\n <label class="stat-entry-modal-field">\n <span>Name</span>\n <input\n type="text"\n [attr.list]="nameListId"\n [value]="draftName()"\n (input)="updateName($event)"\n />\n </label>\n @if (itemNames().length) {\n <datalist [id]="nameListId">\n @for (name of itemNames(); track name) {\n <option [value]="name"></option>\n }\n </datalist>\n }\n @if (showValue()) {\n <label class="stat-entry-modal-field">\n <span>{{ valueLabel() }}</span>\n <input\n type="number"\n [attr.min]="valueMin()"\n [attr.max]="valueMax()"\n [value]="draftValue()"\n (input)="updateValue($event)"\n />\n </label>\n }\n <label\n class="stat-entry-modal-field stat-entry-modal-field--description"\n >\n <span>Description</span>\n <textarea\n rows="6"\n [value]="draftDescription()"\n (input)="updateDescription($event)"\n ></textarea>\n </label>\n <div class="stat-entry-modal-image">\n <button\n type="button"\n class="stat-entry-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="stat-entry-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Entry preview" />\n }\n </div>\n </div>\n <div class="stat-entry-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".stat-entry-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.stat-entry-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:26rem;width:min(90vw,26rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.stat-entry-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.stat-entry-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.stat-entry-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.stat-entry-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.stat-entry-modal-field input,.stat-entry-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.stat-entry-modal-field input:focus,.stat-entry-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.stat-entry-modal-field textarea{min-height:6rem;resize:vertical;text-transform:none}.stat-entry-modal-image{display:flex;flex-direction:column;gap:.75rem}.stat-entry-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.stat-entry-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:8rem;object-fit:contain;padding:.5rem}.stat-entry-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.stat-entry-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-entry-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.stat-entry-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-entry-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.stat-entry-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.stat-entry-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:q,decorators:[{type:n,args:[{selector:"pip-boy-stat-entry-modal",standalone:!0,template:'@if (open()) {\n <div\n class="stat-entry-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="stat-entry-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title() }}</header>\n <form (submit)="submit($event)">\n <div class="stat-entry-modal-body">\n <label class="stat-entry-modal-field">\n <span>Name</span>\n <input\n type="text"\n [attr.list]="nameListId"\n [value]="draftName()"\n (input)="updateName($event)"\n />\n </label>\n @if (itemNames().length) {\n <datalist [id]="nameListId">\n @for (name of itemNames(); track name) {\n <option [value]="name"></option>\n }\n </datalist>\n }\n @if (showValue()) {\n <label class="stat-entry-modal-field">\n <span>{{ valueLabel() }}</span>\n <input\n type="number"\n [attr.min]="valueMin()"\n [attr.max]="valueMax()"\n [value]="draftValue()"\n (input)="updateValue($event)"\n />\n </label>\n }\n <label\n class="stat-entry-modal-field stat-entry-modal-field--description"\n >\n <span>Description</span>\n <textarea\n rows="6"\n [value]="draftDescription()"\n (input)="updateDescription($event)"\n ></textarea>\n </label>\n <div class="stat-entry-modal-image">\n <button\n type="button"\n class="stat-entry-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="stat-entry-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Entry preview" />\n }\n </div>\n </div>\n <div class="stat-entry-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".stat-entry-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.stat-entry-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:26rem;width:min(90vw,26rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.stat-entry-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.stat-entry-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.stat-entry-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.stat-entry-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.stat-entry-modal-field input,.stat-entry-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.stat-entry-modal-field input:focus,.stat-entry-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.stat-entry-modal-field textarea{min-height:6rem;resize:vertical;text-transform:none}.stat-entry-modal-image{display:flex;flex-direction:column;gap:.75rem}.stat-entry-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.stat-entry-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:8rem;object-fit:contain;padding:.5rem}.stat-entry-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.stat-entry-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-entry-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.stat-entry-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-entry-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.stat-entry-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.stat-entry-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],ctorParameters:()=>[],propDecorators:{open:[{type:e.Input,args:[{isSignal:!0,alias:"open",required:!1}]}],title:[{type:e.Input,args:[{isSignal:!0,alias:"title",required:!1}]}],name:[{type:e.Input,args:[{isSignal:!0,alias:"name",required:!1}]}],itemNames:[{type:e.Input,args:[{isSignal:!0,alias:"itemNames",required:!1}]}],description:[{type:e.Input,args:[{isSignal:!0,alias:"description",required:!1}]}],value:[{type:e.Input,args:[{isSignal:!0,alias:"value",required:!1}]}],valueLabel:[{type:e.Input,args:[{isSignal:!0,alias:"valueLabel",required:!1}]}],valueMin:[{type:e.Input,args:[{isSignal:!0,alias:"valueMin",required:!1}]}],valueMax:[{type:e.Input,args:[{isSignal:!0,alias:"valueMax",required:!1}]}],showValue:[{type:e.Input,args:[{isSignal:!0,alias:"showValue",required:!1}]}],imageUrl:[{type:e.Input,args:[{isSignal:!0,alias:"imageUrl",required:!1}]}],closeResult:[{type:e.Output,args:["closeResult"]}],save:[{type:e.Output,args:["save"]}]}});class W{constructor(){r(()=>{const e=this.items(),t=this.selectedId();e.length?null!==t&&e.some(e=>e.id===t)||this.selectedId.set(e[0].id):null!==t&&this.selectedId.set(null)})}category="SPECIAL";valueLabel="Value";valueMin=null;valueMax=null;settings=l(B);imageStore=l(x);soundStore=l(O);showEditModal=o(!1,...ngDevMode?[{debugName:"showEditModal"}]:[]);editMode=o("EDIT",...ngDevMode?[{debugName:"editMode"}]:[]);selectedId=o(null,...ngDevMode?[{debugName:"selectedId"}]:[]);items=c(()=>this.getItems(),...ngDevMode?[{debugName:"items"}]:[]);selectedItem=c(()=>{const e=this.selectedId();return null===e?null:this.items().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedItem"}]:[]);itemNames=c(()=>{const e=this.getSourceNames();return Array.from(new Set(e)).sort()},...ngDevMode?[{debugName:"itemNames"}]:[]);editModalTitle=c(()=>{if("ADD"===this.editMode())return"Add Entry";const e=this.selectedItem();return e?`Edit ${e.name}`:"Edit Entry"},...ngDevMode?[{debugName:"editModalTitle"}]:[]);modalName=c(()=>{const e=this.selectedItem();return"ADD"===this.editMode()?"":e?.name??""},...ngDevMode?[{debugName:"modalName"}]:[]);modalDescription=c(()=>{const e=this.selectedItem();return"ADD"===this.editMode()?"":e?.description??""},...ngDevMode?[{debugName:"modalDescription"}]:[]);modalValue=c(()=>{if("ADD"===this.editMode())return this.valueMin??0;const e=this.selectedItem();return e?.value??0},...ngDevMode?[{debugName:"modalValue"}]:[]);modalImage=c(()=>{const e=this.selectedItem();return"ADD"===this.editMode()?null:this.imageStore.getImageUrl(e?.imageId??null)},...ngDevMode?[{debugName:"modalImage"}]:[]);openAddModal(){this.settings.editLockEnabled()||(this.editMode.set("ADD"),this.showEditModal.set(!0))}openEditModal(){this.settings.editLockEnabled()||this.selectedItem()&&(this.playClickSound(),this.editMode.set("EDIT"),this.showEditModal.set(!0))}closeEditModal(){this.showEditModal.set(!1)}selectItem(e){this.selectedId.set(e),this.playClickSound()}async saveEditModal(e){const t=e.name.trim();if(!t)return;const a=this.selectedItem();let n;if(e.removeImage)n=void 0;else if(e.imageFile){const t=await this.imageStore.saveFile(e.imageFile);n=t.id}else n=a?.imageId;if("ADD"===this.editMode()){const a=this.getNextItemId(),o=this.valueMin??0;return this.updateItems(i=>[...i,{id:a,name:t,description:e.description,value:this.showValue()&&"number"==typeof e.value?e.value:o,imageId:n}]),this.selectedId.set(a),void this.closeEditModal()}const o=this.selectedId();null!==o&&(this.updateItems(a=>a.map(a=>a.id!==o?a:{...a,name:t,description:e.description,value:"number"==typeof e.value?e.value:a.value,imageId:n})),this.closeEditModal())}dropSelected(){if(this.settings.editLockEnabled())return;const e=this.selectedId();null!==e&&(this.updateItems(t=>t.filter(t=>t.id!==e)),this.selectedId.set(null))}moveSelected(e){if(this.settings.editLockEnabled())return;const t=this.selectedId();null!==t&&this.updateItems(a=>{const n=a.findIndex(e=>e.id===t);if(-1===n)return a;const o=n+e;if(o<0||o>=a.length)return a;const i=a.slice(),[r]=i.splice(n,1);return i.splice(o,0,r),i})}showValue(){return"SPECIAL"===this.category||"SKILLS"===this.category}getItems(){switch(this.category){case"SPECIAL":return this.settings.specialItems();case"SKILLS":return this.settings.skillItems();case"PERKS":return this.settings.perkItems();case"GENERAL":return this.settings.generalItems();default:return[]}}updateItems(e){switch(this.category){case"SPECIAL":this.settings.specialItems.update(e);break;case"SKILLS":this.settings.skillItems.update(e);break;case"PERKS":this.settings.perkItems.update(e);break;case"GENERAL":this.settings.generalItems.update(e)}}getSourceNames(){switch(this.category){case"SPECIAL":return R.map(e=>e.name);case"SKILLS":return D.map(e=>e.name);case"PERKS":return A.map(e=>e.name);default:return[]}}getNextItemId(){return this.items().reduce((e,t)=>Math.max(e,t.id),0)+1}playClickSound(){this.soundStore.playSound(this.settings.clickSoundId())}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:W,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:W,isStandalone:!0,selector:"pip-boy-stats-layout",inputs:{category:"category",valueLabel:"valueLabel",valueMin:"valueMin",valueMax:"valueMax"},ngImport:e,template:'<div class="resource-layout">\n <div class="resource-list">\n <ul class="resource-list-items">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="resource-list-item"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n <span class="resource-list-item-name">{{ item.name }}</span>\n @if (showValue()) {\n <span class="resource-list-item-value">{{ item.value }}</span>\n }\n </button>\n </li>\n } @empty {\n <li class="is-empty">No entries available.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="inventory-actions">\n <button type="button" class="resource-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="resource-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="resource-drop" (click)="dropSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="resources-detail">\n @if (selectedItem()) {\n <button\n type="button"\n class="resource-image"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openEditModal()"\n [attr.aria-label]="\n selectedItem()?.imageId ? \'Edit image\' : \'Select image\'\n "\n >\n @if (selectedItem()?.imageId) {\n <img\n [src]="imageStore.getImageUrl(selectedItem()?.imageId)"\n alt="Selected entry"\n />\n }\n </button>\n <button\n type="button"\n class="resource-description"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openEditModal()"\n >\n {{ selectedItem()?.description || \'Add description.\' }}\n </button>\n }\n </div>\n</div>\n<pip-boy-stat-entry-modal\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n [open]="showEditModal()"\n [title]="editModalTitle()"\n [name]="modalName()"\n [itemNames]="itemNames()"\n [description]="modalDescription()"\n [value]="modalValue()"\n [valueLabel]="valueLabel"\n [valueMin]="valueMin"\n [valueMax]="valueMax"\n [showValue]="showValue()"\n [imageUrl]="modalImage()"\n/>\n',styles:[':host{width:100%;height:100%;display:block}.resource-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.resource-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.resource-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.resource-list-items li{margin:0;padding:0;font-size:inherit}.resource-list-items .is-empty{opacity:.6}.resource-list-item{align-items:center;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:flex;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;justify-content:space-between;gap:.75rem;width:100%}.resource-list-item:hover{background:#0fbb6b1f}.resource-list-item.is-selected{background:#0fbb6b2e}.resource-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.resource-list-item-name{flex:1 1 auto}.resource-list-item-value{flex:0 0 auto;min-width:2.5rem;text-align:right}.inventory-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.resource-add{background:#0fbb6b14;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-add:hover{background:#0fbb6b2e}.resource-edit{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-edit:hover{background:#0fbb6b1f}.resource-drop{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-drop:hover{background:#0fbb6b1f}.resource-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.resource-move:hover{background:#0fbb6b1f}.resources-detail{display:flex;flex:1 1 45%;flex-direction:column;gap:1rem;height:100%;justify-content:space-between;min-height:0;padding-bottom:1rem}.resource-image{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1 1 auto;flex-direction:column;min-height:0;justify-content:flex-start;padding:1rem;text-transform:uppercase;width:100%}.resource-image span{margin-top:auto;opacity:.7}.resource-image img{align-self:center;max-height:100%;max-width:100%;object-fit:contain;padding:0}.resource-image.is-locked{cursor:default;pointer-events:none}.resource-description{background:#0fbb6b0d;border:1px solid rgba(15,187,107,.35);color:#0fbb6b;cursor:pointer;margin-top:auto;min-height:6rem;padding:.75rem;text-align:left;text-transform:none;width:100%;margin-bottom:1rem;font-size:calc(1.15rem * var(--list-font-scale, 1))}.resource-description:hover{background:#0fbb6b1f}.resource-description.is-locked{cursor:default;pointer-events:none}@media(max-width:720px),(max-height:560px){.inventory-actions{gap:.35rem;margin:0 .75rem .75rem}.resource-add,.resource-edit,.resource-drop{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.resource-move{flex:0 0 1.6rem;height:2.1rem}}\n'],dependencies:[{kind:"component",type:q,selector:"pip-boy-stat-entry-modal",inputs:["open","title","name","itemNames","description","value","valueLabel","valueMin","valueMax","showValue","imageUrl"],outputs:["closeResult","save"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:W,decorators:[{type:n,args:[{selector:"pip-boy-stats-layout",standalone:!0,imports:[q],template:'<div class="resource-layout">\n <div class="resource-list">\n <ul class="resource-list-items">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="resource-list-item"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n <span class="resource-list-item-name">{{ item.name }}</span>\n @if (showValue()) {\n <span class="resource-list-item-value">{{ item.value }}</span>\n }\n </button>\n </li>\n } @empty {\n <li class="is-empty">No entries available.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="inventory-actions">\n <button type="button" class="resource-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="resource-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="resource-drop" (click)="dropSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="resources-detail">\n @if (selectedItem()) {\n <button\n type="button"\n class="resource-image"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openEditModal()"\n [attr.aria-label]="\n selectedItem()?.imageId ? \'Edit image\' : \'Select image\'\n "\n >\n @if (selectedItem()?.imageId) {\n <img\n [src]="imageStore.getImageUrl(selectedItem()?.imageId)"\n alt="Selected entry"\n />\n }\n </button>\n <button\n type="button"\n class="resource-description"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openEditModal()"\n >\n {{ selectedItem()?.description || \'Add description.\' }}\n </button>\n }\n </div>\n</div>\n<pip-boy-stat-entry-modal\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n [open]="showEditModal()"\n [title]="editModalTitle()"\n [name]="modalName()"\n [itemNames]="itemNames()"\n [description]="modalDescription()"\n [value]="modalValue()"\n [valueLabel]="valueLabel"\n [valueMin]="valueMin"\n [valueMax]="valueMax"\n [showValue]="showValue()"\n [imageUrl]="modalImage()"\n/>\n',styles:[':host{width:100%;height:100%;display:block}.resource-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.resource-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.resource-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.resource-list-items li{margin:0;padding:0;font-size:inherit}.resource-list-items .is-empty{opacity:.6}.resource-list-item{align-items:center;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:flex;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;justify-content:space-between;gap:.75rem;width:100%}.resource-list-item:hover{background:#0fbb6b1f}.resource-list-item.is-selected{background:#0fbb6b2e}.resource-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.resource-list-item-name{flex:1 1 auto}.resource-list-item-value{flex:0 0 auto;min-width:2.5rem;text-align:right}.inventory-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.resource-add{background:#0fbb6b14;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-add:hover{background:#0fbb6b2e}.resource-edit{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-edit:hover{background:#0fbb6b1f}.resource-drop{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-drop:hover{background:#0fbb6b1f}.resource-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.resource-move:hover{background:#0fbb6b1f}.resources-detail{display:flex;flex:1 1 45%;flex-direction:column;gap:1rem;height:100%;justify-content:space-between;min-height:0;padding-bottom:1rem}.resource-image{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1 1 auto;flex-direction:column;min-height:0;justify-content:flex-start;padding:1rem;text-transform:uppercase;width:100%}.resource-image span{margin-top:auto;opacity:.7}.resource-image img{align-self:center;max-height:100%;max-width:100%;object-fit:contain;padding:0}.resource-image.is-locked{cursor:default;pointer-events:none}.resource-description{background:#0fbb6b0d;border:1px solid rgba(15,187,107,.35);color:#0fbb6b;cursor:pointer;margin-top:auto;min-height:6rem;padding:.75rem;text-align:left;text-transform:none;width:100%;margin-bottom:1rem;font-size:calc(1.15rem * var(--list-font-scale, 1))}.resource-description:hover{background:#0fbb6b1f}.resource-description.is-locked{cursor:default;pointer-events:none}@media(max-width:720px),(max-height:560px){.inventory-actions{gap:.35rem;margin:0 .75rem .75rem}.resource-add,.resource-edit,.resource-drop{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.resource-move{flex:0 0 1.6rem;height:2.1rem}}\n']}]}],ctorParameters:()=>[],propDecorators:{category:[{type:m}],valueLabel:[{type:m}],valueMin:[{type:m}],valueMax:[{type:m}]}});class H{open=!1;title="Confirm";message="This action cannot be undone. Are you sure you want to continue?";confirmLabel="Confirm";cancelLabel="Cancel";confirm=new s;closeResult=new s;closeModal(){this.closeResult.emit()}confirmReset(){this.confirm.emit()}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:H,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:H,isStandalone:!0,selector:"pip-boy-reset-confirm-modal",inputs:{open:"open",title:"title",message:"message",confirmLabel:"confirmLabel",cancelLabel:"cancelLabel"},outputs:{confirm:"confirm",closeResult:"closeResult"},ngImport:e,template:'@if (open) {\n <div\n class="reset-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n role="button"\n tabindex="0"\n >\n <div\n class="reset-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n role="dialog"\n tabindex="-1"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <div class="reset-modal-body">\n <p>{{ message }}</p>\n </div>\n <div class="reset-modal-actions">\n <button type="button" (click)="closeModal()">{{ cancelLabel }}</button>\n <button type="button" (click)="confirmReset()">\n {{ confirmLabel }}\n </button>\n </div>\n </div>\n </div>\n}\n',styles:[".reset-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:110}.reset-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:26rem;width:min(90vw,26rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.reset-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:.75rem;text-transform:uppercase}.reset-modal p{margin:0 0 1.25rem}.reset-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch}.reset-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.reset-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.reset-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"],dependencies:[{kind:"ngmodule",type:g}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:H,decorators:[{type:n,args:[{selector:"pip-boy-reset-confirm-modal",standalone:!0,imports:[g],template:'@if (open) {\n <div\n class="reset-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n role="button"\n tabindex="0"\n >\n <div\n class="reset-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n role="dialog"\n tabindex="-1"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <div class="reset-modal-body">\n <p>{{ message }}</p>\n </div>\n <div class="reset-modal-actions">\n <button type="button" (click)="closeModal()">{{ cancelLabel }}</button>\n <button type="button" (click)="confirmReset()">\n {{ confirmLabel }}\n </button>\n </div>\n </div>\n </div>\n}\n',styles:[".reset-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:110}.reset-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:26rem;width:min(90vw,26rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.reset-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:.75rem;text-transform:uppercase}.reset-modal p{margin:0 0 1.25rem}.reset-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch}.reset-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.reset-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.reset-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],title:[{type:m}],message:[{type:m}],confirmLabel:[{type:m}],cancelLabel:[{type:m}],confirm:[{type:d}],closeResult:[{type:d}]}});class U{constructor(){r(()=>{this.open()&&this.draft.set(this.value())})}open=t(!1,...ngDevMode?[{debugName:"open"}]:[]);title=t("Edit Name",...ngDevMode?[{debugName:"title"}]:[]);value=t("",...ngDevMode?[{debugName:"value"}]:[]);placeholder=t("Name",...ngDevMode?[{debugName:"placeholder"}]:[]);allowEmpty=t(!1,...ngDevMode?[{debugName:"allowEmpty"}]:[]);closeResult=u();save=u();draft=o("",...ngDevMode?[{debugName:"draft"}]:[]);updateDraft(e){this.draft.set(e.target.value)}closeModal(){this.closeResult.emit()}submit(){const e=this.draft().trim();(e||this.allowEmpty())&&this.save.emit(e),this.closeResult.emit()}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:U,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:U,isStandalone:!0,selector:"pip-boy-name-edit-modal",inputs:{open:{classPropertyName:"open",publicName:"open",isSignal:!0,isRequired:!1,transformFunction:null},title:{classPropertyName:"title",publicName:"title",isSignal:!0,isRequired:!1,transformFunction:null},value:{classPropertyName:"value",publicName:"value",isSignal:!0,isRequired:!1,transformFunction:null},placeholder:{classPropertyName:"placeholder",publicName:"placeholder",isSignal:!0,isRequired:!1,transformFunction:null},allowEmpty:{classPropertyName:"allowEmpty",publicName:"allowEmpty",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{closeResult:"closeResult",save:"save"},ngImport:e,template:'@if (open()) {\n <div\n class="name-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="name-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <h2>{{ title() }}</h2>\n <div class="name-modal-body">\n <label class="name-modal-field">\n <span>{{ placeholder() }}</span>\n <input\n type="text"\n [value]="draft()"\n (input)="updateDraft($event)"\n (keydown.enter)="submit()"\n />\n </label>\n </div>\n <div class="name-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="button" (click)="submit()">Save</button>\n </div>\n </div>\n </div>\n}\n',styles:[".name-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#000000b3;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:100}.name-modal{background:#071c12;border:1px solid rgba(15,187,107,.45);border-radius:.5rem;box-shadow:0 0 30px #0009;padding:1.5rem;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;color:#0fbb6b;text-transform:uppercase}.name-modal h2{font-size:clamp(1rem,1rem + (1.2rem - 1rem) * (100vw - 360px) / (1200px - 360px),1.2rem);margin:0 0 1rem}.name-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch}.name-modal-field{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1.5rem}.name-modal-field span{font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);opacity:.8}.name-modal-field input{background:transparent;border:1px solid rgba(15,187,107,.4);color:#0fbb6b;padding:.5rem .75rem;font:inherit}.name-modal-field input:focus{outline:none;border-color:#0fbb6b}.name-modal-actions{display:flex;justify-content:flex-end;gap:.75rem}.name-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;font:inherit;padding:.45rem 1rem;text-transform:uppercase}.name-modal-actions button:hover{background:#0fbb6b26;border-color:#0fbb6b}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:U,decorators:[{type:n,args:[{selector:"pip-boy-name-edit-modal",standalone:!0,template:'@if (open()) {\n <div\n class="name-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="name-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <h2>{{ title() }}</h2>\n <div class="name-modal-body">\n <label class="name-modal-field">\n <span>{{ placeholder() }}</span>\n <input\n type="text"\n [value]="draft()"\n (input)="updateDraft($event)"\n (keydown.enter)="submit()"\n />\n </label>\n </div>\n <div class="name-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="button" (click)="submit()">Save</button>\n </div>\n </div>\n </div>\n}\n',styles:[".name-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#000000b3;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:100}.name-modal{background:#071c12;border:1px solid rgba(15,187,107,.45);border-radius:.5rem;box-shadow:0 0 30px #0009;padding:1.5rem;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;color:#0fbb6b;text-transform:uppercase}.name-modal h2{font-size:clamp(1rem,1rem + (1.2rem - 1rem) * (100vw - 360px) / (1200px - 360px),1.2rem);margin:0 0 1rem}.name-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch}.name-modal-field{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1.5rem}.name-modal-field span{font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);opacity:.8}.name-modal-field input{background:transparent;border:1px solid rgba(15,187,107,.4);color:#0fbb6b;padding:.5rem .75rem;font:inherit}.name-modal-field input:focus{outline:none;border-color:#0fbb6b}.name-modal-actions{display:flex;justify-content:flex-end;gap:.75rem}.name-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;font:inherit;padding:.45rem 1rem;text-transform:uppercase}.name-modal-actions button:hover{background:#0fbb6b26;border-color:#0fbb6b}\n"]}]}],ctorParameters:()=>[],propDecorators:{open:[{type:e.Input,args:[{isSignal:!0,alias:"open",required:!1}]}],title:[{type:e.Input,args:[{isSignal:!0,alias:"title",required:!1}]}],value:[{type:e.Input,args:[{isSignal:!0,alias:"value",required:!1}]}],placeholder:[{type:e.Input,args:[{isSignal:!0,alias:"placeholder",required:!1}]}],allowEmpty:[{type:e.Input,args:[{isSignal:!0,alias:"allowEmpty",required:!1}]}],closeResult:[{type:e.Output,args:["closeResult"]}],save:[{type:e.Output,args:["save"]}]}});class V{settings=l(B);imageStore=l(x);soundStore=l(O);nameDraft=o("",...ngDevMode?[{debugName:"nameDraft"}]:[]);showNameModal=o(!1,...ngDevMode?[{debugName:"showNameModal"}]:[]);showVaultBoyDeleteModal=o(!1,...ngDevMode?[{debugName:"showVaultBoyDeleteModal"}]:[]);extraOptionModal=o(null,...ngDevMode?[{debugName:"extraOptionModal"}]:[]);extraOptionTitle=c(()=>{switch(this.extraOptionModal()){case"STIMPAK":case"LIMBS":return"Edit Text";default:return""}},...ngDevMode?[{debugName:"extraOptionTitle"}]:[]);extraOptionValue=c(()=>{const e=this.extraOptionModal();return"STIMPAK"===e?this.settings.stimpakLabel():"LIMBS"===e?this.settings.limbLabel():""},...ngDevMode?[{debugName:"extraOptionValue"}]:[]);selectVaultBoySlot(e){this.settings.selectedVaultBoyImageIndex.set(e),this.playClickSound()}addVaultBoySlot(){if(this.settings.editLockEnabled())return;if(this.settings.vaultBoyImages().length>=10)return;const e=this.settings.vaultBoyImages().length;this.settings.vaultBoyImages.update(e=>[...e,null]),this.settings.selectedVaultBoyImageIndex.set(e)}async onVaultBoyImageSelected(e){if(this.settings.editLockEnabled())return;const t=e.target,a=t.files?.[0]??null;if(!a)return;const n=await this.imageStore.saveFile(a),o=this.settings.selectedVaultBoyImageIndex();this.settings.vaultBoyImages.update(e=>e.map((e,t)=>t===o?n.id:e)),t.value=""}startNameEdit(){this.settings.editLockEnabled()||(this.nameDraft.set(this.settings.userName()),this.showNameModal.set(!0),this.playClickSound())}closeNameModal(){this.showNameModal.set(!1)}saveNameEdit(e){e.trim()&&this.settings.userName.set(e.trim()),this.closeNameModal()}openVaultBoyDeleteModal(){if(this.settings.editLockEnabled())return;const e=this.settings.vaultBoyImages();if(0===e.length)return;e[this.settings.selectedVaultBoyImageIndex()]?this.showVaultBoyDeleteModal.set(!0):this.confirmVaultBoyDelete()}closeVaultBoyDeleteModal(){this.showVaultBoyDeleteModal.set(!1)}confirmVaultBoyDelete(){if(this.settings.editLockEnabled())return;const e=this.settings.selectedVaultBoyImageIndex();this.settings.vaultBoyImages.update(t=>t.filter((t,a)=>a!==e));const t=this.settings.vaultBoyImages().length,a=0===t?0:Math.min(e,t-1);this.settings.selectedVaultBoyImageIndex.set(a),this.closeVaultBoyDeleteModal()}openExtraOptionModal(e){this.settings.editLockEnabled()||this.extraOptionModal.set(e)}closeExtraOptionModal(){this.extraOptionModal.set(null)}saveExtraOptionModal(e){const t=this.extraOptionModal();"STIMPAK"===t?this.settings.stimpakLabel.set(e):"LIMBS"===t&&this.settings.limbLabel.set(e),this.closeExtraOptionModal()}playClickSound(){this.soundStore.playSound(this.settings.clickSoundId())}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:V,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:V,isStandalone:!0,selector:"pip-boy-cnd-status",ngImport:e,template:'<div class="vault-boy-status">\n <label\n class="vault-boy-uploader"\n [class.is-locked]="settings.editLockEnabled()"\n for="vault-boy-image-input"\n >\n @if (settings.vaultBoyImages()[settings.selectedVaultBoyImageIndex()]) {\n <img\n [src]="\n imageStore.getImageUrl(\n settings.vaultBoyImages()[settings.selectedVaultBoyImageIndex()]\n )\n "\n alt="Vault Boy"\n />\n } @else if (settings.vaultBoyImages().length > 0) {\n <span>Click to upload an Image</span>\n }\n </label>\n <input\n #vaultBoyImageInput\n id="vault-boy-image-input"\n type="file"\n accept="image/*"\n [disabled]="settings.editLockEnabled()"\n (change)="onVaultBoyImageSelected($event)"\n />\n <div class="vault-boy-slots">\n @for (slot of settings.vaultBoyImages(); track $index) {\n <button\n type="button"\n class="vault-boy-slot"\n [class.is-active]="settings.selectedVaultBoyImageIndex() === $index"\n [attr.aria-label]="\'Select action-buttonimage slot \' + ($index + 1)"\n (click)="selectVaultBoySlot($index)"\n ></button>\n }\n @if (!settings.editLockEnabled()) {\n <button\n type="button"\n class="vault-boy-slot vault-boy-slot--add"\n (click)="addVaultBoySlot()"\n [disabled]="settings.vaultBoyImages().length >= 10"\n >\n +\n </button>\n <button\n type="button"\n class="vault-boy-slot vault-boy-slot--delete"\n (click)="openVaultBoyDeleteModal()"\n [disabled]="settings.vaultBoyImages().length === 0"\n >\n -\n </button>\n }\n </div>\n <button\n type="button"\n class="vault-boy-name"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="startNameEdit()"\n >\n {{ settings.userName() }} - Level {{ settings.userLevel() }}\n </button>\n</div>\n<div class="extra-options">\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'STIMPAK\')"\n >\n {{ settings.stimpakLabel() }}\n </button>\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'LIMBS\')"\n >\n {{ settings.limbLabel() }}\n </button>\n <pip-boy-reset-confirm-modal\n [open]="showVaultBoyDeleteModal()"\n title="Delete image"\n message="This will remove the selected slot. Continue?"\n confirmLabel="Delete"\n (closeResult)="closeVaultBoyDeleteModal()"\n (confirm)="confirmVaultBoyDelete()"\n />\n <pip-boy-name-edit-modal\n [open]="showNameModal()"\n [value]="nameDraft()"\n title="Edit Name"\n placeholder="Name"\n (closeResult)="closeNameModal()"\n (save)="saveNameEdit($event)"\n />\n <pip-boy-name-edit-modal\n [open]="extraOptionModal() !== null"\n [value]="extraOptionValue()"\n [title]="extraOptionTitle()"\n placeholder="Value"\n [allowEmpty]="true"\n (closeResult)="closeExtraOptionModal()"\n (save)="saveExtraOptionModal($event)"\n />\n</div>\n',styles:[":host{display:flex;flex:1;gap:1rem;min-height:0}.vault-boy-status{align-items:stretch;box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;gap:.75rem;justify-content:flex-start;margin:0 1rem 1rem;min-height:0;overflow:hidden}.vault-boy-uploader{align-items:center;cursor:pointer;display:flex;flex:1 1 auto;justify-content:center;min-height:0;overflow:hidden;text-transform:uppercase;width:100%}.vault-boy-uploader span{opacity:.7;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.vault-boy-uploader img{max-height:100%;max-width:100%;object-fit:contain;padding:.5rem}.vault-boy-uploader.is-locked{cursor:default;pointer-events:none}#vault-boy-image-input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.vault-boy-slots{display:flex;gap:.5rem;flex-wrap:wrap;justify-content:center}.vault-boy-slot{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;height:2rem;padding:0;width:2rem}.vault-boy-slot.is-active{background:#0fbb6b33;border-color:#0fbb6b}.vault-boy-slot:disabled{cursor:not-allowed;opacity:.4}.vault-boy-slot--add{border-style:dashed}.vault-boy-slot--delete{border-style:solid}.vault-boy-name{align-items:center;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:inline-flex;justify-content:center;padding:.5rem .75rem;text-align:center;font-size:clamp(1.45rem,1.45rem + (1.75rem - 1.45rem) * (100vw - 360px) / (1200px - 360px),1.75rem);width:100%}.vault-boy-name:hover{background:#0fbb6b1f}.vault-boy-name.is-locked{cursor:default}.extra-options{margin-top:.25rem;display:flex;flex-direction:column;font-size:calc(clamp(1.05rem,1.05rem + .2rem * (100vw - 360px) / 840px,1.25rem) * var(--list-font-scale, 1));align-items:flex-end;gap:.75rem;white-space:nowrap}.extra-options button{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font:inherit;padding:0;white-space:nowrap}.extra-options button:hover{opacity:.8}.extra-options button.is-locked{cursor:default}.extra-options .controller-button{font-size:inherit;white-space:nowrap}.extra-options .controller-button .large-par{display:inline;padding-left:.5rem;font-size:calc(clamp(1.45rem,1.45rem + .3rem * (100vw - 360px) / 840px,1.75rem) * var(--list-font-scale, 1));top:-.15rem;position:relative;white-space:nowrap}\n"],dependencies:[{kind:"component",type:H,selector:"pip-boy-reset-confirm-modal",inputs:["open","title","message","confirmLabel","cancelLabel"],outputs:["confirm","closeResult"]},{kind:"component",type:U,selector:"pip-boy-name-edit-modal",inputs:["open","title","value","placeholder","allowEmpty"],outputs:["closeResult","save"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:V,decorators:[{type:n,args:[{selector:"pip-boy-cnd-status",standalone:!0,imports:[H,U],template:'<div class="vault-boy-status">\n <label\n class="vault-boy-uploader"\n [class.is-locked]="settings.editLockEnabled()"\n for="vault-boy-image-input"\n >\n @if (settings.vaultBoyImages()[settings.selectedVaultBoyImageIndex()]) {\n <img\n [src]="\n imageStore.getImageUrl(\n settings.vaultBoyImages()[settings.selectedVaultBoyImageIndex()]\n )\n "\n alt="Vault Boy"\n />\n } @else if (settings.vaultBoyImages().length > 0) {\n <span>Click to upload an Image</span>\n }\n </label>\n <input\n #vaultBoyImageInput\n id="vault-boy-image-input"\n type="file"\n accept="image/*"\n [disabled]="settings.editLockEnabled()"\n (change)="onVaultBoyImageSelected($event)"\n />\n <div class="vault-boy-slots">\n @for (slot of settings.vaultBoyImages(); track $index) {\n <button\n type="button"\n class="vault-boy-slot"\n [class.is-active]="settings.selectedVaultBoyImageIndex() === $index"\n [attr.aria-label]="\'Select action-buttonimage slot \' + ($index + 1)"\n (click)="selectVaultBoySlot($index)"\n ></button>\n }\n @if (!settings.editLockEnabled()) {\n <button\n type="button"\n class="vault-boy-slot vault-boy-slot--add"\n (click)="addVaultBoySlot()"\n [disabled]="settings.vaultBoyImages().length >= 10"\n >\n +\n </button>\n <button\n type="button"\n class="vault-boy-slot vault-boy-slot--delete"\n (click)="openVaultBoyDeleteModal()"\n [disabled]="settings.vaultBoyImages().length === 0"\n >\n -\n </button>\n }\n </div>\n <button\n type="button"\n class="vault-boy-name"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="startNameEdit()"\n >\n {{ settings.userName() }} - Level {{ settings.userLevel() }}\n </button>\n</div>\n<div class="extra-options">\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'STIMPAK\')"\n >\n {{ settings.stimpakLabel() }}\n </button>\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'LIMBS\')"\n >\n {{ settings.limbLabel() }}\n </button>\n <pip-boy-reset-confirm-modal\n [open]="showVaultBoyDeleteModal()"\n title="Delete image"\n message="This will remove the selected slot. Continue?"\n confirmLabel="Delete"\n (closeResult)="closeVaultBoyDeleteModal()"\n (confirm)="confirmVaultBoyDelete()"\n />\n <pip-boy-name-edit-modal\n [open]="showNameModal()"\n [value]="nameDraft()"\n title="Edit Name"\n placeholder="Name"\n (closeResult)="closeNameModal()"\n (save)="saveNameEdit($event)"\n />\n <pip-boy-name-edit-modal\n [open]="extraOptionModal() !== null"\n [value]="extraOptionValue()"\n [title]="extraOptionTitle()"\n placeholder="Value"\n [allowEmpty]="true"\n (closeResult)="closeExtraOptionModal()"\n (save)="saveExtraOptionModal($event)"\n />\n</div>\n',styles:[":host{display:flex;flex:1;gap:1rem;min-height:0}.vault-boy-status{align-items:stretch;box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;gap:.75rem;justify-content:flex-start;margin:0 1rem 1rem;min-height:0;overflow:hidden}.vault-boy-uploader{align-items:center;cursor:pointer;display:flex;flex:1 1 auto;justify-content:center;min-height:0;overflow:hidden;text-transform:uppercase;width:100%}.vault-boy-uploader span{opacity:.7;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.vault-boy-uploader img{max-height:100%;max-width:100%;object-fit:contain;padding:.5rem}.vault-boy-uploader.is-locked{cursor:default;pointer-events:none}#vault-boy-image-input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.vault-boy-slots{display:flex;gap:.5rem;flex-wrap:wrap;justify-content:center}.vault-boy-slot{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;height:2rem;padding:0;width:2rem}.vault-boy-slot.is-active{background:#0fbb6b33;border-color:#0fbb6b}.vault-boy-slot:disabled{cursor:not-allowed;opacity:.4}.vault-boy-slot--add{border-style:dashed}.vault-boy-slot--delete{border-style:solid}.vault-boy-name{align-items:center;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:inline-flex;justify-content:center;padding:.5rem .75rem;text-align:center;font-size:clamp(1.45rem,1.45rem + (1.75rem - 1.45rem) * (100vw - 360px) / (1200px - 360px),1.75rem);width:100%}.vault-boy-name:hover{background:#0fbb6b1f}.vault-boy-name.is-locked{cursor:default}.extra-options{margin-top:.25rem;display:flex;flex-direction:column;font-size:calc(clamp(1.05rem,1.05rem + .2rem * (100vw - 360px) / 840px,1.25rem) * var(--list-font-scale, 1));align-items:flex-end;gap:.75rem;white-space:nowrap}.extra-options button{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font:inherit;padding:0;white-space:nowrap}.extra-options button:hover{opacity:.8}.extra-options button.is-locked{cursor:default}.extra-options .controller-button{font-size:inherit;white-space:nowrap}.extra-options .controller-button .large-par{display:inline;padding-left:.5rem;font-size:calc(clamp(1.45rem,1.45rem + .3rem * (100vw - 360px) / 840px,1.75rem) * var(--list-font-scale, 1));top:-.15rem;position:relative;white-space:nowrap}\n"]}]}]});class _{constructor(){"undefined"!=typeof window&&"DeviceMotionEvent"in window&&this.motionSupported.set(!0),"undefined"!=typeof window&&(this.startTicking(),this.startJitter())}audioContext=null;lastNoiseAt=0;tickTimer=null;jitterTimer=null;lastPointerLevel=null;level=o(0,...ngDevMode?[{debugName:"level"}]:[]);targetLevel=o(0,...ngDevMode?[{debugName:"targetLevel"}]:[]);motionEnabled=o(!1,...ngDevMode?[{debugName:"motionEnabled"}]:[]);motionSupported=o(!1,...ngDevMode?[{debugName:"motionSupported"}]:[]);showResistModal=o(!1,...ngDevMode?[{debugName:"showResistModal"}]:[]);resistPercent=o(12,...ngDevMode?[{debugName:"resistPercent"}]:[]);motionHandler=e=>{const t=e.accelerationIncludingGravity;if(!t)return;const a=Math.abs(t.x??0),n=Math.abs(t.y??0),o=Math.abs(t.z??0),i=Math.min(1,(a+n+o)/30);this.targetLevel.set(Number(i.toFixed(2)))};ngOnDestroy(){this.disableMotion(),this.stopTicking(),this.stopJitter()}getLevelPercent(){return`${Math.round(100*this.level())}%`}async enableMotion(){const e=DeviceMotionEvent;if(e.requestPermission){if("granted"!==await e.requestPermission())return}window.addEventListener("devicemotion",this.motionHandler),this.motionEnabled.set(!0)}disableMotion(){this.motionEnabled()&&window.removeEventListener("devicemotion",this.motionHandler),this.motionEnabled.set(!1)}updateFromPointer(e){if(this.motionEnabled())return;const t=e.currentTarget.getBoundingClientRect();if(!t.width)return;const a=Math.max(0,Math.min(t.width,e.clientX-t.left))/t.width;this.lastPointerLevel=Number(a.toFixed(2)),this.targetLevel.set(this.lastPointerLevel)}playNoise(){const e=Date.now();if(e-this.lastNoiseAt<500)return;this.lastNoiseAt=e;const t=this.getAudioContext();if(!t)return;const a=Math.floor(.2*t.sampleRate),n=t.createBuffer(1,a,t.sampleRate),o=n.getChannelData(0);for(let e=0;e<a;e+=1)o[e]=2*Math.random()-1;const i=t.createBufferSource();i.buffer=n;const r=t.createGain();r.gain.value=.7,i.connect(r),r.connect(t.destination),i.start()}startTicking(){if(null!==this.tickTimer)return;const e=()=>{const t=this.level();this.playTick(t);const a=Math.max(90,700-520*t);this.tickTimer=window.setTimeout(e,a)};this.tickTimer=window.setTimeout(e,400)}stopTicking(){null!==this.tickTimer&&(window.clearTimeout(this.tickTimer),this.tickTimer=null)}startJitter(){null===this.jitterTimer&&(this.jitterTimer=window.setInterval(()=>{const e=this.targetLevel(),t=.12*(Math.random()-.5),a=Math.max(0,Math.min(1,e+t)),n=this.level(),o=n+.35*(a-n);this.level.set(Number(o.toFixed(2)))},180))}stopJitter(){null!==this.jitterTimer&&(window.clearInterval(this.jitterTimer),this.jitterTimer=null)}playTick(e){const t=this.getAudioContext();if(!t)return;const a=t.createOscillator(),n=t.createGain(),o=t.currentTime,i=600+600*e;a.type="square",a.frequency.setValueAtTime(i,o),n.gain.setValueAtTime(.001,o),n.gain.exponentialRampToValueAtTime(.18,o+.01),n.gain.exponentialRampToValueAtTime(.001,o+.08),a.connect(n),n.connect(t.destination),a.start(o),a.stop(o+.09)}getAudioContext(){if(this.audioContext)return this.audioContext;try{return this.audioContext=new AudioContext,this.audioContext}catch{return null}}showEnableMotion(){return this.motionSupported()&&!this.motionEnabled()}openResistModal(){this.showResistModal.set(!0)}closeResistModal(){this.showResistModal.set(!1)}saveResistModal(e){const t=Number.parseInt(e,10);Number.isFinite(t)&&this.resistPercent.set(Math.max(1,t)),this.closeResistModal()}getResistLabel(){return`RAD RESIST ${this.resistPercent()}%`}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:_,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:_,isStandalone:!0,selector:"pip-boy-radiation-meter",ngImport:e,template:'<div class="radiation-panel">\n <div class="radiation-info">\n <button type="button" class="radiation-resist" (click)="openResistModal()">\n {{ getResistLabel() }}\n </button>\n @if (motionSupported()) {\n <div class="radiation-motion">\n @if (showEnableMotion()) {\n <button type="button" (click)="enableMotion()">Enable Motion</button>\n } @else {\n <button type="button" (click)="disableMotion()">\n Disable Motion\n </button>\n }\n </div>\n }\n </div>\n <div class="radiation-meter">\n <div\n class="radiation-meter-track"\n (pointermove)="updateFromPointer($event)"\n >\n <div class="radiation-meter-labels">\n <span class="radiation-meter-label" style="left: 50%">500</span>\n <span class="radiation-meter-label" style="left: 100%">1000</span>\n </div>\n <div class="radiation-meter-fill" [style.width]="getLevelPercent()"></div>\n <div\n class="radiation-meter-trigger"\n tabindex="0"\n (mouseenter)="playNoise()"\n (click)="playNoise()"\n (keyup.enter)="playNoise()"\n (keyup.space)="playNoise()"\n ></div>\n </div>\n <div class="radiation-meter-value">{{ getLevelPercent() }}</div>\n </div>\n</div>\n<pip-boy-name-edit-modal\n [open]="showResistModal()"\n title="RAD RESIST"\n [value]="resistPercent().toString()"\n placeholder="Percent"\n (closeResult)="closeResistModal()"\n (save)="saveResistModal($event)"\n/>\n',styles:[':host{display:flex;flex:1 1 auto;min-height:0}.radiation-panel{display:grid;grid-template-columns:30% 1fr;gap:1.5rem;min-height:0;padding:1rem;align-items:center;width:100%;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.radiation-info{display:flex;flex-direction:column}.radiation-resist{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;padding:.6rem .9rem;text-align:left;text-transform:uppercase;font-size:inherit}.radiation-resist:hover{border-color:#0fbb6b;background:#0fbb6b1f}.radiation-meter{display:flex;flex-direction:column;gap:.75rem;width:100%;justify-self:stretch}.radiation-meter-track{position:relative;width:100%;height:2.5rem;border:1px solid rgba(15,187,107,.4);background:#0fbb6b14;overflow:hidden}.radiation-meter-fill{position:absolute;top:0;left:0;height:100%;background:#0fbb6b73;box-shadow:0 0 20px #0fbb6b59}.radiation-meter-labels{position:absolute;top:-1.2rem;left:0;width:100%;height:1.2rem}.radiation-meter-label{position:absolute;transform:translate(-50%);font-size:calc(clamp(.7rem,.7rem + .15rem * (100vw - 360px) / 840px,.85rem) * var(--list-font-scale, 1));text-transform:uppercase}.radiation-meter-track:before{content:"";position:absolute;left:0;top:0;width:100%;height:25%;background:repeating-linear-gradient(to right,rgba(15,187,107,.35),rgba(15,187,107,.35) 2px,transparent 2px,transparent 12px);pointer-events:none}.radiation-meter-trigger{position:absolute;top:0;right:0;width:15%;height:40%;cursor:pointer;background:#0fbb6b0d}.radiation-meter-value{font-size:calc(clamp(.9rem,.9rem + .2rem * (100vw - 360px) / 840px,1.1rem) * var(--list-font-scale, 1));letter-spacing:.08em;text-transform:uppercase}.radiation-motion button{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;padding:.4rem .9rem;text-transform:uppercase}.radiation-motion button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n'],dependencies:[{kind:"component",type:U,selector:"pip-boy-name-edit-modal",inputs:["open","title","value","placeholder","allowEmpty"],outputs:["closeResult","save"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:_,decorators:[{type:n,args:[{selector:"pip-boy-radiation-meter",standalone:!0,imports:[U],template:'<div class="radiation-panel">\n <div class="radiation-info">\n <button type="button" class="radiation-resist" (click)="openResistModal()">\n {{ getResistLabel() }}\n </button>\n @if (motionSupported()) {\n <div class="radiation-motion">\n @if (showEnableMotion()) {\n <button type="button" (click)="enableMotion()">Enable Motion</button>\n } @else {\n <button type="button" (click)="disableMotion()">\n Disable Motion\n </button>\n }\n </div>\n }\n </div>\n <div class="radiation-meter">\n <div\n class="radiation-meter-track"\n (pointermove)="updateFromPointer($event)"\n >\n <div class="radiation-meter-labels">\n <span class="radiation-meter-label" style="left: 50%">500</span>\n <span class="radiation-meter-label" style="left: 100%">1000</span>\n </div>\n <div class="radiation-meter-fill" [style.width]="getLevelPercent()"></div>\n <div\n class="radiation-meter-trigger"\n tabindex="0"\n (mouseenter)="playNoise()"\n (click)="playNoise()"\n (keyup.enter)="playNoise()"\n (keyup.space)="playNoise()"\n ></div>\n </div>\n <div class="radiation-meter-value">{{ getLevelPercent() }}</div>\n </div>\n</div>\n<pip-boy-name-edit-modal\n [open]="showResistModal()"\n title="RAD RESIST"\n [value]="resistPercent().toString()"\n placeholder="Percent"\n (closeResult)="closeResistModal()"\n (save)="saveResistModal($event)"\n/>\n',styles:[':host{display:flex;flex:1 1 auto;min-height:0}.radiation-panel{display:grid;grid-template-columns:30% 1fr;gap:1.5rem;min-height:0;padding:1rem;align-items:center;width:100%;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.radiation-info{display:flex;flex-direction:column}.radiation-resist{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;padding:.6rem .9rem;text-align:left;text-transform:uppercase;font-size:inherit}.radiation-resist:hover{border-color:#0fbb6b;background:#0fbb6b1f}.radiation-meter{display:flex;flex-direction:column;gap:.75rem;width:100%;justify-self:stretch}.radiation-meter-track{position:relative;width:100%;height:2.5rem;border:1px solid rgba(15,187,107,.4);background:#0fbb6b14;overflow:hidden}.radiation-meter-fill{position:absolute;top:0;left:0;height:100%;background:#0fbb6b73;box-shadow:0 0 20px #0fbb6b59}.radiation-meter-labels{position:absolute;top:-1.2rem;left:0;width:100%;height:1.2rem}.radiation-meter-label{position:absolute;transform:translate(-50%);font-size:calc(clamp(.7rem,.7rem + .15rem * (100vw - 360px) / 840px,.85rem) * var(--list-font-scale, 1));text-transform:uppercase}.radiation-meter-track:before{content:"";position:absolute;left:0;top:0;width:100%;height:25%;background:repeating-linear-gradient(to right,rgba(15,187,107,.35),rgba(15,187,107,.35) 2px,transparent 2px,transparent 12px);pointer-events:none}.radiation-meter-trigger{position:absolute;top:0;right:0;width:15%;height:40%;cursor:pointer;background:#0fbb6b0d}.radiation-meter-value{font-size:calc(clamp(.9rem,.9rem + .2rem * (100vw - 360px) / 840px,1.1rem) * var(--list-font-scale, 1));letter-spacing:.08em;text-transform:uppercase}.radiation-motion button{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;padding:.4rem .9rem;text-transform:uppercase}.radiation-motion button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n']}]}],ctorParameters:()=>[]});class G{open=!1;title="Edit Effect";name="";description="";closeResult=new s;save=new s;draftName=o("",...ngDevMode?[{debugName:"draftName"}]:[]);draftDescription=o("",...ngDevMode?[{debugName:"draftDescription"}]:[]);ngOnChanges(e){if(e.open&&this.open)return this.draftName.set(this.name??""),void this.draftDescription.set(this.description??"");e.name&&this.draftName.set(this.name??""),e.description&&this.draftDescription.set(this.description??"")}updateName(e){this.draftName.set(e)}updateDescription(e){this.draftDescription.set(e)}closeModal(){this.closeResult.emit()}submit(e){e.preventDefault();const t=this.draftName().trim();t&&this.save.emit({name:t,description:this.draftDescription().trim()})}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:G,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:G,isStandalone:!0,selector:"pip-boy-effect-edit-modal",inputs:{open:"open",title:"title",name:"name",description:"description"},outputs:{closeResult:"closeResult",save:"save"},usesOnChanges:!0,ngImport:e,template:'@if (open) {\n <div\n class="effect-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="effect-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title }}</header>\n <form (submit)="submit($event)">\n <div class="effect-modal-body">\n <label class="effect-modal-field">\n <span>Name</span>\n <input\n type="text"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n <label class="effect-modal-field">\n <span>Description</span>\n <textarea\n rows="5"\n [value]="draftDescription()"\n (input)="updateDescription($any($event.target).value)"\n ></textarea>\n </label>\n </div>\n <div class="effect-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".effect-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.effect-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.effect-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.effect-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.effect-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.effect-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.effect-modal-field input,.effect-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.effect-modal-field input:focus,.effect-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.effect-modal-field textarea{resize:vertical;text-transform:none}.effect-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.effect-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.effect-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:G,decorators:[{type:n,args:[{selector:"pip-boy-effect-edit-modal",standalone:!0,template:'@if (open) {\n <div\n class="effect-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="effect-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title }}</header>\n <form (submit)="submit($event)">\n <div class="effect-modal-body">\n <label class="effect-modal-field">\n <span>Name</span>\n <input\n type="text"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n <label class="effect-modal-field">\n <span>Description</span>\n <textarea\n rows="5"\n [value]="draftDescription()"\n (input)="updateDescription($any($event.target).value)"\n ></textarea>\n </label>\n </div>\n <div class="effect-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".effect-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.effect-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.effect-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.effect-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.effect-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.effect-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.effect-modal-field input,.effect-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.effect-modal-field input:focus,.effect-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.effect-modal-field textarea{resize:vertical;text-transform:none}.effect-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.effect-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.effect-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],title:[{type:m}],name:[{type:m}],description:[{type:m}],closeResult:[{type:d}],save:[{type:d}]}});class ${settings=l(B);selectedId=o(null,...ngDevMode?[{debugName:"selectedId"}]:[]);showEditModal=o(!1,...ngDevMode?[{debugName:"showEditModal"}]:[]);editMode=o("ADD",...ngDevMode?[{debugName:"editMode"}]:[]);modalName=o("",...ngDevMode?[{debugName:"modalName"}]:[]);modalDescription=o("",...ngDevMode?[{debugName:"modalDescription"}]:[]);items=c(()=>this.settings.effectItems(),...ngDevMode?[{debugName:"items"}]:[]);selectedItem=c(()=>{const e=this.selectedId();return null===e?null:this.items().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedItem"}]:[]);openAddModal(){this.settings.editLockEnabled()||(this.editMode.set("ADD"),this.modalName.set(""),this.modalDescription.set(""),this.showEditModal.set(!0))}openEditModal(){if(this.settings.editLockEnabled())return;const e=this.selectedItem();e&&(this.editMode.set("EDIT"),this.modalName.set(e.name),this.modalDescription.set(e.description),this.showEditModal.set(!0))}closeEditModal(){this.showEditModal.set(!1)}saveEditModal(e){if(this.settings.editLockEnabled())return;const t=e.name.trim(),a=e.description.trim();if(!t)return;if("ADD"===this.editMode()){const e=this.getNextItemId();return this.settings.effectItems.update(n=>[...n,{id:e,name:t,description:a}]),this.selectedId.set(e),void this.closeEditModal()}const n=this.selectedId();null!==n&&(this.settings.effectItems.update(e=>e.map(e=>e.id===n?{...e,name:t,description:a}:e)),this.closeEditModal())}selectItem(e){this.selectedId.set(this.selectedId()===e?null:e)}deleteSelected(){if(this.settings.editLockEnabled())return;const e=this.selectedId();null!==e&&(this.settings.effectItems.update(t=>t.filter(t=>t.id!==e)),this.selectedId.set(null))}moveSelected(e){if(this.settings.editLockEnabled())return;const t=this.selectedId();null!==t&&this.settings.effectItems.update(a=>{const n=a.findIndex(e=>e.id===t);if(-1===n)return a;const o=n+e;if(o<0||o>=a.length)return a;const i=a.slice(),[r]=i.splice(n,1);return i.splice(o,0,r),i})}getNextItemId(){return this.items().reduce((e,t)=>Math.max(e,t.id),0)+1}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:$,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:$,isStandalone:!0,selector:"pip-boy-eff-layout",ngImport:e,template:'<div class="eff-layout">\n <ul class="eff-list">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="eff-row"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n <span class="eff-name">{{ item.name }}</span>\n <span class="eff-description">{{ item.description }}</span>\n </button>\n </li>\n } @empty {\n <li class="eff-empty">No effects added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="eff-actions">\n <button type="button" class="eff-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="eff-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="eff-delete" (click)="deleteSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="eff-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="eff-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n</div>\n<pip-boy-effect-edit-modal\n [open]="showEditModal()"\n [title]="editMode() === \'ADD\' ? \'Add Effect\' : \'Edit Effect\'"\n [name]="modalName()"\n [description]="modalDescription()"\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n/>\n',styles:[":host{display:block;width:100%;height:100%}.eff-layout{display:flex;flex-direction:column;height:100%;min-height:0}.eff-list{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.75rem 1rem .5rem;display:flex;flex-direction:column;justify-content:center;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.eff-list li{margin:0;padding:0}.eff-row{background:transparent;border:none;border-bottom:2px solid rgba(15,187,107,.6);color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.6rem .2rem;text-align:left;text-transform:none;white-space:normal;width:100%;display:grid;grid-template-columns:1fr 1fr;gap:1rem}.eff-row:hover{background:#0fbb6b1f}.eff-row.is-selected{background:#0fbb6b2e}.eff-list li:last-child .eff-row{border-bottom:none}.eff-name,.eff-description{word-break:break-word;font-size:inherit}.eff-empty{opacity:.6;padding:.4rem .2rem}.eff-actions{display:flex;gap:.5rem;padding:.75rem 1rem 1rem}.eff-add,.eff-edit,.eff-delete{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.eff-add:hover,.eff-edit:hover,.eff-delete:hover{background:#0fbb6b1f}.eff-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.eff-move:hover{background:#0fbb6b1f}@media(max-width:720px),(max-height:560px){.eff-actions{gap:.35rem;padding:.75rem .75rem .9rem}.eff-add,.eff-edit,.eff-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.eff-move{flex:0 0 1.6rem;height:2.1rem}}\n"],dependencies:[{kind:"component",type:G,selector:"pip-boy-effect-edit-modal",inputs:["open","title","name","description"],outputs:["closeResult","save"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:$,decorators:[{type:n,args:[{selector:"pip-boy-eff-layout",standalone:!0,imports:[G],template:'<div class="eff-layout">\n <ul class="eff-list">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="eff-row"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n <span class="eff-name">{{ item.name }}</span>\n <span class="eff-description">{{ item.description }}</span>\n </button>\n </li>\n } @empty {\n <li class="eff-empty">No effects added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="eff-actions">\n <button type="button" class="eff-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="eff-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="eff-delete" (click)="deleteSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="eff-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="eff-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n</div>\n<pip-boy-effect-edit-modal\n [open]="showEditModal()"\n [title]="editMode() === \'ADD\' ? \'Add Effect\' : \'Edit Effect\'"\n [name]="modalName()"\n [description]="modalDescription()"\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n/>\n',styles:[":host{display:block;width:100%;height:100%}.eff-layout{display:flex;flex-direction:column;height:100%;min-height:0}.eff-list{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.75rem 1rem .5rem;display:flex;flex-direction:column;justify-content:center;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.eff-list li{margin:0;padding:0}.eff-row{background:transparent;border:none;border-bottom:2px solid rgba(15,187,107,.6);color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.6rem .2rem;text-align:left;text-transform:none;white-space:normal;width:100%;display:grid;grid-template-columns:1fr 1fr;gap:1rem}.eff-row:hover{background:#0fbb6b1f}.eff-row.is-selected{background:#0fbb6b2e}.eff-list li:last-child .eff-row{border-bottom:none}.eff-name,.eff-description{word-break:break-word;font-size:inherit}.eff-empty{opacity:.6;padding:.4rem .2rem}.eff-actions{display:flex;gap:.5rem;padding:.75rem 1rem 1rem}.eff-add,.eff-edit,.eff-delete{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.eff-add:hover,.eff-edit:hover,.eff-delete:hover{background:#0fbb6b1f}.eff-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.eff-move:hover{background:#0fbb6b1f}@media(max-width:720px),(max-height:560px){.eff-actions{gap:.35rem;padding:.75rem .75rem .9rem}.eff-add,.eff-edit,.eff-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.eff-move{flex:0 0 1.6rem;height:2.1rem}}\n"]}]}]});class j{settings=l(B);soundStore=l(O);selectedQuestId=o(null,...ngDevMode?[{debugName:"selectedQuestId"}]:[]);selectedTaskId=o(null,...ngDevMode?[{debugName:"selectedTaskId"}]:[]);showEditModal=o(!1,...ngDevMode?[{debugName:"showEditModal"}]:[]);editTarget=o("QUEST",...ngDevMode?[{debugName:"editTarget"}]:[]);editMode=o("ADD",...ngDevMode?[{debugName:"editMode"}]:[]);editingTaskId=o(null,...ngDevMode?[{debugName:"editingTaskId"}]:[]);modalName=o("",...ngDevMode?[{debugName:"modalName"}]:[]);quests=c(()=>this.settings.questItems(),...ngDevMode?[{debugName:"quests"}]:[]);selectedQuest=c(()=>{const e=this.selectedQuestId();return null===e?null:this.quests().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedQuest"}]:[]);tasks=c(()=>this.selectedQuest()?.tasks??[],...ngDevMode?[{debugName:"tasks"}]:[]);selectedTask=c(()=>{const e=this.selectedTaskId();return null===e?null:this.tasks().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedTask"}]:[]);modalTitle=c(()=>{const e=this.editTarget(),t=this.editMode();return"TASK"===e?"ADD"===t?"Add Task":"Edit Task":"ADD"===t?"Add Quest":"Edit Quest"},...ngDevMode?[{debugName:"modalTitle"}]:[]);selectQuest(e){const t=this.selectedQuestId()===e?null:e;this.selectedQuestId.set(t),null===t&&this.selectedTaskId.set(null),this.playClickSound()}selectTask(e){this.selectedTaskId.set(this.selectedTaskId()===e?null:e),this.playClickSound()}openAddQuest(){this.settings.editLockEnabled()||(this.editTarget.set("QUEST"),this.editMode.set("ADD"),this.modalName.set(""),this.showEditModal.set(!0))}openEditQuest(e){this.settings.editLockEnabled()||(this.editTarget.set("QUEST"),this.editMode.set("EDIT"),this.modalName.set(e.name),this.selectedQuestId.set(e.id),this.showEditModal.set(!0))}openAddTask(){this.settings.editLockEnabled()||this.selectedQuest()&&(this.editTarget.set("TASK"),this.editMode.set("ADD"),this.editingTaskId.set(null),this.modalName.set(""),this.showEditModal.set(!0))}openEditTask(e){this.settings.editLockEnabled()||(this.editTarget.set("TASK"),this.editMode.set("EDIT"),this.editingTaskId.set(e.id),this.modalName.set(e.name),this.showEditModal.set(!0))}openEditSelectedQuest(){if(this.settings.editLockEnabled())return;const e=this.selectedQuest();e&&(this.playClickSound(),this.openEditQuest(e))}openEditSelectedTask(){if(this.settings.editLockEnabled())return;const e=this.selectedTask();e&&(this.playClickSound(),this.openEditTask(e))}closeEditModal(){this.showEditModal.set(!1)}saveEditModal(e){const t=e.name?.trim()??"";if(!t)return;if("QUEST"===this.editTarget()){if("ADD"===this.editMode()){const e=this.getNextQuestId();this.settings.questItems.update(a=>[...a,{id:e,name:t,completed:!1,tasks:[]}]),this.selectedQuestId.set(e),this.selectedTaskId.set(null)}else{const e=this.selectedQuestId();if(null===e)return;this.settings.questItems.update(a=>a.map(a=>a.id===e?{...a,name:t}:a))}return void this.closeEditModal()}const a=this.selectedQuest();if(a){if("ADD"===this.editMode()){const e=this.getNextTaskId(a);this.settings.questItems.update(n=>n.map(n=>n.id===a.id?{...n,tasks:[...n.tasks,{id:e,name:t,completed:!1}]}:n))}else{const e=this.editingTaskId();if(null===e)return;this.settings.questItems.update(n=>n.map(n=>n.id===a.id?{...n,tasks:n.tasks.map(a=>a.id===e?{...a,name:t}:a)}:n))}this.closeEditModal()}}toggleQuest(e){this.settings.editLockEnabled()||(this.playClickSound(),this.settings.questItems.update(t=>t.map(t=>t.id===e?{...t,completed:!t.completed}:t)))}toggleTask(e){const t=this.selectedQuest();t&&(this.settings.editLockEnabled()||(this.playClickSound(),this.settings.questItems.update(a=>a.map(a=>a.id===t.id?{...a,tasks:a.tasks.map(t=>t.id===e?{...t,completed:!t.completed}:t)}:a))))}deleteSelectedQuest(){if(this.settings.editLockEnabled())return;const e=this.selectedQuestId();null!==e&&(this.settings.questItems.update(t=>t.filter(t=>t.id!==e)),this.selectedQuestId.set(null),this.selectedTaskId.set(null))}deleteSelectedTask(){if(this.settings.editLockEnabled())return;const e=this.selectedQuest(),t=this.selectedTaskId();e&&null!==t&&(this.settings.questItems.update(a=>a.map(a=>a.id===e.id?{...a,tasks:a.tasks.filter(e=>e.id!==t)}:a)),this.selectedTaskId.set(null))}moveSelectedQuest(e){if(this.settings.editLockEnabled())return;const t=this.selectedQuestId();null!==t&&this.settings.questItems.update(a=>{const n=a.findIndex(e=>e.id===t);if(-1===n)return a;const o=n+e;if(o<0||o>=a.length)return a;const i=a.slice(),[r]=i.splice(n,1);return i.splice(o,0,r),i})}moveSelectedTask(e){if(this.settings.editLockEnabled())return;const t=this.selectedQuest(),a=this.selectedTaskId();t&&null!==a&&this.settings.questItems.update(n=>n.map(n=>{if(n.id!==t.id)return n;const o=n.tasks.findIndex(e=>e.id===a);if(-1===o)return n;const i=o+e;if(i<0||i>=n.tasks.length)return n;const r=n.tasks.slice(),[l]=r.splice(o,1);return r.splice(i,0,l),{...n,tasks:r}}))}getNextQuestId(){return this.quests().reduce((e,t)=>Math.max(e,t.id),0)+1}getNextTaskId(e){return e.tasks.reduce((e,t)=>Math.max(e,t.id),0)+1}playClickSound(){this.soundStore.playSound(this.settings.clickSoundId())}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:j,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:j,isStandalone:!0,selector:"pip-boy-quests-layout",ngImport:e,template:'<div class="quest-layout">\n <div class="quest-column">\n <ul class="quest-list">\n @for (quest of quests(); track quest.id) {\n <li\n class="quest-row"\n [class.is-selected]="selectedQuestId() === quest.id"\n (click)="selectQuest(quest.id)"\n (keyup.enter)="selectQuest(quest.id)"\n tabindex="0"\n >\n <button\n type="button"\n class="quest-toggle"\n [class.is-checked]="quest.completed"\n [disabled]="settings.editLockEnabled()"\n (click)="toggleQuest(quest.id); $event.stopPropagation()"\n aria-label="Toggle quest"\n ></button>\n <button\n type="button"\n class="quest-name"\n (click)="selectQuest(quest.id); $event.stopPropagation()"\n >\n {{ quest.name }}\n </button>\n </li>\n } @empty {\n <li class="quest-empty">No quests added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="quest-actions">\n <button type="button" class="quest-add" (click)="openAddQuest()">\n + Add\n </button>\n <button\n type="button"\n class="quest-edit"\n [disabled]="!selectedQuest()"\n (click)="openEditSelectedQuest()"\n >\n Edit\n </button>\n <button\n type="button"\n class="quest-delete"\n [disabled]="!selectedQuest()"\n (click)="deleteSelectedQuest()"\n >\n - Delete\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedQuest()"\n (click)="moveSelectedQuest(-1)"\n aria-label="Move quest up"\n >\n ▲\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedQuest()"\n (click)="moveSelectedQuest(1)"\n aria-label="Move quest down"\n >\n ▼\n </button>\n </div>\n }\n </div>\n <div class="quest-column">\n <ul class="quest-list">\n @if (selectedQuest()) {\n @for (task of tasks(); track task.id) {\n <li\n class="quest-row"\n [class.is-selected]="selectedTaskId() === task.id"\n (click)="selectTask(task.id)"\n (keyup.enter)="selectTask(task.id)"\n tabindex="0"\n >\n <button\n type="button"\n class="quest-toggle"\n [class.is-checked]="task.completed"\n [disabled]="settings.editLockEnabled()"\n (click)="toggleTask(task.id); $event.stopPropagation()"\n aria-label="Toggle task"\n ></button>\n <button\n type="button"\n class="quest-name"\n (click)="selectTask(task.id); $event.stopPropagation()"\n >\n {{ task.name }}\n </button>\n </li>\n } @empty {\n <li class="quest-empty">No tasks added.</li>\n }\n } @else {\n <li class="quest-empty">Select a quest to view tasks.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="quest-actions">\n @if (selectedQuest()) {\n <button type="button" class="quest-add" (click)="openAddTask()">\n + Add\n </button>\n <button\n type="button"\n class="quest-edit"\n [disabled]="!selectedTask()"\n (click)="openEditSelectedTask()"\n >\n Edit\n </button>\n <button\n type="button"\n class="quest-delete"\n [disabled]="!selectedTask()"\n (click)="deleteSelectedTask()"\n >\n - Delete\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedTask()"\n (click)="moveSelectedTask(-1)"\n aria-label="Move task up"\n >\n ▲\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedTask()"\n (click)="moveSelectedTask(1)"\n aria-label="Move task down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n</div>\n<pip-boy-stat-edit-modal\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n [open]="showEditModal()"\n [title]="modalTitle()"\n [name]="modalName()"\n nameLabel="Name"\n [showName]="true"\n [fields]="[]"\n/>\n',styles:[":host{display:block;width:100%;height:100%}.quest-layout{display:flex;gap:1.5rem;height:100%;min-height:0}.quest-column{display:flex;flex:1 1 50%;flex-direction:column;min-height:0}.quest-list{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.quest-row{align-items:center;display:grid;grid-template-columns:1.5rem 1fr;gap:.6rem;padding:.25rem .35rem .25rem .2rem;font-size:inherit}.quest-row.is-selected{background:#0fbb6b2e}.quest-toggle{background:transparent;border:1px solid rgba(15,187,107,.65);cursor:pointer;height:.9rem;width:.9rem}.quest-toggle.is-checked{background:#0fbb6b}.quest-toggle:disabled{cursor:default;opacity:.6}.quest-name{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:0;text-align:left}.quest-name:hover{opacity:.8}.quest-empty{opacity:.6;padding:0 .2rem}.quest-actions{display:flex;gap:.5rem;justify-content:flex-end;margin:0 1rem 1rem;padding:0}.quest-add{background:#0fbb6b14;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.quest-add:hover{background:#0fbb6b2e}.quest-edit,.quest-delete{background:#0fbb6b0d;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.quest-edit:hover,.quest-delete:hover{background:#0fbb6b1f}.quest-edit:disabled,.quest-delete:disabled{cursor:not-allowed;opacity:.5}.quest-move{background:#0fbb6b0d;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.quest-move:hover{background:#0fbb6b1f}.quest-move:disabled{cursor:not-allowed;opacity:.5}.quest-actions button{flex:1 1 0}.quest-actions .quest-move{flex:0 0 2rem;width:2rem;padding:0}@media(max-width:720px),(max-height:560px){.quest-actions{gap:.35rem;margin:0 .75rem .75rem}.quest-add,.quest-edit,.quest-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.quest-move,.quest-actions .quest-move{flex:0 0 1.6rem;width:1.6rem;height:2.1rem}}\n"],dependencies:[{kind:"component",type:F,selector:"pip-boy-stat-edit-modal",inputs:["open","title","name","nameLabel","showName","nameOptions","imageUrl","showImage","fields","textFields"],outputs:["closeResult","save","nameChange"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:j,decorators:[{type:n,args:[{selector:"pip-boy-quests-layout",standalone:!0,imports:[F],template:'<div class="quest-layout">\n <div class="quest-column">\n <ul class="quest-list">\n @for (quest of quests(); track quest.id) {\n <li\n class="quest-row"\n [class.is-selected]="selectedQuestId() === quest.id"\n (click)="selectQuest(quest.id)"\n (keyup.enter)="selectQuest(quest.id)"\n tabindex="0"\n >\n <button\n type="button"\n class="quest-toggle"\n [class.is-checked]="quest.completed"\n [disabled]="settings.editLockEnabled()"\n (click)="toggleQuest(quest.id); $event.stopPropagation()"\n aria-label="Toggle quest"\n ></button>\n <button\n type="button"\n class="quest-name"\n (click)="selectQuest(quest.id); $event.stopPropagation()"\n >\n {{ quest.name }}\n </button>\n </li>\n } @empty {\n <li class="quest-empty">No quests added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="quest-actions">\n <button type="button" class="quest-add" (click)="openAddQuest()">\n + Add\n </button>\n <button\n type="button"\n class="quest-edit"\n [disabled]="!selectedQuest()"\n (click)="openEditSelectedQuest()"\n >\n Edit\n </button>\n <button\n type="button"\n class="quest-delete"\n [disabled]="!selectedQuest()"\n (click)="deleteSelectedQuest()"\n >\n - Delete\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedQuest()"\n (click)="moveSelectedQuest(-1)"\n aria-label="Move quest up"\n >\n ▲\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedQuest()"\n (click)="moveSelectedQuest(1)"\n aria-label="Move quest down"\n >\n ▼\n </button>\n </div>\n }\n </div>\n <div class="quest-column">\n <ul class="quest-list">\n @if (selectedQuest()) {\n @for (task of tasks(); track task.id) {\n <li\n class="quest-row"\n [class.is-selected]="selectedTaskId() === task.id"\n (click)="selectTask(task.id)"\n (keyup.enter)="selectTask(task.id)"\n tabindex="0"\n >\n <button\n type="button"\n class="quest-toggle"\n [class.is-checked]="task.completed"\n [disabled]="settings.editLockEnabled()"\n (click)="toggleTask(task.id); $event.stopPropagation()"\n aria-label="Toggle task"\n ></button>\n <button\n type="button"\n class="quest-name"\n (click)="selectTask(task.id); $event.stopPropagation()"\n >\n {{ task.name }}\n </button>\n </li>\n } @empty {\n <li class="quest-empty">No tasks added.</li>\n }\n } @else {\n <li class="quest-empty">Select a quest to view tasks.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="quest-actions">\n @if (selectedQuest()) {\n <button type="button" class="quest-add" (click)="openAddTask()">\n + Add\n </button>\n <button\n type="button"\n class="quest-edit"\n [disabled]="!selectedTask()"\n (click)="openEditSelectedTask()"\n >\n Edit\n </button>\n <button\n type="button"\n class="quest-delete"\n [disabled]="!selectedTask()"\n (click)="deleteSelectedTask()"\n >\n - Delete\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedTask()"\n (click)="moveSelectedTask(-1)"\n aria-label="Move task up"\n >\n ▲\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedTask()"\n (click)="moveSelectedTask(1)"\n aria-label="Move task down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n</div>\n<pip-boy-stat-edit-modal\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n [open]="showEditModal()"\n [title]="modalTitle()"\n [name]="modalName()"\n nameLabel="Name"\n [showName]="true"\n [fields]="[]"\n/>\n',styles:[":host{display:block;width:100%;height:100%}.quest-layout{display:flex;gap:1.5rem;height:100%;min-height:0}.quest-column{display:flex;flex:1 1 50%;flex-direction:column;min-height:0}.quest-list{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.quest-row{align-items:center;display:grid;grid-template-columns:1.5rem 1fr;gap:.6rem;padding:.25rem .35rem .25rem .2rem;font-size:inherit}.quest-row.is-selected{background:#0fbb6b2e}.quest-toggle{background:transparent;border:1px solid rgba(15,187,107,.65);cursor:pointer;height:.9rem;width:.9rem}.quest-toggle.is-checked{background:#0fbb6b}.quest-toggle:disabled{cursor:default;opacity:.6}.quest-name{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:0;text-align:left}.quest-name:hover{opacity:.8}.quest-empty{opacity:.6;padding:0 .2rem}.quest-actions{display:flex;gap:.5rem;justify-content:flex-end;margin:0 1rem 1rem;padding:0}.quest-add{background:#0fbb6b14;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.quest-add:hover{background:#0fbb6b2e}.quest-edit,.quest-delete{background:#0fbb6b0d;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.quest-edit:hover,.quest-delete:hover{background:#0fbb6b1f}.quest-edit:disabled,.quest-delete:disabled{cursor:not-allowed;opacity:.5}.quest-move{background:#0fbb6b0d;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.quest-move:hover{background:#0fbb6b1f}.quest-move:disabled{cursor:not-allowed;opacity:.5}.quest-actions button{flex:1 1 0}.quest-actions .quest-move{flex:0 0 2rem;width:2rem;padding:0}@media(max-width:720px),(max-height:560px){.quest-actions{gap:.35rem;margin:0 .75rem .75rem}.quest-add,.quest-edit,.quest-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.quest-move,.quest-actions .quest-move{flex:0 0 1.6rem;width:1.6rem;height:2.1rem}}\n"]}]}]});class Q{soundStore=l(O);audio=null;audioUrl=null;currentChannel=null;currentSoundId=null;endedHandlers=new Map;setOnEnded(e,t){this.endedHandlers.set(e,t),this.currentChannel===e&&this.audio&&(this.audio.onended=t??null)}isPlaying(e){return!(!this.audio||this.currentChannel!==e||this.audio.paused)}async play(e,t){if(!t)return;if(this.audio&&this.currentChannel===e&&this.currentSoundId===t)return void await this.audio.play().catch(()=>{});this.stop();const a=await this.soundStore.getRecord(t);if(!a)return;const n=URL.createObjectURL(a.blob),o=new Audio(n);o.onended=this.endedHandlers.get(e)??null,this.audio=o,this.audioUrl=n,this.currentChannel=e,this.currentSoundId=t,await o.play().catch(()=>{})}async toggle(e,t){this.audio&&this.currentChannel===e&&this.currentSoundId===t?this.audio.paused?await this.audio.play().catch(()=>{}):this.audio.pause():await this.play(e,t)}pause(e){this.audio&&this.currentChannel===e&&this.audio.pause()}stop(e){e&&this.currentChannel!==e||(this.audio&&(this.audio.pause(),this.audio.currentTime=0),this.audioUrl&&URL.revokeObjectURL(this.audioUrl),this.audio=null,this.audioUrl=null,this.currentChannel=null,this.currentSoundId=null)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Q,deps:[],target:e.ɵɵFactoryTarget.Injectable});static"ɵprov"=e.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Q,providedIn:"root"})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Q,decorators:[{type:i,args:[{providedIn:"root"}]}]});class K{open=!1;title="Edit Audio";name="";fileLabel=null;nameLabel="Song Name";fileFieldLabel="Song File";selectLabel="Select Song";closeResult=new s;save=new s;draftName=o("",...ngDevMode?[{debugName:"draftName"}]:[]);draftFileLabel=o(null,...ngDevMode?[{debugName:"draftFileLabel"}]:[]);draftFile=null;ngOnChanges(e){if(e.open&&this.open)return this.draftName.set(this.name??""),this.draftFileLabel.set(this.fileLabel),void(this.draftFile=null);e.name&&this.draftName.set(this.name??""),e.fileLabel&&this.draftFileLabel.set(this.fileLabel)}closeModal(){this.closeResult.emit()}updateName(e){this.draftName.set(e)}onFileSelected(e){const t=e.target,a=t.files?.[0]??null;this.draftFile=a,this.draftFileLabel.set(a?.name??this.fileLabel),t&&(t.value="")}removeFile(){this.draftFile=null,this.draftFileLabel.set(null)}submit(e){e.preventDefault();const t=this.draftName().trim();t&&this.draftFile&&this.save.emit({name:t,file:this.draftFile})}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:K,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:K,isStandalone:!0,selector:"pip-boy-audio-edit-modal",inputs:{open:"open",title:"title",name:"name",fileLabel:"fileLabel",nameLabel:"nameLabel",fileFieldLabel:"fileFieldLabel",selectLabel:"selectLabel"},outputs:{closeResult:"closeResult",save:"save"},usesOnChanges:!0,ngImport:e,template:'@if (open) {\n <div\n class="audio-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="audio-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <form (submit)="submit($event)">\n <div class="audio-modal-body">\n <label class="audio-modal-field">\n <span>{{ nameLabel }}</span>\n <input\n type="text"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n <div class="audio-modal-field">\n <span>{{ fileFieldLabel }}</span>\n <div class="audio-modal-file-row">\n <button\n type="button"\n class="audio-modal-file-button"\n (click)="audioFileInput.click()"\n >\n {{ draftFileLabel() ?? selectLabel }}\n </button>\n @if (draftFileLabel()) {\n <button\n type="button"\n class="audio-modal-file-remove"\n (click)="removeFile()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #audioFileInput\n type="file"\n accept="audio/*"\n (change)="onFileSelected($event)"\n />\n </div>\n </div>\n <div class="audio-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".audio-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.audio-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.audio-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.audio-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.audio-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.audio-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.audio-modal-field input{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.audio-modal-field input:focus{outline:none;border-color:#0fbb6b}.audio-modal-file-row{display:flex;gap:.5rem;align-items:center}.audio-modal-file-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;flex:1 1 auto;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.audio-modal-file-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.audio-modal-file-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.audio-modal-file-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.audio-modal input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.audio-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.audio-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.audio-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:K,decorators:[{type:n,args:[{selector:"pip-boy-audio-edit-modal",standalone:!0,template:'@if (open) {\n <div\n class="audio-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="audio-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <form (submit)="submit($event)">\n <div class="audio-modal-body">\n <label class="audio-modal-field">\n <span>{{ nameLabel }}</span>\n <input\n type="text"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n <div class="audio-modal-field">\n <span>{{ fileFieldLabel }}</span>\n <div class="audio-modal-file-row">\n <button\n type="button"\n class="audio-modal-file-button"\n (click)="audioFileInput.click()"\n >\n {{ draftFileLabel() ?? selectLabel }}\n </button>\n @if (draftFileLabel()) {\n <button\n type="button"\n class="audio-modal-file-remove"\n (click)="removeFile()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #audioFileInput\n type="file"\n accept="audio/*"\n (change)="onFileSelected($event)"\n />\n </div>\n </div>\n <div class="audio-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".audio-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.audio-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.audio-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.audio-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.audio-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.audio-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.audio-modal-field input{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.audio-modal-field input:focus{outline:none;border-color:#0fbb6b}.audio-modal-file-row{display:flex;gap:.5rem;align-items:center}.audio-modal-file-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;flex:1 1 auto;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.audio-modal-file-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.audio-modal-file-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.audio-modal-file-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.audio-modal input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.audio-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.audio-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.audio-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],title:[{type:m}],name:[{type:m}],fileLabel:[{type:m}],nameLabel:[{type:m}],fileFieldLabel:[{type:m}],selectLabel:[{type:m}],closeResult:[{type:d}],save:[{type:d}]}});class Y{constructor(){r(()=>{const e=this.items(),t=this.selectedId();e.length?null!==t&&e.some(e=>e.id===t)||this.setSelectedId(e[0].id):null!==t&&this.setSelectedId(null)})}category="NOTES";settings=l(B);soundStore=l(O);audioPlayer=l(Q);showEditModal=o(!1,...ngDevMode?[{debugName:"showEditModal"}]:[]);editMode=o("ADD",...ngDevMode?[{debugName:"editMode"}]:[]);modalName=o("",...ngDevMode?[{debugName:"modalName"}]:[]);modalFileLabel=o(null,...ngDevMode?[{debugName:"modalFileLabel"}]:[]);autoplayEnabled=o(!1,...ngDevMode?[{debugName:"autoplayEnabled"}]:[]);items=c(()=>this.getItems(),...ngDevMode?[{debugName:"items"}]:[]);selectedItem=c(()=>{const e=this.selectedId();return null===e?null:this.items().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedItem"}]:[]);modalTitle=c(()=>{const e=this.editMode(),t="RADIO"===this.category?"Radio":"Note";return"ADD"===e?`Add ${t}`:`Edit ${t}`},...ngDevMode?[{debugName:"modalTitle"}]:[]);modalLabelPrefix=c(()=>"RADIO"===this.category?"Song":"Note",...ngDevMode?[{debugName:"modalLabelPrefix"}]:[]);ngOnDestroy(){"NOTES"===this.category&&this.audioPlayer.stop("NOTES"),this.audioPlayer.setOnEnded(this.getChannel(),null)}openAddModal(){this.settings.editLockEnabled()||(this.editMode.set("ADD"),this.modalName.set(""),this.modalFileLabel.set(null),this.showEditModal.set(!0))}openEditModal(){if(this.settings.editLockEnabled())return;const e=this.selectedItem();e&&(this.editMode.set("EDIT"),this.modalName.set(e.name),this.modalFileLabel.set(this.soundStore.getSoundLabel(e.soundId)),this.showEditModal.set(!0),this.playClickSound())}closeEditModal(){this.showEditModal.set(!1)}selectItem(e){const t=this.selectedId();this.setSelectedId(t===e?null:e),this.playClickSound()}async saveEditModal(e){if(this.settings.editLockEnabled())return;const t=e.name.trim();if(!t||!e.file)return;const a=await this.soundStore.saveFile(e.file);if("ADD"===this.editMode()){const e=this.getNextItemId();return this.updateItems(n=>[...n,{id:e,name:t,soundId:a.id}]),this.setSelectedId(e),void this.closeEditModal()}const n=this.selectedId();null!==n&&(this.updateItems(e=>e.map(e=>e.id===n?{...e,name:t,soundId:a.id}:e)),this.closeEditModal())}deleteSelected(){if(this.settings.editLockEnabled())return;const e=this.selectedId();null!==e&&(this.updateItems(t=>t.filter(t=>t.id!==e)),this.setSelectedId(null),this.audioPlayer.stop(this.getChannel()))}moveSelected(e){if(this.settings.editLockEnabled())return;const t=this.selectedId();null!==t&&this.updateItems(a=>{const n=a.findIndex(e=>e.id===t);if(-1===n)return a;const o=n+e;if(o<0||o>=a.length)return a;const i=a.slice(),[r]=i.splice(n,1);return i.splice(o,0,r),i})}async playSelected(){const e=this.items();if(!e.length)return;let t=this.selectedItem();t||(t=e[0],this.setSelectedId(t.id)),await this.audioPlayer.play(this.getChannel(),t.soundId)}pauseSelected(){this.audioPlayer.pause(this.getChannel())}stopSelected(){this.audioPlayer.stop(this.getChannel())}toggleAutoplay(){const e=!this.autoplayEnabled();this.autoplayEnabled.set(e),e?this.audioPlayer.setOnEnded(this.getChannel(),()=>{this.playNext()}):this.audioPlayer.setOnEnded(this.getChannel(),null)}async playNext(){const e=this.items();if(!e.length)return;const t=this.selectedId(),a=e.findIndex(e=>e.id===t),n=e[-1===a?0:(a+1)%e.length];this.setSelectedId(n.id),await this.audioPlayer.play(this.getChannel(),n.soundId)}getChannel(){return"RADIO"===this.category?"RADIO":"NOTES"}getItems(){return"RADIO"===this.category?this.settings.radioItems():this.settings.notesItems()}updateItems(e){"RADIO"===this.category?this.settings.radioItems.update(e):this.settings.notesItems.update(e)}selectedId(){return"RADIO"===this.category?this.settings.selectedRadioItemId():this.settings.selectedNotesItemId()}setSelectedId(e){"RADIO"===this.category?this.settings.selectedRadioItemId.set(e):this.settings.selectedNotesItemId.set(e)}getNextItemId(){return this.items().reduce((e,t)=>Math.max(e,t.id),0)+1}playClickSound(){this.soundStore.playSound(this.settings.clickSoundId())}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Y,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:Y,isStandalone:!0,selector:"pip-boy-music-layout",inputs:{category:"category"},ngImport:e,template:'<div class="music-layout">\n <div class="music-list">\n <ul class="music-list-items">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="music-list-item"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n {{ item.name }}\n </button>\n </li>\n } @empty {\n <li class="is-empty">No items added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="music-actions">\n <button type="button" class="music-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="music-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="music-delete" (click)="deleteSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="music-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="music-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="music-controls">\n <div class="music-controls-inner">\n <button type="button" class="music-control" (click)="playSelected()">\n Play\n </button>\n <button type="button" class="music-control" (click)="pauseSelected()">\n Pause\n </button>\n <button type="button" class="music-control" (click)="stopSelected()">\n Stop\n </button>\n <button\n type="button"\n class="music-control"\n [class.is-active]="autoplayEnabled()"\n (click)="toggleAutoplay()"\n >\n Autoplay\n </button>\n </div>\n </div>\n</div>\n<pip-boy-audio-edit-modal\n [open]="showEditModal()"\n [title]="modalTitle()"\n [name]="modalName()"\n [fileLabel]="modalFileLabel()"\n [nameLabel]="modalLabelPrefix() + \' Name\'"\n [fileFieldLabel]="modalLabelPrefix() + \' File\'"\n [selectLabel]="\'Select \' + modalLabelPrefix()"\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n/>\n',styles:[':host{width:100%;height:100%;display:block}.music-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.music-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.music-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.music-list-items li{margin:0;padding:0;font-size:inherit}.music-list-items .is-empty{opacity:.6}.music-list-item{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;width:100%}.music-list-item:hover{background:#0fbb6b1f}.music-list-item.is-selected{background:#0fbb6b2e}.music-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.music-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.music-add{background:#0fbb6b14;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.music-add:hover{background:#0fbb6b2e}.music-edit,.music-delete{background:#0fbb6b0d;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.music-edit:hover,.music-delete:hover{background:#0fbb6b1f}.music-move{background:#0fbb6b0d;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.music-move:hover{background:#0fbb6b1f}.music-controls{display:flex;flex:1 1 45%;min-height:0;align-items:center;justify-content:center}.music-controls-inner{display:flex;flex-direction:column;gap:.75rem;width:min(18rem,100%)}.music-control{background:#0fbb6b0d;border:1px solid rgba(15,187,107,.6);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);letter-spacing:.08em;padding:.6rem .75rem;text-transform:uppercase}.music-control:hover,.music-control.is-active{background:#0fbb6b1f;border-color:#0fbb6b}@media(max-width:720px),(max-height:560px){.music-actions{gap:.35rem;margin:0 .75rem .75rem}.music-add,.music-edit,.music-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.music-move{flex:0 0 1.6rem;height:2.1rem}.music-controls-inner{flex-direction:row;flex-wrap:wrap;gap:.5rem;justify-content:center;padding:.25rem;width:100%}.music-control{flex:1 1 calc(50% - .5rem);font-size:clamp(.7rem,.7rem + (.85rem - .7rem) * (100vw - 360px) / (1200px - 360px),.85rem);padding:.35rem .5rem;border-radius:.4rem}}\n'],dependencies:[{kind:"component",type:K,selector:"pip-boy-audio-edit-modal",inputs:["open","title","name","fileLabel","nameLabel","fileFieldLabel","selectLabel"],outputs:["closeResult","save"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Y,decorators:[{type:n,args:[{selector:"pip-boy-music-layout",standalone:!0,imports:[K],template:'<div class="music-layout">\n <div class="music-list">\n <ul class="music-list-items">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="music-list-item"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n {{ item.name }}\n </button>\n </li>\n } @empty {\n <li class="is-empty">No items added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="music-actions">\n <button type="button" class="music-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="music-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="music-delete" (click)="deleteSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="music-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="music-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="music-controls">\n <div class="music-controls-inner">\n <button type="button" class="music-control" (click)="playSelected()">\n Play\n </button>\n <button type="button" class="music-control" (click)="pauseSelected()">\n Pause\n </button>\n <button type="button" class="music-control" (click)="stopSelected()">\n Stop\n </button>\n <button\n type="button"\n class="music-control"\n [class.is-active]="autoplayEnabled()"\n (click)="toggleAutoplay()"\n >\n Autoplay\n </button>\n </div>\n </div>\n</div>\n<pip-boy-audio-edit-modal\n [open]="showEditModal()"\n [title]="modalTitle()"\n [name]="modalName()"\n [fileLabel]="modalFileLabel()"\n [nameLabel]="modalLabelPrefix() + \' Name\'"\n [fileFieldLabel]="modalLabelPrefix() + \' File\'"\n [selectLabel]="\'Select \' + modalLabelPrefix()"\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n/>\n',styles:[':host{width:100%;height:100%;display:block}.music-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.music-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.music-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.music-list-items li{margin:0;padding:0;font-size:inherit}.music-list-items .is-empty{opacity:.6}.music-list-item{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;width:100%}.music-list-item:hover{background:#0fbb6b1f}.music-list-item.is-selected{background:#0fbb6b2e}.music-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.music-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.music-add{background:#0fbb6b14;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.music-add:hover{background:#0fbb6b2e}.music-edit,.music-delete{background:#0fbb6b0d;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.music-edit:hover,.music-delete:hover{background:#0fbb6b1f}.music-move{background:#0fbb6b0d;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.music-move:hover{background:#0fbb6b1f}.music-controls{display:flex;flex:1 1 45%;min-height:0;align-items:center;justify-content:center}.music-controls-inner{display:flex;flex-direction:column;gap:.75rem;width:min(18rem,100%)}.music-control{background:#0fbb6b0d;border:1px solid rgba(15,187,107,.6);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);letter-spacing:.08em;padding:.6rem .75rem;text-transform:uppercase}.music-control:hover,.music-control.is-active{background:#0fbb6b1f;border-color:#0fbb6b}@media(max-width:720px),(max-height:560px){.music-actions{gap:.35rem;margin:0 .75rem .75rem}.music-add,.music-edit,.music-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.music-move{flex:0 0 1.6rem;height:2.1rem}.music-controls-inner{flex-direction:row;flex-wrap:wrap;gap:.5rem;justify-content:center;padding:.25rem;width:100%}.music-control{flex:1 1 calc(50% - .5rem);font-size:clamp(.7rem,.7rem + (.85rem - .7rem) * (100vw - 360px) / (1200px - 360px),.85rem);padding:.35rem .5rem;border-radius:.4rem}}\n']}]}],ctorParameters:()=>[],propDecorators:{category:[{type:m}]}});class J{open=!1;listFontScale=1.25;closeResult=new s;previewListFontScale=new s;appVersion=E;updateListFontScale(e){const t=Number(e);if(!Number.isFinite(t))return;const a=Math.min(150,Math.max(50,t))/100*1.25;this.listFontScale=a,this.previewListFontScale.emit(a)}listFontScalePercent(){return Math.round(this.listFontScale/1.25*100)}closeModal(){this.closeResult.emit()}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:J,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:J,isStandalone:!0,selector:"pip-boy-welcome-modal",inputs:{open:"open",listFontScale:"listFontScale"},outputs:{closeResult:"closeResult",previewListFontScale:"previewListFontScale"},ngImport:e,template:'@if (open) {\n <div\n class="welcome-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n aria-hidden="true"\n >\n <div\n class="welcome"\n (click)="$event.stopPropagation()"\n (keydown.escape)="closeModal()"\n role="dialog"\n aria-modal="true"\n aria-labelledby="pipUiWelcomeTitle"\n tabindex="-1"\n >\n <header class="welcome__header">\n <div class="welcome__title" id="pipUiWelcomeTitle">\n Welcome to Pip UI\n <span class="welcome__version">v{{ appVersion }}</span>\n </div>\n <div class="welcome__subtitle">\n A fan made Pip-Boy 3000 style simulator.\n </div>\n </header>\n\n <div class="welcome__body">\n <div class="welcome__intro">\n <p>A wrist terminal for roleplay sessions and more!</p>\n </div>\n\n <div class="welcome__divider" aria-hidden="true"></div>\n\n <section class="welcome__section" aria-labelledby="welcomeFontTitle">\n <div class="welcome__section-head">\n <div class="welcome__section-title" id="welcomeFontTitle">\n Global Font Size\n </div>\n <p class="welcome__section-text">\n Adjusts the size of list text and key UI labels across tabs.\n </p>\n </div>\n\n <div class="welcome__slider">\n <input\n class="welcome__range"\n type="range"\n min="50"\n max="150"\n step="1"\n [value]="listFontScalePercent()"\n (input)="updateListFontScale($any($event.target).value)"\n aria-label="Global font size"\n />\n <span class="welcome__value">{{ listFontScalePercent() }}%</span>\n </div>\n\n <p class="welcome__hint">\n You can adjust this anytime later in the settings menu.\n </p>\n </section>\n\n <div class="welcome__divider" aria-hidden="true"></div>\n\n <section class="welcome__section" aria-labelledby="welcomeNpmTitle">\n <div class="welcome__section-head">\n <div class="welcome__section-title" id="welcomeNpmTitle">Npm</div>\n <p class="welcome__section-text">\n Install the package to use it in your project.\n </p>\n </div>\n\n <dl class="welcome__meta" aria-label="Install information">\n <div class="welcome__row">\n <dt class="welcome__label">Package</dt>\n <dd class="welcome__data"><code>@vault-tec/pip-boy</code></dd>\n </div>\n\n <div class="welcome__row">\n <dt class="welcome__label">Install</dt>\n <dd class="welcome__data">\n <code>npm install @vault-tec/pip-boy</code>\n </dd>\n </div>\n\n <div class="welcome__row">\n <dt class="welcome__label">NPM</dt>\n <dd class="welcome__data">\n <a\n href="https://www.npmjs.com/package/@vault-tec/pip-boy"\n target="_blank"\n rel="noreferrer"\n >\n npmjs.com/package/@vault-tec/pip-boy\n </a>\n </dd>\n </div>\n </dl>\n\n <p class="welcome__disclaimer">\n Unofficial fan project. No official game assets included. Not\n affiliated with or endorsed by Bethesda Softworks or ZeniMax Media.\n </p>\n </section>\n </div>\n\n <footer class="welcome__actions">\n <button type="button" (click)="closeModal()">Close</button>\n </footer>\n </div>\n </div>\n}\n',styles:[".welcome-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0000009e;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:110}.welcome{margin:1rem;max-height:calc(100vh - 2rem);max-height:calc(100svh - 2rem);max-width:36rem;width:min(92vw,36rem);display:flex;flex-direction:column;overflow:hidden;background:#062114f5;border:1px solid rgba(15,187,107,.42);border-radius:.9rem;box-shadow:0 0 34px #000000a6}.welcome:focus{outline:none}.welcome__header{padding:1.1rem 1.25rem .95rem;border-bottom:1px solid rgba(15,187,107,.18);background:linear-gradient(to bottom,#0fbb6b0f,#0fbb6b00)}.welcome__title{font-size:clamp(1.05rem,1.05rem + (1.3rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.3rem);letter-spacing:.1em}.welcome__version{color:#0fbb6bc7;font-size:clamp(.8rem,.8rem + (.9rem - .8rem) * (100vw - 360px) / (1200px - 360px),.9rem);letter-spacing:.1em}.welcome__subtitle{margin-top:.35rem;color:#0fbb6bbf;font-size:clamp(.85rem,.85rem + (.95rem - .85rem) * (100vw - 360px) / (1200px - 360px),.95rem)}.welcome__body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;padding:1rem 1.25rem 0;display:flex;flex-direction:column;gap:.9rem}.welcome__body p{margin:0}.welcome__intro{color:#0fbb6be6}.welcome__divider{border-top:1px solid rgba(15,187,107,.22);margin:.15rem 0}.welcome__section{border:1px solid rgba(15,187,107,.2);border-radius:.75rem;padding:.9rem .95rem;background:#0fbb6b0a;display:flex;flex-direction:column;gap:.75rem}.welcome__section:last-child{margin-bottom:1rem}.welcome__section-head{display:flex;flex-direction:column;gap:.35rem}.welcome__section-title{text-transform:uppercase;letter-spacing:.08em;color:#0fbb6bd1;font-size:clamp(.8rem,.8rem + (.95rem - .8rem) * (100vw - 360px) / (1200px - 360px),.95rem)}.welcome__section-text{color:#0fbb6bc7;font-size:clamp(.85rem,.85rem + (.95rem - .85rem) * (100vw - 360px) / (1200px - 360px),.95rem);line-height:1.35}.welcome__slider{align-items:center;display:flex;gap:.8rem}.welcome__range{appearance:none;background:#0fbb6b33;border-radius:999px;cursor:pointer;flex:1 1 auto;height:.35rem;outline:none}.welcome__range::-webkit-slider-thumb{appearance:none;background:#0fbb6b;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.welcome__range::-moz-range-thumb{background:#0fbb6b;border:none;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.welcome__value{font-size:clamp(.75rem,.75rem + (.85rem - .75rem) * (100vw - 360px) / (1200px - 360px),.85rem);color:#0fbb6bd1;letter-spacing:.08em;min-width:3.25rem;text-align:right}.welcome__hint{color:#0fbb6bbf;font-size:clamp(.82rem,.82rem + (.92rem - .82rem) * (100vw - 360px) / (1200px - 360px),.92rem);line-height:1.35}.welcome__meta{display:grid;gap:.6rem;margin:0}.welcome__row{display:grid;grid-template-columns:5.25rem 1fr;align-items:start;gap:.75rem}.welcome__label{color:#0fbb6bbd;text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;line-height:1.25;padding-top:.15rem}.welcome__data{margin:0}.welcome__data code{background:#0fbb6b14;border:1px solid rgba(15,187,107,.22);border-radius:.45rem;color:#0fbb6b;display:inline-block;padding:.25rem .55rem;max-width:100%;overflow-wrap:anywhere}.welcome__data a{color:#0fbb6b;text-decoration:none;overflow-wrap:anywhere}.welcome__data a:hover{text-decoration:underline}.welcome__disclaimer{color:#0fbb6bc2;font-size:clamp(.82rem,.82rem + (.92rem - .82rem) * (100vw - 360px) / (1200px - 360px),.92rem);line-height:1.35}.welcome__actions{display:flex;justify-content:flex-end;padding:.9rem 1.25rem 1.1rem;border-top:1px solid rgba(15,187,107,.12);background:#0000001f}.welcome__actions button{background:#0fbb6b0f;border:1px solid rgba(15,187,107,.5);border-radius:.6rem;color:#0fbb6b;cursor:pointer;padding:.55rem 1rem;text-transform:uppercase;letter-spacing:.08em}.welcome__actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"],dependencies:[{kind:"ngmodule",type:g}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:J,decorators:[{type:n,args:[{selector:"pip-boy-welcome-modal",standalone:!0,imports:[g],template:'@if (open) {\n <div\n class="welcome-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n aria-hidden="true"\n >\n <div\n class="welcome"\n (click)="$event.stopPropagation()"\n (keydown.escape)="closeModal()"\n role="dialog"\n aria-modal="true"\n aria-labelledby="pipUiWelcomeTitle"\n tabindex="-1"\n >\n <header class="welcome__header">\n <div class="welcome__title" id="pipUiWelcomeTitle">\n Welcome to Pip UI\n <span class="welcome__version">v{{ appVersion }}</span>\n </div>\n <div class="welcome__subtitle">\n A fan made Pip-Boy 3000 style simulator.\n </div>\n </header>\n\n <div class="welcome__body">\n <div class="welcome__intro">\n <p>A wrist terminal for roleplay sessions and more!</p>\n </div>\n\n <div class="welcome__divider" aria-hidden="true"></div>\n\n <section class="welcome__section" aria-labelledby="welcomeFontTitle">\n <div class="welcome__section-head">\n <div class="welcome__section-title" id="welcomeFontTitle">\n Global Font Size\n </div>\n <p class="welcome__section-text">\n Adjusts the size of list text and key UI labels across tabs.\n </p>\n </div>\n\n <div class="welcome__slider">\n <input\n class="welcome__range"\n type="range"\n min="50"\n max="150"\n step="1"\n [value]="listFontScalePercent()"\n (input)="updateListFontScale($any($event.target).value)"\n aria-label="Global font size"\n />\n <span class="welcome__value">{{ listFontScalePercent() }}%</span>\n </div>\n\n <p class="welcome__hint">\n You can adjust this anytime later in the settings menu.\n </p>\n </section>\n\n <div class="welcome__divider" aria-hidden="true"></div>\n\n <section class="welcome__section" aria-labelledby="welcomeNpmTitle">\n <div class="welcome__section-head">\n <div class="welcome__section-title" id="welcomeNpmTitle">Npm</div>\n <p class="welcome__section-text">\n Install the package to use it in your project.\n </p>\n </div>\n\n <dl class="welcome__meta" aria-label="Install information">\n <div class="welcome__row">\n <dt class="welcome__label">Package</dt>\n <dd class="welcome__data"><code>@vault-tec/pip-boy</code></dd>\n </div>\n\n <div class="welcome__row">\n <dt class="welcome__label">Install</dt>\n <dd class="welcome__data">\n <code>npm install @vault-tec/pip-boy</code>\n </dd>\n </div>\n\n <div class="welcome__row">\n <dt class="welcome__label">NPM</dt>\n <dd class="welcome__data">\n <a\n href="https://www.npmjs.com/package/@vault-tec/pip-boy"\n target="_blank"\n rel="noreferrer"\n >\n npmjs.com/package/@vault-tec/pip-boy\n </a>\n </dd>\n </div>\n </dl>\n\n <p class="welcome__disclaimer">\n Unofficial fan project. No official game assets included. Not\n affiliated with or endorsed by Bethesda Softworks or ZeniMax Media.\n </p>\n </section>\n </div>\n\n <footer class="welcome__actions">\n <button type="button" (click)="closeModal()">Close</button>\n </footer>\n </div>\n </div>\n}\n',styles:[".welcome-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0000009e;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:110}.welcome{margin:1rem;max-height:calc(100vh - 2rem);max-height:calc(100svh - 2rem);max-width:36rem;width:min(92vw,36rem);display:flex;flex-direction:column;overflow:hidden;background:#062114f5;border:1px solid rgba(15,187,107,.42);border-radius:.9rem;box-shadow:0 0 34px #000000a6}.welcome:focus{outline:none}.welcome__header{padding:1.1rem 1.25rem .95rem;border-bottom:1px solid rgba(15,187,107,.18);background:linear-gradient(to bottom,#0fbb6b0f,#0fbb6b00)}.welcome__title{font-size:clamp(1.05rem,1.05rem + (1.3rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.3rem);letter-spacing:.1em}.welcome__version{color:#0fbb6bc7;font-size:clamp(.8rem,.8rem + (.9rem - .8rem) * (100vw - 360px) / (1200px - 360px),.9rem);letter-spacing:.1em}.welcome__subtitle{margin-top:.35rem;color:#0fbb6bbf;font-size:clamp(.85rem,.85rem + (.95rem - .85rem) * (100vw - 360px) / (1200px - 360px),.95rem)}.welcome__body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;padding:1rem 1.25rem 0;display:flex;flex-direction:column;gap:.9rem}.welcome__body p{margin:0}.welcome__intro{color:#0fbb6be6}.welcome__divider{border-top:1px solid rgba(15,187,107,.22);margin:.15rem 0}.welcome__section{border:1px solid rgba(15,187,107,.2);border-radius:.75rem;padding:.9rem .95rem;background:#0fbb6b0a;display:flex;flex-direction:column;gap:.75rem}.welcome__section:last-child{margin-bottom:1rem}.welcome__section-head{display:flex;flex-direction:column;gap:.35rem}.welcome__section-title{text-transform:uppercase;letter-spacing:.08em;color:#0fbb6bd1;font-size:clamp(.8rem,.8rem + (.95rem - .8rem) * (100vw - 360px) / (1200px - 360px),.95rem)}.welcome__section-text{color:#0fbb6bc7;font-size:clamp(.85rem,.85rem + (.95rem - .85rem) * (100vw - 360px) / (1200px - 360px),.95rem);line-height:1.35}.welcome__slider{align-items:center;display:flex;gap:.8rem}.welcome__range{appearance:none;background:#0fbb6b33;border-radius:999px;cursor:pointer;flex:1 1 auto;height:.35rem;outline:none}.welcome__range::-webkit-slider-thumb{appearance:none;background:#0fbb6b;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.welcome__range::-moz-range-thumb{background:#0fbb6b;border:none;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.welcome__value{font-size:clamp(.75rem,.75rem + (.85rem - .75rem) * (100vw - 360px) / (1200px - 360px),.85rem);color:#0fbb6bd1;letter-spacing:.08em;min-width:3.25rem;text-align:right}.welcome__hint{color:#0fbb6bbf;font-size:clamp(.82rem,.82rem + (.92rem - .82rem) * (100vw - 360px) / (1200px - 360px),.92rem);line-height:1.35}.welcome__meta{display:grid;gap:.6rem;margin:0}.welcome__row{display:grid;grid-template-columns:5.25rem 1fr;align-items:start;gap:.75rem}.welcome__label{color:#0fbb6bbd;text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;line-height:1.25;padding-top:.15rem}.welcome__data{margin:0}.welcome__data code{background:#0fbb6b14;border:1px solid rgba(15,187,107,.22);border-radius:.45rem;color:#0fbb6b;display:inline-block;padding:.25rem .55rem;max-width:100%;overflow-wrap:anywhere}.welcome__data a{color:#0fbb6b;text-decoration:none;overflow-wrap:anywhere}.welcome__data a:hover{text-decoration:underline}.welcome__disclaimer{color:#0fbb6bc2;font-size:clamp(.82rem,.82rem + (.92rem - .82rem) * (100vw - 360px) / (1200px - 360px),.92rem);line-height:1.35}.welcome__actions{display:flex;justify-content:flex-end;padding:.9rem 1.25rem 1.1rem;border-top:1px solid rgba(15,187,107,.12);background:#0000001f}.welcome__actions button{background:#0fbb6b0f;border:1px solid rgba(15,187,107,.5);border-radius:.6rem;color:#0fbb6b;cursor:pointer;padding:.55rem 1rem;text-transform:uppercase;letter-spacing:.08em}.welcome__actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],listFontScale:[{type:m}],closeResult:[{type:d}],previewListFontScale:[{type:d}]}});class X{open=!1;scanLinesEnabled=!0;editLockEnabled=!1;listFontScale=1.25;secondaryTabSoundLabel=null;mainTabSoundLabel=null;clickSoundLabel=null;closeResult=new s;save=new s;previewListFontScale=new s;draftScanLines=o(!0,...ngDevMode?[{debugName:"draftScanLines"}]:[]);draftEditLock=o(!1,...ngDevMode?[{debugName:"draftEditLock"}]:[]);draftListFontScale=o(1.25,...ngDevMode?[{debugName:"draftListFontScale"}]:[]);secondarySoundName=o(null,...ngDevMode?[{debugName:"secondarySoundName"}]:[]);mainSoundName=o(null,...ngDevMode?[{debugName:"mainSoundName"}]:[]);clickSoundName=o(null,...ngDevMode?[{debugName:"clickSoundName"}]:[]);secondarySoundFile=null;mainSoundFile=null;clickSoundFile=null;removeSecondary=!1;removeMain=!1;removeClick=!1;ngOnChanges(e){e.scanLinesEnabled&&this.draftScanLines.set(this.scanLinesEnabled),e.editLockEnabled&&this.draftEditLock.set(this.editLockEnabled),e.listFontScale&&this.draftListFontScale.set(this.listFontScale),e.secondaryTabSoundLabel&&this.secondarySoundName.set(this.secondaryTabSoundLabel),e.mainTabSoundLabel&&this.mainSoundName.set(this.mainTabSoundLabel),e.clickSoundLabel&&this.clickSoundName.set(this.clickSoundLabel),e.open&&this.open&&(this.secondarySoundFile=null,this.mainSoundFile=null,this.clickSoundFile=null,this.removeSecondary=!1,this.removeMain=!1,this.removeClick=!1)}closeModal(){this.closeResult.emit()}toggleScanLines(){this.draftScanLines.update(e=>!e)}toggleEditLock(){this.draftEditLock.update(e=>!e)}updateListFontScale(e){const t=Number(e);if(!Number.isFinite(t))return;const a=Math.min(150,Math.max(50,t))/100*1.25;this.draftListFontScale.set(a),this.previewListFontScale.emit(a)}listFontScalePercent(){return Math.round(this.draftListFontScale()/1.25*100)}onSecondarySoundSelected(e){const t=e.target,a=t.files?.[0]??null;this.secondarySoundFile=a,this.removeSecondary=!1,this.secondarySoundName.set(a?.name??this.secondaryTabSoundLabel),t&&(t.value="")}onMainSoundSelected(e){const t=e.target,a=t.files?.[0]??null;this.mainSoundFile=a,this.removeMain=!1,this.mainSoundName.set(a?.name??this.mainTabSoundLabel),t&&(t.value="")}onClickSoundSelected(e){const t=e.target,a=t.files?.[0]??null;this.clickSoundFile=a,this.removeClick=!1,this.clickSoundName.set(a?.name??this.clickSoundLabel),t&&(t.value="")}removeSecondarySound(){this.secondarySoundFile=null,this.removeSecondary=!0,this.secondarySoundName.set(null)}removeMainSound(){this.mainSoundFile=null,this.removeMain=!0,this.mainSoundName.set(null)}removeClickSound(){this.clickSoundFile=null,this.removeClick=!0,this.clickSoundName.set(null)}submit(e){e.preventDefault(),this.save.emit({scanLinesEnabled:this.draftScanLines(),editLockEnabled:this.draftEditLock(),listFontScale:this.draftListFontScale(),secondaryTabSoundFile:this.secondarySoundFile,mainTabSoundFile:this.mainSoundFile,clickSoundFile:this.clickSoundFile,removeSecondaryTabSound:this.removeSecondary,removeMainTabSound:this.removeMain,removeClickSound:this.removeClick})}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:X,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:X,isStandalone:!0,selector:"pip-boy-settings-modal",inputs:{open:"open",scanLinesEnabled:"scanLinesEnabled",editLockEnabled:"editLockEnabled",listFontScale:"listFontScale",secondaryTabSoundLabel:"secondaryTabSoundLabel",mainTabSoundLabel:"mainTabSoundLabel",clickSoundLabel:"clickSoundLabel"},outputs:{closeResult:"closeResult",save:"save",previewListFontScale:"previewListFontScale"},usesOnChanges:!0,ngImport:e,template:'@if (open) {\n <div\n class="settings-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="settings-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>Settings</span>\n </header>\n <form (submit)="submit($event)">\n <div class="settings-modal-body">\n <label class="settings-modal-field settings-modal-toggle">\n <span>Screen Line Effect</span>\n <input\n type="checkbox"\n [checked]="draftScanLines()"\n (change)="toggleScanLines()"\n hidden\n />\n <button\n type="button"\n class="settings-toggle"\n [class.is-on]="draftScanLines()"\n (click)="toggleScanLines()"\n >\n {{ draftScanLines() ? \'On\' : \'Off\' }}\n </button>\n </label>\n <label class="settings-modal-field settings-modal-toggle">\n <span>Edit Lock</span>\n <input\n type="checkbox"\n [checked]="draftEditLock()"\n (change)="toggleEditLock()"\n hidden\n />\n <button\n type="button"\n class="settings-toggle"\n [class.is-on]="draftEditLock()"\n (click)="toggleEditLock()"\n >\n {{ draftEditLock() ? \'Locked\' : \'Unlocked\' }}\n </button>\n </label>\n <label class="settings-modal-field settings-modal-slider">\n <span>Content Font Size</span>\n <div class="settings-slider-row">\n <input\n type="range"\n min="50"\n max="150"\n step="1"\n [value]="listFontScalePercent()"\n (input)="updateListFontScale($any($event.target).value)"\n />\n <span class="settings-slider-value">\n {{ listFontScalePercent() }}%\n </span>\n </div>\n </label>\n <div class="settings-divider"></div>\n <div class="settings-modal-field">\n <span>Secondary Tab Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="secondarySoundInput.click()"\n >\n {{ secondarySoundName() ?? \'Select Sound\' }}\n </button>\n @if (secondarySoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeSecondarySound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #secondarySoundInput\n type="file"\n accept="audio/*"\n (change)="onSecondarySoundSelected($event)"\n />\n </div>\n <div class="settings-modal-field">\n <span>Main Tab Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="mainSoundInput.click()"\n >\n {{ mainSoundName() ?? \'Select Sound\' }}\n </button>\n @if (mainSoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeMainSound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #mainSoundInput\n type="file"\n accept="audio/*"\n (change)="onMainSoundSelected($event)"\n />\n </div>\n <div class="settings-divider"></div>\n <div class="settings-modal-field">\n <span>Click Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="clickSoundInput.click()"\n >\n {{ clickSoundName() ?? \'Select Sound\' }}\n </button>\n @if (clickSoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeClickSound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #clickSoundInput\n type="file"\n accept="audio/*"\n (change)="onClickSoundSelected($event)"\n />\n </div>\n </div>\n <div class="settings-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".settings-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.settings-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:22rem;width:min(90vw,22rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.settings-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.settings-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.settings-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.settings-modal-field{display:flex;flex-direction:column;gap:.5rem}.settings-modal-slider{gap:.65rem}.settings-slider-row{align-items:center;display:flex;gap:.75rem}.settings-slider-row input[type=range]{appearance:none;background:#0fbb6b33;border-radius:999px;cursor:pointer;flex:1 1 auto;height:.35rem;outline:none}.settings-slider-row input[type=range]::-webkit-slider-thumb{appearance:none;background:#0fbb6b;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.settings-slider-row input[type=range]::-moz-range-thumb{background:#0fbb6b;border:none;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.settings-slider-value{font-size:clamp(.75rem,.75rem + (.85rem - .75rem) * (100vw - 360px) / (1200px - 360px),.85rem);color:#0fbb6bcc;letter-spacing:.08em;min-width:3.25rem;text-align:right}.settings-modal-toggle{align-items:center;flex-direction:row;justify-content:space-between}.settings-divider{border-top:1px solid rgba(15,187,107,.2);margin:.5rem 0}.settings-sound-actions{display:flex;gap:.5rem;align-items:center}.settings-sound-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;flex:1 1 auto;padding:.5rem .75rem;text-align:left;text-transform:uppercase}.settings-sound-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-sound-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.4rem .7rem;text-transform:uppercase}.settings-sound-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-modal input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.settings-toggle{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:999px;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.35rem .9rem;text-transform:uppercase}.settings-toggle.is-on{background:#0fbb6b33;border-color:#0fbb6b}.settings-toggle:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.settings-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.settings-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:X,decorators:[{type:n,args:[{selector:"pip-boy-settings-modal",standalone:!0,template:'@if (open) {\n <div\n class="settings-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="settings-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>Settings</span>\n </header>\n <form (submit)="submit($event)">\n <div class="settings-modal-body">\n <label class="settings-modal-field settings-modal-toggle">\n <span>Screen Line Effect</span>\n <input\n type="checkbox"\n [checked]="draftScanLines()"\n (change)="toggleScanLines()"\n hidden\n />\n <button\n type="button"\n class="settings-toggle"\n [class.is-on]="draftScanLines()"\n (click)="toggleScanLines()"\n >\n {{ draftScanLines() ? \'On\' : \'Off\' }}\n </button>\n </label>\n <label class="settings-modal-field settings-modal-toggle">\n <span>Edit Lock</span>\n <input\n type="checkbox"\n [checked]="draftEditLock()"\n (change)="toggleEditLock()"\n hidden\n />\n <button\n type="button"\n class="settings-toggle"\n [class.is-on]="draftEditLock()"\n (click)="toggleEditLock()"\n >\n {{ draftEditLock() ? \'Locked\' : \'Unlocked\' }}\n </button>\n </label>\n <label class="settings-modal-field settings-modal-slider">\n <span>Content Font Size</span>\n <div class="settings-slider-row">\n <input\n type="range"\n min="50"\n max="150"\n step="1"\n [value]="listFontScalePercent()"\n (input)="updateListFontScale($any($event.target).value)"\n />\n <span class="settings-slider-value">\n {{ listFontScalePercent() }}%\n </span>\n </div>\n </label>\n <div class="settings-divider"></div>\n <div class="settings-modal-field">\n <span>Secondary Tab Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="secondarySoundInput.click()"\n >\n {{ secondarySoundName() ?? \'Select Sound\' }}\n </button>\n @if (secondarySoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeSecondarySound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #secondarySoundInput\n type="file"\n accept="audio/*"\n (change)="onSecondarySoundSelected($event)"\n />\n </div>\n <div class="settings-modal-field">\n <span>Main Tab Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="mainSoundInput.click()"\n >\n {{ mainSoundName() ?? \'Select Sound\' }}\n </button>\n @if (mainSoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeMainSound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #mainSoundInput\n type="file"\n accept="audio/*"\n (change)="onMainSoundSelected($event)"\n />\n </div>\n <div class="settings-divider"></div>\n <div class="settings-modal-field">\n <span>Click Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="clickSoundInput.click()"\n >\n {{ clickSoundName() ?? \'Select Sound\' }}\n </button>\n @if (clickSoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeClickSound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #clickSoundInput\n type="file"\n accept="audio/*"\n (change)="onClickSoundSelected($event)"\n />\n </div>\n </div>\n <div class="settings-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".settings-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.settings-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:22rem;width:min(90vw,22rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.settings-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.settings-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.settings-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.settings-modal-field{display:flex;flex-direction:column;gap:.5rem}.settings-modal-slider{gap:.65rem}.settings-slider-row{align-items:center;display:flex;gap:.75rem}.settings-slider-row input[type=range]{appearance:none;background:#0fbb6b33;border-radius:999px;cursor:pointer;flex:1 1 auto;height:.35rem;outline:none}.settings-slider-row input[type=range]::-webkit-slider-thumb{appearance:none;background:#0fbb6b;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.settings-slider-row input[type=range]::-moz-range-thumb{background:#0fbb6b;border:none;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.settings-slider-value{font-size:clamp(.75rem,.75rem + (.85rem - .75rem) * (100vw - 360px) / (1200px - 360px),.85rem);color:#0fbb6bcc;letter-spacing:.08em;min-width:3.25rem;text-align:right}.settings-modal-toggle{align-items:center;flex-direction:row;justify-content:space-between}.settings-divider{border-top:1px solid rgba(15,187,107,.2);margin:.5rem 0}.settings-sound-actions{display:flex;gap:.5rem;align-items:center}.settings-sound-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;flex:1 1 auto;padding:.5rem .75rem;text-align:left;text-transform:uppercase}.settings-sound-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-sound-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.4rem .7rem;text-transform:uppercase}.settings-sound-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-modal input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.settings-toggle{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:999px;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.35rem .9rem;text-transform:uppercase}.settings-toggle.is-on{background:#0fbb6b33;border-color:#0fbb6b}.settings-toggle:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.settings-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.settings-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],scanLinesEnabled:[{type:m}],editLockEnabled:[{type:m}],listFontScale:[{type:m}],secondaryTabSoundLabel:[{type:m}],mainTabSoundLabel:[{type:m}],clickSoundLabel:[{type:m}],closeResult:[{type:d}],save:[{type:d}],previewListFontScale:[{type:d}]}});class Z{constructor(){r(()=>{this.open()&&(this.draftImageUrl.set(this.imageUrl()),this.draftImageName.set(null),this.draftImageFile.set(null),this.removedImage.set(!1),this.clearPreviewUrl())})}open=t(!1,...ngDevMode?[{debugName:"open"}]:[]);title=t("Map Image",...ngDevMode?[{debugName:"title"}]:[]);imageUrl=t(null,...ngDevMode?[{debugName:"imageUrl"}]:[]);closeResult=u();save=u();draftImageName=o(null,...ngDevMode?[{debugName:"draftImageName"}]:[]);draftImageUrl=o(null,...ngDevMode?[{debugName:"draftImageUrl"}]:[]);draftImageFile=o(null,...ngDevMode?[{debugName:"draftImageFile"}]:[]);removedImage=o(!1,...ngDevMode?[{debugName:"removedImage"}]:[]);previewUrl=null;closeModal(){this.clearPreviewUrl(),this.closeResult.emit()}onImageSelected(e){const t=e.target,a=t.files?.[0]??null;this.draftImageName.set(a?a.name:null),a&&(this.removedImage.set(!1),this.draftImageFile.set(a),this.setPreviewUrl(URL.createObjectURL(a)),t.value="")}removeImage(){this.draftImageName.set(null),this.draftImageUrl.set(null),this.draftImageFile.set(null),this.removedImage.set(!0),this.clearPreviewUrl()}submit(e){e?.preventDefault(),this.save.emit({imageFile:this.draftImageFile(),removeImage:this.removedImage()}),this.clearPreviewUrl(),this.closeResult.emit()}setPreviewUrl(e){this.clearPreviewUrl(),this.previewUrl=e,this.draftImageUrl.set(e)}clearPreviewUrl(){this.previewUrl&&(URL.revokeObjectURL(this.previewUrl),this.previewUrl=null)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Z,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:Z,isStandalone:!0,selector:"pip-boy-map-image-modal",inputs:{open:{classPropertyName:"open",publicName:"open",isSignal:!0,isRequired:!1,transformFunction:null},title:{classPropertyName:"title",publicName:"title",isSignal:!0,isRequired:!1,transformFunction:null},imageUrl:{classPropertyName:"imageUrl",publicName:"imageUrl",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{closeResult:"closeResult",save:"save"},ngImport:e,template:'@if (open()) {\n <div\n class="map-image-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="map-image-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title() }}</header>\n <form (submit)="submit($event)">\n <div class="map-image-modal-body">\n <div class="map-image-modal-image">\n <button\n type="button"\n class="map-image-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="map-image-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Map preview" />\n }\n </div>\n </div>\n <div class="map-image-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".map-image-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.map-image-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:28rem;width:min(90vw,28rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.map-image-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.map-image-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.map-image-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.map-image-modal-image{display:flex;flex-direction:column;gap:.75rem}.map-image-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.map-image-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:12rem;object-fit:contain;padding:.5rem}.map-image-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.map-image-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-image-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.map-image-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-image-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.map-image-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.map-image-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Z,decorators:[{type:n,args:[{selector:"pip-boy-map-image-modal",standalone:!0,template:'@if (open()) {\n <div\n class="map-image-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="map-image-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title() }}</header>\n <form (submit)="submit($event)">\n <div class="map-image-modal-body">\n <div class="map-image-modal-image">\n <button\n type="button"\n class="map-image-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="map-image-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Map preview" />\n }\n </div>\n </div>\n <div class="map-image-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[".map-image-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.map-image-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:28rem;width:min(90vw,28rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.map-image-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.map-image-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.map-image-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.map-image-modal-image{display:flex;flex-direction:column;gap:.75rem}.map-image-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.map-image-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:12rem;object-fit:contain;padding:.5rem}.map-image-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.map-image-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-image-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.map-image-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-image-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.map-image-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.map-image-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],ctorParameters:()=>[],propDecorators:{open:[{type:e.Input,args:[{isSignal:!0,alias:"open",required:!1}]}],title:[{type:e.Input,args:[{isSignal:!0,alias:"title",required:!1}]}],imageUrl:[{type:e.Input,args:[{isSignal:!0,alias:"imageUrl",required:!1}]}],closeResult:[{type:e.Output,args:["closeResult"]}],save:[{type:e.Output,args:["save"]}]}});class ee{returnToUrl=t("https://www.pip-boy.com",...ngDevMode?[{debugName:"returnToUrl"}]:[]);state=l(w);settings=l(B);imageStore=l(x);soundStore=l(O);appVersion=E;tabsOpen=o(!1,...ngDevMode?[{debugName:"tabsOpen"}]:[]);showResetModal=o(!1,...ngDevMode?[{debugName:"showResetModal"}]:[]);showExitModal=o(!1,...ngDevMode?[{debugName:"showExitModal"}]:[]);showBugModal=o(!1,...ngDevMode?[{debugName:"showBugModal"}]:[]);showSettingsModal=o(!1,...ngDevMode?[{debugName:"showSettingsModal"}]:[]);settingsListFontScaleSnapshot=o(null,...ngDevMode?[{debugName:"settingsListFontScaleSnapshot"}]:[]);showWelcomeModal=o(!0,...ngDevMode?[{debugName:"showWelcomeModal"}]:[]);mapImageModal=o(null,...ngDevMode?[{debugName:"mapImageModal"}]:[]);localMapZoom=o(1,...ngDevMode?[{debugName:"localMapZoom"}]:[]);worldMapZoom=o(1,...ngDevMode?[{debugName:"worldMapZoom"}]:[]);extraOptionModal=o(null,...ngDevMode?[{debugName:"extraOptionModal"}]:[]);tabsActionsLeftOpen=o(!1,...ngDevMode?[{debugName:"tabsActionsLeftOpen"}]:[]);tabsActionsRightOpen=o(!1,...ngDevMode?[{debugName:"tabsActionsRightOpen"}]:[]);viewportWidth=o("undefined"==typeof window?0:window.innerWidth,...ngDevMode?[{debugName:"viewportWidth"}]:[]);mapImageModalTitle=c(()=>"WORLD"===this.mapImageModal()?"World Map":"Local Map",...ngDevMode?[{debugName:"mapImageModalTitle"}]:[]);mapImageModalImage=c(()=>{const e="WORLD"===this.mapImageModal()?this.settings.worldMapImage():this.settings.localMapImage();return this.imageStore.getImageUrl(e)},...ngDevMode?[{debugName:"mapImageModalImage"}]:[]);secondaryTabSoundLabel=c(()=>this.soundStore.getSoundLabel(this.settings.secondaryTabSoundId()),...ngDevMode?[{debugName:"secondaryTabSoundLabel"}]:[]);mainTabSoundLabel=c(()=>this.soundStore.getSoundLabel(this.settings.mainTabSoundId()),...ngDevMode?[{debugName:"mainTabSoundLabel"}]:[]);clickSoundLabel=c(()=>this.soundStore.getSoundLabel(this.settings.clickSoundId()),...ngDevMode?[{debugName:"clickSoundLabel"}]:[]);isScreenTooSmall=c(()=>this.viewportWidth()<650,...ngDevMode?[{debugName:"isScreenTooSmall"}]:[]);extraOptionTitle=c(()=>{switch(this.extraOptionModal()){case"RADAWAY":case"RADX":return"Edit Text";default:return""}},...ngDevMode?[{debugName:"extraOptionTitle"}]:[]);extraOptionValue=c(()=>{const e=this.extraOptionModal();return"STIMPAK"===e?this.settings.stimpakLabel():"LIMBS"===e?this.settings.limbLabel():"RADAWAY"===e?this.settings.radAwayLabel():"RADX"===e?this.settings.radXLabel():""},...ngDevMode?[{debugName:"extraOptionValue"}]:[]);toggleTabs(){this.tabsOpen.update(e=>!e)}toggleTabsActions(e){"left"===e?(this.tabsActionsLeftOpen.update(e=>!e),this.tabsActionsRightOpen.set(!1)):(this.tabsActionsRightOpen.update(e=>!e),this.tabsActionsLeftOpen.set(!1))}onResize(){this.viewportWidth.set(window.innerWidth)}async saveSettingsToFile(){const e=this.settings.exportSettingsSnapshot(),t=this.collectImageIds(e),a=this.collectSoundIds(e),n=[],o=[],i=new f;for(const e of t){const t=await this.imageStore.getRecord(e);if(!t)continue;const a=this.getExtension(t.fileName,t.mime);i.file(`images/${e}${a}`,t.blob),n.push({id:e,fileName:t.fileName,mime:t.mime})}for(const e of a){const t=await this.soundStore.getRecord(e);if(!t)continue;const a=this.getSoundExtension(t.fileName,t.mime);i.file(`sounds/${e}${a}`,t.blob),o.push({id:e,fileName:t.fileName,mime:t.mime})}const r={version:1,images:n,sounds:o,pipBoy3000Settings:e};i.file("settings.json",JSON.stringify(r));const l=await i.generateAsync({type:"blob"}),s=URL.createObjectURL(l),d=document.createElement("a");d.href=s,d.download="pip-boy-export.zip",d.click(),URL.revokeObjectURL(s)}openResetModal(){this.showResetModal.set(!0)}closeResetModal(){this.showResetModal.set(!1)}confirmReset(){this.settings.resetToDefaults(),this.closeResetModal(),this.showWelcomeModal.set(!0)}openExitModal(){this.showExitModal.set(!0)}closeExitModal(){this.showExitModal.set(!1)}confirmExit(){window.location.href=this.returnToUrl()}openBugModal(){this.showBugModal.set(!0)}closeBugModal(){this.showBugModal.set(!1)}confirmBugReport(){window.open("https://github.com/CodyTolene/pip-terminal/issues","_blank"),this.closeBugModal()}openSettingsModal(){this.settingsListFontScaleSnapshot.set(this.settings.listFontScale()),this.showSettingsModal.set(!0)}closeSettingsModal(){this.showSettingsModal.set(!1)}cancelSettingsModal(){const e=this.settingsListFontScaleSnapshot();null!==e&&this.settings.listFontScale.set(e),this.settingsListFontScaleSnapshot.set(null),this.showSettingsModal.set(!1)}closeWelcomeModal(){this.showWelcomeModal.set(!1)}saveSettingsModal(e){this.settings.scanLinesEnabled.set(e.scanLinesEnabled),this.settings.editLockEnabled.set(e.editLockEnabled),this.settings.listFontScale.set(e.listFontScale),this.settingsListFontScaleSnapshot.set(null),e.removeSecondaryTabSound&&this.settings.secondaryTabSoundId.set(null),e.removeMainTabSound&&this.settings.mainTabSoundId.set(null),e.removeClickSound&&this.settings.clickSoundId.set(null),e.secondaryTabSoundFile&&this.soundStore.saveFile(e.secondaryTabSoundFile).then(e=>this.settings.secondaryTabSoundId.set(e.id)),e.mainTabSoundFile&&this.soundStore.saveFile(e.mainTabSoundFile).then(e=>this.settings.mainTabSoundId.set(e.id)),e.clickSoundFile&&this.soundStore.saveFile(e.clickSoundFile).then(e=>this.settings.clickSoundId.set(e.id)),this.closeSettingsModal()}previewListFontScale(e){this.settings.listFontScale.set(e)}openGithubProfile(){window.open("https://github.com/CodyTolene","_blank")}selectPrimary(e){this.soundStore.playSound(this.settings.mainTabSoundId()),this.state.selectPrimary(e)}selectSecondary(e){this.soundStore.playSound(this.settings.secondaryTabSoundId()),this.state.selectSecondary(e)}openExtraOptionModal(e){this.settings.editLockEnabled()||this.extraOptionModal.set(e)}closeExtraOptionModal(){this.extraOptionModal.set(null)}saveExtraOptionModal(e){const t=this.extraOptionModal();"STIMPAK"===t?this.settings.stimpakLabel.set(e):"LIMBS"===t?this.settings.limbLabel.set(e):"RADAWAY"===t?this.settings.radAwayLabel.set(e):"RADX"===t&&this.settings.radXLabel.set(e),this.closeExtraOptionModal()}async loadSettingsFromFile(e){const t=e.target,a=t.files?.[0]??null;if(!a)return;const n=await f.loadAsync(a),o=n.file("settings.json");if(!o)return void(t.value="");const i=await o.async("string"),r=JSON.parse(i),l=r.pipBoy3000Settings??r;if(Array.isArray(r.images))for(const e of r.images){const t=this.getExtension(e.fileName,e.mime),a=n.file(`images/${e.id}${t}`)??n.file(new RegExp(`^images/${e.id}\\.`))?.[0];if(!a)continue;const o=await a.async("blob");await this.imageStore.saveBlobWithId(e.id,o,e.fileName,e.mime)}if(Array.isArray(r.sounds))for(const e of r.sounds){const t=this.getSoundExtension(e.fileName,e.mime),a=n.file(`sounds/${e.id}${t}`)??n.file(new RegExp(`^sounds/${e.id}\\.`))?.[0];if(!a)continue;const o=await a.async("blob");await this.soundStore.saveBlobWithId(e.id,o,e.fileName,e.mime)}this.settings.importSettingsSnapshot(l),t.value=""}collectImageIds(e){const t=new Set,a=e=>{e&&t.add(e)};return e.weaponItems.forEach(e=>a(e.imageId)),e.apparelItems.forEach(e=>a(e.imageId)),e.aidItems.forEach(e=>a(e.imageId)),e.miscItems.forEach(e=>a(e.imageId)),e.ammoItems.forEach(e=>a(e.imageId)),e.specialItems.forEach(e=>a(e.imageId)),e.skillItems.forEach(e=>a(e.imageId)),e.perkItems.forEach(e=>a(e.imageId)),e.vaultBoyImages.forEach(e=>a(e)),a(e.localMapImage),a(e.worldMapImage),Array.from(t)}collectSoundIds(e){const t=new Set,a=e=>{e&&t.add(e)};return a(e.secondaryTabSoundId),a(e.mainTabSoundId),a(e.clickSoundId),e.notesItems.forEach(e=>a(e.soundId)),e.radioItems.forEach(e=>a(e.soundId)),Array.from(t)}getExtension(e,t){const a=e.match(/\.[a-z0-9]+$/i);return a?a[0]:this.imageStore.extensionFromMime(t)}getSoundExtension(e,t){const a=e.match(/\.[a-z0-9]+$/i);return a?a[0]:this.soundStore.extensionFromMime(t)}openMapImageModal(e){this.mapImageModal.set(e)}closeMapImageModal(){this.mapImageModal.set(null)}zoomMap(e,t){const a="WORLD"===e?this.worldMapZoom:this.localMapZoom,n=Math.min(3,Math.max(.5,a()+t));a.set(Number(n.toFixed(2)))}resetMapZoom(e){"WORLD"===e?this.worldMapZoom.set(1):this.localMapZoom.set(1)}async saveMapImageModal(e){const t=this.mapImageModal();if(t){if(e.removeImage)return"WORLD"===t?this.settings.worldMapImage.set(null):this.settings.localMapImage.set(null),void this.closeMapImageModal();if(e.imageFile){const a=await this.imageStore.saveFile(e.imageFile);"WORLD"===t?this.settings.worldMapImage.set(a.id):this.settings.localMapImage.set(a.id)}this.closeMapImageModal()}}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:ee,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:ee,isStandalone:!0,selector:"pip-boy-3000",inputs:{returnToUrl:{classPropertyName:"returnToUrl",publicName:"returnToUrl",isSignal:!0,isRequired:!1,transformFunction:null}},host:{listeners:{"window:resize":"onResize()"}},providers:[w],ngImport:e,template:'<main\n #screen\n class="screen"\n [style.--list-font-scale]="settings.listFontScale()"\n>\n @if (settings.scanLinesEnabled()) {\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="300"\n />\n }\n @if (isScreenTooSmall()) {\n <div class="screen-size-overlay" role="alert" aria-live="assertive">\n Screen is too small.<br />Please rotate to landscape.\n </div>\n }\n \x3c!-- HEADER --\x3e\n <pip-boy-3000-header />\n \x3c!-- CONTENT --\x3e\n <section class="content">\n @if (state.primary() === \'STATS\') {\n @if (state.secondary() === \'STATUS\') {\n <div class="status-content">\n <nav class="column sub-content" aria-label="Status tabs">\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'CND\'"\n (click)="state.selectTertiary(\'CND\')"\n >\n CND\n </button>\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'RAD\'"\n (click)="state.selectTertiary(\'RAD\')"\n >\n RAD\n </button>\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'EFF\'"\n (click)="state.selectTertiary(\'EFF\')"\n >\n EFF\n </button>\n </nav>\n @if (state.tertiary() === \'CND\') {\n <pip-boy-cnd-status />\n } @else if (state.tertiary() === \'RAD\') {\n <pip-boy-radiation-meter />\n <div class="extra-options">\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'RADAWAY\')"\n >\n {{ settings.radAwayLabel() }}\n </button>\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'RADX\')"\n >\n {{ settings.radXLabel() }}\n </button>\n </div>\n } @else if (state.tertiary() === \'EFF\') {\n <pip-boy-eff-layout />\n }\n </div>\n } @else if (state.secondary() === \'S.P.E.C.I.A.L.\') {\n <pip-boy-stats-layout\n category="SPECIAL"\n valueLabel="Rating"\n [valueMin]="1"\n [valueMax]="10"\n />\n } @else if (state.secondary() === \'SKILLS\') {\n <pip-boy-stats-layout\n category="SKILLS"\n valueLabel="Skill"\n [valueMin]="0"\n [valueMax]="100"\n />\n } @else if (state.secondary() === \'PERKS\') {\n <pip-boy-stats-layout\n category="PERKS"\n valueLabel="Rank"\n [valueMin]="0"\n />\n } @else if (state.secondary() === \'GENERAL\') {\n <pip-boy-stats-layout category="GENERAL" valueLabel="Value" />\n }\n } @else if (state.primary() === \'ITEMS\') {\n @if (state.secondary() === \'WEAPONS\') {\n <pip-boy-inventory-layout category="WEAPONS" />\n } @else if (state.secondary() === \'APPAREL\') {\n <pip-boy-inventory-layout category="APPAREL" />\n } @else if (state.secondary() === \'AID\') {\n <pip-boy-inventory-layout category="AID" />\n } @else if (state.secondary() === \'MISC\') {\n <pip-boy-inventory-layout category="MISC" />\n } @else if (state.secondary() === \'AMMO\') {\n <pip-boy-inventory-layout category="AMMO" />\n }\n } @else if (state.primary() === \'DATA\') {\n @if (state.secondary() === \'LOCAL MAP\') {\n <div class="map-panel">\n <button\n type="button"\n class="map-view"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openMapImageModal(\'LOCAL\')"\n >\n @if (settings.localMapImage()) {\n <img\n [src]="imageStore.getImageUrl(settings.localMapImage())"\n alt="Local map"\n [style.transform]="\'scale(\' + localMapZoom() + \')\'"\n style="transform-origin: top left"\n />\n } @else {\n <span>CLICK TO UPLOAD IMAGE</span>\n }\n </button>\n @if (settings.localMapImage()) {\n <div\n class="map-zoom"\n role="group"\n tabindex="0"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n >\n <button type="button" (click)="zoomMap(\'LOCAL\', 0.2)">+</button>\n <button type="button" (click)="zoomMap(\'LOCAL\', -0.2)">-</button>\n <button type="button" (click)="resetMapZoom(\'LOCAL\')">\n Reset\n </button>\n </div>\n }\n </div>\n } @else if (state.secondary() === \'WORLD MAP\') {\n <div class="map-panel">\n <button\n type="button"\n class="map-view"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openMapImageModal(\'WORLD\')"\n >\n @if (settings.worldMapImage()) {\n <img\n [src]="imageStore.getImageUrl(settings.worldMapImage())"\n alt="World map"\n [style.transform]="\'scale(\' + worldMapZoom() + \')\'"\n style="transform-origin: top left"\n />\n } @else {\n <span>CLICK TO UPLOAD IMAGE</span>\n }\n </button>\n @if (settings.worldMapImage()) {\n <div\n class="map-zoom"\n role="group"\n tabindex="0"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n >\n <button type="button" (click)="zoomMap(\'WORLD\', 0.2)">+</button>\n <button type="button" (click)="zoomMap(\'WORLD\', -0.2)">-</button>\n <button type="button" (click)="resetMapZoom(\'WORLD\')">\n Reset\n </button>\n </div>\n }\n </div>\n } @else if (state.secondary() === \'QUESTS\') {\n <pip-boy-quests-layout />\n } @else if (state.secondary() === \'NOTES\') {\n <pip-boy-music-layout category="NOTES" />\n } @else if (state.secondary() === \'RADIO\') {\n <pip-boy-music-layout category="RADIO" />\n }\n }\n </section>\n \x3c!-- SUB TABS --\x3e\n <section class="sub-tabs">\n @if (state.primary() === \'STATS\') {\n <nav aria-label="Stats tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'STATUS\'"\n (click)="selectSecondary(\'STATUS\')"\n >\n Status\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'S.P.E.C.I.A.L.\'"\n (click)="selectSecondary(\'S.P.E.C.I.A.L.\')"\n >\n S.P.E.C.I.A.L.\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'SKILLS\'"\n (click)="selectSecondary(\'SKILLS\')"\n >\n Skills\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'PERKS\'"\n (click)="selectSecondary(\'PERKS\')"\n >\n Perks\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'GENERAL\'"\n (click)="selectSecondary(\'GENERAL\')"\n >\n General\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n } @else if (state.primary() === \'ITEMS\') {\n <nav aria-label="Items tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'WEAPONS\'"\n (click)="selectSecondary(\'WEAPONS\')"\n >\n Weapons\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'APPAREL\'"\n (click)="selectSecondary(\'APPAREL\')"\n >\n Apparel\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'AID\'"\n (click)="selectSecondary(\'AID\')"\n >\n Aid\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'MISC\'"\n (click)="selectSecondary(\'MISC\')"\n >\n Misc\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'AMMO\'"\n (click)="selectSecondary(\'AMMO\')"\n >\n Ammo\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n } @else if (state.primary() === \'DATA\') {\n <nav aria-label="Data tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'LOCAL MAP\'"\n (click)="selectSecondary(\'LOCAL MAP\')"\n >\n Local Map\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'WORLD MAP\'"\n (click)="selectSecondary(\'WORLD MAP\')"\n >\n World Map\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'QUESTS\'"\n (click)="selectSecondary(\'QUESTS\')"\n >\n Quests\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'NOTES\'"\n (click)="selectSecondary(\'NOTES\')"\n >\n Notes\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'RADIO\'"\n (click)="selectSecondary(\'RADIO\')"\n >\n Radio\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n }\n </section>\n \x3c!-- MAIN TABS --\x3e\n <section class="tabs" [class.is-collapsed]="!tabsOpen()">\n <button\n type="button"\n class="tabs-toggle"\n aria-label="Toggle main tabs"\n [attr.aria-expanded]="tabsOpen()"\n aria-controls="main-tabs"\n (click)="toggleTabs()"\n >\n <span class="tabs-toggle-label tabs-toggle-label--state">\n {{ tabsOpen() ? \'CLOSE\' : \'OPEN\' }}\n </span>\n <span class="caret" aria-hidden="true"></span>\n <span class="tabs-toggle-label tabs-toggle-label--menu">MENU</span>\n </button>\n <nav id="main-tabs" aria-label="Main tabs">\n <div\n class="tabs-actions tabs-actions--left"\n [class.is-open]="tabsActionsLeftOpen()"\n >\n <button\n type="button"\n class="tabs-actions-toggle"\n aria-label="Open settings actions"\n (click)="toggleTabsActions(\'left\')"\n >\n <span class="tabs-actions-icon" aria-hidden="true"></span>\n </button>\n <div class="tabs-actions-menu">\n <button\n type="button"\n class="action-button"\n aria-label="Save settings"\n title="Save settings"\n (click)="saveSettingsToFile()"\n >\n Save\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Load settings"\n title="Load settings"\n (click)="loadSettingsInput.click()"\n >\n Load\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Reset settings"\n title="Reset settings"\n (click)="openResetModal()"\n >\n Reset\n </button>\n <input\n #loadSettingsInput\n type="file"\n accept=".zip,application/zip"\n (change)="loadSettingsFromFile($event)"\n />\n </div>\n </div>\n <button\n type="button"\n [class.is-active]="state.primary() === \'STATS\'"\n (click)="selectPrimary(\'STATS\')"\n >\n <span>STATS</span>\n </button>\n <button\n type="button"\n [class.is-active]="state.primary() === \'ITEMS\'"\n (click)="selectPrimary(\'ITEMS\')"\n >\n <span>ITEMS</span>\n </button>\n <button\n type="button"\n [class.is-active]="state.primary() === \'DATA\'"\n (click)="selectPrimary(\'DATA\')"\n >\n <span>DATA</span>\n </button>\n <div\n class="tabs-actions tabs-actions--right"\n [class.is-open]="tabsActionsRightOpen()"\n >\n <button\n type="button"\n class="tabs-actions-toggle"\n aria-label="Open utility actions"\n (click)="toggleTabsActions(\'right\')"\n >\n <span class="tabs-actions-icon" aria-hidden="true"></span>\n </button>\n <div class="tabs-actions-menu">\n <button\n type="button"\n class="action-button"\n aria-label="Open GitHub profile"\n title="Open GitHub profile"\n (click)="openGithubProfile()"\n >\n ❤\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Open settings"\n title="Settings"\n (click)="openSettingsModal()"\n >\n Settings\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Report a bug"\n title="Report a bug"\n (click)="openBugModal()"\n >\n Bug\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Reset settings"\n title="Exit"\n (click)="openExitModal()"\n >\n Exit\n </button>\n <input\n #loadSettingsInput\n type="file"\n accept=".zip,application/zip"\n (change)="loadSettingsFromFile($event)"\n />\n </div>\n </div>\n @if (tabsOpen()) {\n <div class="tabs-version">v{{ appVersion }}</div>\n }\n </nav>\n </section>\n <pip-boy-welcome-modal\n [open]="showWelcomeModal()"\n [listFontScale]="settings.listFontScale()"\n (previewListFontScale)="previewListFontScale($event)"\n (closeResult)="closeWelcomeModal()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showResetModal()"\n title="Reset Settings"\n message="This will reset all values back to defaults. This cannot be undone."\n confirmLabel="Reset"\n (closeResult)="closeResetModal()"\n (confirm)="confirmReset()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showExitModal()"\n title="Exit"\n message="Are you sure you want to leave this screen?"\n confirmLabel="Exit"\n (closeResult)="closeExitModal()"\n (confirm)="confirmExit()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showBugModal()"\n title="Report a bug"\n message="Would you like to report a bug?"\n confirmLabel="Yes"\n cancelLabel="No"\n (closeResult)="closeBugModal()"\n (confirm)="confirmBugReport()"\n />\n <pip-boy-map-image-modal\n [open]="mapImageModal() !== null"\n [title]="mapImageModalTitle()"\n [imageUrl]="mapImageModalImage()"\n (closeResult)="closeMapImageModal()"\n (save)="saveMapImageModal($event)"\n />\n <pip-boy-settings-modal\n [open]="showSettingsModal()"\n [scanLinesEnabled]="settings.scanLinesEnabled()"\n [editLockEnabled]="settings.editLockEnabled()"\n [listFontScale]="settings.listFontScale()"\n [secondaryTabSoundLabel]="secondaryTabSoundLabel()"\n [mainTabSoundLabel]="mainTabSoundLabel()"\n [clickSoundLabel]="clickSoundLabel()"\n (closeResult)="cancelSettingsModal()"\n (previewListFontScale)="previewListFontScale($event)"\n (save)="saveSettingsModal($event)"\n />\n <pip-boy-name-edit-modal\n [open]="extraOptionModal() !== null"\n [value]="extraOptionValue()"\n [title]="extraOptionTitle()"\n placeholder="Value"\n [allowEmpty]="true"\n (closeResult)="closeExtraOptionModal()"\n (save)="saveExtraOptionModal($event)"\n />\n</main>\n',styles:[".content{box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%;overflow:auto;padding:1rem 2rem;width:100%}.content .status-content{box-sizing:border-box;display:flex;flex-direction:row;height:100%;gap:1rem}.content .column{box-sizing:border-box;display:flex;flex:1;flex-direction:column}.content .sub-content{max-width:max-content}.content .sub-content button{width:auto;max-width:10rem;height:2.5rem;background:transparent;color:#0fbb6b;text-transform:uppercase;border:none;border-left:2px solid transparent;border-right:2px solid transparent;cursor:pointer;padding:0 1rem;margin-bottom:1rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.content .sub-content button.is-active{background:#0fbb6b14;border-left:2px solid #0fbb6b;border-right:2px solid #0fbb6b}.content .sub-content button:hover{background:#0fbb6b26}.content .radiation-status,.content .effects-status{box-sizing:border-box;display:flex;align-items:center;justify-content:center}.content .actions{box-sizing:border-box;display:flex;align-items:flex-end;max-width:max-content}\n",".sub-tabs{flex:0 0 auto;min-height:0;margin-bottom:.5rem;padding:0 1rem;position:relative;z-index:1}.sub-tabs>nav{box-sizing:border-box;display:flex;align-items:center;width:100%;height:2.25rem;gap:0}.sub-tabs>nav .center-line{flex:1 1 auto;height:100%;min-width:1.5rem}.sub-tabs>nav>.center-line:last-child .top-half-line:before{left:auto;right:0}.sub-tabs>nav button{background:transparent;border:2px solid transparent;color:#0fbb6b;cursor:pointer;font-size:clamp(1.25rem,1.25rem + (1.5rem - 1.25rem) * (100vw - 360px) / (1200px - 360px),1.5rem);padding:.5rem}.sub-tabs>nav button.is-active{background:#0fbb6b14;border:2px solid #0fbb6b}.sub-tabs>nav button:hover{background:#0fbb6b26}\n",'.tabs{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;flex:0 0 auto;gap:.5rem;max-height:12rem;overflow:hidden;padding:0;position:relative;z-index:5;transition:max-height .35s ease-in-out,padding .35s ease-in-out,gap .35s ease-in-out;width:100%}.tabs.is-collapsed{gap:0;max-height:2rem}.tabs.is-collapsed>nav{opacity:0;pointer-events:none;transform:translateY(100%)}.tabs.is-collapsed .tabs-toggle .caret{transform:translateY(2px) rotate(-135deg)}.tabs .tabs-toggle{align-items:center;background:transparent;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;display:inline-flex;height:2rem;justify-content:center;line-height:0;max-height:2rem;min-height:2rem;overflow:hidden;padding:0 1rem;transition:border-color .2s ease;width:100%}.tabs .tabs-toggle:hover{background-color:#0fbb6b1f}.tabs .tabs-toggle .caret{border:solid #0fbb6b;border-width:0 2px 2px 0;box-sizing:border-box;display:inline-block;height:.6rem;margin:0 .5rem;padding:0;transform:translateY(-4px) rotate(45deg);transform-origin:center;transition:transform .35s ease;width:.6rem}.tabs .tabs-toggle .tabs-toggle-label{font-size:clamp(.7rem,.7rem + (.85rem - .7rem) * (100vw - 360px) / (1200px - 360px),.85rem);letter-spacing:.1em;line-height:1;text-transform:uppercase;white-space:nowrap}.tabs>nav{display:flex;justify-content:center;opacity:1;padding-bottom:.5rem;transform:translateY(0);transition:transform .35s ease-in-out,opacity .35s ease-in-out;transform-origin:bottom;will-change:transform,opacity;width:100%;position:relative}.tabs .tabs-version{bottom:14px;color:#0fbb6bbf;font-size:10px;letter-spacing:.08em;position:absolute;right:22px}.tabs .tabs-actions{align-items:center;display:flex;gap:.5rem;left:1rem;position:absolute;top:50%;transform:translateY(-50%)}.tabs .tabs-actions.right,.tabs .tabs-actions.tabs-actions--right{left:auto;right:1rem}.tabs .tabs-actions .tabs-actions-toggle{align-items:center;background:transparent;border:1px solid rgba(15,187,107,.6);border-radius:9999px;color:#0fbb6b;cursor:pointer;display:none;height:2.1rem;justify-content:center;padding:0 .6rem;text-transform:uppercase;width:2.4rem}.tabs .tabs-actions .tabs-actions-toggle:hover{background:#0fbb6b1f;border-color:#0fbb6b}.tabs .tabs-actions .tabs-actions-icon{background:#0fbb6b;border-radius:9999px;display:block;height:2px;position:relative;width:1.1rem}.tabs .tabs-actions .tabs-actions-icon:before,.tabs .tabs-actions .tabs-actions-icon:after{content:"";background:#0fbb6b;border-radius:9999px;height:2px;left:0;position:absolute;width:100%}.tabs .tabs-actions .tabs-actions-icon:before{top:-5px}.tabs .tabs-actions .tabs-actions-icon:after{top:5px}.tabs .tabs-actions .tabs-actions-menu{display:flex;gap:.5rem;align-items:center}.tabs .tabs-actions .action-button{background:transparent;border:1px solid rgba(15,187,107,.7);color:#0fbb6bb3;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.25rem .35rem;text-align:left;width:100%;border-radius:1rem;text-align:center}.tabs .tabs-actions .action-button:hover{background:#0fbb6b1f;border-color:#0fbb6b}.tabs .tabs-actions input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.tabs .tabs-action{align-items:center;background:#0fbb6b1a;border:2px solid rgba(15,187,107,.6);border-radius:.4rem;color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.65rem,.65rem + (.75rem - .65rem) * (100vw - 360px) / (1200px - 360px),.75rem);height:2.5rem;justify-content:center;letter-spacing:.08em;padding:0 .85rem;text-transform:uppercase;transition:background .2s ease,border-color .2s ease;width:auto}.tabs .tabs-action:hover{background:#0fbb6b2e;border-color:#0fbb6b}.tabs>nav>button{align-items:center;background:transparent;border-radius:9999px;border:2px solid rgba(15,187,107,.35);box-sizing:border-box;color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);height:5rem;justify-content:center;line-height:1;margin:0 1rem;padding:0;text-transform:uppercase;width:5rem}.tabs>nav>button>span{align-items:center;display:inline-flex;justify-content:center;line-height:1;white-space:nowrap;width:100%;height:100%;border-radius:9999px;padding:0}.tabs>nav>button:hover{border-color:#0fbb6ba6}.tabs>nav>button:hover>span{background:#0fbb6b1f}.tabs>nav>button.is-active{border-color:#0fbb6b}.tabs>nav>button.is-active>span{background:#0fbb6b29}@media(max-width:750px){.tabs .tabs-actions{z-index:5}.tabs .tabs-actions .tabs-actions-toggle{display:inline-flex}.tabs .tabs-actions .tabs-actions-menu{display:none}.tabs .tabs-actions.is-open .tabs-actions-menu{background:#062114f2;border:1px solid rgba(15,187,107,.35);border-radius:.5rem;display:flex;flex-direction:column;gap:.35rem;padding:.5rem;position:absolute;bottom:2.6rem;z-index:1000}.tabs .tabs-actions.tabs-actions--left.is-open .tabs-actions-menu{left:0}.tabs .tabs-actions.tabs-actions--right.is-open .tabs-actions-menu{right:0}.tabs .tabs-actions .action-button{width:100%}}@media(max-width:750px){.tabs{overflow:visible}}\n',':host{font-family:Roboto Condensed,sans-serif;font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);scrollbar-color:rgba(107,255,153,.6) rgba(6,33,20,.6);scrollbar-width:thin;background-color:#062114;background-image:repeating-linear-gradient(to bottom,#ffffff0a 0 1px,#0000 4px);background-size:100% 6px;animation:scan-lines 6s linear infinite;box-shadow:inset 0 0 24px #0009,inset 0 0 90px #00000073;box-sizing:border-box;color:#0fbb6b;display:block;height:100%;overflow:hidden;position:relative;width:100%}:host ::-webkit-scrollbar{width:6px;height:6px}:host ::-webkit-scrollbar-track{background:#06211499}:host ::-webkit-scrollbar-thumb{background:#6bff9999;border-radius:9999px}:host:before{content:"";position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse at center,#06211400 55%,#00000040 70%,#0009);mix-blend-mode:multiply}@keyframes scan-lines{0%{background-position:0 0}to{background-position:0 60px}}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:0;position:relative;width:100%;display:flex;flex-direction:column;min-height:0}.screen-size-overlay{position:absolute;inset:0;background:#000000d9;color:#0fbb6b;display:flex;align-items:center;justify-content:center;text-align:center;padding:2rem;text-transform:uppercase;font-size:clamp(1.1rem,1.1rem + (1.35rem - 1.1rem) * (100vw - 360px) / (1200px - 360px),1.35rem);z-index:200}.center-line{position:relative;height:100%;overflow:visible}.center-line:before{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:2px;background:#0fbb6b}.bottom-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.bottom-half-line:before{content:"";position:absolute;top:50%;bottom:-1.25rem;width:2px;z-index:2;background:linear-gradient(to bottom,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}.top-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.top-half-line:before{content:"";position:absolute;bottom:50%;top:-1.25rem;width:2px;z-index:2;left:0;background:linear-gradient(to top,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}.extra-options{margin-top:.25rem;display:flex;flex-direction:column;font-size:clamp(1.05rem,1.05rem + (1.25rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.25rem);align-items:flex-end;gap:.75rem;white-space:nowrap}.extra-options button{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font:inherit;padding:0;white-space:nowrap}.extra-options button:hover{opacity:.8}.extra-options button:disabled,.extra-options button.is-locked{cursor:default}.extra-options .controller-button{font-size:clamp(1.05rem,1.05rem + (1.25rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.25rem);white-space:nowrap}.extra-options .controller-button .large-par{display:inline;padding-left:.5rem;font-size:clamp(1.45rem,1.45rem + (1.75rem - 1.45rem) * (100vw - 360px) / (1200px - 360px),1.75rem);top:-.15rem;position:relative;white-space:nowrap}.map-panel{display:flex;flex:1 1 auto;min-height:0;position:relative;width:100%}.map-view{align-items:flex-start;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:flex;flex:1 1 auto;justify-content:flex-start;min-height:0;overflow:auto;padding:1.5rem;width:100%}.map-view span{letter-spacing:.1em;margin:auto;text-transform:uppercase;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.map-view img{display:block;max-width:none;max-height:none}.map-view.is-locked,.map-view:disabled{cursor:default}.map-zoom{display:flex;gap:.5rem;position:absolute;right:.75rem;top:.75rem;z-index:2}.map-zoom button{align-items:center;background:#0fbb6b1f;border:1px solid rgba(15,187,107,.65);color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);justify-content:center;text-transform:uppercase;height:2rem;padding:0 .6rem}.map-zoom button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-zoom button:not(:last-child){padding:0;width:2rem}\n'],dependencies:[{kind:"component",type:h,selector:"pip-boy-screen-scan-lines",inputs:["replayTimeoutSeconds","screen","scanSpeedSeconds","tailLengthPx"]},{kind:"component",type:T,selector:"pip-boy-3000-header"},{kind:"component",type:z,selector:"pip-boy-inventory-layout",inputs:["category"]},{kind:"component",type:W,selector:"pip-boy-stats-layout",inputs:["category","valueLabel","valueMin","valueMax"]},{kind:"component",type:H,selector:"pip-boy-reset-confirm-modal",inputs:["open","title","message","confirmLabel","cancelLabel"],outputs:["confirm","closeResult"]},{kind:"component",type:U,selector:"pip-boy-name-edit-modal",inputs:["open","title","value","placeholder","allowEmpty"],outputs:["closeResult","save"]},{kind:"component",type:V,selector:"pip-boy-cnd-status"},{kind:"component",type:_,selector:"pip-boy-radiation-meter"},{kind:"component",type:$,selector:"pip-boy-eff-layout"},{kind:"component",type:Z,selector:"pip-boy-map-image-modal",inputs:["open","title","imageUrl"],outputs:["closeResult","save"]},{kind:"component",type:j,selector:"pip-boy-quests-layout"},{kind:"component",type:X,selector:"pip-boy-settings-modal",inputs:["open","scanLinesEnabled","editLockEnabled","listFontScale","secondaryTabSoundLabel","mainTabSoundLabel","clickSoundLabel"],outputs:["closeResult","save","previewListFontScale"]},{kind:"component",type:Y,selector:"pip-boy-music-layout",inputs:["category"]},{kind:"component",type:J,selector:"pip-boy-welcome-modal",inputs:["open","listFontScale"],outputs:["closeResult","previewListFontScale"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:ee,decorators:[{type:n,args:[{selector:"pip-boy-3000",standalone:!0,imports:[h,T,z,W,H,U,V,_,$,Z,j,X,Y,J],providers:[w],template:'<main\n #screen\n class="screen"\n [style.--list-font-scale]="settings.listFontScale()"\n>\n @if (settings.scanLinesEnabled()) {\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="300"\n />\n }\n @if (isScreenTooSmall()) {\n <div class="screen-size-overlay" role="alert" aria-live="assertive">\n Screen is too small.<br />Please rotate to landscape.\n </div>\n }\n \x3c!-- HEADER --\x3e\n <pip-boy-3000-header />\n \x3c!-- CONTENT --\x3e\n <section class="content">\n @if (state.primary() === \'STATS\') {\n @if (state.secondary() === \'STATUS\') {\n <div class="status-content">\n <nav class="column sub-content" aria-label="Status tabs">\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'CND\'"\n (click)="state.selectTertiary(\'CND\')"\n >\n CND\n </button>\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'RAD\'"\n (click)="state.selectTertiary(\'RAD\')"\n >\n RAD\n </button>\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'EFF\'"\n (click)="state.selectTertiary(\'EFF\')"\n >\n EFF\n </button>\n </nav>\n @if (state.tertiary() === \'CND\') {\n <pip-boy-cnd-status />\n } @else if (state.tertiary() === \'RAD\') {\n <pip-boy-radiation-meter />\n <div class="extra-options">\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'RADAWAY\')"\n >\n {{ settings.radAwayLabel() }}\n </button>\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'RADX\')"\n >\n {{ settings.radXLabel() }}\n </button>\n </div>\n } @else if (state.tertiary() === \'EFF\') {\n <pip-boy-eff-layout />\n }\n </div>\n } @else if (state.secondary() === \'S.P.E.C.I.A.L.\') {\n <pip-boy-stats-layout\n category="SPECIAL"\n valueLabel="Rating"\n [valueMin]="1"\n [valueMax]="10"\n />\n } @else if (state.secondary() === \'SKILLS\') {\n <pip-boy-stats-layout\n category="SKILLS"\n valueLabel="Skill"\n [valueMin]="0"\n [valueMax]="100"\n />\n } @else if (state.secondary() === \'PERKS\') {\n <pip-boy-stats-layout\n category="PERKS"\n valueLabel="Rank"\n [valueMin]="0"\n />\n } @else if (state.secondary() === \'GENERAL\') {\n <pip-boy-stats-layout category="GENERAL" valueLabel="Value" />\n }\n } @else if (state.primary() === \'ITEMS\') {\n @if (state.secondary() === \'WEAPONS\') {\n <pip-boy-inventory-layout category="WEAPONS" />\n } @else if (state.secondary() === \'APPAREL\') {\n <pip-boy-inventory-layout category="APPAREL" />\n } @else if (state.secondary() === \'AID\') {\n <pip-boy-inventory-layout category="AID" />\n } @else if (state.secondary() === \'MISC\') {\n <pip-boy-inventory-layout category="MISC" />\n } @else if (state.secondary() === \'AMMO\') {\n <pip-boy-inventory-layout category="AMMO" />\n }\n } @else if (state.primary() === \'DATA\') {\n @if (state.secondary() === \'LOCAL MAP\') {\n <div class="map-panel">\n <button\n type="button"\n class="map-view"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openMapImageModal(\'LOCAL\')"\n >\n @if (settings.localMapImage()) {\n <img\n [src]="imageStore.getImageUrl(settings.localMapImage())"\n alt="Local map"\n [style.transform]="\'scale(\' + localMapZoom() + \')\'"\n style="transform-origin: top left"\n />\n } @else {\n <span>CLICK TO UPLOAD IMAGE</span>\n }\n </button>\n @if (settings.localMapImage()) {\n <div\n class="map-zoom"\n role="group"\n tabindex="0"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n >\n <button type="button" (click)="zoomMap(\'LOCAL\', 0.2)">+</button>\n <button type="button" (click)="zoomMap(\'LOCAL\', -0.2)">-</button>\n <button type="button" (click)="resetMapZoom(\'LOCAL\')">\n Reset\n </button>\n </div>\n }\n </div>\n } @else if (state.secondary() === \'WORLD MAP\') {\n <div class="map-panel">\n <button\n type="button"\n class="map-view"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openMapImageModal(\'WORLD\')"\n >\n @if (settings.worldMapImage()) {\n <img\n [src]="imageStore.getImageUrl(settings.worldMapImage())"\n alt="World map"\n [style.transform]="\'scale(\' + worldMapZoom() + \')\'"\n style="transform-origin: top left"\n />\n } @else {\n <span>CLICK TO UPLOAD IMAGE</span>\n }\n </button>\n @if (settings.worldMapImage()) {\n <div\n class="map-zoom"\n role="group"\n tabindex="0"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n >\n <button type="button" (click)="zoomMap(\'WORLD\', 0.2)">+</button>\n <button type="button" (click)="zoomMap(\'WORLD\', -0.2)">-</button>\n <button type="button" (click)="resetMapZoom(\'WORLD\')">\n Reset\n </button>\n </div>\n }\n </div>\n } @else if (state.secondary() === \'QUESTS\') {\n <pip-boy-quests-layout />\n } @else if (state.secondary() === \'NOTES\') {\n <pip-boy-music-layout category="NOTES" />\n } @else if (state.secondary() === \'RADIO\') {\n <pip-boy-music-layout category="RADIO" />\n }\n }\n </section>\n \x3c!-- SUB TABS --\x3e\n <section class="sub-tabs">\n @if (state.primary() === \'STATS\') {\n <nav aria-label="Stats tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'STATUS\'"\n (click)="selectSecondary(\'STATUS\')"\n >\n Status\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'S.P.E.C.I.A.L.\'"\n (click)="selectSecondary(\'S.P.E.C.I.A.L.\')"\n >\n S.P.E.C.I.A.L.\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'SKILLS\'"\n (click)="selectSecondary(\'SKILLS\')"\n >\n Skills\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'PERKS\'"\n (click)="selectSecondary(\'PERKS\')"\n >\n Perks\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'GENERAL\'"\n (click)="selectSecondary(\'GENERAL\')"\n >\n General\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n } @else if (state.primary() === \'ITEMS\') {\n <nav aria-label="Items tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'WEAPONS\'"\n (click)="selectSecondary(\'WEAPONS\')"\n >\n Weapons\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'APPAREL\'"\n (click)="selectSecondary(\'APPAREL\')"\n >\n Apparel\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'AID\'"\n (click)="selectSecondary(\'AID\')"\n >\n Aid\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'MISC\'"\n (click)="selectSecondary(\'MISC\')"\n >\n Misc\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'AMMO\'"\n (click)="selectSecondary(\'AMMO\')"\n >\n Ammo\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n } @else if (state.primary() === \'DATA\') {\n <nav aria-label="Data tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'LOCAL MAP\'"\n (click)="selectSecondary(\'LOCAL MAP\')"\n >\n Local Map\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'WORLD MAP\'"\n (click)="selectSecondary(\'WORLD MAP\')"\n >\n World Map\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'QUESTS\'"\n (click)="selectSecondary(\'QUESTS\')"\n >\n Quests\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'NOTES\'"\n (click)="selectSecondary(\'NOTES\')"\n >\n Notes\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'RADIO\'"\n (click)="selectSecondary(\'RADIO\')"\n >\n Radio\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n }\n </section>\n \x3c!-- MAIN TABS --\x3e\n <section class="tabs" [class.is-collapsed]="!tabsOpen()">\n <button\n type="button"\n class="tabs-toggle"\n aria-label="Toggle main tabs"\n [attr.aria-expanded]="tabsOpen()"\n aria-controls="main-tabs"\n (click)="toggleTabs()"\n >\n <span class="tabs-toggle-label tabs-toggle-label--state">\n {{ tabsOpen() ? \'CLOSE\' : \'OPEN\' }}\n </span>\n <span class="caret" aria-hidden="true"></span>\n <span class="tabs-toggle-label tabs-toggle-label--menu">MENU</span>\n </button>\n <nav id="main-tabs" aria-label="Main tabs">\n <div\n class="tabs-actions tabs-actions--left"\n [class.is-open]="tabsActionsLeftOpen()"\n >\n <button\n type="button"\n class="tabs-actions-toggle"\n aria-label="Open settings actions"\n (click)="toggleTabsActions(\'left\')"\n >\n <span class="tabs-actions-icon" aria-hidden="true"></span>\n </button>\n <div class="tabs-actions-menu">\n <button\n type="button"\n class="action-button"\n aria-label="Save settings"\n title="Save settings"\n (click)="saveSettingsToFile()"\n >\n Save\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Load settings"\n title="Load settings"\n (click)="loadSettingsInput.click()"\n >\n Load\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Reset settings"\n title="Reset settings"\n (click)="openResetModal()"\n >\n Reset\n </button>\n <input\n #loadSettingsInput\n type="file"\n accept=".zip,application/zip"\n (change)="loadSettingsFromFile($event)"\n />\n </div>\n </div>\n <button\n type="button"\n [class.is-active]="state.primary() === \'STATS\'"\n (click)="selectPrimary(\'STATS\')"\n >\n <span>STATS</span>\n </button>\n <button\n type="button"\n [class.is-active]="state.primary() === \'ITEMS\'"\n (click)="selectPrimary(\'ITEMS\')"\n >\n <span>ITEMS</span>\n </button>\n <button\n type="button"\n [class.is-active]="state.primary() === \'DATA\'"\n (click)="selectPrimary(\'DATA\')"\n >\n <span>DATA</span>\n </button>\n <div\n class="tabs-actions tabs-actions--right"\n [class.is-open]="tabsActionsRightOpen()"\n >\n <button\n type="button"\n class="tabs-actions-toggle"\n aria-label="Open utility actions"\n (click)="toggleTabsActions(\'right\')"\n >\n <span class="tabs-actions-icon" aria-hidden="true"></span>\n </button>\n <div class="tabs-actions-menu">\n <button\n type="button"\n class="action-button"\n aria-label="Open GitHub profile"\n title="Open GitHub profile"\n (click)="openGithubProfile()"\n >\n ❤\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Open settings"\n title="Settings"\n (click)="openSettingsModal()"\n >\n Settings\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Report a bug"\n title="Report a bug"\n (click)="openBugModal()"\n >\n Bug\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Reset settings"\n title="Exit"\n (click)="openExitModal()"\n >\n Exit\n </button>\n <input\n #loadSettingsInput\n type="file"\n accept=".zip,application/zip"\n (change)="loadSettingsFromFile($event)"\n />\n </div>\n </div>\n @if (tabsOpen()) {\n <div class="tabs-version">v{{ appVersion }}</div>\n }\n </nav>\n </section>\n <pip-boy-welcome-modal\n [open]="showWelcomeModal()"\n [listFontScale]="settings.listFontScale()"\n (previewListFontScale)="previewListFontScale($event)"\n (closeResult)="closeWelcomeModal()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showResetModal()"\n title="Reset Settings"\n message="This will reset all values back to defaults. This cannot be undone."\n confirmLabel="Reset"\n (closeResult)="closeResetModal()"\n (confirm)="confirmReset()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showExitModal()"\n title="Exit"\n message="Are you sure you want to leave this screen?"\n confirmLabel="Exit"\n (closeResult)="closeExitModal()"\n (confirm)="confirmExit()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showBugModal()"\n title="Report a bug"\n message="Would you like to report a bug?"\n confirmLabel="Yes"\n cancelLabel="No"\n (closeResult)="closeBugModal()"\n (confirm)="confirmBugReport()"\n />\n <pip-boy-map-image-modal\n [open]="mapImageModal() !== null"\n [title]="mapImageModalTitle()"\n [imageUrl]="mapImageModalImage()"\n (closeResult)="closeMapImageModal()"\n (save)="saveMapImageModal($event)"\n />\n <pip-boy-settings-modal\n [open]="showSettingsModal()"\n [scanLinesEnabled]="settings.scanLinesEnabled()"\n [editLockEnabled]="settings.editLockEnabled()"\n [listFontScale]="settings.listFontScale()"\n [secondaryTabSoundLabel]="secondaryTabSoundLabel()"\n [mainTabSoundLabel]="mainTabSoundLabel()"\n [clickSoundLabel]="clickSoundLabel()"\n (closeResult)="cancelSettingsModal()"\n (previewListFontScale)="previewListFontScale($event)"\n (save)="saveSettingsModal($event)"\n />\n <pip-boy-name-edit-modal\n [open]="extraOptionModal() !== null"\n [value]="extraOptionValue()"\n [title]="extraOptionTitle()"\n placeholder="Value"\n [allowEmpty]="true"\n (closeResult)="closeExtraOptionModal()"\n (save)="saveExtraOptionModal($event)"\n />\n</main>\n',styles:[".content{box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%;overflow:auto;padding:1rem 2rem;width:100%}.content .status-content{box-sizing:border-box;display:flex;flex-direction:row;height:100%;gap:1rem}.content .column{box-sizing:border-box;display:flex;flex:1;flex-direction:column}.content .sub-content{max-width:max-content}.content .sub-content button{width:auto;max-width:10rem;height:2.5rem;background:transparent;color:#0fbb6b;text-transform:uppercase;border:none;border-left:2px solid transparent;border-right:2px solid transparent;cursor:pointer;padding:0 1rem;margin-bottom:1rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.content .sub-content button.is-active{background:#0fbb6b14;border-left:2px solid #0fbb6b;border-right:2px solid #0fbb6b}.content .sub-content button:hover{background:#0fbb6b26}.content .radiation-status,.content .effects-status{box-sizing:border-box;display:flex;align-items:center;justify-content:center}.content .actions{box-sizing:border-box;display:flex;align-items:flex-end;max-width:max-content}\n",".sub-tabs{flex:0 0 auto;min-height:0;margin-bottom:.5rem;padding:0 1rem;position:relative;z-index:1}.sub-tabs>nav{box-sizing:border-box;display:flex;align-items:center;width:100%;height:2.25rem;gap:0}.sub-tabs>nav .center-line{flex:1 1 auto;height:100%;min-width:1.5rem}.sub-tabs>nav>.center-line:last-child .top-half-line:before{left:auto;right:0}.sub-tabs>nav button{background:transparent;border:2px solid transparent;color:#0fbb6b;cursor:pointer;font-size:clamp(1.25rem,1.25rem + (1.5rem - 1.25rem) * (100vw - 360px) / (1200px - 360px),1.5rem);padding:.5rem}.sub-tabs>nav button.is-active{background:#0fbb6b14;border:2px solid #0fbb6b}.sub-tabs>nav button:hover{background:#0fbb6b26}\n",'.tabs{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;flex:0 0 auto;gap:.5rem;max-height:12rem;overflow:hidden;padding:0;position:relative;z-index:5;transition:max-height .35s ease-in-out,padding .35s ease-in-out,gap .35s ease-in-out;width:100%}.tabs.is-collapsed{gap:0;max-height:2rem}.tabs.is-collapsed>nav{opacity:0;pointer-events:none;transform:translateY(100%)}.tabs.is-collapsed .tabs-toggle .caret{transform:translateY(2px) rotate(-135deg)}.tabs .tabs-toggle{align-items:center;background:transparent;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;display:inline-flex;height:2rem;justify-content:center;line-height:0;max-height:2rem;min-height:2rem;overflow:hidden;padding:0 1rem;transition:border-color .2s ease;width:100%}.tabs .tabs-toggle:hover{background-color:#0fbb6b1f}.tabs .tabs-toggle .caret{border:solid #0fbb6b;border-width:0 2px 2px 0;box-sizing:border-box;display:inline-block;height:.6rem;margin:0 .5rem;padding:0;transform:translateY(-4px) rotate(45deg);transform-origin:center;transition:transform .35s ease;width:.6rem}.tabs .tabs-toggle .tabs-toggle-label{font-size:clamp(.7rem,.7rem + (.85rem - .7rem) * (100vw - 360px) / (1200px - 360px),.85rem);letter-spacing:.1em;line-height:1;text-transform:uppercase;white-space:nowrap}.tabs>nav{display:flex;justify-content:center;opacity:1;padding-bottom:.5rem;transform:translateY(0);transition:transform .35s ease-in-out,opacity .35s ease-in-out;transform-origin:bottom;will-change:transform,opacity;width:100%;position:relative}.tabs .tabs-version{bottom:14px;color:#0fbb6bbf;font-size:10px;letter-spacing:.08em;position:absolute;right:22px}.tabs .tabs-actions{align-items:center;display:flex;gap:.5rem;left:1rem;position:absolute;top:50%;transform:translateY(-50%)}.tabs .tabs-actions.right,.tabs .tabs-actions.tabs-actions--right{left:auto;right:1rem}.tabs .tabs-actions .tabs-actions-toggle{align-items:center;background:transparent;border:1px solid rgba(15,187,107,.6);border-radius:9999px;color:#0fbb6b;cursor:pointer;display:none;height:2.1rem;justify-content:center;padding:0 .6rem;text-transform:uppercase;width:2.4rem}.tabs .tabs-actions .tabs-actions-toggle:hover{background:#0fbb6b1f;border-color:#0fbb6b}.tabs .tabs-actions .tabs-actions-icon{background:#0fbb6b;border-radius:9999px;display:block;height:2px;position:relative;width:1.1rem}.tabs .tabs-actions .tabs-actions-icon:before,.tabs .tabs-actions .tabs-actions-icon:after{content:"";background:#0fbb6b;border-radius:9999px;height:2px;left:0;position:absolute;width:100%}.tabs .tabs-actions .tabs-actions-icon:before{top:-5px}.tabs .tabs-actions .tabs-actions-icon:after{top:5px}.tabs .tabs-actions .tabs-actions-menu{display:flex;gap:.5rem;align-items:center}.tabs .tabs-actions .action-button{background:transparent;border:1px solid rgba(15,187,107,.7);color:#0fbb6bb3;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.25rem .35rem;text-align:left;width:100%;border-radius:1rem;text-align:center}.tabs .tabs-actions .action-button:hover{background:#0fbb6b1f;border-color:#0fbb6b}.tabs .tabs-actions input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.tabs .tabs-action{align-items:center;background:#0fbb6b1a;border:2px solid rgba(15,187,107,.6);border-radius:.4rem;color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.65rem,.65rem + (.75rem - .65rem) * (100vw - 360px) / (1200px - 360px),.75rem);height:2.5rem;justify-content:center;letter-spacing:.08em;padding:0 .85rem;text-transform:uppercase;transition:background .2s ease,border-color .2s ease;width:auto}.tabs .tabs-action:hover{background:#0fbb6b2e;border-color:#0fbb6b}.tabs>nav>button{align-items:center;background:transparent;border-radius:9999px;border:2px solid rgba(15,187,107,.35);box-sizing:border-box;color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);height:5rem;justify-content:center;line-height:1;margin:0 1rem;padding:0;text-transform:uppercase;width:5rem}.tabs>nav>button>span{align-items:center;display:inline-flex;justify-content:center;line-height:1;white-space:nowrap;width:100%;height:100%;border-radius:9999px;padding:0}.tabs>nav>button:hover{border-color:#0fbb6ba6}.tabs>nav>button:hover>span{background:#0fbb6b1f}.tabs>nav>button.is-active{border-color:#0fbb6b}.tabs>nav>button.is-active>span{background:#0fbb6b29}@media(max-width:750px){.tabs .tabs-actions{z-index:5}.tabs .tabs-actions .tabs-actions-toggle{display:inline-flex}.tabs .tabs-actions .tabs-actions-menu{display:none}.tabs .tabs-actions.is-open .tabs-actions-menu{background:#062114f2;border:1px solid rgba(15,187,107,.35);border-radius:.5rem;display:flex;flex-direction:column;gap:.35rem;padding:.5rem;position:absolute;bottom:2.6rem;z-index:1000}.tabs .tabs-actions.tabs-actions--left.is-open .tabs-actions-menu{left:0}.tabs .tabs-actions.tabs-actions--right.is-open .tabs-actions-menu{right:0}.tabs .tabs-actions .action-button{width:100%}}@media(max-width:750px){.tabs{overflow:visible}}\n',':host{font-family:Roboto Condensed,sans-serif;font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);scrollbar-color:rgba(107,255,153,.6) rgba(6,33,20,.6);scrollbar-width:thin;background-color:#062114;background-image:repeating-linear-gradient(to bottom,#ffffff0a 0 1px,#0000 4px);background-size:100% 6px;animation:scan-lines 6s linear infinite;box-shadow:inset 0 0 24px #0009,inset 0 0 90px #00000073;box-sizing:border-box;color:#0fbb6b;display:block;height:100%;overflow:hidden;position:relative;width:100%}:host ::-webkit-scrollbar{width:6px;height:6px}:host ::-webkit-scrollbar-track{background:#06211499}:host ::-webkit-scrollbar-thumb{background:#6bff9999;border-radius:9999px}:host:before{content:"";position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse at center,#06211400 55%,#00000040 70%,#0009);mix-blend-mode:multiply}@keyframes scan-lines{0%{background-position:0 0}to{background-position:0 60px}}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:0;position:relative;width:100%;display:flex;flex-direction:column;min-height:0}.screen-size-overlay{position:absolute;inset:0;background:#000000d9;color:#0fbb6b;display:flex;align-items:center;justify-content:center;text-align:center;padding:2rem;text-transform:uppercase;font-size:clamp(1.1rem,1.1rem + (1.35rem - 1.1rem) * (100vw - 360px) / (1200px - 360px),1.35rem);z-index:200}.center-line{position:relative;height:100%;overflow:visible}.center-line:before{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:2px;background:#0fbb6b}.bottom-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.bottom-half-line:before{content:"";position:absolute;top:50%;bottom:-1.25rem;width:2px;z-index:2;background:linear-gradient(to bottom,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}.top-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.top-half-line:before{content:"";position:absolute;bottom:50%;top:-1.25rem;width:2px;z-index:2;left:0;background:linear-gradient(to top,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}.extra-options{margin-top:.25rem;display:flex;flex-direction:column;font-size:clamp(1.05rem,1.05rem + (1.25rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.25rem);align-items:flex-end;gap:.75rem;white-space:nowrap}.extra-options button{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font:inherit;padding:0;white-space:nowrap}.extra-options button:hover{opacity:.8}.extra-options button:disabled,.extra-options button.is-locked{cursor:default}.extra-options .controller-button{font-size:clamp(1.05rem,1.05rem + (1.25rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.25rem);white-space:nowrap}.extra-options .controller-button .large-par{display:inline;padding-left:.5rem;font-size:clamp(1.45rem,1.45rem + (1.75rem - 1.45rem) * (100vw - 360px) / (1200px - 360px),1.75rem);top:-.15rem;position:relative;white-space:nowrap}.map-panel{display:flex;flex:1 1 auto;min-height:0;position:relative;width:100%}.map-view{align-items:flex-start;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:flex;flex:1 1 auto;justify-content:flex-start;min-height:0;overflow:auto;padding:1.5rem;width:100%}.map-view span{letter-spacing:.1em;margin:auto;text-transform:uppercase;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.map-view img{display:block;max-width:none;max-height:none}.map-view.is-locked,.map-view:disabled{cursor:default}.map-zoom{display:flex;gap:.5rem;position:absolute;right:.75rem;top:.75rem;z-index:2}.map-zoom button{align-items:center;background:#0fbb6b1f;border:1px solid rgba(15,187,107,.65);color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);justify-content:center;text-transform:uppercase;height:2rem;padding:0 .6rem}.map-zoom button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-zoom button:not(:last-child){padding:0;width:2rem}\n']}]}],propDecorators:{returnToUrl:[{type:e.Input,args:[{isSignal:!0,alias:"returnToUrl",required:!1}]}],onResize:[{type:p,args:["window:resize"]}]}});export{y as PipBoy2000MkVI,ee as PipBoy3000,I as PipBoy3000MkIV,w as PipBoy3000State,v as PipBoy3000a};
|
|
1
|
+
import*as e from"@angular/core";import{input as t,ViewChild as a,Component as n,signal as o,Injectable as i,effect as r,inject as s,EventEmitter as l,Output as d,Input as m,computed as c,output as u,HostListener as p}from"@angular/core";import b from"gsap";import{CommonModule as g}from"@angular/common";import f from"jszip";class h{replayTimeoutSeconds=t(8,...ngDevMode?[{debugName:"replayTimeoutSeconds"}]:[]);screen=t.required(...ngDevMode?[{debugName:"screen"}]:[]);scanSpeedSeconds=t(5,...ngDevMode?[{debugName:"scanSpeedSeconds"}]:[]);tailLengthPx=t(300,...ngDevMode?[{debugName:"tailLengthPx"}]:[]);scanlineRef;scanTween=null;resizeObserver=null;ngAfterViewInit(){if(window.matchMedia("(prefers-reduced-motion: reduce)").matches)return;const e=this.scanlineRef.nativeElement,t=this.screen(),a=()=>{e.style.height=`${this.tailLengthPx()}px`;const a=t.clientHeight,n=e.offsetHeight;if(a<=0||n<=0)return;const o=-n,i=a+n;this.scanTween&&(this.scanTween.kill(),this.scanTween=null),b.set(e,{y:o});const r=this.replayTimeoutSeconds(),s=r>0?Math.random()*r:0;this.scanTween=b.to(e,{y:i,duration:this.scanSpeedSeconds(),ease:"none",repeat:-1,repeatDelay:r,delay:s})};a(),this.resizeObserver=new ResizeObserver(()=>{a()}),this.resizeObserver.observe(t)}ngOnDestroy(){this.scanTween&&(this.scanTween.kill(),this.scanTween=null),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:h,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.1.0",version:"21.0.8",type:h,isStandalone:!0,selector:"pip-boy-screen-scan-lines",inputs:{replayTimeoutSeconds:{classPropertyName:"replayTimeoutSeconds",publicName:"replayTimeoutSeconds",isSignal:!0,isRequired:!1,transformFunction:null},screen:{classPropertyName:"screen",publicName:"screen",isSignal:!0,isRequired:!0,transformFunction:null},scanSpeedSeconds:{classPropertyName:"scanSpeedSeconds",publicName:"scanSpeedSeconds",isSignal:!0,isRequired:!1,transformFunction:null},tailLengthPx:{classPropertyName:"tailLengthPx",publicName:"tailLengthPx",isSignal:!0,isRequired:!1,transformFunction:null}},viewQueries:[{propertyName:"scanlineRef",first:!0,predicate:["scanline"],descendants:!0,static:!0}],ngImport:e,template:'<div #scanline class="screen-scanline" aria-hidden="true"></div>\n',styles:['.screen>:not(.screen-scanline){position:relative;z-index:1}.screen-scanline{position:absolute;left:0;right:0;top:0;height:140px;z-index:0;pointer-events:none;background:linear-gradient(to bottom,#3ad03a00,#3ad03a0a 35%,#3ad03a1f 65%,#3ad03a29 85%);mix-blend-mode:screen;opacity:.5;filter:blur(5px)}.screen-scanline:after{content:"";position:absolute;left:0;right:0;bottom:8px;height:2px}\n']})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:h,decorators:[{type:n,args:[{selector:"pip-boy-screen-scan-lines",template:'<div #scanline class="screen-scanline" aria-hidden="true"></div>\n',styles:['.screen>:not(.screen-scanline){position:relative;z-index:1}.screen-scanline{position:absolute;left:0;right:0;top:0;height:140px;z-index:0;pointer-events:none;background:linear-gradient(to bottom,#3ad03a00,#3ad03a0a 35%,#3ad03a1f 65%,#3ad03a29 85%);mix-blend-mode:screen;opacity:.5;filter:blur(5px)}.screen-scanline:after{content:"";position:absolute;left:0;right:0;bottom:8px;height:2px}\n']}]}],propDecorators:{replayTimeoutSeconds:[{type:e.Input,args:[{isSignal:!0,alias:"replayTimeoutSeconds",required:!1}]}],screen:[{type:e.Input,args:[{isSignal:!0,alias:"screen",required:!0}]}],scanSpeedSeconds:[{type:e.Input,args:[{isSignal:!0,alias:"scanSpeedSeconds",required:!1}]}],tailLengthPx:[{type:e.Input,args:[{isSignal:!0,alias:"tailLengthPx",required:!1}]}],scanlineRef:[{type:a,args:["scanline",{static:!0}]}]}});class y{static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:y,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"21.0.8",type:y,isStandalone:!0,selector:"pip-boy-2000-mk-vi",ngImport:e,template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"],dependencies:[{kind:"component",type:h,selector:"pip-boy-screen-scan-lines",inputs:["replayTimeoutSeconds","screen","scanSpeedSeconds","tailLengthPx"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:y,decorators:[{type:n,args:[{selector:"pip-boy-2000-mk-vi",standalone:!0,imports:[h],template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"]}]}]});class v{static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:v,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"21.0.8",type:v,isStandalone:!0,selector:"pip-boy-3000a",ngImport:e,template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"],dependencies:[{kind:"component",type:h,selector:"pip-boy-screen-scan-lines",inputs:["replayTimeoutSeconds","screen","scanSpeedSeconds","tailLengthPx"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:v,decorators:[{type:n,args:[{selector:"pip-boy-3000a",standalone:!0,imports:[h],template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"]}]}]});class I{static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:I,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"21.0.8",type:I,isStandalone:!0,selector:"pip-boy-3000-mk-iv",ngImport:e,template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"],dependencies:[{kind:"component",type:h,selector:"pip-boy-screen-scan-lines",inputs:["replayTimeoutSeconds","screen","scanSpeedSeconds","tailLengthPx"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:I,decorators:[{type:n,args:[{selector:"pip-boy-3000-mk-iv",standalone:!0,imports:[h],template:'<section #screen class="screen">\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="200"\n />\n</section>\n',styles:[":host{background:#030703;box-sizing:border-box;color:#3ad03a;display:block;height:100%;width:100%}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:1rem;position:relative;width:100%}\n"]}]}]});class w{primary=o("STATS",...ngDevMode?[{debugName:"primary"}]:[]);secondary=o("STATUS",...ngDevMode?[{debugName:"secondary"}]:[]);tertiary=o("CND",...ngDevMode?[{debugName:"tertiary"}]:[]);selectPrimary(e){if(this.primary()!==e)switch(this.primary.set(e),e){case"STATS":this.secondary.set("STATUS"),this.tertiary.set("CND");break;case"ITEMS":this.secondary.set("WEAPONS"),this.tertiary.set(null);break;case"DATA":this.secondary.set("LOCAL MAP"),this.tertiary.set(null);break;default:throw new Error(`Unhandled primary tab selection: ${e}`)}}selectSecondary(e){this.secondary.set(e),"STATS"!==this.primary()||"STATUS"!==e?this.tertiary.set(null):null===this.tertiary()&&this.tertiary.set("CND")}selectTertiary(e){"STATS"===this.primary()&&"STATUS"===this.secondary()&&this.tertiary.set(e)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:w,deps:[],target:e.ɵɵFactoryTarget.Injectable});static"ɵprov"=e.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:w})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:w,decorators:[{type:i}]});class x{dbPromise=this.openDb();imageUrls=o({},...ngDevMode?[{debugName:"imageUrls"}]:[]);loading=new Set;getImageUrl(e){if(!e)return null;const t=this.imageUrls()[e];return t||(this.loadImageUrl(e),null)}async saveFile(e){const t=this.createId(),a={id:t,fileName:e.name,mime:e.type||"application/octet-stream"};return await this.putRecord({...a,blob:e}),this.cacheUrl(t,URL.createObjectURL(e)),a}async saveBlobWithId(e,t,a,n){await this.putRecord({id:e,blob:t,fileName:a,mime:n}),this.cacheUrl(e,URL.createObjectURL(t))}async saveDataUrlWithId(e,t){const a=await fetch(t),n=await a.blob(),o=n.type||"application/octet-stream",i=`image-${e}${this.extensionFromMime(o)}`;await this.saveBlobWithId(e,n,i,o)}async getRecord(e){const t=await this.dbPromise;return new Promise((a,n)=>{const o=t.transaction("images","readonly").objectStore("images").get(e);o.onsuccess=()=>{a(o.result??null)},o.onerror=()=>n(o.error)})}async getBlob(e){const t=await this.getRecord(e);return t?.blob??null}extensionFromMime(e){switch(e){case"image/png":return".png";case"image/jpeg":return".jpg";case"image/webp":return".webp";case"image/gif":return".gif";case"image/svg+xml":return".svg";default:return""}}generateId(){return this.createId()}cacheUrl(e,t){this.imageUrls.update(a=>({...a,[e]:t}))}async loadImageUrl(e){if(!this.loading.has(e)){this.loading.add(e);try{const t=await this.getBlob(e);if(!t)return;this.cacheUrl(e,URL.createObjectURL(t))}finally{this.loading.delete(e)}}}async putRecord(e){const t=await this.dbPromise;return new Promise((a,n)=>{const o=t.transaction("images","readwrite").objectStore("images").put(e);o.onsuccess=()=>a(),o.onerror=()=>n(o.error)})}openDb(){return new Promise((e,t)=>{const a=indexedDB.open("pipBoy3000Images",1);a.onupgradeneeded=()=>{const e=a.result;e.objectStoreNames.contains("images")||e.createObjectStore("images",{keyPath:"id"})},a.onsuccess=()=>e(a.result),a.onerror=()=>t(a.error)})}createId(){return"undefined"!=typeof crypto&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:x,deps:[],target:e.ɵɵFactoryTarget.Injectable});static"ɵprov"=e.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:x,providedIn:"root"})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:x,decorators:[{type:i,args:[{providedIn:"root"}]}]});const k=[{formId:"0003C345",editorId:"AntMeat",name:"Ant Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00031020",editorId:"AntNectar",name:"Ant Nectar",nonPlayable:!1,wg:.25,val:20,effects:"INT +2,CHA +2,STR +4,Usage Monitor Effect 20"},{formId:"00033068",editorId:"AntQueenPheromones",name:"Ant Queen Pheromones",nonPlayable:!1,wg:1,val:75,effects:"CHA +3,INT +3,PER +3"},{formId:"00015197",editorId:"Beer",name:"Beer",nonPlayable:!1,wg:1,val:2,effects:"INT +1,STR +1,CHA +1"},{formId:"000BF7C6",editorId:"MS15Mentat02",name:"Berry Mentats",nonPlayable:!1,wg:0,val:20,effects:"INT +5"},{formId:"0008C556",editorId:"BlamcoMacandCheese",name:"Blamco Mac and Cheese",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0007C10D",editorId:"BloatflyMeat",name:"Bloatfly Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00034051",editorId:"BloodPack",name:"Blood Pack",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 19,Restore Health 1"},{formId:"00015198",editorId:"BrahminSteak",name:"Brahmin Steak",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0008C560",editorId:"Bubblegum",name:"Bubblegum",nonPlayable:!1,wg:1,val:1,effects:"Restore Health 1,Restore Health 1,Damage Rads 1"},{formId:"00015163",editorId:"Buffout",name:"Buffout",nonPlayable:!1,wg:0,val:20,effects:"STR +2,END +3,Increased Health - Buffout 60,Usage Monitor Effect 30"},{formId:"00038E0C",editorId:"CaveFungus",name:"Cave Fungus",nonPlayable:!1,wg:1,val:50,effects:"Restore Health 5,Restore Rads 10"},{formId:"0008C552",editorId:"Cram",name:"Cram",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00031948",editorId:"SquirrelBits",name:"Crispy Squirrel Bits",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0001519C",editorId:"Mutfruit1",name:"Crunchy Mutfruit",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0008C554",editorId:"DandyBoyApples",name:"Dandy Boy Apples",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"000151A4",editorId:"WaterUnpurified",name:"Dirty Water",nonPlayable:!1,wg:1,val:10,effects:"Restore Health 10,Restore Health 2,Damage Rads 6"},{formId:"00034050",editorId:"DogMeat",name:"Dog Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0008C55A",editorId:"FancyLadsSnackCakes",name:"Fancy Lads Snack Cakes",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00085ABB",editorId:"MS04FireAntNectar",name:"Fire Ant Nectar",nonPlayable:!1,wg:1,val:20,effects:"AGL +4,INT +3,Increased Fire Resistance 25"},{formId:"00015196",editorId:"Apple",name:"Fresh Apple",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 10"},{formId:"00015199",editorId:"Carrot",name:"Fresh Carrot",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 10"},{formId:"0001519F",editorId:"Pear",name:"Fresh Pear",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 10"},{formId:"000151A0",editorId:"Potato",name:"Fresh Potato",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 10"},{formId:"000BF7C5",editorId:"MS15Mentat01",name:"Grape Mentats",nonPlayable:!1,wg:0,val:20,effects:"CHA +5"},{formId:"0008C564",editorId:"RadioactiveGumDrops",name:"Gum Drops",nonPlayable:!1,wg:1,val:2,effects:"Restore Health 1,Damage Rads 1,Restore Health 1"},{formId:"00065175",editorId:"MirelurkMeatHatchling",name:"Hatchling Mirelurk Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0003404F",editorId:"HumanFlesh",name:"Human Flesh",nonPlayable:!1,wg:1,val:0,effects:"Restore Health 25,Restore Health 5,Damage Rads 10"},{formId:"00040DCB",editorId:"MS05IceNukaCola",name:"Ice Cold Nuka-Cola",nonPlayable:!1,wg:1,val:20,effects:"Restore Health 20,Nuka-Cola Add Cap Effect,Restore Health 4,Damage Rads 3"},{formId:"0001519A",editorId:"IguanaBits",name:"Iguana Bits",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0001519B",editorId:"IguanaOnAStick",name:"Iguana on a Stick",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0008C558",editorId:"InstaMash",name:"InstaMash",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00015164",editorId:"Jet",name:"Jet",nonPlayable:!1,wg:0,val:20,effects:"Increase Action Points - Jet 30,Usage Monitor Effect 30"},{formId:"0003359C",editorId:"JunkFood",name:"Junk Food",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00050F8F",editorId:"Morphine",name:"Med-X",nonPlayable:!1,wg:0,val:20,effects:"Increase Damage Resistance - Psycho 25,Usage Monitor Effect 30"},{formId:"00015165",editorId:"Mentats",name:"Mentats",nonPlayable:!1,wg:0,val:20,effects:"INT +5,PER +5,Usage Monitor Effect 30"},{formId:"0003404D",editorId:"MirelurkCakes",name:"Mirelurk Cakes",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0003404E",editorId:"MirelurkMeat",name:"Mirelurk Meat",nonPlayable:!1,wg:1,val:20,effects:"Restore Health 20,Restore Health 4,Damage Rads 3"},{formId:"00049076",editorId:"MS05FinNukaPie",name:"Miss. Quantum Pie",nonPlayable:!1,wg:1,val:20,effects:"STR +1,INT +1,Increased Action Points 20,Damage Rads 5"},{formId:"0003404C",editorId:"MoleRatMeat",name:"Mole Rat Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"000ABD17",editorId:"MoleRatWonderMeat",name:"Mole Rat Wonder Meat",nonPlayable:!1,wg:1,val:20,effects:"Restore Health 20,Restore Health 4,Damage Rads 3"},{formId:"00034049",editorId:"Mutfruit2",name:"Mutfruit",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0001519D",editorId:"Noodles",name:"Noodles",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"000284F9",editorId:"MS05NukaColaQtm",name:"Nuka-Cola Quantum",nonPlayable:!1,wg:1,val:30,effects:"Nuka-Cola Add Cap Effect,Increased Action Points 20,Damage Rads 10,Usage Monitor Effect 12"},{formId:"0001519E",editorId:"NukaCola",name:"Nuka-Cola",nonPlayable:!1,wg:1,val:20,effects:"Restore Health 10,Nuka-Cola Add Cap Effect,Restore Health 2,Damage Rads 3"},{formId:"00095F48",editorId:"MS05NukalurkMeat",name:"NukaLurk Meat",nonPlayable:!1,wg:1,val:7,effects:"Restore Health 20,Restore Health 4,Increased Action Points 10,Damage Rads 5"},{formId:"000BF7C7",editorId:"MS15Mentat03",name:"Orange Mentats",nonPlayable:!1,wg:0,val:20,effects:"PER +5"},{formId:"0008C55E",editorId:"PorkNBeans",name:"Pork N' Beans",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0008C562",editorId:"PotatoCrisps",name:"Potato Crisps",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00015166",editorId:"Psycho",name:"Psycho",nonPlayable:!1,wg:0,val:20,effects:"Damage +25%,Usage Monitor Effect 30"},{formId:"000151A3",editorId:"WaterPurified",name:"Purified Water",nonPlayable:!1,wg:1,val:20,effects:"Restore Health 20"},{formId:"00015167",editorId:"RadAway",name:"RadAway",nonPlayable:!1,wg:0,val:20,effects:"Restore Rads 50"},{formId:"0009C957",editorId:"RadroachMeat",name:"Radroach Meat",nonPlayable:!1,wg:1,val:4,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00015168",editorId:"RadX",name:"Rad-X",nonPlayable:!1,wg:0,val:20,effects:"Increased Radiation Resistance 25"},{formId:"000293A9",editorId:"SalisburySteak",name:"Salisbury Steak",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"000151A1",editorId:"Scotch",name:"Scotch",nonPlayable:!1,wg:1,val:10,effects:"STR +1,INT +1,CHA +1"},{formId:"000552CE",editorId:"MirelurkMeatSoftshell",name:"Softshell Mirelurk Meat",nonPlayable:!1,wg:1,val:30,effects:"Restore Health 30,Restore Health 6,Damage Rads 3"},{formId:"00031949",editorId:"SquirrelOnAStick",name:"Squirrel on a Stick",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"0003194A",editorId:"SquirrelStew",name:"Squirrel Stew",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00043E94",editorId:"StealthBoy",name:"Stealth Boy",nonPlayable:!1,wg:1,val:100,effects:"Stealth Field 75,Increased Sneak 100,Stealth Field Stop Combat"},{formId:"00015169",editorId:"Stimpak",name:"Stimpak",nonPlayable:!1,wg:0,val:25,effects:"Restore Health & Conditions 30,Restore Health & Conditions 36"},{formId:"0007E173",editorId:"StrangeMeatPie",name:"Strange Meat Pie",nonPlayable:!1,wg:1,val:2,effects:"Restore Health 5,Damage Rads 3,Restore Health 1"},{formId:"0002E376",editorId:"StrangeMeat",name:"Strange Meat",nonPlayable:!1,wg:1,val:2,effects:"Restore Health 5,Damage Rads 3,Restore Health 1"},{formId:"0008C551",editorId:"SugarBombs01",name:"Sugar Bombs",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"},{formId:"00030A23",editorId:"CG02Sweetroll",name:"Sweetroll",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1"},{formId:"000C9CF4",editorId:"MS09Ultrajet",name:"Ultrajet",nonPlayable:!1,wg:0,val:50,effects:"Increase Action Points - Jet 40,Usage Monitor Effect 12"},{formId:"00032C74",editorId:"Vodka",name:"Vodka",nonPlayable:!1,wg:1,val:20,effects:"STR +1,INT +1,CHA +1"},{formId:"00032C75",editorId:"Whiskey",name:"Whiskey",nonPlayable:!1,wg:1,val:10,effects:"STR +1,INT +1,CHA +1"},{formId:"0003404A",editorId:"Wine",name:"Wine",nonPlayable:!1,wg:1,val:10,effects:"STR +1,INT +1,CHA +1"},{formId:"0003404B",editorId:"YaoGuaiMeat",name:"Yao Guai Meat",nonPlayable:!1,wg:1,val:30,effects:"Restore Health 10,Restore Health 2,Damage Rads 10,Damage +10%"},{formId:"0008C55C",editorId:"YumYumDeviledEggs",name:"YumYum Deviled Eggs",nonPlayable:!1,wg:1,val:5,effects:"Restore Health 5,Restore Health 1,Damage Rads 3"}],S=[{formId:"0006B53C",editorId:"Ammo308Caliber",name:".308 Caliber Round",nonPlayable:!1,wg:0,val:3},{formId:"000207F7",editorId:"Ammo32Caliber",name:".32 Caliber Round",nonPlayable:!1,wg:0,val:1},{formId:"0002937E",editorId:"Ammo44magnum",name:".44 Round, Magnum",nonPlayable:!1,wg:0,val:2},{formId:"00004241",editorId:"Ammo10mm",name:"10mm Round",nonPlayable:!1,wg:0,val:1},{formId:"00004240",editorId:"Ammo556mm",name:"5.56mm Round",nonPlayable:!1,wg:0,val:1},{formId:"00078CC4",editorId:"Ammo556mmRobot",name:"5.56mm Round",nonPlayable:!1,wg:0,val:0},{formId:"000615A8",editorId:"Ammo5mmRobot",name:"5mm Round",nonPlayable:!1,wg:0,val:1},{formId:"0006B53D",editorId:"Ammo5mm",name:"5mm Round",nonPlayable:!1,wg:0,val:1},{formId:"00029364",editorId:"AmmoAlienPowerCell",name:"Alien Power Cell",nonPlayable:!1,wg:0,val:10},{formId:"0002935B",editorId:"AmmoBB",name:"BB",nonPlayable:!1,wg:0,val:1},{formId:"0002936E",editorId:"AmmoDart",name:"Dart",nonPlayable:!1,wg:0,val:1},{formId:"00047419",editorId:"AmmoBloasflyDart",name:"Dart",nonPlayable:!1,wg:0,val:1},{formId:"000615AF",editorId:"AmmoElectronChargePackRobot",name:"Electron Charge Pack",nonPlayable:!1,wg:0,val:1},{formId:"0006B53E",editorId:"AmmoElectronChargePack",name:"Electron Charge Pack",nonPlayable:!1,wg:0,val:1},{formId:"00020772",editorId:"AmmoSmallEnergyCell",name:"Energy Cell",nonPlayable:!1,wg:0,val:2},{formId:"00078CC2",editorId:"AmmoSmallEnergyCellRobot",name:"Energy Cell",nonPlayable:!1,wg:0,val:0},{formId:"00029371",editorId:"AmmoFlamerFuel",name:"Flamer Fuel",nonPlayable:!1,wg:0,val:1},{formId:"00078CC1",editorId:"AmmoFlamerFuelRobot",name:"Flamer Fuel",nonPlayable:!1,wg:0,val:0},{formId:"0006A80D",editorId:"AmmoMesmetronPowerCell",name:"Mesmetron Power Cell",nonPlayable:!1,wg:0,val:10},{formId:"00004485",editorId:"AmmoMicroFusionCell",name:"Microfusion Cell",nonPlayable:!1,wg:0,val:3},{formId:"00078CC3",editorId:"AmmoMicroFusionCellRobot",name:"Microfusion Cell",nonPlayable:!1,wg:0,val:0},{formId:"00020799",editorId:"ammoFatMan",name:"Mini Nuke",nonPlayable:!1,wg:0,val:250},{formId:"00029383",editorId:"AmmoMissile",name:"Missile",nonPlayable:!1,wg:0,val:50},{formId:"0005F706",editorId:"AmmoCentaurSpit",name:"Missile",nonPlayable:!1,wg:0,val:1},{formId:"00078CC5",editorId:"AmmoMissileRobot",name:"Missile",nonPlayable:!1,wg:0,val:50},{formId:"000B8791",editorId:"AmmoAntSpit",name:"Missile",nonPlayable:!1,wg:0,val:1},{formId:"00029384",editorId:"AmmoRailwaySpikes",name:"Railway Spikes",nonPlayable:!1,wg:0,val:2},{formId:"00028EEA",editorId:"AmmoShotgunShell",name:"Shotgun Shell",nonPlayable:!1,wg:0,val:2},{formId:"0004C5F9",editorId:"AmmoShotgunShellRobot",name:"Shotgun Shell",nonPlayable:!1,wg:0,val:2},{formId:"00056634",editorId:"AmmoMirelurkKing",name:"Sonic Energy",nonPlayable:!1,wg:0,val:10}],P=[{formId:"000CB5F9",editorId:"ArmorUniqueTeslaPower",name:'"Robo-Thor" Armor',nonPlayable:!1,dr:40,wg:45,val:820,cnd:3e3},{formId:"000CB5F8",editorId:"ArmorUniqueTeslaHelmet",name:'"Robo-Thor" Helmet',nonPlayable:!1,dr:8,wg:5,val:120,cnd:125},{formId:"0003307A",editorId:"ArmorRadiationSuitAdvanced",name:"Advanced Radiation Suit",nonPlayable:!1,dr:8,wg:7,val:100,cnd:25},{formId:"000CB605",editorId:"OutfitUniqueEnclaveScientist",name:"All-Purpose Science Suit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000CB5F6",editorId:"ArmorUniqueMetal",name:"Apocalypse Gladiator Armor",nonPlayable:!1,dr:36,wg:30,val:460,cnd:1200},{formId:"000CB5F7",editorId:"ArmorUniqueMetalHelmet",name:"Apocalypse Gladiator Helmet",nonPlayable:!1,dr:5,wg:3,val:70,cnd:75},{formId:"00034121",editorId:"MS03VaultSuit101Armored",name:"Armored Vault 101 Jumpsuit",nonPlayable:!1,dr:12,wg:15,val:180,cnd:100},{formId:"0006C587",editorId:"MountedVaultSuit101Armored",name:"Armored Vault 101 Jumpsuit",nonPlayable:!1,dr:12,wg:15,val:180,cnd:100},{formId:"00061A72",editorId:"ArmorPowerArmy",name:"Army Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"000340FB",editorId:"KIDOutfitWastelandChild04",name:"Athlete of the Wastes Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"00028FFA",editorId:"OutfitWastelandHat04",name:"Ballcap with Glasses",nonPlayable:!1,dr:1,wg:1,val:6,cnd:10},{formId:"00073D57",editorId:"OutfitWastelandHat05",name:"Bandana",nonPlayable:!1,dr:2,wg:1,val:6,cnd:10},{formId:"0009B188",editorId:"OutfitWastelandHat03",name:"Biker Goggles",nonPlayable:!1,dr:1,wg:1,val:6,cnd:10},{formId:"0007CFEF",editorId:"CG00BirthSkirt",name:"BirthSkirt",nonPlayable:!1,dr:0,wg:0,val:0,cnd:100},{formId:"0007494C",editorId:"KIDOutfitWastelandChild05Hat",name:"Blast Off Helmet",nonPlayable:!1,dr:1,wg:1,val:30,cnd:100},{formId:"0005B6EA",editorId:"KIDOutfitWastelandChild05",name:"Blast Off Pajamas",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"0008F775",editorId:"LLFFArmorRaider03Helmet",name:"Boogeyman's Hood",nonPlayable:!1,dr:8,wg:3,val:110,cnd:100},{formId:"00018DE5",editorId:"OutfitWasteland01",name:"Brahmin-Skin Outfit",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"00075201",editorId:"ArmorPowerBrotherhoodOfSteel",name:"Brotherhood Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"00075203",editorId:"ArmorPowerHelmetBrotherhoodOfSteel",name:"Brotherhood Power Helmet",nonPlayable:!1,dr:8,wg:5,val:110,cnd:75},{formId:"000854CF",editorId:"OutfitBoSScribe",name:"Brotherhood Scribe Robe",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"0008A6DD",editorId:"MS15ButtonsWig",name:"Button's Wig",nonPlayable:!1,dr:1,wg:1,val:20,cnd:100},{formId:"0007CFF0",editorId:"CG00SurgicalMask",name:"",nonPlayable:!1,dr:0,wg:1,val:30,cnd:100},{formId:"0007C109",editorId:"ChildBlastoffHelmet",name:"ChildBlastoffHelmet",nonPlayable:!1,dr:0,wg:0,val:0,cnd:25},{formId:"00078646",editorId:"OutfitChineseCommandoHat",name:"Chinese Commando Hat",nonPlayable:!1,dr:1,wg:1,val:6,cnd:15},{formId:"000340D2",editorId:"OutfitChineseCommandoJumpsuit",name:"Chinese Jumpsuit",nonPlayable:!1,dr:6,wg:2,val:10,cnd:100},{formId:"0005157E",editorId:"OutfitColonelAutumn",name:"Colonel Autumn's Uniform",nonPlayable:!1,dr:10,wg:3,val:12,cnd:100},{formId:"00020420",editorId:"ArmorCombat",name:"Combat Armor",nonPlayable:!1,dr:32,wg:25,val:390,cnd:400},{formId:"00020426",editorId:"ArmorCombatHelmet",name:"Combat Helmet",nonPlayable:!1,dr:5,wg:3,val:50,cnd:50},{formId:"000CB544",editorId:"UniqueArmorCommando",name:"Commando Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"000CB5FA",editorId:"ArmorUniqueRecon",name:"Composite Recon Armor",nonPlayable:!1,dr:28,wg:20,val:180,cnd:600},{formId:"000CB5FB",editorId:"ArmorUniqueReconHelmet",name:"Composite Recon Helmet",nonPlayable:!1,dr:4,wg:3,val:40,cnd:70},{formId:"000B17A0",editorId:"HelmetEyebotCaravanSpecial",name:"Crow's Eyebot Helmet",nonPlayable:!1,dr:5,wg:10,val:20,cnd:25},{formId:"00079F09",editorId:"VaultSuitUtilityDad",name:"Dad's Wasteland Outfit",nonPlayable:!1,dr:2,wg:20,val:6,cnd:100},{formId:"000CB543",editorId:"UniqueArmorDefender",name:"Defender Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"000340D3",editorId:"OutfitChineseCommandoJumpsuitOld",name:"Dirty Chinese Jumpsuit",nonPlayable:!1,dr:6,wg:2,val:6,cnd:50},{formId:"000CB603",editorId:"OutfitUniqueChineseCommandoJumpsuitOld",name:"Dirty Chinese Jumpsuit",nonPlayable:!1,dr:6,wg:2,val:6,cnd:50},{formId:"0005C682",editorId:"OutfitPrewarBusinesswearDirty",name:"Dirty Pre-War Businesswear",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000340CF",editorId:"OutfitPrewarCasualwearDirty",name:"Dirty Pre-War Casualwear",nonPlayable:!1,dr:3,wg:2,val:6,cnd:100},{formId:"000340C4",editorId:"KIDOutfitPrewarChildOld",name:"Dirty Pre-War Kid's Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"0005BB70",editorId:"OutfitPrewarSpring2Dirty",name:"Dirty Pre-War Parkstroller Outfit",nonPlayable:!1,dr:3,wg:10,val:5,cnd:100},{formId:"0005BB6F",editorId:"OutfitPrewarCasualwear2Dirty",name:"Dirty Pre-War Relaxedwear",nonPlayable:!1,dr:3,wg:5,val:6,cnd:100},{formId:"000340D1",editorId:"OutfitPrewarSpringDirty",name:"Dirty Pre-War Spring Outfit",nonPlayable:!1,dr:3,wg:2,val:5,cnd:100},{formId:"00066C71",editorId:"FollowersOutfitClover",name:"Dirty Pre-War Spring Outfit",nonPlayable:!1,dr:4,wg:2,val:40,cnd:100},{formId:"0005C9A0",editorId:"GlassesDoctorLi",name:"Doctor Li's Glasses",nonPlayable:!1,dr:1,wg:0,val:6,cnd:100},{formId:"000340DA",editorId:"OutfitDoctorLi",name:"Doctor Li's Outfit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"00087274",editorId:"OutfitElderLyons",name:"Elder Lyons' Robe",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"00078647",editorId:"OutfitEnclaveOfficer01Hat",name:"Enclave Officer Hat",nonPlayable:!1,dr:1,wg:1,val:6,cnd:15},{formId:"000340DE",editorId:"OutfitEnclaveOfficer01",name:"Enclave Officer Uniform",nonPlayable:!1,dr:5,wg:3,val:8,cnd:100},{formId:"00023B62",editorId:"RavenRockCorpseArmorEnclave",name:"Enclave Power Armor",nonPlayable:!1,dr:40,wg:45,val:780,cnd:1200},{formId:"0004443E",editorId:"ArmorEnclave",name:"Enclave Power Armor",nonPlayable:!1,dr:40,wg:45,val:780,cnd:1200},{formId:"0004443F",editorId:"ArmorEnclaveHelmet",name:"Enclave Power Helmet",nonPlayable:!1,dr:9,wg:5,val:110,cnd:75},{formId:"0001B5BD",editorId:"OutfitEnclaveScientist",name:"Enclave Scientist Outfit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000CB5F3",editorId:"ArmorUniqueEnclave",name:"Enclave Shocktrooper Armor",nonPlayable:!1,dr:40,wg:45,val:900,cnd:1500},{formId:"000CB5F4",editorId:"ArmorUniqueEnclaveHelmet",name:"Enclave Shocktrooper Helmet",nonPlayable:!1,dr:7,wg:5,val:150,cnd:125},{formId:"000C09D4",editorId:"MS03EnvironmentSuit",name:"Environment Suit",nonPlayable:!1,dr:6,wg:5,val:100,cnd:25},{formId:"00034126",editorId:"OutfitEulogyJonesHat",name:"Eulogy Jones' Hat",nonPlayable:!1,dr:1,wg:1,val:6,cnd:15},{formId:"00034125",editorId:"OutfitEulogyJones",name:"Eulogy Jones' Suit",nonPlayable:!1,dr:2,wg:3,val:6,cnd:100},{formId:"000CB549",editorId:"ArmorUniqueExplorer",name:"Explorer's Gear",nonPlayable:!1,dr:12,wg:3,val:50,cnd:100},{formId:"0004E6A0",editorId:"HelmetEyebot",name:"Eyebot Helmet",nonPlayable:!1,dr:5,wg:3,val:20,cnd:25},{formId:"000340FD",editorId:"GlassesBlackrimmed",name:"Eyeglasses",nonPlayable:!1,dr:1,wg:0,val:8,cnd:150},{formId:"0001DC1C",editorId:"MS12GhoulMask",name:"Ghoul Mask",nonPlayable:!1,dr:3,wg:1,val:50,cnd:100},{formId:"0005DC82",editorId:"GlassesReadingChild",name:"GlassesReadingChild",nonPlayable:!1,dr:0,wg:0,val:12,cnd:150},{formId:"000B1056",editorId:"OutfitPrewarBusinesswearDirtyDARK",name:"Grimy Pre-War Businesswear",nonPlayable:!1,dr:3,wg:2,val:6,cnd:100},{formId:"000CB5FE",editorId:"ArmorUniqueRaider02",name:"Hand-Me-Down Raider Armor",nonPlayable:!1,dr:15,wg:15,val:180,cnd:100},{formId:"000BF6FD",editorId:"OutfitJumpsuitTLHandyman",name:"Handyman Jumpsuit",nonPlayable:!1,dr:2,wg:1,val:6,cnd:100},{formId:"000CB604",editorId:"OutfitUniqueChineseCommandoHat",name:"Hat of the People",nonPlayable:!1,dr:1,wg:1,val:30,cnd:20},{formId:"00074296",editorId:"HeadWrap01",name:"Head Wrap",nonPlayable:!1,dr:1,wg:0,val:0,cnd:10},{formId:"00074334",editorId:"HeadWrap04",name:"Head Wrap",nonPlayable:!1,dr:1,wg:0,val:0,cnd:10},{formId:"00074335",editorId:"HeadWrap03",name:"Head Wrap",nonPlayable:!1,dr:1,wg:0,val:0,cnd:10},{formId:"00074336",editorId:"HeadWrap02",name:"Head Wrap",nonPlayable:!1,dr:1,wg:0,val:0,cnd:10},{formId:"000CB5FF",editorId:"ArmorUniqueRaider04",name:"Highway Scar Armor",nonPlayable:!1,dr:15,wg:15,val:180,cnd:100},{formId:"00033598",editorId:"HelmetHockeyMask",name:"Hockey Mask",nonPlayable:!1,dr:3,wg:1,val:10,cnd:15},{formId:"000340F9",editorId:"KIDOutfitWastelandChild02",name:"Junior Officer Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"0009B185",editorId:"KIDOutfitWastelandChild04Hat",name:"Kid's Ballcap with Glasses",nonPlayable:!1,dr:1,wg:1,val:30,cnd:100},{formId:"000340C1",editorId:"KIDHatPrewarCapKid",name:"Kid's Baseball Cap",nonPlayable:!1,dr:1,wg:1,val:40,cnd:150},{formId:"000340E4",editorId:"KIDOutfitLittleLamplighter01",name:"Kid's Cave Rat Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"00078643",editorId:"KIDOutfitLittleLamplighter01Hat",name:"Kid's Murray the Mole Hat",nonPlayable:!1,dr:2,wg:1,val:30,cnd:100},{formId:"00028FF8",editorId:"KIDHatPartyChild",name:"Kid's Party Hat",nonPlayable:!1,dr:1,wg:1,val:5,cnd:10},{formId:"000340E1",editorId:"KIDHatPoliceChild",name:"Kid's Police Hat",nonPlayable:!1,dr:1,wg:1,val:40,cnd:150},{formId:"000340D7",editorId:"OutfitProjectPurityDoctor",name:"Lab Technician Outfit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"00020423",editorId:"ArmorLeather",name:"Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"0002DC05",editorId:"ArmorLeatherUnplayable",name:"Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"00066C72",editorId:"FollowersOutfitJericho",name:"Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"00066C74",editorId:"FollowersOutfitCharon",name:"Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"0007401C",editorId:"MSMiniLedouxsMask",name:"Ledoux's Hockey Mask",nonPlayable:!1,dr:4,wg:1,val:100,cnd:25},{formId:"000C24F9",editorId:"MS04LeskosLabCoat",name:"Lesko's Lab Coat",nonPlayable:!1,dr:5,wg:1,val:150,cnd:200},{formId:"0004445B",editorId:"MS06LincolnsHat",name:"Lincoln's Hat",nonPlayable:!1,dr:1,wg:1,val:40,cnd:50},{formId:"00070877",editorId:"MS10LindensOutcastPowerArmor",name:"Linden's Outcast Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"000CB54B",editorId:"UniqueGlassesLuckyShades",name:"Lucky Shades",nonPlayable:!1,dr:1,wg:1,val:40,cnd:150},{formId:"00061A73",editorId:"ArmorPowerLyons",name:"Lyons' Pride Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"0002D11B",editorId:"HelmetMayorMacCready",name:"MacCready's Helmet",nonPlayable:!1,dr:6,wg:1,val:60,cnd:15},{formId:"000C111A",editorId:"Vault106GasMask",name:"Makeshift Gas Mask",nonPlayable:!1,dr:3,wg:2,val:40,cnd:25},{formId:"0005A6CA",editorId:"MS10RewardOutfitOasisDruid",name:"Maple's Garb",nonPlayable:!1,dr:15,wg:2,val:200,cnd:150},{formId:"000340E7",editorId:"KIDOutfitMayorMacCready",name:"Mayor MacCready's Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"00034124",editorId:"OutfitMerc03",name:"Merc Adventurer Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000CB608",editorId:"OutfitUniqueMerc03",name:"Merc Adventurer Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"00034122",editorId:"OutfitMerc01",name:"Merc Charmer Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000CB606",editorId:"OutfitUniqueMerc01",name:"Merc Charmer Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000C5D34",editorId:"OutfitMerc06",name:"Merc Cruiser Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000CB60B",editorId:"OutfitUniqueMerc06",name:"Merc Cruiser Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000A3045",editorId:"OutfitMerc05",name:"Merc Grunt Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000CB60A",editorId:"OutfitUniqueMerc05",name:"Merc Grunt Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"00034123",editorId:"OutfitMerc02",name:"Merc Troublemaker Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"000CB607",editorId:"OutfitUniqueMerc02",name:"Merc Troublemaker Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"0008C83C",editorId:"OutfitMerc04",name:"Merc Veteran Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"0003307F",editorId:"ArmorMetal",name:"Metal Armor",nonPlayable:!1,dr:36,wg:30,val:460,cnd:500},{formId:"00033080",editorId:"ArmorMetalHelmet",name:"Metal Helmet",nonPlayable:!1,dr:5,wg:3,val:70,cnd:50},{formId:"0007C17C",editorId:"MS16VaultSuit101Utility",name:"Modified Utility Jumpsuit",nonPlayable:!1,dr:1,wg:2,val:30,cnd:100},{formId:"0009B186",editorId:"OutfitWastelandHat01",name:"Motorcycle Helmet",nonPlayable:!1,dr:5,wg:1,val:6,cnd:10},{formId:"0006B467",editorId:"OutfitMysteriousStrangerHat",name:"Mysterious Stranger Hat",nonPlayable:!1,dr:2,wg:1,val:30,cnd:100},{formId:"0006696D",editorId:"OutfitMysteriousStranger",name:"Mysterious Stranger Outfit",nonPlayable:!1,dr:5,wg:3,val:40,cnd:100},{formId:"000C8E07",editorId:"MS04AmorousAttire",name:"Naughty Nightwear",nonPlayable:!1,dr:1,wg:1,val:200,cnd:100},{formId:"0009B18A",editorId:"OutfitOasisVillagerHood",name:"Oasis Druid Hood",nonPlayable:!1,dr:2,wg:1,val:6,cnd:10},{formId:"000C942D",editorId:"OutfitOasisExileHood",name:"Oasis Exile Hood",nonPlayable:!1,dr:2,wg:1,val:30,cnd:10},{formId:"000340E8",editorId:"OutfitOasisDruid",name:"Oasis Robe",nonPlayable:!1,dr:4,wg:3,val:30,cnd:100},{formId:"000340E9",editorId:"OutfitOasisVillager",name:"Oasis Villager Robe",nonPlayable:!1,dr:4,wg:2,val:6,cnd:100},{formId:"00060C70",editorId:"ArmorPowerOutcast",name:"Outcast Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"00060C72",editorId:"ArmorPowerHelmetOutcast",name:"Outcast Power Helmet",nonPlayable:!1,dr:8,wg:5,val:110,cnd:75},{formId:"000645EC",editorId:"ArmorReconOutcast",name:"Outcast Recon Armor",nonPlayable:!1,dr:28,wg:20,val:180,cnd:400},{formId:"000645ED",editorId:"ArmorReconHelmetOutcast",name:"Outcast Recon Helmet",nonPlayable:!1,dr:4,wg:3,val:40,cnd:40},{formId:"00050E44",editorId:"HatParty",name:"Party Hat",nonPlayable:!1,dr:1,wg:1,val:5,cnd:10},{formId:"000B75E2",editorId:"HatPartyStanley",name:"Party HatStanley",nonPlayable:!1,dr:0,wg:1,val:5,cnd:10},{formId:"000340FC",editorId:"MQ04SlasherMask",name:"Pint-Sized Slasher Mask",nonPlayable:!1,dr:6,wg:1,val:60,cnd:150},{formId:"00015038",editorId:"PipBoy",name:"Pip-Boy 3000",nonPlayable:!1,dr:0,wg:0,val:0,cnd:1e5},{formId:"000236D8",editorId:"PipBoyNPC",name:"Pip-Boy 3000",nonPlayable:!1,dr:0,wg:0,val:0,cnd:1e5},{formId:"00025B83",editorId:"PipBoyGlove",name:"Pip-Boy Glove",nonPlayable:!1,dr:0,wg:0,val:30,cnd:1e5},{formId:"000AB491",editorId:"HatPoliceAdult",name:"Police Hat",nonPlayable:!1,dr:1,wg:1,val:8,cnd:150},{formId:"0005A6CB",editorId:"MS10RewardOasisVillagerHood",name:"Poplar's Hood",nonPlayable:!1,dr:2,wg:1,val:100,cnd:50},{formId:"00014E13",editorId:"ArmorPower",name:"Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1e3},{formId:"00025083",editorId:"ArmorPowerUnplayable",name:"Power Armor",nonPlayable:!1,dr:40,wg:45,val:510,cnd:1e3},{formId:"00066C73",editorId:"FollowersOutfitCross",name:"Power Armor",nonPlayable:!1,dr:40,wg:45,val:740,cnd:1500},{formId:"00014C08",editorId:"ArmorPowerHelmet",name:"Power Helmet",nonPlayable:!1,dr:8,wg:5,val:110,cnd:75},{formId:"000CB60C",editorId:"OutfitUniquePrewarBusinesswearDirtyDARK",name:"Power-Suit Armor",nonPlayable:!1,dr:3,wg:2,val:12,cnd:100},{formId:"00028FF9",editorId:"HatPrewarBaseballCap",name:"Pre-War Baseball Cap",nonPlayable:!1,dr:1,wg:1,val:8,cnd:15},{formId:"000340CD",editorId:"HatPrewarBonnet",name:"Pre-War Bonnet",nonPlayable:!1,dr:1,wg:1,val:8,cnd:15},{formId:"0001EA6D",editorId:"OutfitPrewarCasualwear",name:"Pre-War Casualwear",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000CB60D",editorId:"OutfitUniquePrewarCasualwear",name:"Pre-War Casualwear",nonPlayable:!1,dr:3,wg:2,val:12,cnd:100},{formId:"000340C8",editorId:"HatPrewarHat",name:"Pre-War Hat",nonPlayable:!1,dr:1,wg:1,val:8,cnd:15},{formId:"000340C3",editorId:"KIDOutfitPrewarChild",name:"Pre-War Kid's Outfit",nonPlayable:!1,dr:1,wg:2,val:30,cnd:100},{formId:"0008198C",editorId:"KIDOutfitPrewarChildandWatch",name:"Pre-War Outfit and Watch",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"000ABBE2",editorId:"MQ04PlayerOutfit",name:"Pre-War Outfit and Watch",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"0005BB66",editorId:"OutfitPrewarSpring2",name:"Pre-War Parkstroller Outfit",nonPlayable:!1,dr:3,wg:2,val:6,cnd:100},{formId:"000CB60F",editorId:"OutfitUniquePrewarSpring2",name:"Pre-War Parkstroller Outfit",nonPlayable:!1,dr:3,wg:2,val:10,cnd:100},{formId:"0005BB63",editorId:"OutfitPrewarCasualwear2",name:"Pre-War Relaxedwear",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000340D0",editorId:"OutfitPrewarSpring",name:"Pre-War Spring Outfit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"0007836E",editorId:"MS14PowerArmorMorphine",name:"Prototype Medic Power Armor",nonPlayable:!1,dr:40,wg:45,val:1e3,cnd:1e3},{formId:"000CB600",editorId:"ArmorUniqueRaider04Helmet",name:"Pyro Helmet",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"00033078",editorId:"ArmorRadiationSuit",name:"Radiation Suit",nonPlayable:!1,dr:6,wg:5,val:60,cnd:15},{formId:"000340F8",editorId:"KIDOutfitWastelandChild01",name:"Ragamuffin Outfit",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"00074950",editorId:"KIDOutfitWastelandChild01Hat",name:"Ragamuffin Tophat",nonPlayable:!1,dr:1,wg:1,val:30,cnd:100},{formId:"00078644",editorId:"ArmorRaider02Helmet",name:"Raider Arclight Helmet",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"0003307D",editorId:"ArmorRaider03",name:"Raider Badlands Armor",nonPlayable:!1,dr:16,wg:15,val:180,cnd:100},{formId:"0003307E",editorId:"ArmorRaider04",name:"Raider Blastmaster Armor",nonPlayable:!1,dr:16,wg:15,val:180,cnd:100},{formId:"0005B6E8",editorId:"ArmorRaider04Helmet",name:"Raider Blastmaster Helmet",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"0002042F",editorId:"ArmorRaider01",name:"Raider Painspike Armor",nonPlayable:!1,dr:16,wg:15,val:180,cnd:100},{formId:"00020432",editorId:"ArmorRaider01Helmet",name:"Raider Psycho-Tic Helmet",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"0003307C",editorId:"ArmorRaider02",name:"Raider Sadist Armor",nonPlayable:!1,dr:16,wg:15,val:180,cnd:100},{formId:"00078645",editorId:"ArmorRaider03Helmet",name:"Raider Wastehound Helmet",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"00023030",editorId:"MS18RangerBattlearmor",name:"Ranger Battle Armor",nonPlayable:!1,dr:39,wg:27,val:430,cnd:1100},{formId:"00034105",editorId:"MS18RangerHelmet",name:"Ranger Battle Helmet",nonPlayable:!1,dr:6,wg:5,val:60,cnd:50},{formId:"0001C296",editorId:"GlassesReading",name:"Reading Glasses",nonPlayable:!1,dr:1,wg:0,val:12,cnd:150},{formId:"00028EAD",editorId:"ArmorReconHelmet",name:"Recon Armor Helmet",nonPlayable:!1,dr:4,wg:3,val:40,cnd:40},{formId:"0003064D",editorId:"ArmorRecon",name:"Recon Armor",nonPlayable:!1,dr:28,wg:20,val:180,cnd:400},{formId:"0003411B",editorId:"OutfitJumpsuitRedRacer",name:"Red Racer Jumpsuit",nonPlayable:!1,dr:2,wg:1,val:6,cnd:100},{formId:"000340EB",editorId:"MS01OutfitRedHat",name:"Red's Bandana",nonPlayable:!1,dr:2,wg:1,val:30,cnd:10},{formId:"000340EA",editorId:"MS01OutfitRed",name:"Red's Jumpsuit",nonPlayable:!1,dr:3,wg:1,val:40,cnd:100},{formId:"0003E54A",editorId:"RegulatorDuster",name:"Regulator Duster",nonPlayable:!1,dr:10,wg:3,val:70,cnd:150},{formId:"000239CB",editorId:"ArmorRivetCitySecurityHelmet",name:"Rivet City Security Helmet",nonPlayable:!1,dr:4,wg:3,val:50,cnd:25},{formId:"000239CC",editorId:"ArmorRivetCitySecurity",name:"Rivet City Security Uniform",nonPlayable:!1,dr:24,wg:20,val:330,cnd:100},{formId:"000CB5F5",editorId:"ArmorUniqueLeather",name:"Road Rascal Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"0003411A",editorId:"OutfitJumpsuitRobco",name:"RobCo Jumpsuit",nonPlayable:!1,dr:2,wg:1,val:6,cnd:100},{formId:"00078648",editorId:"OutfitWastelandMerchantHat",name:"Roving Trader Hat",nonPlayable:!1,dr:1,wg:1,val:6,cnd:10},{formId:"0002B385",editorId:"OutfitWastelandMerchant01",name:"Roving Trader Outfit",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"000340D9",editorId:"OutfitRivetCityScientist",name:"Scientist Outfit",nonPlayable:!1,dr:3,wg:2,val:8,cnd:100},{formId:"000340E6",editorId:"OutfitPrewarNegligee",name:"Sexy Sleepwear",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"0007C17D",editorId:"MS03StealthHat",name:"Shady Hat",nonPlayable:!1,dr:1,wg:1,val:40,cnd:50},{formId:"000CB5FC",editorId:"ArmorUniqueRaider01",name:"Sharp-Dressed Raider's Armor",nonPlayable:!1,dr:15,wg:15,val:180,cnd:100},{formId:"000CB5EF",editorId:"ArmorUniqueCombat",name:"Shellshocked Combat Armor",nonPlayable:!1,dr:32,wg:25,val:390,cnd:400},{formId:"000CB5F0",editorId:"ArmorUniqueCombatHelmet",name:"Shellshocked Combat Helmet",nonPlayable:!1,dr:5,wg:3,val:50,cnd:50},{formId:"00020429",editorId:"OutfitLucasSimms",name:"Sheriff's Duster",nonPlayable:!1,dr:5,wg:3,val:35,cnd:150},{formId:"0002DD80",editorId:"OutfitLucasSimmsHat",name:"Sheriff's Hat",nonPlayable:!1,dr:1,wg:1,val:35,cnd:40},{formId:"0002F563",editorId:"SlaveCollar",name:"Slave Collar",nonPlayable:!1,dr:3,wg:5,val:50,cnd:150},{formId:"0003D1FE",editorId:"MS13Collar",name:"Slave Collar",nonPlayable:!1,dr:4,wg:5,val:100,cnd:400},{formId:"000CB60E",editorId:"OutfitUniquePrewarNegligee",name:"Sleepwear",nonPlayable:!1,dr:1,wg:1,val:10,cnd:100},{formId:"0009B189",editorId:"OutfitWastelandHat02",name:"Stormchaser Hat",nonPlayable:!1,dr:1,wg:1,val:6,cnd:10},{formId:"0005C99F",editorId:"GlassesShades",name:"Sunglasses",nonPlayable:!1,dr:1,wg:0,val:8,cnd:150},{formId:"0003E591",editorId:"MS03SurgicalMask",name:"Surgical Mask",nonPlayable:!1,dr:1,wg:1,val:6,cnd:10},{formId:"000A6F77",editorId:"ArmorPowerT51b",name:"T-51b Power Armor",nonPlayable:!1,dr:50,wg:40,val:1e3,cnd:2e3},{formId:"000A6F78",editorId:"ArmorPowerT51bHelmet",name:"T-51b Power Helmet",nonPlayable:!1,dr:10,wg:4,val:120,cnd:100},{formId:"000C72FB",editorId:"HatTakomaBaseballCap",name:"Takoma Park Little Leaguer Cap",nonPlayable:!1,dr:1,wg:1,val:60,cnd:15},{formId:"000A6F76",editorId:"ArmorCombatTalon",name:"Talon Combat Armor",nonPlayable:!1,dr:28,wg:25,val:275,cnd:300},{formId:"000CB5F2",editorId:"ArmorUniqueCombatTalon",name:"Talon Combat Armor",nonPlayable:!1,dr:32,wg:25,val:390,cnd:1e3},{formId:"000B0278",editorId:"ArmorCombatHelmetTalon",name:"Talon Combat Helmet",nonPlayable:!1,dr:4,wg:3,val:60,cnd:40},{formId:"000CB5F1",editorId:"ArmorUniqueCombatHelmetTalon",name:"Talon Combat Helmet",nonPlayable:!1,dr:5,wg:3,val:60,cnd:50},{formId:"0005B6EB",editorId:"ArmorTenpennyHelmet",name:"Tenpenny Security Helmet",nonPlayable:!1,dr:4,wg:1,val:50,cnd:25},{formId:"00034119",editorId:"ArmorTenpennySecurity",name:"Tenpenny Security Uniform",nonPlayable:!1,dr:24,wg:20,val:180,cnd:100},{formId:"00096CB7",editorId:"OutfitTenpenny",name:"Tenpenny's Suit",nonPlayable:!1,dr:2,wg:2,val:8,cnd:100},{formId:"0006B464",editorId:"ArmorTeslaPower",name:"Tesla Armor",nonPlayable:!1,dr:43,wg:45,val:820,cnd:1500},{formId:"0008F571",editorId:"ArmorTeslaPowerFX",name:"Tesla Armor",nonPlayable:!1,dr:40,wg:45,val:820,cnd:1500},{formId:"0006B465",editorId:"ArmorTeslaHelmet",name:"Tesla Helmet",nonPlayable:!1,dr:9,wg:5,val:120,cnd:100},{formId:"0003411D",editorId:"MS02SuitAntagonizer",name:"The AntAgonizer's Costume",nonPlayable:!1,dr:20,wg:15,val:120,cnd:100},{formId:"0003411F",editorId:"MS02SuitHelmetAntagonizer",name:"The AntAgonizer's Helmet",nonPlayable:!1,dr:6,wg:5,val:60,cnd:50},{formId:"000CB5FD",editorId:"ArmorUniqueRaider01Helmet",name:"The Devil's Pigtails",nonPlayable:!1,dr:3,wg:3,val:20,cnd:15},{formId:"0003411E",editorId:"MS02SuitMechanist",name:"The Mechanist's Costume",nonPlayable:!1,dr:20,wg:15,val:30,cnd:100},{formId:"00034120",editorId:"MS02SuitHelmetMechanist",name:"The Mechanist's Helmet",nonPlayable:!1,dr:6,wg:5,val:60,cnd:50},{formId:"000C71E1",editorId:"RedRacerLabCoat",name:"The Surgeon's Lab Coat",nonPlayable:!1,dr:2,wg:1,val:30,cnd:100},{formId:"000ACDA4",editorId:"GlassesThreeDog",name:"Three Dog's Glasses",nonPlayable:!1,dr:1,wg:0,val:12,cnd:150},{formId:"00073FEC",editorId:"MQ02ThreeDogsHeadwrap",name:"Three Dog's Head Wrap",nonPlayable:!1,dr:2,wg:0,val:200,cnd:15},{formId:"0001C295",editorId:"GlassesReadingClr",name:"Tinted Reading Glasses",nonPlayable:!1,dr:1,wg:0,val:12,cnd:150},{formId:"000C7C4E",editorId:"ArmorTorcherMask",name:"Torcher's Mask",nonPlayable:!1,dr:2,wg:3,val:20,cnd:15},{formId:"0005C9A1",editorId:"GlassesTortiseshell",name:"Tortiseshell Glasses",nonPlayable:!1,dr:1,wg:0,val:8,cnd:150},{formId:"0002042E",editorId:"OutfitTunnelSnake01",name:"Tunnel Snake Outfit",nonPlayable:!1,dr:4,wg:2,val:8,cnd:100},{formId:"00061D98",editorId:"FollwerOutfitButch",name:"Tunnel Snake Outfit",nonPlayable:!1,dr:4,wg:3,val:40,cnd:100},{formId:"00089B52",editorId:"Underwear",name:"Underwear",nonPlayable:!1,dr:0,wg:1,val:2,cnd:100},{formId:"00083C5C",editorId:"MS09VancesOutfit",name:"Vance's Longcoat Outfit",nonPlayable:!1,dr:10,wg:4,val:100,cnd:100},{formId:"000340F2",editorId:"KIDVaultSuitChild101",name:"Vault 101 Child's Jumpsuit",nonPlayable:!1,dr:1,wg:2,val:5,cnd:100},{formId:"0000431E",editorId:"VaultSuit101",name:"Vault 101 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:8,cnd:100},{formId:"0001CBDD",editorId:"ArmorVault101Security",name:"Vault 101 Security Armor",nonPlayable:!1,dr:12,wg:15,val:70,cnd:100},{formId:"0003411C",editorId:"ArmorVault101SecurityHelmet",name:"Vault 101 Security Helmet",nonPlayable:!1,dr:3,wg:3,val:30,cnd:25},{formId:"000425BA",editorId:"VaultSuit101Utility",name:"Vault 101 Utility Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:10,cnd:100},{formId:"000B73F2",editorId:"VaultSuit106",name:"Vault 106 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"000B73F1",editorId:"VaultSuit108",name:"Vault 108 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"000340EF",editorId:"VaultSuit112",name:"Vault 112 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"000CAFBE",editorId:"VaultSuit77",name:"Vault 77 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"000340ED",editorId:"VaultSuit87",name:"Vault 87 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"000B73F3",editorId:"VaultSuit92",name:"Vault 92 Jumpsuit",nonPlayable:!1,dr:1,wg:1,val:6,cnd:100},{formId:"0001CBDC",editorId:"VaultLabCoat",name:"Vault Lab Uniform",nonPlayable:!1,dr:2,wg:1,val:6,cnd:100},{formId:"000C7C54",editorId:"ArmorWanderersLeather",name:"Wanderer's Leather Armor",nonPlayable:!1,dr:24,wg:15,val:160,cnd:150},{formId:"000340FE",editorId:"OutfitWastelandDoctor01",name:"Wasteland Doctor Fatigues",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"000CB609",editorId:"OutfitUniqueMerc04",name:"Wasteland Legend Outfit",nonPlayable:!1,dr:12,wg:8,val:50,cnd:100},{formId:"00074952",editorId:"KIDOutfitWastelandChild03Hat",name:"Wasteland Scout Hat",nonPlayable:!1,dr:1,wg:1,val:30,cnd:100},{formId:"000340FA",editorId:"KIDOutfitWastelandChild03",name:"Wasteland Scout Uniform",nonPlayable:!1,dr:2,wg:2,val:30,cnd:100},{formId:"0001CBDB",editorId:"OutfitWasteland03",name:"Wasteland Settler Outfit",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"000340FF",editorId:"OutfitWastelandDoctor02",name:"Wasteland Surgeon Outfit",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"0001BA00",editorId:"OutfitWasteland02",name:"Wasteland Wanderer Outfit",nonPlayable:!1,dr:2,wg:2,val:6,cnd:100},{formId:"000CB545",editorId:"ArmorUniqueWastelander",name:"Wastelander's Gear",nonPlayable:!1,dr:12,wg:2,val:50,cnd:100}],M=[{formId:"0002B41B",editorId:"pool10ball",name:"10 Ball",nonPlayable:!1,wg:1,val:2},{formId:"0002B41D",editorId:"pool13ball",name:"13 Ball",nonPlayable:!1,wg:1,val:2},{formId:"0002B415",editorId:"pool2ball",name:"2 Ball",nonPlayable:!1,wg:1,val:2},{formId:"0002B417",editorId:"pool5ball",name:"5 Ball",nonPlayable:!1,wg:1,val:2},{formId:"0002B419",editorId:"pool8ball",name:"8 Ball",nonPlayable:!1,wg:1,val:2},{formId:"00022106",editorId:"AbraxoCleaner",name:"Abraxo Cleaner",nonPlayable:!1,wg:1,val:5},{formId:"00045258",editorId:"MS06ActionAbe",name:"Action Abe Action Figure",nonPlayable:!1,wg:1,val:5},{formId:"000C8503",editorId:"MS08AndroidComponent",name:"Android Component",nonPlayable:!1,wg:0,val:0},{formId:"0006AA59",editorId:"MS02AntResin",name:"Ant Resin",nonPlayable:!1,wg:1,val:3},{formId:"00045252",editorId:"MS06Pennies",name:"Antique Lincoln Coin Collection",nonPlayable:!1,wg:1,val:5},{formId:"000BF20F",editorId:"MS15PrizeVoucher",name:"Archives Prize Voucher",nonPlayable:!1,wg:1,val:0},{formId:"00034057",editorId:"Ashtray",name:"Ashtray",nonPlayable:!1,wg:1,val:1},{formId:"0002B410",editorId:"BaseballGlove",name:"Baseball Glove",nonPlayable:!1,wg:1,val:4},{formId:"0002B40B",editorId:"Baseball01",name:"Baseball",nonPlayable:!1,wg:1,val:2},{formId:"0002B40E",editorId:"Basketball",name:"Basketball",nonPlayable:!1,wg:1,val:1},{formId:"0005B6CA",editorId:"TinCan02",name:"Bent Tin Can",nonPlayable:!1,wg:1,val:1},{formId:"0005B640",editorId:"SpoonBig01",name:"Big Spoon",nonPlayable:!1,wg:1,val:1},{formId:"00003A82",editorId:"MS15BillofRightsRolled",name:"Bill of Rights",nonPlayable:!1,wg:1,val:0},{formId:"000504DA",editorId:"MS10TestTubeFull",name:"Birch's Sap",nonPlayable:!1,wg:1,val:0},{formId:"00028706",editorId:"PassCardBlue",name:"Blue Pass Card",nonPlayable:!1,wg:0,val:1},{formId:"000388E5",editorId:"BobbleheadAGL",name:"Bobblehead - Agility",nonPlayable:!1,wg:0,val:0},{formId:"000388F3",editorId:"BobbleheadBART",name:"Bobblehead - Barter",nonPlayable:!1,wg:0,val:0},{formId:"00038906",editorId:"BobbleheadBGUN",name:"Bobblehead - Big Guns",nonPlayable:!1,wg:0,val:0},{formId:"00038850",editorId:"BobbleheadCHA",name:"Bobblehead - Charisma",nonPlayable:!1,wg:0,val:0},{formId:"00038834",editorId:"BobbleheadEND",name:"Bobblehead - Endurance",nonPlayable:!1,wg:0,val:0},{formId:"0003892F",editorId:"BobbleheadERGW",name:"Bobblehead - Energy Weapons",nonPlayable:!1,wg:0,val:0},{formId:"00038930",editorId:"BobbleheadEXPL",name:"Bobblehead - Explosives",nonPlayable:!1,wg:0,val:0},{formId:"0003885C",editorId:"BobbleheadINT",name:"Bobblehead - Intelligence",nonPlayable:!1,wg:0,val:0},{formId:"00038931",editorId:"BobbleheadLOCK",name:"Bobblehead - Lockpick",nonPlayable:!1,wg:0,val:0},{formId:"000388E6",editorId:"BobbleheadLUK",name:"Bobblehead - Luck",nonPlayable:!1,wg:0,val:0},{formId:"00038950",editorId:"BobbleheadMEDI",name:"Bobblehead - Medicine",nonPlayable:!1,wg:0,val:0},{formId:"00038951",editorId:"BobbleheadMELE",name:"Bobblehead - Melee Weapons",nonPlayable:!1,wg:0,val:0},{formId:"00038833",editorId:"BobbleheadPER",name:"Bobblehead - Perception",nonPlayable:!1,wg:0,val:0},{formId:"00038952",editorId:"BobbleheadREPR",name:"Bobblehead - Repair",nonPlayable:!1,wg:0,val:0},{formId:"00038953",editorId:"BobbleheadSCNC",name:"Bobblehead - Science",nonPlayable:!1,wg:0,val:0},{formId:"00038954",editorId:"BobbleheadSGUN",name:"Bobblehead - Small Guns",nonPlayable:!1,wg:0,val:0},{formId:"00038955",editorId:"BobbleheadSNEK",name:"Bobblehead - Sneak",nonPlayable:!1,wg:0,val:0},{formId:"00038956",editorId:"BobbleheadSPCH",name:"Bobblehead - Speech",nonPlayable:!1,wg:0,val:0},{formId:"00038832",editorId:"BobbleheadSTR",name:"Bobblehead - Strength",nonPlayable:!1,wg:0,val:0},{formId:"00038958",editorId:"BobbleheadUARM",name:"Bobblehead - Unarmed",nonPlayable:!1,wg:0,val:0},{formId:"0000000A",editorId:"Lockpick",name:"Bobby Pin",nonPlayable:!1,wg:0,val:1},{formId:"000250A3",editorId:"SurgicalBonesaw01",name:"Bonesaw",nonPlayable:!1,wg:2,val:5},{formId:"0000000F",editorId:"Caps001",name:"Bottle Cap",nonPlayable:!1,wg:0,val:1},{formId:"0003406F",editorId:"BoxDetergent",name:"Box of Detergent",nonPlayable:!1,wg:1,val:1},{formId:"0003405E",editorId:"SkullBrahmin",name:"Brahmin Skull",nonPlayable:!1,wg:2,val:1},{formId:"0001EDC5",editorId:"FFDCBrotherhoodDogtag",name:"Brotherhood of Steel Holotag",nonPlayable:!1,wg:0,val:1},{formId:"0005B639",editorId:"Knife01",name:"Butter Knife",nonPlayable:!1,wg:1,val:1},{formId:"0005B63A",editorId:"Knife02",name:"Butter Knife",nonPlayable:!1,wg:1,val:1},{formId:"00034062",editorId:"Camera",name:"Camera",nonPlayable:!1,wg:1,val:5},{formId:"0006CA2F",editorId:"MS03LibraryCatalogueHolotape",name:"Card Catalog Holotape",nonPlayable:!1,wg:0,val:0},{formId:"00034068",editorId:"CigaretteCarton",name:"Carton of Cigarettes",nonPlayable:!1,wg:2,val:50},{formId:"000340A0",editorId:"PlateDinnerCeramic",name:"Ceramic Dinner Plate",nonPlayable:!1,wg:1,val:1},{formId:"00048467",editorId:"CG01Rattle",name:"",nonPlayable:!1,wg:1,val:1},{formId:"0003A17D",editorId:"CG01TeddyBear01",name:"",nonPlayable:!1,wg:1,val:1},{formId:"0003FCCE",editorId:"CG01ToyBlock",name:"",nonPlayable:!1,wg:1,val:1},{formId:"00063BF5",editorId:"CG01ToyCar",name:"",nonPlayable:!1,wg:1,val:1},{formId:"000291D7",editorId:"MQ04Chandelier",name:"Chandelier",nonPlayable:!1,wg:14,val:2},{formId:"0003713C",editorId:"FollowersCharonContract",name:"Charon's Employment Contract",nonPlayable:!1,wg:0,val:1},{formId:"00022108",editorId:"CherryBomb",name:"Cherry Bomb",nonPlayable:!1,wg:0,val:5},{formId:"0009A809",editorId:"Chessboard",name:"Chessboard",nonPlayable:!1,wg:1,val:1},{formId:"0005B52C",editorId:"Cigarette01",name:"Cigarette",nonPlayable:!1,wg:0,val:1},{formId:"0004525A",editorId:"MS06DraftPoster",name:"Civil War Draft Poster",nonPlayable:!1,wg:1,val:5},{formId:"00025238",editorId:"Clipboard02",name:"Clipboard",nonPlayable:!1,wg:1,val:1},{formId:"0003406C",editorId:"CoffeeMug01",name:"Coffee Mug",nonPlayable:!1,wg:1,val:1},{formId:"00025421",editorId:"CoffeeKettle",name:"Coffee Pot",nonPlayable:!1,wg:1,val:1},{formId:"0005B5A9",editorId:"MS15SecurityModule",name:"Computer Password Module",nonPlayable:!1,wg:0,val:0},{formId:"00022102",editorId:"Conductor",name:"Conductor",nonPlayable:!1,wg:5,val:30},{formId:"0008C214",editorId:"CapPresConstitutionRolled",name:"Constitution of the United States",nonPlayable:!1,wg:1,val:1},{formId:"0006C55A",editorId:"RRControlCollar",name:"Control Collar",nonPlayable:!1,wg:5,val:1},{formId:"000151DB",editorId:"BrassLanternPasswordAdder",name:"Crumpled Note",nonPlayable:!1,wg:1,val:1},{formId:"0001B01F",editorId:"Crutch",name:"Crutch",nonPlayable:!1,wg:2,val:5},{formId:"0002B41F",editorId:"poolcueball",name:"Cue Ball",nonPlayable:!1,wg:1,val:3},{formId:"0003407B",editorId:"DrinkingGlass01",name:"Cup",nonPlayable:!1,wg:1,val:1},{formId:"0003406E",editorId:"BoardCutting",name:"Cutting Board",nonPlayable:!1,wg:1,val:1},{formId:"0005B635",editorId:"GardenGnomeDestroyed01",name:"Damaged Garden Gnome",nonPlayable:!1,wg:4,val:1},{formId:"000C9403",editorId:"JournalGeneric",name:"Danielle's Book",nonPlayable:!1,wg:1,val:1},{formId:"0002210B",editorId:"DeathclawHand",name:"Deathclaw Hand",nonPlayable:!1,wg:1,val:25},{formId:"00003A7F",editorId:"MS15DeclarationRolled",name:"Declaration of Independence",nonPlayable:!1,wg:1,val:0},{formId:"0005B59F",editorId:"DinnerPlate01",name:"Dinner Plate",nonPlayable:!1,wg:1,val:1},{formId:"00034070",editorId:"BowlDog",name:"Dog Bowl",nonPlayable:!1,wg:1,val:1},{formId:"00070CD4",editorId:"MS18DonovansWrench",name:"Donovan's Wrench",nonPlayable:!1,wg:0,val:75},{formId:"000A8745",editorId:"AWMFFDoorComponent",name:"Door Component",nonPlayable:!1,wg:1,val:1},{formId:"0005B633",editorId:"DrinkingGlass02",name:"Drinking Glass",nonPlayable:!1,wg:1,val:1},{formId:"000604DD",editorId:"Ear",name:"Ear",nonPlayable:!1,wg:0,val:1},{formId:"00025237",editorId:"Clipboard03",name:"Earnings Clipboard",nonPlayable:!1,wg:1,val:1},{formId:"0008C215",editorId:"CapPresEmancRolled",name:"Emancipation Proclamation",nonPlayable:!1,wg:1,val:1},{formId:"00022103",editorId:"NukaColaBottle",name:"Empty Nuka-Cola Bottle",nonPlayable:!1,wg:1,val:2},{formId:"000504D7",editorId:"MS10TestTubeEmpty",name:"Empty Sap Container",nonPlayable:!1,wg:1,val:0},{formId:"0009AA4E",editorId:"SodaBottleEmpty01",name:"Empty Soda Bottle",nonPlayable:!1,wg:1,val:1},{formId:"000250A8",editorId:"SurgicalSyringe01",name:"Empty Syringe",nonPlayable:!1,wg:1,val:5},{formId:"0005B6CE",editorId:"WhiskeyBottle01Empty01",name:"Empty Whisky Bottle",nonPlayable:!1,wg:1,val:1},{formId:"000347DE",editorId:"FFEC09OfficerID",name:"Experimental Rho ID",nonPlayable:!1,wg:0,val:1},{formId:"000BAFBC",editorId:"FactoryID",name:"Factory Employee ID",nonPlayable:!1,wg:0,val:1},{formId:"00025236",editorId:"Clipboard04",name:"Finance Clipboard",nonPlayable:!1,wg:1,val:1},{formId:"000604DE",editorId:"Finger",name:"Finger",nonPlayable:!1,wg:0,val:1},{formId:"00022101",editorId:"FirehoseNozzle",name:"Firehose Nozzle",nonPlayable:!1,wg:1,val:5},{formId:"00033BC6",editorId:"FissionBattery",name:"Fission Battery",nonPlayable:!1,wg:10,val:75},{formId:"00074EE1",editorId:"Flour",name:"Flour",nonPlayable:!1,wg:1,val:2},{formId:"0002D3A5",editorId:"MS03Sanitizer",name:"Food Sanitizer",nonPlayable:!1,wg:7,val:150},{formId:"000250A7",editorId:"SurgicalForceps01",name:"Forceps",nonPlayable:!1,wg:1,val:5},{formId:"0006B192",editorId:"MS15DeclarationRolledForged",name:"Forged Declaration",nonPlayable:!1,wg:1,val:0},{formId:"00034078",editorId:"Fork01",name:"Fork",nonPlayable:!1,wg:.5,val:1},{formId:"0001A168",editorId:"MQ05Fuse",name:"Fuse",nonPlayable:!1,wg:0,val:0},{formId:"00014F81",editorId:"FusionPulseCharge",name:"Fusion Pulse Charge",nonPlayable:!1,wg:0,val:1},{formId:"0003D34D",editorId:"MQ08GECK",name:"G.E.C.K.",nonPlayable:!1,wg:5,val:0},{formId:"0003407A",editorId:"GnomeGarden",name:"Garden Gnome",nonPlayable:!1,wg:5,val:1},{formId:"00040D4D",editorId:"MS18FinGeomapper",name:"Geomapper Module",nonPlayable:!1,wg:1,val:20},{formId:"0008C216",editorId:"CapPresGettysburgRolled",name:"Gettysburg Address",nonPlayable:!1,wg:1,val:1},{formId:"0005B636",editorId:"GlassPitcher01",name:"Glass Pitcher",nonPlayable:!1,wg:1,val:1},{formId:"0005B63F",editorId:"Plate03",name:"Green Plate",nonPlayable:!1,wg:1,val:1},{formId:"0005B637",editorId:"Hammer01",name:"Hammer",nonPlayable:!1,wg:2,val:3},{formId:"0005B638",editorId:"Harmonica01",name:"Harmonica",nonPlayable:!1,wg:1,val:2},{formId:"0005FAE6",editorId:"MS08Note",name:"Holotape",nonPlayable:!1,wg:0,val:0},{formId:"0005516B",editorId:"HotPlate",name:"Hot Plate",nonPlayable:!1,wg:2,val:5},{formId:"0007C121",editorId:"HD00ExplorerTheme",name:"House: Explorer Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C125",editorId:"HD00Jukebox",name:"House: Jukebox",nonPlayable:!1,wg:0,val:500},{formId:"000C7AF0",editorId:"HD00LoveTheme",name:"House: Love Machine Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C128",editorId:"HD00Infirmary",name:"House: My First Infirmary",nonPlayable:!1,wg:0,val:1200},{formId:"0007C127",editorId:"HD00Lab",name:"House: My First Laboratory",nonPlayable:!1,wg:0,val:1200},{formId:"0007C126",editorId:"HD00NukaCola",name:"House: Nuka-Cola Machine",nonPlayable:!1,wg:0,val:500},{formId:"0007C123",editorId:"HD00PreWarTheme",name:"House: Pre-War Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C124",editorId:"HD00RaiderTheme",name:"House: Raider Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C120",editorId:"HD00ScienceTheme",name:"House: Scientist Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C122",editorId:"HD00BoSTheme",name:"House: Vault Theme",nonPlayable:!1,wg:0,val:1e3},{formId:"0007C11D",editorId:"HD00Workbench",name:"House: Workbench",nonPlayable:!1,wg:0,val:500},{formId:"00003AA2",editorId:"MS15Ink",name:"Ink Container",nonPlayable:!1,wg:0,val:0},{formId:"0005B634",editorId:"GardenGnome01",name:"Intact Garden Gnome",nonPlayable:!1,wg:5,val:1},{formId:"00034088",editorId:"Iron",name:"Iron",nonPlayable:!1,wg:5,val:2},{formId:"00045256",editorId:"MS06AssassinationPoster",name:"John Wilkes Booth Wanted Poster",nonPlayable:!1,wg:1,val:5},{formId:"000CAFA2",editorId:"JundersPlunkettFinger",name:"Junders Plunkett's Finger",nonPlayable:!1,wg:0,val:1},{formId:"000270F0",editorId:"MQ04Undies",name:"Lacy Underwear",nonPlayable:!1,wg:0,val:3},{formId:"000A9E6C",editorId:"BurnedBook05",name:"Large Burned Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E6F",editorId:"BurnedBook08",name:"Large Destroyed Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E6D",editorId:"BurnedBook06",name:"Large Ruined Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E6E",editorId:"BurnedBook07",name:"Large Scorched Book",nonPlayable:!1,wg:1,val:1},{formId:"0005B6CD",editorId:"WhiskeyBottle02",name:"Large Whiskey Bottle",nonPlayable:!1,wg:2,val:5},{formId:"0003E56A",editorId:"MS10Liniment",name:"Laurel's Liniment",nonPlayable:!1,wg:1,val:0},{formId:"00025E03",editorId:"LawnmowerBlade",name:"Lawn Mower Blade",nonPlayable:!1,wg:2,val:10},{formId:"00022100",editorId:"LeafBlower",name:"Leaf Blower",nonPlayable:!1,wg:2,val:15},{formId:"0002210C",editorId:"LeatherBelt",name:"Leather Belt",nonPlayable:!1,wg:1,val:5},{formId:"00028EE9",editorId:"MS06Poster",name:"Lincoln Memorial Poster",nonPlayable:!1,wg:1,val:0},{formId:"00045254",editorId:"MS06LincolnDiary",name:"Lincoln's Diary",nonPlayable:!1,wg:1,val:5},{formId:"00028EE6",editorId:"MS06Recording",name:"Lincoln's Voice",nonPlayable:!1,wg:2,val:5},{formId:"0002EDFB",editorId:"MS01Lucky8ball",name:"Lucky 8 Ball",nonPlayable:!1,wg:1,val:4},{formId:"0001890A",editorId:"MS09SealedEnvelope",name:"Lucy's Sealed Envelope",nonPlayable:!1,wg:0,val:0},{formId:"00022107",editorId:"Lunchbox",name:"Lunchbox",nonPlayable:!1,wg:1,val:3},{formId:"00003A80",editorId:"MS15MagnaCartaRolled",name:"Magna Carta",nonPlayable:!1,wg:1,val:0},{formId:"0006CA30",editorId:"MS03LibraryArchivesHolotape",name:"Media Archives Holotape",nonPlayable:!1,wg:0,val:0},{formId:"0002210D",editorId:"MedicalBrace",name:"Medical Brace",nonPlayable:!1,wg:2,val:10},{formId:"0003A73A",editorId:"MedicalBraceNew",name:"Medical Brace",nonPlayable:!1,wg:2,val:1},{formId:"00025235",editorId:"Clipboard01",name:"Medical Clipboard",nonPlayable:!1,wg:1,val:1},{formId:"0003409C",editorId:"PanCookingMetal",name:"Metal Cooking Pan",nonPlayable:!1,wg:1,val:5},{formId:"000340A7",editorId:"PotCookingMetal",name:"Metal Cooking Pot",nonPlayable:!1,wg:1,val:1},{formId:"000340BC",editorId:"Spoon01",name:"Metal Spoon",nonPlayable:!1,wg:.5,val:1},{formId:"0002920F",editorId:"MetroTicket",name:"Metro Ticket",nonPlayable:!1,wg:0,val:1},{formId:"000391B1",editorId:"MilitaryID",name:"Military ID",nonPlayable:!1,wg:0,val:1},{formId:"000296C0",editorId:"MQ04Brochure",name:"Military School Brochure",nonPlayable:!1,wg:0,val:0},{formId:"0005B63B",editorId:"Milkbottle01",name:"Milk Bottle",nonPlayable:!1,wg:1,val:1},{formId:"0003BD33",editorId:"MQ09FEVVial",name:"Modified FEV Virus",nonPlayable:!1,wg:1,val:0},{formId:"0008C217",editorId:"CapPresMonroeRolled",name:"Monroe Doctrine",nonPlayable:!1,wg:1,val:1},{formId:"000220FB",editorId:"MotorcycleGasTank",name:"Motorcycle Gas Tank",nonPlayable:!1,wg:5,val:25},{formId:"000220FE",editorId:"MotorcycleHandbrake",name:"Motorcycle Handbrake",nonPlayable:!1,wg:1,val:15},{formId:"00022419",editorId:"MS15MuseumToken",name:"Museum Token",nonPlayable:!1,wg:0,val:1},{formId:"0006EEE7",editorId:"BodyPart01",name:"Mutilated Arm",nonPlayable:!1,wg:2,val:0},{formId:"0006F2D8",editorId:"BodyPart02",name:"Mutilated Leg",nonPlayable:!1,wg:2,val:0},{formId:"0006F2D9",editorId:"BodyPart03",name:"Mutilated Organs",nonPlayable:!1,wg:2,val:0},{formId:"00074170",editorId:"BodyPart05",name:"Mutilated Skull",nonPlayable:!1,wg:2,val:0},{formId:"0006F2DA",editorId:"BodyPart04",name:"Mutilated Torso",nonPlayable:!1,wg:2,val:0},{formId:"000CADE6",editorId:"MS05NukaColaDisk",name:"Nuka-Cola Clear Formula",nonPlayable:!1,wg:1,val:150},{formId:"00029171",editorId:"NukaTruck",name:"Nuka-Cola Truck",nonPlayable:!1,wg:2,val:5},{formId:"00030663",editorId:"MS03Observer",name:"Observer",nonPlayable:!1,wg:1,val:0},{formId:"0003997E",editorId:"OfficeID",name:"Office Employee ID",nonPlayable:!1,wg:0,val:1},{formId:"0005F183",editorId:"Opthalmoscope",name:"Opthalmoscope",nonPlayable:!1,wg:1,val:4},{formId:"00034069",editorId:"CigarettePack",name:"Pack of Cigarettes",nonPlayable:!1,wg:.5,val:10},{formId:"0002210E",editorId:"PaintGun",name:"Paint Gun",nonPlayable:!1,wg:5,val:15},{formId:"0003409D",editorId:"Paperweight",name:"Paperweight",nonPlayable:!1,wg:1,val:1},{formId:"0005B63C",editorId:"Pencil01",name:"Pencil",nonPlayable:!1,wg:0,val:1},{formId:"000220FC",editorId:"PilotLight",name:"Pilot Light",nonPlayable:!1,wg:1,val:14},{formId:"000340A4",editorId:"Plunger",name:"Plunger",nonPlayable:!1,wg:1,val:1},{formId:"0002B412",editorId:"PoolBall",name:"Pool Ball",nonPlayable:!1,wg:1,val:2},{formId:"0002541B",editorId:"BigPot",name:"Pot",nonPlayable:!1,wg:2,val:0},{formId:"00022113",editorId:"PressureCooker",name:"Pressure Cooker",nonPlayable:!1,wg:5,val:15},{formId:"000943F2",editorId:"PreWarBook",name:"Pre-War Book",nonPlayable:!1,wg:1,val:5},{formId:"000C5D24",editorId:"BookGeneric01",name:"Pre-War Book",nonPlayable:!1,wg:1,val:1},{formId:"00034067",editorId:"PrewarMoney",name:"Pre-war Money",nonPlayable:!1,wg:0,val:10},{formId:"0002210F",editorId:"RadscorpionPoisonGland",name:"Radscorpion Poison Gland",nonPlayable:!1,wg:1,val:30},{formId:"000340AD",editorId:"Rake",name:"Rake",nonPlayable:!1,wg:2,val:1},{formId:"00028704",editorId:"PassCardRed",name:"Red Pass Card",nonPlayable:!1,wg:0,val:1},{formId:"0005B63E",editorId:"Plate02",name:"Red Plate",nonPlayable:!1,wg:1,val:1},{formId:"0002D3B3",editorId:"MS03HistoryHolotape",name:"Rivet City Historical Record",nonPlayable:!1,wg:1,val:0},{formId:"0002D3B4",editorId:"MS03TelemetryUnit",name:"RobCo Processor Widget",nonPlayable:!1,wg:1,val:0},{formId:"000285F8",editorId:"MQ04RollerSkate",name:"Rollerskate",nonPlayable:!1,wg:1,val:4},{formId:"000250A5",editorId:"SurgicalScalpel01",name:"Scalpel",nonPlayable:!1,wg:1,val:5},{formId:"000BAFFB",editorId:"SchematicsBottlecapMineItem",name:"Schematics - Bottlecap Mine",nonPlayable:!1,wg:0,val:300},{formId:"000BAFFA",editorId:"SchematicsDartGunItem",name:"Schematics - Dart Gun",nonPlayable:!1,wg:0,val:500},{formId:"000BAFFC",editorId:"SchematicsDeathclawGauntletItem",name:"Schematics - Deathclaw Gauntlet",nonPlayable:!1,wg:0,val:800},{formId:"000BAFFD",editorId:"SchematicsNukaCocktailItem",name:"Schematics - Nuka-Grenade",nonPlayable:!1,wg:0,val:300},{formId:"000BAFFE",editorId:"SchematicsRailwayRifleItem",name:"Schematics - Railway Rifle",nonPlayable:!1,wg:0,val:800},{formId:"000BAFFF",editorId:"SchematicsRockItLauncherItem",name:"Schematics - Rock-It Launcher",nonPlayable:!1,wg:0,val:800},{formId:"000BB000",editorId:"SchematicsShishkebabItem",name:"Schematics - Shishkebab",nonPlayable:!1,wg:0,val:500},{formId:"000250A4",editorId:"SurgicalScissors01",name:"Scissors",nonPlayable:!1,wg:1,val:3},{formId:"00031944",editorId:"SpareParts",name:"Scrap Metal",nonPlayable:!1,wg:1,val:1},{formId:"00022109",editorId:"SensorModule",name:"Sensor Module",nonPlayable:!1,wg:2,val:30},{formId:"0006835F",editorId:"MS17FinSheetMusicBook",name:"Sheet Music Book",nonPlayable:!1,wg:1,val:100},{formId:"000340B5",editorId:"ShotGlass01",name:"Shot glass",nonPlayable:!1,wg:1,val:1},{formId:"00022FF0",editorId:"MS13CollarMiscObj",name:"Slave Collar",nonPlayable:!1,wg:1,val:0},{formId:"000A9E70",editorId:"BurnedBook01",name:"Small Burned Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E6B",editorId:"BurnedBook04",name:"Small Destroyed Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E69",editorId:"BurnedBook02",name:"Small Ruined Book",nonPlayable:!1,wg:1,val:1},{formId:"000A9E6A",editorId:"BurnedBook03",name:"Small Scorched Book",nonPlayable:!1,wg:1,val:1},{formId:"000033FF",editorId:"MS17SoilStrad",name:"Soil Stradivarius",nonPlayable:!1,wg:3,val:0},{formId:"000340BB",editorId:"Spatula01",name:"Spatula",nonPlayable:!1,wg:1,val:1},{formId:"0005B641",editorId:"Spork01",name:"Spork",nonPlayable:!1,wg:.5,val:1},{formId:"00022112",editorId:"SteamGaugeAssembly",name:"Steam Gauge Assembly",nonPlayable:!1,wg:10,val:25},{formId:"00022111",editorId:"SurgicalTubing",name:"Surgical Tubing",nonPlayable:!1,wg:1,val:10},{formId:"0001F21F",editorId:"TeddyBear01",name:"Teddy Bear",nonPlayable:!1,wg:1,val:3},{formId:"00022104",editorId:"TinCan01",name:"Tin Can",nonPlayable:!1,wg:1,val:1},{formId:"0002541C",editorId:"Plate04",name:"Tin Plate",nonPlayable:!1,wg:1,val:1},{formId:"0009A807",editorId:"ToasterPostwar",name:"Toaster",nonPlayable:!1,wg:3,val:5},{formId:"0009A808",editorId:"ToasterPrewar",name:"Toaster",nonPlayable:!1,wg:3,val:5},{formId:"00022110",editorId:"ToyCar",name:"Toy Car",nonPlayable:!1,wg:1,val:5},{formId:"0002C5F6",editorId:"poolTriangle",name:"Triangle",nonPlayable:!1,wg:1,val:1},{formId:"00022105",editorId:"Turpentine",name:"Turpentine",nonPlayable:!1,wg:2,val:10},{formId:"000250A6",editorId:"SurgicalTweasers01",name:"Tweezers",nonPlayable:!1,wg:1,val:3},{formId:"0008C219",editorId:"CapPresDecWarChinaRolled",name:"U.S. Declaration of War on China",nonPlayable:!1,wg:1,val:1},{formId:"0008C218",editorId:"CapPresDecWarGermanyRolled",name:"U.S. Declaration of War on Germany",nonPlayable:!1,wg:1,val:1},{formId:"00039B5F",editorId:"UtilityID",name:"Utility Worker ID",nonPlayable:!1,wg:0,val:1},{formId:"000220FF",editorId:"VacuumCleaner",name:"Vacuum Cleaner",nonPlayable:!1,wg:10,val:20},{formId:"0001CFAF",editorId:"MS09VancesProposal",name:"Vance's Proposal",nonPlayable:!1,wg:0,val:0},{formId:"0002393C",editorId:"MQ02VirgoIIDish",name:"Virgo II Dish",nonPlayable:!1,wg:1,val:0},{formId:"0005A795",editorId:"xMS03survivalGuideBookItem",name:"Wasteland Survival Guide",nonPlayable:!1,wg:2,val:1},{formId:"0005B6CB",editorId:"WhetStone01",name:"Whet Stone",nonPlayable:!1,wg:2,val:1},{formId:"0005B63D",editorId:"Plate01",name:"White Plate",nonPlayable:!1,wg:1,val:1},{formId:"0002210A",editorId:"WonderGlue",name:"Wonderglue",nonPlayable:!1,wg:1,val:10},{formId:"0007CBCC",editorId:"WoodChipper",name:"Wood Chipper",nonPlayable:!1,wg:50,val:25},{formId:"0005B6D0",editorId:"Wrench01",name:"Wrench",nonPlayable:!1,wg:1,val:1},{formId:"0005A6CE",editorId:"MS10RewardBearCharm",name:"Yew's Bear Charm",nonPlayable:!1,wg:1,val:50}],A=[{formId:"00031DBA",editorId:"ActionBoy",name:"Action Boy",description:"With the Action Boy perk, you gain an additional 25 Action Points to use in V.A.T.S.",maxRanks:1,nonPlayable:!1},{formId:"0007B202",editorId:"ActionGirl",name:"Action Girl",description:"With the Action Girl perk, you gain an additional 25 Action Points to use in V.A.T.S.",maxRanks:1,nonPlayable:!1},{formId:"00094EC4",editorId:"AdamantiumSkeleton",name:"Adamantium Skeleton",description:"With the Adamantium Skeleton perk, your limbs only receive 50% of the damage they normally would.",maxRanks:1,nonPlayable:!1},{formId:"00031DB5",editorId:"AnimalFriend",name:"Animal Friend",description:"At the first rank of this perk, animals simply won't attack. At the second rank, they will actually come to your aid in combat, but never against another animal. This perk affects the Dog, Yao Guai, Mole Rat, and Brahmin. ",maxRanks:2,nonPlayable:!1},{formId:"000C1A6B",editorId:"MS04StrengthPerk",name:"Ant Might",description:"Your body has been genetically enhanced with the strength and flame resistance of the Grayditch Fire Ants! Your Strength has increased by 1 and you are now 25% resistant to fire.",maxRanks:1,nonPlayable:!1},{formId:"000C1A6C",editorId:"MS04PerceptionPerk",name:"Ant Sight",description:"Your body has been genetically enhanced with the perception and flame resistance of the Grayditch Fire Ants! Your Perception has increased by 1 and you are now 25% resistant to fire.",maxRanks:1,nonPlayable:!1},{formId:"00035E04",editorId:"MS10Barkskin",name:"Barkskin",description:"You've been exposed to Harold's mutation and your skin is now as hard as tree bark. As a result, you've gained a permanent +5% to Damage Resistance.",maxRanks:1,nonPlayable:!1},{formId:"00031DBB",editorId:"BetterCriticals",name:"Better Criticals",description:"With the Better Criticals perk, you gain a 50% damage bonus every time a critical hit is scored on an opponent.",maxRanks:1,nonPlayable:!1},{formId:"00094EB8",editorId:"BlackWidow",name:"Black Widow",description:"In combat, you do +10% damage against male opponents. Outside of combat, you'll sometimes have access to unique dialogue options when dealing with the opposite sex. ",maxRanks:1,nonPlayable:!1},{formId:"00094EBA",editorId:"BloodyMess",name:"Bloody Mess",description:"With the Bloody Mess perk, characters and creatures you kill will often explode into a red, gut-ridden, eyeball-strewn paste. Fun! Oh, and you'll do 5% extra damage with all weapons.",maxRanks:1,nonPlayable:!1},{formId:"00094EBC",editorId:"Cannibal",name:"Cannibal",description:"With the Cannibal perk, when you're in Sneak mode, you gain the option to eat a corpse to regain Health. But every time you feed, you lose Karma, and if the act is witnessed, it is considered a crime against nature.",maxRanks:1,nonPlayable:!1},{formId:"00099827",editorId:"ChemResistant",name:"Chem Resistant",description:"Having the Chem Resistant perk means you're 50% less likely to develop an addiction to chems, like Psycho or Jet.",maxRanks:1,nonPlayable:!1},{formId:"0009982D",editorId:"Chemist",name:"Chemist",description:"With the Chemist perk, any chems you take last twice as long.",maxRanks:1,nonPlayable:!1},{formId:"00003142",editorId:"ChildAtHeart",name:"Child at Heart",description:"The Child at Heart perk greatly improves your interactions with children, usually in the form of unique dialogue choices.",maxRanks:1,nonPlayable:!1},{formId:"00099828",editorId:"Commando",name:"Commando",description:"While using a rifle (or similar two-handed weapon), your accuracy in V.A.T.S. is significantly increased.",maxRanks:1,nonPlayable:!1},{formId:"00031DE1",editorId:"Comprehension",name:"Comprehension",description:"With the Comprehension perk, you gain one additional skill point whenever a skill book is read.",maxRanks:1,nonPlayable:!1},{formId:"00031DC4",editorId:"ComputerWhiz",name:"Computer Whiz",description:"Fail a hack attempt and get locked out of a computer? Not if you're a Computer Whiz! With this perk, you can attempt to re-hack any computer you were previously locked out of.",maxRanks:1,nonPlayable:!1},{formId:"00044CAF",editorId:"ConcentratedFire",name:"Concentrated Fire",description:"With Concentrated Fire, your accuracy to hit any body part in V.A.T.S. increases slightly with each subsequent hit on that body part.",maxRanks:1,nonPlayable:!1},{formId:"00044CA8",editorId:"ContractKiller",name:"Contract Killer",description:"Once you have the Contract Killer perk, any good character you kill will have an ear on their corpse. This ear can then be sold to a certain person (whose identity is disclosed when you take the perk) for caps and negative Karma. ",maxRanks:1,nonPlayable:!1},{formId:"00044CAB",editorId:"Cyborg",name:"Cyborg",description:"You've made permanent enhancements to your body! The Cyborg perk instantly adds +10% to your Damage, Poison, and Radiation Resistances, and 10 points to the Energy Weapons skill.",maxRanks:1,nonPlayable:!1},{formId:"00044948",editorId:"DaddysBoy",name:"Daddy's Boy",description:"Just like dear old Dad, you've devoted your time to intellectual pursuits. You gain an additional 5 points to both the Science and Medicine skills.",maxRanks:3,nonPlayable:!1},{formId:"00069310",editorId:"DaddysGirl",name:"Daddy's Girl",description:"Just like dear old Dad, you've devoted your time to intellectual pursuits. You gain an additional 5 points to both the Science and Medicine skills.",maxRanks:3,nonPlayable:!1},{formId:"00031DAB",editorId:"DemolitionExpert",name:"Demolition Expert",description:"With each rank of this perk, all of your explosive weapons do an additional 20% damage. ",maxRanks:3,nonPlayable:!1},{formId:"00030FEB",editorId:"MS03DreamCrusherPerk",name:"Dream Crusher",description:"Something about your presence dampens others' desires to exceed. Any enemy's chance of getting critical hits on you is reduced by 50%. ",maxRanks:1,nonPlayable:!1},{formId:"00031DD8",editorId:"Educated",name:"Educated",description:"With the Educated perk, you gain three more skill points every time you advance in level. This perk is best taken early on, to maximize its effectiveness.",maxRanks:1,nonPlayable:!1},{formId:"00031DD9",editorId:"Entomologist",name:"Entomologist",description:"With the Entomologist perk, you do an additional +50% damage every time you attack a mutated insect, like the Radroach, Giant Ant, or Radscorpion.",maxRanks:1,nonPlayable:!1},{formId:"00031DE5",editorId:"Explorer",name:"Explorer",description:"When you choose the Explorer perk, every location in the world is revealed on your map. So get out there and explore!",maxRanks:1,nonPlayable:!1},{formId:"00094EBF",editorId:"FastMetabolism",name:"Fast Metabolism",description:"With the Fast Metabolism perk, you gain a 20% Health bonus when using Stimpaks.",maxRanks:1,nonPlayable:!1},{formId:"00094EC1",editorId:"Finesse",name:"Finesse",description:"With the Finesse perk, you have a higher chance to score a critical hit on an opponent in combat, equivalent to 5 extra points of Luck.",maxRanks:1,nonPlayable:!1},{formId:"00031DE3",editorId:"FortuneFinder",name:"Fortune Finder",description:"With the Fortune Finder perk, you'll find considerably more Nuka-Cola caps in containers than you normally would. ",maxRanks:1,nonPlayable:!1},{formId:"00099834",editorId:"GrimReaperSprint",name:"Grim Reaper's Sprint",description:"If you kill a target in V.A.T.S., all your Action Points are restored upon exiting V.A.T.S.",maxRanks:1,nonPlayable:!1},{formId:"0004494E",editorId:"GunNut",name:"Gun Nut",description:"You're obsessed with using and maintaining a wide variety of conventional firearms. With each rank of the Gun Nut perk, you gain an additional 5 points to the Small Guns and Repair skills.",maxRanks:3,nonPlayable:!1},{formId:"00094EBB",editorId:"Gunslinger",name:"Gunslinger",description:"While using a pistol (or similar one-handed weapon), your accuracy in V.A.T.S. is significantly increased.",maxRanks:1,nonPlayable:!1},{formId:"00003131",editorId:"MS09Hematophage",name:"Hematophage",description:"This perk allows you to regain health by consuming Bloodpacks.",maxRanks:1,nonPlayable:!1},{formId:"00031DAC",editorId:"HereandNow",name:"Here and Now",description:"The Here and Now perk immediately grants an additional experience level, complete with all the advantages that brings.",maxRanks:1,nonPlayable:!1},{formId:"00044CAD",editorId:"ImpartialMediation",name:"Impartial Mediation",description:"With the Impartial Mediation perk, you gain an extra 30 points to Speech... so long as you maintain a Neutral Karma level.",maxRanks:1,nonPlayable:!1},{formId:"00044CB0",editorId:"Infiltrator",name:"Infiltrator",description:'With Infiltrator, if a lock is broken, and can\'t normally be picked again, you can attempt to pick it again one more time. This includes locks previously broken by a "Force Lock" attempt.',maxRanks:1,nonPlayable:!1},{formId:"00044CB1",editorId:"IntenseTraining",name:"Intense Training",description:"With the Intense Training perk, you can put a single point into any of your S.P.E.C.I.A.L. attributes.",maxRanks:10,nonPlayable:!1},{formId:"00031DDB",editorId:"IronFist",name:"Iron Fist",description:"With the Iron Fist perk, you do an additional 5 points of Unarmed damage per rank.",maxRanks:3,nonPlayable:!1},{formId:"0002D3A2",editorId:"MS03Perk1A",name:"Junior Survivor",description:"You've been tested in some of the most dangerous parts of the wastes, and you're still alive to tell the tale. You've gained +2% bonus to Poison Resistance and Radiation Resistance, and +5 points to maximum Health.",maxRanks:1,nonPlayable:!1},{formId:"000331D4",editorId:"MS03Perk1B",name:"Junior Survivor",description:"You've been tested in some of the most dangerous parts of the wastes, and you're still alive to tell the tale. You've gained +2% bonus to Poison Resistance and Radiation Resistance, and 2 points to both the Medicine and Science skills.",maxRanks:1,nonPlayable:!1},{formId:"000331D5",editorId:"MS03Perk1C",name:"Junior Survivor",description:"You've been tested in some of the most dangerous parts of the wastes, and you're still alive to tell the tale. You've gained +2% bonus to Poison Resistance, Radiation Resistance and Damage Resistance.",maxRanks:1,nonPlayable:!1},{formId:"000331D6",editorId:"MS03Perk1D",name:"Junior Survivor",description:"You've been tested in some of the most dangerous parts of the wastes, and you're still alive to tell the tale. You've gained +2% bonus to Poison Resistance & Radiation Resistance, and 2 points to both the Speech and Sneak skills.",maxRanks:1,nonPlayable:!1},{formId:"000331D7",editorId:"MS03Perk1E",name:"Junior Survivor",description:"You've been tested in some of the most dangerous parts of the wastes, and you're still alive to tell the tale. You've gained +2% bonus to Poison Resistance and Radiation Resistance, and a +1% bonus to Critical Chance.",maxRanks:1,nonPlayable:!1},{formId:"00094EB9",editorId:"LadyKiller",name:"Lady Killer",description:"In combat, you do +10% damage against female opponents. Outside of combat, you'll sometimes have access to unique dialogue options when dealing with the opposite sex. ",maxRanks:1,nonPlayable:!1},{formId:"00044CAC",editorId:"Lawbringer",name:"Lawbringer",description:"Once you have the Lawbringer perk, any evil character you kill will have a finger on their corpse. This finger can then be sold to a certain person (whose identity is disclosed when you take the perk) for caps and positive Karma. ",maxRanks:1,nonPlayable:!1},{formId:"00044CA9",editorId:"LeadBelly",name:"Lead Belly",description:"With the Lead Belly perk, you take 50% less radiation every time you drink from an irradiated water source.",maxRanks:1,nonPlayable:!1},{formId:"00031DB1",editorId:"LifeGiver",name:"Life Giver",description:"With the Life Giver perk, you gain an additional 30 Hit Points.",maxRanks:1,nonPlayable:!1},{formId:"00031DB7",editorId:"LightStep",name:"Light Step",description:"With the Light Step perk, you'll never set off an enemy's mines or floor-based traps.",maxRanks:1,nonPlayable:!1},{formId:"00014B97",editorId:"LittleLeaguer",name:"Little Leaguer",description:"Years as the Vault little league MVP have honed your hitting and throwing. With every rank, you gain 5 points of Melee Weapons skill and 5 points of Explosives skill.",maxRanks:3,nonPlayable:!1},{formId:"00031DB8",editorId:"MasterTrader",name:"Master Trader",description:"When you take the Master Trader perk, the price of every item you buy from a vendor is reduced by 25%.",maxRanks:1,nonPlayable:!1},{formId:"00031DAD",editorId:"MisterSandman",name:"Mister Sandman",description:"With the Mister Sandman perk, when you're in Sneak mode, you gain the option to silently kill any human or Ghoul while they're sleeping. And, all Mister Sandman kills earn bonus XP.",maxRanks:1,nonPlayable:!1},{formId:"00031DBC",editorId:"MysteriousStranger",name:"Mysterious Stranger",description:"You've gained your own personal guardian angel... armed with a fully loaded .44 Magnum. With this perk, the Mysterious Stranger will appear occasionally in V.A.T.S. mode to lend a hand, with deadly efficiency.",maxRanks:1,nonPlayable:!1},{formId:"00044CA7",editorId:"NerdRage",name:"Nerd Rage!",description:"You've been pushed around long enough! With the Nerd Rage! perk, your Strength is raised to 10 and you gain 50% to damage resistance whenever your Health drops to 20% or below.",maxRanks:1,nonPlayable:!1},{formId:"00094EBD",editorId:"NightPerson",name:"Night Person",description:'When the sun is down, a Night Person gains +2 to both Intelligence and Perception (up to a maximum of 10). This perk directly affects your "internal clock," and remains active both inside and outside.',maxRanks:1,nonPlayable:!1},{formId:"00031DCC",editorId:"Ninja",name:"Ninja",description:"The Ninja perk grants you the power of the fabled shadow warriors. When attacking with either Melee or Unarmed, you gain a +15% critical chance on every strike. Sneak attack criticals do 25% more damage than normal.",maxRanks:1,nonPlayable:!1},{formId:"00044CAA",editorId:"ParalyzingPalm",name:"Paralyzing Palm",description:"With Paralyzing Palm, you will sometimes perform a special V.A.T.S. palm strike that paralyzes your opponent for 30 seconds. Note that in order to perform the Paralyzing Palm, you must be completely unarmed.",maxRanks:1,nonPlayable:!1},{formId:"00058FDF",editorId:"PowerArmorTraining",name:"Power Armor Training",description:"You have received the specialized training needed to move in any form of Power Armor.",maxRanks:1,nonPlayable:!1},{formId:"0006835C",editorId:"PsychoPerk",name:"",description:"",maxRanks:1,nonPlayable:!1},{formId:"00031DB2",editorId:"Pyromaniac",name:"Pyromaniac",description:"With the Pyromaniac perk, you do +50% damage with fire-based weapons, like the Flamer and Shishkebab.",maxRanks:1,nonPlayable:!1},{formId:"0003066B",editorId:"MS03MutationPerk",name:"Rad Regeneration",description:"After an experimental treatment, intense radiation keeps your body operating at peak performance regardless of crippling injuries... right up until death. When you suffer from Advanced Radiation Poisoning, crippled limbs automatically regenerate.",maxRanks:1,nonPlayable:!1},{formId:"00031DA9",editorId:"RadResistance",name:"Rad Resistance",description:"Rad Resistance allows you to -- what else? -- resist radiation. This perk grants an additional 25% to Radiation Resistance.",maxRanks:1,nonPlayable:!1},{formId:"00031DC2",editorId:"RoboticsExpert",name:"Robotics Expert",description:"With the Robotics perk, you do an additional 25% damage to any robot. But, even better, sneaking up on a hostile robot undetected and activating it will put that robot into a permanent shutdown state.",maxRanks:1,nonPlayable:!1},{formId:"00044CA6",editorId:"Scoundrel",name:"Scoundrel",description:"Take the Scoundrel perk, and you can use your wily charms to influence people -- each rank raises your Speech and Barter skills by 5 points.",maxRanks:3,nonPlayable:!1},{formId:"00031DAA",editorId:"Scrounger",name:"Scrounger",description:"With the Scrounger perk, you'll find considerably more ammunition in containers than you normally would. ",maxRanks:1,nonPlayable:!1},{formId:"00031DB3",editorId:"SilentRunning",name:"Silent Running",description:"With the Silent Running perk, you gain an additional 10 points to Sneak, and running no longer factors into a successful sneak attempt.",maxRanks:1,nonPlayable:!1},{formId:"0009982E",editorId:"SizeMatters",name:"Size Matters",description:"You're obsessed with really big weapons. With each rank of this perk, you gain an additional 15 points to the Big Guns skill.",maxRanks:3,nonPlayable:!1},{formId:"00031DB4",editorId:"Sniper",name:"Sniper",description:"With the Sniper perk, your chance to hit an opponent's head in V.A.T.S. is significantly increased.",maxRanks:1,nonPlayable:!1},{formId:"00031DC5",editorId:"SolarPowered",name:"Solar Powered",description:"With the Solar Powered perk, you gain an additional 2 points to Strength when in direct sunlight, and slowly regenerate lost Health.",maxRanks:1,nonPlayable:!1},{formId:"00031DDE",editorId:"StrongBack",name:"Strong Back",description:"With the Strong Back perk, you can carry 50 more pounds of equipment.",maxRanks:1,nonPlayable:!1},{formId:"0002D3A1",editorId:"MS03Perk2A",name:"Survival Expert",description:"You've been tested in some of the most dangerous parts of the wastes, and you've not only survived - you've learned a few things. You've gained +4% bonus to Poison Resistance and Radiation Resistance, and +10 points to maximum Health.",maxRanks:1,nonPlayable:!1},{formId:"000331D8",editorId:"MS03Perk2B",name:"Survival Expert",description:"You've been tested in some of the most dangerous parts of the wastes, and you've not only survived - you've learned a few things. You've gained +4% bonus to Poison Resistance and Radiation Resistance, and 4 points to both the Medicine and Science skills.",maxRanks:1,nonPlayable:!1},{formId:"000331D9",editorId:"MS03Perk2C",name:"Survival Expert",description:"You've been tested in some of the most dangerous parts of the wastes, and you've not only survived - you've learned a few things. You've gained +4% bonus to Poison Resistance, Radiation Resistance and Damage Resistance.",maxRanks:1,nonPlayable:!1},{formId:"000331DA",editorId:"MS03Perk2D",name:"Survival Expert",description:"You've been tested in some of the most dangerous parts of the wastes, and you've not only survived - you've learned a few things. You've gained +4% bonus to Poison Resistance & Radiation Resistance, and 4 points to both the Speech and Sneak skills.",maxRanks:1,nonPlayable:!1},{formId:"000331DB",editorId:"MS03Perk2E",name:"Survival Expert",description:"You've been tested in some of the most dangerous parts of the wastes, and you've not only survived - you've learned a few things. You've gained +4% bonus to Poison Resistance and Radiation Resistance, and a +2% bonus to Critical Chance.",maxRanks:1,nonPlayable:!1},{formId:"0002D3A0",editorId:"MS03Perk3A",name:"Survival Guru",description:"You wrote the book on how to survive in the Wasteland, and have shared your secrets with humanity. You've gained +6% bonus to Poison Resistance and Radiation Resistance, and +15 points to maximum Health.",maxRanks:1,nonPlayable:!1},{formId:"000331DC",editorId:"MS03Perk3B",name:"Survival Guru",description:"You wrote the book on how to survive in the Wasteland, and have shared your secrets with humanity. You've gained +6% bonus to Poison Resistance and Radiation Resistance, and 6 points to both the Medicine and Science skills.",maxRanks:1,nonPlayable:!1},{formId:"000331DD",editorId:"MS03Perk3C",name:"Survival Guru",description:"You wrote the book on how to survive in the Wasteland, and have shared your secrets with humanity. You've gained +6% bonus to Poison Resistance, Radiation Resistance and Damage Resistance.",maxRanks:1,nonPlayable:!1},{formId:"000331DE",editorId:"MS03Perk3D",name:"Survival Guru",description:"You wrote the book on how to survive in the Wasteland, and have shared your secrets with humanity. You've gained +6% bonus to Poison Resistance & Radiation Resistance, and 6 points to both the Speech and Sneak skills.",maxRanks:1,nonPlayable:!1},{formId:"000331DF",editorId:"MS03Perk3E",name:"Survival Guru",description:"You wrote the book on how to survive in the Wasteland, and have shared your secrets with humanity. You've gained +6% bonus to Poison Resistance & Radiation Resistance, and +3% bonus to Critical Chance.",maxRanks:1,nonPlayable:!1},{formId:"00031DD3",editorId:"SwiftLearner",name:"Swift Learner",description:"With each rank in the Swift Learner perk, you gain an additional 10% to total Experience Points whenever Experience Points are earned.",maxRanks:3,nonPlayable:!1},{formId:"00031DBD",editorId:"Tag",name:"Tag!",description:"The Tag! perk allows you to select a fourth Skill to be a Tag skill, which instantly raises it by 15 points.",maxRanks:1,nonPlayable:!1},{formId:"00031DD6",editorId:"Thief",name:"Thief",description:"With each rank of the Thief perk, you gain an immediate bonus of 5 points to both the Sneak and Lockpick skills.",maxRanks:3,nonPlayable:!1},{formId:"00031DE0",editorId:"Toughness",name:"Toughness",description:"With the Toughness perk, you gain +10% to overall Damage Resistance, up to the maximum of 85%. ",maxRanks:1,nonPlayable:!1},{formId:"00061822",editorId:"WellRestedPerk",name:"Well Rested",description:"After sleeping in a safe bed, you will wake well rested. You earn 10% more experience points for several hours.",maxRanks:1,nonPlayable:!1},{formId:"00024D5C",editorId:"MS08RewardPerk",name:"Wired Reflexes",description:"Advanced technology from the Commonwealth has increased your reaction speed, giving you a higher chance to hit in V.A.T.S.",maxRanks:1,nonPlayable:!1},{formId:"000770CC",editorId:"YaoGuaiMeatPerk",name:"",description:"",maxRanks:1,nonPlayable:!1}].filter(e=>e.name&&e.description).map((e,t)=>({id:t+1,name:e.name,description:e.description,value:0})),R=[{id:1,name:"Barter",description:"Improves buying and selling prices.",value:0},{id:2,name:"Big Guns",description:"Accuracy and damage with heavy weapons.",value:0},{id:3,name:"Energy Weapons",description:"Accuracy and damage with energy weapons.",value:0},{id:4,name:"Explosives",description:"Damage with explosives and ability to disarm traps.",value:0},{id:5,name:"Lockpick",description:"Ability to pick locks.",value:0},{id:6,name:"Medicine",description:"Effectiveness of Stimpaks and healing.",value:0},{id:7,name:"Melee Weapons",description:"Damage with melee weapons.",value:0},{id:8,name:"Repair",description:"Ability to maintain and repair items.",value:0},{id:9,name:"Science",description:"Ability to hack terminals and use tech.",value:0},{id:10,name:"Small Guns",description:"Accuracy and damage with small firearms.",value:0},{id:11,name:"Sneak",description:"Ability to remain undetected.",value:0},{id:12,name:"Speech",description:"Effectiveness in dialogue and persuasion.",value:0},{id:13,name:"Unarmed",description:"Damage with fists and unarmed weapons.",value:0}],D=[{key:"Agility",short:"AGI",description:"Affects your Action Points and your ability to sneak and avoid detection."},{key:"Charisma",short:"CHA",description:"Affects your speech skills and how people react to you in conversation."},{key:"Endurance",short:"END",description:"Affects your total Health and resistance to physical punishment over time."},{key:"Intelligence",short:"INT",description:"Affects how many skill points you gain when leveling up."},{key:"Luck",short:"LCK",description:"Affects many things in small ways, and helps you succeed at random chances."},{key:"Perception",short:"PER",description:"Affects your ability to notice things and your accuracy in VATS."},{key:"Strength",short:"STR",description:"Affects how much you can carry and the damage you do with melee attacks."}].map((e,t)=>({id:t+1,name:e.key,description:e.description,value:5})),L=[{formId:"0000080A",editorId:"Weap32CaliberPistol",name:".32 Pistol",nonPlayable:!1,damage:6,health:100,value:110,weight:2},{formId:"00050F92",editorId:"MysteriousStranger44Magnum",name:".44 Magnum",nonPlayable:!1,damage:9e3,health:1e3,value:0,weight:3},{formId:"0000434F",editorId:"Weap10mmPistol",name:"10mm Pistol",nonPlayable:!1,damage:9,health:150,value:225,weight:3},{formId:"0001A334",editorId:"FollowersButch10mmPistol",name:"10mm Pistol",nonPlayable:!1,damage:9,health:150,value:30,weight:2},{formId:"0006F210",editorId:"SonoraCruzWeap10mmPistol",name:"10mm Pistol",nonPlayable:!1,damage:100,health:150,value:43590,weight:2},{formId:"00004321",editorId:"Weap10mmSubmachineGun",name:"10mm Submachine Gun",nonPlayable:!1,damage:7,health:250,value:330,weight:5},{formId:"0006B539",editorId:"WeapUniqueA321PlasmaRifle",name:"A3-21's Plasma Rifle",nonPlayable:!1,damage:50,health:1200,value:2200,weight:8},{formId:"0006E8CE",editorId:"QueenAnt2HL",name:"Acid Spit",nonPlayable:!1,damage:40,health:100,value:80,weight:1},{formId:"000B8793",editorId:"MS04QueenAnt2HL",name:"Acid Spit",nonPlayable:!1,damage:70,health:100,value:130,weight:1},{formId:"00004322",editorId:"WeapAlienBlaster",name:"Alien Blaster",nonPlayable:!1,damage:100,health:500,value:500,weight:2},{formId:"000C553E",editorId:"WeapUniqueAntSting",name:"Ant's Sting",nonPlayable:!1,damage:4,health:250,value:30,weight:1},{formId:"0001FFEC",editorId:"WeapAssaultRifle",name:"Assault Rifle",nonPlayable:!1,damage:8,health:300,value:300,weight:7},{formId:"0000421C",editorId:"WeapBaseballBat",name:"Baseball Bat",nonPlayable:!1,damage:9,health:400,value:55,weight:3},{formId:"00033D84",editorId:"TrapBaseball",name:"Baseball",nonPlayable:!1,damage:6,health:5,value:10,weight:4},{formId:"00004323",editorId:"WeapBBGun",name:"BB Gun",nonPlayable:!1,damage:4,health:50,value:36,weight:2},{formId:"000C0327",editorId:"CG02WeapBBGun",name:"BB Gun",nonPlayable:!1,damage:4,health:1e3,value:36,weight:2},{formId:"0006B535",editorId:"WeapUniqueBlackBartsBBGun",name:"Black Bart's Bane",nonPlayable:!1,damage:8,health:100,value:60,weight:2},{formId:"000303A2",editorId:"WeapUniqueBlackhawk",name:"Blackhawk",nonPlayable:!1,damage:55,health:360,value:500,weight:4},{formId:"00046BDD",editorId:"Bloatfly1HP",name:"",nonPlayable:!1,damage:5,health:100,value:20,weight:1},{formId:"000C310F",editorId:"WeapUniqueBoardOfEducation",name:"Board of Education",nonPlayable:!1,damage:12,health:150,value:60,weight:4},{formId:"0000433A",editorId:"WeapMineBottlecap",name:"Bottlecap Mine",nonPlayable:!1,damage:1,health:5,value:75,weight:.5},{formId:"00004324",editorId:"WeapBrassKnuckles",name:"Brass Knuckles",nonPlayable:!1,damage:6,health:200,value:20,weight:1},{formId:"000CB546",editorId:"WeapUniqueBreaker",name:"Breaker",nonPlayable:!1,damage:12,health:150,value:30,weight:4},{formId:"000C80BD",editorId:"WeapUniqueBurnmaster",name:"Burnmaster",nonPlayable:!1,damage:24,health:200,value:500,weight:15},{formId:"00078440",editorId:"WeapUniqueButchToothpick",name:"Butch's Toothpick",nonPlayable:!1,damage:10,health:150,value:50,weight:1},{formId:"0003BC6F",editorId:"MisterHandyBuzzsaw",name:"Buzzsaw",nonPlayable:!1,damage:20,health:100,value:250,weight:1},{formId:"0000080B",editorId:"WeapChineseAssaultRifle",name:"Chinese Assault Rifle",nonPlayable:!1,damage:11,health:400,value:500,weight:7},{formId:"00040840",editorId:"FollowersJerichoChineseAssaultRifle",name:"Chinese Assault Rifle",nonPlayable:!1,damage:11,health:200,value:340,weight:7},{formId:"0002B3CB",editorId:"WeapChineseOfficerSword",name:"Chinese Officer's Sword",nonPlayable:!1,damage:10,health:500,value:75,weight:3},{formId:"0006415D",editorId:"FollowersCloverChineseOfficerSword",name:"Chinese Officer's Sword",nonPlayable:!1,damage:10,health:500,value:75,weight:3},{formId:"00004325",editorId:"WeapChinesePistol",name:"Chinese Pistol",nonPlayable:!1,damage:4,health:150,value:190,weight:2},{formId:"000C80B8",editorId:"WeapUniqueCloversCleaver",name:"Clover's Cleaver",nonPlayable:!1,damage:15,health:500,value:100,weight:3},{formId:"0006B531",editorId:"WeapUniqueColAutumns10mmPistol",name:"Col. Autumn's 10mm Pistol",nonPlayable:!1,damage:13,health:225,value:325,weight:3},{formId:"000ABBE4",editorId:"MQ11AutumnLaserPistol",name:"Col. Autumn's Laser Pistol",nonPlayable:!1,damage:10,health:500,value:420,weight:2},{formId:"00004326",editorId:"WeapKnifeCombat",name:"Combat Knife",nonPlayable:!1,damage:7,health:450,value:50,weight:1},{formId:"00064093",editorId:"FollowersCharonCombatKnife",name:"Combat Knife",nonPlayable:!1,damage:7,health:450,value:50,weight:1},{formId:"00004327",editorId:"WeapShotgunCombat",name:"Combat Shotgun",nonPlayable:!1,damage:55,health:240,value:200,weight:7},{formId:"0003713D",editorId:"FollowersCharonShotgunScene",name:"Combat Shotgun",nonPlayable:!1,damage:20,health:150,value:90,weight:10},{formId:"000372B8",editorId:"FollowersCharonShotgun",name:"Combat Shotgun",nonPlayable:!1,damage:55,health:150,value:70,weight:10},{formId:"000C80BB",editorId:"WeapUniqueCursebreaker",name:"Curse Breaker",nonPlayable:!1,damage:13,health:600,value:75,weight:3},{formId:"0000432A",editorId:"WeapDartGun",name:"Dart Gun",nonPlayable:!1,damage:6,health:150,value:500,weight:3},{formId:"0000432B",editorId:"WeapDeathclawGauntlet",name:"Deathclaw Gauntlet",nonPlayable:!1,damage:20,health:600,value:150,weight:10},{formId:"00022FF1",editorId:"EyeBot1HP",name:"Electrical Zap",nonPlayable:!1,damage:5,health:100,value:110,weight:1},{formId:"0006B538",editorId:"WeapUniqueMS18Minigun",name:"Eugene",nonPlayable:!1,damage:7,health:1500,value:1500,weight:18},{formId:"000C80BC",editorId:"WeapUniqueExcalibat",name:"Excalibat",nonPlayable:!1,damage:13,health:600,value:75,weight:3},{formId:"0003422B",editorId:"WeapUniqueMIRV",name:"Experimental MIRV",nonPlayable:!1,damage:10,health:300,value:2500,weight:30},{formId:"0000432C",editorId:"WeapFatman",name:"Fat Man",nonPlayable:!1,damage:10,health:100,value:1e3,weight:30},{formId:"0007843F",editorId:"WeapUniqueFawkesSuperSledge",name:"Fawkes' Super Sledge",nonPlayable:!1,damage:32,health:1e3,value:300,weight:18},{formId:"00021367",editorId:"BehemothFireHydrant",name:"Fire Hydrant",nonPlayable:!1,damage:100,health:1e3,value:100,weight:300},{formId:"000C80BA",editorId:"WeapUniqueFirelance",name:"Firelance",nonPlayable:!1,damage:80,health:200,value:750,weight:2},{formId:"000CB601",editorId:"WeapUniquePowerFist",name:"Fisto!",nonPlayable:!1,damage:25,health:600,value:100,weight:6},{formId:"000001F4",editorId:"Fists",name:"",nonPlayable:!1,damage:0,health:2,value:0,weight:0},{formId:"0000432D",editorId:"WeapFlamer",name:"Flamer",nonPlayable:!1,damage:16,health:200,value:500,weight:15},{formId:"00039550",editorId:"MisterGutsyFlamer2HL",name:"Flamer",nonPlayable:!1,damage:6,health:100,value:210,weight:1},{formId:"00078C60",editorId:"MS04FireAntWorkerFlame2HL",name:"Flamer",nonPlayable:!1,damage:2,health:100,value:30,weight:1},{formId:"0007C10B",editorId:"FollowerRL3Flamer2HL",name:"Flamer",nonPlayable:!1,damage:6,health:100,value:210,weight:1},{formId:"0009E8DF",editorId:"MS04FireAntSoldierFlame2HL",name:"Flamer",nonPlayable:!1,damage:4,health:100,value:60,weight:1},{formId:"000A0C02",editorId:"MisterHandyFlamer2HL",name:"Flamer",nonPlayable:!1,damage:2,health:100,value:60,weight:1},{formId:"000C58EE",editorId:"MS04FireAntGuardFlame2HL",name:"Flamer",nonPlayable:!1,damage:6,health:100,value:60,weight:1},{formId:"00004330",editorId:"WeapGrenadeFrag",name:"Frag Grenade",nonPlayable:!1,damage:1,health:5,value:25,weight:.5},{formId:"0000433C",editorId:"WeapMineFrag",name:"Frag Mine",nonPlayable:!1,damage:1,health:5,value:25,weight:.5},{formId:"00028172",editorId:"MQ04Mine",name:"Frag Mine",nonPlayable:!1,damage:300,health:5,value:3900,weight:1},{formId:"000001F6",editorId:"GasTrapDummy",name:"GasTrap Dummy",nonPlayable:!1,damage:0,health:100,value:0,weight:0},{formId:"0000432E",editorId:"WeapGatlingLaser",name:"Gatling Laser",nonPlayable:!1,damage:8,health:1500,value:2e3,weight:18},{formId:"0001A333",editorId:"FollowersFawkesGatlingLaser",name:"Gatling Laser",nonPlayable:!1,damage:9,health:1500,value:611,weight:10},{formId:"00018B9E",editorId:"ProtectronHandLaser1HP",name:"Hand Laser",nonPlayable:!1,damage:30,health:100,value:360,weight:1},{formId:"00018B9F",editorId:"ProtectronHeadLaser2HL",name:"Head Laser",nonPlayable:!1,damage:30,health:100,value:100,weight:1},{formId:"00078442",editorId:"WeapUniqueHighwaymansFriendTireIron",name:"Highwayman's Friend",nonPlayable:!1,damage:10,health:500,value:75,weight:5},{formId:"00004333",editorId:"WeapHuntingRifle",name:"Hunting Rifle",nonPlayable:!1,damage:25,health:500,value:150,weight:6},{formId:"000C6E5B",editorId:"WeapUniqueJackTheRipper",name:"Jack",nonPlayable:!1,damage:30,health:800,value:200,weight:6},{formId:"00004334",editorId:"WeapKnife",name:"Knife",nonPlayable:!1,damage:4,health:100,value:20,weight:1},{formId:"00004335",editorId:"WeapLaserPistol",name:"Laser Pistol",nonPlayable:!1,damage:12,health:350,value:320,weight:3},{formId:"00063E8A",editorId:"FollowersCrossLaserPistol",name:"Laser Pistol",nonPlayable:!1,damage:12,health:350,value:320,weight:3},{formId:"000B4178",editorId:"ElderLyonsLaserPistol",name:"Laser Pistol",nonPlayable:!1,damage:9,health:300,value:420,weight:2},{formId:"00004336",editorId:"WeapLaserRifle",name:"Laser Rifle",nonPlayable:!1,damage:23,health:1e3,value:1e3,weight:8},{formId:"00074795",editorId:"DemoLaserRifle",name:"Laser Rifle",nonPlayable:!1,damage:22,health:1e3,value:1e3,weight:8},{formId:"00050ED0",editorId:"RobobrainLaser1HPRight",name:"Laser",nonPlayable:!1,damage:38,health:100,value:1310,weight:1},{formId:"0007B237",editorId:"Turret01Laser2HR",name:"Laser",nonPlayable:!1,damage:8,health:50,value:100,weight:1},{formId:"0007B239",editorId:"Turret02Laser2HR",name:"Laser",nonPlayable:!1,damage:9,health:100,value:180,weight:1},{formId:"0007B23A",editorId:"Turret03Laser2HR",name:"Laser",nonPlayable:!1,damage:10,health:150,value:290,weight:1},{formId:"0006B532",editorId:"WeapUniqueLawDog32CalPistol",name:"Law Dog",nonPlayable:!1,damage:9,health:150,value:210,weight:2},{formId:"00004337",editorId:"WeapLeadPipe",name:"Lead Pipe",nonPlayable:!1,damage:9,health:300,value:75,weight:3},{formId:"00033FE2",editorId:"LibertyPrimeLaser",name:"Liberty Laser",nonPlayable:!1,damage:1e3,health:100,value:9674e3,weight:0},{formId:"0005932F",editorId:"LibertyPrimeWeapBomb",name:"LibertyPrimeWeapBomb",nonPlayable:!1,damage:200,health:100,value:23730,weight:0},{formId:"0003C07A",editorId:"MS06LincolnsRifle",name:"Lincoln's Repeater",nonPlayable:!1,damage:50,health:600,value:500,weight:5},{formId:"000C80B9",editorId:"WeapUniqueLoveTap",name:"Love Tap",nonPlayable:!1,damage:8,health:100,value:20,weight:1},{formId:"00004339",editorId:"WeapMesmetron",name:"Mesmetron",nonPlayable:!1,damage:1,health:100,value:500,weight:2},{formId:"000BF5A4",editorId:"RobobrainMesmetron",name:"Mesmetron",nonPlayable:!1,damage:1,health:100,value:500,weight:2},{formId:"0000433F",editorId:"WeapMinigun",name:"Minigun",nonPlayable:!1,damage:5,health:1e3,value:1e3,weight:18},{formId:"00030664",editorId:"MS03BaitGrenade",name:"Mirelurk Bait Grenade",nonPlayable:!1,damage:0,health:5,value:5,weight:1},{formId:"000B2644",editorId:"WeapUniqueMissLauncher",name:"Miss Launcher",nonPlayable:!1,damage:20,health:100,value:400,weight:15},{formId:"00004340",editorId:"WeapMissileLauncher",name:"Missile Launcher",nonPlayable:!1,damage:20,health:100,value:500,weight:20},{formId:"00057E8F",editorId:"SentryBotMissileLauncher2HL",name:"Missile Launcher",nonPlayable:!1,damage:20,health:1e3,value:4300,weight:15},{formId:"00063FDC",editorId:"FollowersJerichoNailBoard",name:"Nail Board",nonPlayable:!1,damage:8,health:60,value:30,weight:4},{formId:"000A01DD",editorId:"WeapNailBoard",name:"Nail Board",nonPlayable:!1,damage:8,health:60,value:30,weight:4},{formId:"00004342",editorId:"WeapNukaCocktail",name:"Nuka-Grenade",nonPlayable:!1,damage:1,health:5,value:50,weight:.5},{formId:"000CB602",editorId:"WeapUniqueKnifeCombat",name:"Occam's Razor",nonPlayable:!1,damage:10,health:600,value:65,weight:1},{formId:"0007843D",editorId:"WeapUniqueOGradysPoliceBaton",name:"O'Grady's Peacemaker",nonPlayable:!1,damage:6,health:400,value:100,weight:2},{formId:"00066C76",editorId:"WeapUniqueOlPainless",name:"Ol' Painless",nonPlayable:!1,damage:30,health:500,value:250,weight:6},{formId:"00004332",editorId:"WeapGrenadePlasma",name:"Plasma Grenade",nonPlayable:!1,damage:1,health:5,value:50,weight:.5},{formId:"0003954F",editorId:"MisterGutsyPlasma1HP",name:"Plasma Gun",nonPlayable:!1,damage:60,health:400,value:7200,weight:1},{formId:"0007C10C",editorId:"FollowerRL3Plasma1HP",name:"Plasma Gun",nonPlayable:!1,damage:40,health:400,value:7200,weight:1},{formId:"0000433D",editorId:"WeapMinePlasma",name:"Plasma Mine",nonPlayable:!1,damage:1,health:5,value:50,weight:.5},{formId:"00004343",editorId:"WeapPlasmaPistol",name:"Plasma Pistol",nonPlayable:!1,damage:25,health:400,value:360,weight:3},{formId:"00004344",editorId:"WeapPlasmaRifle",name:"Plasma Rifle",nonPlayable:!1,damage:45,health:900,value:1800,weight:8},{formId:"000CAFA9",editorId:"WeapUniqueJundersBrassKnuckles",name:"Plunkett's Valid Points",nonPlayable:!1,damage:12,health:200,value:30,weight:1},{formId:"00004345",editorId:"WeapPoliceBaton",name:"Police Baton",nonPlayable:!1,damage:4,health:250,value:70,weight:2},{formId:"00004346",editorId:"WeapPoolCue",name:"Pool Cue",nonPlayable:!1,damage:3,health:50,value:15,weight:1},{formId:"00004347",editorId:"WeapPowerFist",name:"Power Fist",nonPlayable:!1,damage:20,health:500,value:100,weight:6},{formId:"000C553F",editorId:"WeapUniqueProtectronGaze",name:"Protectron's Gaze",nonPlayable:!1,damage:24,health:500,value:320,weight:3},{formId:"00004331",editorId:"WeapGrenadePulse",name:"Pulse Grenade",nonPlayable:!1,damage:1,health:5,value:40,weight:.5},{formId:"0000433E",editorId:"WeapMinePulse",name:"Pulse Mine",nonPlayable:!1,damage:1,health:5,value:40,weight:.5},{formId:"00058717",editorId:"CentaurSpitMissile",name:"Radioactive Spit",nonPlayable:!1,damage:30,health:1e3,value:130,weight:1},{formId:"00004348",editorId:"WeapRailwayRifle",name:"Railway Rifle",nonPlayable:!1,damage:30,health:200,value:200,weight:9},{formId:"0002D3B7",editorId:"MS03Repellent",name:"Repellent Stick",nonPlayable:!1,damage:1,health:100,value:120,weight:3},{formId:"00092966",editorId:"WeapUniqueReservistsRifle",name:"Reservist's Rifle",nonPlayable:!1,damage:40,health:150,value:500,weight:10},{formId:"00004349",editorId:"WeapRipper",name:"Ripper",nonPlayable:!1,damage:30,health:600,value:100,weight:6},{formId:"0000434B",editorId:"WeapRockItLauncher",name:"Rock-It Launcher",nonPlayable:!1,damage:50,health:300,value:200,weight:8},{formId:"00029769",editorId:"MQ04RollingPin",name:"Rolling Pin",nonPlayable:!1,damage:20,health:100,value:10,weight:2},{formId:"000B2943",editorId:"WeapRollingPin",name:"Rolling Pin",nonPlayable:!1,damage:3,health:100,value:10,weight:1},{formId:"0005DEEE",editorId:"SatcomNuclearStrike",name:"",nonPlayable:!1,damage:20,health:100,value:500,weight:20},{formId:"0000434C",editorId:"WeapShotgunSawedOff",name:"Sawed-Off Shotgun",nonPlayable:!1,damage:50,health:250,value:150,weight:4},{formId:"000AE8AE",editorId:"FollowersCloverShotgun",name:"Sawed-Off Shotgun",nonPlayable:!1,damage:50,health:100,value:190,weight:5},{formId:"0000434D",editorId:"Weap44MagnumScoped",name:"Scoped .44 Magnum",nonPlayable:!1,damage:35,health:240,value:300,weight:4},{formId:"000389AF",editorId:"SentryBotGatling2HH",name:"SentryBot Laser Gatling",nonPlayable:!1,damage:6,health:1e3,value:1070,weight:15},{formId:"00057E8E",editorId:"SentryBotMinigun2HR",name:"SentryBot Minigun",nonPlayable:!1,damage:9,health:1e3,value:1070,weight:15},{formId:"0000434E",editorId:"WeapShishkebab",name:"Shishkebab",nonPlayable:!1,damage:35,health:750,value:200,weight:3},{formId:"0007F598",editorId:"MirelurkSonic2HL",name:"Shriek",nonPlayable:!1,damage:10,health:100,value:40,weight:1},{formId:"00004350",editorId:"Weap10mmPistolSilenced",name:"Silenced 10mm Pistol",nonPlayable:!1,damage:8,health:80,value:250,weight:3},{formId:"0002869C",editorId:"MQ04SlasherKnife",name:"Slasher Knife",nonPlayable:!1,damage:50,health:1e3,value:50,weight:1},{formId:"00004351",editorId:"WeapSledgehammer",name:"Sledgehammer",nonPlayable:!1,damage:20,health:500,value:130,weight:12},{formId:"00063FA2",editorId:"FollowersFawkesSledgehammer",name:"Sledgehammer",nonPlayable:!1,damage:20,health:500,value:130,weight:12},{formId:"0006B536",editorId:"WeapUniqueSmugglersEndLaserPistol",name:"Smuggler's End",nonPlayable:!1,damage:18,health:500,value:450,weight:2},{formId:"00004353",editorId:"WeapSniperRifle",name:"Sniper Rifle",nonPlayable:!1,damage:40,health:100,value:300,weight:10},{formId:"00004354",editorId:"WeapSpikedKnuckles",name:"Spiked Knuckles",nonPlayable:!1,damage:9,health:300,value:25,weight:1},{formId:"000C80BE",editorId:"WeapUniqueStabhappy",name:"Stabhappy",nonPlayable:!1,damage:10,health:600,value:65,weight:1},{formId:"00004352",editorId:"WeapSuperSledge",name:"Super Sledge",nonPlayable:!1,damage:25,health:750,value:180,weight:20},{formId:"000B0E7C",editorId:"FollowersCrossSuperSledge",name:"Super Sledge",nonPlayable:!1,damage:25,health:250,value:130,weight:3},{formId:"000289C3",editorId:"WeapSwitchBlade",name:"Switchblade",nonPlayable:!1,damage:5,health:100,value:35,weight:1},{formId:"0006407F",editorId:"FollowersButchSwitchblade",name:"Switchblade",nonPlayable:!1,damage:5,health:100,value:50,weight:1},{formId:"00066346",editorId:"WeapUniqueSydneys10mmSubGunFollwerVersion",name:'Sydney\'s 10mm "Ultra" SMG',nonPlayable:!1,damage:9,health:250,value:430,weight:5},{formId:"0006E7CC",editorId:"WeapUniqueSydneys10mmSubGun",name:'Sydney\'s 10mm "Ultra" SMG',nonPlayable:!1,damage:9,health:250,value:430,weight:5},{formId:"00066C77",editorId:"WeapUniqueTheBreak",name:"The Break",nonPlayable:!1,damage:6,health:200,value:50,weight:1},{formId:"0006B53A",editorId:"WeapUniqueKneecapper",name:"The Kneecapper",nonPlayable:!1,damage:75,health:250,value:350,weight:5},{formId:"000BFF62",editorId:"WeapUniqueShocker",name:"The Shocker",nonPlayable:!1,damage:20,health:400,value:150,weight:6},{formId:"000A874B",editorId:"WeapUniqueTenderizer",name:"The Tenderizer",nonPlayable:!1,damage:30,health:750,value:230,weight:12},{formId:"0006B534",editorId:"WeapUniqueTerribleShotgun",name:"The Terrible Shotgun",nonPlayable:!1,damage:80,health:350,value:250,weight:10},{formId:"00004328",editorId:"WeapTireIron",name:"Tire Iron",nonPlayable:!1,damage:6,health:200,value:40,weight:3},{formId:"00018E53",editorId:"TurretGunCeiling02",name:"Turret Gun",nonPlayable:!1,damage:7,health:150,value:230,weight:7},{formId:"00018E54",editorId:"TurretGunCeiling03",name:"Turret Gun",nonPlayable:!1,damage:10,health:150,value:370,weight:7},{formId:"000A84BD",editorId:"TurretGunCeiling01",name:"Turret Gun",nonPlayable:!1,damage:5,health:150,value:140,weight:7},{formId:"00078441",editorId:"WeapUniqueVancesChineseSword",name:"Vampire's Edge",nonPlayable:!1,damage:15,health:750,value:100,weight:1},{formId:"000CB547",editorId:"WeapUniqueVengeance",name:"Vengeance",nonPlayable:!1,damage:11,health:2e3,value:2400,weight:18},{formId:"0003E5E2",editorId:"VertibirdBombGun",name:"Vertibird Bomb Gun",nonPlayable:!1,damage:10,health:30,value:1e3,weight:30},{formId:"00089C51",editorId:"VertibirdGun",name:"Vertibird Gun",nonPlayable:!1,damage:20,health:3e3,value:6040,weight:10},{formId:"000CB548",editorId:"WeapUniqueVictoryRifle",name:"Victory Rifle",nonPlayable:!1,damage:40,health:300,value:450,weight:10},{formId:"0006B533",editorId:"WeapUniqueWandaAssaultRifle",name:"Wanda",nonPlayable:!1,damage:12,health:450,value:500,weight:7},{formId:"00061793",editorId:"WeapUniqueWazerWifle",name:"Wazer Wifle",nonPlayable:!1,damage:28,health:1800,value:900,weight:8},{formId:"000C800E",editorId:"WeapUniqueXuanlongAssaultRifle",name:"Xuanlong Assault Rifle",nonPlayable:!1,damage:12,health:400,value:400,weight:7},{formId:"00060C2C",editorId:"WeapUniqueZhuRongChinesePistol",name:"Zhu-Rong v418 Chinese Pistol",nonPlayable:!1,damage:4,health:200,value:290,weight:2}],E="1.0.3",C="pipBoy3000Settings",N=e=>e.map(e=>({id:e.id,name:e.name,description:e.description,value:e.value,imageId:e.imageId}));class B{constructor(){this.loadFromLocalStorage(),r(()=>{this.userLevel(),this.userHealth(),this.userHealthMax(),this.userActionPoints(),this.userActionPointsMax(),this.userExperience(),this.userExperienceNextLevel(),this.userName(),this.stimpakLabel(),this.limbLabel(),this.radAwayLabel(),this.radXLabel(),this.equippedWeaponId(),this.equippedApparelId(),this.equippedAidId(),this.equippedMiscId(),this.equippedAmmoId(),this.weaponItems(),this.apparelItems(),this.aidItems(),this.miscItems(),this.ammoItems(),this.specialItems(),this.skillItems(),this.perkItems(),this.questItems(),this.generalItems(),this.notesItems(),this.radioItems(),this.selectedNotesItemId(),this.selectedRadioItemId(),this.effectItems(),this.localMapImage(),this.worldMapImage(),this.vaultBoyImages(),this.selectedVaultBoyImageIndex(),this.scanLinesEnabled(),this.editLockEnabled(),this.listFontScale(),this.secondaryTabSoundId(),this.mainTabSoundId(),this.clickSoundId(),this.saveToLocalStorage()})}imageStore=s(x);userLevel=o(1,...ngDevMode?[{debugName:"userLevel"}]:[]);userHealth=o(99,...ngDevMode?[{debugName:"userHealth"}]:[]);userHealthMax=o(100,...ngDevMode?[{debugName:"userHealthMax"}]:[]);userActionPoints=o(50,...ngDevMode?[{debugName:"userActionPoints"}]:[]);userActionPointsMax=o(100,...ngDevMode?[{debugName:"userActionPointsMax"}]:[]);userExperience=o(1,...ngDevMode?[{debugName:"userExperience"}]:[]);userExperienceNextLevel=o(100,...ngDevMode?[{debugName:"userExperienceNextLevel"}]:[]);userName=o("Vault Dweller",...ngDevMode?[{debugName:"userName"}]:[]);stimpakLabel=o("(4) Stimpak",...ngDevMode?[{debugName:"stimpakLabel"}]:[]);limbLabel=o("Limbs",...ngDevMode?[{debugName:"limbLabel"}]:[]);radAwayLabel=o("RadAway",...ngDevMode?[{debugName:"radAwayLabel"}]:[]);radXLabel=o("Rad-X",...ngDevMode?[{debugName:"radXLabel"}]:[]);equippedWeaponId=o(null,...ngDevMode?[{debugName:"equippedWeaponId"}]:[]);equippedApparelId=o(null,...ngDevMode?[{debugName:"equippedApparelId"}]:[]);equippedAidId=o(null,...ngDevMode?[{debugName:"equippedAidId"}]:[]);equippedMiscId=o(null,...ngDevMode?[{debugName:"equippedMiscId"}]:[]);equippedAmmoId=o(null,...ngDevMode?[{debugName:"equippedAmmoId"}]:[]);weaponItems=o([],...ngDevMode?[{debugName:"weaponItems"}]:[]);apparelItems=o([],...ngDevMode?[{debugName:"apparelItems"}]:[]);aidItems=o([],...ngDevMode?[{debugName:"aidItems"}]:[]);miscItems=o([],...ngDevMode?[{debugName:"miscItems"}]:[]);ammoItems=o([],...ngDevMode?[{debugName:"ammoItems"}]:[]);specialItems=o(N(D),...ngDevMode?[{debugName:"specialItems"}]:[]);skillItems=o(N(R),...ngDevMode?[{debugName:"skillItems"}]:[]);perkItems=o(N(A),...ngDevMode?[{debugName:"perkItems"}]:[]);generalItems=o([],...ngDevMode?[{debugName:"generalItems"}]:[]);questItems=o([{id:1,name:"Quest item",completed:!1,tasks:[{id:1,name:"Task 1",completed:!1},{id:2,name:"Task 2",completed:!1},{id:3,name:"Task 3",completed:!1}]}],...ngDevMode?[{debugName:"questItems"}]:[]);notesItems=o([],...ngDevMode?[{debugName:"notesItems"}]:[]);radioItems=o([],...ngDevMode?[{debugName:"radioItems"}]:[]);selectedNotesItemId=o(null,...ngDevMode?[{debugName:"selectedNotesItemId"}]:[]);selectedRadioItemId=o(null,...ngDevMode?[{debugName:"selectedRadioItemId"}]:[]);effectItems=o([],...ngDevMode?[{debugName:"effectItems"}]:[]);localMapImage=o(null,...ngDevMode?[{debugName:"localMapImage"}]:[]);worldMapImage=o(null,...ngDevMode?[{debugName:"worldMapImage"}]:[]);vaultBoyImages=o([null,null,null],...ngDevMode?[{debugName:"vaultBoyImages"}]:[]);selectedVaultBoyImageIndex=o(0,...ngDevMode?[{debugName:"selectedVaultBoyImageIndex"}]:[]);scanLinesEnabled=o(!0,...ngDevMode?[{debugName:"scanLinesEnabled"}]:[]);editLockEnabled=o(!1,...ngDevMode?[{debugName:"editLockEnabled"}]:[]);listFontScale=o(1.25,...ngDevMode?[{debugName:"listFontScale"}]:[]);secondaryTabSoundId=o(null,...ngDevMode?[{debugName:"secondaryTabSoundId"}]:[]);mainTabSoundId=o(null,...ngDevMode?[{debugName:"mainTabSoundId"}]:[]);clickSoundId=o(null,...ngDevMode?[{debugName:"clickSoundId"}]:[]);exportSettingsSnapshot(){return{userLevel:this.userLevel(),userHealth:this.userHealth(),userHealthMax:this.userHealthMax(),userActionPoints:this.userActionPoints(),userActionPointsMax:this.userActionPointsMax(),userExperience:this.userExperience(),userExperienceNextLevel:this.userExperienceNextLevel(),userName:this.userName(),stimpakLabel:this.stimpakLabel(),limbLabel:this.limbLabel(),radAwayLabel:this.radAwayLabel(),radXLabel:this.radXLabel(),equippedWeaponId:this.equippedWeaponId(),equippedApparelId:this.equippedApparelId(),equippedAidId:this.equippedAidId(),equippedMiscId:this.equippedMiscId(),equippedAmmoId:this.equippedAmmoId(),weaponItems:this.weaponItems(),apparelItems:this.apparelItems(),aidItems:this.aidItems(),miscItems:this.miscItems(),ammoItems:this.ammoItems(),specialItems:this.specialItems(),skillItems:this.skillItems(),perkItems:this.perkItems(),questItems:this.questItems(),generalItems:this.generalItems(),notesItems:this.notesItems(),radioItems:this.radioItems(),selectedNotesItemId:this.selectedNotesItemId(),selectedRadioItemId:this.selectedRadioItemId(),effectItems:this.effectItems(),localMapImage:this.localMapImage(),worldMapImage:this.worldMapImage(),vaultBoyImages:this.vaultBoyImages(),selectedVaultBoyImageIndex:this.selectedVaultBoyImageIndex(),scanLinesEnabled:this.scanLinesEnabled(),editLockEnabled:this.editLockEnabled(),listFontScale:this.listFontScale(),secondaryTabSoundId:this.secondaryTabSoundId(),mainTabSoundId:this.mainTabSoundId(),clickSoundId:this.clickSoundId()}}exportSettingsJson(){return JSON.stringify(this.exportSettingsSnapshot())}importSettingsJson(e){const t=JSON.parse(e);this.importSettingsSnapshot(t)}importSettingsSnapshot(e){if(this.setNumberSignal(this.userLevel,e.userLevel),this.setNumberSignal(this.userHealth,e.userHealth),this.setNumberSignal(this.userHealthMax,e.userHealthMax),this.setNumberSignal(this.userActionPoints,e.userActionPoints),this.setNumberSignal(this.userActionPointsMax,e.userActionPointsMax),this.setNumberSignal(this.userExperience,e.userExperience),this.setNumberSignal(this.userExperienceNextLevel,e.userExperienceNextLevel),"string"==typeof e.userName&&this.userName.set(e.userName),"string"==typeof e.stimpakLabel&&this.stimpakLabel.set(e.stimpakLabel),"string"==typeof e.limbLabel&&this.limbLabel.set(e.limbLabel),"string"==typeof e.radAwayLabel&&this.radAwayLabel.set(e.radAwayLabel),"string"==typeof e.radXLabel&&this.radXLabel.set(e.radXLabel),"number"==typeof e.equippedWeaponId?this.equippedWeaponId.set(e.equippedWeaponId):null===e.equippedWeaponId&&this.equippedWeaponId.set(null),"number"==typeof e.equippedApparelId?this.equippedApparelId.set(e.equippedApparelId):null===e.equippedApparelId&&this.equippedApparelId.set(null),"number"==typeof e.equippedAidId?this.equippedAidId.set(e.equippedAidId):null===e.equippedAidId&&this.equippedAidId.set(null),"number"==typeof e.equippedMiscId?this.equippedMiscId.set(e.equippedMiscId):null===e.equippedMiscId&&this.equippedMiscId.set(null),"number"==typeof e.equippedAmmoId?this.equippedAmmoId.set(e.equippedAmmoId):null===e.equippedAmmoId&&this.equippedAmmoId.set(null),this.weaponItems.set(this.normalizeItems(e.weaponItems)),this.apparelItems.set(this.normalizeItems(e.apparelItems)),this.aidItems.set(this.normalizeItems(e.aidItems)),this.miscItems.set(this.normalizeItems(e.miscItems)),this.ammoItems.set(this.normalizeItems(e.ammoItems)),this.specialItems.set(this.normalizeStatItems(e.specialItems,N(D))),this.skillItems.set(this.normalizeStatItems(e.skillItems,N(R))),this.perkItems.set(this.normalizeStatItems(e.perkItems,N(A))),this.generalItems.set(this.normalizeStatItems(e.generalItems,[])),this.questItems.set(this.normalizeQuestItems(e.questItems)),this.notesItems.set(this.normalizeAudioItems(e.notesItems)),this.radioItems.set(this.normalizeAudioItems(e.radioItems)),"number"==typeof e.selectedNotesItemId?this.selectedNotesItemId.set(e.selectedNotesItemId):null===e.selectedNotesItemId&&this.selectedNotesItemId.set(null),"number"==typeof e.selectedRadioItemId?this.selectedRadioItemId.set(e.selectedRadioItemId):null===e.selectedRadioItemId&&this.selectedRadioItemId.set(null),this.effectItems.set(this.normalizeEffectItems(e.effectItems)),"string"==typeof e.localMapImage?this.localMapImage.set(this.normalizeImageId(e.localMapImage)??null):null===e.localMapImage&&this.localMapImage.set(null),"string"==typeof e.worldMapImage?this.worldMapImage.set(this.normalizeImageId(e.worldMapImage)??null):null===e.worldMapImage&&this.worldMapImage.set(null),Array.isArray(e.vaultBoyImages)){const t=this.normalizeImageSlots(e.vaultBoyImages);if(this.vaultBoyImages.set(t),"number"==typeof e.selectedVaultBoyImageIndex&&Number.isFinite(e.selectedVaultBoyImageIndex)){const a=Math.min(Math.max(0,e.selectedVaultBoyImageIndex),Math.max(0,t.length-1));this.selectedVaultBoyImageIndex.set(a)}}if("boolean"==typeof e.scanLinesEnabled&&this.scanLinesEnabled.set(e.scanLinesEnabled),"boolean"==typeof e.editLockEnabled&&this.editLockEnabled.set(e.editLockEnabled),"number"==typeof e.listFontScale){const t=Math.min(1.875,Math.max(.625,e.listFontScale));Number.isFinite(t)&&this.listFontScale.set(t)}"string"==typeof e.secondaryTabSoundId?this.secondaryTabSoundId.set(e.secondaryTabSoundId):null===e.secondaryTabSoundId&&this.secondaryTabSoundId.set(null),"string"==typeof e.mainTabSoundId?this.mainTabSoundId.set(e.mainTabSoundId):null===e.mainTabSoundId&&this.mainTabSoundId.set(null),"string"==typeof e.clickSoundId?this.clickSoundId.set(e.clickSoundId):null===e.clickSoundId&&this.clickSoundId.set(null)}saveToLocalStorage(e=C){"undefined"!=typeof localStorage&&localStorage.setItem(e,this.exportSettingsJson())}loadFromLocalStorage(e=C){if("undefined"==typeof localStorage)return;const t=localStorage.getItem(e);t&&this.importSettingsJson(t)}resetToDefaults(){this.userLevel.set(1),this.userHealth.set(99),this.userHealthMax.set(100),this.userActionPoints.set(50),this.userActionPointsMax.set(100),this.userExperience.set(1),this.userExperienceNextLevel.set(100),this.userName.set("Vault Dweller"),this.stimpakLabel.set("(4) Stimpak"),this.limbLabel.set("Limbs"),this.radAwayLabel.set("RadAway"),this.radXLabel.set("Rad-X"),this.equippedWeaponId.set(null),this.equippedApparelId.set(null),this.equippedAidId.set(null),this.equippedMiscId.set(null),this.equippedAmmoId.set(null),this.weaponItems.set([]),this.apparelItems.set([]),this.aidItems.set([]),this.miscItems.set([]),this.ammoItems.set([]),this.specialItems.set(N(D)),this.skillItems.set(N(R)),this.perkItems.set(N(A)),this.generalItems.set([]),this.questItems.set([{id:1,name:"Quest item",completed:!1,tasks:[{id:1,name:"Task 1",completed:!1},{id:2,name:"Task 2",completed:!1},{id:3,name:"Task 3",completed:!1}]}]),this.notesItems.set([]),this.radioItems.set([]),this.selectedNotesItemId.set(null),this.selectedRadioItemId.set(null),this.effectItems.set([]),this.localMapImage.set(null),this.worldMapImage.set(null),this.vaultBoyImages.set([null,null,null]),this.selectedVaultBoyImageIndex.set(0),this.scanLinesEnabled.set(!0),this.editLockEnabled.set(!1),this.listFontScale.set(1.25),this.secondaryTabSoundId.set(null),this.mainTabSoundId.set(null),this.clickSoundId.set(null)}setNumberSignal(e,t){"number"==typeof t&&Number.isFinite(t)&&e.set(t)}normalizeItems(e){return Array.isArray(e)?e.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name).map(e=>({id:e.id,name:e.name,damage:"number"==typeof e.damage&&Number.isFinite(e.damage)?e.damage:void 0,imageId:this.normalizeImageId(e.imageId??e.image),effects:"string"==typeof e.effects?e.effects:void 0,quantity:"number"==typeof e.quantity&&Number.isFinite(e.quantity)?e.quantity:void 0,value:"number"==typeof e.value&&Number.isFinite(e.value)?e.value:void 0,weight:"number"==typeof e.weight&&Number.isFinite(e.weight)?e.weight:void 0})):[]}normalizeStatItems(e,t){return Array.isArray(e)?e.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name&&"string"==typeof e.description&&"number"==typeof e.value&&Number.isFinite(e.value)).map(e=>({id:e.id,name:e.name,description:e.description,value:e.value,imageId:this.normalizeImageId(e.imageId??e.image)})):t}normalizeAudioItems(e){return Array.isArray(e)?e.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name&&"string"==typeof e.soundId).map(e=>({id:e.id,name:e.name,soundId:e.soundId})):[]}normalizeEffectItems(e){return Array.isArray(e)?e.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name&&"string"==typeof e.description).map(e=>({id:e.id,name:e.name,description:e.description})):[]}normalizeQuestItems(e){return Array.isArray(e)?e.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name&&"boolean"==typeof e.completed&&Array.isArray(e.tasks)).map(e=>({id:e.id,name:e.name,completed:e.completed,tasks:e.tasks.filter(e=>!!e&&"number"==typeof e.id&&"string"==typeof e.name&&"boolean"==typeof e.completed).map(e=>({id:e.id,name:e.name,completed:e.completed}))})):[]}normalizeImageSlots(e){if(!Array.isArray(e))return[];return e.map(e=>"string"!=typeof e?null:this.normalizeImageId(e)??null).slice(0,10)}normalizeImageId(e){if("string"==typeof e){if(e.startsWith("data:")){const t=this.imageStore.generateId();return this.imageStore.saveDataUrlWithId(t,e),t}return e}}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:B,deps:[],target:e.ɵɵFactoryTarget.Injectable});static"ɵprov"=e.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:B,providedIn:"root"})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:B,decorators:[{type:i,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});class F{static nextId=0;open=!1;title="";name="";nameLabel="Name";showName=!1;nameOptions=[];imageUrl=null;showImage=!1;fields=[];textFields=[];closeResult=new l;save=new l;nameChange=new l;values=o({},...ngDevMode?[{debugName:"values"}]:[]);draftName=o("",...ngDevMode?[{debugName:"draftName"}]:[]);draftImageUrl=o(null,...ngDevMode?[{debugName:"draftImageUrl"}]:[]);draftImageName=o(null,...ngDevMode?[{debugName:"draftImageName"}]:[]);draftImageFile=o(null,...ngDevMode?[{debugName:"draftImageFile"}]:[]);removedImage=o(!1,...ngDevMode?[{debugName:"removedImage"}]:[]);textValues=o({},...ngDevMode?[{debugName:"textValues"}]:[]);nameListId="stat-edit-name-"+F.nextId++;previewUrl=null;ngOnChanges(){if(this.open){this.draftName.set(this.name),this.draftImageUrl.set(this.imageUrl),this.draftImageName.set(null),this.draftImageFile.set(null),this.removedImage.set(!1),this.clearPreviewUrl();const e={};for(const t of this.fields)e[t.key]=t.value;this.values.set(e);const t={};for(const e of this.textFields)t[e.key]=e.value;this.textValues.set(t)}}closeModal(){this.clearPreviewUrl(),this.closeResult.emit()}updateName(e){this.draftName.set(e),this.nameChange.emit(e)}onImageSelected(e){const t=e.target,a=t.files?.[0]??null;this.draftImageName.set(a?a.name:null),a&&(this.removedImage.set(!1),this.draftImageFile.set(a),this.setPreviewUrl(URL.createObjectURL(a)),t.value="")}removeImage(){this.draftImageName.set(null),this.draftImageUrl.set(null),this.draftImageFile.set(null),this.removedImage.set(!0),this.clearPreviewUrl()}updateText(e,t){this.textValues.update(a=>({...a,[e]:t}))}onInput(e,t){const a=Number(t);this.values.update(t=>({...t,[e]:a}))}submit(e){e?.preventDefault(),this.save.emit({name:this.draftName(),values:this.values(),imageFile:this.draftImageFile(),removeImage:this.removedImage(),textValues:this.textValues()}),this.clearPreviewUrl()}setPreviewUrl(e){this.clearPreviewUrl(),this.previewUrl=e,this.draftImageUrl.set(e)}clearPreviewUrl(){this.previewUrl&&(URL.revokeObjectURL(this.previewUrl),this.previewUrl=null)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:F,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:F,isStandalone:!0,selector:"pip-boy-stat-edit-modal",inputs:{open:"open",title:"title",name:"name",nameLabel:"nameLabel",showName:"showName",nameOptions:"nameOptions",imageUrl:"imageUrl",showImage:"showImage",fields:"fields",textFields:"textFields"},outputs:{closeResult:"closeResult",save:"save",nameChange:"nameChange"},usesOnChanges:!0,ngImport:e,template:'@if (open) {\n <div\n class="stat-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="stat-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <form (submit)="submit($event)">\n <div class="stat-modal-body">\n @if (showName) {\n <label class="stat-modal-field">\n <span>{{ nameLabel }}</span>\n <input\n type="text"\n [attr.list]="nameOptions.length ? nameListId : null"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n @if (nameOptions.length) {\n <datalist [id]="nameListId">\n @for (name of nameOptions; track name) {\n <option [value]="name"></option>\n }\n </datalist>\n }\n }\n @for (field of fields; track field.key) {\n <label class="stat-modal-field">\n <span>{{ field.label }}</span>\n <input\n type="number"\n inputmode="numeric"\n [value]="values()[field.key]"\n (input)="onInput(field.key, $any($event.target).value)"\n />\n </label>\n }\n @for (field of textFields; track field.key) {\n <label\n class="stat-modal-field"\n [attr.for]="\'text-field-\' + field.key"\n >\n <span>{{ field.label }}</span>\n @if (field.multiline) {\n <textarea\n [id]="\'text-field-\' + field.key"\n rows="4"\n [value]="textValues()[field.key]"\n (input)="updateText(field.key, $any($event.target).value)"\n ></textarea>\n } @else {\n <input\n [id]="\'text-field-\' + field.key"\n type="text"\n [value]="textValues()[field.key]"\n (input)="updateText(field.key, $any($event.target).value)"\n />\n }\n </label>\n }\n @if (showImage) {\n <div class="stat-modal-image">\n <button\n type="button"\n class="stat-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="stat-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Item preview" />\n }\n </div>\n }\n </div>\n <div class="stat-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.stat-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.stat-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.stat-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.stat-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.stat-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.stat-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.stat-modal-field input,.stat-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.stat-modal-field input:focus,.stat-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.stat-modal-field input{height:2.5rem}.stat-modal-field textarea{min-height:6rem;resize:vertical;text-transform:none}.stat-modal-image{display:flex;flex-direction:column;gap:.75rem}.stat-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.stat-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:8rem;object-fit:contain;padding:.5rem}.stat-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.stat-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.stat-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.stat-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.stat-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"],dependencies:[{kind:"ngmodule",type:g}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:F,decorators:[{type:n,args:[{selector:"pip-boy-stat-edit-modal",standalone:!0,imports:[g],template:'@if (open) {\n <div\n class="stat-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="stat-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <form (submit)="submit($event)">\n <div class="stat-modal-body">\n @if (showName) {\n <label class="stat-modal-field">\n <span>{{ nameLabel }}</span>\n <input\n type="text"\n [attr.list]="nameOptions.length ? nameListId : null"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n @if (nameOptions.length) {\n <datalist [id]="nameListId">\n @for (name of nameOptions; track name) {\n <option [value]="name"></option>\n }\n </datalist>\n }\n }\n @for (field of fields; track field.key) {\n <label class="stat-modal-field">\n <span>{{ field.label }}</span>\n <input\n type="number"\n inputmode="numeric"\n [value]="values()[field.key]"\n (input)="onInput(field.key, $any($event.target).value)"\n />\n </label>\n }\n @for (field of textFields; track field.key) {\n <label\n class="stat-modal-field"\n [attr.for]="\'text-field-\' + field.key"\n >\n <span>{{ field.label }}</span>\n @if (field.multiline) {\n <textarea\n [id]="\'text-field-\' + field.key"\n rows="4"\n [value]="textValues()[field.key]"\n (input)="updateText(field.key, $any($event.target).value)"\n ></textarea>\n } @else {\n <input\n [id]="\'text-field-\' + field.key"\n type="text"\n [value]="textValues()[field.key]"\n (input)="updateText(field.key, $any($event.target).value)"\n />\n }\n </label>\n }\n @if (showImage) {\n <div class="stat-modal-image">\n <button\n type="button"\n class="stat-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="stat-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Item preview" />\n }\n </div>\n }\n </div>\n <div class="stat-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.stat-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.stat-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.stat-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.stat-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.stat-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.stat-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.stat-modal-field input,.stat-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.stat-modal-field input:focus,.stat-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.stat-modal-field input{height:2.5rem}.stat-modal-field textarea{min-height:6rem;resize:vertical;text-transform:none}.stat-modal-image{display:flex;flex-direction:column;gap:.75rem}.stat-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.stat-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:8rem;object-fit:contain;padding:.5rem}.stat-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.stat-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.stat-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.stat-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.stat-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],title:[{type:m}],name:[{type:m}],nameLabel:[{type:m}],showName:[{type:m}],nameOptions:[{type:m}],imageUrl:[{type:m}],showImage:[{type:m}],fields:[{type:m}],textFields:[{type:m}],closeResult:[{type:d}],save:[{type:d}],nameChange:[{type:d}]}});class T{state=s(w);settings=s(B);statModal=o(null,...ngDevMode?[{debugName:"statModal"}]:[]);statModalTitle=c(()=>{switch(this.statModal()){case"LVL":return"Edit Level";case"HP":return"Edit Health";case"AP":return"Edit Action Points";case"XP":return"Edit Experience";default:return""}},...ngDevMode?[{debugName:"statModalTitle"}]:[]);statModalFields=c(()=>{switch(this.statModal()){case"LVL":return[{key:"level",label:"Level",value:this.settings.userLevel()}];case"HP":return[{key:"current",label:"Current",value:this.settings.userHealth()},{key:"max",label:"Max",value:this.settings.userHealthMax()}];case"AP":return[{key:"current",label:"Current",value:this.settings.userActionPoints()},{key:"max",label:"Max",value:this.settings.userActionPointsMax()}];case"XP":return[{key:"current",label:"Current",value:this.settings.userExperience()},{key:"max",label:"Next Level",value:this.settings.userExperienceNextLevel()}];default:return[]}},...ngDevMode?[{debugName:"statModalFields"}]:[]);openStatModal(e){this.statModal.set(e)}closeStatModal(){this.statModal.set(null)}saveStatModal(e){const t=this.statModal();if(t){if("LVL"===t){const t=e.values.level;return Number.isFinite(t)&&this.settings.userLevel.set(t),void this.closeStatModal()}"HP"===t?this.applyPair(e.values,this.settings.userHealth,this.settings.userHealthMax):"AP"===t?this.applyPair(e.values,this.settings.userActionPoints,this.settings.userActionPointsMax):"XP"===t&&this.applyPair(e.values,this.settings.userExperience,this.settings.userExperienceNextLevel),this.closeStatModal()}}applyPair(e,t,a){Number.isFinite(e.current)&&t.set(e.current),Number.isFinite(e.max)&&a.set(e.max)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:T,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:T,isStandalone:!0,selector:"pip-boy-3000-header",ngImport:e,template:'<header>\n <div class="header-top">\n <div class="main-title">\n <div class="main-title-left-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="main-title-text">\n @if (state.primary() === \'STATS\') {\n STATS\n } @else if (state.primary() === \'ITEMS\') {\n ITEMS\n } @else if (state.primary() === \'DATA\') {\n DATA\n }\n </div>\n <div class="main-title-right-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n </div>\n <div class="hp-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="ap-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="xp-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n </div>\n <div class="header-content">\n <button\n type="button"\n class="stats stat-button"\n (click)="openStatModal(\'LVL\')"\n >\n <span>LVL</span> {{ settings.userLevel() }}\n </button>\n <button type="button" class="hp stat-button" (click)="openStatModal(\'HP\')">\n <span>HP</span>\n <span>{{ settings.userHealth() }} / {{ settings.userHealthMax() }}</span>\n </button>\n <button type="button" class="ap stat-button" (click)="openStatModal(\'AP\')">\n <span>AP</span>\n {{ settings.userActionPoints() }} / {{ settings.userActionPointsMax() }}\n </button>\n <button type="button" class="xp stat-button" (click)="openStatModal(\'XP\')">\n <span>XP</span>\n {{ settings.userExperience() }} /\n {{ settings.userExperienceNextLevel() }}\n </button>\n </div>\n</header>\n<pip-boy-stat-edit-modal\n (closeResult)="closeStatModal()"\n (save)="saveStatModal($event)"\n [fields]="statModalFields()"\n [open]="statModal() !== null"\n [title]="statModalTitle()"\n/>\n',styles:[':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.center-line{position:relative;height:100%;overflow:visible}.center-line:before{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:2px;background:#0fbb6b}.bottom-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.bottom-half-line:before{content:"";position:absolute;top:50%;bottom:-1.25rem;width:2px;z-index:2;background:linear-gradient(to bottom,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}header{width:100%;box-sizing:border-box;display:flex;flex-direction:column;flex:0 0 auto;min-height:0;padding:0 1rem}header>.header-top,header>.header-content{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.25rem;padding:0}header>.header-top{height:2.25rem;align-items:center;text-transform:uppercase;overflow:visible}header>.header-top>.main-title{display:flex;align-items:center;justify-content:center;gap:.5rem;height:100%;overflow:visible}header>.header-top>.main-title>.main-title-left-line,header>.header-top>.main-title>.main-title-right-line{flex-grow:1;min-width:2rem;height:100%;position:relative;overflow:visible}header>.header-top>.main-title>.main-title-text{font-size:clamp(1.25rem,1.25rem + (1.5rem - 1.25rem) * (100vw - 360px) / (1200px - 360px),1.5rem);flex-grow:0;letter-spacing:.1em;white-space:nowrap;line-height:1}header>.header-top .main-title-left-line .bottom-half-line:before{left:0}header>.header-top .main-title-right-line .bottom-half-line:before{right:0}header>.header-top .hp-title-line,header>.header-top .ap-title-line,header>.header-top .xp-title-line{overflow:visible}header>.header-top .hp-title-line .bottom-half-line:before,header>.header-top .ap-title-line .bottom-half-line:before,header>.header-top .xp-title-line .bottom-half-line:before{right:0}header>.header-content{box-sizing:border-box;margin-top:-.5rem;font-size:calc(clamp(.9rem,.9rem + .2rem * (100vw - 360px) / 840px,1.1rem) * (1 + (var(--list-font-scale, 1) - 1) * .6))}header>.header-content>.stats,header>.header-content>.hp,header>.header-content>.ap,header>.header-content>.xp{display:flex;justify-content:flex-end;padding:0 1rem;gap:1rem}header>.header-content>.stat-button{align-items:center;background:transparent;border:none;color:inherit;cursor:pointer;font:inherit;text-align:right;text-transform:uppercase}header>.header-content>.stat-button:hover{background:#0fbb6b14}\n'],dependencies:[{kind:"component",type:F,selector:"pip-boy-stat-edit-modal",inputs:["open","title","name","nameLabel","showName","nameOptions","imageUrl","showImage","fields","textFields"],outputs:["closeResult","save","nameChange"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:T,decorators:[{type:n,args:[{selector:"pip-boy-3000-header",standalone:!0,imports:[F],template:'<header>\n <div class="header-top">\n <div class="main-title">\n <div class="main-title-left-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="main-title-text">\n @if (state.primary() === \'STATS\') {\n STATS\n } @else if (state.primary() === \'ITEMS\') {\n ITEMS\n } @else if (state.primary() === \'DATA\') {\n DATA\n }\n </div>\n <div class="main-title-right-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n </div>\n <div class="hp-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="ap-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n <div class="xp-title-line center-line">\n <div class="bottom-half-line"></div>\n </div>\n </div>\n <div class="header-content">\n <button\n type="button"\n class="stats stat-button"\n (click)="openStatModal(\'LVL\')"\n >\n <span>LVL</span> {{ settings.userLevel() }}\n </button>\n <button type="button" class="hp stat-button" (click)="openStatModal(\'HP\')">\n <span>HP</span>\n <span>{{ settings.userHealth() }} / {{ settings.userHealthMax() }}</span>\n </button>\n <button type="button" class="ap stat-button" (click)="openStatModal(\'AP\')">\n <span>AP</span>\n {{ settings.userActionPoints() }} / {{ settings.userActionPointsMax() }}\n </button>\n <button type="button" class="xp stat-button" (click)="openStatModal(\'XP\')">\n <span>XP</span>\n {{ settings.userExperience() }} /\n {{ settings.userExperienceNextLevel() }}\n </button>\n </div>\n</header>\n<pip-boy-stat-edit-modal\n (closeResult)="closeStatModal()"\n (save)="saveStatModal($event)"\n [fields]="statModalFields()"\n [open]="statModal() !== null"\n [title]="statModalTitle()"\n/>\n',styles:[':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.center-line{position:relative;height:100%;overflow:visible}.center-line:before{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:2px;background:#0fbb6b}.bottom-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.bottom-half-line:before{content:"";position:absolute;top:50%;bottom:-1.25rem;width:2px;z-index:2;background:linear-gradient(to bottom,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}header{width:100%;box-sizing:border-box;display:flex;flex-direction:column;flex:0 0 auto;min-height:0;padding:0 1rem}header>.header-top,header>.header-content{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.25rem;padding:0}header>.header-top{height:2.25rem;align-items:center;text-transform:uppercase;overflow:visible}header>.header-top>.main-title{display:flex;align-items:center;justify-content:center;gap:.5rem;height:100%;overflow:visible}header>.header-top>.main-title>.main-title-left-line,header>.header-top>.main-title>.main-title-right-line{flex-grow:1;min-width:2rem;height:100%;position:relative;overflow:visible}header>.header-top>.main-title>.main-title-text{font-size:clamp(1.25rem,1.25rem + (1.5rem - 1.25rem) * (100vw - 360px) / (1200px - 360px),1.5rem);flex-grow:0;letter-spacing:.1em;white-space:nowrap;line-height:1}header>.header-top .main-title-left-line .bottom-half-line:before{left:0}header>.header-top .main-title-right-line .bottom-half-line:before{right:0}header>.header-top .hp-title-line,header>.header-top .ap-title-line,header>.header-top .xp-title-line{overflow:visible}header>.header-top .hp-title-line .bottom-half-line:before,header>.header-top .ap-title-line .bottom-half-line:before,header>.header-top .xp-title-line .bottom-half-line:before{right:0}header>.header-content{box-sizing:border-box;margin-top:-.5rem;font-size:calc(clamp(.9rem,.9rem + .2rem * (100vw - 360px) / 840px,1.1rem) * (1 + (var(--list-font-scale, 1) - 1) * .6))}header>.header-content>.stats,header>.header-content>.hp,header>.header-content>.ap,header>.header-content>.xp{display:flex;justify-content:flex-end;padding:0 1rem;gap:1rem}header>.header-content>.stat-button{align-items:center;background:transparent;border:none;color:inherit;cursor:pointer;font:inherit;text-align:right;text-transform:uppercase}header>.header-content>.stat-button:hover{background:#0fbb6b14}\n']}]}]});class O{dbPromise=this.openDb();soundUrls=o({},...ngDevMode?[{debugName:"soundUrls"}]:[]);soundLabels=o({},...ngDevMode?[{debugName:"soundLabels"}]:[]);metaLoading=new Set;getSoundLabel(e){if(!e)return null;const t=this.soundLabels()[e];return t||(this.loadSoundMeta(e),null)}async playSound(e){if(!e)return;const t=this.soundUrls()[e];if(t){const e=new Audio(t);return void await e.play().catch(()=>{})}const a=await this.getRecord(e);if(!a)return;const n=URL.createObjectURL(a.blob);this.cacheUrl(e,n),this.cacheLabel(e,a.fileName);const o=new Audio(n);await o.play().catch(()=>{})}async saveFile(e){const t=this.createId(),a={id:t,fileName:e.name,mime:e.type||"application/octet-stream"};return await this.putRecord({...a,blob:e}),this.cacheUrl(t,URL.createObjectURL(e)),this.cacheLabel(t,a.fileName),a}async saveBlobWithId(e,t,a,n){await this.putRecord({id:e,blob:t,fileName:a,mime:n}),this.cacheUrl(e,URL.createObjectURL(t)),this.cacheLabel(e,a)}async getRecord(e){const t=await this.dbPromise;return new Promise((a,n)=>{const o=t.transaction("sounds","readonly").objectStore("sounds").get(e);o.onsuccess=()=>{a(o.result??null)},o.onerror=()=>n(o.error)})}extensionFromMime(e){switch(e){case"audio/mpeg":case"audio/mp3":return".mp3";case"audio/wav":case"audio/x-wav":case"audio/wave":return".wav";case"audio/ogg":return".ogg";case"audio/aac":return".aac";case"audio/mp4":case"audio/x-m4a":return".m4a";case"audio/webm":return".webm";default:return""}}cacheUrl(e,t){this.soundUrls.update(a=>({...a,[e]:t}))}cacheLabel(e,t){this.soundLabels.update(a=>({...a,[e]:t}))}async loadSoundMeta(e){if(!this.metaLoading.has(e)){this.metaLoading.add(e);try{const t=await this.getRecord(e);if(!t)return;this.cacheLabel(e,t.fileName)}finally{this.metaLoading.delete(e)}}}async putRecord(e){const t=await this.dbPromise;return new Promise((a,n)=>{const o=t.transaction("sounds","readwrite").objectStore("sounds").put(e);o.onsuccess=()=>a(),o.onerror=()=>n(o.error)})}openDb(){return new Promise((e,t)=>{const a=indexedDB.open("pipBoy3000Sounds",1);a.onupgradeneeded=()=>{const e=a.result;e.objectStoreNames.contains("sounds")||e.createObjectStore("sounds",{keyPath:"id"})},a.onsuccess=()=>e(a.result),a.onerror=()=>t(a.error)})}createId(){return"undefined"!=typeof crypto&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:O,deps:[],target:e.ɵɵFactoryTarget.Injectable});static"ɵprov"=e.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:O,providedIn:"root"})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:O,decorators:[{type:i,args:[{providedIn:"root"}]}]});class z{category="WEAPONS";settings=s(B);imageStore=s(x);soundStore=s(O);showStatEditModal=o(!1,...ngDevMode?[{debugName:"showStatEditModal"}]:[]);editMode=o("EDIT",...ngDevMode?[{debugName:"editMode"}]:[]);modalName=o("",...ngDevMode?[{debugName:"modalName"}]:[]);modalImageId=o(null,...ngDevMode?[{debugName:"modalImageId"}]:[]);modalValues=o({damage:0,weight:0,value:0,quantity:0},...ngDevMode?[{debugName:"modalValues"}]:[]);modalTextValues=o({},...ngDevMode?[{debugName:"modalTextValues"}]:[]);selectedItem=c(()=>{const e=this.getEquippedId();return null===e?null:this.getItems().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedItem"}]:[]);itemNames=c(()=>{const e=this.getSourceNames();return Array.from(new Set(e)).sort()},...ngDevMode?[{debugName:"itemNames"}]:[]);editStatModalTitle=c(()=>{if("ADD"===this.editMode())return this.modalTitle();const e=this.selectedItem();return e?`Edit ${e.name}`:"Edit Stats"},...ngDevMode?[{debugName:"editStatModalTitle"}]:[]);statEditFields=c(()=>{const e=this.modalValues();switch(this.category){case"WEAPONS":return[{key:"damage",label:"Damage",value:e.damage??0},{key:"weight",label:"Weight",value:e.weight??0},{key:"value",label:"Value",value:e.value??0}];case"APPAREL":return[{key:"damage",label:"DR",value:e.damage??0},{key:"weight",label:"WG",value:e.weight??0},{key:"value",label:"VAL",value:e.value??0},{key:"quantity",label:"QTY",value:e.quantity??0}];default:return[{key:"weight",label:"WG",value:e.weight??0},{key:"value",label:"VAL",value:e.value??0},{key:"quantity",label:"QTY",value:e.quantity??0}]}},...ngDevMode?[{debugName:"statEditFields"}]:[]);textEditFields=c(()=>{const e=this.modalTextValues();return"AID"===this.category?[{key:"effects",label:"Effects",value:e.effects??"",multiline:!0}]:[]},...ngDevMode?[{debugName:"textEditFields"}]:[]);statRows=c(()=>{const e=this.selectedItem();return e?"WEAPONS"===this.category?[{key:"damage",label:"Damage",value:e.damage??"--"},{key:"weight",label:"Weight",value:e.weight??"--"},{key:"value",label:"Value",value:e.value??"--"}]:"APPAREL"===this.category?[{key:"damage",label:"DR",value:e.damage??"--"},{key:"weight",label:"WG",value:e.weight??"--"},{key:"value",label:"VAL",value:e.value??"--"}]:"AID"===this.category?[{key:"effects",label:"Effects",value:e.effects??"--"},{key:"weight",label:"WG",value:e.weight??"--"},{key:"value",label:"VAL",value:e.value??"--"}]:[{key:"weight",label:"WG",value:e.weight??"--"},{key:"value",label:"VAL",value:e.value??"--"}]:[]},...ngDevMode?[{debugName:"statRows"}]:[]);modalTitle=c(()=>{switch(this.category){case"WEAPONS":return"Add Weapon";case"APPAREL":return"Add Apparel";case"AID":return"Add Aid";case"MISC":return"Add Misc";case"AMMO":return"Add Ammo";default:return"Add Item"}},...ngDevMode?[{debugName:"modalTitle"}]:[]);openAddModal(){this.settings.editLockEnabled()||(this.editMode.set("ADD"),this.modalName.set(""),this.modalImageId.set(null),this.modalValues.set({damage:0,weight:0,value:0,quantity:this.defaultQuantity()}),this.modalTextValues.set({}),this.showStatEditModal.set(!0))}openStatEditModal(){if(this.settings.editLockEnabled())return;if(!this.selectedItem())return;this.playClickSound();const e=this.selectedItem();e&&(this.modalName.set(e.name),this.modalImageId.set(e.imageId??null),this.modalValues.set({damage:e.damage??0,weight:e.weight??0,value:e.value??0,quantity:this.normalizeQuantity(e.quantity)}),this.modalTextValues.set({effects:e.effects??""})),this.editMode.set("EDIT"),this.showStatEditModal.set(!0)}closeStatEditModal(){this.showStatEditModal.set(!1)}selectItem(e){const t=this.getEquippedId();this.setEquippedId(t===e?null:e),this.playClickSound()}async saveStatEditModal(e){const t=e.name?.trim()??"";if(!t)return;const a=this.selectedItem();let n;if(e.removeImage)n=void 0;else if(e.imageFile){const t=await this.imageStore.saveFile(e.imageFile);n=t.id}else n=a?.imageId;if("ADD"===this.editMode()){const a=this.supportsQuantity()?this.normalizeQuantity(e.values.quantity):void 0,o=this.getNextItemId();return this.updateItems(i=>[...i,{id:o,name:t,damage:this.normalizeStatValue(e.values.damage),weight:this.normalizeStatValue(e.values.weight),value:this.normalizeStatValue(e.values.value),imageId:n,effects:e.textValues?.effects,...this.supportsQuantity()?{quantity:a}:{}}]),this.setEquippedId(o),void this.closeStatEditModal()}const o=this.getEquippedId();null!==o&&(this.updateItems(a=>a.map(a=>a.id!==o?a:{...a,name:t,damage:this.normalizeStatValue(e.values.damage,a.damage),weight:this.normalizeStatValue(e.values.weight,a.weight),value:this.normalizeStatValue(e.values.value,a.value),imageId:n,...this.supportsQuantity()?{quantity:this.normalizeQuantity(e.values.quantity)}:{},effects:e.textValues?.effects??("AID"===this.category?a.effects:void 0)})),this.closeStatEditModal())}handleNameChange(e){if(this.modalName.set(e),"ADD"!==this.editMode())return;const t=this.getDefaultsForName(e);t&&("number"==typeof t.damage&&this.modalValues.set({...this.modalValues(),damage:t.damage}),"number"==typeof t.weight&&this.modalValues.set({...this.modalValues(),weight:t.weight}),"number"==typeof t.value&&this.modalValues.set({...this.modalValues(),value:t.value}),"string"==typeof t.effects&&this.modalTextValues.set({...this.modalTextValues(),effects:t.effects}))}dropSelected(){if(this.settings.editLockEnabled())return;const e=this.getEquippedId();null!==e&&(this.updateItems(t=>t.filter(t=>t.id!==e)),this.setEquippedId(null))}moveSelected(e){if(this.settings.editLockEnabled())return;const t=this.getEquippedId();null!==t&&this.updateItems(a=>{const n=a.findIndex(e=>e.id===t);if(-1===n)return a;const o=n+e;if(o<0||o>=a.length)return a;const i=a.slice(),[r]=i.splice(n,1);return i.splice(o,0,r),i})}displayItemName(e){const t="number"==typeof e.quantity&&Number.isFinite(e.quantity)?e.quantity:0;return this.supportsQuantity()&&t>1?`${e.name} (${t})`:e.name}getItems(){switch(this.category){case"WEAPONS":return this.settings.weaponItems();case"APPAREL":return this.settings.apparelItems();case"AID":return this.settings.aidItems();case"MISC":return this.settings.miscItems();case"AMMO":return this.settings.ammoItems();default:return[]}}updateItems(e){switch(this.category){case"WEAPONS":this.settings.weaponItems.update(e);break;case"APPAREL":this.settings.apparelItems.update(e);break;case"AID":this.settings.aidItems.update(e);break;case"MISC":this.settings.miscItems.update(e);break;case"AMMO":this.settings.ammoItems.update(e)}}getEquippedId(){switch(this.category){case"WEAPONS":return this.settings.equippedWeaponId();case"APPAREL":return this.settings.equippedApparelId();case"AID":return this.settings.equippedAidId();case"MISC":return this.settings.equippedMiscId();case"AMMO":return this.settings.equippedAmmoId();default:return null}}setEquippedId(e){switch(this.category){case"WEAPONS":this.settings.equippedWeaponId.set(e);break;case"APPAREL":this.settings.equippedApparelId.set(e);break;case"AID":this.settings.equippedAidId.set(e);break;case"MISC":this.settings.equippedMiscId.set(e);break;case"AMMO":this.settings.equippedAmmoId.set(e)}}getSourceNames(){switch(this.category){case"WEAPONS":return L.map(e=>e.name).filter(e=>e);case"APPAREL":return P.map(e=>e.name).filter(e=>e);case"AID":return k.map(e=>e.name).filter(e=>e);case"MISC":return M.map(e=>e.name).filter(e=>e);case"AMMO":return S.map(e=>e.name).filter(e=>e);default:return[]}}getNextItemId(){return this.getItems().reduce((e,t)=>Math.max(e,t.id),0)+1}normalizeStatValue(e,t){return"number"==typeof e&&Number.isFinite(e)?e:t}normalizeQuantity(e){return"number"==typeof e&&Number.isFinite(e)?Math.max(1,Math.floor(e)):1}playClickSound(){this.soundStore.playSound(this.settings.clickSoundId())}supportsQuantity(){return"APPAREL"===this.category||"AID"===this.category||"MISC"===this.category||"AMMO"===this.category}defaultQuantity(){return this.supportsQuantity()?1:0}getDefaultsForName(e){if("WEAPONS"===this.category){const t=L.find(t=>t.name===e);return t?{damage:t.damage,weight:t.weight,value:t.value}:null}if("APPAREL"===this.category){const t=P.find(t=>t.name===e);return t?{damage:t.dr,weight:t.wg,value:t.val}:null}if("AID"===this.category){const t=k.find(t=>t.name===e);return t?{weight:t.wg,value:t.val,effects:t.effects}:null}if("MISC"===this.category){const t=M.find(t=>t.name===e);return t?{weight:t.wg,value:t.val}:null}if("AMMO"===this.category){const t=S.find(t=>t.name===e);return t?{weight:t.wg,value:t.val}:null}return null}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:z,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:z,isStandalone:!0,selector:"pip-boy-inventory-layout",inputs:{category:"category"},ngImport:e,template:'<div class="resource-layout">\n <div class="resource-list">\n <ul class="resource-list-items">\n @for (item of getItems(); track item.id) {\n <li>\n <button\n type="button"\n class="resource-list-item"\n [class.is-selected]="getEquippedId() === item.id"\n (click)="selectItem(item.id)"\n >\n {{ displayItemName(item) }}\n </button>\n </li>\n } @empty {\n <li class="is-empty">No items added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="inventory-actions">\n <button type="button" class="resource-add" (click)="openAddModal()">\n + Add\n </button>\n @if (getEquippedId() !== null) {\n <button\n type="button"\n class="resource-edit"\n (click)="openStatEditModal()"\n >\n Edit\n </button>\n <button type="button" class="resource-drop" (click)="dropSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="resources-detail">\n @if (getItems().length > 0 && selectedItem()) {\n <button\n type="button"\n class="resource-image"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openStatEditModal()"\n >\n @if (selectedItem()?.imageId) {\n <img\n [src]="imageStore.getImageUrl(selectedItem()?.imageId)"\n alt="Selected item"\n />\n }\n </button>\n <div class="resource-stats">\n @for (row of statRows(); track row.key) {\n <button\n type="button"\n class="resource-stat"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openStatEditModal()"\n >\n <span>{{ row.label }}</span>\n <span>{{ row.value }}</span>\n </button>\n }\n </div>\n }\n </div>\n</div>\n<pip-boy-stat-edit-modal\n (closeResult)="closeStatEditModal()"\n (nameChange)="handleNameChange($event)"\n (save)="saveStatEditModal($event)"\n [open]="showStatEditModal()"\n [title]="editStatModalTitle()"\n [name]="modalName()"\n nameLabel="Item Name"\n [nameOptions]="itemNames()"\n [showName]="true"\n [imageUrl]="imageStore.getImageUrl(modalImageId())"\n [showImage]="true"\n [textFields]="textEditFields()"\n [fields]="statEditFields()"\n/>\n',styles:[':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{width:100%;height:100%;display:block}.resource-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.resource-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.resource-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.resource-list-items li{margin:0;padding:0;font-size:inherit}.resource-list-items .is-empty{opacity:.6}.resource-list-item{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;width:100%}.resource-list-item:hover{background:#0fbb6b1f}.resource-list-item.is-selected{background:#0fbb6b2e}.resource-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.inventory-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.resource-add{background:#0fbb6b14;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-add:hover{background:#0fbb6b2e}.resource-edit{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-edit:hover{background:#0fbb6b1f}.resource-drop{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-drop:hover{background:#0fbb6b1f}.resource-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.resource-move:hover{background:#0fbb6b1f}.resources-detail{display:flex;flex:1 1 45%;flex-direction:column;gap:1rem;height:100%;min-height:0;overflow:auto;padding-right:1rem}.resource-image{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1 1 auto;flex-direction:column;min-height:60%;justify-content:flex-start;padding:1rem;text-transform:uppercase;width:100%}.resource-image span{margin-top:auto;opacity:.7}.resource-image img{align-self:center;max-height:100%;max-width:100%;object-fit:contain;padding:0}.resource-image.is-locked{cursor:default;pointer-events:none}.resource-stats{display:flex;flex-direction:column;gap:.5rem;margin-top:auto;padding:.75rem;font-size:calc(1.15rem * var(--list-font-scale, 1))}.resource-stat{background:transparent;border:1px solid transparent;color:#0fbb6b;cursor:pointer;display:flex;justify-content:space-between;padding:.2rem .35rem;text-align:left;text-transform:uppercase;width:100%;font-size:inherit}.resource-stat:hover{background:#0fbb6b1f}.resource-stat.is-locked{cursor:default;pointer-events:none}.resource-stat span{padding:.25rem}.resource-stat--name{font-size:calc(clamp(.9rem,.9rem + .15rem * (100vw - 360px) / 840px,1.05rem) * var(--list-font-scale, 1));letter-spacing:.04em}@media(max-width:720px),(max-height:560px){.inventory-actions{gap:.35rem;margin:0 .75rem .75rem}.resource-add,.resource-edit,.resource-drop{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.resource-move{flex:0 0 1.6rem;height:2.1rem}}\n'],dependencies:[{kind:"component",type:F,selector:"pip-boy-stat-edit-modal",inputs:["open","title","name","nameLabel","showName","nameOptions","imageUrl","showImage","fields","textFields"],outputs:["closeResult","save","nameChange"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:z,decorators:[{type:n,args:[{selector:"pip-boy-inventory-layout",standalone:!0,imports:[F],template:'<div class="resource-layout">\n <div class="resource-list">\n <ul class="resource-list-items">\n @for (item of getItems(); track item.id) {\n <li>\n <button\n type="button"\n class="resource-list-item"\n [class.is-selected]="getEquippedId() === item.id"\n (click)="selectItem(item.id)"\n >\n {{ displayItemName(item) }}\n </button>\n </li>\n } @empty {\n <li class="is-empty">No items added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="inventory-actions">\n <button type="button" class="resource-add" (click)="openAddModal()">\n + Add\n </button>\n @if (getEquippedId() !== null) {\n <button\n type="button"\n class="resource-edit"\n (click)="openStatEditModal()"\n >\n Edit\n </button>\n <button type="button" class="resource-drop" (click)="dropSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="resources-detail">\n @if (getItems().length > 0 && selectedItem()) {\n <button\n type="button"\n class="resource-image"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openStatEditModal()"\n >\n @if (selectedItem()?.imageId) {\n <img\n [src]="imageStore.getImageUrl(selectedItem()?.imageId)"\n alt="Selected item"\n />\n }\n </button>\n <div class="resource-stats">\n @for (row of statRows(); track row.key) {\n <button\n type="button"\n class="resource-stat"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openStatEditModal()"\n >\n <span>{{ row.label }}</span>\n <span>{{ row.value }}</span>\n </button>\n }\n </div>\n }\n </div>\n</div>\n<pip-boy-stat-edit-modal\n (closeResult)="closeStatEditModal()"\n (nameChange)="handleNameChange($event)"\n (save)="saveStatEditModal($event)"\n [open]="showStatEditModal()"\n [title]="editStatModalTitle()"\n [name]="modalName()"\n nameLabel="Item Name"\n [nameOptions]="itemNames()"\n [showName]="true"\n [imageUrl]="imageStore.getImageUrl(modalImageId())"\n [showImage]="true"\n [textFields]="textEditFields()"\n [fields]="statEditFields()"\n/>\n',styles:[':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{width:100%;height:100%;display:block}.resource-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.resource-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.resource-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.resource-list-items li{margin:0;padding:0;font-size:inherit}.resource-list-items .is-empty{opacity:.6}.resource-list-item{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;width:100%}.resource-list-item:hover{background:#0fbb6b1f}.resource-list-item.is-selected{background:#0fbb6b2e}.resource-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.inventory-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.resource-add{background:#0fbb6b14;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-add:hover{background:#0fbb6b2e}.resource-edit{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-edit:hover{background:#0fbb6b1f}.resource-drop{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-drop:hover{background:#0fbb6b1f}.resource-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.resource-move:hover{background:#0fbb6b1f}.resources-detail{display:flex;flex:1 1 45%;flex-direction:column;gap:1rem;height:100%;min-height:0;overflow:auto;padding-right:1rem}.resource-image{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1 1 auto;flex-direction:column;min-height:60%;justify-content:flex-start;padding:1rem;text-transform:uppercase;width:100%}.resource-image span{margin-top:auto;opacity:.7}.resource-image img{align-self:center;max-height:100%;max-width:100%;object-fit:contain;padding:0}.resource-image.is-locked{cursor:default;pointer-events:none}.resource-stats{display:flex;flex-direction:column;gap:.5rem;margin-top:auto;padding:.75rem;font-size:calc(1.15rem * var(--list-font-scale, 1))}.resource-stat{background:transparent;border:1px solid transparent;color:#0fbb6b;cursor:pointer;display:flex;justify-content:space-between;padding:.2rem .35rem;text-align:left;text-transform:uppercase;width:100%;font-size:inherit}.resource-stat:hover{background:#0fbb6b1f}.resource-stat.is-locked{cursor:default;pointer-events:none}.resource-stat span{padding:.25rem}.resource-stat--name{font-size:calc(clamp(.9rem,.9rem + .15rem * (100vw - 360px) / 840px,1.05rem) * var(--list-font-scale, 1));letter-spacing:.04em}@media(max-width:720px),(max-height:560px){.inventory-actions{gap:.35rem;margin:0 .75rem .75rem}.resource-add,.resource-edit,.resource-drop{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.resource-move{flex:0 0 1.6rem;height:2.1rem}}\n']}]}],propDecorators:{category:[{type:m}]}});class q{constructor(){r(()=>{this.open()&&(this.draftName.set(this.name()),this.draftDescription.set(this.description()),this.draftValue.set(this.value()),this.draftImageUrl.set(this.imageUrl()),this.draftImageName.set(null),this.draftImageFile.set(null),this.removedImage.set(!1),this.clearPreviewUrl())})}static nextId=0;open=t(!1,...ngDevMode?[{debugName:"open"}]:[]);title=t("Edit Entry",...ngDevMode?[{debugName:"title"}]:[]);name=t("",...ngDevMode?[{debugName:"name"}]:[]);itemNames=t([],...ngDevMode?[{debugName:"itemNames"}]:[]);description=t("",...ngDevMode?[{debugName:"description"}]:[]);value=t(0,...ngDevMode?[{debugName:"value"}]:[]);valueLabel=t("Value",...ngDevMode?[{debugName:"valueLabel"}]:[]);valueMin=t(null,...ngDevMode?[{debugName:"valueMin"}]:[]);valueMax=t(null,...ngDevMode?[{debugName:"valueMax"}]:[]);showValue=t(!0,...ngDevMode?[{debugName:"showValue"}]:[]);imageUrl=t(null,...ngDevMode?[{debugName:"imageUrl"}]:[]);closeResult=u();save=u();draftDescription=o("",...ngDevMode?[{debugName:"draftDescription"}]:[]);draftName=o("",...ngDevMode?[{debugName:"draftName"}]:[]);draftValue=o(0,...ngDevMode?[{debugName:"draftValue"}]:[]);draftImageName=o(null,...ngDevMode?[{debugName:"draftImageName"}]:[]);draftImageUrl=o(null,...ngDevMode?[{debugName:"draftImageUrl"}]:[]);draftImageFile=o(null,...ngDevMode?[{debugName:"draftImageFile"}]:[]);removedImage=o(!1,...ngDevMode?[{debugName:"removedImage"}]:[]);nameListId="stat-entry-name-"+q.nextId++;previewUrl=null;closeModal(){this.clearPreviewUrl(),this.closeResult.emit()}updateName(e){this.draftName.set(e.target.value)}updateDescription(e){this.draftDescription.set(e.target.value)}updateValue(e){const t=Number(e.target.value);Number.isFinite(t)&&this.draftValue.set(this.clampValue(t))}onImageSelected(e){const t=e.target,a=t.files?.[0]??null;this.draftImageName.set(a?a.name:null),a&&(this.removedImage.set(!1),this.draftImageFile.set(a),this.setPreviewUrl(URL.createObjectURL(a)),t.value="")}removeImage(){this.draftImageName.set(null),this.draftImageUrl.set(null),this.draftImageFile.set(null),this.removedImage.set(!0),this.clearPreviewUrl()}submit(e){e?.preventDefault();const t={name:this.draftName(),description:this.draftDescription(),imageFile:this.draftImageFile(),removeImage:this.removedImage()};this.showValue()&&(t.value=this.clampValue(this.draftValue())),this.clearPreviewUrl(),this.save.emit(t),this.closeResult.emit()}clampValue(e){let t=e;const a=this.valueMin(),n=this.valueMax();return"number"==typeof a&&(t=Math.max(a,t)),"number"==typeof n&&(t=Math.min(n,t)),t}setPreviewUrl(e){this.clearPreviewUrl(),this.previewUrl=e,this.draftImageUrl.set(e)}clearPreviewUrl(){this.previewUrl&&(URL.revokeObjectURL(this.previewUrl),this.previewUrl=null)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:q,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:q,isStandalone:!0,selector:"pip-boy-stat-entry-modal",inputs:{open:{classPropertyName:"open",publicName:"open",isSignal:!0,isRequired:!1,transformFunction:null},title:{classPropertyName:"title",publicName:"title",isSignal:!0,isRequired:!1,transformFunction:null},name:{classPropertyName:"name",publicName:"name",isSignal:!0,isRequired:!1,transformFunction:null},itemNames:{classPropertyName:"itemNames",publicName:"itemNames",isSignal:!0,isRequired:!1,transformFunction:null},description:{classPropertyName:"description",publicName:"description",isSignal:!0,isRequired:!1,transformFunction:null},value:{classPropertyName:"value",publicName:"value",isSignal:!0,isRequired:!1,transformFunction:null},valueLabel:{classPropertyName:"valueLabel",publicName:"valueLabel",isSignal:!0,isRequired:!1,transformFunction:null},valueMin:{classPropertyName:"valueMin",publicName:"valueMin",isSignal:!0,isRequired:!1,transformFunction:null},valueMax:{classPropertyName:"valueMax",publicName:"valueMax",isSignal:!0,isRequired:!1,transformFunction:null},showValue:{classPropertyName:"showValue",publicName:"showValue",isSignal:!0,isRequired:!1,transformFunction:null},imageUrl:{classPropertyName:"imageUrl",publicName:"imageUrl",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{closeResult:"closeResult",save:"save"},ngImport:e,template:'@if (open()) {\n <div\n class="stat-entry-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="stat-entry-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title() }}</header>\n <form (submit)="submit($event)">\n <div class="stat-entry-modal-body">\n <label class="stat-entry-modal-field">\n <span>Name</span>\n <input\n type="text"\n [attr.list]="nameListId"\n [value]="draftName()"\n (input)="updateName($event)"\n />\n </label>\n @if (itemNames().length) {\n <datalist [id]="nameListId">\n @for (name of itemNames(); track name) {\n <option [value]="name"></option>\n }\n </datalist>\n }\n @if (showValue()) {\n <label class="stat-entry-modal-field">\n <span>{{ valueLabel() }}</span>\n <input\n type="number"\n [attr.min]="valueMin()"\n [attr.max]="valueMax()"\n [value]="draftValue()"\n (input)="updateValue($event)"\n />\n </label>\n }\n <label\n class="stat-entry-modal-field stat-entry-modal-field--description"\n >\n <span>Description</span>\n <textarea\n rows="6"\n [value]="draftDescription()"\n (input)="updateDescription($event)"\n ></textarea>\n </label>\n <div class="stat-entry-modal-image">\n <button\n type="button"\n class="stat-entry-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="stat-entry-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Entry preview" />\n }\n </div>\n </div>\n <div class="stat-entry-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.stat-entry-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.stat-entry-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:26rem;width:min(90vw,26rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.stat-entry-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.stat-entry-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.stat-entry-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.stat-entry-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.stat-entry-modal-field input,.stat-entry-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.stat-entry-modal-field input:focus,.stat-entry-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.stat-entry-modal-field textarea{min-height:6rem;resize:vertical;text-transform:none}.stat-entry-modal-image{display:flex;flex-direction:column;gap:.75rem}.stat-entry-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.stat-entry-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:8rem;object-fit:contain;padding:.5rem}.stat-entry-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.stat-entry-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-entry-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.stat-entry-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-entry-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.stat-entry-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.stat-entry-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:q,decorators:[{type:n,args:[{selector:"pip-boy-stat-entry-modal",standalone:!0,template:'@if (open()) {\n <div\n class="stat-entry-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="stat-entry-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title() }}</header>\n <form (submit)="submit($event)">\n <div class="stat-entry-modal-body">\n <label class="stat-entry-modal-field">\n <span>Name</span>\n <input\n type="text"\n [attr.list]="nameListId"\n [value]="draftName()"\n (input)="updateName($event)"\n />\n </label>\n @if (itemNames().length) {\n <datalist [id]="nameListId">\n @for (name of itemNames(); track name) {\n <option [value]="name"></option>\n }\n </datalist>\n }\n @if (showValue()) {\n <label class="stat-entry-modal-field">\n <span>{{ valueLabel() }}</span>\n <input\n type="number"\n [attr.min]="valueMin()"\n [attr.max]="valueMax()"\n [value]="draftValue()"\n (input)="updateValue($event)"\n />\n </label>\n }\n <label\n class="stat-entry-modal-field stat-entry-modal-field--description"\n >\n <span>Description</span>\n <textarea\n rows="6"\n [value]="draftDescription()"\n (input)="updateDescription($event)"\n ></textarea>\n </label>\n <div class="stat-entry-modal-image">\n <button\n type="button"\n class="stat-entry-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="stat-entry-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Entry preview" />\n }\n </div>\n </div>\n <div class="stat-entry-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.stat-entry-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.stat-entry-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:26rem;width:min(90vw,26rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.stat-entry-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.stat-entry-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.stat-entry-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.stat-entry-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.stat-entry-modal-field input,.stat-entry-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.stat-entry-modal-field input:focus,.stat-entry-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.stat-entry-modal-field textarea{min-height:6rem;resize:vertical;text-transform:none}.stat-entry-modal-image{display:flex;flex-direction:column;gap:.75rem}.stat-entry-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.stat-entry-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:8rem;object-fit:contain;padding:.5rem}.stat-entry-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.stat-entry-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-entry-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.stat-entry-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.stat-entry-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.stat-entry-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.stat-entry-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],ctorParameters:()=>[],propDecorators:{open:[{type:e.Input,args:[{isSignal:!0,alias:"open",required:!1}]}],title:[{type:e.Input,args:[{isSignal:!0,alias:"title",required:!1}]}],name:[{type:e.Input,args:[{isSignal:!0,alias:"name",required:!1}]}],itemNames:[{type:e.Input,args:[{isSignal:!0,alias:"itemNames",required:!1}]}],description:[{type:e.Input,args:[{isSignal:!0,alias:"description",required:!1}]}],value:[{type:e.Input,args:[{isSignal:!0,alias:"value",required:!1}]}],valueLabel:[{type:e.Input,args:[{isSignal:!0,alias:"valueLabel",required:!1}]}],valueMin:[{type:e.Input,args:[{isSignal:!0,alias:"valueMin",required:!1}]}],valueMax:[{type:e.Input,args:[{isSignal:!0,alias:"valueMax",required:!1}]}],showValue:[{type:e.Input,args:[{isSignal:!0,alias:"showValue",required:!1}]}],imageUrl:[{type:e.Input,args:[{isSignal:!0,alias:"imageUrl",required:!1}]}],closeResult:[{type:e.Output,args:["closeResult"]}],save:[{type:e.Output,args:["save"]}]}});class H{constructor(){r(()=>{const e=this.items(),t=this.selectedId();e.length?null!==t&&e.some(e=>e.id===t)||this.selectedId.set(e[0].id):null!==t&&this.selectedId.set(null)})}category="SPECIAL";valueLabel="Value";valueMin=null;valueMax=null;settings=s(B);imageStore=s(x);soundStore=s(O);showEditModal=o(!1,...ngDevMode?[{debugName:"showEditModal"}]:[]);editMode=o("EDIT",...ngDevMode?[{debugName:"editMode"}]:[]);selectedId=o(null,...ngDevMode?[{debugName:"selectedId"}]:[]);items=c(()=>this.getItems(),...ngDevMode?[{debugName:"items"}]:[]);selectedItem=c(()=>{const e=this.selectedId();return null===e?null:this.items().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedItem"}]:[]);itemNames=c(()=>{const e=this.getSourceNames();return Array.from(new Set(e)).sort()},...ngDevMode?[{debugName:"itemNames"}]:[]);editModalTitle=c(()=>{if("ADD"===this.editMode())return"Add Entry";const e=this.selectedItem();return e?`Edit ${e.name}`:"Edit Entry"},...ngDevMode?[{debugName:"editModalTitle"}]:[]);modalName=c(()=>{const e=this.selectedItem();return"ADD"===this.editMode()?"":e?.name??""},...ngDevMode?[{debugName:"modalName"}]:[]);modalDescription=c(()=>{const e=this.selectedItem();return"ADD"===this.editMode()?"":e?.description??""},...ngDevMode?[{debugName:"modalDescription"}]:[]);modalValue=c(()=>{if("ADD"===this.editMode())return this.valueMin??0;const e=this.selectedItem();return e?.value??0},...ngDevMode?[{debugName:"modalValue"}]:[]);modalImage=c(()=>{const e=this.selectedItem();return"ADD"===this.editMode()?null:this.imageStore.getImageUrl(e?.imageId??null)},...ngDevMode?[{debugName:"modalImage"}]:[]);openAddModal(){this.settings.editLockEnabled()||(this.editMode.set("ADD"),this.showEditModal.set(!0))}openEditModal(){this.settings.editLockEnabled()||this.selectedItem()&&(this.playClickSound(),this.editMode.set("EDIT"),this.showEditModal.set(!0))}closeEditModal(){this.showEditModal.set(!1)}selectItem(e){this.selectedId.set(e),this.playClickSound()}async saveEditModal(e){const t=e.name.trim();if(!t)return;const a=this.selectedItem();let n;if(e.removeImage)n=void 0;else if(e.imageFile){const t=await this.imageStore.saveFile(e.imageFile);n=t.id}else n=a?.imageId;if("ADD"===this.editMode()){const a=this.getNextItemId(),o=this.valueMin??0;return this.updateItems(i=>[...i,{id:a,name:t,description:e.description,value:this.showValue()&&"number"==typeof e.value?e.value:o,imageId:n}]),this.selectedId.set(a),void this.closeEditModal()}const o=this.selectedId();null!==o&&(this.updateItems(a=>a.map(a=>a.id!==o?a:{...a,name:t,description:e.description,value:"number"==typeof e.value?e.value:a.value,imageId:n})),this.closeEditModal())}dropSelected(){if(this.settings.editLockEnabled())return;const e=this.selectedId();null!==e&&(this.updateItems(t=>t.filter(t=>t.id!==e)),this.selectedId.set(null))}moveSelected(e){if(this.settings.editLockEnabled())return;const t=this.selectedId();null!==t&&this.updateItems(a=>{const n=a.findIndex(e=>e.id===t);if(-1===n)return a;const o=n+e;if(o<0||o>=a.length)return a;const i=a.slice(),[r]=i.splice(n,1);return i.splice(o,0,r),i})}showValue(){return"SPECIAL"===this.category||"SKILLS"===this.category}getItems(){switch(this.category){case"SPECIAL":return this.settings.specialItems();case"SKILLS":return this.settings.skillItems();case"PERKS":return this.settings.perkItems();case"GENERAL":return this.settings.generalItems();default:return[]}}updateItems(e){switch(this.category){case"SPECIAL":this.settings.specialItems.update(e);break;case"SKILLS":this.settings.skillItems.update(e);break;case"PERKS":this.settings.perkItems.update(e);break;case"GENERAL":this.settings.generalItems.update(e)}}getSourceNames(){switch(this.category){case"SPECIAL":return D.map(e=>e.name);case"SKILLS":return R.map(e=>e.name);case"PERKS":return A.map(e=>e.name);default:return[]}}getNextItemId(){return this.items().reduce((e,t)=>Math.max(e,t.id),0)+1}playClickSound(){this.soundStore.playSound(this.settings.clickSoundId())}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:H,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:H,isStandalone:!0,selector:"pip-boy-stats-layout",inputs:{category:"category",valueLabel:"valueLabel",valueMin:"valueMin",valueMax:"valueMax"},ngImport:e,template:'<div class="resource-layout">\n <div class="resource-list">\n <ul class="resource-list-items">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="resource-list-item"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n <span class="resource-list-item-name">{{ item.name }}</span>\n @if (showValue()) {\n <span class="resource-list-item-value">{{ item.value }}</span>\n }\n </button>\n </li>\n } @empty {\n <li class="is-empty">No entries available.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="inventory-actions">\n <button type="button" class="resource-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="resource-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="resource-drop" (click)="dropSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="resources-detail">\n @if (selectedItem()) {\n <button\n type="button"\n class="resource-image"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openEditModal()"\n [attr.aria-label]="\n selectedItem()?.imageId ? \'Edit image\' : \'Select image\'\n "\n >\n @if (selectedItem()?.imageId) {\n <img\n [src]="imageStore.getImageUrl(selectedItem()?.imageId)"\n alt="Selected entry"\n />\n }\n </button>\n <button\n type="button"\n class="resource-description"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openEditModal()"\n [innerHTML]="selectedItem()?.description || \'Add description.\'"\n ></button>\n }\n </div>\n</div>\n<pip-boy-stat-entry-modal\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n [open]="showEditModal()"\n [title]="editModalTitle()"\n [name]="modalName()"\n [itemNames]="itemNames()"\n [description]="modalDescription()"\n [value]="modalValue()"\n [valueLabel]="valueLabel"\n [valueMin]="valueMin"\n [valueMax]="valueMax"\n [showValue]="showValue()"\n [imageUrl]="modalImage()"\n/>\n',styles:[':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{width:100%;height:100%;display:block}.resource-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.resource-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.resource-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.resource-list-items li{margin:0;padding:0;font-size:inherit}.resource-list-items .is-empty{opacity:.6}.resource-list-item{align-items:center;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:flex;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;justify-content:space-between;gap:.75rem;width:100%}.resource-list-item:hover{background:#0fbb6b1f}.resource-list-item.is-selected{background:#0fbb6b2e}.resource-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.resource-list-item-name{flex:1 1 auto}.resource-list-item-value{flex:0 0 auto;min-width:2.5rem;text-align:right}.inventory-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.resource-add{background:#0fbb6b14;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-add:hover{background:#0fbb6b2e}.resource-edit{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-edit:hover{background:#0fbb6b1f}.resource-drop{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-drop:hover{background:#0fbb6b1f}.resource-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.resource-move:hover{background:#0fbb6b1f}.resources-detail{display:flex;flex:1 1 45%;flex-direction:column;gap:1rem;height:100%;min-height:0;overflow:auto;padding-bottom:1rem;padding-right:1rem}.resource-image{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1 1 auto;flex-direction:column;min-height:60%;justify-content:flex-start;padding:1rem;text-transform:uppercase;width:100%}.resource-image span{margin-top:auto;opacity:.7}.resource-image img{align-self:center;max-height:100%;max-width:100%;object-fit:contain;padding:0}.resource-image.is-locked{cursor:default;pointer-events:none}.resource-description{background:transparent;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;display:block;position:relative;padding:.75rem;text-align:left;text-transform:none;width:100%;max-width:100%;margin-bottom:1rem;font-size:calc(1.15rem * var(--list-font-scale, 1));white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere}.resource-description:before,.resource-description:after{content:"";position:absolute;pointer-events:none}.resource-description:before{left:0;right:0;top:0;height:2px;background:#0fbb6b}.resource-description:after{top:0;bottom:auto;right:0;width:2px;height:2rem;background:linear-gradient(to bottom,#0fbb6b,#0fbb6ba6 35%,#0fbb6b59 65%,#0fbb6b00)}.resource-description:hover{background:#0fbb6b14}.resource-description.is-locked{cursor:default;pointer-events:none}@media(max-width:720px),(max-height:560px){.inventory-actions{gap:.35rem;margin:0 .75rem .75rem}.resource-add,.resource-edit,.resource-drop{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.resource-move{flex:0 0 1.6rem;height:2.1rem}}\n'],dependencies:[{kind:"component",type:q,selector:"pip-boy-stat-entry-modal",inputs:["open","title","name","itemNames","description","value","valueLabel","valueMin","valueMax","showValue","imageUrl"],outputs:["closeResult","save"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:H,decorators:[{type:n,args:[{selector:"pip-boy-stats-layout",standalone:!0,imports:[q],template:'<div class="resource-layout">\n <div class="resource-list">\n <ul class="resource-list-items">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="resource-list-item"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n <span class="resource-list-item-name">{{ item.name }}</span>\n @if (showValue()) {\n <span class="resource-list-item-value">{{ item.value }}</span>\n }\n </button>\n </li>\n } @empty {\n <li class="is-empty">No entries available.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="inventory-actions">\n <button type="button" class="resource-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="resource-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="resource-drop" (click)="dropSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="resource-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="resources-detail">\n @if (selectedItem()) {\n <button\n type="button"\n class="resource-image"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openEditModal()"\n [attr.aria-label]="\n selectedItem()?.imageId ? \'Edit image\' : \'Select image\'\n "\n >\n @if (selectedItem()?.imageId) {\n <img\n [src]="imageStore.getImageUrl(selectedItem()?.imageId)"\n alt="Selected entry"\n />\n }\n </button>\n <button\n type="button"\n class="resource-description"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openEditModal()"\n [innerHTML]="selectedItem()?.description || \'Add description.\'"\n ></button>\n }\n </div>\n</div>\n<pip-boy-stat-entry-modal\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n [open]="showEditModal()"\n [title]="editModalTitle()"\n [name]="modalName()"\n [itemNames]="itemNames()"\n [description]="modalDescription()"\n [value]="modalValue()"\n [valueLabel]="valueLabel"\n [valueMin]="valueMin"\n [valueMax]="valueMax"\n [showValue]="showValue()"\n [imageUrl]="modalImage()"\n/>\n',styles:[':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{width:100%;height:100%;display:block}.resource-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.resource-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.resource-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.resource-list-items li{margin:0;padding:0;font-size:inherit}.resource-list-items .is-empty{opacity:.6}.resource-list-item{align-items:center;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:flex;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;justify-content:space-between;gap:.75rem;width:100%}.resource-list-item:hover{background:#0fbb6b1f}.resource-list-item.is-selected{background:#0fbb6b2e}.resource-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.resource-list-item-name{flex:1 1 auto}.resource-list-item-value{flex:0 0 auto;min-width:2.5rem;text-align:right}.inventory-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.resource-add{background:#0fbb6b14;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-add:hover{background:#0fbb6b2e}.resource-edit{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-edit:hover{background:#0fbb6b1f}.resource-drop{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.resource-drop:hover{background:#0fbb6b1f}.resource-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.resource-move:hover{background:#0fbb6b1f}.resources-detail{display:flex;flex:1 1 45%;flex-direction:column;gap:1rem;height:100%;min-height:0;overflow:auto;padding-bottom:1rem;padding-right:1rem}.resource-image{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1 1 auto;flex-direction:column;min-height:60%;justify-content:flex-start;padding:1rem;text-transform:uppercase;width:100%}.resource-image span{margin-top:auto;opacity:.7}.resource-image img{align-self:center;max-height:100%;max-width:100%;object-fit:contain;padding:0}.resource-image.is-locked{cursor:default;pointer-events:none}.resource-description{background:transparent;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;display:block;position:relative;padding:.75rem;text-align:left;text-transform:none;width:100%;max-width:100%;margin-bottom:1rem;font-size:calc(1.15rem * var(--list-font-scale, 1));white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere}.resource-description:before,.resource-description:after{content:"";position:absolute;pointer-events:none}.resource-description:before{left:0;right:0;top:0;height:2px;background:#0fbb6b}.resource-description:after{top:0;bottom:auto;right:0;width:2px;height:2rem;background:linear-gradient(to bottom,#0fbb6b,#0fbb6ba6 35%,#0fbb6b59 65%,#0fbb6b00)}.resource-description:hover{background:#0fbb6b14}.resource-description.is-locked{cursor:default;pointer-events:none}@media(max-width:720px),(max-height:560px){.inventory-actions{gap:.35rem;margin:0 .75rem .75rem}.resource-add,.resource-edit,.resource-drop{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.resource-move{flex:0 0 1.6rem;height:2.1rem}}\n']}]}],ctorParameters:()=>[],propDecorators:{category:[{type:m}],valueLabel:[{type:m}],valueMin:[{type:m}],valueMax:[{type:m}]}});class W{open=!1;title="Confirm";message="This action cannot be undone. Are you sure you want to continue?";confirmLabel="Confirm";cancelLabel="Cancel";confirm=new l;closeResult=new l;closeModal(){this.closeResult.emit()}confirmReset(){this.confirm.emit()}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:W,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:W,isStandalone:!0,selector:"pip-boy-reset-confirm-modal",inputs:{open:"open",title:"title",message:"message",confirmLabel:"confirmLabel",cancelLabel:"cancelLabel"},outputs:{confirm:"confirm",closeResult:"closeResult"},ngImport:e,template:'@if (open) {\n <div\n class="reset-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n role="button"\n tabindex="0"\n >\n <div\n class="reset-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n role="dialog"\n tabindex="-1"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <div class="reset-modal-body">\n <p>{{ message }}</p>\n </div>\n <div class="reset-modal-actions">\n <button type="button" (click)="closeModal()">{{ cancelLabel }}</button>\n <button type="button" (click)="confirmReset()">\n {{ confirmLabel }}\n </button>\n </div>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.reset-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:110}.reset-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:26rem;width:min(90vw,26rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.reset-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:.75rem;text-transform:uppercase}.reset-modal p{margin:0 0 1.25rem}.reset-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch}.reset-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.reset-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.reset-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"],dependencies:[{kind:"ngmodule",type:g}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:W,decorators:[{type:n,args:[{selector:"pip-boy-reset-confirm-modal",standalone:!0,imports:[g],template:'@if (open) {\n <div\n class="reset-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n role="button"\n tabindex="0"\n >\n <div\n class="reset-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n role="dialog"\n tabindex="-1"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <div class="reset-modal-body">\n <p>{{ message }}</p>\n </div>\n <div class="reset-modal-actions">\n <button type="button" (click)="closeModal()">{{ cancelLabel }}</button>\n <button type="button" (click)="confirmReset()">\n {{ confirmLabel }}\n </button>\n </div>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.reset-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:110}.reset-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:26rem;width:min(90vw,26rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.reset-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:.75rem;text-transform:uppercase}.reset-modal p{margin:0 0 1.25rem}.reset-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch}.reset-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.reset-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.reset-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],title:[{type:m}],message:[{type:m}],confirmLabel:[{type:m}],cancelLabel:[{type:m}],confirm:[{type:d}],closeResult:[{type:d}]}});class U{constructor(){r(()=>{this.open()&&this.draft.set(this.value())})}open=t(!1,...ngDevMode?[{debugName:"open"}]:[]);title=t("Edit Name",...ngDevMode?[{debugName:"title"}]:[]);value=t("",...ngDevMode?[{debugName:"value"}]:[]);placeholder=t("Name",...ngDevMode?[{debugName:"placeholder"}]:[]);allowEmpty=t(!1,...ngDevMode?[{debugName:"allowEmpty"}]:[]);closeResult=u();save=u();draft=o("",...ngDevMode?[{debugName:"draft"}]:[]);updateDraft(e){this.draft.set(e.target.value)}closeModal(){this.closeResult.emit()}submit(){const e=this.draft().trim();(e||this.allowEmpty())&&this.save.emit(e),this.closeResult.emit()}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:U,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:U,isStandalone:!0,selector:"pip-boy-name-edit-modal",inputs:{open:{classPropertyName:"open",publicName:"open",isSignal:!0,isRequired:!1,transformFunction:null},title:{classPropertyName:"title",publicName:"title",isSignal:!0,isRequired:!1,transformFunction:null},value:{classPropertyName:"value",publicName:"value",isSignal:!0,isRequired:!1,transformFunction:null},placeholder:{classPropertyName:"placeholder",publicName:"placeholder",isSignal:!0,isRequired:!1,transformFunction:null},allowEmpty:{classPropertyName:"allowEmpty",publicName:"allowEmpty",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{closeResult:"closeResult",save:"save"},ngImport:e,template:'@if (open()) {\n <div\n class="name-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="name-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <h2>{{ title() }}</h2>\n <div class="name-modal-body">\n <label class="name-modal-field">\n <span>{{ placeholder() }}</span>\n <input\n type="text"\n [value]="draft()"\n (input)="updateDraft($event)"\n (keydown.enter)="submit()"\n />\n </label>\n </div>\n <div class="name-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="button" (click)="submit()">Save</button>\n </div>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.name-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#000000b3;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:100}.name-modal{background:#071c12;border:1px solid rgba(15,187,107,.45);border-radius:.5rem;box-shadow:0 0 30px #0009;padding:1.5rem;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;color:#0fbb6b;text-transform:uppercase}.name-modal h2{font-size:clamp(1rem,1rem + (1.2rem - 1rem) * (100vw - 360px) / (1200px - 360px),1.2rem);margin:0 0 1rem}.name-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch}.name-modal-field{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1.5rem}.name-modal-field span{font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);opacity:.8}.name-modal-field input{background:transparent;border:1px solid rgba(15,187,107,.4);color:#0fbb6b;padding:.5rem .75rem;font:inherit}.name-modal-field input:focus{outline:none;border-color:#0fbb6b}.name-modal-actions{display:flex;justify-content:flex-end;gap:.75rem}.name-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;font:inherit;padding:.45rem 1rem;text-transform:uppercase}.name-modal-actions button:hover{background:#0fbb6b26;border-color:#0fbb6b}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:U,decorators:[{type:n,args:[{selector:"pip-boy-name-edit-modal",standalone:!0,template:'@if (open()) {\n <div\n class="name-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="name-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <h2>{{ title() }}</h2>\n <div class="name-modal-body">\n <label class="name-modal-field">\n <span>{{ placeholder() }}</span>\n <input\n type="text"\n [value]="draft()"\n (input)="updateDraft($event)"\n (keydown.enter)="submit()"\n />\n </label>\n </div>\n <div class="name-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="button" (click)="submit()">Save</button>\n </div>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.name-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#000000b3;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:100}.name-modal{background:#071c12;border:1px solid rgba(15,187,107,.45);border-radius:.5rem;box-shadow:0 0 30px #0009;padding:1.5rem;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;color:#0fbb6b;text-transform:uppercase}.name-modal h2{font-size:clamp(1rem,1rem + (1.2rem - 1rem) * (100vw - 360px) / (1200px - 360px),1.2rem);margin:0 0 1rem}.name-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch}.name-modal-field{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1.5rem}.name-modal-field span{font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);opacity:.8}.name-modal-field input{background:transparent;border:1px solid rgba(15,187,107,.4);color:#0fbb6b;padding:.5rem .75rem;font:inherit}.name-modal-field input:focus{outline:none;border-color:#0fbb6b}.name-modal-actions{display:flex;justify-content:flex-end;gap:.75rem}.name-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;font:inherit;padding:.45rem 1rem;text-transform:uppercase}.name-modal-actions button:hover{background:#0fbb6b26;border-color:#0fbb6b}\n"]}]}],ctorParameters:()=>[],propDecorators:{open:[{type:e.Input,args:[{isSignal:!0,alias:"open",required:!1}]}],title:[{type:e.Input,args:[{isSignal:!0,alias:"title",required:!1}]}],value:[{type:e.Input,args:[{isSignal:!0,alias:"value",required:!1}]}],placeholder:[{type:e.Input,args:[{isSignal:!0,alias:"placeholder",required:!1}]}],allowEmpty:[{type:e.Input,args:[{isSignal:!0,alias:"allowEmpty",required:!1}]}],closeResult:[{type:e.Output,args:["closeResult"]}],save:[{type:e.Output,args:["save"]}]}});class V{settings=s(B);imageStore=s(x);soundStore=s(O);nameDraft=o("",...ngDevMode?[{debugName:"nameDraft"}]:[]);showNameModal=o(!1,...ngDevMode?[{debugName:"showNameModal"}]:[]);showVaultBoyDeleteModal=o(!1,...ngDevMode?[{debugName:"showVaultBoyDeleteModal"}]:[]);extraOptionModal=o(null,...ngDevMode?[{debugName:"extraOptionModal"}]:[]);extraOptionTitle=c(()=>{switch(this.extraOptionModal()){case"STIMPAK":case"LIMBS":return"Edit Text";default:return""}},...ngDevMode?[{debugName:"extraOptionTitle"}]:[]);extraOptionValue=c(()=>{const e=this.extraOptionModal();return"STIMPAK"===e?this.settings.stimpakLabel():"LIMBS"===e?this.settings.limbLabel():""},...ngDevMode?[{debugName:"extraOptionValue"}]:[]);selectVaultBoySlot(e){this.settings.selectedVaultBoyImageIndex.set(e),this.playClickSound()}addVaultBoySlot(){if(this.settings.editLockEnabled())return;if(this.settings.vaultBoyImages().length>=10)return;const e=this.settings.vaultBoyImages().length;this.settings.vaultBoyImages.update(e=>[...e,null]),this.settings.selectedVaultBoyImageIndex.set(e)}async onVaultBoyImageSelected(e){if(this.settings.editLockEnabled())return;const t=e.target,a=t.files?.[0]??null;if(!a)return;const n=await this.imageStore.saveFile(a),o=this.settings.selectedVaultBoyImageIndex();this.settings.vaultBoyImages.update(e=>e.map((e,t)=>t===o?n.id:e)),t.value=""}startNameEdit(){this.settings.editLockEnabled()||(this.nameDraft.set(this.settings.userName()),this.showNameModal.set(!0),this.playClickSound())}closeNameModal(){this.showNameModal.set(!1)}saveNameEdit(e){e.trim()&&this.settings.userName.set(e.trim()),this.closeNameModal()}openVaultBoyDeleteModal(){if(this.settings.editLockEnabled())return;const e=this.settings.vaultBoyImages();if(0===e.length)return;e[this.settings.selectedVaultBoyImageIndex()]?this.showVaultBoyDeleteModal.set(!0):this.confirmVaultBoyDelete()}closeVaultBoyDeleteModal(){this.showVaultBoyDeleteModal.set(!1)}confirmVaultBoyDelete(){if(this.settings.editLockEnabled())return;const e=this.settings.selectedVaultBoyImageIndex();this.settings.vaultBoyImages.update(t=>t.filter((t,a)=>a!==e));const t=this.settings.vaultBoyImages().length,a=0===t?0:Math.min(e,t-1);this.settings.selectedVaultBoyImageIndex.set(a),this.closeVaultBoyDeleteModal()}openExtraOptionModal(e){this.settings.editLockEnabled()||this.extraOptionModal.set(e)}closeExtraOptionModal(){this.extraOptionModal.set(null)}saveExtraOptionModal(e){const t=this.extraOptionModal();"STIMPAK"===t?this.settings.stimpakLabel.set(e):"LIMBS"===t&&this.settings.limbLabel.set(e),this.closeExtraOptionModal()}playClickSound(){this.soundStore.playSound(this.settings.clickSoundId())}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:V,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:V,isStandalone:!0,selector:"pip-boy-cnd-status",ngImport:e,template:'<div class="vault-boy-status">\n <label\n class="vault-boy-uploader"\n [class.is-locked]="settings.editLockEnabled()"\n for="vault-boy-image-input"\n >\n @if (settings.vaultBoyImages()[settings.selectedVaultBoyImageIndex()]) {\n <img\n [src]="\n imageStore.getImageUrl(\n settings.vaultBoyImages()[settings.selectedVaultBoyImageIndex()]\n )\n "\n alt="Vault Boy"\n />\n } @else if (settings.vaultBoyImages().length > 0) {\n <span>Click to upload an Image</span>\n }\n </label>\n <input\n #vaultBoyImageInput\n id="vault-boy-image-input"\n type="file"\n accept="image/*"\n [disabled]="settings.editLockEnabled()"\n (change)="onVaultBoyImageSelected($event)"\n />\n <div class="vault-boy-slots">\n @for (slot of settings.vaultBoyImages(); track $index) {\n <button\n type="button"\n class="vault-boy-slot"\n [class.is-active]="settings.selectedVaultBoyImageIndex() === $index"\n [attr.aria-label]="\'Select action-buttonimage slot \' + ($index + 1)"\n (click)="selectVaultBoySlot($index)"\n ></button>\n }\n @if (!settings.editLockEnabled()) {\n <button\n type="button"\n class="vault-boy-slot vault-boy-slot--add"\n (click)="addVaultBoySlot()"\n [disabled]="settings.vaultBoyImages().length >= 10"\n >\n +\n </button>\n <button\n type="button"\n class="vault-boy-slot vault-boy-slot--delete"\n (click)="openVaultBoyDeleteModal()"\n [disabled]="settings.vaultBoyImages().length === 0"\n >\n -\n </button>\n }\n </div>\n <button\n type="button"\n class="vault-boy-name"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="startNameEdit()"\n >\n {{ settings.userName() }} - Level {{ settings.userLevel() }}\n </button>\n</div>\n<div class="extra-options">\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'STIMPAK\')"\n >\n {{ settings.stimpakLabel() }}\n </button>\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'LIMBS\')"\n >\n {{ settings.limbLabel() }}\n </button>\n <pip-boy-reset-confirm-modal\n [open]="showVaultBoyDeleteModal()"\n title="Delete image"\n message="This will remove the selected slot. Continue?"\n confirmLabel="Delete"\n (closeResult)="closeVaultBoyDeleteModal()"\n (confirm)="confirmVaultBoyDelete()"\n />\n <pip-boy-name-edit-modal\n [open]="showNameModal()"\n [value]="nameDraft()"\n title="Edit Name"\n placeholder="Name"\n (closeResult)="closeNameModal()"\n (save)="saveNameEdit($event)"\n />\n <pip-boy-name-edit-modal\n [open]="extraOptionModal() !== null"\n [value]="extraOptionValue()"\n [title]="extraOptionTitle()"\n placeholder="Value"\n [allowEmpty]="true"\n (closeResult)="closeExtraOptionModal()"\n (save)="saveExtraOptionModal($event)"\n />\n</div>\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{display:flex;flex:1;gap:1rem;min-height:0}.vault-boy-status{align-items:stretch;box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;gap:.75rem;justify-content:flex-start;margin:0 1rem 1rem;min-height:0;overflow:hidden}.vault-boy-uploader{align-items:center;cursor:pointer;display:flex;flex:1 1 auto;justify-content:center;min-height:0;overflow:hidden;text-transform:uppercase;width:100%}.vault-boy-uploader span{opacity:.7;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.vault-boy-uploader img{max-height:100%;max-width:100%;object-fit:contain;padding:.5rem}.vault-boy-uploader.is-locked{cursor:default;pointer-events:none}#vault-boy-image-input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.vault-boy-slots{display:flex;gap:.5rem;flex-wrap:wrap;justify-content:center}.vault-boy-slot{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;height:2rem;padding:0;width:2rem}.vault-boy-slot.is-active{background:#0fbb6b33;border-color:#0fbb6b}.vault-boy-slot:disabled{cursor:not-allowed;opacity:.4}.vault-boy-slot--add{border-style:dashed}.vault-boy-slot--delete{border-style:solid}.vault-boy-name{align-items:center;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:inline-flex;justify-content:center;padding:.5rem .75rem;text-align:center;font-size:clamp(1.45rem,1.45rem + (1.75rem - 1.45rem) * (100vw - 360px) / (1200px - 360px),1.75rem);width:100%}.vault-boy-name:hover{background:#0fbb6b1f}.vault-boy-name.is-locked{cursor:default}.extra-options{margin-top:.25rem;display:flex;flex-direction:column;font-size:calc(clamp(1.05rem,1.05rem + .2rem * (100vw - 360px) / 840px,1.25rem) * var(--list-font-scale, 1));align-items:flex-end;gap:.75rem;white-space:nowrap}.extra-options button{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font:inherit;padding:0;white-space:nowrap}.extra-options button:hover{opacity:.8}.extra-options button.is-locked{cursor:default}.extra-options .controller-button{font-size:inherit;white-space:nowrap}.extra-options .controller-button .large-par{display:inline;padding-left:.5rem;font-size:calc(clamp(1.45rem,1.45rem + .3rem * (100vw - 360px) / 840px,1.75rem) * var(--list-font-scale, 1));top:-.15rem;position:relative;white-space:nowrap}\n"],dependencies:[{kind:"component",type:W,selector:"pip-boy-reset-confirm-modal",inputs:["open","title","message","confirmLabel","cancelLabel"],outputs:["confirm","closeResult"]},{kind:"component",type:U,selector:"pip-boy-name-edit-modal",inputs:["open","title","value","placeholder","allowEmpty"],outputs:["closeResult","save"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:V,decorators:[{type:n,args:[{selector:"pip-boy-cnd-status",standalone:!0,imports:[W,U],template:'<div class="vault-boy-status">\n <label\n class="vault-boy-uploader"\n [class.is-locked]="settings.editLockEnabled()"\n for="vault-boy-image-input"\n >\n @if (settings.vaultBoyImages()[settings.selectedVaultBoyImageIndex()]) {\n <img\n [src]="\n imageStore.getImageUrl(\n settings.vaultBoyImages()[settings.selectedVaultBoyImageIndex()]\n )\n "\n alt="Vault Boy"\n />\n } @else if (settings.vaultBoyImages().length > 0) {\n <span>Click to upload an Image</span>\n }\n </label>\n <input\n #vaultBoyImageInput\n id="vault-boy-image-input"\n type="file"\n accept="image/*"\n [disabled]="settings.editLockEnabled()"\n (change)="onVaultBoyImageSelected($event)"\n />\n <div class="vault-boy-slots">\n @for (slot of settings.vaultBoyImages(); track $index) {\n <button\n type="button"\n class="vault-boy-slot"\n [class.is-active]="settings.selectedVaultBoyImageIndex() === $index"\n [attr.aria-label]="\'Select action-buttonimage slot \' + ($index + 1)"\n (click)="selectVaultBoySlot($index)"\n ></button>\n }\n @if (!settings.editLockEnabled()) {\n <button\n type="button"\n class="vault-boy-slot vault-boy-slot--add"\n (click)="addVaultBoySlot()"\n [disabled]="settings.vaultBoyImages().length >= 10"\n >\n +\n </button>\n <button\n type="button"\n class="vault-boy-slot vault-boy-slot--delete"\n (click)="openVaultBoyDeleteModal()"\n [disabled]="settings.vaultBoyImages().length === 0"\n >\n -\n </button>\n }\n </div>\n <button\n type="button"\n class="vault-boy-name"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="startNameEdit()"\n >\n {{ settings.userName() }} - Level {{ settings.userLevel() }}\n </button>\n</div>\n<div class="extra-options">\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'STIMPAK\')"\n >\n {{ settings.stimpakLabel() }}\n </button>\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'LIMBS\')"\n >\n {{ settings.limbLabel() }}\n </button>\n <pip-boy-reset-confirm-modal\n [open]="showVaultBoyDeleteModal()"\n title="Delete image"\n message="This will remove the selected slot. Continue?"\n confirmLabel="Delete"\n (closeResult)="closeVaultBoyDeleteModal()"\n (confirm)="confirmVaultBoyDelete()"\n />\n <pip-boy-name-edit-modal\n [open]="showNameModal()"\n [value]="nameDraft()"\n title="Edit Name"\n placeholder="Name"\n (closeResult)="closeNameModal()"\n (save)="saveNameEdit($event)"\n />\n <pip-boy-name-edit-modal\n [open]="extraOptionModal() !== null"\n [value]="extraOptionValue()"\n [title]="extraOptionTitle()"\n placeholder="Value"\n [allowEmpty]="true"\n (closeResult)="closeExtraOptionModal()"\n (save)="saveExtraOptionModal($event)"\n />\n</div>\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{display:flex;flex:1;gap:1rem;min-height:0}.vault-boy-status{align-items:stretch;box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;gap:.75rem;justify-content:flex-start;margin:0 1rem 1rem;min-height:0;overflow:hidden}.vault-boy-uploader{align-items:center;cursor:pointer;display:flex;flex:1 1 auto;justify-content:center;min-height:0;overflow:hidden;text-transform:uppercase;width:100%}.vault-boy-uploader span{opacity:.7;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.vault-boy-uploader img{max-height:100%;max-width:100%;object-fit:contain;padding:.5rem}.vault-boy-uploader.is-locked{cursor:default;pointer-events:none}#vault-boy-image-input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.vault-boy-slots{display:flex;gap:.5rem;flex-wrap:wrap;justify-content:center}.vault-boy-slot{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;height:2rem;padding:0;width:2rem}.vault-boy-slot.is-active{background:#0fbb6b33;border-color:#0fbb6b}.vault-boy-slot:disabled{cursor:not-allowed;opacity:.4}.vault-boy-slot--add{border-style:dashed}.vault-boy-slot--delete{border-style:solid}.vault-boy-name{align-items:center;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:inline-flex;justify-content:center;padding:.5rem .75rem;text-align:center;font-size:clamp(1.45rem,1.45rem + (1.75rem - 1.45rem) * (100vw - 360px) / (1200px - 360px),1.75rem);width:100%}.vault-boy-name:hover{background:#0fbb6b1f}.vault-boy-name.is-locked{cursor:default}.extra-options{margin-top:.25rem;display:flex;flex-direction:column;font-size:calc(clamp(1.05rem,1.05rem + .2rem * (100vw - 360px) / 840px,1.25rem) * var(--list-font-scale, 1));align-items:flex-end;gap:.75rem;white-space:nowrap}.extra-options button{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font:inherit;padding:0;white-space:nowrap}.extra-options button:hover{opacity:.8}.extra-options button.is-locked{cursor:default}.extra-options .controller-button{font-size:inherit;white-space:nowrap}.extra-options .controller-button .large-par{display:inline;padding-left:.5rem;font-size:calc(clamp(1.45rem,1.45rem + .3rem * (100vw - 360px) / 840px,1.75rem) * var(--list-font-scale, 1));top:-.15rem;position:relative;white-space:nowrap}\n"]}]}]});class _{constructor(){"undefined"!=typeof window&&"DeviceMotionEvent"in window&&this.motionSupported.set(!0),"undefined"!=typeof window&&(this.startTicking(),this.startJitter())}audioContext=null;lastNoiseAt=0;tickTimer=null;jitterTimer=null;lastPointerLevel=null;level=o(0,...ngDevMode?[{debugName:"level"}]:[]);targetLevel=o(0,...ngDevMode?[{debugName:"targetLevel"}]:[]);motionEnabled=o(!1,...ngDevMode?[{debugName:"motionEnabled"}]:[]);motionSupported=o(!1,...ngDevMode?[{debugName:"motionSupported"}]:[]);showResistModal=o(!1,...ngDevMode?[{debugName:"showResistModal"}]:[]);resistPercent=o(12,...ngDevMode?[{debugName:"resistPercent"}]:[]);motionHandler=e=>{const t=e.accelerationIncludingGravity;if(!t)return;const a=Math.abs(t.x??0),n=Math.abs(t.y??0),o=Math.abs(t.z??0),i=Math.min(1,(a+n+o)/30);this.targetLevel.set(Number(i.toFixed(2)))};ngOnDestroy(){this.disableMotion(),this.stopTicking(),this.stopJitter()}getLevelPercent(){return`${Math.round(100*this.level())}%`}async enableMotion(){const e=DeviceMotionEvent;if(e.requestPermission){if("granted"!==await e.requestPermission())return}window.addEventListener("devicemotion",this.motionHandler),this.motionEnabled.set(!0)}disableMotion(){this.motionEnabled()&&window.removeEventListener("devicemotion",this.motionHandler),this.motionEnabled.set(!1)}updateFromPointer(e){if(this.motionEnabled())return;const t=e.currentTarget.getBoundingClientRect();if(!t.width)return;const a=Math.max(0,Math.min(t.width,e.clientX-t.left))/t.width;this.lastPointerLevel=Number(a.toFixed(2)),this.targetLevel.set(this.lastPointerLevel)}playNoise(){const e=Date.now();if(e-this.lastNoiseAt<500)return;this.lastNoiseAt=e;const t=this.getAudioContext();if(!t)return;const a=Math.floor(.2*t.sampleRate),n=t.createBuffer(1,a,t.sampleRate),o=n.getChannelData(0);for(let e=0;e<a;e+=1)o[e]=2*Math.random()-1;const i=t.createBufferSource();i.buffer=n;const r=t.createGain();r.gain.value=.7,i.connect(r),r.connect(t.destination),i.start()}startTicking(){if(null!==this.tickTimer)return;const e=()=>{const t=this.level();this.playTick(t);const a=Math.max(90,700-520*t);this.tickTimer=window.setTimeout(e,a)};this.tickTimer=window.setTimeout(e,400)}stopTicking(){null!==this.tickTimer&&(window.clearTimeout(this.tickTimer),this.tickTimer=null)}startJitter(){null===this.jitterTimer&&(this.jitterTimer=window.setInterval(()=>{const e=this.targetLevel(),t=.12*(Math.random()-.5),a=Math.max(0,Math.min(1,e+t)),n=this.level(),o=n+.35*(a-n);this.level.set(Number(o.toFixed(2)))},180))}stopJitter(){null!==this.jitterTimer&&(window.clearInterval(this.jitterTimer),this.jitterTimer=null)}playTick(e){const t=this.getAudioContext();if(!t)return;const a=t.createOscillator(),n=t.createGain(),o=t.currentTime,i=600+600*e;a.type="square",a.frequency.setValueAtTime(i,o),n.gain.setValueAtTime(.001,o),n.gain.exponentialRampToValueAtTime(.18,o+.01),n.gain.exponentialRampToValueAtTime(.001,o+.08),a.connect(n),n.connect(t.destination),a.start(o),a.stop(o+.09)}getAudioContext(){if(this.audioContext)return this.audioContext;try{return this.audioContext=new AudioContext,this.audioContext}catch{return null}}showEnableMotion(){return this.motionSupported()&&!this.motionEnabled()}openResistModal(){this.showResistModal.set(!0)}closeResistModal(){this.showResistModal.set(!1)}saveResistModal(e){const t=Number.parseInt(e,10);Number.isFinite(t)&&this.resistPercent.set(Math.max(1,t)),this.closeResistModal()}getResistLabel(){return`RAD RESIST ${this.resistPercent()}%`}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:_,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:_,isStandalone:!0,selector:"pip-boy-radiation-meter",ngImport:e,template:'<div class="radiation-panel">\n <div class="radiation-info">\n <button type="button" class="radiation-resist" (click)="openResistModal()">\n {{ getResistLabel() }}\n </button>\n @if (motionSupported()) {\n <div class="radiation-motion">\n @if (showEnableMotion()) {\n <button type="button" (click)="enableMotion()">Enable Motion</button>\n } @else {\n <button type="button" (click)="disableMotion()">\n Disable Motion\n </button>\n }\n </div>\n }\n </div>\n <div class="radiation-meter">\n <div\n class="radiation-meter-track"\n (pointermove)="updateFromPointer($event)"\n >\n <div class="radiation-meter-labels">\n <span class="radiation-meter-label" style="left: 50%">500</span>\n <span class="radiation-meter-label" style="left: 100%">1000</span>\n </div>\n <div class="radiation-meter-fill" [style.width]="getLevelPercent()"></div>\n <div\n class="radiation-meter-trigger"\n tabindex="0"\n (mouseenter)="playNoise()"\n (click)="playNoise()"\n (keyup.enter)="playNoise()"\n (keyup.space)="playNoise()"\n ></div>\n </div>\n <div class="radiation-meter-value">{{ getLevelPercent() }}</div>\n </div>\n</div>\n<pip-boy-name-edit-modal\n [open]="showResistModal()"\n title="RAD RESIST"\n [value]="resistPercent().toString()"\n placeholder="Percent"\n (closeResult)="closeResistModal()"\n (save)="saveResistModal($event)"\n/>\n',styles:[':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{display:flex;flex:1 1 auto;min-height:0}.radiation-panel{display:grid;grid-template-columns:30% 1fr;gap:1.5rem;min-height:0;padding:1rem;align-items:center;width:100%;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.radiation-info{display:flex;flex-direction:column}.radiation-resist{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;padding:.6rem .9rem;text-align:left;text-transform:uppercase;font-size:inherit}.radiation-resist:hover{border-color:#0fbb6b;background:#0fbb6b1f}.radiation-meter{display:flex;flex-direction:column;gap:.75rem;width:100%;justify-self:stretch}.radiation-meter-track{position:relative;width:100%;height:2.5rem;border:1px solid rgba(15,187,107,.4);background:#0fbb6b14;overflow:hidden}.radiation-meter-fill{position:absolute;top:0;left:0;height:100%;background:#0fbb6b73;box-shadow:0 0 20px #0fbb6b59}.radiation-meter-labels{position:absolute;top:-1.2rem;left:0;width:100%;height:1.2rem}.radiation-meter-label{position:absolute;transform:translate(-50%);font-size:calc(clamp(.7rem,.7rem + .15rem * (100vw - 360px) / 840px,.85rem) * var(--list-font-scale, 1));text-transform:uppercase}.radiation-meter-track:before{content:"";position:absolute;left:0;top:0;width:100%;height:25%;background:repeating-linear-gradient(to right,rgba(15,187,107,.35),rgba(15,187,107,.35) 2px,transparent 2px,transparent 12px);pointer-events:none}.radiation-meter-trigger{position:absolute;top:0;right:0;width:15%;height:40%;cursor:pointer;background:#0fbb6b0d}.radiation-meter-value{font-size:calc(clamp(.9rem,.9rem + .2rem * (100vw - 360px) / 840px,1.1rem) * var(--list-font-scale, 1));letter-spacing:.08em;text-transform:uppercase}.radiation-motion button{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;padding:.4rem .9rem;text-transform:uppercase}.radiation-motion button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n'],dependencies:[{kind:"component",type:U,selector:"pip-boy-name-edit-modal",inputs:["open","title","value","placeholder","allowEmpty"],outputs:["closeResult","save"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:_,decorators:[{type:n,args:[{selector:"pip-boy-radiation-meter",standalone:!0,imports:[U],template:'<div class="radiation-panel">\n <div class="radiation-info">\n <button type="button" class="radiation-resist" (click)="openResistModal()">\n {{ getResistLabel() }}\n </button>\n @if (motionSupported()) {\n <div class="radiation-motion">\n @if (showEnableMotion()) {\n <button type="button" (click)="enableMotion()">Enable Motion</button>\n } @else {\n <button type="button" (click)="disableMotion()">\n Disable Motion\n </button>\n }\n </div>\n }\n </div>\n <div class="radiation-meter">\n <div\n class="radiation-meter-track"\n (pointermove)="updateFromPointer($event)"\n >\n <div class="radiation-meter-labels">\n <span class="radiation-meter-label" style="left: 50%">500</span>\n <span class="radiation-meter-label" style="left: 100%">1000</span>\n </div>\n <div class="radiation-meter-fill" [style.width]="getLevelPercent()"></div>\n <div\n class="radiation-meter-trigger"\n tabindex="0"\n (mouseenter)="playNoise()"\n (click)="playNoise()"\n (keyup.enter)="playNoise()"\n (keyup.space)="playNoise()"\n ></div>\n </div>\n <div class="radiation-meter-value">{{ getLevelPercent() }}</div>\n </div>\n</div>\n<pip-boy-name-edit-modal\n [open]="showResistModal()"\n title="RAD RESIST"\n [value]="resistPercent().toString()"\n placeholder="Percent"\n (closeResult)="closeResistModal()"\n (save)="saveResistModal($event)"\n/>\n',styles:[':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{display:flex;flex:1 1 auto;min-height:0}.radiation-panel{display:grid;grid-template-columns:30% 1fr;gap:1.5rem;min-height:0;padding:1rem;align-items:center;width:100%;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.radiation-info{display:flex;flex-direction:column}.radiation-resist{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;padding:.6rem .9rem;text-align:left;text-transform:uppercase;font-size:inherit}.radiation-resist:hover{border-color:#0fbb6b;background:#0fbb6b1f}.radiation-meter{display:flex;flex-direction:column;gap:.75rem;width:100%;justify-self:stretch}.radiation-meter-track{position:relative;width:100%;height:2.5rem;border:1px solid rgba(15,187,107,.4);background:#0fbb6b14;overflow:hidden}.radiation-meter-fill{position:absolute;top:0;left:0;height:100%;background:#0fbb6b73;box-shadow:0 0 20px #0fbb6b59}.radiation-meter-labels{position:absolute;top:-1.2rem;left:0;width:100%;height:1.2rem}.radiation-meter-label{position:absolute;transform:translate(-50%);font-size:calc(clamp(.7rem,.7rem + .15rem * (100vw - 360px) / 840px,.85rem) * var(--list-font-scale, 1));text-transform:uppercase}.radiation-meter-track:before{content:"";position:absolute;left:0;top:0;width:100%;height:25%;background:repeating-linear-gradient(to right,rgba(15,187,107,.35),rgba(15,187,107,.35) 2px,transparent 2px,transparent 12px);pointer-events:none}.radiation-meter-trigger{position:absolute;top:0;right:0;width:15%;height:40%;cursor:pointer;background:#0fbb6b0d}.radiation-meter-value{font-size:calc(clamp(.9rem,.9rem + .2rem * (100vw - 360px) / 840px,1.1rem) * var(--list-font-scale, 1));letter-spacing:.08em;text-transform:uppercase}.radiation-motion button{background:transparent;border:1px solid rgba(15,187,107,.5);color:#0fbb6b;cursor:pointer;padding:.4rem .9rem;text-transform:uppercase}.radiation-motion button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n']}]}],ctorParameters:()=>[]});class G{open=!1;title="Edit Effect";name="";description="";closeResult=new l;save=new l;draftName=o("",...ngDevMode?[{debugName:"draftName"}]:[]);draftDescription=o("",...ngDevMode?[{debugName:"draftDescription"}]:[]);ngOnChanges(e){if(e.open&&this.open)return this.draftName.set(this.name??""),void this.draftDescription.set(this.description??"");e.name&&this.draftName.set(this.name??""),e.description&&this.draftDescription.set(this.description??"")}updateName(e){this.draftName.set(e)}updateDescription(e){this.draftDescription.set(e)}closeModal(){this.closeResult.emit()}submit(e){e.preventDefault();const t=this.draftName().trim();t&&this.save.emit({name:t,description:this.draftDescription().trim()})}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:G,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:G,isStandalone:!0,selector:"pip-boy-effect-edit-modal",inputs:{open:"open",title:"title",name:"name",description:"description"},outputs:{closeResult:"closeResult",save:"save"},usesOnChanges:!0,ngImport:e,template:'@if (open) {\n <div\n class="effect-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="effect-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title }}</header>\n <form (submit)="submit($event)">\n <div class="effect-modal-body">\n <label class="effect-modal-field">\n <span>Name</span>\n <input\n type="text"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n <label class="effect-modal-field">\n <span>Description</span>\n <textarea\n rows="5"\n [value]="draftDescription()"\n (input)="updateDescription($any($event.target).value)"\n ></textarea>\n </label>\n </div>\n <div class="effect-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.effect-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.effect-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.effect-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.effect-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.effect-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.effect-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.effect-modal-field input,.effect-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.effect-modal-field input:focus,.effect-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.effect-modal-field textarea{resize:vertical;text-transform:none}.effect-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.effect-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.effect-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:G,decorators:[{type:n,args:[{selector:"pip-boy-effect-edit-modal",standalone:!0,template:'@if (open) {\n <div\n class="effect-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="effect-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title }}</header>\n <form (submit)="submit($event)">\n <div class="effect-modal-body">\n <label class="effect-modal-field">\n <span>Name</span>\n <input\n type="text"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n <label class="effect-modal-field">\n <span>Description</span>\n <textarea\n rows="5"\n [value]="draftDescription()"\n (input)="updateDescription($any($event.target).value)"\n ></textarea>\n </label>\n </div>\n <div class="effect-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.effect-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.effect-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.effect-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.effect-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.effect-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.effect-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.effect-modal-field input,.effect-modal-field textarea{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.effect-modal-field input:focus,.effect-modal-field textarea:focus{outline:none;border-color:#0fbb6b}.effect-modal-field textarea{resize:vertical;text-transform:none}.effect-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.effect-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.effect-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],title:[{type:m}],name:[{type:m}],description:[{type:m}],closeResult:[{type:d}],save:[{type:d}]}});class ${settings=s(B);selectedId=o(null,...ngDevMode?[{debugName:"selectedId"}]:[]);showEditModal=o(!1,...ngDevMode?[{debugName:"showEditModal"}]:[]);editMode=o("ADD",...ngDevMode?[{debugName:"editMode"}]:[]);modalName=o("",...ngDevMode?[{debugName:"modalName"}]:[]);modalDescription=o("",...ngDevMode?[{debugName:"modalDescription"}]:[]);items=c(()=>this.settings.effectItems(),...ngDevMode?[{debugName:"items"}]:[]);selectedItem=c(()=>{const e=this.selectedId();return null===e?null:this.items().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedItem"}]:[]);openAddModal(){this.settings.editLockEnabled()||(this.editMode.set("ADD"),this.modalName.set(""),this.modalDescription.set(""),this.showEditModal.set(!0))}openEditModal(){if(this.settings.editLockEnabled())return;const e=this.selectedItem();e&&(this.editMode.set("EDIT"),this.modalName.set(e.name),this.modalDescription.set(e.description),this.showEditModal.set(!0))}closeEditModal(){this.showEditModal.set(!1)}saveEditModal(e){if(this.settings.editLockEnabled())return;const t=e.name.trim(),a=e.description.trim();if(!t)return;if("ADD"===this.editMode()){const e=this.getNextItemId();return this.settings.effectItems.update(n=>[...n,{id:e,name:t,description:a}]),this.selectedId.set(e),void this.closeEditModal()}const n=this.selectedId();null!==n&&(this.settings.effectItems.update(e=>e.map(e=>e.id===n?{...e,name:t,description:a}:e)),this.closeEditModal())}selectItem(e){this.selectedId.set(this.selectedId()===e?null:e)}deleteSelected(){if(this.settings.editLockEnabled())return;const e=this.selectedId();null!==e&&(this.settings.effectItems.update(t=>t.filter(t=>t.id!==e)),this.selectedId.set(null))}moveSelected(e){if(this.settings.editLockEnabled())return;const t=this.selectedId();null!==t&&this.settings.effectItems.update(a=>{const n=a.findIndex(e=>e.id===t);if(-1===n)return a;const o=n+e;if(o<0||o>=a.length)return a;const i=a.slice(),[r]=i.splice(n,1);return i.splice(o,0,r),i})}getNextItemId(){return this.items().reduce((e,t)=>Math.max(e,t.id),0)+1}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:$,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:$,isStandalone:!0,selector:"pip-boy-eff-layout",ngImport:e,template:'<div class="eff-layout">\n <ul class="eff-list">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="eff-row"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n <span class="eff-name">{{ item.name }}</span>\n <span class="eff-description">{{ item.description }}</span>\n </button>\n </li>\n } @empty {\n <li class="eff-empty">No effects added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="eff-actions">\n <button type="button" class="eff-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="eff-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="eff-delete" (click)="deleteSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="eff-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="eff-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n</div>\n<pip-boy-effect-edit-modal\n [open]="showEditModal()"\n [title]="editMode() === \'ADD\' ? \'Add Effect\' : \'Edit Effect\'"\n [name]="modalName()"\n [description]="modalDescription()"\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n/>\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{display:block;width:100%;height:100%}.eff-layout{display:flex;flex-direction:column;height:100%;min-height:0}.eff-list{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.75rem 1rem .5rem;display:flex;flex-direction:column;justify-content:center;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.eff-list li{margin:0;padding:0}.eff-row{background:transparent;border:none;border-bottom:2px solid rgba(15,187,107,.6);color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.6rem .2rem;text-align:left;text-transform:none;white-space:normal;width:100%;display:grid;grid-template-columns:1fr 1fr;gap:1rem}.eff-row:hover{background:#0fbb6b1f}.eff-row.is-selected{background:#0fbb6b2e}.eff-list li:last-child .eff-row{border-bottom:none}.eff-name,.eff-description{word-break:break-word;font-size:inherit}.eff-empty{opacity:.6;padding:.4rem .2rem}.eff-actions{display:flex;gap:.5rem;padding:.75rem 1rem 1rem}.eff-add,.eff-edit,.eff-delete{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.eff-add:hover,.eff-edit:hover,.eff-delete:hover{background:#0fbb6b1f}.eff-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.eff-move:hover{background:#0fbb6b1f}@media(max-width:720px),(max-height:560px){.eff-actions{gap:.35rem;padding:.75rem .75rem .9rem}.eff-add,.eff-edit,.eff-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.eff-move{flex:0 0 1.6rem;height:2.1rem}}\n"],dependencies:[{kind:"component",type:G,selector:"pip-boy-effect-edit-modal",inputs:["open","title","name","description"],outputs:["closeResult","save"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:$,decorators:[{type:n,args:[{selector:"pip-boy-eff-layout",standalone:!0,imports:[G],template:'<div class="eff-layout">\n <ul class="eff-list">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="eff-row"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n <span class="eff-name">{{ item.name }}</span>\n <span class="eff-description">{{ item.description }}</span>\n </button>\n </li>\n } @empty {\n <li class="eff-empty">No effects added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="eff-actions">\n <button type="button" class="eff-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="eff-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="eff-delete" (click)="deleteSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="eff-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="eff-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n</div>\n<pip-boy-effect-edit-modal\n [open]="showEditModal()"\n [title]="editMode() === \'ADD\' ? \'Add Effect\' : \'Edit Effect\'"\n [name]="modalName()"\n [description]="modalDescription()"\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n/>\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{display:block;width:100%;height:100%}.eff-layout{display:flex;flex-direction:column;height:100%;min-height:0}.eff-list{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.75rem 1rem .5rem;display:flex;flex-direction:column;justify-content:center;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.eff-list li{margin:0;padding:0}.eff-row{background:transparent;border:none;border-bottom:2px solid rgba(15,187,107,.6);color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.6rem .2rem;text-align:left;text-transform:none;white-space:normal;width:100%;display:grid;grid-template-columns:1fr 1fr;gap:1rem}.eff-row:hover{background:#0fbb6b1f}.eff-row.is-selected{background:#0fbb6b2e}.eff-list li:last-child .eff-row{border-bottom:none}.eff-name,.eff-description{word-break:break-word;font-size:inherit}.eff-empty{opacity:.6;padding:.4rem .2rem}.eff-actions{display:flex;gap:.5rem;padding:.75rem 1rem 1rem}.eff-add,.eff-edit,.eff-delete{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.eff-add:hover,.eff-edit:hover,.eff-delete:hover{background:#0fbb6b1f}.eff-move{background:#0fbb6b0d;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.eff-move:hover{background:#0fbb6b1f}@media(max-width:720px),(max-height:560px){.eff-actions{gap:.35rem;padding:.75rem .75rem .9rem}.eff-add,.eff-edit,.eff-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.eff-move{flex:0 0 1.6rem;height:2.1rem}}\n"]}]}]});class j{settings=s(B);soundStore=s(O);selectedQuestId=o(null,...ngDevMode?[{debugName:"selectedQuestId"}]:[]);selectedTaskId=o(null,...ngDevMode?[{debugName:"selectedTaskId"}]:[]);showEditModal=o(!1,...ngDevMode?[{debugName:"showEditModal"}]:[]);editTarget=o("QUEST",...ngDevMode?[{debugName:"editTarget"}]:[]);editMode=o("ADD",...ngDevMode?[{debugName:"editMode"}]:[]);editingTaskId=o(null,...ngDevMode?[{debugName:"editingTaskId"}]:[]);modalName=o("",...ngDevMode?[{debugName:"modalName"}]:[]);quests=c(()=>this.settings.questItems(),...ngDevMode?[{debugName:"quests"}]:[]);selectedQuest=c(()=>{const e=this.selectedQuestId();return null===e?null:this.quests().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedQuest"}]:[]);tasks=c(()=>this.selectedQuest()?.tasks??[],...ngDevMode?[{debugName:"tasks"}]:[]);selectedTask=c(()=>{const e=this.selectedTaskId();return null===e?null:this.tasks().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedTask"}]:[]);modalTitle=c(()=>{const e=this.editTarget(),t=this.editMode();return"TASK"===e?"ADD"===t?"Add Task":"Edit Task":"ADD"===t?"Add Quest":"Edit Quest"},...ngDevMode?[{debugName:"modalTitle"}]:[]);selectQuest(e){const t=this.selectedQuestId()===e?null:e;this.selectedQuestId.set(t),null===t&&this.selectedTaskId.set(null),this.playClickSound()}selectTask(e){this.selectedTaskId.set(this.selectedTaskId()===e?null:e),this.playClickSound()}openAddQuest(){this.settings.editLockEnabled()||(this.editTarget.set("QUEST"),this.editMode.set("ADD"),this.modalName.set(""),this.showEditModal.set(!0))}openEditQuest(e){this.settings.editLockEnabled()||(this.editTarget.set("QUEST"),this.editMode.set("EDIT"),this.modalName.set(e.name),this.selectedQuestId.set(e.id),this.showEditModal.set(!0))}openAddTask(){this.settings.editLockEnabled()||this.selectedQuest()&&(this.editTarget.set("TASK"),this.editMode.set("ADD"),this.editingTaskId.set(null),this.modalName.set(""),this.showEditModal.set(!0))}openEditTask(e){this.settings.editLockEnabled()||(this.editTarget.set("TASK"),this.editMode.set("EDIT"),this.editingTaskId.set(e.id),this.modalName.set(e.name),this.showEditModal.set(!0))}openEditSelectedQuest(){if(this.settings.editLockEnabled())return;const e=this.selectedQuest();e&&(this.playClickSound(),this.openEditQuest(e))}openEditSelectedTask(){if(this.settings.editLockEnabled())return;const e=this.selectedTask();e&&(this.playClickSound(),this.openEditTask(e))}closeEditModal(){this.showEditModal.set(!1)}saveEditModal(e){const t=e.name?.trim()??"";if(!t)return;if("QUEST"===this.editTarget()){if("ADD"===this.editMode()){const e=this.getNextQuestId();this.settings.questItems.update(a=>[...a,{id:e,name:t,completed:!1,tasks:[]}]),this.selectedQuestId.set(e),this.selectedTaskId.set(null)}else{const e=this.selectedQuestId();if(null===e)return;this.settings.questItems.update(a=>a.map(a=>a.id===e?{...a,name:t}:a))}return void this.closeEditModal()}const a=this.selectedQuest();if(a){if("ADD"===this.editMode()){const e=this.getNextTaskId(a);this.settings.questItems.update(n=>n.map(n=>n.id===a.id?{...n,tasks:[...n.tasks,{id:e,name:t,completed:!1}]}:n))}else{const e=this.editingTaskId();if(null===e)return;this.settings.questItems.update(n=>n.map(n=>n.id===a.id?{...n,tasks:n.tasks.map(a=>a.id===e?{...a,name:t}:a)}:n))}this.closeEditModal()}}toggleQuest(e){this.settings.editLockEnabled()||(this.playClickSound(),this.settings.questItems.update(t=>t.map(t=>t.id===e?{...t,completed:!t.completed}:t)))}toggleTask(e){const t=this.selectedQuest();t&&(this.settings.editLockEnabled()||(this.playClickSound(),this.settings.questItems.update(a=>a.map(a=>a.id===t.id?{...a,tasks:a.tasks.map(t=>t.id===e?{...t,completed:!t.completed}:t)}:a))))}deleteSelectedQuest(){if(this.settings.editLockEnabled())return;const e=this.selectedQuestId();null!==e&&(this.settings.questItems.update(t=>t.filter(t=>t.id!==e)),this.selectedQuestId.set(null),this.selectedTaskId.set(null))}deleteSelectedTask(){if(this.settings.editLockEnabled())return;const e=this.selectedQuest(),t=this.selectedTaskId();e&&null!==t&&(this.settings.questItems.update(a=>a.map(a=>a.id===e.id?{...a,tasks:a.tasks.filter(e=>e.id!==t)}:a)),this.selectedTaskId.set(null))}moveSelectedQuest(e){if(this.settings.editLockEnabled())return;const t=this.selectedQuestId();null!==t&&this.settings.questItems.update(a=>{const n=a.findIndex(e=>e.id===t);if(-1===n)return a;const o=n+e;if(o<0||o>=a.length)return a;const i=a.slice(),[r]=i.splice(n,1);return i.splice(o,0,r),i})}moveSelectedTask(e){if(this.settings.editLockEnabled())return;const t=this.selectedQuest(),a=this.selectedTaskId();t&&null!==a&&this.settings.questItems.update(n=>n.map(n=>{if(n.id!==t.id)return n;const o=n.tasks.findIndex(e=>e.id===a);if(-1===o)return n;const i=o+e;if(i<0||i>=n.tasks.length)return n;const r=n.tasks.slice(),[s]=r.splice(o,1);return r.splice(i,0,s),{...n,tasks:r}}))}getNextQuestId(){return this.quests().reduce((e,t)=>Math.max(e,t.id),0)+1}getNextTaskId(e){return e.tasks.reduce((e,t)=>Math.max(e,t.id),0)+1}playClickSound(){this.soundStore.playSound(this.settings.clickSoundId())}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:j,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:j,isStandalone:!0,selector:"pip-boy-quests-layout",ngImport:e,template:'<div class="quest-layout">\n <div class="quest-column">\n <ul class="quest-list">\n @for (quest of quests(); track quest.id) {\n <li\n class="quest-row"\n [class.is-selected]="selectedQuestId() === quest.id"\n (click)="selectQuest(quest.id)"\n (keyup.enter)="selectQuest(quest.id)"\n tabindex="0"\n >\n <button\n type="button"\n class="quest-toggle"\n [class.is-checked]="quest.completed"\n [disabled]="settings.editLockEnabled()"\n (click)="toggleQuest(quest.id); $event.stopPropagation()"\n aria-label="Toggle quest"\n ></button>\n <button\n type="button"\n class="quest-name"\n (click)="selectQuest(quest.id); $event.stopPropagation()"\n >\n {{ quest.name }}\n </button>\n </li>\n } @empty {\n <li class="quest-empty">No quests added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="quest-actions">\n <button type="button" class="quest-add" (click)="openAddQuest()">\n + Add\n </button>\n <button\n type="button"\n class="quest-edit"\n [disabled]="!selectedQuest()"\n (click)="openEditSelectedQuest()"\n >\n Edit\n </button>\n <button\n type="button"\n class="quest-delete"\n [disabled]="!selectedQuest()"\n (click)="deleteSelectedQuest()"\n >\n - Delete\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedQuest()"\n (click)="moveSelectedQuest(-1)"\n aria-label="Move quest up"\n >\n ▲\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedQuest()"\n (click)="moveSelectedQuest(1)"\n aria-label="Move quest down"\n >\n ▼\n </button>\n </div>\n }\n </div>\n <div class="quest-column">\n <ul class="quest-list">\n @if (selectedQuest()) {\n @for (task of tasks(); track task.id) {\n <li\n class="quest-row"\n [class.is-selected]="selectedTaskId() === task.id"\n (click)="selectTask(task.id)"\n (keyup.enter)="selectTask(task.id)"\n tabindex="0"\n >\n <button\n type="button"\n class="quest-toggle"\n [class.is-checked]="task.completed"\n [disabled]="settings.editLockEnabled()"\n (click)="toggleTask(task.id); $event.stopPropagation()"\n aria-label="Toggle task"\n ></button>\n <button\n type="button"\n class="quest-name"\n (click)="selectTask(task.id); $event.stopPropagation()"\n >\n {{ task.name }}\n </button>\n </li>\n } @empty {\n <li class="quest-empty">No tasks added.</li>\n }\n } @else {\n <li class="quest-empty">Select a quest to view tasks.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="quest-actions">\n @if (selectedQuest()) {\n <button type="button" class="quest-add" (click)="openAddTask()">\n + Add\n </button>\n <button\n type="button"\n class="quest-edit"\n [disabled]="!selectedTask()"\n (click)="openEditSelectedTask()"\n >\n Edit\n </button>\n <button\n type="button"\n class="quest-delete"\n [disabled]="!selectedTask()"\n (click)="deleteSelectedTask()"\n >\n - Delete\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedTask()"\n (click)="moveSelectedTask(-1)"\n aria-label="Move task up"\n >\n ▲\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedTask()"\n (click)="moveSelectedTask(1)"\n aria-label="Move task down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n</div>\n<pip-boy-stat-edit-modal\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n [open]="showEditModal()"\n [title]="modalTitle()"\n [name]="modalName()"\n nameLabel="Name"\n [showName]="true"\n [fields]="[]"\n/>\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{display:block;width:100%;height:100%}.quest-layout{display:flex;gap:1.5rem;height:100%;min-height:0}.quest-column{display:flex;flex:1 1 50%;flex-direction:column;min-height:0}.quest-list{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.quest-row{align-items:center;display:grid;grid-template-columns:1.5rem 1fr;gap:.6rem;padding:.25rem .35rem .25rem .2rem;font-size:inherit}.quest-row.is-selected{background:#0fbb6b2e}.quest-toggle{background:transparent;border:1px solid rgba(15,187,107,.65);cursor:pointer;height:.9rem;width:.9rem}.quest-toggle.is-checked{background:#0fbb6b}.quest-toggle:disabled{cursor:default;opacity:.6}.quest-name{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:0;text-align:left}.quest-name:hover{opacity:.8}.quest-empty{opacity:.6;padding:0 .2rem}.quest-actions{display:flex;gap:.5rem;justify-content:flex-end;margin:0 1rem 1rem;padding:0}.quest-add{background:#0fbb6b14;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.quest-add:hover{background:#0fbb6b2e}.quest-edit,.quest-delete{background:#0fbb6b0d;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.quest-edit:hover,.quest-delete:hover{background:#0fbb6b1f}.quest-edit:disabled,.quest-delete:disabled{cursor:not-allowed;opacity:.5}.quest-move{background:#0fbb6b0d;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.quest-move:hover{background:#0fbb6b1f}.quest-move:disabled{cursor:not-allowed;opacity:.5}.quest-actions button{flex:1 1 0}.quest-actions .quest-move{flex:0 0 2rem;width:2rem;padding:0}@media(max-width:720px),(max-height:560px){.quest-actions{gap:.35rem;margin:0 .75rem .75rem}.quest-add,.quest-edit,.quest-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.quest-move,.quest-actions .quest-move{flex:0 0 1.6rem;width:1.6rem;height:2.1rem}}\n"],dependencies:[{kind:"component",type:F,selector:"pip-boy-stat-edit-modal",inputs:["open","title","name","nameLabel","showName","nameOptions","imageUrl","showImage","fields","textFields"],outputs:["closeResult","save","nameChange"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:j,decorators:[{type:n,args:[{selector:"pip-boy-quests-layout",standalone:!0,imports:[F],template:'<div class="quest-layout">\n <div class="quest-column">\n <ul class="quest-list">\n @for (quest of quests(); track quest.id) {\n <li\n class="quest-row"\n [class.is-selected]="selectedQuestId() === quest.id"\n (click)="selectQuest(quest.id)"\n (keyup.enter)="selectQuest(quest.id)"\n tabindex="0"\n >\n <button\n type="button"\n class="quest-toggle"\n [class.is-checked]="quest.completed"\n [disabled]="settings.editLockEnabled()"\n (click)="toggleQuest(quest.id); $event.stopPropagation()"\n aria-label="Toggle quest"\n ></button>\n <button\n type="button"\n class="quest-name"\n (click)="selectQuest(quest.id); $event.stopPropagation()"\n >\n {{ quest.name }}\n </button>\n </li>\n } @empty {\n <li class="quest-empty">No quests added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="quest-actions">\n <button type="button" class="quest-add" (click)="openAddQuest()">\n + Add\n </button>\n <button\n type="button"\n class="quest-edit"\n [disabled]="!selectedQuest()"\n (click)="openEditSelectedQuest()"\n >\n Edit\n </button>\n <button\n type="button"\n class="quest-delete"\n [disabled]="!selectedQuest()"\n (click)="deleteSelectedQuest()"\n >\n - Delete\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedQuest()"\n (click)="moveSelectedQuest(-1)"\n aria-label="Move quest up"\n >\n ▲\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedQuest()"\n (click)="moveSelectedQuest(1)"\n aria-label="Move quest down"\n >\n ▼\n </button>\n </div>\n }\n </div>\n <div class="quest-column">\n <ul class="quest-list">\n @if (selectedQuest()) {\n @for (task of tasks(); track task.id) {\n <li\n class="quest-row"\n [class.is-selected]="selectedTaskId() === task.id"\n (click)="selectTask(task.id)"\n (keyup.enter)="selectTask(task.id)"\n tabindex="0"\n >\n <button\n type="button"\n class="quest-toggle"\n [class.is-checked]="task.completed"\n [disabled]="settings.editLockEnabled()"\n (click)="toggleTask(task.id); $event.stopPropagation()"\n aria-label="Toggle task"\n ></button>\n <button\n type="button"\n class="quest-name"\n (click)="selectTask(task.id); $event.stopPropagation()"\n >\n {{ task.name }}\n </button>\n </li>\n } @empty {\n <li class="quest-empty">No tasks added.</li>\n }\n } @else {\n <li class="quest-empty">Select a quest to view tasks.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="quest-actions">\n @if (selectedQuest()) {\n <button type="button" class="quest-add" (click)="openAddTask()">\n + Add\n </button>\n <button\n type="button"\n class="quest-edit"\n [disabled]="!selectedTask()"\n (click)="openEditSelectedTask()"\n >\n Edit\n </button>\n <button\n type="button"\n class="quest-delete"\n [disabled]="!selectedTask()"\n (click)="deleteSelectedTask()"\n >\n - Delete\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedTask()"\n (click)="moveSelectedTask(-1)"\n aria-label="Move task up"\n >\n ▲\n </button>\n <button\n type="button"\n class="quest-move"\n [disabled]="!selectedTask()"\n (click)="moveSelectedTask(1)"\n aria-label="Move task down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n</div>\n<pip-boy-stat-edit-modal\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n [open]="showEditModal()"\n [title]="modalTitle()"\n [name]="modalName()"\n nameLabel="Name"\n [showName]="true"\n [fields]="[]"\n/>\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{display:block;width:100%;height:100%}.quest-layout{display:flex;gap:1.5rem;height:100%;min-height:0}.quest-column{display:flex;flex:1 1 50%;flex-direction:column;min-height:0}.quest-list{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.quest-row{align-items:center;display:grid;grid-template-columns:1.5rem 1fr;gap:.6rem;padding:.25rem .35rem .25rem .2rem;font-size:inherit}.quest-row.is-selected{background:#0fbb6b2e}.quest-toggle{background:transparent;border:1px solid rgba(15,187,107,.65);cursor:pointer;height:.9rem;width:.9rem}.quest-toggle.is-checked{background:#0fbb6b}.quest-toggle:disabled{cursor:default;opacity:.6}.quest-name{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:0;text-align:left}.quest-name:hover{opacity:.8}.quest-empty{opacity:.6;padding:0 .2rem}.quest-actions{display:flex;gap:.5rem;justify-content:flex-end;margin:0 1rem 1rem;padding:0}.quest-add{background:#0fbb6b14;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.quest-add:hover{background:#0fbb6b2e}.quest-edit,.quest-delete{background:#0fbb6b0d;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.quest-edit:hover,.quest-delete:hover{background:#0fbb6b1f}.quest-edit:disabled,.quest-delete:disabled{cursor:not-allowed;opacity:.5}.quest-move{background:#0fbb6b0d;border:none;border-left:0;border-right:0;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.quest-move:hover{background:#0fbb6b1f}.quest-move:disabled{cursor:not-allowed;opacity:.5}.quest-actions button{flex:1 1 0}.quest-actions .quest-move{flex:0 0 2rem;width:2rem;padding:0}@media(max-width:720px),(max-height:560px){.quest-actions{gap:.35rem;margin:0 .75rem .75rem}.quest-add,.quest-edit,.quest-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.quest-move,.quest-actions .quest-move{flex:0 0 1.6rem;width:1.6rem;height:2.1rem}}\n"]}]}]});class Q{soundStore=s(O);audio=null;audioUrl=null;currentChannel=null;currentSoundId=null;endedHandlers=new Map;setOnEnded(e,t){this.endedHandlers.set(e,t),this.currentChannel===e&&this.audio&&(this.audio.onended=t??null)}isPlaying(e){return!(!this.audio||this.currentChannel!==e||this.audio.paused)}async play(e,t){if(!t)return;if(this.audio&&this.currentChannel===e&&this.currentSoundId===t)return void await this.audio.play().catch(()=>{});this.stop();const a=await this.soundStore.getRecord(t);if(!a)return;const n=URL.createObjectURL(a.blob),o=new Audio(n);o.onended=this.endedHandlers.get(e)??null,this.audio=o,this.audioUrl=n,this.currentChannel=e,this.currentSoundId=t,await o.play().catch(()=>{})}async toggle(e,t){this.audio&&this.currentChannel===e&&this.currentSoundId===t?this.audio.paused?await this.audio.play().catch(()=>{}):this.audio.pause():await this.play(e,t)}pause(e){this.audio&&this.currentChannel===e&&this.audio.pause()}stop(e){e&&this.currentChannel!==e||(this.audio&&(this.audio.pause(),this.audio.currentTime=0),this.audioUrl&&URL.revokeObjectURL(this.audioUrl),this.audio=null,this.audioUrl=null,this.currentChannel=null,this.currentSoundId=null)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Q,deps:[],target:e.ɵɵFactoryTarget.Injectable});static"ɵprov"=e.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Q,providedIn:"root"})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Q,decorators:[{type:i,args:[{providedIn:"root"}]}]});class K{open=!1;title="Edit Audio";name="";fileLabel=null;nameLabel="Song Name";fileFieldLabel="Song File";selectLabel="Select Song";closeResult=new l;save=new l;draftName=o("",...ngDevMode?[{debugName:"draftName"}]:[]);draftFileLabel=o(null,...ngDevMode?[{debugName:"draftFileLabel"}]:[]);draftFile=null;ngOnChanges(e){if(e.open&&this.open)return this.draftName.set(this.name??""),this.draftFileLabel.set(this.fileLabel),void(this.draftFile=null);e.name&&this.draftName.set(this.name??""),e.fileLabel&&this.draftFileLabel.set(this.fileLabel)}closeModal(){this.closeResult.emit()}updateName(e){this.draftName.set(e)}onFileSelected(e){const t=e.target,a=t.files?.[0]??null;this.draftFile=a,this.draftFileLabel.set(a?.name??this.fileLabel),t&&(t.value="")}removeFile(){this.draftFile=null,this.draftFileLabel.set(null)}submit(e){e.preventDefault();const t=this.draftName().trim();t&&this.draftFile&&this.save.emit({name:t,file:this.draftFile})}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:K,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:K,isStandalone:!0,selector:"pip-boy-audio-edit-modal",inputs:{open:"open",title:"title",name:"name",fileLabel:"fileLabel",nameLabel:"nameLabel",fileFieldLabel:"fileFieldLabel",selectLabel:"selectLabel"},outputs:{closeResult:"closeResult",save:"save"},usesOnChanges:!0,ngImport:e,template:'@if (open) {\n <div\n class="audio-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="audio-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <form (submit)="submit($event)">\n <div class="audio-modal-body">\n <label class="audio-modal-field">\n <span>{{ nameLabel }}</span>\n <input\n type="text"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n <div class="audio-modal-field">\n <span>{{ fileFieldLabel }}</span>\n <div class="audio-modal-file-row">\n <button\n type="button"\n class="audio-modal-file-button"\n (click)="audioFileInput.click()"\n >\n {{ draftFileLabel() ?? selectLabel }}\n </button>\n @if (draftFileLabel()) {\n <button\n type="button"\n class="audio-modal-file-remove"\n (click)="removeFile()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #audioFileInput\n type="file"\n accept="audio/*"\n (change)="onFileSelected($event)"\n />\n </div>\n </div>\n <div class="audio-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.audio-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.audio-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.audio-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.audio-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.audio-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.audio-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.audio-modal-field input{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.audio-modal-field input:focus{outline:none;border-color:#0fbb6b}.audio-modal-file-row{display:flex;gap:.5rem;align-items:center}.audio-modal-file-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;flex:1 1 auto;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.audio-modal-file-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.audio-modal-file-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.audio-modal-file-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.audio-modal input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.audio-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.audio-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.audio-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:K,decorators:[{type:n,args:[{selector:"pip-boy-audio-edit-modal",standalone:!0,template:'@if (open) {\n <div\n class="audio-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="audio-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>{{ title }}</span>\n </header>\n <form (submit)="submit($event)">\n <div class="audio-modal-body">\n <label class="audio-modal-field">\n <span>{{ nameLabel }}</span>\n <input\n type="text"\n [value]="draftName()"\n (input)="updateName($any($event.target).value)"\n />\n </label>\n <div class="audio-modal-field">\n <span>{{ fileFieldLabel }}</span>\n <div class="audio-modal-file-row">\n <button\n type="button"\n class="audio-modal-file-button"\n (click)="audioFileInput.click()"\n >\n {{ draftFileLabel() ?? selectLabel }}\n </button>\n @if (draftFileLabel()) {\n <button\n type="button"\n class="audio-modal-file-remove"\n (click)="removeFile()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #audioFileInput\n type="file"\n accept="audio/*"\n (change)="onFileSelected($event)"\n />\n </div>\n </div>\n <div class="audio-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.audio-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.audio-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:24rem;width:min(90vw,24rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.audio-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.audio-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.audio-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.audio-modal-field{display:flex;flex-direction:column;gap:.5rem;text-transform:uppercase}.audio-modal-field input{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);padding:.6rem .75rem}.audio-modal-field input:focus{outline:none;border-color:#0fbb6b}.audio-modal-file-row{display:flex;gap:.5rem;align-items:center}.audio-modal-file-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;flex:1 1 auto;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.audio-modal-file-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.audio-modal-file-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.audio-modal-file-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.audio-modal input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.audio-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.audio-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.audio-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],title:[{type:m}],name:[{type:m}],fileLabel:[{type:m}],nameLabel:[{type:m}],fileFieldLabel:[{type:m}],selectLabel:[{type:m}],closeResult:[{type:d}],save:[{type:d}]}});class Y{constructor(){r(()=>{const e=this.items(),t=this.selectedId();e.length?null!==t&&e.some(e=>e.id===t)||this.setSelectedId(e[0].id):null!==t&&this.setSelectedId(null)})}category="NOTES";settings=s(B);soundStore=s(O);audioPlayer=s(Q);showEditModal=o(!1,...ngDevMode?[{debugName:"showEditModal"}]:[]);editMode=o("ADD",...ngDevMode?[{debugName:"editMode"}]:[]);modalName=o("",...ngDevMode?[{debugName:"modalName"}]:[]);modalFileLabel=o(null,...ngDevMode?[{debugName:"modalFileLabel"}]:[]);autoplayEnabled=o(!1,...ngDevMode?[{debugName:"autoplayEnabled"}]:[]);items=c(()=>this.getItems(),...ngDevMode?[{debugName:"items"}]:[]);selectedItem=c(()=>{const e=this.selectedId();return null===e?null:this.items().find(t=>t.id===e)??null},...ngDevMode?[{debugName:"selectedItem"}]:[]);modalTitle=c(()=>{const e=this.editMode(),t="RADIO"===this.category?"Radio":"Note";return"ADD"===e?`Add ${t}`:`Edit ${t}`},...ngDevMode?[{debugName:"modalTitle"}]:[]);modalLabelPrefix=c(()=>"RADIO"===this.category?"Song":"Note",...ngDevMode?[{debugName:"modalLabelPrefix"}]:[]);ngOnDestroy(){"NOTES"===this.category&&this.audioPlayer.stop("NOTES"),this.audioPlayer.setOnEnded(this.getChannel(),null)}openAddModal(){this.settings.editLockEnabled()||(this.editMode.set("ADD"),this.modalName.set(""),this.modalFileLabel.set(null),this.showEditModal.set(!0))}openEditModal(){if(this.settings.editLockEnabled())return;const e=this.selectedItem();e&&(this.editMode.set("EDIT"),this.modalName.set(e.name),this.modalFileLabel.set(this.soundStore.getSoundLabel(e.soundId)),this.showEditModal.set(!0),this.playClickSound())}closeEditModal(){this.showEditModal.set(!1)}selectItem(e){const t=this.selectedId();this.setSelectedId(t===e?null:e),this.playClickSound()}async saveEditModal(e){if(this.settings.editLockEnabled())return;const t=e.name.trim();if(!t||!e.file)return;const a=await this.soundStore.saveFile(e.file);if("ADD"===this.editMode()){const e=this.getNextItemId();return this.updateItems(n=>[...n,{id:e,name:t,soundId:a.id}]),this.setSelectedId(e),void this.closeEditModal()}const n=this.selectedId();null!==n&&(this.updateItems(e=>e.map(e=>e.id===n?{...e,name:t,soundId:a.id}:e)),this.closeEditModal())}deleteSelected(){if(this.settings.editLockEnabled())return;const e=this.selectedId();null!==e&&(this.updateItems(t=>t.filter(t=>t.id!==e)),this.setSelectedId(null),this.audioPlayer.stop(this.getChannel()))}moveSelected(e){if(this.settings.editLockEnabled())return;const t=this.selectedId();null!==t&&this.updateItems(a=>{const n=a.findIndex(e=>e.id===t);if(-1===n)return a;const o=n+e;if(o<0||o>=a.length)return a;const i=a.slice(),[r]=i.splice(n,1);return i.splice(o,0,r),i})}async playSelected(){const e=this.items();if(!e.length)return;let t=this.selectedItem();t||(t=e[0],this.setSelectedId(t.id)),await this.audioPlayer.play(this.getChannel(),t.soundId)}pauseSelected(){this.audioPlayer.pause(this.getChannel())}stopSelected(){this.audioPlayer.stop(this.getChannel())}toggleAutoplay(){const e=!this.autoplayEnabled();this.autoplayEnabled.set(e),e?this.audioPlayer.setOnEnded(this.getChannel(),()=>{this.playNext()}):this.audioPlayer.setOnEnded(this.getChannel(),null)}async playNext(){const e=this.items();if(!e.length)return;const t=this.selectedId(),a=e.findIndex(e=>e.id===t),n=e[-1===a?0:(a+1)%e.length];this.setSelectedId(n.id),await this.audioPlayer.play(this.getChannel(),n.soundId)}getChannel(){return"RADIO"===this.category?"RADIO":"NOTES"}getItems(){return"RADIO"===this.category?this.settings.radioItems():this.settings.notesItems()}updateItems(e){"RADIO"===this.category?this.settings.radioItems.update(e):this.settings.notesItems.update(e)}selectedId(){return"RADIO"===this.category?this.settings.selectedRadioItemId():this.settings.selectedNotesItemId()}setSelectedId(e){"RADIO"===this.category?this.settings.selectedRadioItemId.set(e):this.settings.selectedNotesItemId.set(e)}getNextItemId(){return this.items().reduce((e,t)=>Math.max(e,t.id),0)+1}playClickSound(){this.soundStore.playSound(this.settings.clickSoundId())}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Y,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:Y,isStandalone:!0,selector:"pip-boy-music-layout",inputs:{category:"category"},ngImport:e,template:'<div class="music-layout">\n <div class="music-list">\n <ul class="music-list-items">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="music-list-item"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n {{ item.name }}\n </button>\n </li>\n } @empty {\n <li class="is-empty">No items added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="music-actions">\n <button type="button" class="music-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="music-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="music-delete" (click)="deleteSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="music-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="music-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="music-controls">\n <div class="music-controls-inner">\n <button type="button" class="music-control" (click)="playSelected()">\n Play\n </button>\n <button type="button" class="music-control" (click)="pauseSelected()">\n Pause\n </button>\n <button type="button" class="music-control" (click)="stopSelected()">\n Stop\n </button>\n <button\n type="button"\n class="music-control"\n [class.is-active]="autoplayEnabled()"\n (click)="toggleAutoplay()"\n >\n Autoplay\n </button>\n </div>\n </div>\n</div>\n<pip-boy-audio-edit-modal\n [open]="showEditModal()"\n [title]="modalTitle()"\n [name]="modalName()"\n [fileLabel]="modalFileLabel()"\n [nameLabel]="modalLabelPrefix() + \' Name\'"\n [fileFieldLabel]="modalLabelPrefix() + \' File\'"\n [selectLabel]="\'Select \' + modalLabelPrefix()"\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n/>\n',styles:[':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{width:100%;height:100%;display:block}.music-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.music-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.music-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.music-list-items li{margin:0;padding:0;font-size:inherit}.music-list-items .is-empty{opacity:.6}.music-list-item{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;width:100%}.music-list-item:hover{background:#0fbb6b1f}.music-list-item.is-selected{background:#0fbb6b2e}.music-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.music-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.music-add{background:#0fbb6b14;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.music-add:hover{background:#0fbb6b2e}.music-edit,.music-delete{background:#0fbb6b0d;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.music-edit:hover,.music-delete:hover{background:#0fbb6b1f}.music-move{background:#0fbb6b0d;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.music-move:hover{background:#0fbb6b1f}.music-controls{display:flex;flex:1 1 45%;min-height:0;align-items:center;justify-content:center}.music-controls-inner{display:flex;flex-direction:column;gap:.75rem;width:min(18rem,100%)}.music-control{background:#0fbb6b0d;border:1px solid rgba(15,187,107,.6);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);letter-spacing:.08em;padding:.6rem .75rem;text-transform:uppercase}.music-control:hover,.music-control.is-active{background:#0fbb6b1f;border-color:#0fbb6b}@media(max-width:720px),(max-height:560px){.music-actions{gap:.35rem;margin:0 .75rem .75rem}.music-add,.music-edit,.music-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.music-move{flex:0 0 1.6rem;height:2.1rem}.music-controls-inner{flex-direction:row;flex-wrap:wrap;gap:.5rem;justify-content:center;padding:.25rem;width:100%}.music-control{flex:1 1 calc(50% - .5rem);font-size:clamp(.7rem,.7rem + (.85rem - .7rem) * (100vw - 360px) / (1200px - 360px),.85rem);padding:.35rem .5rem;border-radius:.4rem}}\n'],dependencies:[{kind:"component",type:K,selector:"pip-boy-audio-edit-modal",inputs:["open","title","name","fileLabel","nameLabel","fileFieldLabel","selectLabel"],outputs:["closeResult","save"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Y,decorators:[{type:n,args:[{selector:"pip-boy-music-layout",standalone:!0,imports:[K],template:'<div class="music-layout">\n <div class="music-list">\n <ul class="music-list-items">\n @for (item of items(); track item.id) {\n <li>\n <button\n type="button"\n class="music-list-item"\n [class.is-selected]="selectedId() === item.id"\n (click)="selectItem(item.id)"\n >\n {{ item.name }}\n </button>\n </li>\n } @empty {\n <li class="is-empty">No items added.</li>\n }\n </ul>\n @if (!settings.editLockEnabled()) {\n <div class="music-actions">\n <button type="button" class="music-add" (click)="openAddModal()">\n + Add\n </button>\n @if (selectedId() !== null) {\n <button type="button" class="music-edit" (click)="openEditModal()">\n Edit\n </button>\n <button type="button" class="music-delete" (click)="deleteSelected()">\n - Delete\n </button>\n <button\n type="button"\n class="music-move"\n (click)="moveSelected(-1)"\n aria-label="Move up"\n >\n ▲\n </button>\n <button\n type="button"\n class="music-move"\n (click)="moveSelected(1)"\n aria-label="Move down"\n >\n ▼\n </button>\n }\n </div>\n }\n </div>\n <div class="music-controls">\n <div class="music-controls-inner">\n <button type="button" class="music-control" (click)="playSelected()">\n Play\n </button>\n <button type="button" class="music-control" (click)="pauseSelected()">\n Pause\n </button>\n <button type="button" class="music-control" (click)="stopSelected()">\n Stop\n </button>\n <button\n type="button"\n class="music-control"\n [class.is-active]="autoplayEnabled()"\n (click)="toggleAutoplay()"\n >\n Autoplay\n </button>\n </div>\n </div>\n</div>\n<pip-boy-audio-edit-modal\n [open]="showEditModal()"\n [title]="modalTitle()"\n [name]="modalName()"\n [fileLabel]="modalFileLabel()"\n [nameLabel]="modalLabelPrefix() + \' Name\'"\n [fileFieldLabel]="modalLabelPrefix() + \' File\'"\n [selectLabel]="\'Select \' + modalLabelPrefix()"\n (closeResult)="closeEditModal()"\n (save)="saveEditModal($event)"\n/>\n',styles:[':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{width:100%;height:100%;display:block}.music-layout{box-sizing:border-box;display:flex;gap:1.5rem;height:100%;min-height:0}.music-list{display:flex;flex:1 1 55%;flex-direction:column;gap:.5rem;min-height:0}.music-list-items{flex:1 1 auto;list-style:none;margin:0;min-height:0;overflow:auto;padding:.5rem .75rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.music-list-items li{margin:0;padding:0;font-size:inherit}.music-list-items .is-empty{opacity:.6}.music-list-item{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font-size:inherit;padding:.25rem .35rem .25rem 1.2rem;position:relative;text-align:left;width:100%}.music-list-item:hover{background:#0fbb6b1f}.music-list-item.is-selected{background:#0fbb6b2e}.music-list-item.is-selected:before{content:"";position:absolute;left:.35rem;top:50%;transform:translateY(-50%);width:.45rem;height:.45rem;background:#0fbb6b}.music-actions{display:flex;gap:.5rem;margin:0 1rem 1rem}.music-add{background:#0fbb6b14;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.music-add:hover{background:#0fbb6b2e}.music-edit,.music-delete{background:#0fbb6b0d;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:1 1 33%;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);height:2.5rem;padding:0 .75rem;text-transform:uppercase;white-space:nowrap}.music-edit:hover,.music-delete:hover{background:#0fbb6b1f}.music-move{background:#0fbb6b0d;border:none;border-left:0;border-right:0;box-sizing:border-box;color:#0fbb6b;cursor:pointer;flex:0 0 2rem;height:2.5rem;padding:0;text-transform:uppercase;white-space:nowrap}.music-move:hover{background:#0fbb6b1f}.music-controls{display:flex;flex:1 1 45%;min-height:0;align-items:center;justify-content:center}.music-controls-inner{display:flex;flex-direction:column;gap:.75rem;width:min(18rem,100%)}.music-control{background:#0fbb6b0d;border:1px solid rgba(15,187,107,.6);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);letter-spacing:.08em;padding:.6rem .75rem;text-transform:uppercase}.music-control:hover,.music-control.is-active{background:#0fbb6b1f;border-color:#0fbb6b}@media(max-width:720px),(max-height:560px){.music-actions{gap:.35rem;margin:0 .75rem .75rem}.music-add,.music-edit,.music-delete{font-size:clamp(.65rem,.65rem + (.8rem - .65rem) * (100vw - 360px) / (1200px - 360px),.8rem);height:2.1rem;padding:0 .5rem}.music-move{flex:0 0 1.6rem;height:2.1rem}.music-controls-inner{flex-direction:row;flex-wrap:wrap;gap:.5rem;justify-content:center;padding:.25rem;width:100%}.music-control{flex:1 1 calc(50% - .5rem);font-size:clamp(.7rem,.7rem + (.85rem - .7rem) * (100vw - 360px) / (1200px - 360px),.85rem);padding:.35rem .5rem;border-radius:.4rem}}\n']}]}],ctorParameters:()=>[],propDecorators:{category:[{type:m}]}});class J{open=!1;listFontScale=1.25;closeResult=new l;previewListFontScale=new l;appVersion=E;updateListFontScale(e){const t=Number(e);if(!Number.isFinite(t))return;const a=Math.min(150,Math.max(50,t))/100*1.25;this.listFontScale=a,this.previewListFontScale.emit(a)}listFontScalePercent(){return Math.round(this.listFontScale/1.25*100)}closeModal(){this.closeResult.emit()}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:J,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:J,isStandalone:!0,selector:"pip-boy-welcome-modal",inputs:{open:"open",listFontScale:"listFontScale"},outputs:{closeResult:"closeResult",previewListFontScale:"previewListFontScale"},ngImport:e,template:'@if (open) {\n <div\n class="welcome-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n aria-hidden="true"\n >\n <div\n class="welcome"\n (click)="$event.stopPropagation()"\n (keydown.escape)="closeModal()"\n role="dialog"\n aria-modal="true"\n aria-labelledby="pipUiWelcomeTitle"\n tabindex="-1"\n >\n <header class="welcome__header">\n <div class="welcome__title" id="pipUiWelcomeTitle">\n Welcome to Pip UI\n <span class="welcome__version">v{{ appVersion }}</span>\n </div>\n <div class="welcome__subtitle">\n A fan made Pip-Boy 3000 style simulator.\n </div>\n </header>\n\n <div class="welcome__body">\n <div class="welcome__intro">\n <p>A wrist terminal for roleplay sessions and more!</p>\n </div>\n\n <div class="welcome__divider" aria-hidden="true"></div>\n\n <section class="welcome__section" aria-labelledby="welcomeFontTitle">\n <div class="welcome__section-head">\n <div class="welcome__section-title" id="welcomeFontTitle">\n Global Font Size\n </div>\n <p class="welcome__section-text">\n Adjusts the size of list text and key UI labels across tabs.\n </p>\n </div>\n\n <div class="welcome__slider">\n <input\n class="welcome__range"\n type="range"\n min="50"\n max="150"\n step="1"\n [value]="listFontScalePercent()"\n (input)="updateListFontScale($any($event.target).value)"\n aria-label="Global font size"\n />\n <span class="welcome__value">{{ listFontScalePercent() }}%</span>\n </div>\n\n <p class="welcome__hint">\n You can adjust this anytime later in the settings menu.\n </p>\n </section>\n\n <div class="welcome__divider" aria-hidden="true"></div>\n\n <section class="welcome__section" aria-labelledby="welcomeNpmTitle">\n <div class="welcome__section-head">\n <div class="welcome__section-title" id="welcomeNpmTitle">Npm</div>\n <p class="welcome__section-text">\n Install the package to use it in your project.\n </p>\n </div>\n\n <dl class="welcome__meta" aria-label="Install information">\n <div class="welcome__row">\n <dt class="welcome__label">Package</dt>\n <dd class="welcome__data"><code>@vault-tec/pip-boy</code></dd>\n </div>\n\n <div class="welcome__row">\n <dt class="welcome__label">Install</dt>\n <dd class="welcome__data">\n <code>npm install @vault-tec/pip-boy</code>\n </dd>\n </div>\n\n <div class="welcome__row">\n <dt class="welcome__label">NPM</dt>\n <dd class="welcome__data">\n <a\n href="https://www.npmjs.com/package/@vault-tec/pip-boy"\n target="_blank"\n rel="noreferrer"\n >\n npmjs.com/package/@vault-tec/pip-boy\n </a>\n </dd>\n </div>\n </dl>\n\n <p class="welcome__disclaimer">\n Unofficial fan project. No official game assets included. Not\n affiliated with or endorsed by Bethesda Softworks or ZeniMax Media.\n </p>\n </section>\n </div>\n\n <footer class="welcome__actions">\n <button type="button" (click)="closeModal()">Close</button>\n </footer>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.welcome-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0000009e;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:110}.welcome{margin:1rem;max-height:calc(100vh - 2rem);max-height:calc(100svh - 2rem);max-width:36rem;width:min(92vw,36rem);display:flex;flex-direction:column;overflow:hidden;background:#062114f5;border:1px solid rgba(15,187,107,.42);border-radius:.9rem;box-shadow:0 0 34px #000000a6}.welcome:focus{outline:none}.welcome__header{padding:1.1rem 1.25rem .95rem;border-bottom:1px solid rgba(15,187,107,.18);background:linear-gradient(to bottom,#0fbb6b0f,#0fbb6b00)}.welcome__title{font-size:clamp(1.05rem,1.05rem + (1.3rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.3rem);letter-spacing:.1em}.welcome__version{color:#0fbb6bc7;font-size:clamp(.8rem,.8rem + (.9rem - .8rem) * (100vw - 360px) / (1200px - 360px),.9rem);letter-spacing:.1em}.welcome__subtitle{margin-top:.35rem;color:#0fbb6bbf;font-size:clamp(.85rem,.85rem + (.95rem - .85rem) * (100vw - 360px) / (1200px - 360px),.95rem)}.welcome__body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;padding:1rem 1.25rem 0;display:flex;flex-direction:column;gap:.9rem}.welcome__body p{margin:0}.welcome__intro{color:#0fbb6be6}.welcome__divider{border-top:1px solid rgba(15,187,107,.22);margin:.15rem 0}.welcome__section{border:1px solid rgba(15,187,107,.2);border-radius:.75rem;padding:.9rem .95rem;background:#0fbb6b0a;display:flex;flex-direction:column;gap:.75rem}.welcome__section:last-child{margin-bottom:1rem}.welcome__section-head{display:flex;flex-direction:column;gap:.35rem}.welcome__section-title{text-transform:uppercase;letter-spacing:.08em;color:#0fbb6bd1;font-size:clamp(.8rem,.8rem + (.95rem - .8rem) * (100vw - 360px) / (1200px - 360px),.95rem)}.welcome__section-text{color:#0fbb6bc7;font-size:clamp(.85rem,.85rem + (.95rem - .85rem) * (100vw - 360px) / (1200px - 360px),.95rem);line-height:1.35}.welcome__slider{align-items:center;display:flex;gap:.8rem}.welcome__range{appearance:none;background:#0fbb6b33;border-radius:999px;cursor:pointer;flex:1 1 auto;height:.35rem;outline:none}.welcome__range::-webkit-slider-thumb{appearance:none;background:#0fbb6b;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.welcome__range::-moz-range-thumb{background:#0fbb6b;border:none;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.welcome__value{font-size:clamp(.75rem,.75rem + (.85rem - .75rem) * (100vw - 360px) / (1200px - 360px),.85rem);color:#0fbb6bd1;letter-spacing:.08em;min-width:3.25rem;text-align:right}.welcome__hint{color:#0fbb6bbf;font-size:clamp(.82rem,.82rem + (.92rem - .82rem) * (100vw - 360px) / (1200px - 360px),.92rem);line-height:1.35}.welcome__meta{display:grid;gap:.6rem;margin:0}.welcome__row{display:grid;grid-template-columns:5.25rem 1fr;align-items:start;gap:.75rem}.welcome__label{color:#0fbb6bbd;text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;line-height:1.25;padding-top:.15rem}.welcome__data{margin:0}.welcome__data code{background:#0fbb6b14;border:1px solid rgba(15,187,107,.22);border-radius:.45rem;color:#0fbb6b;display:inline-block;padding:.25rem .55rem;max-width:100%;overflow-wrap:anywhere}.welcome__data a{color:#0fbb6b;text-decoration:none;overflow-wrap:anywhere}.welcome__data a:hover{text-decoration:underline}.welcome__disclaimer{color:#0fbb6bc2;font-size:clamp(.82rem,.82rem + (.92rem - .82rem) * (100vw - 360px) / (1200px - 360px),.92rem);line-height:1.35}.welcome__actions{display:flex;justify-content:flex-end;padding:.9rem 1.25rem 1.1rem;border-top:1px solid rgba(15,187,107,.12);background:#0000001f}.welcome__actions button{background:#0fbb6b0f;border:1px solid rgba(15,187,107,.5);border-radius:.6rem;color:#0fbb6b;cursor:pointer;padding:.55rem 1rem;text-transform:uppercase;letter-spacing:.08em}.welcome__actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"],dependencies:[{kind:"ngmodule",type:g}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:J,decorators:[{type:n,args:[{selector:"pip-boy-welcome-modal",standalone:!0,imports:[g],template:'@if (open) {\n <div\n class="welcome-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n aria-hidden="true"\n >\n <div\n class="welcome"\n (click)="$event.stopPropagation()"\n (keydown.escape)="closeModal()"\n role="dialog"\n aria-modal="true"\n aria-labelledby="pipUiWelcomeTitle"\n tabindex="-1"\n >\n <header class="welcome__header">\n <div class="welcome__title" id="pipUiWelcomeTitle">\n Welcome to Pip UI\n <span class="welcome__version">v{{ appVersion }}</span>\n </div>\n <div class="welcome__subtitle">\n A fan made Pip-Boy 3000 style simulator.\n </div>\n </header>\n\n <div class="welcome__body">\n <div class="welcome__intro">\n <p>A wrist terminal for roleplay sessions and more!</p>\n </div>\n\n <div class="welcome__divider" aria-hidden="true"></div>\n\n <section class="welcome__section" aria-labelledby="welcomeFontTitle">\n <div class="welcome__section-head">\n <div class="welcome__section-title" id="welcomeFontTitle">\n Global Font Size\n </div>\n <p class="welcome__section-text">\n Adjusts the size of list text and key UI labels across tabs.\n </p>\n </div>\n\n <div class="welcome__slider">\n <input\n class="welcome__range"\n type="range"\n min="50"\n max="150"\n step="1"\n [value]="listFontScalePercent()"\n (input)="updateListFontScale($any($event.target).value)"\n aria-label="Global font size"\n />\n <span class="welcome__value">{{ listFontScalePercent() }}%</span>\n </div>\n\n <p class="welcome__hint">\n You can adjust this anytime later in the settings menu.\n </p>\n </section>\n\n <div class="welcome__divider" aria-hidden="true"></div>\n\n <section class="welcome__section" aria-labelledby="welcomeNpmTitle">\n <div class="welcome__section-head">\n <div class="welcome__section-title" id="welcomeNpmTitle">Npm</div>\n <p class="welcome__section-text">\n Install the package to use it in your project.\n </p>\n </div>\n\n <dl class="welcome__meta" aria-label="Install information">\n <div class="welcome__row">\n <dt class="welcome__label">Package</dt>\n <dd class="welcome__data"><code>@vault-tec/pip-boy</code></dd>\n </div>\n\n <div class="welcome__row">\n <dt class="welcome__label">Install</dt>\n <dd class="welcome__data">\n <code>npm install @vault-tec/pip-boy</code>\n </dd>\n </div>\n\n <div class="welcome__row">\n <dt class="welcome__label">NPM</dt>\n <dd class="welcome__data">\n <a\n href="https://www.npmjs.com/package/@vault-tec/pip-boy"\n target="_blank"\n rel="noreferrer"\n >\n npmjs.com/package/@vault-tec/pip-boy\n </a>\n </dd>\n </div>\n </dl>\n\n <p class="welcome__disclaimer">\n Unofficial fan project. No official game assets included. Not\n affiliated with or endorsed by Bethesda Softworks or ZeniMax Media.\n </p>\n </section>\n </div>\n\n <footer class="welcome__actions">\n <button type="button" (click)="closeModal()">Close</button>\n </footer>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.welcome-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0000009e;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:110}.welcome{margin:1rem;max-height:calc(100vh - 2rem);max-height:calc(100svh - 2rem);max-width:36rem;width:min(92vw,36rem);display:flex;flex-direction:column;overflow:hidden;background:#062114f5;border:1px solid rgba(15,187,107,.42);border-radius:.9rem;box-shadow:0 0 34px #000000a6}.welcome:focus{outline:none}.welcome__header{padding:1.1rem 1.25rem .95rem;border-bottom:1px solid rgba(15,187,107,.18);background:linear-gradient(to bottom,#0fbb6b0f,#0fbb6b00)}.welcome__title{font-size:clamp(1.05rem,1.05rem + (1.3rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.3rem);letter-spacing:.1em}.welcome__version{color:#0fbb6bc7;font-size:clamp(.8rem,.8rem + (.9rem - .8rem) * (100vw - 360px) / (1200px - 360px),.9rem);letter-spacing:.1em}.welcome__subtitle{margin-top:.35rem;color:#0fbb6bbf;font-size:clamp(.85rem,.85rem + (.95rem - .85rem) * (100vw - 360px) / (1200px - 360px),.95rem)}.welcome__body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;padding:1rem 1.25rem 0;display:flex;flex-direction:column;gap:.9rem}.welcome__body p{margin:0}.welcome__intro{color:#0fbb6be6}.welcome__divider{border-top:1px solid rgba(15,187,107,.22);margin:.15rem 0}.welcome__section{border:1px solid rgba(15,187,107,.2);border-radius:.75rem;padding:.9rem .95rem;background:#0fbb6b0a;display:flex;flex-direction:column;gap:.75rem}.welcome__section:last-child{margin-bottom:1rem}.welcome__section-head{display:flex;flex-direction:column;gap:.35rem}.welcome__section-title{text-transform:uppercase;letter-spacing:.08em;color:#0fbb6bd1;font-size:clamp(.8rem,.8rem + (.95rem - .8rem) * (100vw - 360px) / (1200px - 360px),.95rem)}.welcome__section-text{color:#0fbb6bc7;font-size:clamp(.85rem,.85rem + (.95rem - .85rem) * (100vw - 360px) / (1200px - 360px),.95rem);line-height:1.35}.welcome__slider{align-items:center;display:flex;gap:.8rem}.welcome__range{appearance:none;background:#0fbb6b33;border-radius:999px;cursor:pointer;flex:1 1 auto;height:.35rem;outline:none}.welcome__range::-webkit-slider-thumb{appearance:none;background:#0fbb6b;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.welcome__range::-moz-range-thumb{background:#0fbb6b;border:none;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.welcome__value{font-size:clamp(.75rem,.75rem + (.85rem - .75rem) * (100vw - 360px) / (1200px - 360px),.85rem);color:#0fbb6bd1;letter-spacing:.08em;min-width:3.25rem;text-align:right}.welcome__hint{color:#0fbb6bbf;font-size:clamp(.82rem,.82rem + (.92rem - .82rem) * (100vw - 360px) / (1200px - 360px),.92rem);line-height:1.35}.welcome__meta{display:grid;gap:.6rem;margin:0}.welcome__row{display:grid;grid-template-columns:5.25rem 1fr;align-items:start;gap:.75rem}.welcome__label{color:#0fbb6bbd;text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;line-height:1.25;padding-top:.15rem}.welcome__data{margin:0}.welcome__data code{background:#0fbb6b14;border:1px solid rgba(15,187,107,.22);border-radius:.45rem;color:#0fbb6b;display:inline-block;padding:.25rem .55rem;max-width:100%;overflow-wrap:anywhere}.welcome__data a{color:#0fbb6b;text-decoration:none;overflow-wrap:anywhere}.welcome__data a:hover{text-decoration:underline}.welcome__disclaimer{color:#0fbb6bc2;font-size:clamp(.82rem,.82rem + (.92rem - .82rem) * (100vw - 360px) / (1200px - 360px),.92rem);line-height:1.35}.welcome__actions{display:flex;justify-content:flex-end;padding:.9rem 1.25rem 1.1rem;border-top:1px solid rgba(15,187,107,.12);background:#0000001f}.welcome__actions button{background:#0fbb6b0f;border:1px solid rgba(15,187,107,.5);border-radius:.6rem;color:#0fbb6b;cursor:pointer;padding:.55rem 1rem;text-transform:uppercase;letter-spacing:.08em}.welcome__actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],listFontScale:[{type:m}],closeResult:[{type:d}],previewListFontScale:[{type:d}]}});class X{open=!1;scanLinesEnabled=!0;editLockEnabled=!1;listFontScale=1.25;secondaryTabSoundLabel=null;mainTabSoundLabel=null;clickSoundLabel=null;closeResult=new l;save=new l;previewListFontScale=new l;draftScanLines=o(!0,...ngDevMode?[{debugName:"draftScanLines"}]:[]);draftEditLock=o(!1,...ngDevMode?[{debugName:"draftEditLock"}]:[]);draftListFontScale=o(1.25,...ngDevMode?[{debugName:"draftListFontScale"}]:[]);secondarySoundName=o(null,...ngDevMode?[{debugName:"secondarySoundName"}]:[]);mainSoundName=o(null,...ngDevMode?[{debugName:"mainSoundName"}]:[]);clickSoundName=o(null,...ngDevMode?[{debugName:"clickSoundName"}]:[]);secondarySoundFile=null;mainSoundFile=null;clickSoundFile=null;removeSecondary=!1;removeMain=!1;removeClick=!1;ngOnChanges(e){e.scanLinesEnabled&&this.draftScanLines.set(this.scanLinesEnabled),e.editLockEnabled&&this.draftEditLock.set(this.editLockEnabled),e.listFontScale&&this.draftListFontScale.set(this.listFontScale),e.secondaryTabSoundLabel&&this.secondarySoundName.set(this.secondaryTabSoundLabel),e.mainTabSoundLabel&&this.mainSoundName.set(this.mainTabSoundLabel),e.clickSoundLabel&&this.clickSoundName.set(this.clickSoundLabel),e.open&&this.open&&(this.secondarySoundFile=null,this.mainSoundFile=null,this.clickSoundFile=null,this.removeSecondary=!1,this.removeMain=!1,this.removeClick=!1)}closeModal(){this.closeResult.emit()}toggleScanLines(){this.draftScanLines.update(e=>!e)}toggleEditLock(){this.draftEditLock.update(e=>!e)}updateListFontScale(e){const t=Number(e);if(!Number.isFinite(t))return;const a=Math.min(150,Math.max(50,t))/100*1.25;this.draftListFontScale.set(a),this.previewListFontScale.emit(a)}listFontScalePercent(){return Math.round(this.draftListFontScale()/1.25*100)}onSecondarySoundSelected(e){const t=e.target,a=t.files?.[0]??null;this.secondarySoundFile=a,this.removeSecondary=!1,this.secondarySoundName.set(a?.name??this.secondaryTabSoundLabel),t&&(t.value="")}onMainSoundSelected(e){const t=e.target,a=t.files?.[0]??null;this.mainSoundFile=a,this.removeMain=!1,this.mainSoundName.set(a?.name??this.mainTabSoundLabel),t&&(t.value="")}onClickSoundSelected(e){const t=e.target,a=t.files?.[0]??null;this.clickSoundFile=a,this.removeClick=!1,this.clickSoundName.set(a?.name??this.clickSoundLabel),t&&(t.value="")}removeSecondarySound(){this.secondarySoundFile=null,this.removeSecondary=!0,this.secondarySoundName.set(null)}removeMainSound(){this.mainSoundFile=null,this.removeMain=!0,this.mainSoundName.set(null)}removeClickSound(){this.clickSoundFile=null,this.removeClick=!0,this.clickSoundName.set(null)}submit(e){e.preventDefault(),this.save.emit({scanLinesEnabled:this.draftScanLines(),editLockEnabled:this.draftEditLock(),listFontScale:this.draftListFontScale(),secondaryTabSoundFile:this.secondarySoundFile,mainTabSoundFile:this.mainSoundFile,clickSoundFile:this.clickSoundFile,removeSecondaryTabSound:this.removeSecondary,removeMainTabSound:this.removeMain,removeClickSound:this.removeClick})}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:X,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:X,isStandalone:!0,selector:"pip-boy-settings-modal",inputs:{open:"open",scanLinesEnabled:"scanLinesEnabled",editLockEnabled:"editLockEnabled",listFontScale:"listFontScale",secondaryTabSoundLabel:"secondaryTabSoundLabel",mainTabSoundLabel:"mainTabSoundLabel",clickSoundLabel:"clickSoundLabel"},outputs:{closeResult:"closeResult",save:"save",previewListFontScale:"previewListFontScale"},usesOnChanges:!0,ngImport:e,template:'@if (open) {\n <div\n class="settings-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="settings-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>Settings</span>\n </header>\n <form (submit)="submit($event)">\n <div class="settings-modal-body">\n <label class="settings-modal-field settings-modal-toggle">\n <span>Screen Line Effect</span>\n <input\n type="checkbox"\n [checked]="draftScanLines()"\n (change)="toggleScanLines()"\n hidden\n />\n <button\n type="button"\n class="settings-toggle"\n [class.is-on]="draftScanLines()"\n (click)="toggleScanLines()"\n >\n {{ draftScanLines() ? \'On\' : \'Off\' }}\n </button>\n </label>\n <label class="settings-modal-field settings-modal-toggle">\n <span>Edit Lock</span>\n <input\n type="checkbox"\n [checked]="draftEditLock()"\n (change)="toggleEditLock()"\n hidden\n />\n <button\n type="button"\n class="settings-toggle"\n [class.is-on]="draftEditLock()"\n (click)="toggleEditLock()"\n >\n {{ draftEditLock() ? \'Locked\' : \'Unlocked\' }}\n </button>\n </label>\n <label class="settings-modal-field settings-modal-slider">\n <span>Content Font Size</span>\n <div class="settings-slider-row">\n <input\n type="range"\n min="50"\n max="150"\n step="1"\n [value]="listFontScalePercent()"\n (input)="updateListFontScale($any($event.target).value)"\n />\n <span class="settings-slider-value">\n {{ listFontScalePercent() }}%\n </span>\n </div>\n </label>\n <div class="settings-divider"></div>\n <div class="settings-modal-field">\n <span>Secondary Tab Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="secondarySoundInput.click()"\n >\n {{ secondarySoundName() ?? \'Select Sound\' }}\n </button>\n @if (secondarySoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeSecondarySound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #secondarySoundInput\n type="file"\n accept="audio/*"\n (change)="onSecondarySoundSelected($event)"\n />\n </div>\n <div class="settings-modal-field">\n <span>Main Tab Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="mainSoundInput.click()"\n >\n {{ mainSoundName() ?? \'Select Sound\' }}\n </button>\n @if (mainSoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeMainSound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #mainSoundInput\n type="file"\n accept="audio/*"\n (change)="onMainSoundSelected($event)"\n />\n </div>\n <div class="settings-divider"></div>\n <div class="settings-modal-field">\n <span>Click Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="clickSoundInput.click()"\n >\n {{ clickSoundName() ?? \'Select Sound\' }}\n </button>\n @if (clickSoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeClickSound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #clickSoundInput\n type="file"\n accept="audio/*"\n (change)="onClickSoundSelected($event)"\n />\n </div>\n </div>\n <div class="settings-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.settings-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.settings-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:22rem;width:min(90vw,22rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.settings-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.settings-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.settings-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.settings-modal-field{display:flex;flex-direction:column;gap:.5rem}.settings-modal-slider{gap:.65rem}.settings-slider-row{align-items:center;display:flex;gap:.75rem}.settings-slider-row input[type=range]{appearance:none;background:#0fbb6b33;border-radius:999px;cursor:pointer;flex:1 1 auto;height:.35rem;outline:none}.settings-slider-row input[type=range]::-webkit-slider-thumb{appearance:none;background:#0fbb6b;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.settings-slider-row input[type=range]::-moz-range-thumb{background:#0fbb6b;border:none;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.settings-slider-value{font-size:clamp(.75rem,.75rem + (.85rem - .75rem) * (100vw - 360px) / (1200px - 360px),.85rem);color:#0fbb6bcc;letter-spacing:.08em;min-width:3.25rem;text-align:right}.settings-modal-toggle{align-items:center;flex-direction:row;justify-content:space-between}.settings-divider{border-top:1px solid rgba(15,187,107,.2);margin:.5rem 0}.settings-sound-actions{display:flex;gap:.5rem;align-items:center}.settings-sound-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;flex:1 1 auto;padding:.5rem .75rem;text-align:left;text-transform:uppercase}.settings-sound-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-sound-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.4rem .7rem;text-transform:uppercase}.settings-sound-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-modal input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.settings-toggle{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:999px;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.35rem .9rem;text-transform:uppercase}.settings-toggle.is-on{background:#0fbb6b33;border-color:#0fbb6b}.settings-toggle:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.settings-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.settings-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:X,decorators:[{type:n,args:[{selector:"pip-boy-settings-modal",standalone:!0,template:'@if (open) {\n <div\n class="settings-modal-backdrop"\n (click)="closeModal()"\n (keydown.enter)="closeModal()"\n (keydown.space)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="settings-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>\n <span>Settings</span>\n </header>\n <form (submit)="submit($event)">\n <div class="settings-modal-body">\n <label class="settings-modal-field settings-modal-toggle">\n <span>Screen Line Effect</span>\n <input\n type="checkbox"\n [checked]="draftScanLines()"\n (change)="toggleScanLines()"\n hidden\n />\n <button\n type="button"\n class="settings-toggle"\n [class.is-on]="draftScanLines()"\n (click)="toggleScanLines()"\n >\n {{ draftScanLines() ? \'On\' : \'Off\' }}\n </button>\n </label>\n <label class="settings-modal-field settings-modal-toggle">\n <span>Edit Lock</span>\n <input\n type="checkbox"\n [checked]="draftEditLock()"\n (change)="toggleEditLock()"\n hidden\n />\n <button\n type="button"\n class="settings-toggle"\n [class.is-on]="draftEditLock()"\n (click)="toggleEditLock()"\n >\n {{ draftEditLock() ? \'Locked\' : \'Unlocked\' }}\n </button>\n </label>\n <label class="settings-modal-field settings-modal-slider">\n <span>Content Font Size</span>\n <div class="settings-slider-row">\n <input\n type="range"\n min="50"\n max="150"\n step="1"\n [value]="listFontScalePercent()"\n (input)="updateListFontScale($any($event.target).value)"\n />\n <span class="settings-slider-value">\n {{ listFontScalePercent() }}%\n </span>\n </div>\n </label>\n <div class="settings-divider"></div>\n <div class="settings-modal-field">\n <span>Secondary Tab Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="secondarySoundInput.click()"\n >\n {{ secondarySoundName() ?? \'Select Sound\' }}\n </button>\n @if (secondarySoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeSecondarySound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #secondarySoundInput\n type="file"\n accept="audio/*"\n (change)="onSecondarySoundSelected($event)"\n />\n </div>\n <div class="settings-modal-field">\n <span>Main Tab Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="mainSoundInput.click()"\n >\n {{ mainSoundName() ?? \'Select Sound\' }}\n </button>\n @if (mainSoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeMainSound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #mainSoundInput\n type="file"\n accept="audio/*"\n (change)="onMainSoundSelected($event)"\n />\n </div>\n <div class="settings-divider"></div>\n <div class="settings-modal-field">\n <span>Click Sound</span>\n <div class="settings-sound-actions">\n <button\n type="button"\n class="settings-sound-button"\n (click)="clickSoundInput.click()"\n >\n {{ clickSoundName() ?? \'Select Sound\' }}\n </button>\n @if (clickSoundName()) {\n <button\n type="button"\n class="settings-sound-remove"\n (click)="removeClickSound()"\n >\n Remove\n </button>\n }\n </div>\n <input\n #clickSoundInput\n type="file"\n accept="audio/*"\n (change)="onClickSoundSelected($event)"\n />\n </div>\n </div>\n <div class="settings-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.settings-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:120}.settings-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:22rem;width:min(90vw,22rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.settings-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.settings-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.settings-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.settings-modal-field{display:flex;flex-direction:column;gap:.5rem}.settings-modal-slider{gap:.65rem}.settings-slider-row{align-items:center;display:flex;gap:.75rem}.settings-slider-row input[type=range]{appearance:none;background:#0fbb6b33;border-radius:999px;cursor:pointer;flex:1 1 auto;height:.35rem;outline:none}.settings-slider-row input[type=range]::-webkit-slider-thumb{appearance:none;background:#0fbb6b;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.settings-slider-row input[type=range]::-moz-range-thumb{background:#0fbb6b;border:none;border-radius:999px;cursor:pointer;height:.9rem;width:.9rem}.settings-slider-value{font-size:clamp(.75rem,.75rem + (.85rem - .75rem) * (100vw - 360px) / (1200px - 360px),.85rem);color:#0fbb6bcc;letter-spacing:.08em;min-width:3.25rem;text-align:right}.settings-modal-toggle{align-items:center;flex-direction:row;justify-content:space-between}.settings-divider{border-top:1px solid rgba(15,187,107,.2);margin:.5rem 0}.settings-sound-actions{display:flex;gap:.5rem;align-items:center}.settings-sound-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;flex:1 1 auto;padding:.5rem .75rem;text-align:left;text-transform:uppercase}.settings-sound-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-sound-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.4rem .7rem;text-transform:uppercase}.settings-sound-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-modal input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.settings-toggle{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:999px;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.35rem .9rem;text-transform:uppercase}.settings-toggle.is-on{background:#0fbb6b33;border-color:#0fbb6b}.settings-toggle:hover{border-color:#0fbb6b;background:#0fbb6b1f}.settings-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.settings-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.settings-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],propDecorators:{open:[{type:m}],scanLinesEnabled:[{type:m}],editLockEnabled:[{type:m}],listFontScale:[{type:m}],secondaryTabSoundLabel:[{type:m}],mainTabSoundLabel:[{type:m}],clickSoundLabel:[{type:m}],closeResult:[{type:d}],save:[{type:d}],previewListFontScale:[{type:d}]}});class Z{constructor(){r(()=>{this.open()&&(this.draftImageUrl.set(this.imageUrl()),this.draftImageName.set(null),this.draftImageFile.set(null),this.removedImage.set(!1),this.clearPreviewUrl())})}open=t(!1,...ngDevMode?[{debugName:"open"}]:[]);title=t("Map Image",...ngDevMode?[{debugName:"title"}]:[]);imageUrl=t(null,...ngDevMode?[{debugName:"imageUrl"}]:[]);closeResult=u();save=u();draftImageName=o(null,...ngDevMode?[{debugName:"draftImageName"}]:[]);draftImageUrl=o(null,...ngDevMode?[{debugName:"draftImageUrl"}]:[]);draftImageFile=o(null,...ngDevMode?[{debugName:"draftImageFile"}]:[]);removedImage=o(!1,...ngDevMode?[{debugName:"removedImage"}]:[]);previewUrl=null;closeModal(){this.clearPreviewUrl(),this.closeResult.emit()}onImageSelected(e){const t=e.target,a=t.files?.[0]??null;this.draftImageName.set(a?a.name:null),a&&(this.removedImage.set(!1),this.draftImageFile.set(a),this.setPreviewUrl(URL.createObjectURL(a)),t.value="")}removeImage(){this.draftImageName.set(null),this.draftImageUrl.set(null),this.draftImageFile.set(null),this.removedImage.set(!0),this.clearPreviewUrl()}submit(e){e?.preventDefault(),this.save.emit({imageFile:this.draftImageFile(),removeImage:this.removedImage()}),this.clearPreviewUrl(),this.closeResult.emit()}setPreviewUrl(e){this.clearPreviewUrl(),this.previewUrl=e,this.draftImageUrl.set(e)}clearPreviewUrl(){this.previewUrl&&(URL.revokeObjectURL(this.previewUrl),this.previewUrl=null)}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Z,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:Z,isStandalone:!0,selector:"pip-boy-map-image-modal",inputs:{open:{classPropertyName:"open",publicName:"open",isSignal:!0,isRequired:!1,transformFunction:null},title:{classPropertyName:"title",publicName:"title",isSignal:!0,isRequired:!1,transformFunction:null},imageUrl:{classPropertyName:"imageUrl",publicName:"imageUrl",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{closeResult:"closeResult",save:"save"},ngImport:e,template:'@if (open()) {\n <div\n class="map-image-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="map-image-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title() }}</header>\n <form (submit)="submit($event)">\n <div class="map-image-modal-body">\n <div class="map-image-modal-image">\n <button\n type="button"\n class="map-image-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="map-image-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Map preview" />\n }\n </div>\n </div>\n <div class="map-image-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.map-image-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.map-image-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:28rem;width:min(90vw,28rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.map-image-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.map-image-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.map-image-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.map-image-modal-image{display:flex;flex-direction:column;gap:.75rem}.map-image-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.map-image-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:12rem;object-fit:contain;padding:.5rem}.map-image-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.map-image-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-image-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.map-image-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-image-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.map-image-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.map-image-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:Z,decorators:[{type:n,args:[{selector:"pip-boy-map-image-modal",standalone:!0,template:'@if (open()) {\n <div\n class="map-image-modal-backdrop"\n (click)="closeModal()"\n (keydown.escape)="closeModal()"\n tabindex="0"\n role="button"\n >\n <div\n class="map-image-modal"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n tabindex="0"\n role="dialog"\n >\n <header>{{ title() }}</header>\n <form (submit)="submit($event)">\n <div class="map-image-modal-body">\n <div class="map-image-modal-image">\n <button\n type="button"\n class="map-image-modal-image-button"\n (click)="modalImageInput.click()"\n >\n {{ draftImageName() ? draftImageName() : \'Select Image\' }}\n </button>\n @if (draftImageUrl()) {\n <button\n type="button"\n class="map-image-modal-image-remove"\n (click)="removeImage()"\n >\n Remove Image\n </button>\n }\n <input\n #modalImageInput\n type="file"\n accept="image/*"\n (change)="onImageSelected($event)"\n />\n @if (draftImageUrl()) {\n <img [src]="draftImageUrl()" alt="Map preview" />\n }\n </div>\n </div>\n <div class="map-image-modal-actions">\n <button type="button" (click)="closeModal()">Cancel</button>\n <button type="submit">Save</button>\n </div>\n </form>\n </div>\n </div>\n}\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.map-image-modal-backdrop{align-items:center;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background:#0009;display:flex;inset:0;justify-content:center;padding:1rem;position:fixed;z-index:50}.map-image-modal{background:#062114f2;border:1px solid rgba(15,187,107,.4);border-radius:.75rem;box-shadow:0 0 30px #0009;margin:2.5rem;max-height:calc(100vh - 4rem);max-height:calc(100svh - 4rem);max-width:28rem;width:min(90vw,28rem);display:flex;flex-direction:column;overflow:hidden;padding:1.5rem}.map-image-modal header{font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);letter-spacing:.08em;margin-bottom:1rem;text-transform:uppercase}.map-image-modal form{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;gap:1rem}.map-image-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:.25rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:1rem}.map-image-modal-image{display:flex;flex-direction:column;gap:.75rem}.map-image-modal-image input{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.map-image-modal-image img{border:1px solid rgba(15,187,107,.35);max-height:12rem;object-fit:contain;padding:.5rem}.map-image-modal-image-button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.6rem .75rem;text-align:left;text-transform:uppercase}.map-image-modal-image-button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-image-modal-image-remove{background:transparent;border:1px solid rgba(15,187,107,.4);border-radius:.5rem;color:#0fbb6b;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.45rem .75rem;text-transform:uppercase}.map-image-modal-image-remove:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-image-modal-actions{display:flex;gap:.75rem;justify-content:flex-end}.map-image-modal-actions button{background:transparent;border:1px solid rgba(15,187,107,.5);border-radius:.5rem;color:#0fbb6b;cursor:pointer;padding:.5rem .9rem;text-transform:uppercase}.map-image-modal-actions button:hover{border-color:#0fbb6b;background:#0fbb6b1f}\n"]}]}],ctorParameters:()=>[],propDecorators:{open:[{type:e.Input,args:[{isSignal:!0,alias:"open",required:!1}]}],title:[{type:e.Input,args:[{isSignal:!0,alias:"title",required:!1}]}],imageUrl:[{type:e.Input,args:[{isSignal:!0,alias:"imageUrl",required:!1}]}],closeResult:[{type:e.Output,args:["closeResult"]}],save:[{type:e.Output,args:["save"]}]}});class ee{returnToUrl=t("https://www.pip-boy.com",...ngDevMode?[{debugName:"returnToUrl"}]:[]);state=s(w);settings=s(B);imageStore=s(x);soundStore=s(O);appVersion=E;tabsOpen=o(!1,...ngDevMode?[{debugName:"tabsOpen"}]:[]);showResetModal=o(!1,...ngDevMode?[{debugName:"showResetModal"}]:[]);showExitModal=o(!1,...ngDevMode?[{debugName:"showExitModal"}]:[]);showBugModal=o(!1,...ngDevMode?[{debugName:"showBugModal"}]:[]);showSettingsModal=o(!1,...ngDevMode?[{debugName:"showSettingsModal"}]:[]);settingsListFontScaleSnapshot=o(null,...ngDevMode?[{debugName:"settingsListFontScaleSnapshot"}]:[]);showWelcomeModal=o(!0,...ngDevMode?[{debugName:"showWelcomeModal"}]:[]);mapImageModal=o(null,...ngDevMode?[{debugName:"mapImageModal"}]:[]);localMapZoom=o(1,...ngDevMode?[{debugName:"localMapZoom"}]:[]);worldMapZoom=o(1,...ngDevMode?[{debugName:"worldMapZoom"}]:[]);extraOptionModal=o(null,...ngDevMode?[{debugName:"extraOptionModal"}]:[]);tabsActionsLeftOpen=o(!1,...ngDevMode?[{debugName:"tabsActionsLeftOpen"}]:[]);tabsActionsRightOpen=o(!1,...ngDevMode?[{debugName:"tabsActionsRightOpen"}]:[]);viewportWidth=o("undefined"==typeof window?0:window.innerWidth,...ngDevMode?[{debugName:"viewportWidth"}]:[]);mapImageModalTitle=c(()=>"WORLD"===this.mapImageModal()?"World Map":"Local Map",...ngDevMode?[{debugName:"mapImageModalTitle"}]:[]);mapImageModalImage=c(()=>{const e="WORLD"===this.mapImageModal()?this.settings.worldMapImage():this.settings.localMapImage();return this.imageStore.getImageUrl(e)},...ngDevMode?[{debugName:"mapImageModalImage"}]:[]);secondaryTabSoundLabel=c(()=>this.soundStore.getSoundLabel(this.settings.secondaryTabSoundId()),...ngDevMode?[{debugName:"secondaryTabSoundLabel"}]:[]);mainTabSoundLabel=c(()=>this.soundStore.getSoundLabel(this.settings.mainTabSoundId()),...ngDevMode?[{debugName:"mainTabSoundLabel"}]:[]);clickSoundLabel=c(()=>this.soundStore.getSoundLabel(this.settings.clickSoundId()),...ngDevMode?[{debugName:"clickSoundLabel"}]:[]);isScreenTooSmall=c(()=>this.viewportWidth()<650,...ngDevMode?[{debugName:"isScreenTooSmall"}]:[]);extraOptionTitle=c(()=>{switch(this.extraOptionModal()){case"RADAWAY":case"RADX":return"Edit Text";default:return""}},...ngDevMode?[{debugName:"extraOptionTitle"}]:[]);extraOptionValue=c(()=>{const e=this.extraOptionModal();return"STIMPAK"===e?this.settings.stimpakLabel():"LIMBS"===e?this.settings.limbLabel():"RADAWAY"===e?this.settings.radAwayLabel():"RADX"===e?this.settings.radXLabel():""},...ngDevMode?[{debugName:"extraOptionValue"}]:[]);toggleTabs(){this.tabsOpen.update(e=>!e)}toggleTabsActions(e){"left"===e?(this.tabsActionsLeftOpen.update(e=>!e),this.tabsActionsRightOpen.set(!1)):(this.tabsActionsRightOpen.update(e=>!e),this.tabsActionsLeftOpen.set(!1))}onResize(){this.viewportWidth.set(window.innerWidth)}async saveSettingsToFile(){const e=this.settings.exportSettingsSnapshot(),t=this.collectImageIds(e),a=this.collectSoundIds(e),n=[],o=[],i=new f;for(const e of t){const t=await this.imageStore.getRecord(e);if(!t)continue;const a=this.getExtension(t.fileName,t.mime);i.file(`images/${e}${a}`,t.blob),n.push({id:e,fileName:t.fileName,mime:t.mime})}for(const e of a){const t=await this.soundStore.getRecord(e);if(!t)continue;const a=this.getSoundExtension(t.fileName,t.mime);i.file(`sounds/${e}${a}`,t.blob),o.push({id:e,fileName:t.fileName,mime:t.mime})}const r={version:1,images:n,sounds:o,pipBoy3000Settings:e};i.file("settings.json",JSON.stringify(r));const s=await i.generateAsync({type:"blob"}),l=URL.createObjectURL(s),d=document.createElement("a");d.href=l,d.download="pip-boy-export.zip",d.click(),URL.revokeObjectURL(l)}openResetModal(){this.showResetModal.set(!0)}closeResetModal(){this.showResetModal.set(!1)}confirmReset(){this.settings.resetToDefaults(),this.closeResetModal(),this.showWelcomeModal.set(!0)}openExitModal(){this.showExitModal.set(!0)}closeExitModal(){this.showExitModal.set(!1)}confirmExit(){window.location.href=this.returnToUrl()}openBugModal(){this.showBugModal.set(!0)}closeBugModal(){this.showBugModal.set(!1)}confirmBugReport(){window.open("https://github.com/CodyTolene/pip-terminal/issues","_blank"),this.closeBugModal()}openSettingsModal(){this.settingsListFontScaleSnapshot.set(this.settings.listFontScale()),this.showSettingsModal.set(!0)}closeSettingsModal(){this.showSettingsModal.set(!1)}cancelSettingsModal(){const e=this.settingsListFontScaleSnapshot();null!==e&&this.settings.listFontScale.set(e),this.settingsListFontScaleSnapshot.set(null),this.showSettingsModal.set(!1)}closeWelcomeModal(){this.showWelcomeModal.set(!1)}saveSettingsModal(e){this.settings.scanLinesEnabled.set(e.scanLinesEnabled),this.settings.editLockEnabled.set(e.editLockEnabled),this.settings.listFontScale.set(e.listFontScale),this.settingsListFontScaleSnapshot.set(null),e.removeSecondaryTabSound&&this.settings.secondaryTabSoundId.set(null),e.removeMainTabSound&&this.settings.mainTabSoundId.set(null),e.removeClickSound&&this.settings.clickSoundId.set(null),e.secondaryTabSoundFile&&this.soundStore.saveFile(e.secondaryTabSoundFile).then(e=>this.settings.secondaryTabSoundId.set(e.id)),e.mainTabSoundFile&&this.soundStore.saveFile(e.mainTabSoundFile).then(e=>this.settings.mainTabSoundId.set(e.id)),e.clickSoundFile&&this.soundStore.saveFile(e.clickSoundFile).then(e=>this.settings.clickSoundId.set(e.id)),this.closeSettingsModal()}previewListFontScale(e){this.settings.listFontScale.set(e)}openGithubProfile(){window.open("https://github.com/CodyTolene","_blank")}selectPrimary(e){this.soundStore.playSound(this.settings.mainTabSoundId()),this.state.selectPrimary(e)}selectSecondary(e){this.soundStore.playSound(this.settings.secondaryTabSoundId()),this.state.selectSecondary(e)}openExtraOptionModal(e){this.settings.editLockEnabled()||this.extraOptionModal.set(e)}closeExtraOptionModal(){this.extraOptionModal.set(null)}saveExtraOptionModal(e){const t=this.extraOptionModal();"STIMPAK"===t?this.settings.stimpakLabel.set(e):"LIMBS"===t?this.settings.limbLabel.set(e):"RADAWAY"===t?this.settings.radAwayLabel.set(e):"RADX"===t&&this.settings.radXLabel.set(e),this.closeExtraOptionModal()}async loadSettingsFromFile(e){const t=e.target,a=t.files?.[0]??null;if(!a)return;const n=await f.loadAsync(a),o=n.file("settings.json");if(!o)return void(t.value="");const i=await o.async("string"),r=JSON.parse(i),s=r.pipBoy3000Settings??r;if(Array.isArray(r.images))for(const e of r.images){const t=this.getExtension(e.fileName,e.mime),a=n.file(`images/${e.id}${t}`)??n.file(new RegExp(`^images/${e.id}\\.`))?.[0];if(!a)continue;const o=await a.async("blob");await this.imageStore.saveBlobWithId(e.id,o,e.fileName,e.mime)}if(Array.isArray(r.sounds))for(const e of r.sounds){const t=this.getSoundExtension(e.fileName,e.mime),a=n.file(`sounds/${e.id}${t}`)??n.file(new RegExp(`^sounds/${e.id}\\.`))?.[0];if(!a)continue;const o=await a.async("blob");await this.soundStore.saveBlobWithId(e.id,o,e.fileName,e.mime)}this.settings.importSettingsSnapshot(s),t.value=""}collectImageIds(e){const t=new Set,a=e=>{e&&t.add(e)};return e.weaponItems.forEach(e=>a(e.imageId)),e.apparelItems.forEach(e=>a(e.imageId)),e.aidItems.forEach(e=>a(e.imageId)),e.miscItems.forEach(e=>a(e.imageId)),e.ammoItems.forEach(e=>a(e.imageId)),e.specialItems.forEach(e=>a(e.imageId)),e.skillItems.forEach(e=>a(e.imageId)),e.perkItems.forEach(e=>a(e.imageId)),e.vaultBoyImages.forEach(e=>a(e)),a(e.localMapImage),a(e.worldMapImage),Array.from(t)}collectSoundIds(e){const t=new Set,a=e=>{e&&t.add(e)};return a(e.secondaryTabSoundId),a(e.mainTabSoundId),a(e.clickSoundId),e.notesItems.forEach(e=>a(e.soundId)),e.radioItems.forEach(e=>a(e.soundId)),Array.from(t)}getExtension(e,t){const a=e.match(/\.[a-z0-9]+$/i);return a?a[0]:this.imageStore.extensionFromMime(t)}getSoundExtension(e,t){const a=e.match(/\.[a-z0-9]+$/i);return a?a[0]:this.soundStore.extensionFromMime(t)}openMapImageModal(e){this.mapImageModal.set(e)}closeMapImageModal(){this.mapImageModal.set(null)}zoomMap(e,t){const a="WORLD"===e?this.worldMapZoom:this.localMapZoom,n=Math.min(3,Math.max(.5,a()+t));a.set(Number(n.toFixed(2)))}resetMapZoom(e){"WORLD"===e?this.worldMapZoom.set(1):this.localMapZoom.set(1)}async saveMapImageModal(e){const t=this.mapImageModal();if(t){if(e.removeImage)return"WORLD"===t?this.settings.worldMapImage.set(null):this.settings.localMapImage.set(null),void this.closeMapImageModal();if(e.imageFile){const a=await this.imageStore.saveFile(e.imageFile);"WORLD"===t?this.settings.worldMapImage.set(a.id):this.settings.localMapImage.set(a.id)}this.closeMapImageModal()}}static"ɵfac"=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:ee,deps:[],target:e.ɵɵFactoryTarget.Component});static"ɵcmp"=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"21.0.8",type:ee,isStandalone:!0,selector:"pip-boy-3000",inputs:{returnToUrl:{classPropertyName:"returnToUrl",publicName:"returnToUrl",isSignal:!0,isRequired:!1,transformFunction:null}},host:{listeners:{"window:resize":"onResize()"}},providers:[w],ngImport:e,template:'<main\n #screen\n class="screen"\n [style.--list-font-scale]="settings.listFontScale()"\n>\n @if (settings.scanLinesEnabled()) {\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="300"\n />\n }\n @if (isScreenTooSmall()) {\n <div class="screen-size-overlay" role="alert" aria-live="assertive">\n Screen is too small.<br />Please rotate to landscape.\n </div>\n }\n \x3c!-- HEADER --\x3e\n <pip-boy-3000-header />\n \x3c!-- CONTENT --\x3e\n <section class="content">\n @if (state.primary() === \'STATS\') {\n @if (state.secondary() === \'STATUS\') {\n <div class="status-content">\n <nav class="column sub-content" aria-label="Status tabs">\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'CND\'"\n (click)="state.selectTertiary(\'CND\')"\n >\n CND\n </button>\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'RAD\'"\n (click)="state.selectTertiary(\'RAD\')"\n >\n RAD\n </button>\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'EFF\'"\n (click)="state.selectTertiary(\'EFF\')"\n >\n EFF\n </button>\n </nav>\n @if (state.tertiary() === \'CND\') {\n <pip-boy-cnd-status />\n } @else if (state.tertiary() === \'RAD\') {\n <pip-boy-radiation-meter />\n <div class="extra-options">\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'RADAWAY\')"\n >\n {{ settings.radAwayLabel() }}\n </button>\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'RADX\')"\n >\n {{ settings.radXLabel() }}\n </button>\n </div>\n } @else if (state.tertiary() === \'EFF\') {\n <pip-boy-eff-layout />\n }\n </div>\n } @else if (state.secondary() === \'S.P.E.C.I.A.L.\') {\n <pip-boy-stats-layout\n category="SPECIAL"\n valueLabel="Rating"\n [valueMin]="1"\n [valueMax]="10"\n />\n } @else if (state.secondary() === \'SKILLS\') {\n <pip-boy-stats-layout\n category="SKILLS"\n valueLabel="Skill"\n [valueMin]="0"\n [valueMax]="100"\n />\n } @else if (state.secondary() === \'PERKS\') {\n <pip-boy-stats-layout\n category="PERKS"\n valueLabel="Rank"\n [valueMin]="0"\n />\n } @else if (state.secondary() === \'GENERAL\') {\n <pip-boy-stats-layout category="GENERAL" valueLabel="Value" />\n }\n } @else if (state.primary() === \'ITEMS\') {\n @if (state.secondary() === \'WEAPONS\') {\n <pip-boy-inventory-layout category="WEAPONS" />\n } @else if (state.secondary() === \'APPAREL\') {\n <pip-boy-inventory-layout category="APPAREL" />\n } @else if (state.secondary() === \'AID\') {\n <pip-boy-inventory-layout category="AID" />\n } @else if (state.secondary() === \'MISC\') {\n <pip-boy-inventory-layout category="MISC" />\n } @else if (state.secondary() === \'AMMO\') {\n <pip-boy-inventory-layout category="AMMO" />\n }\n } @else if (state.primary() === \'DATA\') {\n @if (state.secondary() === \'LOCAL MAP\') {\n <div class="map-panel">\n <button\n type="button"\n class="map-view"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openMapImageModal(\'LOCAL\')"\n >\n @if (settings.localMapImage()) {\n <img\n [src]="imageStore.getImageUrl(settings.localMapImage())"\n alt="Local map"\n [style.transform]="\'scale(\' + localMapZoom() + \')\'"\n style="transform-origin: top left"\n />\n } @else {\n <span>CLICK TO UPLOAD IMAGE</span>\n }\n </button>\n @if (settings.localMapImage()) {\n <div\n class="map-zoom"\n role="group"\n tabindex="0"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n >\n <button type="button" (click)="zoomMap(\'LOCAL\', 0.2)">+</button>\n <button type="button" (click)="zoomMap(\'LOCAL\', -0.2)">-</button>\n <button type="button" (click)="resetMapZoom(\'LOCAL\')">\n Reset\n </button>\n </div>\n }\n </div>\n } @else if (state.secondary() === \'WORLD MAP\') {\n <div class="map-panel">\n <button\n type="button"\n class="map-view"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openMapImageModal(\'WORLD\')"\n >\n @if (settings.worldMapImage()) {\n <img\n [src]="imageStore.getImageUrl(settings.worldMapImage())"\n alt="World map"\n [style.transform]="\'scale(\' + worldMapZoom() + \')\'"\n style="transform-origin: top left"\n />\n } @else {\n <span>CLICK TO UPLOAD IMAGE</span>\n }\n </button>\n @if (settings.worldMapImage()) {\n <div\n class="map-zoom"\n role="group"\n tabindex="0"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n >\n <button type="button" (click)="zoomMap(\'WORLD\', 0.2)">+</button>\n <button type="button" (click)="zoomMap(\'WORLD\', -0.2)">-</button>\n <button type="button" (click)="resetMapZoom(\'WORLD\')">\n Reset\n </button>\n </div>\n }\n </div>\n } @else if (state.secondary() === \'QUESTS\') {\n <pip-boy-quests-layout />\n } @else if (state.secondary() === \'NOTES\') {\n <pip-boy-music-layout category="NOTES" />\n } @else if (state.secondary() === \'RADIO\') {\n <pip-boy-music-layout category="RADIO" />\n }\n }\n </section>\n \x3c!-- SUB TABS --\x3e\n <section class="sub-tabs">\n @if (state.primary() === \'STATS\') {\n <nav aria-label="Stats tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'STATUS\'"\n (click)="selectSecondary(\'STATUS\')"\n >\n Status\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'S.P.E.C.I.A.L.\'"\n (click)="selectSecondary(\'S.P.E.C.I.A.L.\')"\n >\n S.P.E.C.I.A.L.\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'SKILLS\'"\n (click)="selectSecondary(\'SKILLS\')"\n >\n Skills\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'PERKS\'"\n (click)="selectSecondary(\'PERKS\')"\n >\n Perks\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'GENERAL\'"\n (click)="selectSecondary(\'GENERAL\')"\n >\n General\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n } @else if (state.primary() === \'ITEMS\') {\n <nav aria-label="Items tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'WEAPONS\'"\n (click)="selectSecondary(\'WEAPONS\')"\n >\n Weapons\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'APPAREL\'"\n (click)="selectSecondary(\'APPAREL\')"\n >\n Apparel\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'AID\'"\n (click)="selectSecondary(\'AID\')"\n >\n Aid\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'MISC\'"\n (click)="selectSecondary(\'MISC\')"\n >\n Misc\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'AMMO\'"\n (click)="selectSecondary(\'AMMO\')"\n >\n Ammo\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n } @else if (state.primary() === \'DATA\') {\n <nav aria-label="Data tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'LOCAL MAP\'"\n (click)="selectSecondary(\'LOCAL MAP\')"\n >\n Local Map\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'WORLD MAP\'"\n (click)="selectSecondary(\'WORLD MAP\')"\n >\n World Map\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'QUESTS\'"\n (click)="selectSecondary(\'QUESTS\')"\n >\n Quests\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'NOTES\'"\n (click)="selectSecondary(\'NOTES\')"\n >\n Notes\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'RADIO\'"\n (click)="selectSecondary(\'RADIO\')"\n >\n Radio\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n }\n </section>\n \x3c!-- MAIN TABS --\x3e\n <section class="tabs" [class.is-collapsed]="!tabsOpen()">\n <button\n type="button"\n class="tabs-toggle"\n aria-label="Toggle main tabs"\n [attr.aria-expanded]="tabsOpen()"\n aria-controls="main-tabs"\n (click)="toggleTabs()"\n >\n <span class="tabs-toggle-label tabs-toggle-label--state">\n {{ tabsOpen() ? \'CLOSE\' : \'OPEN\' }}\n </span>\n <span class="caret" aria-hidden="true"></span>\n <span class="tabs-toggle-label tabs-toggle-label--menu">MENU</span>\n </button>\n <nav id="main-tabs" aria-label="Main tabs">\n <div\n class="tabs-actions tabs-actions--left"\n [class.is-open]="tabsActionsLeftOpen()"\n >\n <button\n type="button"\n class="tabs-actions-toggle"\n aria-label="Open settings actions"\n (click)="toggleTabsActions(\'left\')"\n >\n <span class="tabs-actions-icon" aria-hidden="true"></span>\n </button>\n <div class="tabs-actions-menu">\n <button\n type="button"\n class="action-button"\n aria-label="Save settings"\n title="Save settings"\n (click)="saveSettingsToFile()"\n >\n Save\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Load settings"\n title="Load settings"\n (click)="loadSettingsInput.click()"\n >\n Load\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Reset settings"\n title="Reset settings"\n (click)="openResetModal()"\n >\n Reset\n </button>\n <input\n #loadSettingsInput\n type="file"\n accept=".zip,application/zip"\n (change)="loadSettingsFromFile($event)"\n />\n </div>\n </div>\n <button\n type="button"\n [class.is-active]="state.primary() === \'STATS\'"\n (click)="selectPrimary(\'STATS\')"\n >\n <span>STATS</span>\n </button>\n <button\n type="button"\n [class.is-active]="state.primary() === \'ITEMS\'"\n (click)="selectPrimary(\'ITEMS\')"\n >\n <span>ITEMS</span>\n </button>\n <button\n type="button"\n [class.is-active]="state.primary() === \'DATA\'"\n (click)="selectPrimary(\'DATA\')"\n >\n <span>DATA</span>\n </button>\n <div\n class="tabs-actions tabs-actions--right"\n [class.is-open]="tabsActionsRightOpen()"\n >\n <button\n type="button"\n class="tabs-actions-toggle"\n aria-label="Open utility actions"\n (click)="toggleTabsActions(\'right\')"\n >\n <span class="tabs-actions-icon" aria-hidden="true"></span>\n </button>\n <div class="tabs-actions-menu">\n <button\n type="button"\n class="action-button"\n aria-label="Open GitHub profile"\n title="Open GitHub profile"\n (click)="openGithubProfile()"\n >\n ❤\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Open settings"\n title="Settings"\n (click)="openSettingsModal()"\n >\n Settings\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Report a bug"\n title="Report a bug"\n (click)="openBugModal()"\n >\n Bug\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Reset settings"\n title="Exit"\n (click)="openExitModal()"\n >\n Exit\n </button>\n <input\n #loadSettingsInput\n type="file"\n accept=".zip,application/zip"\n (change)="loadSettingsFromFile($event)"\n />\n </div>\n </div>\n @if (tabsOpen()) {\n <div class="tabs-version">v{{ appVersion }}</div>\n }\n </nav>\n </section>\n <pip-boy-welcome-modal\n [open]="showWelcomeModal()"\n [listFontScale]="settings.listFontScale()"\n (previewListFontScale)="previewListFontScale($event)"\n (closeResult)="closeWelcomeModal()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showResetModal()"\n title="Reset Settings"\n message="This will reset all values back to defaults. This cannot be undone."\n confirmLabel="Reset"\n (closeResult)="closeResetModal()"\n (confirm)="confirmReset()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showExitModal()"\n title="Exit"\n message="Are you sure you want to leave this screen?"\n confirmLabel="Exit"\n (closeResult)="closeExitModal()"\n (confirm)="confirmExit()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showBugModal()"\n title="Report a bug"\n message="Would you like to report a bug?"\n confirmLabel="Yes"\n cancelLabel="No"\n (closeResult)="closeBugModal()"\n (confirm)="confirmBugReport()"\n />\n <pip-boy-map-image-modal\n [open]="mapImageModal() !== null"\n [title]="mapImageModalTitle()"\n [imageUrl]="mapImageModalImage()"\n (closeResult)="closeMapImageModal()"\n (save)="saveMapImageModal($event)"\n />\n <pip-boy-settings-modal\n [open]="showSettingsModal()"\n [scanLinesEnabled]="settings.scanLinesEnabled()"\n [editLockEnabled]="settings.editLockEnabled()"\n [listFontScale]="settings.listFontScale()"\n [secondaryTabSoundLabel]="secondaryTabSoundLabel()"\n [mainTabSoundLabel]="mainTabSoundLabel()"\n [clickSoundLabel]="clickSoundLabel()"\n (closeResult)="cancelSettingsModal()"\n (previewListFontScale)="previewListFontScale($event)"\n (save)="saveSettingsModal($event)"\n />\n <pip-boy-name-edit-modal\n [open]="extraOptionModal() !== null"\n [value]="extraOptionValue()"\n [title]="extraOptionTitle()"\n placeholder="Value"\n [allowEmpty]="true"\n (closeResult)="closeExtraOptionModal()"\n (save)="saveExtraOptionModal($event)"\n />\n</main>\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.content{box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%;overflow:auto;padding:1rem 2rem;width:100%}.content .status-content{box-sizing:border-box;display:flex;flex-direction:row;height:100%;gap:1rem}.content .column{box-sizing:border-box;display:flex;flex:1;flex-direction:column}.content .sub-content{max-width:max-content}.content .sub-content button{width:auto;max-width:10rem;height:2.5rem;background:transparent;color:#0fbb6b;text-transform:uppercase;border:none;border-left:2px solid transparent;border-right:2px solid transparent;cursor:pointer;padding:0 1rem;margin-bottom:1rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.content .sub-content button.is-active{background:#0fbb6b14;border-left:2px solid #0fbb6b;border-right:2px solid #0fbb6b}.content .sub-content button:hover{background:#0fbb6b26}.content .radiation-status,.content .effects-status{box-sizing:border-box;display:flex;align-items:center;justify-content:center}.content .actions{box-sizing:border-box;display:flex;align-items:flex-end;max-width:max-content}\n",":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.sub-tabs{flex:0 0 auto;min-height:0;margin-bottom:.5rem;padding:0 1rem;position:relative;z-index:1}.sub-tabs>nav{box-sizing:border-box;display:flex;align-items:center;width:100%;height:2.25rem;gap:0}.sub-tabs>nav .center-line{flex:1 1 auto;height:100%;min-width:1.5rem}.sub-tabs>nav>.center-line:last-child .top-half-line:before{left:auto;right:0}.sub-tabs>nav button{background:transparent;border:2px solid transparent;color:#0fbb6b;cursor:pointer;font-size:clamp(1.25rem,1.25rem + (1.5rem - 1.25rem) * (100vw - 360px) / (1200px - 360px),1.5rem);padding:.5rem}.sub-tabs>nav button.is-active{background:#0fbb6b14;border:2px solid #0fbb6b}.sub-tabs>nav button:hover{background:#0fbb6b26}\n",':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.tabs{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;flex:0 0 auto;gap:.5rem;max-height:12rem;overflow:hidden;padding:0;position:relative;z-index:5;transition:max-height .35s ease-in-out,padding .35s ease-in-out,gap .35s ease-in-out;width:100%}.tabs.is-collapsed{gap:0;max-height:2rem}.tabs.is-collapsed>nav{opacity:0;pointer-events:none;transform:translateY(100%)}.tabs.is-collapsed .tabs-toggle .caret{transform:translateY(2px) rotate(-135deg)}.tabs .tabs-toggle{align-items:center;background:transparent;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;display:inline-flex;height:2rem;justify-content:center;line-height:0;max-height:2rem;min-height:2rem;overflow:hidden;padding:0 1rem;transition:border-color .2s ease;width:100%}.tabs .tabs-toggle:hover{background-color:#0fbb6b1f}.tabs .tabs-toggle .caret{border:solid #0fbb6b;border-width:0 2px 2px 0;box-sizing:border-box;display:inline-block;height:.6rem;margin:0 .5rem;padding:0;transform:translateY(-4px) rotate(45deg);transform-origin:center;transition:transform .35s ease;width:.6rem}.tabs .tabs-toggle .tabs-toggle-label{font-size:clamp(.7rem,.7rem + (.85rem - .7rem) * (100vw - 360px) / (1200px - 360px),.85rem);letter-spacing:.1em;line-height:1;text-transform:uppercase;white-space:nowrap}.tabs>nav{display:flex;justify-content:center;opacity:1;padding-bottom:.5rem;transform:translateY(0);transition:transform .35s ease-in-out,opacity .35s ease-in-out;transform-origin:bottom;will-change:transform,opacity;width:100%;position:relative}.tabs .tabs-version{bottom:14px;color:#0fbb6bbf;font-size:10px;letter-spacing:.08em;position:absolute;right:22px}.tabs .tabs-actions{align-items:center;display:flex;gap:.5rem;left:1rem;position:absolute;top:50%;transform:translateY(-50%)}.tabs .tabs-actions.right,.tabs .tabs-actions.tabs-actions--right{left:auto;right:1rem}.tabs .tabs-actions .tabs-actions-toggle{align-items:center;background:transparent;border:1px solid rgba(15,187,107,.6);border-radius:9999px;color:#0fbb6b;cursor:pointer;display:none;height:2.1rem;justify-content:center;padding:0 .6rem;text-transform:uppercase;width:2.4rem}.tabs .tabs-actions .tabs-actions-toggle:hover{background:#0fbb6b1f;border-color:#0fbb6b}.tabs .tabs-actions .tabs-actions-icon{background:#0fbb6b;border-radius:9999px;display:block;height:2px;position:relative;width:1.1rem}.tabs .tabs-actions .tabs-actions-icon:before,.tabs .tabs-actions .tabs-actions-icon:after{content:"";background:#0fbb6b;border-radius:9999px;height:2px;left:0;position:absolute;width:100%}.tabs .tabs-actions .tabs-actions-icon:before{top:-5px}.tabs .tabs-actions .tabs-actions-icon:after{top:5px}.tabs .tabs-actions .tabs-actions-menu{display:flex;gap:.5rem;align-items:center}.tabs .tabs-actions .action-button{background:transparent;border:1px solid rgba(15,187,107,.7);color:#0fbb6bb3;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.25rem .35rem;text-align:left;width:100%;border-radius:1rem;text-align:center}.tabs .tabs-actions .action-button:hover{background:#0fbb6b1f;border-color:#0fbb6b}.tabs .tabs-actions input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.tabs .tabs-action{align-items:center;background:#0fbb6b1a;border:2px solid rgba(15,187,107,.6);border-radius:.4rem;color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.65rem,.65rem + (.75rem - .65rem) * (100vw - 360px) / (1200px - 360px),.75rem);height:2.5rem;justify-content:center;letter-spacing:.08em;padding:0 .85rem;text-transform:uppercase;transition:background .2s ease,border-color .2s ease;width:auto}.tabs .tabs-action:hover{background:#0fbb6b2e;border-color:#0fbb6b}.tabs>nav>button{align-items:center;background:transparent;border-radius:9999px;border:2px solid rgba(15,187,107,.35);box-sizing:border-box;color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);height:5rem;justify-content:center;line-height:1;margin:0 1rem;padding:0;text-transform:uppercase;width:5rem}.tabs>nav>button>span{align-items:center;display:inline-flex;justify-content:center;line-height:1;white-space:nowrap;width:100%;height:100%;border-radius:9999px;padding:0}.tabs>nav>button:hover{border-color:#0fbb6ba6}.tabs>nav>button:hover>span{background:#0fbb6b1f}.tabs>nav>button.is-active{border-color:#0fbb6b}.tabs>nav>button.is-active>span{background:#0fbb6b29}@media(max-width:750px){.tabs .tabs-actions{z-index:5}.tabs .tabs-actions .tabs-actions-toggle{display:inline-flex}.tabs .tabs-actions .tabs-actions-menu{display:none}.tabs .tabs-actions.is-open .tabs-actions-menu{background:#062114f2;border:1px solid rgba(15,187,107,.35);border-radius:.5rem;display:flex;flex-direction:column;gap:.35rem;padding:.5rem;position:absolute;bottom:2.6rem;z-index:1000}.tabs .tabs-actions.tabs-actions--left.is-open .tabs-actions-menu{left:0}.tabs .tabs-actions.tabs-actions--right.is-open .tabs-actions-menu{right:0}.tabs .tabs-actions .action-button{width:100%}}@media(max-width:750px){.tabs{overflow:visible}}\n',':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{font-family:Roboto Condensed,sans-serif;font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);scrollbar-color:rgba(107,255,153,.6) rgba(6,33,20,.6);scrollbar-width:thin;background-color:#062114;background-image:repeating-linear-gradient(to bottom,#ffffff0a 0 1px,#0000 4px);background-size:100% 6px;animation:scan-lines 6s linear infinite;box-shadow:inset 0 0 24px #0009,inset 0 0 90px #00000073;box-sizing:border-box;color:#0fbb6b;display:block;height:100%;overflow:hidden;position:relative;width:100%}:host ::-webkit-scrollbar{width:6px;height:6px}:host ::-webkit-scrollbar-track{background:#06211499}:host ::-webkit-scrollbar-thumb{background:#6bff9999;border-radius:9999px}:host:before{content:"";position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse at center,#06211400 55%,#00000040 70%,#0009);mix-blend-mode:multiply}@keyframes scan-lines{0%{background-position:0 0}to{background-position:0 60px}}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:0;position:relative;width:100%;display:flex;flex-direction:column;min-height:0}.screen-size-overlay{position:absolute;inset:0;background:#000000d9;color:#0fbb6b;display:flex;align-items:center;justify-content:center;text-align:center;padding:2rem;text-transform:uppercase;font-size:clamp(1.1rem,1.1rem + (1.35rem - 1.1rem) * (100vw - 360px) / (1200px - 360px),1.35rem);z-index:200}.center-line{position:relative;height:100%;overflow:visible}.center-line:before{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:2px;background:#0fbb6b}.bottom-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.bottom-half-line:before{content:"";position:absolute;top:50%;bottom:-1.25rem;width:2px;z-index:2;background:linear-gradient(to bottom,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}.top-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.top-half-line:before{content:"";position:absolute;bottom:50%;top:-1.25rem;width:2px;z-index:2;left:0;background:linear-gradient(to top,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}.extra-options{margin-top:.25rem;display:flex;flex-direction:column;font-size:clamp(1.05rem,1.05rem + (1.25rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.25rem);align-items:flex-end;gap:.75rem;white-space:nowrap}.extra-options button{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font:inherit;padding:0;white-space:nowrap}.extra-options button:hover{opacity:.8}.extra-options button:disabled,.extra-options button.is-locked{cursor:default}.extra-options .controller-button{font-size:clamp(1.05rem,1.05rem + (1.25rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.25rem);white-space:nowrap}.extra-options .controller-button .large-par{display:inline;padding-left:.5rem;font-size:clamp(1.45rem,1.45rem + (1.75rem - 1.45rem) * (100vw - 360px) / (1200px - 360px),1.75rem);top:-.15rem;position:relative;white-space:nowrap}.map-panel{display:flex;flex:1 1 auto;min-height:0;position:relative;width:100%}.map-view{align-items:flex-start;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:flex;flex:1 1 auto;justify-content:flex-start;min-height:0;overflow:auto;padding:1.5rem;width:100%}.map-view span{letter-spacing:.1em;margin:auto;text-transform:uppercase;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.map-view img{display:block;max-width:none;max-height:none}.map-view.is-locked,.map-view:disabled{cursor:default}.map-zoom{display:flex;gap:.5rem;position:absolute;right:.75rem;top:.75rem;z-index:2}.map-zoom button{align-items:center;background:#0fbb6b1f;border:1px solid rgba(15,187,107,.65);color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);justify-content:center;text-transform:uppercase;height:2rem;padding:0 .6rem}.map-zoom button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-zoom button:not(:last-child){padding:0;width:2rem}\n'],dependencies:[{kind:"component",type:h,selector:"pip-boy-screen-scan-lines",inputs:["replayTimeoutSeconds","screen","scanSpeedSeconds","tailLengthPx"]},{kind:"component",type:T,selector:"pip-boy-3000-header"},{kind:"component",type:z,selector:"pip-boy-inventory-layout",inputs:["category"]},{kind:"component",type:H,selector:"pip-boy-stats-layout",inputs:["category","valueLabel","valueMin","valueMax"]},{kind:"component",type:W,selector:"pip-boy-reset-confirm-modal",inputs:["open","title","message","confirmLabel","cancelLabel"],outputs:["confirm","closeResult"]},{kind:"component",type:U,selector:"pip-boy-name-edit-modal",inputs:["open","title","value","placeholder","allowEmpty"],outputs:["closeResult","save"]},{kind:"component",type:V,selector:"pip-boy-cnd-status"},{kind:"component",type:_,selector:"pip-boy-radiation-meter"},{kind:"component",type:$,selector:"pip-boy-eff-layout"},{kind:"component",type:Z,selector:"pip-boy-map-image-modal",inputs:["open","title","imageUrl"],outputs:["closeResult","save"]},{kind:"component",type:j,selector:"pip-boy-quests-layout"},{kind:"component",type:X,selector:"pip-boy-settings-modal",inputs:["open","scanLinesEnabled","editLockEnabled","listFontScale","secondaryTabSoundLabel","mainTabSoundLabel","clickSoundLabel"],outputs:["closeResult","save","previewListFontScale"]},{kind:"component",type:Y,selector:"pip-boy-music-layout",inputs:["category"]},{kind:"component",type:J,selector:"pip-boy-welcome-modal",inputs:["open","listFontScale"],outputs:["closeResult","previewListFontScale"]}]})}e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"21.0.8",ngImport:e,type:ee,decorators:[{type:n,args:[{selector:"pip-boy-3000",standalone:!0,imports:[h,T,z,H,W,U,V,_,$,Z,j,X,Y,J],providers:[w],template:'<main\n #screen\n class="screen"\n [style.--list-font-scale]="settings.listFontScale()"\n>\n @if (settings.scanLinesEnabled()) {\n <pip-boy-screen-scan-lines\n [replayTimeoutSeconds]="8"\n [scanSpeedSeconds]="5"\n [screen]="screen"\n [tailLengthPx]="300"\n />\n }\n @if (isScreenTooSmall()) {\n <div class="screen-size-overlay" role="alert" aria-live="assertive">\n Screen is too small.<br />Please rotate to landscape.\n </div>\n }\n \x3c!-- HEADER --\x3e\n <pip-boy-3000-header />\n \x3c!-- CONTENT --\x3e\n <section class="content">\n @if (state.primary() === \'STATS\') {\n @if (state.secondary() === \'STATUS\') {\n <div class="status-content">\n <nav class="column sub-content" aria-label="Status tabs">\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'CND\'"\n (click)="state.selectTertiary(\'CND\')"\n >\n CND\n </button>\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'RAD\'"\n (click)="state.selectTertiary(\'RAD\')"\n >\n RAD\n </button>\n <button\n type="button"\n [class.is-active]="state.tertiary() === \'EFF\'"\n (click)="state.selectTertiary(\'EFF\')"\n >\n EFF\n </button>\n </nav>\n @if (state.tertiary() === \'CND\') {\n <pip-boy-cnd-status />\n } @else if (state.tertiary() === \'RAD\') {\n <pip-boy-radiation-meter />\n <div class="extra-options">\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'RADAWAY\')"\n >\n {{ settings.radAwayLabel() }}\n </button>\n <button\n type="button"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openExtraOptionModal(\'RADX\')"\n >\n {{ settings.radXLabel() }}\n </button>\n </div>\n } @else if (state.tertiary() === \'EFF\') {\n <pip-boy-eff-layout />\n }\n </div>\n } @else if (state.secondary() === \'S.P.E.C.I.A.L.\') {\n <pip-boy-stats-layout\n category="SPECIAL"\n valueLabel="Rating"\n [valueMin]="1"\n [valueMax]="10"\n />\n } @else if (state.secondary() === \'SKILLS\') {\n <pip-boy-stats-layout\n category="SKILLS"\n valueLabel="Skill"\n [valueMin]="0"\n [valueMax]="100"\n />\n } @else if (state.secondary() === \'PERKS\') {\n <pip-boy-stats-layout\n category="PERKS"\n valueLabel="Rank"\n [valueMin]="0"\n />\n } @else if (state.secondary() === \'GENERAL\') {\n <pip-boy-stats-layout category="GENERAL" valueLabel="Value" />\n }\n } @else if (state.primary() === \'ITEMS\') {\n @if (state.secondary() === \'WEAPONS\') {\n <pip-boy-inventory-layout category="WEAPONS" />\n } @else if (state.secondary() === \'APPAREL\') {\n <pip-boy-inventory-layout category="APPAREL" />\n } @else if (state.secondary() === \'AID\') {\n <pip-boy-inventory-layout category="AID" />\n } @else if (state.secondary() === \'MISC\') {\n <pip-boy-inventory-layout category="MISC" />\n } @else if (state.secondary() === \'AMMO\') {\n <pip-boy-inventory-layout category="AMMO" />\n }\n } @else if (state.primary() === \'DATA\') {\n @if (state.secondary() === \'LOCAL MAP\') {\n <div class="map-panel">\n <button\n type="button"\n class="map-view"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openMapImageModal(\'LOCAL\')"\n >\n @if (settings.localMapImage()) {\n <img\n [src]="imageStore.getImageUrl(settings.localMapImage())"\n alt="Local map"\n [style.transform]="\'scale(\' + localMapZoom() + \')\'"\n style="transform-origin: top left"\n />\n } @else {\n <span>CLICK TO UPLOAD IMAGE</span>\n }\n </button>\n @if (settings.localMapImage()) {\n <div\n class="map-zoom"\n role="group"\n tabindex="0"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n >\n <button type="button" (click)="zoomMap(\'LOCAL\', 0.2)">+</button>\n <button type="button" (click)="zoomMap(\'LOCAL\', -0.2)">-</button>\n <button type="button" (click)="resetMapZoom(\'LOCAL\')">\n Reset\n </button>\n </div>\n }\n </div>\n } @else if (state.secondary() === \'WORLD MAP\') {\n <div class="map-panel">\n <button\n type="button"\n class="map-view"\n [class.is-locked]="settings.editLockEnabled()"\n [disabled]="settings.editLockEnabled()"\n (click)="openMapImageModal(\'WORLD\')"\n >\n @if (settings.worldMapImage()) {\n <img\n [src]="imageStore.getImageUrl(settings.worldMapImage())"\n alt="World map"\n [style.transform]="\'scale(\' + worldMapZoom() + \')\'"\n style="transform-origin: top left"\n />\n } @else {\n <span>CLICK TO UPLOAD IMAGE</span>\n }\n </button>\n @if (settings.worldMapImage()) {\n <div\n class="map-zoom"\n role="group"\n tabindex="0"\n (click)="$event.stopPropagation()"\n (keydown)="$event.stopPropagation()"\n >\n <button type="button" (click)="zoomMap(\'WORLD\', 0.2)">+</button>\n <button type="button" (click)="zoomMap(\'WORLD\', -0.2)">-</button>\n <button type="button" (click)="resetMapZoom(\'WORLD\')">\n Reset\n </button>\n </div>\n }\n </div>\n } @else if (state.secondary() === \'QUESTS\') {\n <pip-boy-quests-layout />\n } @else if (state.secondary() === \'NOTES\') {\n <pip-boy-music-layout category="NOTES" />\n } @else if (state.secondary() === \'RADIO\') {\n <pip-boy-music-layout category="RADIO" />\n }\n }\n </section>\n \x3c!-- SUB TABS --\x3e\n <section class="sub-tabs">\n @if (state.primary() === \'STATS\') {\n <nav aria-label="Stats tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'STATUS\'"\n (click)="selectSecondary(\'STATUS\')"\n >\n Status\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'S.P.E.C.I.A.L.\'"\n (click)="selectSecondary(\'S.P.E.C.I.A.L.\')"\n >\n S.P.E.C.I.A.L.\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'SKILLS\'"\n (click)="selectSecondary(\'SKILLS\')"\n >\n Skills\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'PERKS\'"\n (click)="selectSecondary(\'PERKS\')"\n >\n Perks\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'GENERAL\'"\n (click)="selectSecondary(\'GENERAL\')"\n >\n General\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n } @else if (state.primary() === \'ITEMS\') {\n <nav aria-label="Items tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'WEAPONS\'"\n (click)="selectSecondary(\'WEAPONS\')"\n >\n Weapons\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'APPAREL\'"\n (click)="selectSecondary(\'APPAREL\')"\n >\n Apparel\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'AID\'"\n (click)="selectSecondary(\'AID\')"\n >\n Aid\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'MISC\'"\n (click)="selectSecondary(\'MISC\')"\n >\n Misc\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'AMMO\'"\n (click)="selectSecondary(\'AMMO\')"\n >\n Ammo\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n } @else if (state.primary() === \'DATA\') {\n <nav aria-label="Data tabs">\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'LOCAL MAP\'"\n (click)="selectSecondary(\'LOCAL MAP\')"\n >\n Local Map\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'WORLD MAP\'"\n (click)="selectSecondary(\'WORLD MAP\')"\n >\n World Map\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'QUESTS\'"\n (click)="selectSecondary(\'QUESTS\')"\n >\n Quests\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'NOTES\'"\n (click)="selectSecondary(\'NOTES\')"\n >\n Notes\n </button>\n <div class="center-line"></div>\n <button\n type="button"\n [class.is-active]="state.secondary() === \'RADIO\'"\n (click)="selectSecondary(\'RADIO\')"\n >\n Radio\n </button>\n <div class="center-line">\n <div class="top-half-line"></div>\n </div>\n </nav>\n }\n </section>\n \x3c!-- MAIN TABS --\x3e\n <section class="tabs" [class.is-collapsed]="!tabsOpen()">\n <button\n type="button"\n class="tabs-toggle"\n aria-label="Toggle main tabs"\n [attr.aria-expanded]="tabsOpen()"\n aria-controls="main-tabs"\n (click)="toggleTabs()"\n >\n <span class="tabs-toggle-label tabs-toggle-label--state">\n {{ tabsOpen() ? \'CLOSE\' : \'OPEN\' }}\n </span>\n <span class="caret" aria-hidden="true"></span>\n <span class="tabs-toggle-label tabs-toggle-label--menu">MENU</span>\n </button>\n <nav id="main-tabs" aria-label="Main tabs">\n <div\n class="tabs-actions tabs-actions--left"\n [class.is-open]="tabsActionsLeftOpen()"\n >\n <button\n type="button"\n class="tabs-actions-toggle"\n aria-label="Open settings actions"\n (click)="toggleTabsActions(\'left\')"\n >\n <span class="tabs-actions-icon" aria-hidden="true"></span>\n </button>\n <div class="tabs-actions-menu">\n <button\n type="button"\n class="action-button"\n aria-label="Save settings"\n title="Save settings"\n (click)="saveSettingsToFile()"\n >\n Save\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Load settings"\n title="Load settings"\n (click)="loadSettingsInput.click()"\n >\n Load\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Reset settings"\n title="Reset settings"\n (click)="openResetModal()"\n >\n Reset\n </button>\n <input\n #loadSettingsInput\n type="file"\n accept=".zip,application/zip"\n (change)="loadSettingsFromFile($event)"\n />\n </div>\n </div>\n <button\n type="button"\n [class.is-active]="state.primary() === \'STATS\'"\n (click)="selectPrimary(\'STATS\')"\n >\n <span>STATS</span>\n </button>\n <button\n type="button"\n [class.is-active]="state.primary() === \'ITEMS\'"\n (click)="selectPrimary(\'ITEMS\')"\n >\n <span>ITEMS</span>\n </button>\n <button\n type="button"\n [class.is-active]="state.primary() === \'DATA\'"\n (click)="selectPrimary(\'DATA\')"\n >\n <span>DATA</span>\n </button>\n <div\n class="tabs-actions tabs-actions--right"\n [class.is-open]="tabsActionsRightOpen()"\n >\n <button\n type="button"\n class="tabs-actions-toggle"\n aria-label="Open utility actions"\n (click)="toggleTabsActions(\'right\')"\n >\n <span class="tabs-actions-icon" aria-hidden="true"></span>\n </button>\n <div class="tabs-actions-menu">\n <button\n type="button"\n class="action-button"\n aria-label="Open GitHub profile"\n title="Open GitHub profile"\n (click)="openGithubProfile()"\n >\n ❤\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Open settings"\n title="Settings"\n (click)="openSettingsModal()"\n >\n Settings\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Report a bug"\n title="Report a bug"\n (click)="openBugModal()"\n >\n Bug\n </button>\n <button\n type="button"\n class="action-button"\n aria-label="Reset settings"\n title="Exit"\n (click)="openExitModal()"\n >\n Exit\n </button>\n <input\n #loadSettingsInput\n type="file"\n accept=".zip,application/zip"\n (change)="loadSettingsFromFile($event)"\n />\n </div>\n </div>\n @if (tabsOpen()) {\n <div class="tabs-version">v{{ appVersion }}</div>\n }\n </nav>\n </section>\n <pip-boy-welcome-modal\n [open]="showWelcomeModal()"\n [listFontScale]="settings.listFontScale()"\n (previewListFontScale)="previewListFontScale($event)"\n (closeResult)="closeWelcomeModal()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showResetModal()"\n title="Reset Settings"\n message="This will reset all values back to defaults. This cannot be undone."\n confirmLabel="Reset"\n (closeResult)="closeResetModal()"\n (confirm)="confirmReset()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showExitModal()"\n title="Exit"\n message="Are you sure you want to leave this screen?"\n confirmLabel="Exit"\n (closeResult)="closeExitModal()"\n (confirm)="confirmExit()"\n />\n <pip-boy-reset-confirm-modal\n [open]="showBugModal()"\n title="Report a bug"\n message="Would you like to report a bug?"\n confirmLabel="Yes"\n cancelLabel="No"\n (closeResult)="closeBugModal()"\n (confirm)="confirmBugReport()"\n />\n <pip-boy-map-image-modal\n [open]="mapImageModal() !== null"\n [title]="mapImageModalTitle()"\n [imageUrl]="mapImageModalImage()"\n (closeResult)="closeMapImageModal()"\n (save)="saveMapImageModal($event)"\n />\n <pip-boy-settings-modal\n [open]="showSettingsModal()"\n [scanLinesEnabled]="settings.scanLinesEnabled()"\n [editLockEnabled]="settings.editLockEnabled()"\n [listFontScale]="settings.listFontScale()"\n [secondaryTabSoundLabel]="secondaryTabSoundLabel()"\n [mainTabSoundLabel]="mainTabSoundLabel()"\n [clickSoundLabel]="clickSoundLabel()"\n (closeResult)="cancelSettingsModal()"\n (previewListFontScale)="previewListFontScale($event)"\n (save)="saveSettingsModal($event)"\n />\n <pip-boy-name-edit-modal\n [open]="extraOptionModal() !== null"\n [value]="extraOptionValue()"\n [title]="extraOptionTitle()"\n placeholder="Value"\n [allowEmpty]="true"\n (closeResult)="closeExtraOptionModal()"\n (save)="saveExtraOptionModal($event)"\n />\n</main>\n',styles:[":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.content{box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%;overflow:auto;padding:1rem 2rem;width:100%}.content .status-content{box-sizing:border-box;display:flex;flex-direction:row;height:100%;gap:1rem}.content .column{box-sizing:border-box;display:flex;flex:1;flex-direction:column}.content .sub-content{max-width:max-content}.content .sub-content button{width:auto;max-width:10rem;height:2.5rem;background:transparent;color:#0fbb6b;text-transform:uppercase;border:none;border-left:2px solid transparent;border-right:2px solid transparent;cursor:pointer;padding:0 1rem;margin-bottom:1rem;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.content .sub-content button.is-active{background:#0fbb6b14;border-left:2px solid #0fbb6b;border-right:2px solid #0fbb6b}.content .sub-content button:hover{background:#0fbb6b26}.content .radiation-status,.content .effects-status{box-sizing:border-box;display:flex;align-items:center;justify-content:center}.content .actions{box-sizing:border-box;display:flex;align-items:flex-end;max-width:max-content}\n",":host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.sub-tabs{flex:0 0 auto;min-height:0;margin-bottom:.5rem;padding:0 1rem;position:relative;z-index:1}.sub-tabs>nav{box-sizing:border-box;display:flex;align-items:center;width:100%;height:2.25rem;gap:0}.sub-tabs>nav .center-line{flex:1 1 auto;height:100%;min-width:1.5rem}.sub-tabs>nav>.center-line:last-child .top-half-line:before{left:auto;right:0}.sub-tabs>nav button{background:transparent;border:2px solid transparent;color:#0fbb6b;cursor:pointer;font-size:clamp(1.25rem,1.25rem + (1.5rem - 1.25rem) * (100vw - 360px) / (1200px - 360px),1.5rem);padding:.5rem}.sub-tabs>nav button.is-active{background:#0fbb6b14;border:2px solid #0fbb6b}.sub-tabs>nav button:hover{background:#0fbb6b26}\n",':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}.tabs{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;flex:0 0 auto;gap:.5rem;max-height:12rem;overflow:hidden;padding:0;position:relative;z-index:5;transition:max-height .35s ease-in-out,padding .35s ease-in-out,gap .35s ease-in-out;width:100%}.tabs.is-collapsed{gap:0;max-height:2rem}.tabs.is-collapsed>nav{opacity:0;pointer-events:none;transform:translateY(100%)}.tabs.is-collapsed .tabs-toggle .caret{transform:translateY(2px) rotate(-135deg)}.tabs .tabs-toggle{align-items:center;background:transparent;border:none;box-sizing:border-box;color:#0fbb6b;cursor:pointer;display:inline-flex;height:2rem;justify-content:center;line-height:0;max-height:2rem;min-height:2rem;overflow:hidden;padding:0 1rem;transition:border-color .2s ease;width:100%}.tabs .tabs-toggle:hover{background-color:#0fbb6b1f}.tabs .tabs-toggle .caret{border:solid #0fbb6b;border-width:0 2px 2px 0;box-sizing:border-box;display:inline-block;height:.6rem;margin:0 .5rem;padding:0;transform:translateY(-4px) rotate(45deg);transform-origin:center;transition:transform .35s ease;width:.6rem}.tabs .tabs-toggle .tabs-toggle-label{font-size:clamp(.7rem,.7rem + (.85rem - .7rem) * (100vw - 360px) / (1200px - 360px),.85rem);letter-spacing:.1em;line-height:1;text-transform:uppercase;white-space:nowrap}.tabs>nav{display:flex;justify-content:center;opacity:1;padding-bottom:.5rem;transform:translateY(0);transition:transform .35s ease-in-out,opacity .35s ease-in-out;transform-origin:bottom;will-change:transform,opacity;width:100%;position:relative}.tabs .tabs-version{bottom:14px;color:#0fbb6bbf;font-size:10px;letter-spacing:.08em;position:absolute;right:22px}.tabs .tabs-actions{align-items:center;display:flex;gap:.5rem;left:1rem;position:absolute;top:50%;transform:translateY(-50%)}.tabs .tabs-actions.right,.tabs .tabs-actions.tabs-actions--right{left:auto;right:1rem}.tabs .tabs-actions .tabs-actions-toggle{align-items:center;background:transparent;border:1px solid rgba(15,187,107,.6);border-radius:9999px;color:#0fbb6b;cursor:pointer;display:none;height:2.1rem;justify-content:center;padding:0 .6rem;text-transform:uppercase;width:2.4rem}.tabs .tabs-actions .tabs-actions-toggle:hover{background:#0fbb6b1f;border-color:#0fbb6b}.tabs .tabs-actions .tabs-actions-icon{background:#0fbb6b;border-radius:9999px;display:block;height:2px;position:relative;width:1.1rem}.tabs .tabs-actions .tabs-actions-icon:before,.tabs .tabs-actions .tabs-actions-icon:after{content:"";background:#0fbb6b;border-radius:9999px;height:2px;left:0;position:absolute;width:100%}.tabs .tabs-actions .tabs-actions-icon:before{top:-5px}.tabs .tabs-actions .tabs-actions-icon:after{top:5px}.tabs .tabs-actions .tabs-actions-menu{display:flex;gap:.5rem;align-items:center}.tabs .tabs-actions .action-button{background:transparent;border:1px solid rgba(15,187,107,.7);color:#0fbb6bb3;cursor:pointer;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);padding:.25rem .35rem;text-align:left;width:100%;border-radius:1rem;text-align:center}.tabs .tabs-actions .action-button:hover{background:#0fbb6b1f;border-color:#0fbb6b}.tabs .tabs-actions input[type=file]{height:1px;opacity:0;overflow:hidden;position:absolute;width:1px}.tabs .tabs-action{align-items:center;background:#0fbb6b1a;border:2px solid rgba(15,187,107,.6);border-radius:.4rem;color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.65rem,.65rem + (.75rem - .65rem) * (100vw - 360px) / (1200px - 360px),.75rem);height:2.5rem;justify-content:center;letter-spacing:.08em;padding:0 .85rem;text-transform:uppercase;transition:background .2s ease,border-color .2s ease;width:auto}.tabs .tabs-action:hover{background:#0fbb6b2e;border-color:#0fbb6b}.tabs>nav>button{align-items:center;background:transparent;border-radius:9999px;border:2px solid rgba(15,187,107,.35);box-sizing:border-box;color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.85rem,.85rem + (1rem - .85rem) * (100vw - 360px) / (1200px - 360px),1rem);height:5rem;justify-content:center;line-height:1;margin:0 1rem;padding:0;text-transform:uppercase;width:5rem}.tabs>nav>button>span{align-items:center;display:inline-flex;justify-content:center;line-height:1;white-space:nowrap;width:100%;height:100%;border-radius:9999px;padding:0}.tabs>nav>button:hover{border-color:#0fbb6ba6}.tabs>nav>button:hover>span{background:#0fbb6b1f}.tabs>nav>button.is-active{border-color:#0fbb6b}.tabs>nav>button.is-active>span{background:#0fbb6b29}@media(max-width:750px){.tabs .tabs-actions{z-index:5}.tabs .tabs-actions .tabs-actions-toggle{display:inline-flex}.tabs .tabs-actions .tabs-actions-menu{display:none}.tabs .tabs-actions.is-open .tabs-actions-menu{background:#062114f2;border:1px solid rgba(15,187,107,.35);border-radius:.5rem;display:flex;flex-direction:column;gap:.35rem;padding:.5rem;position:absolute;bottom:2.6rem;z-index:1000}.tabs .tabs-actions.tabs-actions--left.is-open .tabs-actions-menu{left:0}.tabs .tabs-actions.tabs-actions--right.is-open .tabs-actions-menu{right:0}.tabs .tabs-actions .action-button{width:100%}}@media(max-width:750px){.tabs{overflow:visible}}\n',':host,:host button,:host input,:host select,:host textarea{font-family:Roboto Mono,monospace}:host{font-family:Roboto Condensed,sans-serif;font-size:clamp(.95rem,.95rem + (1.15rem - .95rem) * (100vw - 360px) / (1200px - 360px),1.15rem);scrollbar-color:rgba(107,255,153,.6) rgba(6,33,20,.6);scrollbar-width:thin;background-color:#062114;background-image:repeating-linear-gradient(to bottom,#ffffff0a 0 1px,#0000 4px);background-size:100% 6px;animation:scan-lines 6s linear infinite;box-shadow:inset 0 0 24px #0009,inset 0 0 90px #00000073;box-sizing:border-box;color:#0fbb6b;display:block;height:100%;overflow:hidden;position:relative;width:100%}:host ::-webkit-scrollbar{width:6px;height:6px}:host ::-webkit-scrollbar-track{background:#06211499}:host ::-webkit-scrollbar-thumb{background:#6bff9999;border-radius:9999px}:host:before{content:"";position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse at center,#06211400 55%,#00000040 70%,#0009);mix-blend-mode:multiply}@keyframes scan-lines{0%{background-position:0 0}to{background-position:0 60px}}.screen{box-sizing:border-box;height:100%;overflow:hidden;padding:0;position:relative;width:100%;display:flex;flex-direction:column;min-height:0}.screen-size-overlay{position:absolute;inset:0;background:#000000d9;color:#0fbb6b;display:flex;align-items:center;justify-content:center;text-align:center;padding:2rem;text-transform:uppercase;font-size:clamp(1.1rem,1.1rem + (1.35rem - 1.1rem) * (100vw - 360px) / (1200px - 360px),1.35rem);z-index:200}.center-line{position:relative;height:100%;overflow:visible}.center-line:before{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:2px;background:#0fbb6b}.bottom-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.bottom-half-line:before{content:"";position:absolute;top:50%;bottom:-1.25rem;width:2px;z-index:2;background:linear-gradient(to bottom,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}.top-half-line{position:absolute;inset:0;pointer-events:none;overflow:visible}.top-half-line:before{content:"";position:absolute;bottom:50%;top:-1.25rem;width:2px;z-index:2;left:0;background:linear-gradient(to top,#0fbb6b,#0fbb6ba6 18%,#0fbb6b59 40%,#0fbb6b26 65%,#0fbb6b00)}.extra-options{margin-top:.25rem;display:flex;flex-direction:column;font-size:clamp(1.05rem,1.05rem + (1.25rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.25rem);align-items:flex-end;gap:.75rem;white-space:nowrap}.extra-options button{background:transparent;border:none;color:#0fbb6b;cursor:pointer;font:inherit;padding:0;white-space:nowrap}.extra-options button:hover{opacity:.8}.extra-options button:disabled,.extra-options button.is-locked{cursor:default}.extra-options .controller-button{font-size:clamp(1.05rem,1.05rem + (1.25rem - 1.05rem) * (100vw - 360px) / (1200px - 360px),1.25rem);white-space:nowrap}.extra-options .controller-button .large-par{display:inline;padding-left:.5rem;font-size:clamp(1.45rem,1.45rem + (1.75rem - 1.45rem) * (100vw - 360px) / (1200px - 360px),1.75rem);top:-.15rem;position:relative;white-space:nowrap}.map-panel{display:flex;flex:1 1 auto;min-height:0;position:relative;width:100%}.map-view{align-items:flex-start;background:transparent;border:none;color:#0fbb6b;cursor:pointer;display:flex;flex:1 1 auto;justify-content:flex-start;min-height:0;overflow:auto;padding:1.5rem;width:100%}.map-view span{letter-spacing:.1em;margin:auto;text-transform:uppercase;font-size:calc(clamp(.95rem,.95rem + .2rem * (100vw - 360px) / 840px,1.15rem) * var(--list-font-scale, 1))}.map-view img{display:block;max-width:none;max-height:none}.map-view.is-locked,.map-view:disabled{cursor:default}.map-zoom{display:flex;gap:.5rem;position:absolute;right:.75rem;top:.75rem;z-index:2}.map-zoom button{align-items:center;background:#0fbb6b1f;border:1px solid rgba(15,187,107,.65);color:#0fbb6b;cursor:pointer;display:inline-flex;font-size:clamp(.75rem,.75rem + (.9rem - .75rem) * (100vw - 360px) / (1200px - 360px),.9rem);justify-content:center;text-transform:uppercase;height:2rem;padding:0 .6rem}.map-zoom button:hover{border-color:#0fbb6b;background:#0fbb6b1f}.map-zoom button:not(:last-child){padding:0;width:2rem}\n']}]}],propDecorators:{returnToUrl:[{type:e.Input,args:[{isSignal:!0,alias:"returnToUrl",required:!1}]}],onResize:[{type:p,args:["window:resize"]}]}});export{y as PipBoy2000MkVI,ee as PipBoy3000,I as PipBoy3000MkIV,w as PipBoy3000State,v as PipBoy3000a};
|