|
{"version":3,"file":"main.js","mappings":";;;;;AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,aAAa,oBAAoB;AACjC,aAAa,oBAAoB;AACjC;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA,aAAa,oBAAoB;AACjC;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA,aAAa,oBAAoB;AACjC;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;;AAEH;AACA,aAAa,oBAAoB;AACjC,aAAa,oBAAoB;AACjC;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA,aAAa,oBAAoB;AACjC,aAAa,oBAAoB;AACjC;AACA;AACA;AACA;AACA,gBAAgB,oBAAoB;AACpC,eAAe,oBAAoB;AACnC,eAAe,oBAAoB;AACnC,cAAc,oBAAoB;AAClC,cAAc,oBAAoB;AAClC,KAAK;AACL;AACA;;AAEA;;AAEA,4BAA4B,sBAAsB;;AAElD,gDAAe,SAAS,EAAC;;;ACzMc;;AAEvC;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA,KAAK;AACL,GAAG;;AAEH;AACA;AACA;AACA,GAAG;;AAEH;AACA,6BAA6B,qBAAqB,EAAE,kBAAkB;AACtE,GAAG;;AAEH;AACA,6BAA6B,qBAAqB,EAAE,kBAAkB;AACtE,GAAG;;AAEH;AACA,8BAA8B,mBAAmB;AACjD,oBAAoB,mBAAmB;AACvC,QAAQ,qBAAqB;AAC7B;AACA,GAAG;;AAEH;AACA;AACA,qCAAqC,mBAAmB,CAAC;AACzD;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;;;AAGH;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,MAAM,EAAE,YAAY,EAAE,WAAW;AACpE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,QAAQ;AACR;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA,6CAA6C,qBAAqB,CAAC,UAAU,KAAK;AAClF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;;AAEA;;;AAGA,gDAAe,KAAK,EAAC;;;ACrGkB;AACR;;AAE/B;AACA;AACA;AACA;AACA;;AAEA,oBAAoB,iBAAa;AACjC;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA,aAAa,qBAAqB,EAAE,IAAI,UAAU,IAAI,IAAI;AAC1D;AACA;AACA;AACA,0CAA0C;AAC1C,UAAU;AACV,8BAA8B;AAC9B;AACA;AACA;AACA;AACA,yCAAyC;AACzC,UAAU;AACV,6BAA6B;AAC7B;AACA;AACA;AACA;AACA,yCAAyC;AACzC,UAAU;AACV,6BAA6B;AAC7B;AACA;AACA;AACA;AACA,0CAA0C;AAC1C,UAAU;AACV,8BAA8B;AAC9B;AACA;AACA;AACA;AACA;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AU,uBAAmB;AAC7B;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;;AAEA,IAAI,uBAAmB;AACvB;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACxJA;AACA;AACwC;AAC4D;AACpD;AACd;AACF;AAC2B;AAChB;;AAEpC;AACP;AACA;AACA,QAAQ,sDAAsD,yBAAyB,wBAAwB,IAAI;AACnH,QAAQ,sDAAsD,oBAAgB,wCAAwC,IAAI;AAC1H,QAAQ,sDAAsD,oBAAgB,4CAA4C,IAAI;AAC9H,QAAQ,gEAAgE,kBAAkB,IAAI;AAC9F,QAAQ,gEAAgE,sBAAsB,IAAI;AAClG,QAAQ,gEAAgE,oBAAgB,yCAAyC,UAAU;AAC3I,QAAQ,gEAAgE,oBAAgB,6CAA6C,UAAU;AAC/I;AACA,WAAW,yBAAyB;AACpC;;AAEA;AACA;AACA,2BAA2B,qBAAqB;AAChD;AACA;AACA;AACA,sBAAsB;AACtB;;AAEA,uBAAuB;AACvB;AACA;AACA,4BAA4B;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe;AACf,oBAAoB;AACpB,kBAAkB;AAClB;AACA;AACA;AACA;AACA;AACA,0BAA0B;AAC1B,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,yBAAyB;AACrC,YAAY,wBAAwB;AACpC,YAAY,iCAAiC;AAC7C,YAAY,sBAAsB;AAClC,YAAY,0BAA0B;AACtC,YAAY,uBAAuB;AACnC,YAAY,2BAA2B;AACvC;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,iBAAa;AAC5C,QAAQ,iBAAa;AACrB,QAAQ,kCAAkC;AAC1C;AACA,0CAA0C,iBAAiB,GAAG,MAAM;AACpE;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,oBAAoB,kBAAc;AAClC;AACA;AACA;AACA;AACA,qDAAqD,cAAc;AACnE;AACA;AACA;AACA,QAAQ;AACR;AACA,8BAA8B,mBAAmB,CAAC,qCAAqC,eAAe;AACtG;AACA;AACA,MAAM;AACN,mDAAmD,mBAAmB,CAAC;AACvE;AACA;;AAEA;AACA;AACA;AACA,uBAAuB,gCAAgC;AACvD;AACA;AACA;AACA,QAAQ;AACR,QAAQ,gBAAY,4BAA4B,wBAAwB,8BAA0B,uBAAuB;AACzH;AACA,YAAY,8BAA0B;AACtC;AACA;AACA,UAAU,SAAS,0BAAsB;AACzC,kDAAkD,cAAc;AAChE;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,+BAA+B,2CAA2C;AAC1E;AACA,MAAM;AACN;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,iBAAiB,iCAAiC;AAClD;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,iBAAiB,iCAAiC;AAClD;AACA;AACA;AACA;AACA,QAAQ,eAAe,IAAI,gCAAgC,EAAE,gCAAgC,SAAS,8CAA8C,EAAE,gCAAgC;AACtL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,IAAI,gBAAY;AAChB;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,qBAAqB,iCAAiC;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,qBAAqB,iCAAiC;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,OAAO;AACP,IAAI,gBAAY;;AAEhB,IAAI,gBAAY;AAChB,oCAAoC,sBAAsB;AAC1D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2DAA2D;AAC3D,6DAA6D,0BAA0B;AACvF,sCAAsC,uMAAuM;AAC7O;AACA;AACA,OAAO;AACP,IAAI,gBAAY;;;AAGhB,IAAI,gBAAY;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,IAAI,gBAAY;AAChB,IAAI,gBAAY;AAChB;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,yBAAyB,uBAAuB;AAChD;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,sBAAsB,wBAAwB;AAC9C,QAAQ;AACR,sBAAsB,oBAAoB;AAC1C,QAAQ;AACR,sBAAsB,eAAe;AACrC;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA,SAAS,0BAAsB;AAC/B;AACA,QAAQ,eAAW;AACnB;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,MAAM,eAAW;AACjB;AACA,OAAO;AACP;AACA;AACA;AACA,IAAI,eAAW;;AAEf;AACA;AACA;;AAEA;AACA;AACA;;AAEA,kCAAkC,gBAAgB;;AAElD,uBAAuB,YAAY,IAAI,eAAe;AACtD;AACA;AACA;AACA,0BAA0B,sBAAsB;AAChD;;AAEA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA,2BAA2B,gCAAgC,IAAI,oCAAoC;AACnG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,QAAQ;;AAER;AACA,2CAA2C,gCAAgC,EAAE,mCAAmC;;AAEhH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA,QAAQ;;AAER;AACA;AACA;AACA;AACA;AACA,QAAQ;;AAER;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;;AAER;AACA;AACA;AACA;AACA;AACA,QAAQ;;AAER;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA,QAAQ;;AAER;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA,QAAQ;;AAER;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;;AAER;AACA;;AAEA;AACA;AACA,IAAI,gBAAY,0CAA0C,MAAM,GAAG,OAAO,uBAAuB,KAAK;AACtG;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,oCAAoC,kEAAkE;AACtG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8CAA8C,uCAAuC;AACr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CA;AACA;AACA,2FAA2F,cAAc;AACzG;AACA;;AAEA,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA,QAAQ,gBAAY,mBAAmB,kCAAkC;AACzE;;AAEA,MAAM,gBAAY;AAClB;AACA,MAAM,gBAAY;AAClB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,MAAM,gBAAY,mCAAmC,cAAc,KAAK,iDAAiD;AACzH,uCAAuC,4EAA4E;AACnH;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA,QAAQ,gBAAY;AACpB;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8B,eAAe;AAC7C,2DAA2D,UAAU;AACrE;AACA;AACA,aAAa;AACb,wEAAwE,uCAAuC;AAC/G,4CAA4C,sCAAsC;AAClF;AACA;AACA;AACA;AACA,MAAM;AACN,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN;AACA;;AAEA,IAAI,gBAAY,8BAA8B,mDAAmD;AACjG;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,0FAA0F,cAAc;AACxG;AACA,iFAAiF,aAAa;;AAE9F,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN;AACA;;AAEA,IAAI,gBAAY,2BAA2B,mDAAmD;AAC9F;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,mEAAmE,cAAc;AACjF,mEAAmE,cAAc;AACjF;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN,MAAM,gBAAY;AAClB;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA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AA+B;AACrF,YAAY;AACZ;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAU,gBAAY;AACtB,kEAAkE,qBAAqB;AACvF;AACA;AACA,yDAAyD,2CAA2C;AACpG;AACA;AACA;;AAEA;AACA,MAAM,gBAAY,+CAA+C,cAAc;AAC/E;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,MAAM;AACN;AACA;AACA;AACA,+DAA+D,IAAI;AACnE,OAAO;AACP;;AAEA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0DAA0D,MAAM;AAChE;AACA;;AAEA;AACA;AACA,gEAAgE,IAAI;AACpE,KAAK;AACL;;AAEA;AACA;AACA,2DAA2D,IAAI;AAC/D,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,gBAAgB,sBAAsB;AACtC;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,sCAAsC,cAAc;AACpD;AACA,mBAAmB,cAAc;AACjC,sBAAsB,cAAc,CAAC,8CAA8C;AACnF,sBAAsB,cAAc,CAAC,iDAAiD;AACtF,sBAAsB,cAAc,CAAC,iDAAiD;AACtF,cAAc,0BAAsB;AACpC,wBAAwB,cAAc,CAAC,kDAAkD;AACzF;AACA,OAAO;AACP;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,+BAA+B;AAC/B;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA,UAAU;AACV;AACA;AACA,QAAQ;AACR;AACA,QAAQ;AACR;AACA,QAAQ;AACR;AACA,QAAQ;AACR,wBAAwB,+BAA+B;AACvD,wBAAwB,+BAA+B;AACvD;AACA;AACA,UAAU;AACV;AACA,UAAU;AACV;AACA;AACA,QAAQ;AACR;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA,MAAM,4GAA4G;AAClH;AACA,IAAI,gBAAY,4BAA4B,MAAM,kBAAkB,SAAS,gBAAgB,WAAW;;AAExG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,gBAAY,2BAA2B,YAAY;AAC3D,0BAA0B,gBAAY,2BAA2B,YAAY,KAAK,oBAAoB;;AAEtG;AACA;AACA;AACA,UAAU,gBAAY,yBAAyB,YAAY;AAC3D;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA,4CAA4C,eAAe,EAAE,gBAAgB;AAC7E,UAAU,gBAAY,+CAA+C,2BAA2B;AAChG,kCAAkC,eAAe,GAAG,gBAAgB;AACpE;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAM,gBAAY;AAClB;AACA;AACA,QAAQ,gBAAY,4BAA4B,aAAa,KAAK,6BAA6B;AAC/F;AACA;AACA;AACA,qBAAqB,4FAA4F;AACjH;AACA;AACA;AACA;AACA;AACA,0CAA0C,eAAe,EAAE,gBAAgB;AAC3E,QAAQ,gBAAY,kDAAkD,6BAA6B;AACnG,iCAAiC,eAAe,GAAG,gBAAgB;AACnE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,6CAA6C,yBAAyB;AACtE;AACA;;AAEA;AACA,QAAQ,4BAA4B;AACpC;AACA;AACA;AACA;;AAEA;AACA;AACA,qDAAqD,yCAAyC;;;AAG9F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,gBAAY,yCAAyC,aAAa;AAC5E;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,mBAAmB,iCAAiC;AACpD;AACA;AACA;AACA;AACA,8BAA8B,4CAA4C,IAAI,iBAAiB;AAC/F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAU,2BAA2B;AACrC;AACA;AACA;AACA;AACA,MAAM,gBAAY;AAClB;AACA;AACA,QAAQ,gBAAY,oBAAoB,SAAS;AACjD,wBAAwB,gDAAgD,KAAK;AAC7E;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,MAAM;AACN;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,eAAe,mBAAmB;AAClC;AACA,4CAA4C,eAAe;AAC3D,OAAO;AACP;;AAEA;AACA;AACA,sCAAsC,eAAe;AACrD,uCAAuC,0BAA0B;AACjE;AACA;;AAEA;AACA,SAAS;AACT,IAAI,gBAAY;AAChB;AACA;AACA,MAAM,gBAAY,gCAAgC,UAAU;AAC5D,sBAAsB,gDAAgD,WAAW;AACjF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAM,0BAA0B,mCAAmC;AACnE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAU,2BAA2B;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS,8BAA8B;AACvC;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,UAAU,2BAA2B;AACrC;AACA;AACA;AACA;;AAEA,MAAM,gBAAY;AAClB,UAAU,4BAA4B;AACtC;AACA;AACA;AACA;AACA,UAAU,gBAAY,wBAAwB,UAAU;AACxD;AACA;AACA;AACA,yFAAyF,UAAU;AACnG;AACA,QAAQ,gBAAY,mCAAmC,OAAO;AAC9D,wBAAwB,4CAA4C,KAAK;AACzE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;;AAEL,oBAAoB,SAAS;AAC7B;AACA;AACA;AACA,MAAM,gBAAY,0CAA0C,wEAAwE,EAAE,QAAQ;AAC9I,sCAAsC,EAAE;AACxC,sCAAsC,EAAE;AACxC;AACA;;AAEA;AACA;AACA;AACA;AACA,4BAA4B;;AAE5B,8BAA8B,oBAAgB,kBAAkB,EAAE,YAAY;;AAE9E;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,OAAO;AACP,eAAe;AACf,8BAA8B,aAAa;AAC3C,4BAA4B,aAAa;AACzC;;AAEA;AACA,oBAAoB,SAAS;;AAE7B,sCAAsC,EAAE;AACxC;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,eAAe,oBAAgB,aAAa;AAC5C;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,SAAS;AACT,gCAAgC,aAAa;AAC7C,OAAO;AACP;AACA;AACA;AACA;;AAEA;AACA,sBAAsB,WAAW;AACjC,IAAI,gBAAY,0BAA0B,6BAA6B;;AAEvE;AACA;AACA;AACA,MAAM,gBAAY,gCAAgC,MAAM,KAAK,6BAA6B;AAC1F,sBAAsB,yCAAyC,mDAAmD;AAClH;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,QAAQ,gBAAY,sBAAsB,GAAG,YAAY,MAAM,KAAK,OAAO;AAC3E;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,gBAAY,oBAAoB,eAAe,YAAY,MAAM,KAAK,OAAO;AACzF;AACA,yCAAyC,MAAM,+BAA+B;AAC9E;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;;AAEA,UAAU,gBAAY,oBAAoB,eAAe,YAAY,MAAM,KAAK,kBAAkB;AAClG;AACA,uCAAuC,MAAM,+BAA+B;AAC5E;AACA,UAAU;AACV,UAAU,eAAW,yBAAyB,MAAM;AACpD;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,iCAAiC,iBAAiB;AAClD;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA,MAAM,gBAAY,0BAA0B,+BAA+B;;AAE3E;AACA;AACA,QAAQ,gBAAY,iCAAiC,OAAO,KAAK,sCAAsC;AACvG,wBAAwB,0CAA0C,0CAA0C;AAC5G;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,MAAM,gBAAY;AAClB;AACA;AACA,MAAM,gBAAY;AAClB,gCAAgC,0CAA0C;AAC1E;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,QAAQ,gBAAY,YAAY,aAAa,oBAAoB,qBAAqB;AACtF;AACA;AACA;AACA;AACA;;AAEA;AACA,8DAA8D,UAAU;AACxE,MAAM,gBAAY,iCAAiC,UAAU;AAC7D;AACA;AACA;AACA,QAAQ,gBAAY,iCAAiC,WAAW,eAAe,QAAQ;AACvF;AACA,QAAQ,gBAAY,qCAAqC,mCAAmC;AAC5F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA,WAAW;AACX;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA,8CAA8C,yCAAyC;AACvF;AACA,QAAQ,qCAAqC;AAC7C,QAAQ,iCAAiC;AACzC,QAAQ,mCAAmC;AAC3C,QAAQ,mCAAmC;AAC3C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAU,gBAAY,4BAA4B,YAAY,KAAK,kCAAkC;AACrG,0BAA0B,iDAAiD,oCAAoC;AAC/G;AACA;AACA;AACA,qBAAqB,gBAAgB;AACrC;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,oBAAoB,uDAAuD;AAC3E,+CAA+C,oFAAoF;AACnI,+CAA+C,iFAAiF;AAChI,+CAA+C,iFAAiF;AAChI,+CAA+C,mFAAmF;AAClI;AACA,wDAAwD,0CAA0C;AAClG;AACA,oBAAoB,uDAAuD;AAC3E,+CAA+C,8DAA8D;AAC7G,+CAA+C,2DAA2D;AAC1G,+CAA+C,2DAA2D;AAC1G,+CAA+C,6DAA6D;AAC5G,+CAA+C,+DAA+D;AAC9G;AACA,wDAAwD,oBAAoB;;AAE5E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,oCAAoC,mBAAmB;AACvD,iCAAiC,2BAA2B;AAC5D;AACA;AACA;;AAEA,kDAAkD,oBAAoB;AACtE;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,uDAAuD;AACvD;AACA,WAAW;AACX;AACA;AACA;AACA,WAAW;;AAEX;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,WAAW;AACX;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2EAA2E,kBAAc;AACzF;AACA;AACA;AACA;AACA;AACA,wFAAwF;AACxF;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,aAAa;AACb;AACA;AACA,mBAAmB,kBAAc,eAAe,kBAAc;AAC9D;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY;AACZ;AACA,UAAU;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,2DAA2D,cAAc;AACzE;AACA;;AAEA;AACA;AACA;AACA,kBAAkB,IAAI;AACtB;AACA;AACA,WAAW;AACX,SAAS;AACT;;AAEA;AACA;;AAEA,MAAM,gBAAY;AAClB,MAAM;AACN,MAAM,gBAAY;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,IAAI,gBAAY;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,IAAI,gBAAY;AAChB;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,WAAW;AACX,SAAS;AACT;AACA;AACA;AACA;AACA,qEAAqE,kBAAc;AACnF;AACA,WAAW;AACX;AACA;AACA,mBAAmB,kBAAc,eAAe,kBAAc;AAC9D;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;;AAEA,IAAI,gBAAY;AAChB,iEAAiE,cAAc;AAC/E,IAAI,gBAAY;AAChB;AACA;;AAEA;AACA,IAAI,gBAAY,aAAa,KAAK;AAClC;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,oCAAoC,UAAU;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAI,gBAAY,sBAAsB,qCAAqC;AAC3E;AACA;AACA;AACA;AACA,kBAAkB,IAAI;AACtB;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA;AACA;AACA,IAAI,gBAAY;AAChB;;AAEA;AACA;AACA,KAAK;AACL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,IAAI,gBAAY;AAChB;AACA;AACA;AACA;;AAEA;AACA;AACA,qEAAqE,+CAA+C,IAAI,SAAS;AACjI;AACA;AACA,wEAAwE,kDAAkD,IAAI,SAAS;AACvI;AACA;AACA,wEAAwE,kDAAkD,IAAI,SAAS;AACvI;AACA;AACA,0EAA0E,oDAAoD,IAAI,SAAS;AAC3I;AACA;AACA,kHAAkH,+CAA+C,IAAI,SAAS;AAC9K;AACA;AACA,oEAAoE,+CAA+C,IAAI,SAAS;AAChI;AACA;AACA;AACA;AACA;AACA,0BAA0B,+CAA+C,IAAI,eAAe;AAC5F;AACA;AACA;AACA;AACA;AACA,0BAA0B,kDAAkD,IAAI,uBAAuB;AACvG;AACA;AACA,yEAAyE,mDAAmD,IAAI,SAAS;AACzI;AACA;AACA,uEAAuE,iDAAiD,IAAI,SAAS;AACrI;AACA;AACA,qEAAqE,+CAA+C,IAAI,SAAS;AACjI;AACA;AACA,4EAA4E,sDAAsD,IAAI,SAAS;AAC/I;AACA;AACA,sEAAsE,gDAAgD,IAAI,SAAS;AACnI;AACA;AACA,yEAAyE,mDAAmD,IAAI,SAAS;AACzI;AACA;AACA,wEAAwE,kDAAkD,IAAI,SAAS;AACvI;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,uBAAuB,uEAAuE,UAAU,oBAAoB;AAC5H;;AAEA,IAAI,gBAAY;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA,OAAO;AACP,MAAM;AACN;AACA;AACA;AACA;;;ACv3FA;AACA;;AAEwC;AACN;AACF;;AAEhC;AACA;AACA;AACO;;;AAGP,iBAAiB,6CAA6C,IAAI;AAClE;AACA;AACA;;AAEA;AACA;AACA,kBAAkB;AAClB;;AAEA;AACA;AACA;;;AAGA;AACA,6CAA6C,mBAAmB,CAAC,WAAW,KAAK;AACjF,+BAA+B,2BAAuB;AACtD;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,8CAA8C,yCAAyC;AACvF;AACA;;AAEA;AACA;AACA;AACA,QAAQ,eAAW,gCAAgC,YAAY,KAAK,8BAA8B;AAClG,iCAAiC,iDAAiD,gCAAgC;AAClH;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,WAAW,iBAAiB,KAAK,UAAU;AAC3C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wDAAwD,iBAAiB;AACzE;AACA,uFAAuF,cAAc;AACrG;AACA;;AAEA;AACA;AACA;AACA;AACA,4BAA4B,oBAAgB;AAC5C;AACA;AACA;;AAEA;;AAEA,IAAI,gBAAY;AAChB;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;ACrIwC;AACN;AACF;AACe;AACR;;AAEhC;;AAEP;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,0CAA0C,mBAAmB,CAAC;AAC9D,0BAA0B,cAAc,CAAC;AACzC;AACA;AACA;AACA;AACA,sBAAsB,kEAAkE;AACxF;AACA;;AAEA;AACA;AACA,kBAAkB,kBAAc;;AAEhC;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;;AAEA;AACA,mEAAmE,KAAK;AACxE;AACA,iCAAiC,kCAAkC;AACnE,qCAAqC,yCAAyC,YAAY,IAAI,GAAG,cAAc;AAC/G;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,gBAAY;;AAEhB,UAAU,kBAAc;;AAExB;AACA;;AAEA,4BAA4B,WAAW;AACvC;AACA;AACA,MAAM;AACN;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;;AAEA,IAAI,gBAAY;AAChB;AACA,IAAI,gBAAY;AAChB;AACA,IAAI,gBAAY;AAChB;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA,0BAA0B,OAAO;AACjC;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;;AAEA;;;AC/HgE;AACE;AACd;AACgB;AACxB;AACI;AACR;AAC0C;AAC5B;AACtB;;AAEzB;AACP,mBAAmB,qBAAqB;AACxC,eAAe;AACf,uBAAuB;AACvB,WAAW;AACX,qBAAqB;AACrB,aAAa;AACb,sBAAsB;AACtB;AACA,uBAAuB,eAAe;AACtC,iBAAiB,oBAAoB;AACrC,2BAA2B,oBAAoB;AAC/C,aAAa,eAAe;AAC5B,KAAK;AACL,WAAW,SAAK;AAChB,aAAa;AACb;AACA;;;AC5BkE;AAC1B;;AAExC;AACA,4CAA4C,8BAA8B;AAC1E;AACA,4BAA4B,qBAAqB;AACjD;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,mCAAmC,mBAAmB,CAAC;AACvD,4BAA4B,mBAAmB,CAAC,qBAAqB;AACrE,WAAW,mBAAmB,CAAC;AAC/B,QAAQ;AACR;AACA;AACA;AACA,uCAAuC,mBAAmB,CAAC;AAC3D;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA;AACA,uCAAuC,mBAAmB,CAAC;AAC3D,SAAS;AACT,OAAO;AACP;AACA,KAAK;AACL;AACA;;AAEO;AACP,6BAA6B,qBAAqB;AAClD,aAAa,mBAAmB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,aAAa,mBAAmB,CAAC;AACjC;AACA;AACA;AACA,GAAG;;AAEH,4CAA4C,8BAA8B;AAC1E,2BAA2B,qBAAqB;AAChD;;AAEA,6BAA6B,qBAAqB;AAClD,aAAa,mBAAmB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,aAAa,mBAAmB,CAAC;AACjC;AACA,UAAU,kBAAkB;AAC5B;AACA,GAAG;;AAEH;;;AC7DoE;AAC5B;AACR;;AAEzB;;AAEP,2BAA2B,iBAAa;AACxC;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,6DAA6D,0BAA0B,CAAC,sCAAsC,0BAA0B,CAAC;;AAEzJ;AACA;AACA,8BAA8B,mBAAmB,CAAC,kCAAkC;AACpF;AACA,UAAU;AACV,sDAAsD,mBAAmB,CAAC,0CAA0C,iBAAiB;AACrI;AACA,OAAO;;AAEP;AACA;AACA;AACA,KAAK;AACL,GAAG;;AAEH;;;ACtC6C;AACU;AACC;;AAExD;AACA,EAAE,gBAAgB;AAClB,CAAC;;AAED;AACA,EAAE,mBAAmB;AACrB,EAAE,WAAW;AACb,CAAC","sources":["webpack://pathmuncher/./src/constants.js","webpack://pathmuncher/./src/utils.js","webpack://pathmuncher/./src/logger.js","webpack://pathmuncher/./src/data/equipment.js","webpack://pathmuncher/./src/data/features.js","webpack://pathmuncher/./src/data/spells.js","webpack://pathmuncher/./src/app/Seasoning.js","webpack://pathmuncher/./src/app/CompendiumMatcher.js","webpack://pathmuncher/./src/app/CompendiumSelector.js","webpack://pathmuncher/./src/app/Pathmuncher.js","webpack://pathmuncher/./src/app/PetShop.js","webpack://pathmuncher/./src/app/PathmuncherImporter.js","webpack://pathmuncher/./src/hooks/api.js","webpack://pathmuncher/./src/hooks/settings.js","webpack://pathmuncher/./src/hooks/sheets.js","webpack://pathmuncher/./src/module.js"],"sourcesContent":["const debouncedReload = foundry.utils.debounce(() => window.location.reload(), 100);\n\nconst CONSTANTS = {\n MODULE_NAME: \"pathmuncher\",\n MODULE_FULL_NAME: \"Pathmuncher\",\n FLAG_NAME: \"pathmuncher\",\n SETTINGS: {\n // Enable options\n LOG_LEVEL: \"log-level\",\n RESTRICT_TO_TRUSTED: \"restrict-to-trusted\",\n ADD_VISION_FEATS: \"add-vision-feats\",\n USE_CUSTOM_COMPENDIUM_MAPPINGS: \"use-custom-compendium-mappings\",\n CUSTOM_COMPENDIUM_MAPPINGS: \"custom-compendium-mappings\",\n USE_IMMEDIATE_DEEP_DIVE: \"use-immediate-deep-dive\",\n },\n\n FEAT_PRIORITY: [\n \"Heritage\",\n \"Heritage Feat\",\n \"Ancestry\",\n \"Ancestry Feat\",\n \"Background\",\n \"Background Feat\",\n \"Class Feat\",\n \"Skill Feat\",\n \"General Feat\",\n \"Awarded Feat\",\n ],\n\n ACTOR_FLAGS: {\n pathbuilderId: undefined,\n addFeats: true,\n addEquipment: true,\n addBackground: true,\n addHeritage: true,\n addAncestry: true,\n addSpells: true,\n adjustBlendedSlots: true,\n addMoney: true,\n addTreasure: true,\n addLores: true,\n addWeapons: true,\n addArmor: true,\n addDeity: true,\n addName: true,\n addClass: true,\n addFamiliars: true,\n addFormulas: true,\n },\n\n CORE_COMPENDIUM_MAPPINGS: {\n feats: [\n \"pf2e.feats-srd\",\n \"pf2e-playtest-data.war-of-immortals-playtest-class-feats\",\n \"pf2e-legacy-content.feats-legacy\",\n ],\n ancestryFeatures: [\"pf2e.ancestryfeatures\", \"pf2e-legacy-content.ancestry-features-legacy\"],\n classFeatures: [\n \"pf2e.classfeatures\",\n \"pf2e-playtest-data.war-of-immortals-playtest-class-features\",\n \"pf2e-legacy-content.class-features-legacy\",\n ],\n actions: [\n \"pf2e.actionspf2e\",\n \"pf2e-playtest-data.war-of-immortals-playtest-actions\",\n \"pf2e-legacy-content.actions-legacy\",\n ],\n spells: [\n \"pf2e-psychic-amps.psychic-psi-cantrips\",\n \"pf2e.spells-srd\",\n \"pf2e-playtest-data.war-of-immortals-playtest-spells\",\n \"pf2e-legacy-content.spells-legacy\",\n ],\n classes: [\n \"pf2e.classes\",\n \"pf2e-playtest-data.war-of-immortals-playtest-classes\",\n \"pf2e-legacy-content.classes-legacy\",\n ],\n ancestries: [\"pf2e.ancestries\", \"pf2e-legacy-content.ancestries-legacy\"],\n heritages: [\"pf2e.heritages\", \"pf2e-legacy-content.heritages-legacy\"],\n equipment: [\"pf2e.equipment-srd\", \"pf2e-legacy-content.equipment-legacy\"],\n formulas: [\"pf2e.equipment-srd\", \"pf2e-legacy-content.formulas-legacy\"],\n deities: [\"pf2e.deities\", \"pf2e-legacy-content.deities-legacy\"],\n backgrounds: [\"pf2e.backgrounds\", \"pf2e-legacy-content.backgrounds-legacy\"],\n },\n\n GET_DEFAULT_SETTINGS() {\n return foundry.utils.deepClone(CONSTANTS.DEFAULT_SETTINGS);\n },\n};\n\nCONSTANTS.DEFAULT_SETTINGS = {\n // Enable options\n [CONSTANTS.SETTINGS.RESTRICT_TO_TRUSTED]: {\n name: `${CONSTANTS.FLAG_NAME}.Settings.RestrictToTrusted.Name`,\n hint: `${CONSTANTS.FLAG_NAME}.Settings.RestrictToTrusted.Hint`,\n scope: \"world\",\n config: true,\n type: Boolean,\n default: false,\n onChange: debouncedReload,\n },\n\n [CONSTANTS.SETTINGS.USE_CUSTOM_COMPENDIUM_MAPPINGS]: {\n name: `${CONSTANTS.FLAG_NAME}.Settings.UseCustomCompendiumMappings.Name`,\n scope: \"world\",\n config: false,\n type: Boolean,\n default: false,\n },\n\n [CONSTANTS.SETTINGS.USE_IMMEDIATE_DEEP_DIVE]: {\n name: `${CONSTANTS.FLAG_NAME}.Settings.UseImmediateDeepDive.Name`,\n scope: \"world\",\n config: false,\n type: Boolean,\n default: true,\n },\n\n [CONSTANTS.SETTINGS.CUSTOM_COMPENDIUM_MAPPINGS]: {\n scope: \"world\",\n config: false,\n type: Object,\n default: {\n feats: [\n \"battlezoo-ancestries-dragons-pf2e.pf2e-battlezoo-dragon-feats\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-features\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-feats\",\n \"clerics.clerics-feats\",\n \"clerics.clerics-features\",\n \"pf2e.feats-srd\",\n \"pf2e-playtest-data.war-of-immortals-playtest-class-feats\",\n ],\n ancestryFeatures: [\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-features\",\n \"pf2e.ancestryfeatures\",\n ],\n classFeatures: [\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-features\",\n \"battlezoo-ancestries-dragons-pf2e.pf2e-battlezoo-dragon-feats\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-feats\",\n \"clerics.clerics-doctrines\",\n \"clerics.clerics-feats\",\n \"clerics.clerics-features\",\n \"pf2e.classfeatures\",\n \"pf2e-playtest-data.war-of-immortals-playtest-class-features\",\n ],\n actions: [\"pf2e.actionspf2e\", \"pf2e-playtest-data.war-of-immortals-playtest-actions\"],\n spells: [\"pf2e-psychic-amps.psychic-psi-cantrips\", \"pf2e.spells-srd\", \"pf2e-playtest-data.war-of-immortals-playtest-spells\"],\n classes: [\"clerics.clerics-features\", \"pf2e.classes\", \"pf2e-playtest-data.war-of-immortals-playtest-classes\"],\n ancestries: [\n \"battlezoo-ancestries-dragons-pf2e.pf2e-battlezoo-dragon-ancestry\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-ancestries\",\n \"pf2e.ancestries\",\n ],\n heritages: [\n \"battlezoo-ancestries-dragons-pf2e.pf2e-battlezoo-dragon-heritages\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-heritages\",\n \"pf2e.heritages\",\n ],\n equipment: [\n \"battlezoo-ancestries-dragons-pf2e.pf2e-battlezoo-dragon-equipment\",\n \"battlezoo-ancestries-year-of-monsters-pf2e.yom-equipment\",\n \"pf2e.equipment-srd\"\n ],\n formulas: [\"pf2e.equipment-srd\"],\n deities: [\"clerics.clerics-deities\", \"pf2e.deities\"],\n backgrounds: [\"pf2e.backgrounds\"],\n },\n },\n\n [CONSTANTS.SETTINGS.ADD_VISION_FEATS]: {\n name: `${CONSTANTS.FLAG_NAME}.Settings.AddVisionFeats.Name`,\n hint: `${CONSTANTS.FLAG_NAME}.Settings.AddVisionFeats.Hint`,\n scope: \"player\",\n config: true,\n type: Boolean,\n default: false,\n },\n\n // debug\n [CONSTANTS.SETTINGS.LOG_LEVEL]: {\n name: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.Name`,\n hint: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.Hint`,\n scope: \"world\",\n config: true,\n type: String,\n choices: {\n DEBUG: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.debug`,\n INFO: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.info`,\n WARN: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.warn`,\n ERR: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.error`,\n OFF: `${CONSTANTS.FLAG_NAME}.Settings.LogLevel.off`,\n },\n default: \"WARN\",\n }\n\n};\n\nCONSTANTS.PATH = `modules/${CONSTANTS.MODULE_NAME}`;\n\nexport default CONSTANTS;\n","import CONSTANTS from \"./constants.js\";\n\nconst utils = {\n\n isObject: (obj) => {\n return typeof obj === 'object' && !Array.isArray(obj) && obj !== null;\n },\n\n isString: (str) => {\n return typeof str === 'string' || str instanceof String;\n },\n\n wait: async (ms) => {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n },\n\n capitalize: (s) => {\n if (typeof s !== \"string\") return \"\";\n return s.charAt(0).toUpperCase() + s.slice(1);\n },\n\n setting: (key) => {\n return game.settings.get(CONSTANTS.MODULE_NAME, CONSTANTS.SETTINGS[key]);\n },\n\n updateSetting: async (key, value) => {\n return game.settings.set(CONSTANTS.MODULE_NAME, CONSTANTS.SETTINGS[key], value);\n },\n\n getFlags: (actor) => {\n const flags = actor.flags[CONSTANTS.FLAG_NAME]\n ? actor.flags[CONSTANTS.FLAG_NAME]\n : CONSTANTS.ACTOR_FLAGS;\n return flags;\n },\n\n setFlags: async (actor, flags) => {\n let updateData = {};\n setProperty(updateData, `flags.${CONSTANTS.FLAG_NAME}`, flags);\n await actor.update(updateData);\n return actor;\n },\n\n resetFlags: async (actor) => {\n return utils.setFlags(actor, null);\n },\n\n\n getOrCreateFolder: async (root, entityType, folderName, folderColor = \"\") => {\n let folder = game.folders.contents.find((f) =>\n f.type === entityType && f.name === folderName\n // if a root folder we want to match the root id for the parent folder\n && (root ? root.id : null) === (f.folder?.id ?? null)\n );\n // console.warn(`Looking for ${root} ${entityType} ${folderName}`);\n // console.warn(folder);\n if (folder) return folder;\n folder = await Folder.create(\n {\n name: folderName,\n type: entityType,\n color: folderColor,\n parent: (root) ? root.id : null,\n },\n { displaySheet: false }\n );\n return folder;\n },\n\n // eslint-disable-next-line no-unused-vars\n getFolder: async (kind, subFolder = \"\", baseFolderName = \"Pathmuncher\", baseColor = \"#6f0006\", subColor = \"#98020a\", typeFolder = true) => {\n let entityTypes = new Map();\n entityTypes.set(\"pets\", \"Pets\");\n\n const folderName = game.i18n.localize(`${CONSTANTS.MODULE_NAME}.labels.${kind}`);\n const entityType = entityTypes.get(kind);\n const baseFolder = await utils.getOrCreateFolder(null, entityType, baseFolderName, baseColor);\n const entityFolder = typeFolder ? await utils.getOrCreateFolder(baseFolder, entityType, folderName, subColor) : baseFolder;\n if (subFolder !== \"\") {\n const subFolderName = subFolder.charAt(0).toUpperCase() + subFolder.slice(1);\n const typeFolder = await utils.getOrCreateFolder(entityFolder, entityType, subFolderName, subColor);\n return typeFolder;\n } else {\n return entityFolder;\n }\n },\n\n allowDualClasses: () => {\n return (isNewerVersion(\"5.9.0\", game.version) && game.settings.get(\"pf2e\", \"dualClassVariant\"));\n // || (!isNewerVersion(\"5.9.0\", game.version) && when remaster supports dualclass then add here\n },\n\n allowAncestryParagon: () => {\n return (isNewerVersion(\"5.9.0\", game.version) && game.settings.get(\"pf2e\", \"ancestryParagonVariant\"));\n }\n\n};\n\n\nexport default utils;\n","import CONSTANTS from \"./constants.js\";\nimport utils from \"./utils.js\";\n\nconst logger = {\n _showMessage: (logLevel, data) => {\n if (!logLevel || !data || typeof logLevel !== \"string\") {\n return false;\n }\n\n const setting = utils.setting(\"LOG_LEVEL\");\n const logLevels = [\"DEBUG\", \"INFO\", \"WARN\", \"ERR\", \"OFF\"];\n const logLevelIndex = logLevels.indexOf(logLevel.toUpperCase());\n if (setting == \"OFF\" || logLevelIndex === -1 || logLevelIndex < logLevels.indexOf(setting)) {\n return false;\n }\n return true;\n },\n log: (logLevel, ...data) => {\n if (!logger._showMessage(logLevel, data)) {\n return;\n }\n\n logLevel = logLevel.toUpperCase();\n\n let msg = \"No logging message provided. Please see the payload for more information.\";\n let payload = data.slice();\n if (data[0] && typeof (data[0] == \"string\")) {\n msg = data[0];\n if (data.length > 1) {\n payload = data.slice(1);\n } else {\n payload = null;\n }\n }\n msg = `${CONSTANTS.MODULE_NAME} | ${logLevel} > ${msg}`;\n switch (logLevel) {\n case \"DEBUG\":\n if (payload) {\n console.debug(msg, ...payload); // eslint-disable-line no-console\n } else {\n console.debug(msg); // eslint-disable-line no-console\n }\n break;\n case \"INFO\":\n if (payload) {\n console.info(msg, ...payload); // eslint-disable-line no-console\n } else {\n console.info(msg); // eslint-disable-line no-console\n }\n break;\n case \"WARN\":\n if (payload) {\n console.warn(msg, ...payload); // eslint-disable-line no-console\n } else {\n console.warn(msg); // eslint-disable-line no-console\n }\n break;\n case \"ERR\":\n if (payload) {\n console.error(msg, ...payload); // eslint-disable-line no-console\n } else {\n console.error(msg); // eslint-disable-line no-console\n }\n break;\n default:\n break;\n }\n },\n\n debug: (...data) => {\n logger.log(\"DEBUG\", ...data);\n },\n\n info: (...data) => {\n logger.log(\"INFO\", ...data);\n },\n\n warn: (...data) => {\n logger.log(\"WARN\", ...data);\n },\n\n error: (...data) => {\n logger.log(\"ERR\", ...data);\n },\n};\nexport default logger;\n","const SWAPS = [\n /^(Greater) (.*)/,\n /^(Lesser) (.*)/,\n /^(Major) (.*)/,\n /^(Moderate) (.*)/,\n /^(Standard) (.*)/,\n];\n\nconst POSTFIX_PB_REMOVALS = [\n /(.*) (- Melee)$/,\n /(.*) (- Ranged)$/,\n /(Charm of Resistance .*) - (.*)/,\n];\n\nconst PARENTHESIS = [\n /^(.*) \\((.*)\\)$/,\n];\n\nconst SPLITS = [\n // /^(.*) - (.*)/,\n];\n\nconst SPLITS_INVERT = [\n /^(.*): (.*)/,\n];\n\nconst REPLACES = [\n { pbName: \"Ring of Energy Resistance\", foundryName: \"Charm of Resistance\" },\n { pbName: \"Feather Token\", foundryName: \"Marvelous Miniatures\" },\n { pbName: \"Goggles of Night\", foundryName: \"Obsidian Goggles\" },\n];\n\n// this equipment is named differently in foundry vs pathbuilder\nexport const EQUIPMENT_RENAME_STATIC_MAP = [\n { pbName: \"Inventor Power Suit\", foundryName: \"Power Suit\" },\n { pbName: \"Inventor Power Suit (Heavy)\", foundryName: \"Power Suit\" },\n { pbName: \"Inventor Subterfuge Suit\", foundryName: \"Subterfuge Suit\" },\n { pbName: \"Chain\", foundryName: \"Chain (10 feet)\" },\n { pbName: \"Oil\", foundryName: \"Oil (1 pint)\" },\n { pbName: \"Bracelets of Dashing\", foundryName: \"Bracelet of Dashing\" },\n { pbName: \"Fingerprinting Kit\", foundryName: \"Fingerprint Kit\" },\n { pbName: \"Ladder\", foundryName: \"Ladder (10-foot)\" },\n { pbName: \"Mezmerizing Opal\", foundryName: \"Mesmerizing Opal\" },\n // { pbName: \"Explorer's Clothing\", foundryName: \"Clothing (Explorer's)\" },\n { pbName: \"Flaming Star (Greater)\", foundryName: \"Greater Flaming Star\" },\n { pbName: \"Potion of Lesser Darkvision\", foundryName: \"Darkvision Elixir (Lesser)\" },\n { pbName: \"Potion of Greater Darkvision\", foundryName: \"Darkvision Elixir (Greater)\" },\n { pbName: \"Potion of Moderate Darkvision\", foundryName: \"Darkvision Elixir (Moderate)\" },\n { pbName: \"Bottled Sunlight\", foundryName: \"Formulated Sunlight\" },\n { pbName: \"Magazine (Repeating Hand Crossbow)\", foundryName: \"Magazine with 5 Bolts\" },\n { pbName: \"Astrolabe (Standard)\", foundryName: \"Standard Astrolabe\" },\n { pbName: \"Skinitch Salve\", foundryName: \"Skinstitch Salve\" },\n { pbName: \"Flawless Scale\", foundryName: \"Abadar's Flawless Scale\" },\n { pbName: \"Construct Key\", foundryName: \"Cordelia's Construct Key\" },\n { pbName: \"Construct Key (Greater)\", foundryName: \"Cordelia's Greater Construct Key\" },\n { pbName: \"Lesser Swapping Stone\", foundryName: \"Lesser Bonmuan Swapping Stone\" },\n { pbName: \"Major Swapping Stone\", foundryName: \"Major Bonmuan Swapping Stone\" },\n { pbName: \"Moderate Swapping Stone\", foundryName: \"Moderate Bonmuan Swapping Stone\" },\n { pbName: \"Greater Swapping Stone\", foundryName: \"Greater Bonmuan Swapping Stone\" },\n { pbName: \"Heartstone\", foundryName: \"Skarja's Heartstone\" },\n { pbName: \"Bullets (10 rounds)\", foundryName: \"Sling Bullets\" },\n { pbName: \"Hide\", foundryName: \"Hide Armor\" },\n { pbName: \"Soverign Glue\", foundryName: \"Sovereign Glue\" },\n { pbName: \"Axe Musket - Melee\", foundryName: \"Axe Musket\" },\n { pbName: \"Axe Musket - Ranged\", foundryName: \"Axe Musket\" },\n { pbName: \"Extendible Pincer\", foundryName: \"Extendable Pincer\" },\n { pbName: \"Clothing (Explorer's)\", foundryName: \"Explorer's Clothing\" },\n { pbName: \"Street Preacher [Placeholder]\", foundryName: \"Street Preacher\" },\n { pbName: \"Repair Kit\", foundryName: \"Repair Toolkit\" },\n { pbName: \"Repair Kit (Superb)\", foundryName: \"Repair Toolkit (Superb)\" },\n { pbName: \"Alchemist's Tools\", foundryName: \"Alchemist's Toolkit\" },\n { pbName: \"Healer's Tools\", foundryName: \"Healer's Toolkit\" },\n { pbName: \"Healer's Tools (Expanded)\", foundryName: \"Healer's Toolkit (Expanded)\" },\n { pbName: \"Thieves' Tools\", foundryName: \"Thieves' Toolkit\" },\n { pbName: \"Thieves' Tools (Infiltrator)\", foundryName: \"Thieves' Toolkit (Infiltrator)\" },\n { pbName: \"Thieves' Tools (Infiltrator Picks)\", foundryName: \"Thieves' Toolkit (Infiltrator Picks)\" },\n { pbName: \"Artisan's Tools\", foundryName: \"Artisan's Toolkit\" },\n { pbName: \"Artisan's Tools (Sterling)\", foundryName: \"Artisan's Toolkit (Sterling)\" },\n\n { pbName: \"Aeon Stone (Dull Grey)\", foundryName: \"Aeon Stone (Consumed)\" },\n { pbName: \"Aeon Stone (Clear Spindle)\", foundryName: \"Aeon Stone (Nourishing)\" },\n { pbName: \"Aeon Stone (Tourmaline Sphere)\", foundryName: \"Aeon Stone (Delaying)\" },\n { pbName: \"Aeon Stone (Orange Prism)\", foundryName: \"Aeon Stone (Amplifying)\" },\n { pbName: \"Bag of Holding\", foundryName: \"Spacious Pouch\" },\n { pbName: \"Barkskin Potion\", foundryName: \"Oak Potion\" },\n { pbName: \"Boots of Speed\", foundryName: \"Propulsive Boots\" },\n { pbName: \"Bracers of Armor\", foundryName: \"Bands of Force\" },\n { pbName: \"Broom of Flying\", foundryName: \"Flying Broomstick\" },\n { pbName: \"Dagger of Venom\", foundryName: \"Serpent Dagger\" },\n // these are actually matched to energy type witch Pathbuilder does not support\n { pbName: \"Dragon's Breath Potion (Young)\", foundryName: \"Energy Breath Potion (Lesser)\" },\n { pbName: \"Dragon's Breath Potion (Adult)\", foundryName: \"Energy Breath Potion (Moderate)\" },\n { pbName: \"Dragon's Breath Potion (Wyrm)\", foundryName: \"Energy Breath Potion (Greater)\" },\n { pbName: \"Druid's Vestments\", foundryName: \"Living Mantle\" },\n { pbName: \"Everburning Torch\", foundryName: \"Everlight Crystal\" },\n { pbName: \"Eyes of the Eagle\", foundryName: \"Eyes of the Cat\" },\n { pbName: \"Feather Token (Chest)\", foundryName: \"Marvelous Miniatures (Chest)\" },\n { pbName: \"Feather Token (Ladder)\", foundryName: \"Marvelous Miniatures (Ladder)\" },\n { pbName: \"Feather Token (Swan Boat)\", foundryName: \"Marvelous Miniatures (Boat)\" },\n { pbName: \"Flame Tongue\", foundryName: \"Searing Blade\" },\n { pbName: \"Gloves of Storing\", foundryName: \"Retrieval Belt\" },\n { pbName: \"Goggles of Night\", foundryName: \"Obsidian Goggles\" },\n { pbName: \"Goggles of Night (Greater)\", foundryName: \"Obsidian Goggles (Greater)\" },\n { pbName: \"Goggles of Night (Major)\", foundryName: \"Obsidian Goggles (Major)\" },\n { pbName: \"Hat of Disguise\", foundryName: \"Masquerade Scarf\" },\n { pbName: \"Hat of Disguise (Greater)\", foundryName: \"Masquerade Scarf (Greater)\" },\n { pbName: \"Horn of Fog\", foundryName: \"Cloud Pouch\" },\n { pbName: \"Horseshoes of Speed\", foundryName: \"Alacritous Horseshoes\" },\n { pbName: \"Javelin of Lightning\", foundryName: \"Trident of Lightning\" },\n { pbName: \"Potion of Expeditious Retreat\", foundryName: \"Potion of Emergency Escape\" },\n { pbName: \"Ring of Energy Resistance (Greater)\", foundryName: \"Charm of Resistance (Greater)\" },\n { pbName: \"Ring of Energy Resistance (Major)\", foundryName: \"Charm of Resistance (Major)\" },\n { pbName: \"Silversheen\", foundryName: \"Silver Salve\" },\n { pbName: \"Smokestick (Lesser)\", foundryName: \"Smoke Ball (Lesser)\" },\n { pbName: \"Smokestick (Greater)\", foundryName: \"Smoke Ball (Greater)\" },\n { pbName: \"Sunrod\", foundryName: \"Glow Rod\" },\n { pbName: \"Tanglefoot Bag (Lesser)\", foundryName: \"Glue Bomb (Lesser)\" },\n { pbName: \"Tanglefoot Bag (Moderate)\", foundryName: \"Glue Bomb (Moderate)\" },\n { pbName: \"Tanglefoot Bag (Major)\", foundryName: \"Glue Bomb (Major)\" },\n { pbName: \"Tanglefoot Bag (Greater)\", foundryName: \"Glue Bomb (Greater)\" },\n { pbName: \"Tindertwig\", foundryName: \"Matchstick\" },\n { pbName: \"Owlbear Claw\", foundryName: \"Predator's Claw\" },\n { pbName: \"Wand of Manifold Missiles\", foundryName: \"Wand of Shardstorm\" },\n { pbName: \"Wand of Manifold Missiles (1st-Level Spell)\", foundryName: \"Wand of Shardstorm (1st-Rank Spell)\" },\n { pbName: \"Wand of Manifold Missiles (3rd-Level Spell)\", foundryName: \"Wand of Shardstorm (3rd-Rank Spell)\" },\n { pbName: \"Wand of Manifold Missiles (5th-Level Spell)\", foundryName: \"Wand of Shardstorm (5th-Rank Spell)\" },\n { pbName: \"Wand of Manifold Missiles (7th-Level Spell)\", foundryName: \"Wand of Shardstorm (7th-Rank Spell)\" },\n\n];\n\nfunction dynamicNamesSteps(pbName) {\n const result = [];\n for (const reg of POSTFIX_PB_REMOVALS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[1], details: match[2] });\n }\n }\n for (const reg of SWAPS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: `${match[2]} (${match[1]})`, details: match[2] });\n }\n }\n for (const reg of SPLITS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[2], details: match[1] });\n }\n }\n for (const reg of SPLITS_INVERT) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[1], details: match[2] });\n }\n }\n for (const reg of PARENTHESIS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[1], details: match[2] });\n }\n }\n return result;\n}\n\nfunction generateDynamicNames(pbName) {\n const result = [];\n // if we have a hardcoded map, don't return here\n const basicResults = EQUIPMENT_RENAME_STATIC_MAP.filter((e) => e.pbName === pbName);\n if (basicResults.length > 0) {\n result.push(...basicResults);\n }\n\n for (const replace of REPLACES) {\n if (pbName.includes(replace.pbName)) {\n const replaced = pbName.replace(replace.pbName, replace.foundryName);\n result.push(...dynamicNamesSteps(replaced));\n result.push({ pbName, foundryName: replaced });\n }\n }\n\n if (result.length > 0) {\n return result;\n }\n\n result.push(...dynamicNamesSteps(pbName));\n return result;\n}\n\n\nexport function EQUIPMENT_RENAME_MAP(pbName = null) {\n const postfixNames = pbName ? generateDynamicNames(pbName) : [];\n return postfixNames.concat(EQUIPMENT_RENAME_STATIC_MAP);\n}\n\n\n// this is equipment is special and shouldn't have the transformations applied to it\nexport const RESTRICTED_EQUIPMENT = [\n \"Bracers of Armor\",\n];\n\nexport const IGNORED_EQUIPMENT = [\n \"Unarmored\",\n \"Inventor Power Suit\",\n \"Inventor Power Suit (Heavy)\",\n \"Inventor Subterfuge Suit\",\n];\n\nconst IGNORED_DISPLAY_POSTFIX = [\n /(.*) - Melee$/,\n /(.*) - Ranged$/,\n];\n\nexport function IGNORED_EQUIPMENT_DISPLAY(pbName) {\n for (const reg of IGNORED_DISPLAY_POSTFIX) {\n const match = reg.test(pbName);\n if (match === true) return true;\n }\n return false;\n}\n\nexport const GRANTED_ITEMS_LIST = [\n \"Inventor Power Suit\",\n \"Inventor Power Suit (Heavy)\",\n \"Inventor Subterfuge Suit\",\n];\n","// these are features which are named differently in pathbuilder to foundry\n\nimport utils from \"../utils.js\";\n\nconst SKILL_LOOKUP = {\n \"acrobatics\": \"acr\",\n \"arcana\": \"arc\",\n \"athletics\": \"ath\",\n \"crafting\": \"cra\",\n \"deception\": \"dec\",\n \"diplomacy\": \"dip\",\n \"intimidation\": \"itm\",\n \"medicine\": \"med\",\n \"nature\": \"nat\",\n \"occultism\": \"occ\",\n \"performance\": \"prf\",\n \"religion\": \"rel\",\n \"society\": \"soc\",\n \"stealth\": \"ste\",\n \"survival\": \"sur\",\n \"thievery\": \"thi\",\n};\n\nconst POSTFIX_PB_REMOVALS = [\n /(.*) (Racket)$/,\n /(.*) (Style)$/,\n /(.*) (Initiate Benefit)$/,\n /(.*) Mystery$/,\n // Cleric +\n /(.*) (Doctrine)$/,\n /(.*) (Element)$/,\n /(.*) (Impulse Junction)$/,\n /(.*) (Gate Junction:).*$/,\n /(.*) (Patron)$/,\n];\n\nconst PREFIX_PB_REMOVALS = [\n /^(Arcane Thesis): (.*)/,\n /^(Arcane School): (.*)/,\n /^(The) (.*)/,\n // Cleric +\n /^(Blessing): (.*)/,\n /^(Empiricism) Selected Skill: (.*)/,\n];\n\nconst POSTFIX_PB_SPLIT_AND_KEEP = [\n /(.*) (Impulse Junction)$/,\n /(.*) Gate Junction: (.*)$/,\n];\n\nconst PARENTHESIS = [\n /^(.*) \\((.*)\\)$/,\n];\n\nconst SPLITS = [\n /^(.*): (.*)/,\n];\n\nconst SWAPS = [\n /^(Greater) (.*)/,\n /^(Lesser) (.*)/,\n /^(Major) (.*)/,\n /^(Moderate) (.*)/,\n /^(Standard) (.*)/,\n];\n\nconst FEAT_RENAME_STATIC_MAP = [\n { pbName: \"Academic\", foundryName: \"Ustalavic Academic\" },\n { pbName: \"Academic (Arcana)\", foundryName: \"Magaambya Academic\" },\n { pbName: \"Academic (Nature)\", foundryName: \"Magaambya Academic\" },\n { pbName: \"Aerialist\", foundryName: \"Shory Aerialist\" },\n { pbName: \"Aeromancer\", foundryName: \"Shory Aeromancer\" },\n { pbName: \"Ancient-Blooded\", foundryName: \"Ancient-Blooded Dwarf\" },\n { pbName: \"Antipaladin [Chaotic Evil]\", foundryName: \"Antipaladin\" },\n { pbName: \"Ape\", foundryName: \"Ape Animal Instinct\" },\n { pbName: \"Aquatic Eyes (Darkvision)\", foundryName: \"Aquatic Eyes\" },\n { pbName: \"Astrology\", foundryName: \"Saoc Astrology\" },\n { pbName: \"Battle Ready\", foundryName: \"Battle-Ready Orc\" },\n { pbName: \"Bite (Gnoll)\", foundryName: \"Bite\" },\n { pbName: \"Bloodline: Genie (Efreeti)\", foundryName: \"Bloodline: Genie\" },\n { pbName: \"Bloody Debilitations\", foundryName: \"Bloody Debilitation\" },\n { pbName: \"Canoneer\", foundryName: \"Cannoneer\" },\n { pbName: \"Cave Climber Kobold\", foundryName: \"Caveclimber Kobold\" },\n { pbName: \"Child of Squalor\", foundryName: \"Child of the Puddles\" },\n { pbName: \"Chosen One\", foundryName: \"Chosen of Lamashtu\" },\n { pbName: \"Cognative Mutagen (Greater)\", foundryName: \"Cognitive Mutagen (Greater)\" },\n { pbName: \"Cognative Mutagen (Lesser)\", foundryName: \"Cognitive Mutagen (Lesser)\" },\n { pbName: \"Cognative Mutagen (Major)\", foundryName: \"Cognitive Mutagen (Major)\" },\n { pbName: \"Cognative Mutagen (Moderate)\", foundryName: \"Cognitive Mutagen (Moderate)\" },\n { pbName: \"Cognitive Crossover\", foundryName: \"Kreighton's Cognitive Crossover\" },\n { pbName: \"Collegiate Attendant Dedication\", foundryName: \"Magaambyan Attendant Dedication\" },\n { pbName: \"Construct Carver\", foundryName: \"Tupilaq Carver\" },\n { pbName: \"Cunning Stance\", foundryName: \"Devrin's Cunning Stance\" },\n { pbName: \"Constructed (Android)\", foundryName: \"Constructed\" },\n { pbName: \"Dazzling Diversion\", foundryName: \"Devrin's Dazzling Diversion\" },\n { pbName: \"Deadly Hair\", foundryName: \"Syu Tak-nwa's Deadly Hair\" },\n { pbName: \"Deepvision\", foundryName: \"Deep Vision\" },\n { pbName: \"Deflect Arrows\", foundryName: \"Deflect Arrow\" },\n { pbName: \"Desecrator [Neutral Evil]\", foundryName: \"Desecrator\" },\n { pbName: \"Detective Dedication\", foundryName: \"Edgewatch Detective Dedication\" },\n { pbName: \"Duelist Dedication (LO)\", foundryName: \"Aldori Duelist Dedication\" },\n { pbName: \"Dwarven Hold Education\", foundryName: \"Dongun Education\" },\n { pbName: \"Ember's Eyes (Darkvision)\", foundryName: \"Ember's Eyes\" },\n { pbName: \"Enhanced Familiar Feat\", foundryName: \"Enhanced Familiar\" },\n { pbName: \"Enhanced Fire\", foundryName: \"Artokus's Fire\" },\n { pbName: \"Enigma\", foundryName: \"Enigma Muse\" },\n { pbName: \"Escape\", foundryName: \"Fane's Escape\" },\n { pbName: \"Eye of the Arcane Lords\", foundryName: \"Eye of the Arclords\" },\n { pbName: \"Flip\", foundryName: \"Farabellus Flip\" },\n { pbName: \"Fourberie\", foundryName: \"Fane's Fourberie\" },\n { pbName: \"Ganzi Gaze (Low-Light Vision)\", foundryName: \"Ganzi Gaze\" },\n { pbName: \"Guild Agent Dedication\", foundryName: \"Pathfinder Agent Dedication\" },\n { pbName: \"Harmful Font\", foundryName: \"Divine Font\" },\n { pbName: \"Green Watcher\", foundryName: \"Greenwatcher\" },\n { pbName: \"Green Watch Initiate\", foundryName: \"Greenwatch Initiate\" },\n { pbName: \"Green Watch Veteran\", foundryName: \"Greenwatch Veteran\" },\n { pbName: \"Healing Font\", foundryName: \"Divine Font\" },\n { pbName: \"Heatwave\", foundryName: \"Heat Wave\" },\n { pbName: \"Heavenseeker Dedication\", foundryName: \"Jalmeri Heavenseeker Dedication\" },\n { pbName: \"Heir of the Astrologers\", foundryName: \"Heir of the Saoc\" },\n { pbName: \"High Killer Training\", foundryName: \"Vernai Training\" },\n { pbName: \"Ice-Witch\", foundryName: \"Irriseni Ice-Witch\" },\n { pbName: \"Impeccable Crafter\", foundryName: \"Impeccable Crafting\" },\n { pbName: \"Incredible Beastmaster's Companion\", foundryName: \"Incredible Beastmaster Companion\" },\n { pbName: \"Interrogation\", foundryName: \"Bolera's Interrogation\" },\n { pbName: \"Katana\", foundryName: \"Katana Weapon Familiarity\" },\n { pbName: \"Liberator [Chaotic Good]\", foundryName: \"Liberator\" },\n { pbName: \"Lumberjack Dedication\", foundryName: \"Turpin Rowe Lumberjack Dedication\" },\n { pbName: \"Lumberjack\", foundryName: \"Lumber Consortium Laborer\" },\n { pbName: \"Maestro\", foundryName: \"Maestro Muse\" },\n { pbName: \"Major Lesson I\", foundryName: \"Major Lesson\" },\n { pbName: \"Major Lesson II\", foundryName: \"Major Lesson\" },\n { pbName: \"Major Lesson III\", foundryName: \"Major Lesson\" },\n { pbName: \"Mantis God's Grip\", foundryName: \"Achaekek's Grip\" },\n { pbName: \"Marked for Death\", foundryName: \"Mark for Death\" },\n { pbName: \"Miraculous Spells\", foundryName: \"Miraculous Spell\" },\n { pbName: \"Multifarious\", foundryName: \"Multifarious Muse\" },\n { pbName: \"Mystic\", foundryName: \"Nexian Mystic\" },\n { pbName: \"Paladin [Lawful Good]\", foundryName: \"Paladin\" },\n { pbName: \"Parry\", foundryName: \"Aldori Parry\" },\n { pbName: \"Polymath\", foundryName: \"Polymath Muse\" },\n { pbName: \"Precise Debilitation\", foundryName: \"Precise Debilitations\" },\n { pbName: \"Prodigy\", foundryName: \"Merabite Prodigy\" },\n { pbName: \"Quick Climber\", foundryName: \"Quick Climb\" },\n { pbName: \"Raider\", foundryName: \"Ulfen Raider\" },\n { pbName: \"Recognise Threat\", foundryName: \"Recognize Threat\" },\n { pbName: \"Redeemer [Neutral Good]\", foundryName: \"Redeemer\" },\n { pbName: \"Revivification Protocall\", foundryName: \"Revivification Protocol\" },\n { pbName: \"Riposte\", foundryName: \"Aldori Riposte\" },\n { pbName: \"Rkoan Arts\", foundryName: \"Rokoan Arts\" },\n { pbName: \"Saberteeth\", foundryName: \"Saber Teeth\" },\n { pbName: \"Scholarly Recollection\", foundryName: \"Uzunjati Recollection\" },\n { pbName: \"Scholarly Storytelling\", foundryName: \"Uzunjati Storytelling\" },\n { pbName: \"Shamanic Adherent\", foundryName: \"Rivethun Adherent\" },\n { pbName: \"Shamanic Disciple\", foundryName: \"Rivethun Disciple\" },\n { pbName: \"Shamanic Spiritual Attunement\", foundryName: \"Rivethun Spiritual Attunement\" },\n { pbName: \"Skysage Dedication\", foundryName: \"Oatia Skysage Dedication\" },\n { pbName: \"Secret Lesson\", foundryName: \"Janatimo's Lessons\" },\n { pbName: \"Sentry Dedication\", foundryName: \"Lastwall Sentry Dedication\" },\n { pbName: \"Stab and Snag\", foundryName: \"Stella's Stab and Snag\" },\n { pbName: \"Tenets of Evil\", foundryName: \"The Tenets of Evil\" },\n { pbName: \"Tenets of Good\", foundryName: \"The Tenets of Good\" },\n { pbName: \"Tongue of the Sun and Moon\", foundryName: \"Tongue of Sun and Moon\" },\n { pbName: \"Tribal Bond\", foundryName: \"Quah Bond\" },\n { pbName: \"Tyrant [Lawful Evil]\", foundryName: \"Tyrant\" },\n { pbName: \"Vestigal Wings\", foundryName: \"Vestigial Wings\" },\n { pbName: \"Virtue-Forged Tattooed\", foundryName: \"Virtue-Forged Tattoos\" },\n { pbName: \"Wakizashi\", foundryName: \"Wakizashi Weapon Familiarity\" },\n { pbName: \"Warden\", foundryName: \"Lastwall Warden\" },\n { pbName: \"Warrior\", foundryName: \"Warrior Muse\" },\n { pbName: \"Wary Eye\", foundryName: \"Eye of Ozem\" },\n { pbName: \"Wayfinder Resonance Infiltrator\", foundryName: \"Westyr's Wayfinder Repository\" },\n { pbName: \"Wind God's Fan\", foundryName: \"Wind God’s Fan\" },\n { pbName: \"Wind God’s Fan\", foundryName: \"Wind God's Fan\" },\n // dragons\n { pbName: \"Black\", foundryName: \"Black Dragon\" },\n { pbName: \"Brine\", foundryName: \"Brine Dragon\" },\n { pbName: \"Copper\", foundryName: \"Copper Dragon\" },\n { pbName: \"Blue\", foundryName: \"Blue Dragon\" },\n { pbName: \"Bronze\", foundryName: \"Bronze Dragon\" },\n { pbName: \"Cloud\", foundryName: \"Cloud Dragon\" },\n { pbName: \"Sky\", foundryName: \"Sky Dragon\" },\n { pbName: \"Brass\", foundryName: \"Brass Dragon\" },\n { pbName: \"Underworld\", foundryName: \"Underworld Dragon\" },\n { pbName: \"Crystal\", foundryName: \"Crystal Dragon\" },\n { pbName: \"Forest\", foundryName: \"Forest Dragon\" },\n { pbName: \"Green\", foundryName: \"Green Dragon\" },\n { pbName: \"Sea\", foundryName: \"Sea Dragon\" },\n { pbName: \"Silver\", foundryName: \"Silver Dragon\" },\n { pbName: \"White\", foundryName: \"White Dragon\" },\n { pbName: \"Sovereign\", foundryName: \"Sovereign Dragon\" },\n { pbName: \"Umbral\", foundryName: \"Umbral Dragon\" },\n { pbName: \"Red\", foundryName: \"Red Dragon\" },\n { pbName: \"Gold\", foundryName: \"Gold Dragon\" },\n { pbName: \"Magma\", foundryName: \"Magma Dragon\" },\n // sizes for fleshwarp\n { pbName: \"Medium\", foundryName: \"med\" },\n { pbName: \"Small\", foundryName: \"sm\" },\n // Cleric +\n { pbName: \"Decree of the Warsworn Ecstacy\", foundryName: \"Decree of Warsworn Ecstacy\" },\n { pbName: \"Decree of Warsworn Ecstacy\", foundryName: \"Decree of the Warsworn Ecstacy\" },\n\n // remaster\n { pbName: \"Lightning Reflexes\", foundryName: \"Reflex Expertise\" },\n { pbName: \"Great Fortitude\", foundryName: \"Fortitude Expertise\" },\n { pbName: \"Iron Will\", foundryName: \"Will Expertise\" },\n { pbName: \"Alertness\", foundryName: \"Perception Expertise\" },\n { pbName: \"Incredible Senses\", foundryName: \"Perception Legend\" },\n { pbName: \"Vigilant Senses\", foundryName: \"Perception Mastery\" },\n];\n\nfunction generateDynamicNames(pbName) {\n const result = [];\n // if we have a hardcoded map, don't return here\n if (FEAT_RENAME_STATIC_MAP.some((e) => e.pbName === pbName)) return result;\n for (const reg of POSTFIX_PB_REMOVALS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[1], details: match[2] });\n }\n }\n for (const reg of PREFIX_PB_REMOVALS) {\n const match = pbName.match(reg);\n if (match) {\n const parsed = { pbName, foundryName: match[2], details: match[1] };\n parsed.foundryValue = SKILL_LOOKUP[parsed.foundryName.toLowerCase()];\n result.push(parsed);\n }\n }\n for (const reg of SPLITS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[2], details: match[1] });\n }\n }\n for (const reg of PARENTHESIS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: match[1], details: match[2] });\n }\n }\n for (const reg of SWAPS) {\n const match = pbName.match(reg);\n if (match) {\n result.push({ pbName, foundryName: `${match[2]} (${match[1]})`, details: match[2] });\n }\n }\n return result;\n}\n\nexport function FEAT_RENAME_MAP(pbName = null) {\n const postfixNames = pbName ? generateDynamicNames(pbName) : [];\n return postfixNames.concat(FEAT_RENAME_STATIC_MAP);\n}\n\nconst SHARED_IGNORE_LIST = [\n \"Draconic Rage\", // just handled by effects on Draconic Instinct\n \"Mirror Initiate Benefit\",\n \"Spellstrike Specifics\",\n \"Unarmored\",\n \"Simple Weapon Expertise\",\n \"Spellbook\",\n \"Titan Mauler\", // not needed\n \"Energy Emanation\", // pathbuilder does not pass through a type for this\n \"Imprecise Sense\", // this gets picked up and added by granted features\n \"Imprecise Scent\", // this gets picked up and added by granted features\n \"Sanctification\", // choose on import\n];\n\nconst IGNORED_FEATS_LIST = [\n // ignore skills listed as feats\n \"Acrobatics\",\n \"Athletics\",\n \"Deception\",\n \"Intimidation\",\n \"Nature\",\n \"Performance\",\n \"Society\",\n \"Survival\",\n \"Arcana\",\n \"Crafting\",\n \"Diplomacy\",\n \"Medicine\",\n \"Occultism\",\n \"Religion\",\n \"Stealth\",\n \"Thievery\",\n\n // sizes\n // \"Medium\",\n // \"Small\",\n];\n\nconst IGNORED_SPECIALS_LIST = [\n\n];\n\nexport function IGNORED_FEATS() {\n // const visionFeats = utils.setting(\"ADD_VISION_FEATS\") ? [] : [\"Low-Light Vision\", \"Darkvision\"];\n return IGNORED_FEATS_LIST.concat(SHARED_IGNORE_LIST);\n}\n\nexport function IGNORED_SPECIALS() {\n const visionFeats = utils.setting(\"ADD_VISION_FEATS\") ? [] : [\"Low-Light Vision\", \"Darkvision\"];\n return IGNORED_SPECIALS_LIST.concat(SHARED_IGNORE_LIST, visionFeats);\n}\n\nexport function specialOnlyNameLookup(name) {\n for (const [key, value] of Object.entries(SKILL_LOOKUP)) {\n if (key === name.toLowerCase()) {\n return { pbName: name, foundryName: name, foundryValue: value };\n }\n }\n return undefined;\n}\n\n\nexport function SPECIAL_NAME_ADDITIONS(specials) {\n const newSpecials = [];\n\n for (const special of specials) {\n for (const reg of POSTFIX_PB_SPLIT_AND_KEEP) {\n const match = special.match(reg);\n if (match) {\n newSpecials.push(match[2]);\n }\n }\n }\n return newSpecials;\n}\n\nconst NO_AUTO_CHOICE_LIST = [\n // \"Elemental Evolution\",\n];\n\nexport function NO_AUTO_CHOICE() {\n return NO_AUTO_CHOICE_LIST;\n}\n","export const FEAT_SPELLCASTING = [\n { name: \"Kitsune Spell Familiarity\", showSlotless: false, knownSpells: [\"Daze\", \"Forbidding Ward\", \"Ghost Sound\"], preparePBSpells: true, },\n { name: \"Kitsune Spell Expertise\", showSlotless: false, knownSpells: [\"Confusion\", \"Death Ward\", \"Illusory Scene\"], preparePBSpells: true, },\n { name: \"Kitsune Spell Mysteries\", showSlotless: false, knownSpells: [\"Bane\", \"Illusory Object\", \"Sanctuary\"], preparePBSpells: true, },\n { name: \"Nagaji Spell Familiarity\", showSlotless: false, knownSpells: [\"Daze\", \"Detect Magic\", \"Mage Hand\"], preparePBSpells: true, },\n { name: \"Nagaji Spell Expertise\", showSlotless: false, knownSpells: [\"Blink\", \"Control Water\", \"Subconscious Suggestion\"], preparePBSpells: true, },\n { name: \"Nagaji Spell Mysteries\", showSlotless: false, knownSpells: [\"Charm\", \"Fleet Step\", \"Heal\"], preparePBSpells: true, },\n { name: \"Rat Magic\", showSlotless: false, knownSpells: [], preparePBSpells: true, },\n];\n\nconst REMASTER_NAMES = [\n { pbName: \"Animate Dead\", foundryName: \"Summon Undead\" },\n { pbName: \"Augment Summoning\", foundryName: \"Fortify Summoning\" },\n { pbName: \"Baleful Polymorph\", foundryName: \"Cursed Metamorphosis\" },\n { pbName: \"Barkskin\", foundryName: \"Oaken Resilience\" },\n { pbName: \"Bind Soul\", foundryName: \"Seize Soul\" },\n { pbName: \"Blind Ambition\", foundryName: \"Ignite Ambition\" },\n { pbName: \"Blink\", foundryName: \"Flicker\" },\n { pbName: \"Burning Hands\", foundryName: \"Breathe Fire\" },\n { pbName: \"Calm Emotions\", foundryName: \"Calm\" },\n { pbName: \"Charming Words\", foundryName: \"Charming Push\" },\n { pbName: \"Chill Touch\", foundryName: \"Void Warp\" },\n { pbName: \"Cloudkill\", foundryName: \"Toxic Cloud\" },\n { pbName: \"Color Spray\", foundryName: \"Dizzying Colors\" },\n { pbName: \"Commune with Nature\", foundryName: \"Commune\" },\n { pbName: \"Comprehend Language\", foundryName: \"Translate\" },\n { pbName: \"Continual Flame\", foundryName: \"Everlight\" },\n { pbName: \"Crushing Despair\", foundryName: \"Wave of Despair\" },\n { pbName: \"Dancing Lights\", foundryName: \"Light\" },\n { pbName: \"Dimension Door\", foundryName: \"Translocate\" },\n { pbName: \"Dimensional Anchor\", foundryName: \"Planar Seal\" },\n { pbName: \"Dimensional Lock\", foundryName: \"Planar Tether\" },\n { pbName: \"Discern Location\", foundryName: \"Pinpoint\" },\n { pbName: \"Disrupt Undead\", foundryName: \"Vitality Lash\" },\n { pbName: \"Disrupting Weapons\", foundryName: \"Infuse Vitality\" },\n { pbName: \"Endure Elements\", foundryName: \"Environmental Endurance\" },\n { pbName: \"Entangle\", foundryName: \"Entangling Flora\" },\n { pbName: \"False Life\", foundryName: \"False Vitality\" },\n { pbName: \"Feather Fall\", foundryName: \"Gentle Landing\" },\n { pbName: \"Feeblemind\", foundryName: \"Never Mind\" },\n { pbName: \"Finger of Death\", foundryName: \"Execute\" },\n { pbName: \"Flaming Sphere\", foundryName: \"Floating Flame\" },\n { pbName: \"Flesh To Stone\", foundryName: \"Petrify\" },\n { pbName: \"Freedom of Movement\", foundryName: \"Unfettered Movement\" },\n { pbName: \"Gaseous Form\", foundryName: \"Vapor Form\" },\n { pbName: \"Gentle Repose\", foundryName: \"Peaceful Rest\" },\n { pbName: \"Glibness\", foundryName: \"Honeyed Words\" },\n { pbName: \"Glitterdust\", foundryName: \"Revealing Light\" },\n { pbName: \"Globe of Invulnerability\", foundryName: \"Dispelling Globe\" },\n { pbName: \"Hallucinatory Terrain\", foundryName: \"Mirage\" },\n { pbName: \"Hideous Laughter\", foundryName: \"Laughing Fit\" },\n { pbName: \"Horrid Wilting\", foundryName: \"Desiccate\" },\n { pbName: \"Hypnotic Pattern\", foundryName: \"Hypnotize\" },\n { pbName: \"Inspire Competence\", foundryName: \"Uplifting Overture\" },\n { pbName: \"Inspire Courage\", foundryName: \"Courageous Anthem\" },\n { pbName: \"Inspire Defense\", foundryName: \"Rallying Anthem\" },\n { pbName: \"Inspire Heroics\", foundryName: \"Fortissimo Composition\" },\n { pbName: \"Know Direction\", foundryName: \"Know the Way\" },\n { pbName: \"Legend Lore\", foundryName: \"Collective Memories\" },\n { pbName: \"Longstrider\", foundryName: \"Tailwind\" },\n { pbName: \"Mage Armor\", foundryName: \"Mystic Armor\" },\n { pbName: \"Mage Hand\", foundryName: \"Telekinetic Hand\" },\n { pbName: \"Magic Aura\", foundryName: \"Disguise Magic\" },\n { pbName: \"Magic Fang\", foundryName: \"Runic Body\" },\n { pbName: \"Magic Missile\", foundryName: \"Force Barrage\" },\n { pbName: \"Magic Mouth\", foundryName: \"Embed Message\" },\n { pbName: \"Magic Weapon\", foundryName: \"Runic Weapon\" },\n { pbName: \"Magnificent Mansion\", foundryName: \"Planar Palace\" },\n { pbName: \"Maze\", foundryName: \"Quandary\" },\n { pbName: \"Meld into Stone\", foundryName: \"One with Stone\" },\n { pbName: \"Meteor Swarm\", foundryName: \"Falling Stars\" },\n { pbName: \"Mind Blank\", foundryName: \"Hidden Mind\" },\n { pbName: \"Misdirection\", foundryName: \"Disguise Magic\" },\n { pbName: \"Modify Memory\", foundryName: \"Rewrite Memory\" },\n { pbName: \"Neutralize Poison\", foundryName: \"Cleanse Affliction\" },\n { pbName: \"Nondetection\", foundryName: \"Veil of Privacy\" },\n { pbName: \"Obscuring Mist\", foundryName: \"Mist\" },\n { pbName: \"Pass Without Trace\", foundryName: \"Vanishing Tracks\" },\n { pbName: \"Passwall\", foundryName: \"Magic Passage\" },\n { pbName: \"Phantom Mount\", foundryName: \"Marvelous Mount\" },\n { pbName: \"Planar Binding\", foundryName: \"Planar Servitor\" },\n { pbName: \"Plane Shift\", foundryName: \"Interplanar Teleport\" },\n { pbName: \"Positive Luminance\", foundryName: \"Vital Luminance\" },\n { pbName: \"Private Sanctum\", foundryName: \"Peaceful Bubble\" },\n { pbName: \"Prying Eye\", foundryName: \"Scouting Eye\" },\n { pbName: \"Pulse of The City\", foundryName: \"Pulse of Civilization\" },\n { pbName: \"Purify Food And Drink\", foundryName: \"Cleanse Cuisine\" },\n { pbName: \"Ray of Enfeeblement\", foundryName: \"Enfeeble\" },\n { pbName: \"Remove Curse\", foundryName: \"Cleanse Affliction\" },\n { pbName: \"Remove Disease\", foundryName: \"Cleanse Affliction\" },\n { pbName: \"Remove Fear\", foundryName: \"Clear Mind\" },\n { pbName: \"Remove Paralysis\", foundryName: \"Sure Footing\" },\n { pbName: \"Restore Senses\", foundryName: \"Sound Body\" },\n { pbName: \"Scorching Ray\", foundryName: \"Blazing Bolt\" },\n { pbName: \"Searing Light\", foundryName: \"Holy Light\" },\n { pbName: \"See Invisibility\", foundryName: \"See the Unseen\" },\n { pbName: \"Shadow Walk\", foundryName: \"Umbral Journey\" },\n { pbName: \"Shapechange\", foundryName: \"Metamorphosis\" },\n { pbName: \"Shield Other\", foundryName: \"Share Life\" },\n { pbName: \"Sound Burst\", foundryName: \"Noise Blast\" },\n { pbName: \"Spectral Hand\", foundryName: \"Ghostly Carrier\" },\n { pbName: \"Spider Climb\", foundryName: \"Gecko Grip\" },\n { pbName: \"Splash of Art\", foundryName: \"Creative Splash\" },\n { pbName: \"Stone Tell\", foundryName: \"Speak with Stones\" },\n { pbName: \"Stoneskin\", foundryName: \"Mountain Resilience\" },\n { pbName: \"Tanglefoot\", foundryName: \"Tangle Vine\" },\n { pbName: \"Time Stop\", foundryName: \"Freeze Time\" },\n { pbName: \"Tongues\", foundryName: \"Truespeech\" },\n { pbName: \"Touch of Idiocy\", foundryName: \"Stupefy\" },\n { pbName: \"Tree Shape\", foundryName: \"One with Plants\" },\n { pbName: \"Tree Stride\", foundryName: \"Nature's Pathway\" },\n { pbName: \"Trueseeing\", foundryName: \"Truesight\" },\n { pbName: \"True Strike\", foundryName: \"Sure Strike\" },\n { pbName: \"Unseen Servant\", foundryName: \"Phantasmal Minion\" },\n { pbName: \"Vampiric Touch\", foundryName: \"Vampiric Feast\" },\n { pbName: \"Veil\", foundryName: \"Illusory Disguise\" },\n { pbName: \"Vigilant Eye\", foundryName: \"Rune of Observation\" },\n { pbName: \"Wail of the Banshee\", foundryName: \"Wails of the Damned\" },\n { pbName: \"Wind Walk\", foundryName: \"Migration\" },\n { pbName: \"Zone of Truth\", foundryName: \"Ring of Truth\" },\n];\n\nexport function spellRename(spellName) {\n if (isNewerVersion(game.version, \"5.9.0\") && game.modules.get(\"pf2e-legacy-content\")?.active) return spellName;\n const remasterName = REMASTER_NAMES.find((remaster) => remaster.pbName === spellName);\n if (remasterName) {\n return remasterName.foundryName;\n }\n return spellName;\n}\n","import { EQUIPMENT_RENAME_MAP, RESTRICTED_EQUIPMENT, IGNORED_EQUIPMENT, IGNORED_EQUIPMENT_DISPLAY, GRANTED_ITEMS_LIST } from \"../data/equipment.js\";\nimport { FEAT_RENAME_MAP, IGNORED_FEATS, IGNORED_SPECIALS } from \"../data/features.js\";\nimport { FEAT_SPELLCASTING } from \"../data/spells.js\";\n\n/**\n * This class acts as a wrapper around the renaming data,\n * and the changing of names for foundry\n *\n * When Munching we refer to this as Seasoning the data to taste.\n *\n * It's split out just to make it more manageable\n */\nexport class Seasoning {\n\n // sluggify\n static slug(name) {\n if (!name) return undefined;\n return game.pf2e.system.sluggify(name);\n }\n\n // sluggify with dromedary casing\n static slugD(name) {\n if (!name) return undefined;\n return game.pf2e.system.sluggify(name, { camel: \"dromedary\" });\n }\n\n static FEAT_RENAME_MAP(name) {\n return FEAT_RENAME_MAP(name);\n }\n\n static EQUIPMENT_RENAME_MAP(name) {\n return EQUIPMENT_RENAME_MAP(name);\n }\n\n static getSpellCastingFeatureAdjustment(name) {\n return FEAT_SPELLCASTING.find((f) => f.name === name);\n }\n\n static getFoundryEquipmentName(pbName) {\n return Seasoning.EQUIPMENT_RENAME_MAP(pbName).find((map) => map.pbName == pbName)?.foundryName ?? pbName;\n }\n\n // static getFoundryFeatureName(pbName) {\n // const match = Seasoning.FEAT_RENAME_MAP(pbName).find((map) => map.pbName == pbName);\n // return match ?? { pbName, foundryName: pbName, details: undefined };\n // }\n\n static RESTRICTED_EQUIPMENT() {\n return RESTRICTED_EQUIPMENT;\n }\n\n // specials that are handled by Foundry and shouldn't be added\n static IGNORED_FEATS() {\n return IGNORED_FEATS();\n };\n\n static IGNORED_SPECIALS() {\n return IGNORED_SPECIALS();\n }\n\n static IGNORED_EQUIPMENT() {\n return IGNORED_EQUIPMENT;\n };\n\n static IGNORED_EQUIPMENT_DISPLAY(pbName) {\n return IGNORED_EQUIPMENT_DISPLAY(pbName);\n }\n\n static GRANTED_ITEMS_LIST() {\n return GRANTED_ITEMS_LIST;\n }\n\n static getSizeValue(size) {\n switch (size) {\n case 0:\n return \"tiny\";\n case 1:\n return \"sm\";\n case 3:\n return \"lg\";\n default:\n return \"med\";\n }\n }\n\n static PHYSICAL_ITEM_TYPES = new Set([\n \"armor\",\n \"backpack\",\n \"book\",\n \"consumable\",\n \"equipment\",\n \"treasure\",\n \"weapon\"\n ]);\n\n static isPhysicalItemType(type) {\n return Seasoning.PHYSICAL_ITEM_TYPES.has(type);\n }\n\n static getMaterialGrade(material) {\n if (material.toLowerCase().includes(\"high-grade\")) {\n return \"high\";\n } else if (material.toLowerCase().includes(\"standard-grade\")) {\n return \"standard\";\n }\n return \"low\";\n }\n\n static getFoundryFeatLocation(pathbuilderFeatType, pathbuilderFeatLevel) {\n if (pathbuilderFeatType === \"Ancestry Feat\") {\n return `ancestry-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"Class Feat\") {\n return `class-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"Skill Feat\") {\n return `skill-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"General Feat\") {\n return `general-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"Background Feat\") {\n return `skill-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"Archetype Feat\") {\n return `archetype-${pathbuilderFeatLevel}`;\n } else if (pathbuilderFeatType === \"Kineticist Feat\") { // return as null for now\n return null;\n } else {\n return null;\n }\n }\n\n static getClassAdjustedSpecialNameLowerCase(name, className) {\n return `${name} (${className})`.toLowerCase();\n }\n\n static getDualClassAdjustedSpecialNameLowerCase(name, dualClassName) {\n return `${name} (${dualClassName})`.toLowerCase();\n }\n\n static getAncestryAdjustedSpecialNameLowerCase(name, ancestryName) {\n return `${name} (${ancestryName})`.toLowerCase();\n }\n\n static getHeritageAdjustedSpecialNameLowerCase(name, heritageName) {\n return `${name} (${heritageName})`.toLowerCase();\n }\n\n static getChampionType(alignment) {\n if (alignment == \"LG\") return \"Paladin\";\n else if (alignment == \"CG\") return \"Liberator\";\n else if (alignment == \"NG\") return \"Redeemer\";\n else if (alignment == \"LE\") return \"Tyrant\";\n else if (alignment == \"CE\") return \"Antipaladin\";\n else if (alignment == \"NE\") return \"Desecrator\";\n return \"Unknown\";\n }\n\n\n}\n","/* eslint-disable no-await-in-loop */\nimport CONSTANTS from \"../constants.js\";\nimport logger from \"../logger.js\";\nimport utils from \"../utils.js\";\nimport { Seasoning } from \"./Seasoning.js\";\n\nexport class CompendiumMatcher {\n\n constructor({ type, mappings = null, indexFields = [\"name\", \"type\", \"system.slug\"] } = {}) {\n this.type = type;\n this.indexFields = indexFields;\n this.packs = {};\n\n const packMappings = mappings !== null\n ? mappings\n : utils.setting(\"USE_CUSTOM_COMPENDIUM_MAPPINGS\")\n ? utils.setting(\"CUSTOM_COMPENDIUM_MAPPINGS\")\n : CONSTANTS.CORE_COMPENDIUM_MAPPINGS;\n packMappings[type].forEach((name) => {\n const compendium = game.packs.get(name);\n if (compendium) {\n this.packs[name] = compendium;\n }\n });\n\n this.indexes = {\n\n };\n\n }\n\n async loadCompendiums() {\n for (const [name, compendium] of Object.entries(this.packs)) {\n this.indexes[name] = await compendium.getIndex({ fields: this.indexFields });\n }\n }\n\n\n getFoundryFeatureName(pbName) {\n const match = this.FEAT_RENAME_MAP(pbName).find((map) => map.pbName == pbName);\n return match ?? { pbName, foundryName: pbName, details: undefined };\n }\n\n getNameMatch(pbName, foundryName) {\n for (const [packName, index] of Object.entries(this.indexes)) {\n const indexMatch = index.find((i) => i.name === foundryName)\n ?? index.find((i) => i.name === pbName);\n\n if (indexMatch) {\n logger.debug(`Found name only compendium document for ${pbName} (${foundryName}) in ${packName} with id ${indexMatch._id}`);\n return { i: indexMatch, pack: this.packs[packName] };\n }\n }\n return undefined;\n }\n\n getSlugMatch(pbName, foundryName) {\n for (const [packName, index] of Object.entries(this.indexes)) {\n logger.debug(`Checking for compendium documents for ${pbName} (${foundryName}) in ${packName}`, {\n pbName,\n foundryName,\n packName,\n // index,\n // foundrySlug: Seasoning.slug(foundryName),\n // pbSlug: Seasoning.slug(pbName),\n // foundryMatch: index.find((i) => (i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(foundryName)),\n // pbMatch: index.find((i) => (i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(pbName)),\n // pbSlugMatch: (null ?? Seasoning.slug(\"Phase Bolt (Psychic)\")) === Seasoning.slug(\"Phase Bolt (Psychic)\"),\n });\n const indexMatch = index.find((i) => (i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(foundryName))\n ?? index.find((i) => (i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(pbName));\n\n if (indexMatch) {\n logger.debug(`Found slug based compendium document for ${pbName} (${foundryName}) in ${packName} with id ${indexMatch._id}`);\n return { i: indexMatch, pack: this.packs[packName] };\n }\n }\n return undefined;\n }\n\n getMatch(pbName, foundryName, forceName = false) {\n\n if (forceName) {\n const nameOnlyMatch = this.getNameMatch(pbName, foundryName);\n if (nameOnlyMatch) return nameOnlyMatch;\n }\n\n const slugMatch = this.getSlugMatch(pbName, foundryName);\n if (slugMatch) return slugMatch;\n\n return undefined;\n }\n\n static checkForFilters(i, filters) {\n for (const [key, value] of Object.entries(filters)) {\n if (getProperty(i, key) !== value) {\n return false;\n }\n }\n return true;\n }\n\n getNameMatchWithFilter(pbName, foundryName, filters = {}) {\n for (const [packName, index] of Object.entries(this.indexes)) {\n logger.debug(`Checking for compendium documents for ${pbName} (${foundryName}) in ${packName}`, {\n pbName,\n foundryName,\n filters,\n packName,\n // index,\n });\n const indexMatch = index.find((i) =>\n ((i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(foundryName))\n && CompendiumMatcher.checkForFilters(i, filters))\n ?? index.find((i) =>\n ((i.system.slug ?? Seasoning.slug(i.name)) === Seasoning.slug(pbName)\n && CompendiumMatcher.checkForFilters(i, filters))\n );\n\n if (indexMatch) {\n logger.debug(`Found compendium document for ${pbName} (${foundryName}) in ${packName} with id ${indexMatch._id}`);\n return { i: indexMatch, pack: this.packs[packName] };\n }\n }\n\n return undefined;\n }\n\n\n}\n","import CONSTANTS from \"../constants.js\";\nimport utils from \"../utils.js\";\n\nexport class CompendiumSelector extends FormApplication {\n constructor() {\n super();\n this.lookups = utils.setting(\"CUSTOM_COMPENDIUM_MAPPINGS\");\n this.packs = game.packs\n .filter((p) => p.metadata.type === \"Item\")\n .map((p) => {\n return { id: p.metadata.id, label: `${p.metadata.label} (${p.metadata.packageName})` };\n });\n this.currentType = null;\n this.useCustomCompendiums = utils.setting(\"USE_CUSTOM_COMPENDIUM_MAPPINGS\");\n }\n\n static get defaultOptions() {\n return mergeObject(super.defaultOptions, {\n id: \"pathmuncher-compendium-selector\",\n template: `${CONSTANTS.PATH}/templates/compendium-selector.hbs`,\n width: 722,\n height: 275,\n title: game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.CompendiumSelector.Title`),\n resizable: true,\n classes: ['pathmuncher-compendium-selector'],\n });\n }\n\n getData() {\n const lookups = [];\n for (const key in this.lookups) {\n lookups.push({\n key,\n label: game.i18n.localize(`${CONSTANTS.FLAG_NAME}.CompendiumGroups.${key}`),\n });\n }\n return {\n lookups,\n title: this.options.title,\n sourceItems: [],\n compendiumItems: [],\n useCustomCompendiums: this.useCustomCompendiums,\n };\n }\n\n async reset() {\n const defaults = CONSTANTS.GET_DEFAULT_SETTINGS();\n this.lookups = defaults[CONSTANTS.SETTINGS.CUSTOM_COMPENDIUM_MAPPINGS].default;\n await utils.updateSetting(\"CUSTOM_COMPENDIUM_MAPPINGS\", this.lookups);\n this.currentType = null;\n this.render(true);\n }\n\n async enableCustomCompendiums() {\n this.useCustomCompendiums = !this.useCustomCompendiums;\n await utils.updateSetting(\"USE_CUSTOM_COMPENDIUM_MAPPINGS\", this.useCustomCompendiums);\n }\n\n filterList(event) {\n const compendiumType = event.srcElement.value;\n const sourceList = document.getElementById(\"sourceList\");\n const compendiumList = document.getElementById(\"compendiumList\");\n\n const sourceOptions = this.packs.filter((p) => !this.lookups[compendiumType].includes(p.id));\n const compendiumOptions = this.packs.filter((p) => this.lookups[compendiumType].includes(p.id));\n\n sourceList.innerHTML = \"\";\n compendiumList.innerHTML = \"\";\n\n sourceOptions.forEach((option) => {\n const sourceListItem = document.createElement(\"option\");\n sourceListItem.value = option.id;\n sourceListItem.appendChild(document.createTextNode(option.label));\n sourceList.appendChild(sourceListItem);\n });\n\n compendiumOptions.forEach((option) => {\n const compendiumListItem = document.createElement(\"option\");\n compendiumListItem.value = option.id;\n compendiumListItem.appendChild(document.createTextNode(option.label));\n compendiumList.appendChild(compendiumListItem);\n });\n\n this.currentType = compendiumType;\n }\n\n async updateCompendiums() {\n const compendiumList = document.getElementById(\"compendiumList\");\n const compendiumOptions = Array.from(compendiumList.options);\n const compendiumIds = compendiumOptions.map((option) => {\n return option.value;\n });\n\n this.lookups[this.currentType] = compendiumIds;\n\n utils.updateSetting(\"CUSTOM_COMPENDIUM_MAPPINGS\", this.lookups);\n }\n\n async addCompendium() {\n const sourceList = document.getElementById(\"sourceList\");\n const compendiumList = document.getElementById(\"compendiumList\");\n const selectedOptions = Array.from(sourceList.selectedOptions);\n\n selectedOptions.forEach((option) => {\n compendiumList.appendChild(option);\n });\n\n await this.updateCompendiums();\n }\n\n async removeCompendium() {\n const sourceList = document.getElementById(\"sourceList\");\n const compendiumList = document.getElementById(\"compendiumList\");\n const selectedOptions = Array.from(compendiumList.selectedOptions);\n\n selectedOptions.forEach((option) => {\n sourceList.appendChild(option);\n });\n await this.updateCompendiums();\n }\n\n async moveUp() {\n const compendiumList = document.getElementById(\"compendiumList\");\n const selectedOption = compendiumList.selectedOptions[0];\n\n if (selectedOption && selectedOption.previousElementSibling) {\n compendiumList.insertBefore(selectedOption, selectedOption.previousElementSibling);\n }\n await this.updateCompendiums();\n }\n\n async moveDown() {\n const compendiumList = document.getElementById(\"compendiumList\");\n const selectedOption = compendiumList.selectedOptions[0];\n\n if (selectedOption && selectedOption.nextElementSibling) {\n compendiumList.insertBefore(selectedOption.nextElementSibling, selectedOption);\n }\n await this.updateCompendiums();\n }\n\n activateListeners(html) {\n super.activateListeners(html);\n\n document.getElementById(\"addButton\").addEventListener(\"click\", this.addCompendium.bind(this));\n document.getElementById(\"removeButton\").addEventListener(\"click\", this.removeCompendium.bind(this));\n document.getElementById(\"upButton\").addEventListener(\"click\", this.moveUp.bind(this));\n document.getElementById(\"downButton\").addEventListener(\"click\", this.moveDown.bind(this));\n document.getElementById(\"compSelector\").addEventListener(\"change\", this.filterList.bind(this));\n document.getElementById(\"resetButton\").addEventListener(\"click\", this.reset.bind(this));\n document.getElementById(\"enableCustomCompendiums\").addEventListener(\"change\", this.enableCustomCompendiums.bind(this));\n }\n}\n","/* eslint-disable no-await-in-loop */\n/* eslint-disable no-continue */\nimport CONSTANTS from \"../constants.js\";\nimport { SPECIAL_NAME_ADDITIONS, NO_AUTO_CHOICE, specialOnlyNameLookup } from \"../data/features.js\";\nimport { spellRename } from \"../data/spells.js\";\nimport logger from \"../logger.js\";\nimport utils from \"../utils.js\";\nimport { CompendiumMatcher } from \"./CompendiumMatcher.js\";\nimport { Seasoning } from \"./Seasoning.js\";\n\nexport class Pathmuncher {\n FEAT_RENAME_MAP(name) {\n const dynamicItems = [\n { pbName: \"Shining Oath\", foundryName: `Shining Oath (${Seasoning.getChampionType(this.source.alignment)})` },\n { pbName: \"Counterspell\", foundryName: `Counterspell (${utils.capitalize(this.getClassSpellCastingType() ?? \"\")})` },\n { pbName: \"Counterspell\", foundryName: `Counterspell (${utils.capitalize(this.getClassSpellCastingType(true) ?? \"\")})` },\n { pbName: \"Cantrip Expansion\", foundryName: `Cantrip Expansion (${this.source.class})` },\n { pbName: \"Cantrip Expansion\", foundryName: `Cantrip Expansion (${this.source.dualClass})` },\n { pbName: \"Cantrip Expansion\", foundryName: `Cantrip Expansion (${utils.capitalize(this.getClassSpellCastingType() ?? \"\")} Caster)` },\n { pbName: \"Cantrip Expansion\", foundryName: `Cantrip Expansion (${utils.capitalize(this.getClassSpellCastingType(true) ?? \"\")} Caster)` },\n ];\n return Seasoning.FEAT_RENAME_MAP(name).concat(dynamicItems);\n }\n\n getFoundryFeatureName(pbName, isSpecial = false) {\n if (isSpecial) {\n const specialMatch = specialOnlyNameLookup(pbName);\n if (specialMatch) return specialMatch;\n }\n const match = this.FEAT_RENAME_MAP(pbName).find((map) => map.pbName == pbName);\n return match ?? { pbName, foundryName: pbName, details: undefined };\n }\n\n constructor(actor, { addFeats = true, addEquipment = true, addSpells = true, adjustBlendedSlots = true,\n addMoney = true, addLores = true, addWeapons = true, addArmor = true, addTreasure = true, addDeity = true,\n addName = true, addClass = true, addBackground = true, addHeritage = true, addAncestry = true,\n statusCallback = null } = {}\n ) {\n this.devMode = game.modules.get(\"pathmuncher\").version === \"999.0.0\";\n this.actor = actor;\n // note not all these options do anything yet!\n this.options = {\n addTreasure,\n addMoney,\n addFeats,\n addSpells,\n adjustBlendedSlots,\n addEquipment,\n addLores,\n addWeapons,\n addArmor,\n addDeity,\n addName,\n addClass,\n addBackground,\n addHeritage,\n addAncestry,\n };\n this.source = null;\n this.parsed = {\n specials: [],\n feats: [],\n equipment: [],\n armor: [],\n weapons: [],\n };\n this.usedLocations = new Set();\n this.usedLocationsAlternateRules = new Set();\n this.autoAddedFeatureIds = new Set();\n this.autoAddedFeatureItems = {};\n this.promptRules = {};\n this.allFeatureRules = {};\n this.autoAddedFeatureRules = {};\n this.grantItemLookUp = {};\n this.autoFeats = [];\n this.keyAbility = null;\n this.boosts = {\n custom: false,\n class: {},\n background: {},\n ancestry: {},\n };\n this.size = \"med\";\n this.result = {\n character: {\n _id: this.actor.id,\n prototypeToken: {},\n },\n class: [],\n deity: [],\n heritage: [],\n ancestry: [],\n background: [],\n casters: [],\n spells: [],\n feats: [],\n weapons: [],\n armor: [],\n equipment: [],\n lores: [],\n money: [],\n treasure: [],\n adventurersPack: {\n item: null,\n contents: [\n { slug: \"bedroll\", qty: 1 },\n { slug: \"chalk\", qty: 10 },\n { slug: \"flint-and-steel\", qty: 1 },\n { slug: \"rope\", qty: 1 },\n { slug: \"rations\", qty: 14 },\n { slug: \"torch\", qty: 5 },\n { slug: \"waterskin\", qty: 1 },\n ],\n },\n focusPool: 0,\n };\n this.check = {};\n this.bad = [];\n this.statusCallback = statusCallback;\n this.compendiumMatchers = {};\n const compendiumMappings = utils.setting(\"USE_CUSTOM_COMPENDIUM_MAPPINGS\")\n ? utils.setting(\"CUSTOM_COMPENDIUM_MAPPINGS\")\n : CONSTANTS.CORE_COMPENDIUM_MAPPINGS;\n for (const type of Object.keys(compendiumMappings)) {\n this.compendiumMatchers[type] = new CompendiumMatcher({ type });\n }\n }\n\n async #loadCompendiumMatchers() {\n for (const matcher of Object.values(this.compendiumMatchers)) {\n await matcher.loadCompendiums();\n }\n }\n\n #statusUpdate(total, count, type, prefixLabel) {\n if (this.statusCallback) this.statusCallback(total, count, type, prefixLabel);\n }\n\n async fetchPathbuilder(pathbuilderId) {\n if (!pathbuilderId) {\n const flags = utils.getFlags(this.actor);\n pathbuilderId = flags?.pathbuilderId;\n }\n if (pathbuilderId) {\n const jsonData = await foundry.utils.fetchJsonWithTimeout(\n `https://www.pathbuilder2e.com/json.php?id=${pathbuilderId}`\n );\n if (jsonData.success) {\n this.source = jsonData.build;\n } else {\n ui.notifications.warn(\n game.i18n.format(`${CONSTANTS.FLAG_NAME}.Dialogs.Pathmuncher.FetchFailed`, { pathbuilderId })\n );\n }\n } else {\n ui.notifications.error(game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.Pathmuncher.NoId`));\n }\n }\n\n #generateFoundryFeatLocation(document, feature) {\n if (feature.type && feature.level) {\n // const freeArchetypeVariant = game.settings.get(\"pf2e\", \"freeArchetypeVariant\");\n const location = Seasoning.getFoundryFeatLocation(feature.type, feature.level);\n if (location && !this.usedLocations.has(location)) {\n document.system.location = location;\n this.usedLocations.add(location);\n } else if (location && this.usedLocations.has(location)) {\n logger.debug(\"Variant feat location\", { ancestryParagonVariant: utils.allowAncestryParagon(), location, feature });\n // eslint-disable-next-line max-depth\n if (utils.allowAncestryParagon() && feature.type === \"Ancestry Feat\") {\n document.system.location = \"ancestry-bonus\";\n this.usedLocationsAlternateRules.add(location);\n } else if (utils.allowDualClasses() && feature.type === \"Class Feat\") {\n document.system.location = `dualclass-${feature.level}`;\n this.usedLocationsAlternateRules.add(location);\n }\n }\n }\n }\n\n #processSpecialData(name) {\n if (name.includes(\"Domain: \")) {\n const domainName = name.split(\" \")[1];\n this.parsed.feats.push({ name: \"Deity's Domain\", extra: domainName });\n return true;\n } else {\n return false;\n }\n }\n\n #getContainerData(key) {\n return {\n id: key,\n containerName: this.source.equipmentContainers[key].containerName,\n bagOfHolding: this.source.equipmentContainers[key].bagOfHolding,\n backpack: this.source.equipmentContainers[key].backpack,\n };\n }\n\n #nameMapSourceEquipment(e) {\n const name = Seasoning.getFoundryEquipmentName(e[0]);\n const containerKey = Object.keys(this.source.equipmentContainers)\n .find((key) => this.source.equipmentContainers[key].containerName === name);\n\n const container = containerKey ? this.#getContainerData(containerKey) : null;\n const foundryId = foundry.utils.randomID();\n\n if (container) {\n this.source.equipmentContainers[containerKey].foundryId = foundryId;\n }\n\n const item = {\n foundryName: name,\n pbName: e[0],\n originalName: e[0],\n qty: e[1],\n added: false,\n addedId: null,\n addedAutoId: null,\n inContainer: e[2] !== \"Invested\" ? e[2] : null,\n container,\n foundryId,\n invested: e[2] === \"Invested\",\n sourceType: \"equipment\",\n };\n this.parsed.equipment.push(item);\n }\n\n #nameMapSourceEquipmentAddHandwraps(e) {\n const name = Seasoning.getFoundryEquipmentName(e[0]);\n const potencyMatch = e[0].match(/\\(\\+(\\d)[\\s)]/i);\n const potency = potencyMatch ? parseInt(potencyMatch[1]) : 0;\n const strikingMatch = e[0].match(/\\d( \\w*)? (Striking)/i);\n const striking = strikingMatch\n ? Seasoning.slugD(`${(strikingMatch[1] ?? \"\").trim()}${(strikingMatch[2] ?? \"\").trim()}`) // `${(strikingMatch[2] ?? \"\").toLowerCase().trim()}${(strikingMatch[1] ?? \"\").trim()}`.trim()\n : \"\";\n const mockE = {\n name: e[0],\n qty: 1,\n prof: \"unarmed\",\n pot: Number.isInteger(potency) ? potency : 0,\n str: striking,\n mat: null,\n display: e[0],\n runes: [],\n damageType: \"B\",\n increasedDice: false\n };\n const weapon = mergeObject({\n foundryName: name,\n pbName: mockE.name,\n originalName: mockE.name,\n added: false,\n addedId: null,\n addedAutoId: null,\n sourceType: \"weapons\",\n }, mockE);\n this.parsed.weapons.push(weapon);\n }\n\n #nameMap() {\n let iRank = 0;\n let featRank = 0;\n logger.debug(\"Starting Equipment Rename\");\n this.source.equipment\n .filter((e) => e[0] && e[0] !== \"undefined\")\n .forEach((e) => {\n if (e[0].startsWith(\"Handwraps of Mighty Blows\")) {\n this.#nameMapSourceEquipmentAddHandwraps(e);\n } else {\n this.#nameMapSourceEquipment(e);\n }\n });\n this.source.armor\n .filter((e) => e && e !== \"undefined\")\n .forEach((e) => {\n const name = Seasoning.getFoundryEquipmentName(e.name);\n const item = mergeObject({\n foundryName: name,\n pbName: e.name,\n originalName: e.name,\n added: false,\n addedId: null,\n addedAutoId: null,\n sourceType: \"armor\",\n }, e);\n this.parsed.armor.push(item);\n // work around for now\n if (e.name.startsWith(\"Inventor \")) {\n this.parsed.feats.push({\n name,\n extra: \"\",\n added: false,\n addedId: null,\n addedAutoId: null,\n type: \"Awarded Feat\",\n level: 1,\n originalName: e.name,\n rank: 0,\n sourceType: \"armor\",\n featChoiceRef: null,\n hasChildren: null,\n isChild: null,\n isStandard: null,\n parentFeatChoiceRef: null,\n });\n featRank++;\n }\n });\n this.source.weapons\n .filter((e) => e && e !== \"undefined\")\n .forEach((e) => {\n const name = Seasoning.getFoundryEquipmentName(e.name);\n const item = mergeObject({\n foundryName: name,\n pbName: e.name,\n originalName: e.name,\n added: false,\n addedId: null,\n addedAutoId: null,\n sourceType: \"weapons\",\n }, e);\n this.parsed.weapons.push(item);\n });\n logger.debug(\"Finished Equipment Rename\");\n\n logger.debug(\"Starting Special Rename\");\n [].concat(this.source.specials, SPECIAL_NAME_ADDITIONS(this.source.specials))\n .filter((special) =>\n special\n && special !== \"undefined\"\n && special !== \"Not Selected\"\n && special !== this.source.heritage\n )\n .forEach((special) => {\n const match = this.getFoundryFeatureName(special); // , true);\n if (!this.#processSpecialData(match.foundryName) && !Seasoning.IGNORED_SPECIALS().includes(match.foundryName)) {\n this.parsed.specials.push({ name: match.foundryName, foundryName: match.foundryName, foundryValue: match.foundryValue, originalName: special, added: false, addedId: null, addedAutoId: null, rank: iRank, sourceType: \"specials\" });\n iRank++;\n }\n });\n logger.debug(\"Finished Special Rename\");\n\n\n logger.debug(\"Starting Feat Rename\");\n this.source.feats\n .filter((feat) =>\n feat[0]\n && feat[0] !== \"undefined\"\n && feat[0] !== \"Not Selected\"\n // && feat[0] !== this.source.heritage\n )\n .forEach((feat) => {\n const name = this.getFoundryFeatureName(feat[0]).foundryName;\n const data = {\n name,\n extra: feat[1],\n added: feat[0] === this.source.heritage,\n addedId: null,\n addedAutoId: null,\n type: feat[2],\n level: feat[3],\n originalName: feat[0],\n rank: featRank,\n sourceType: \"feats\",\n };\n if (feat.length >= 7) {\n data.featChoiceRef = feat[4];\n data.hasChildren = feat[5] === \"parentChoice\";\n data.isChild = feat[5] === \"childChoice\";\n data.isStandard = feat[5] === \"standardChoice\";\n data.parentFeatChoiceRef = feat[6];\n const parentFeatMatch = this.source.feats.find((f) =>\n feat[5] === \"childChoice\"\n && (data.featChoiceRef.toLowerCase().startsWith(f[0].toLowerCase())\n || (data.parentFeatChoiceRef\n && data.featChoiceRef.replace(data.parentFeatChoiceRef, \"\").trim().toLowerCase().startsWith(f[0].toLowerCase()))\n )\n );\n data.nameHint = parentFeatMatch?.[0];\n } else {\n // probably an awarded feat\n data.featChoiceRef = null;\n data.hasChildren = null;\n data.isChild = null;\n data.isStandard = null;\n data.parentFeatChoiceRef = null;\n }\n this.parsed.feats.push(data);\n featRank++;\n });\n logger.debug(\"Finished Feat Rename\");\n logger.debug(\"Name remapping results\", {\n parsed: this.parsed,\n });\n }\n\n #fixUps() {\n if (this.source.ancestry === \"Dwarf\" && !this.parsed.feats.some((f) => f.name === \"Clan Pistol\")) {\n const clanDagger = {\n name: \"Clan Dagger\",\n originalName: \"Clan Dagger\",\n added: false,\n addedId: null,\n addedAutoId: null,\n isChoice: true,\n rank: 0,\n sourceType: \"specials\",\n };\n this.parsed.specials.push(clanDagger);\n }\n\n const match = this.source.background.match(/(Magical Experiment) \\((.*)\\)$/);\n if (match) {\n this.parsed.specials.push({\n name: match[2],\n originalName: `${this.source.background}`,\n added: false,\n addedId: null,\n addedAutoId: null,\n isChoice: true,\n rank: 0,\n sourceType: \"specials\",\n });\n this.source.background = match[1];\n }\n }\n\n async #prepare() {\n await this.#loadCompendiumMatchers();\n this.#nameMap();\n this.#fixUps();\n }\n\n async #processSenses() {\n const senses = [];\n this.source.specials.forEach((special) => {\n if (special === \"Low-Light Vision\") {\n senses.push({ type: \"lowLightVision\" });\n } else if (special === \"Darkvision\") {\n senses.push({ type: \"darkvision\" });\n } else if (special === \"Scent\") {\n senses.push({ type: \"scent\" });\n }\n });\n setProperty(this.result.character, \"system.traits.senses\", senses);\n }\n\n // eslint-disable-next-line no-unused-vars\n async #addDualClass(klass) {\n if (!utils.allowDualClasses()) {\n if (this.source.dualClass && this.source.dualClass !== \"\") {\n logger.warn(`Imported character is dual class. Pathmuncher does not support dual class characters, please check the system macros`, {\n class: this.source.class,\n dualClass: this.source.dualClass,\n });\n ui.notifications.warn(`Imported character is dual class. Pathmuncher does not support dual class characters, please check the system macros`);\n }\n return;\n }\n if (!this.source.dualClass || this.source.dualClass === \"\") {\n logger.warn(`Imported character not dual class but system is configured for dual class`, {\n class: this.source.class,\n });\n ui.notifications.warn(`Imported character not dual class but system is configured for dual class`);\n return;\n }\n logger.info(\"Not processing dual class\");\n\n // // find the dual class\n // const foundryName = this.getFoundryFeatureName(this.source.dualClass).foundryName;\n // const indexMatch = this.compendiumMatchers[\"classes\"].getMatch(this.source.dualClass, foundryName);\n\n // if (!indexMatch) return;\n // const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n // const dualClass = doc.toObject();\n\n // logger.debug(`Dual Class ${dualClass.name} found, squashing things together.`);\n\n // klass.name = `${klass.name} - ${dualClass.name}`;\n // const ruleEntry = {\n // domain: \"all\",\n // key: \"RollOption\",\n // option: `class:${dualClass.system.slug}`,\n // };\n\n // // Attacks\n // [\"advanced\", \"martial\", \"simple\", \"unarmed\"].forEach((key) => {\n // if (dualClass.system.attacks[key] > klass.system.attacks[key]) {\n // klass.system.attacks[key] = dualClass.system.attacks[key];\n // }\n // });\n // if (klass.system.attacks.martial <= dualClass.system.attacks.other.rank) {\n // if (dualClass.system.attacks.other.rank === klass.system.attacks.other.rank) {\n // let mashed = `${klass.system.attacks.other.name}, ${dualClass.system.attacks.other.name}`;\n // mashed = mashed.replace(\"and \", \"\");\n // klass.system.attacks.other.name = [...new Set(mashed.split(\",\"))].join(\",\");\n // }\n // if (dualClass.system.attacks.other.rank > klass.system.attacks.other.rank) {\n // klass.system.attacks.other.name = dualClass.system.attacks.other.name;\n // klass.system.attacks.other.rank = dualClass.system.attacks.other.rank;\n // }\n // }\n // if (\n // klass.system.attacks.martial >= dualClass.system.attacks.other.rank\n // && klass.system.attacks.martial >= klass.system.attacks.other.rank\n // ) {\n // klass.system.attacks.other.rank = 0;\n // klass.system.attacks.other.name = \"\";\n // }\n\n // // Class DC\n // if (dualClass.system.classDC > klass.system.classDC) {\n // klass.system.classDC = dualClass.system.classDC;\n // }\n\n // // Defenses\n // [\"heavy\", \"light\", \"medium\", \"unarmored\"].forEach((key) => {\n // if (dualClass.system.defenses[key] > klass.system.defenses[key]) {\n // klass.system.defenses[key] = dualClass.system.defenses[key];\n // }\n // });\n\n // // Description\n // klass.system.description.value = `${klass.system.description.value} ${dualClass.system.description.value}`;\n\n // // HP\n // if (dualClass.system.hp > klass.system.hp) {\n // klass.system.hp = dualClass.system.hp;\n // }\n\n // // Items\n // Object.entries(dualClass.system.items).forEach((i) => {\n // if (Object.values(klass.system.items).some((x) => x.uuid === i[1].uuid && x.level > i[1].level)) {\n // Object.values(klass.system.items).find((x) => x.uuid === i[1].uuid).level = i[1].level;\n // } else if (!Object.values(klass.system.items).some((x) => x.uuid === i[1].uuid && x.level <= i[1].level)) {\n // klass.system.items[i[0]] = i[1];\n // }\n // });\n\n // // Key Ability\n // dualClass.system.keyAbility.value.forEach((v) => {\n // if (!klass.system.keyAbility.value.includes(v)) {\n // klass.system.keyAbility.value.push(v);\n // }\n // });\n\n // // Perception\n // if (dualClass.system.perception > klass.system.perception) klass.system.perception = dualClass.system.perception;\n\n // // Rules\n // klass.system.rules.push(ruleEntry);\n // dualClass.system.rules.forEach((r) => {\n // if (!klass.system.rules.includes(r)) {\n // klass.system.rules.push(r);\n // }\n // });\n // klass.system.rules.forEach((r, i) => {\n // if (r.path !== undefined) {\n // const check = r.path.split(\".\");\n // if (\n // check.includes(\"data\")\n // && check.includes(\"martial\")\n // && check.includes(\"rank\")\n // && klass.system.attacks.martial >= r.value\n // ) {\n // klass.system.rules.splice(i, 1);\n // }\n // }\n // });\n\n // // Saving Throws\n // [\"fortitude\", \"reflex\", \"will\"].forEach((key) => {\n // if (dualClass.system.savingThrows[key] > klass.system.savingThrows[key]) {\n // klass.system.savingThrows[key] = dualClass.system.savingThrows[key];\n // }\n // });\n\n // // Skill Feat Levels\n // dualClass.system.skillFeatLevels.value.forEach((v) => {\n // klass.system.skillFeatLevels.value.push(v);\n // });\n // klass.system.skillFeatLevels.value = [...new Set(klass.system.skillFeatLevels.value)].sort((a, b) => {\n // return a - b;\n // });\n\n // // Skill Increase Levels\n // dualClass.system.skillIncreaseLevels.value.forEach((v) => {\n // klass.system.skillIncreaseLevels.value.push(v);\n // });\n // klass.system.skillIncreaseLevels.value = [...new Set(klass.system.skillIncreaseLevels.value)].sort((a, b) => {\n // return a - b;\n // });\n\n // // Trained Skills\n // if (dualClass.system.trainedSkills.additional > klass.system.trainedSkills.additional) {\n // klass.system.trainedSkills.additional = dualClass.system.trainedSkills.additional;\n // }\n // dualClass.system.trainedSkills.value.forEach((v) => {\n // if (!klass.system.trainedSkills.value.includes(v)) {\n // klass.system.trainedSkills.value.push(v);\n // }\n // });\n\n // this.result.dualClass = dualClass;\n }\n\n // eslint-disable-next-line class-methods-use-this\n async #processGenericCompendiumLookup(type, name, target) {\n logger.debug(`Checking for compendium documents for ${name} (${target}) in compendiums for ${type}`);\n const foundryName = this.getFoundryFeatureName(name).foundryName;\n const indexMatch = this.compendiumMatchers[type].getMatch(name, foundryName);\n\n if (indexMatch) {\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const itemData = doc.toObject();\n if (name.includes(\"(\")) {\n const extra = name.split(\")\")[0].split(\"(\").pop();\n this.parsed.specials.push({ name: doc.name, originalName: name, added: true, extra, rank: 99 });\n }\n if (target === \"class\") {\n itemData.system.keyAbility.selected = this.keyAbility;\n await this.#addDualClass(itemData);\n }\n itemData._id = foundry.utils.randomID();\n // this.#generateGrantItemData(itemData);\n this.result[target].push(itemData);\n await this.#addGrantedItems(itemData, { applyFeatLocation: target !== \"class\" });\n return true;\n } else {\n this.bad.push({ pbName: name, type: target, details: { name } });\n return false;\n }\n }\n\n // for grants, e.g. ont he champion \"Deity and Cause\" where there are choices.\n // how do we determine and match these? should we?\n // \"pf2e\": {\n // \"itemGrants\": {\n // \"adanye\": {\n // \"id\": \"4GHcp3iaREfj2ZgN\",\n // \"onDelete\": \"detach\"\n // },\n // \"paladin\": {\n // \"id\": \"HGWkTEatliHgDaEu\",\n // \"onDelete\": \"detach\"\n // }\n // }\n // }\n\n // \"Paladin\" (granted by deity and casue)\n // \"pf2e\": {\n // \"grantedBy\": {\n // \"id\": \"xnrkrJa2YE1UOAVy\",\n // \"onDelete\": \"cascade\"\n // },\n // \"itemGrants\": {\n // \"retributiveStrike\": {\n // \"id\": \"WVHbj9LljCTovdsv\",\n // \"onDelete\": \"detach\"\n // }\n // }\n // }\n\n // retributive strike\n // \"pf2e\": {\n // \"grantedBy\": {\n // \"id\": \"HGWkTEatliHgDaEu\",\n // \"onDelete\": \"cascade\"\n // }\n\n #slugNameMatch(f, slug) {\n return slug === Seasoning.slug(f.name)\n || slug === Seasoning.slug(f.foundryValue)\n || slug === Seasoning.slug(Seasoning.getClassAdjustedSpecialNameLowerCase(f.name, this.source.class))\n || slug === Seasoning.slug(Seasoning.getAncestryAdjustedSpecialNameLowerCase(f.name, this.source.ancestry))\n || slug === Seasoning.slug(Seasoning.getHeritageAdjustedSpecialNameLowerCase(f.name, this.source.heritage))\n || slug === Seasoning.slug(f.originalName)\n || slug === Seasoning.slug(Seasoning.getClassAdjustedSpecialNameLowerCase(f.originalName, this.source.class))\n || slug\n === Seasoning.slug(Seasoning.getAncestryAdjustedSpecialNameLowerCase(f.originalName, this.source.ancestry))\n || slug\n === Seasoning.slug(Seasoning.getHeritageAdjustedSpecialNameLowerCase(f.originalName, this.source.heritage))\n || (utils.allowDualClasses()\n && (slug\n === Seasoning.slug(Seasoning.getDualClassAdjustedSpecialNameLowerCase(f.name, this.source.dualClass))\n || slug\n === Seasoning.slug(\n Seasoning.getDualClassAdjustedSpecialNameLowerCase(f.originalName, this.source.dualClass)\n )));\n }\n\n #parsedFeatureMatch(type, document, slug, { ignoreAdded, isChoiceMatch = false, featType = null } = {}) {\n if (type === \"feats\" && document) {\n const hintMatch = this.parsed[type].find((f) =>\n (!ignoreAdded || (ignoreAdded && !f.added))\n && f.isChild\n && f.nameHint\n && Seasoning.slug(document.name) === Seasoning.slug(f.nameHint)\n && this.#slugNameMatch(f, slug)\n );\n if (hintMatch) {\n hintMatch.rank = -10;\n return hintMatch;\n }\n }\n // console.warn(`Trying to find ${slug} in ${type}, ignoreAdded? ${ignoreAdded}`, this.parsed[type]);\n const parsedMatch = this.parsed[type].find((f) =>\n (!ignoreAdded || (ignoreAdded && !f.added))\n && (\n featType === null\n || f.type === featType\n )\n && !f.isChoice\n && this.#slugNameMatch(f, slug)\n );\n if (parsedMatch || !document) return parsedMatch;\n\n const extraMatch = this.parsed[type].find((f) =>\n // (!ignoreAdded || (ignoreAdded && !f.added))\n f.extra\n && f.added\n && !f.isChoice\n && Seasoning.slug(f.name) === (document.system.slug ?? Seasoning.slug(document.name))\n && Seasoning.slug(f.extra) === slug\n );\n if (extraMatch) return extraMatch;\n\n if (isChoiceMatch) {\n // console.warn(\"Specials check\", {\n // document,\n // type,\n // slug,\n // });\n const choiceMatch = this.parsed[type].find((f) => f.isChoice && !f.added && Seasoning.slug(f.name) === slug);\n return choiceMatch;\n }\n return undefined;\n }\n\n #generatedResultMatch(type, slug) {\n const featMatch = this.result[type].find((f) => slug === f.system.slug);\n return featMatch;\n }\n\n #findAllFeatureMatch(document, slug, { ignoreAdded, isChoiceMatch = false, featType = null } = {}) {\n // console.warn(\"Finding all feature matches\", { document, slug, ignoreAdded, isChoiceMatch, featType });\n const featMatch = this.#parsedFeatureMatch(\"feats\", document, slug, { ignoreAdded, featType });\n if (featMatch) return featMatch;\n const specialMatch = this.#parsedFeatureMatch(\"specials\", document, slug, { ignoreAdded, isChoiceMatch });\n if (specialMatch) return specialMatch;\n const deityMatch = this.#generatedResultMatch(\"deity\", slug);\n return deityMatch;\n // const classMatch = this.#generatedResultMatch(\"class\", slug);\n // return classMatch;\n // const equipmentMatch = this.#generatedResultMatch(\"equipment\", slug);\n // return equipmentMatch;\n }\n\n #createGrantedItem(document, parent, { itemGrantName = null, originType = null, applyFeatLocation = false } = {}) {\n logger.debug(`Adding granted item flags to ${document.name} (parent ${parent.name}) with originType \"${originType}\", and will applyFeatLocation? ${applyFeatLocation}`);\n if (itemGrantName) {\n const camelCase = Seasoning.slugD(itemGrantName ?? document.system.slug ?? document.name);\n setProperty(parent, `flags.pf2e.itemGrants.${camelCase}`, { id: document._id, onDelete: \"detach\" });\n setProperty(document, \"flags.pf2e.grantedBy\", { id: parent._id, onDelete: \"cascade\" });\n }\n this.autoFeats.push(document);\n this.result.feats.push(document);\n const matchOptions = { ignoreAdded: true, featType: originType };\n const featureMatch\n = this.#findAllFeatureMatch(document, document.system.slug ?? Seasoning.slug(document.name), matchOptions)\n ?? (document.name.includes(\"(\")\n ? this.#findAllFeatureMatch(document, Seasoning.slug(document.name.split(\"(\")[0].trim()), matchOptions)\n : undefined);\n\n if (featureMatch) {\n logger.debug(`Found feature match for ${document.name}`, { featureMatch });\n const existingMatch = false;\n // featureMatch.sourceType\n // ? this.parsed[featureMatch.sourceType].some((f) => f.addedId === document._id)\n // : false;\n if (this.devMode && existingMatch) {\n logger.warn(`create Granted Item Existing match for ${document.name}`, { featureMatch, existingMatch, document });\n }\n // console.warn(`Match for ${document.name} createGrantedItem`, { featureMatch, existingMatch, document });\n if (hasProperty(featureMatch, \"added\") && !existingMatch) {\n featureMatch.added = true;\n featureMatch.addedId = document._id;\n if (applyFeatLocation) this.#generateFoundryFeatLocation(document, featureMatch);\n }\n\n return;\n }\n if (document.type !== \"action\")\n logger.warn(\n `Unable to find parsed feature match for granted feature ${document.name}. This might not be an issue, but might indicate feature duplication.`,\n { document, parent }\n );\n }\n\n\n static #getLowestChoiceRank(choices) {\n return choices.reduce((p, c) => {\n return p.rank > c.rank ? c : p;\n });\n }\n\n async #featureChoiceMatch(document, choices, ignoreAdded, adjustName, choiceHint = null) {\n const matches = [];\n for (const choice of choices) {\n const doc = adjustName ? game.i18n.localize(choice.label) : await fromUuid(choice.value);\n if (!doc) continue;\n const slug = adjustName\n ? Seasoning.slug(doc)\n : doc.system.slug === null\n ? Seasoning.slug(doc.name)\n : doc.system.slug;\n const featMatch = this.#findAllFeatureMatch(document, slug, { ignoreAdded, isChoiceMatch: false });\n if (featMatch) {\n matches.push({\n slug,\n rank: featMatch.rank,\n choice,\n featMatch,\n });\n }\n }\n if (matches.length > 0) {\n if (choiceHint) {\n const hintMatch = matches.find((m) => m.slug === Seasoning.slug(choiceHint));\n if (hintMatch) return hintMatch;\n }\n if (this.devMode) logger.warn(`MATCHES`, matches);\n const match = Pathmuncher.#getLowestChoiceRank(matches);\n const featMatch = this.#findAllFeatureMatch(document, match.slug, { ignoreAdded });\n const existingMatch = false;\n // featMatch.sourceType\n // ? this.parsed[featMatch.sourceType].some((f) => f.addedId === document._id)\n // : false;\n if (this.devMode && existingMatch) {\n logger.warn(`Feature Choice Existing match for ${document.name}`, { featMatch, existingMatch, document });\n }\n // console.warn(`Match for ${document.name} featureChoiceMatch`, { match, featMatch, existingMatch, document });\n if (adjustName && hasProperty(featMatch, \"added\") && !existingMatch) {\n featMatch.added = true;\n featMatch.addedId = document._id;\n }\n logger.debug(\"Choices evaluated\", { choices, document, featMatch, match, matches });\n return match.choice;\n } else {\n return undefined;\n }\n }\n\n async #featureChoiceMatchNoUUID(document, choices, cleansedChoiceSet) {\n const matches = [];\n for (const choice of choices) {\n const featMatch = this.#findAllFeatureMatch(document, choice.value, { ignoreAdded: true, isChoiceMatch: true });\n if (featMatch) {\n matches.push({\n rank: featMatch.rank,\n choice,\n });\n }\n }\n if (matches.length > 0) {\n const match = Pathmuncher.#getLowestChoiceRank(matches);\n const featMatch = this.#findAllFeatureMatch(document, match.choice.value, { ignoreAdded: true, isChoiceMatch: true });\n\n const existingMatch = false;\n // featMatch.sourceType\n // ? this.parsed[featMatch.sourceType].some((f) => f.addedId === document._id)\n // : false;\n\n if (this.devMode && existingMatch) {\n logger.warn(`NoUUID Existing match for ${document.name}`, { featMatch, existingMatch, document });\n }\n // console.warn(`Match for ${document.name} featureChoiceMatchNoUUID`, { match, featMatch, existingMatch, document });\n if (featMatch && !existingMatch) {\n featMatch.added = true;\n featMatch.addedId = document._id;\n match.choice.nouuid = true;\n }\n logger.debug(\"No UUID Choices evaluated\", { choices, cleansedChoiceSet, document, featMatch, match, matches });\n return match.choice;\n } else {\n return undefined;\n }\n }\n\n static getFlag(document, ruleSet) {\n return typeof ruleSet.flag === \"string\" && ruleSet.flag.length > 0\n ? ruleSet.flag.replace(/[^-a-z0-9]/gi, \"\")\n : Seasoning.slugD(document.system.slug ?? document.system.name ?? document.name);\n }\n\n async #evaluateChoices(document, choiceSet, choiceHint) {\n logger.debug(`Evaluating choices for ${document.name}`, { document, choiceSet, choiceHint });\n const tempActor = await this.#generateTempActor([document], false, false, true);\n const cleansedChoiceSet = deepClone(choiceSet);\n try {\n const item = tempActor.getEmbeddedDocument(\"Item\", document._id);\n const choiceSetRules = new game.pf2e.RuleElements.all.ChoiceSet(cleansedChoiceSet, { parent: item });\n const rollOptions = [tempActor.getRollOptions(), item.getRollOptions(\"item\")].flat();\n const choices = await choiceSetRules.inflateChoices(rollOptions, []);\n\n logger.debug(\"Starting choice evaluation\", {\n document,\n choiceSet,\n item,\n choiceSetRules,\n rollOptions,\n choices,\n });\n\n if (cleansedChoiceSet.choices?.query) {\n const nonFilteredChoices = await choiceSetRules.inflateChoices(rollOptions, [item]);\n const queryResults = await choiceSetRules.queryCompendium(cleansedChoiceSet.choices, rollOptions, [item]);\n logger.debug(\"Query Result\", { queryResults, nonFilteredChoices });\n }\n\n logger.debug(\"Evaluating choiceset\", cleansedChoiceSet);\n const choiceMatch = await this.#featureChoiceMatch(document, choices, true, cleansedChoiceSet.adjustName, choiceHint);\n logger.debug(\"choiceMatch result\", choiceMatch);\n if (choiceMatch) {\n choiceMatch.choiceQueryResults = deepClone(choices);\n return choiceMatch;\n }\n\n if (typeof cleansedChoiceSet.choices === \"string\" || Array.isArray(choices)) {\n const featureMatch = await this.#featureChoiceMatchNoUUID(document, choices, cleansedChoiceSet);\n if (featureMatch) {\n return featureMatch;\n }\n }\n\n let tempSet = deepClone(choiceSet);\n logger.debug(`Starting dynamic selection for ${document.name}`, { document, choiceSet, tempSet, Pathmuncher: this });\n await choiceSetRules.preCreate({ itemSource: item, ruleSource: tempSet, pendingItems: [item], tempItems: [] });\n // console.warn(\"chociesetdata\", {\n // choiceSetRules,\n // selection: choiceSetRules.selection,\n // choiceSet: deepClone(choiceSet),\n // tempSet: deepClone(tempSet),\n // });\n if (tempSet.selection) {\n const lookedUpChoice = choices.find((c) => c.value === tempSet.selection);\n logger.debug(\"lookedUpChoice\", lookedUpChoice);\n if (lookedUpChoice) lookedUpChoice.choiceQueryResults = deepClone(choices);\n // set some common lookups here, e.g. deities are often not set!\n if (lookedUpChoice && cleansedChoiceSet.flag === \"deity\") {\n if (lookedUpChoice.label && lookedUpChoice.label !== \"\") {\n setProperty(this.result.character, \"system.details.deity.value\", lookedUpChoice.label);\n await this.#processGenericCompendiumLookup(\"deities\", lookedUpChoice.label, \"deity\");\n const camelCase = Seasoning.slugD(this.result.deity[0].system.slug);\n setProperty(document, `flags.pf2e.itemGrants.${camelCase}`, {\n id: this.result.deity[0]._id,\n onDelete: \"detach\",\n });\n setProperty(this.result.deity[0], \"flags.pf2e.grantedBy\", { id: document._id, onDelete: \"cascade\" });\n this.autoAddedFeatureIds.add(`${lookedUpChoice.value.split(\".\").pop()}deity`);\n }\n }\n return lookedUpChoice;\n }\n } catch (err) {\n logger.error(\"Whoa! Something went major bad wrong during choice evaluation\", {\n err,\n tempActor: tempActor.toObject(),\n document: duplicate(document),\n choiceSet: duplicate(cleansedChoiceSet),\n });\n throw err;\n } finally {\n await Actor.deleteDocuments([tempActor._id]);\n }\n\n logger.debug(\"Evaluate Choices failed\", { choiceSet: cleansedChoiceSet, tempActor, document });\n return undefined;\n }\n\n async #resolveInjectedUuid(document, ruleEntry) {\n const tempActor = await this.#generateTempActor([document], false, false);\n const cleansedRuleEntry = deepClone(ruleEntry);\n try {\n const item = tempActor.getEmbeddedDocument(\"Item\", document._id);\n // console.warn(\"creating grant item\");\n const grantItemRule = new game.pf2e.RuleElements.all.GrantItem(cleansedRuleEntry, { parent: item });\n // console.warn(\"Begining uuid resovle\");\n const uuid = grantItemRule.resolveInjectedProperties(grantItemRule.uuid, { warn: false });\n\n logger.debug(\"uuid selection\", {\n document,\n choiceSet: ruleEntry,\n item,\n grantItemRule,\n uuid,\n });\n if (uuid) return uuid;\n } catch (err) {\n logger.error(\"Whoa! Something went major bad wrong during uuid evaluation\", {\n err,\n tempActor: tempActor.toObject(),\n document: duplicate(document),\n ruleEntry: duplicate(cleansedRuleEntry),\n });\n throw err;\n } finally {\n await Actor.deleteDocuments([tempActor._id]);\n }\n\n logger.debug(\"Evaluate UUID failed\", { choiceSet: cleansedRuleEntry, tempActor, document });\n return undefined;\n }\n\n async #checkRule(document, rule) {\n const tempActor = await this.#generateTempActor([document], true);\n const cleansedRule = deepClone(rule);\n try {\n const item = tempActor.getEmbeddedDocument(\"Item\", document._id);\n const ruleElement = cleansedRule.key === \"ChoiceSet\"\n ? new game.pf2e.RuleElements.all.ChoiceSet(cleansedRule, { parent: item })\n : new game.pf2e.RuleElements.all.GrantItem(cleansedRule, { parent: item });\n const rollOptions = [tempActor.getRollOptions(), item.getRollOptions(\"item\")].flat();\n\n if (rule.predicate) {\n const predicate = ruleElement.resolveInjectedProperties(ruleElement.predicate);\n if (!predicate.test(rollOptions)) return false;\n }\n\n const choices = cleansedRule.key === \"ChoiceSet\"\n ? await ruleElement.inflateChoices(rollOptions, [item])\n : [ruleElement.resolveValue()];\n\n const isGood = cleansedRule.key === \"ChoiceSet\"\n ? (await this.#featureChoiceMatch(document, choices, false)) !== undefined\n : ruleElement.test(rollOptions);\n\n logger.debug(\"Checking rule\", {\n tempActor,\n cleansedRule,\n item,\n ruleElement,\n rollOptions,\n choices,\n isGood,\n });\n return isGood;\n } catch (err) {\n logger.error(\"Something has gone most wrong during rule checking\", {\n document,\n rule: cleansedRule,\n tempActor,\n });\n throw err;\n } finally {\n await Actor.deleteDocuments([tempActor._id]);\n }\n }\n\n async #checkRulePredicate(document, rule) {\n const tempActor = await this.#generateTempActor([document], true);\n const cleansedRule = deepClone(rule);\n try {\n const item = tempActor.getEmbeddedDocument(\"Item\", document._id);\n const ruleElement = cleansedRule.key === \"ChoiceSet\"\n ? new game.pf2e.RuleElements.all.ChoiceSet(cleansedRule, { parent: item })\n : new game.pf2e.RuleElements.all.GrantItem(cleansedRule, { parent: item });\n const rollOptions = [tempActor.getRollOptions(), item.getRollOptions(\"item\")].flat();\n\n if (rule.predicate) {\n const predicate = ruleElement.resolveInjectedProperties(ruleElement.predicate);\n return predicate.test(rollOptions);\n } else {\n return true;\n }\n } catch (err) {\n logger.error(\"Something has gone most wrong during rule predicate checking\", {\n document,\n rule: cleansedRule,\n tempActor,\n });\n throw err;\n } finally {\n await Actor.deleteDocuments([tempActor._id]);\n }\n }\n\n static adjustDocumentName(featureName, label) {\n const localLabel = game.i18n.localize(label);\n if (featureName.trim().toLowerCase() === localLabel.trim().toLowerCase()) return featureName;\n const name = `${featureName} (${localLabel})`;\n const pattern = (() => {\n const escaped = RegExp.escape(localLabel);\n return new RegExp(`\\\\(${escaped}\\\\) \\\\(${escaped}\\\\)$`);\n })();\n return name.replace(pattern, `(${localLabel})`);\n }\n\n // eslint-disable-next-line complexity, no-unused-vars\n async #addGrantedRules(document, originType = null, choiceHint = null) {\n if (document.system.rules.length === 0) return;\n logger.debug(`addGrantedRules for ${document.name}`, duplicate(document));\n\n if (\n hasProperty(document, \"system.level.value\")\n && document.system.level.value > this.result.character.system.details.level.value\n ) {\n return;\n }\n\n const rulesToKeep = [];\n this.allFeatureRules[document._id] = deepClone(document.system.rules);\n this.autoAddedFeatureRules[document._id] = [];\n this.promptRules[document._id] = [];\n let featureRenamed = false;\n\n for (const ruleEntry of document.system.rules) {\n logger.debug(`Ping ${document.name} rule key: ${ruleEntry.key}`, ruleEntry);\n if (![\"ChoiceSet\", \"GrantItem\"].includes(ruleEntry.key)) {\n // size work around due to Pathbuilder not always adding the right size to json\n if (ruleEntry.key === \"CreatureSize\") this.size = ruleEntry.value;\n this.autoAddedFeatureRules[document._id].push(ruleEntry);\n rulesToKeep.push(ruleEntry);\n continue;\n }\n if (NO_AUTO_CHOICE().includes(document.name)) {\n logger.debug(`Deliberately skipping ${document.name} auto choice detection`);\n rulesToKeep.push(ruleEntry);\n continue;\n }\n logger.debug(`Checking ${document.name} rule key: ${ruleEntry.key}`, {\n ruleEntry,\n docRules: deepClone(document.system.rules),\n document: deepClone(document),\n });\n\n if (ruleEntry.key === \"ChoiceSet\" && ruleEntry.predicate) {\n logger.debug(`Checking for predicates`, {\n ruleEntry,\n document,\n });\n const testResult = await this.#checkRulePredicate(duplicate(document), ruleEntry);\n if (!testResult) {\n const data = { document, ruleEntry, testResult };\n logger.debug(\n `The test failed for ${document.name} rule key: ${ruleEntry.key} (This is probably not a problem).`,\n data\n );\n rulesToKeep.push(ruleEntry);\n continue;\n }\n }\n\n const choice = ruleEntry.key === \"ChoiceSet\" ? await this.#evaluateChoices(document, ruleEntry, choiceHint) : undefined;\n const uuid = ruleEntry.key === \"GrantItem\" ? await this.#resolveInjectedUuid(document, ruleEntry) : choice?.value;\n\n if (choice?.choiceQueryResults) {\n ruleEntry.choiceQueryResults = choice.choiceQueryResults;\n }\n\n const flagName = Pathmuncher.getFlag(document, ruleEntry);\n // if (flagName && choice?.value && !hasProperty(document, `flags.pf2e.rulesSelections.${flagName}`)) {\n // setProperty(document, `flags.pf2e.rulesSelections.${flagName}`, choice.value);\n // }\n\n logger.debug(`UUID for ${document.name}: \"${uuid}\"`, { document, ruleEntry, choice, uuid });\n const ruleFeature = uuid && typeof uuid === \"string\" ? await fromUuid(uuid) : undefined;\n // console.warn(\"ruleFeature\", ruleFeature);\n if (ruleFeature) {\n const featureDoc = ruleFeature.toObject();\n featureDoc._id = foundry.utils.randomID();\n if (featureDoc.system.rules) this.allFeatureRules[featureDoc._id] = deepClone(featureDoc.system.rules);\n setProperty(featureDoc, \"flags.pathmuncher.origin.uuid\", uuid);\n logger.debug(`Found rule feature ${featureDoc.name} for ${document.name} for`, ruleEntry);\n\n if (choice) {\n ruleEntry.selection = choice.value;\n setProperty(document, `flags.pf2e.rulesSelections.${flagName}`, choice.value);\n }\n\n if (utils.isString(ruleEntry.rollOption)) {\n ruleEntry.rollOption = `${ruleEntry.rollOption}:${flagName}`;\n }\n\n if (ruleEntry.predicate && ruleEntry.key === \"GrantItem\") {\n logger.debug(`Checking for grantitem predicates`, {\n ruleEntry,\n document,\n featureDoc,\n });\n const testResult = await this.#checkRule(featureDoc, ruleEntry);\n if (!testResult) {\n const data = { document, ruleEntry, featureDoc, testResult };\n logger.debug(\n `The test failed for ${document.name} rule key: ${ruleEntry.key} (This is probably not a problem).`,\n data\n );\n rulesToKeep.push(ruleEntry);\n // this.autoAddedFeatureRules[document._id].push(ruleEntry);\n continue;\n } else {\n logger.debug(`The test passed for ${document.name} rule key: ${ruleEntry.key}`, ruleEntry);\n // this.autoAddedFeatureRules[document._id].push(ruleEntry);\n // eslint-disable-next-line max-depth\n // if (!ruleEntry.flag) ruleEntry.flag = Seasoning.slugD(document.name);\n ruleEntry.pathmuncherImport = true;\n rulesToKeep.push(ruleEntry);\n }\n }\n\n // setProperty(ruleEntry, `preselectChoices.${ruleEntry.flag}`, ruleEntry.selection ?? ruleEntry.uuid);\n\n if (this.autoAddedFeatureIds.has(`${ruleFeature.id}${ruleFeature.type}`)) {\n logger.debug(`Feature ${featureDoc.name} found for ${document.name}, but has already been added (${ruleFeature.id})`, ruleFeature);\n // this.autoAddedFeatureRules[document._id].push(ruleEntry);\n // rulesToKeep.push(ruleEntry);\n if (ruleEntry.key === \"GrantItem\" && ruleEntry.flag) {\n this.autoAddedFeatureRules[document._id].push(ruleEntry);\n rulesToKeep.push(ruleEntry);\n }\n continue;\n } else {\n logger.debug(`Feature ${featureDoc.name} not found for ${document.name}, adding (${ruleFeature.id})`, ruleFeature);\n if (ruleEntry.selection || ruleEntry.flag) {\n rulesToKeep.push(ruleEntry);\n }\n this.autoAddedFeatureIds.add(`${ruleFeature.id}${ruleFeature.type}`);\n featureDoc._id = foundry.utils.randomID();\n this.#createGrantedItem(featureDoc, document, { itemGrantName: flagName, applyFeatLocation: false });\n if (hasProperty(featureDoc, \"system.rules\")) await this.#addGrantedRules(featureDoc);\n }\n } else if (getProperty(choice, \"nouuid\")) {\n logger.debug(\"Parsed no id rule\", { choice, uuid, ruleEntry });\n if (!ruleEntry.flag) ruleEntry.flag = Seasoning.slugD(document.name);\n ruleEntry.selection = choice.value;\n if (choice.label) document.name = `${document.name} (${choice.label})`;\n rulesToKeep.push(ruleEntry);\n } else if (choice && uuid && !hasProperty(ruleEntry, \"selection\")) {\n logger.debug(\"Parsed odd choice rule\", { choice, uuid, ruleEntry });\n // if (!ruleEntry.flag) ruleEntry.flag = Seasoning.slugD(document.name);\n ruleEntry.selection = choice.value;\n if (\n ((!ruleEntry.adjustName && choice.label && typeof uuid === \"object\")\n || (!choice.adjustName && choice.label))\n && !featureRenamed\n ) {\n document.name = Pathmuncher.adjustDocumentName(document.name, choice.label);\n featureRenamed = true;\n }\n rulesToKeep.push(ruleEntry);\n } else {\n logger.debug(`Final rule fallback for ${document.name}`, ruleEntry);\n const data = {\n uuid: ruleEntry.uuid,\n document,\n ruleEntry,\n choice,\n };\n if (\n ruleEntry.key === \"GrantItem\"\n && (ruleEntry.flag || ruleEntry.selection || ruleEntry.uuid.startsWith(\"Compendium\"))\n ) {\n rulesToKeep.push(ruleEntry);\n } else if (ruleEntry.key === \"ChoiceSet\" && !hasProperty(ruleEntry, \"flag\")) {\n logger.debug(\"Prompting user for choices\", ruleEntry);\n this.promptRules[document._id].push(ruleEntry);\n rulesToKeep.push(ruleEntry);\n } else if (ruleEntry.key === \"ChoiceSet\" && !choice && !uuid) {\n logger.warn(\"Unable to determine choice asking\", data);\n rulesToKeep.push(ruleEntry);\n this.promptRules[document._id].push(ruleEntry);\n }\n logger.warn(\"Unable to determine granted rule feature, needs better parser\", data);\n }\n if (ruleEntry.adjustName && choice?.label && !featureRenamed) {\n document.name = Pathmuncher.adjustDocumentName(document.name, choice.label);\n }\n this.autoAddedFeatureRules[document._id].push(ruleEntry);\n\n logger.debug(`End result for ${document.name} for a ${ruleEntry.key}`, {\n document: deepClone(document),\n rulesToKeep: deepClone(rulesToKeep),\n ruleEntry: deepClone(ruleEntry),\n choice: deepClone(choice),\n uuid: deepClone(uuid),\n });\n }\n // eslint-disable-next-line require-atomic-updates\n document.system.rules = rulesToKeep;\n\n logger.debug(`Final status for ${document.name}`, {\n document: deepClone(document),\n rulesToKeep: deepClone(rulesToKeep),\n });\n }\n\n async #addGrantedItems(document, { originType = null, applyFeatLocation = false, choiceHint = null } = {}) {\n const immediateDiveAdd = utils.setting(\"USE_IMMEDIATE_DEEP_DIVE\");\n const subRuleDocuments = [];\n if (hasProperty(document, \"system.items\")) {\n logger.debug(`addGrantedItems for ${document.name}`, duplicate(document));\n if (!this.autoAddedFeatureItems[document._id]) {\n this.autoAddedFeatureItems[document._id] = duplicate(document.system.items);\n }\n const failedFeatureItems = {};\n for (const [key, grantedItemFeature] of Object.entries(document.system.items).sort(([, a], [, b]) => a.level - b.level)) {\n logger.debug(`Checking ${document.name} granted item ${grantedItemFeature.name}, level(${grantedItemFeature.level}) with key: ${key}`, grantedItemFeature);\n if (grantedItemFeature.level > getProperty(this.result.character, \"system.details.level.value\")) continue;\n const feature = await fromUuid(grantedItemFeature.uuid);\n if (!feature) {\n const data = { uuid: grantedItemFeature.uuid, grantedFeature: grantedItemFeature, feature };\n logger.warn(\"Unable to determine granted item feature, needs better parser\", data);\n failedFeatureItems[key] = grantedItemFeature;\n continue;\n }\n this.autoAddedFeatureIds.add(`${feature.id}${feature.type}`);\n const featureDoc = feature.toObject();\n featureDoc._id = foundry.utils.randomID();\n setProperty(featureDoc.system, \"location\", document._id);\n this.#createGrantedItem(featureDoc, document, { originType, applyFeatLocation });\n if (hasProperty(featureDoc, \"system.rules\")) {\n logger.debug(`Processing granted rules for granted item document ${featureDoc.name}`, duplicate(featureDoc));\n if (immediateDiveAdd) {\n await this.#addGrantedItems(featureDoc, { originType, applyFeatLocation });\n } else {\n subRuleDocuments.push(featureDoc);\n }\n }\n }\n // eslint-disable-next-line require-atomic-updates\n document.system.items = failedFeatureItems;\n\n if (!immediateDiveAdd) {\n for (const subRuleDocument of subRuleDocuments) {\n logger.debug(\n `Processing granted rules for granted item document ${subRuleDocument.name}`,\n duplicate(subRuleDocument)\n );\n await this.#addGrantedItems(subRuleDocument, { originType, applyFeatLocation, choiceHint });\n }\n }\n }\n\n if (hasProperty(document, \"system.rules\")) {\n logger.debug(`Processing granted rules for core document ${document.name}`, duplicate(document));\n await this.#addGrantedRules(document, originType, choiceHint);\n }\n }\n\n #determineAbilityBoosts() {\n const breakdown = getProperty(this.source, \"abilities.breakdown\");\n const useCustomStats\n = breakdown\n && breakdown.ancestryFree.length === 0\n && breakdown.ancestryBoosts.length === 0\n && breakdown.ancestryFlaws.length === 0\n && breakdown.backgroundBoosts.length === 0\n && breakdown.classBoosts.length === 0;\n if (breakdown && !useCustomStats) {\n this.boosts.custom = false;\n const classBoostMap = {};\n for (const [key, boosts] of Object.entries(this.source.abilities.breakdown.mapLevelledBoosts)) {\n if (key <= this.source.level) {\n classBoostMap[key] = boosts.map((ability) => ability.toLowerCase());\n }\n }\n setProperty(this.result.character, \"system.build.attributes.boosts\", classBoostMap);\n this.boosts.class = classBoostMap;\n\n // ancestry\n } else {\n this.boosts.custom = true;\n [\"str\", \"dex\", \"con\", \"int\", \"wis\", \"cha\"].forEach((key) => {\n const mod = Math.min(Math.max(Math.trunc((this.source.abilities[key] - 10) / 2), -5), 10) || 0;\n setProperty(this.result.character, `system.abilities.${key}.mod`, mod);\n });\n }\n\n if (breakdown?.classBoosts.length > 0) {\n this.keyAbility = breakdown.classBoosts[0].toLowerCase();\n } else {\n this.keyAbility = this.source.keyability;\n }\n setProperty(this.result.character, \"system.details.keyability.value\", this.keyAbility);\n }\n\n #generateBackgroundAbilityBoosts() {\n if (!this.result.background[0]) return;\n const breakdown = getProperty(this.source, \"abilities.breakdown\");\n for (const boost of breakdown.backgroundBoosts) {\n for (const [key, boostSet] of Object.entries(this.result.background[0].system.boosts)) {\n if (this.result.background[0].system.boosts[key].selected) continue;\n if (boostSet.value.includes(boost.toLowerCase())) {\n this.result.background[0].system.boosts[key].selected = boost.toLowerCase();\n break;\n }\n }\n }\n }\n\n #generateAncestryAbilityBoosts() {\n if (!this.result.ancestry[0]) return;\n const breakdown = getProperty(this.source, \"abilities.breakdown\");\n const boosts = [];\n breakdown.ancestryBoosts.concat(breakdown.ancestryFree).forEach((boost) => {\n for (const [key, boostSet] of Object.entries(this.result.ancestry[0].system.boosts)) {\n if (this.result.ancestry[0].system.boosts[key].selected) continue;\n if (boostSet.value.includes(boost.toLowerCase())) {\n this.result.ancestry[0].system.boosts[key].selected = boost.toLowerCase();\n boosts.push(boost.toLowerCase());\n break;\n }\n }\n });\n if (breakdown.ancestryBoosts.length === 0) {\n setProperty(this.result.ancestry[0], \"system.alternateAncestryBoosts\", boosts);\n }\n }\n\n #setAbilityBoosts() {\n if (this.boosts.custom) return;\n this.#generateBackgroundAbilityBoosts();\n this.#generateAncestryAbilityBoosts();\n\n this.result.class[0].system.boosts = this.boosts.class;\n }\n\n static SKILL_LOOKUP = {\n \"acrobatics\": \"acr\",\n \"arcana\": \"arc\",\n \"athletics\": \"ath\",\n \"crafting\": \"cra\",\n \"deception\": \"dec\",\n \"diplomacy\": \"dip\",\n \"intimidation\": \"itm\",\n \"medicine\": \"med\",\n \"nature\": \"nat\",\n \"occultism\": \"occ\",\n \"performance\": \"prf\",\n \"religion\": \"rel\",\n \"society\": \"soc\",\n \"stealth\": \"ste\",\n \"survival\": \"sur\",\n \"thievery\": \"thi\",\n };\n\n #setSkills(removeSpecials = false) {\n for (const [key, value] of Object.entries(Pathmuncher.SKILL_LOOKUP)) {\n const calculatedValue = removeSpecials\n && (this.source.specials.some((s) => s.toLowerCase() === key)\n || this.parsed.specials.some((s) => s.name.toLowerCase() === key))\n ? 0\n : this.source.proficiencies[key] / 2;\n setProperty(this.result.character, `system.skills.${value}.rank`, calculatedValue);\n };\n }\n\n #setSaves() {\n [\"fortitude\", \"reflex\", \"will\"].forEach((key) => {\n setProperty(this.result.character, `system.savingThrows.${key}`, this.source.proficiencies[key] / 2);\n });\n }\n\n #setMartials() {\n [\"advanced\", \"heavy\", \"light\", \"medium\", \"unarmored\", \"martial\", \"simple\", \"unarmed\"].forEach((key) => {\n setProperty(this.result.character, `system.martial.${key}.rank`, this.source.proficiencies[key] / 2);\n });\n }\n\n async #processCore() {\n setProperty(this.result.character, \"name\", this.source.name);\n setProperty(this.result.character, \"prototypeToken.name\", this.source.name);\n setProperty(this.result.character, \"system.details.level.value\", this.source.level);\n if (this.source.age !== \"Not set\") setProperty(this.result.character, \"system.details.age.value\", this.source.age);\n if (this.source.gender !== \"Not set\") setProperty(this.result.character, \"system.details.gender.value\", this.source.gender);\n // setProperty(this.result.character, \"system.details.alignment.value\", this.source.alignment);\n\n if (this.source.deity !== \"Not set\") setProperty(this.result.character, \"system.details.deity.value\", this.source.deity);\n this.size = Seasoning.getSizeValue(this.source.size);\n setProperty(this.result.character, \"system.traits.size.value\", this.size);\n setProperty(this.result.character, \"system.traits.languages.value\", this.source.languages.map((l) => l.toLowerCase()));\n\n this.#processSenses();\n\n this.#determineAbilityBoosts();\n this.#setSaves();\n this.#setMartials();\n\n // setProperty(this.result.character, \"system.attributes.perception.rank\", this.source.proficiencies.perception / 2);\n // setProperty(this.result.character, \"system.attributes.classDC.rank\", this.source.proficiencies.classDC / 2);\n }\n\n #indexFind(index, arrayOfNameMatches) {\n for (const name of arrayOfNameMatches) {\n const indexMatch = index.find((i) => {\n const slug = i.system.slug ?? Seasoning.slug(i.name);\n return (\n slug === Seasoning.slug(name)\n || slug === Seasoning.slug(Seasoning.getClassAdjustedSpecialNameLowerCase(name, this.source.class))\n || slug === Seasoning.slug(Seasoning.getAncestryAdjustedSpecialNameLowerCase(name, this.source.ancestry))\n || slug === Seasoning.slug(Seasoning.getHeritageAdjustedSpecialNameLowerCase(name, this.source.heritage))\n || (utils.allowDualClasses()\n && slug === Seasoning.slug(Seasoning.getDualClassAdjustedSpecialNameLowerCase(name, this.source.dualClass)))\n );\n });\n if (indexMatch) return indexMatch;\n }\n return undefined;\n }\n\n #findInPackIndexes(type, arrayOfNameMatches) {\n const matcher = this.compendiumMatchers[type];\n for (const [packName, index] of Object.entries(matcher.indexes)) {\n const indexMatch = this.#indexFind(index, arrayOfNameMatches);\n if (indexMatch) return { i: indexMatch, pack: matcher.packs[packName] };\n }\n return undefined;\n }\n\n #sortParsedFeats() {\n // eslint-disable-next-line complexity\n this.parsed.feats.sort((f1, f2) => {\n const f1RefUndefined = !(typeof f1.type === \"string\" || f1.type instanceof String);\n const f2RefUndefined = !(typeof f2.type === \"string\" || f2.type instanceof String);\n if (f1RefUndefined || f2RefUndefined) {\n if (f1RefUndefined && f2RefUndefined) {\n return 0;\n } else if (f1RefUndefined) {\n return 1;\n } else {\n return -1;\n }\n } else if (f1.type === \"Awarded Feat\" && f2.type === \"Awarded Feat\") {\n return (f1.level ?? 20) - (f2.level ?? 20);\n } else if (f1.type === \"Awarded Feat\") {\n return 1;\n } else if (f2.type === \"Awarded Feat\") {\n return -1;\n } else if ((f1.level ?? 20) === (f2.level ?? 20)) {\n const f1Index = CONSTANTS.FEAT_PRIORITY.indexOf(f1.type);\n const f2Index = CONSTANTS.FEAT_PRIORITY.indexOf(f2.type);\n if (f1Index > f2Index) {\n return 1;\n } else if (f1Index < f2Index) {\n return -1;\n } else {\n return 0;\n }\n } else {\n return (f1.level ?? 20) - (f2.level ?? 20);\n }\n });\n }\n\n // eslint-disable-next-line complexity\n async #generateFeatItems(type,\n { levelCap = null, typeFilter = null, excludeChild = false, excludeParents = false, excludeStandard = false } = {}\n ) {\n logger.debug(`Generate feat items for ${type} with level cap \"${levelCap}\" and filter \"${typeFilter}\"`);\n\n for (const featArray of [this.parsed.feats, this.parsed.specials]) {\n for (const pBFeat of featArray) {\n if (pBFeat.added) continue;\n if (levelCap && (pBFeat.level ?? 20) > levelCap) continue;\n if (typeFilter && pBFeat.type !== typeFilter) continue;\n if (excludeChild && pBFeat.isChild === true) continue;\n if (excludeParents && pBFeat.isParent === true) continue;\n if (excludeStandard && pBFeat.isStandard === true) continue;\n logger.debug(`Generating feature for ${pBFeat.name}`, pBFeat);\n if (this.devMode) logger.error(`Generating feature for ${pBFeat.name}`, { pBFeat, this: this });\n\n const indexMatch = this.#findInPackIndexes(type, [pBFeat.name, pBFeat.originalName]);\n const displayName = pBFeat.extra ? Pathmuncher.adjustDocumentName(pBFeat.name, pBFeat.extra) : pBFeat.name;\n if (!indexMatch) {\n logger.debug(`Unable to match feat ${displayName}`, {\n displayName,\n name: pBFeat.name,\n extra: pBFeat.extra,\n pBFeat,\n type,\n });\n this.check[pBFeat.originalName] = {\n name: displayName,\n type: \"feat\",\n details: {\n displayName,\n name: pBFeat.name,\n originalName: pBFeat.originalName,\n extra: pBFeat.extra,\n pBFeat,\n type,\n },\n };\n continue;\n }\n if (this.check[pBFeat.originalName]) delete this.check[pBFeat.originalName];\n pBFeat.added = true;\n if (this.autoAddedFeatureIds.has(`${indexMatch._id}${indexMatch.type}`)) {\n logger.debug(\"Feat included in class features auto add\", { displayName, pBFeat, type });\n pBFeat.addedAutoId = `${indexMatch._id}_${indexMatch.type}`;\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const docData = doc.toObject();\n docData._id = foundry.utils.randomID();\n pBFeat.addedId = docData._id;\n // docData.name = displayName;\n\n this.#generateFoundryFeatLocation(docData, pBFeat);\n this.result.feats.push(docData);\n const options = {\n originType: typeFilter,\n applyFeatLocation: false,\n choiceHint: pBFeat.extra && pBFeat.extra !== \"\" ? pBFeat.extra : null,\n };\n await this.#addGrantedItems(docData, \"feat\", options);\n }\n }\n }\n\n async #generateSpecialItems(type) {\n for (const special of this.parsed.specials) {\n if (special.added) continue;\n logger.debug(\"Generating special for\", special);\n const indexMatch = this.#findInPackIndexes(type, [special.name, special.originalName]);\n if (!indexMatch) {\n logger.debug(`Unable to match special ${special.name}`, { special: special.name, type });\n this.check[special.originalName] = {\n name: special.name,\n type: \"special\",\n details: { displayName: special.name, name: special.name, originalName: special.originalName, special },\n };\n continue;\n }\n special.added = true;\n if (this.check[special.originalName]) delete this.check[special.originalName];\n if (this.autoAddedFeatureIds.has(`${indexMatch._id}${indexMatch.type}`)) {\n logger.debug(\"Special included in class features auto add\", { special: special.name, type });\n special.addedAutoId = `${indexMatch._id}_${indexMatch.type}`;\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const docData = doc.toObject();\n docData._id = foundry.utils.randomID();\n special.addedId = docData._id;\n this.result.feats.push(docData);\n await this.#addGrantedItems(docData, { applyFeatLocation: true });\n }\n }\n\n #resizeItem(item) {\n if (Seasoning.isPhysicalItemType(item.type)) {\n const resizeItem = item.type !== \"treasure\" && ![\"med\", \"sm\"].includes(this.size);\n if (resizeItem) item.system.size = this.size;\n }\n }\n\n async #generateAdventurersPack() {\n const defaultCompendium = game.packs.get(\"pf2e.equipment-srd\");\n const index = await defaultCompendium.getIndex({ fields: [\"name\", \"type\", \"system.slug\"] });\n\n\n const adventurersPack = this.parsed.equipment.find((e) => e.pbName === \"Adventurer's Pack\");\n if (adventurersPack) {\n const compendiumBackpack = await defaultCompendium.getDocument(\"3lgwjrFEsQVKzhh7\");\n const backpackInstance = compendiumBackpack.toObject();\n adventurersPack.added = true;\n backpackInstance._id = foundry.utils.randomID();\n adventurersPack.addedId = backpackInstance._id;\n this.result.adventurersPack.item = adventurersPack;\n this.result.equipment.push(backpackInstance);\n for (const content of this.result.adventurersPack.contents) {\n const indexMatch = index.find((i) => i.system.slug === content.slug);\n if (!indexMatch) {\n logger.error(`Unable to match adventurers kit item ${content.name}`, content);\n continue;\n }\n\n const doc = await defaultCompendium.getDocument(indexMatch._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n itemData.system.quantity = content.qty;\n itemData.system.containerId = backpackInstance?._id;\n this.#resizeItem(itemData);\n this.result.equipment.push(itemData);\n }\n }\n }\n\n async #generateContainers() {\n for (const [key, data] of Object.entries(this.source.equipmentContainers)) {\n if (data.foundryId) continue;\n const name = Seasoning.getFoundryEquipmentName(data.containerName);\n const indexMatch = this.compendiumMatchers[\"equipment\"].getMatch(data.containerName, name);\n const id = foundry.utils.randomID();\n const doc = indexMatch\n ? await indexMatch.pack.getDocument(indexMatch.i._id)\n : await Item.create({ name: data.containerName, type: \"backpack\" }, { temporary: true });\n const itemData = doc.toObject();\n itemData._id = id;\n this.#resizeItem(itemData);\n this.result[\"equipment\"].push(itemData);\n this.parsed.equipment.push({\n foundryName: name,\n pbName: data.containerName,\n originalName: data.containerName,\n name,\n qty: 1,\n added: true,\n inContainer: undefined,\n container: this.#getContainerData(key),\n foundryId: id,\n });\n }\n }\n\n async #generateEquipmentItems() {\n for (const e of this.parsed.equipment) {\n if (e.pbName === \"Adventurer's Pack\") continue;\n if (e.added) continue;\n if (Seasoning.IGNORED_EQUIPMENT().includes(e.pbName)) {\n e.added = true;\n e.addedAutoId = \"ignored\";\n continue;\n }\n logger.debug(\"Generating item for\", e);\n const indexMatch = this.compendiumMatchers[\"equipment\"].getMatch(e.pbName, e.foundryName);\n if (!indexMatch) {\n logger.error(`Unable to match ${e.pbName}`, e);\n this.bad.push({ pbName: e.pbName, type: \"equipment\", details: { e } });\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n if (doc.type != \"kit\") {\n const itemData = doc.toObject();\n itemData._id = e.foundryId || foundry.utils.randomID();\n itemData.system.quantity = e.qty;\n const type = doc.type === \"treasure\" ? \"treasure\" : \"equipment\";\n if (e.inContainer) {\n const containerMatch = this.parsed.equipment.find((con) => con.container?.id === e.inContainer);\n if (containerMatch) {\n itemData.system.containerId = containerMatch.foundryId;\n itemData.system.equipped.carryType = \"stowed\";\n }\n }\n if (e.invested) {\n itemData.system.equipped.carryType = \"worn\";\n itemData.system.equipped.invested = true;\n itemData.system.equipped.inSlot = true;\n itemData.system.equipped.handsHeld = 0;\n }\n this.#resizeItem(itemData);\n this.result[type].push(itemData);\n e.addedId = itemData._id;\n }\n // eslint-disable-next-line require-atomic-updates\n e.added = true;\n }\n }\n\n async #processEquipmentItems() {\n // just in case it's in the equipment, pathbuilder should have translated this to items\n await this.#generateAdventurersPack();\n await this.#generateContainers();\n await this.#generateEquipmentItems();\n }\n\n static RUNE_SCALE = [\n \"\",\n \"Minor\",\n \"Lesser\",\n \"Moderate\",\n \"Greater\",\n \"Major\",\n \"Supreme\",\n ];\n\n static REINFORCING_DATA = {\n \"Minor\": {\n value: 1,\n hp: 44,\n },\n \"Lesser\": {\n value: 2,\n hp: 52,\n },\n \"Moderate\": {\n value: 3,\n hp: 64,\n },\n \"Greater\": {\n value: 4,\n hp: 80,\n },\n \"Major\": {\n value: 5,\n hp: 84,\n },\n \"Supreme\": {\n value: 6,\n hp: 108,\n },\n };\n\n static POTENCY_SCALE = [\n \"\",\n \"striking\",\n \"greaterStriking\",\n \"majorStriking\",\n ];\n\n static RESILIENT_SCALE = [\n \"\",\n \"resilient\",\n \"greaterResilient\",\n \"majorResilient\",\n ];\n\n // eslint-disable-next-line complexity\n static applyRunes(parsedItem, itemData, type) {\n if (itemData.type == \"shield\") {\n parsedItem.runes.forEach((rune) => {\n if (rune.startsWith(\"Reinforcing\")) {\n const runeScale = rune.split(\"(\").pop().split(\")\").shift().trim();\n const runeMatch = Pathmuncher.REINFORCING_DATA[runeScale];\n if (runeMatch) {\n itemData.system.runes.reinforcing = runeMatch.value;\n itemData.system.hp.value += runeMatch.hp;\n }\n } else {\n const runeScale = rune.split(\"(\").pop().split(\")\").shift().trim();\n const runeLevel = Pathmuncher.RUNE_SCALE.indexOf(runeScale);\n const runeType = rune.split(\"(\").shift().toLowerCase().trim();\n if (runeLevel !== -1) {\n itemData.system.runes[runeType] = runeLevel;\n }\n }\n });\n } else if (hasProperty(itemData, \"system.runes.potency\")) {\n itemData.system.runes.potency = parsedItem.pot;\n if (type === \"weapon\") {\n const striking = Pathmuncher.POTENCY_SCALE.indexOf(parsedItem.str);\n if (striking !== -1) itemData.system.runes.striking = striking;\n } else if (type === \"armor\") {\n const resilient = Pathmuncher.RESILIENT_SCALE.indexOf(parsedItem.res);\n if (resilient !== -1) itemData.system.runes.resilient = resilient;\n }\n }\n\n if (type === \"armor\" && parsedItem.worn\n && ((Number.isInteger(parsedItem.pot) && parsedItem.pot > 0)\n || (parsedItem.res && parsedItem.res !== \"\")\n )\n ) {\n itemData.system.equipped.invested = true;\n }\n\n if (hasProperty(itemData, \"system.runes.property\")) {\n parsedItem.runes.forEach((property) => {\n const resistantRegex = /Energy Resistant - (.*)/i;\n const resistantMatch = property.match(resistantRegex);\n const rune = resistantMatch\n ? `${resistantMatch[1]} Resistant`\n : property;\n itemData.system.runes.property.push(Seasoning.slugD(rune));\n });\n }\n\n if (parsedItem.mat) {\n const material = parsedItem.mat.split(\" (\")[0];\n itemData.system.material.type = Seasoning.slugD(material);\n itemData.system.material.grade = Seasoning.getMaterialGrade(parsedItem.mat);\n }\n }\n\n async #createWeaponItem(data) {\n // { pbName, name, prof, qty, die, display, increasedDice, pot, str, mat, runes, attack, damageBonus, extraDamage, damageType }\n logger.debug(\"Generating weapon for\", data);\n const indexMatch = this.compendiumMatchers[\"equipment\"].getMatch(data.pbName, data.foundryName);\n if (!indexMatch) {\n logger.error(`Unable to match weapon item ${data.name}`, data);\n this.bad.push({ pbName: data.pbName, type: \"weapon\", details: { w: data } });\n return null;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n itemData.system.quantity = data.qty;\n // because some shields don't have damage dice, but come in as weapons on pathbuilder\n if (itemData.type === \"weapon\") {\n if (data.die) itemData.system.damage.die = data.die;\n Pathmuncher.applyRunes(data, itemData, \"weapon\");\n }\n\n if (data.display.startsWith(\"Large \") || data.increasedDice) {\n itemData.system.size = \"lg\";\n } else if (data.display && !Seasoning.IGNORED_EQUIPMENT_DISPLAY(data.display)) {\n itemData.name = data.display;\n }\n\n this.#resizeItem(itemData);\n this.result.weapons.push(itemData);\n data.added = true;\n data.addedId = itemData._id;\n return itemData;\n }\n\n async #generateWeaponItems() {\n for (const w of this.parsed.weapons) {\n if (Seasoning.IGNORED_EQUIPMENT().includes(w.pbName)) {\n w.added = true;\n w.addedAutoId = \"ignored\";\n continue;\n }\n await this.#createWeaponItem(w);\n }\n }\n\n #adjustArmorItem(itemData, parsedArmor) {\n itemData._id = foundry.utils.randomID();\n itemData.system.equipped.value = parsedArmor.worn ?? false;\n if (!Seasoning.RESTRICTED_EQUIPMENT().some((i) => itemData.name.startsWith(i))) {\n itemData.system.equipped.inSlot = parsedArmor.worn ?? false;\n itemData.system.quantity = parsedArmor.qty;\n\n const isShield = parsedArmor.prof === \"shield\";\n itemData.system.equipped.handsHeld = isShield && parsedArmor.worn ? 1 : 0;\n itemData.system.equipped.carryType = isShield && parsedArmor.worn ? \"held\" : \"worn\";\n\n Pathmuncher.applyRunes(parsedArmor, itemData, \"armor\");\n }\n if (parsedArmor.display) itemData.name = parsedArmor.display;\n\n this.#resizeItem(itemData);\n return itemData;\n }\n\n async #generateArmorItems() {\n for (const a of this.parsed.armor) {\n if (Seasoning.IGNORED_EQUIPMENT().includes(a.pbName)) {\n a.added = true;\n a.addedAutoId = \"ignored\";\n continue;\n }\n\n logger.debug(\"Generating armor for\", a);\n if (Seasoning.GRANTED_ITEMS_LIST().includes(a.pbName)) {\n const existingItem = this.result.armor.find((i) => i.name === a.foundryName);\n if (existingItem) {\n a.added = true;\n a.addedId = existingItem._id;\n logger.debug(`Ignoring armor item ${a.pbName} as it has been granted by a feature`);\n continue;\n }\n }\n const indexMatch = this.compendiumMatchers[\"equipment\"].getMatch(a.foundryName, `${a.pbName} Armor`);\n if (!indexMatch) {\n logger.error(`Unable to match armor kit item ${a.name}`, a);\n this.bad.push({ pbName: a.pbName, type: \"armor\", details: { a } });\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const itemData = this.#adjustArmorItem(doc.toObject(), a);\n this.result.armor.push(itemData);\n a.addedId = itemData._id;\n a.added = true;\n }\n }\n\n getClassSpellCastingType(dual = false) {\n const classCaster = dual\n ? this.source.spellCasters.find((caster) => caster.name === this.source.dualClass)\n : this.source.spellCasters.find((caster) => caster.name === this.source.class);\n const type = classCaster?.spellcastingType;\n if (type || this.source.spellCasters.length === 0) return type ?? \"spontaneous\";\n // if no type and multiple spell casters, then return the first spell casting type\n return this.source.spellCasters[0].spellcastingType ?? \"spontaneous\";\n }\n\n // aims to determine the class magic tradition for a spellcasting block\n getClassMagicTradition(caster) {\n const classCaster = [this.source.class, this.source.dualClass].includes(caster.name);\n const tradition = classCaster ? caster?.magicTradition : undefined;\n // if a caster tradition or no spellcasters, return divine\n if (tradition || this.source.spellCasters.length === 0) return tradition ?? \"divine\";\n\n // not a focus traditions\n if (caster.magicTradition !== \"focus\" && [\"divine\", \"occult\", \"primal\", \"arcane\"].includes(caster.magicTradition)) {\n return caster.magicTradition;\n }\n\n // this spell caster type is not a class, determine class tradition based on ability\n const abilityTradition = this.source.spellCasters.find((c) =>\n [this.source.class, this.source.dualClass].includes(c.name)\n && c.ability === caster.ability\n );\n if (abilityTradition) return abilityTradition.magicTradition;\n // if no type and multiple spell casters, then return the first spell casting type\n return this.source.spellCasters[0].magicTradition && this.source.spellCasters[0].magicTradition !== \"focus\"\n ? this.source.spellCasters[0].magicTradition\n : \"divine\";\n }\n\n #applySpellBlending(spellcastingEntity, caster) {\n if (caster.blendedSpells.length === 0) return;\n\n const remove = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n const add = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n\n // find adjustments\n caster.blendedSpells.forEach((slot) => {\n remove[slot.levelFrom]++;\n add[slot.LevelTo]++;\n });\n\n for (let i = 0; i <= 10; i++) {\n const toAdd = this.options.adjustBlendedSlots ? 0 : Math.floor(add[i] / 2);\n const toRemove = this.options.adjustBlendedSlots ? remove[i] : 0;\n const adjustment = 0 - toRemove - toAdd;\n logger.debug(\"Adjusting spells for spell blending\", { i, adjustment, add, remove, toAdd, max: spellcastingEntity.slots[`slot${i}`].max });\n spellcastingEntity.slots[`slot${i}`].max += adjustment;\n spellcastingEntity.slots[`slot${i}`].value += adjustment;\n }\n }\n\n #generateSpellCaster(caster) {\n const isFocus = caster.magicTradition === \"focus\";\n const magicTradition = this.getClassMagicTradition(caster);\n const spellcastingType = isFocus ? \"focus\" : caster.spellcastingType;\n const flexible = false; // placeholder\n\n const name = isFocus ? `${utils.capitalize(magicTradition)} ${caster.name}` : caster.name;\n\n const spellcastingEntity = {\n ability: {\n value: caster.ability,\n },\n proficiency: {\n value: caster.proficiency / 2,\n },\n spelldc: {\n item: 0,\n },\n tradition: {\n value: magicTradition,\n },\n prepared: {\n value: spellcastingType,\n flexible,\n },\n slots: {},\n showUnpreparedSpells: { value: true },\n showSlotlessLevels: { value: true },\n };\n\n // apply slot data\n for (let i = 0; i <= 10; i++) {\n\n spellcastingEntity.slots[`slot${i}`] = {\n max: caster.perDay[i],\n prepared: {},\n value: caster.perDay[i],\n };\n }\n // adjust slots for spell blended effects\n this.#applySpellBlending(spellcastingEntity, caster);\n\n const data = {\n _id: foundry.utils.randomID(),\n name,\n type: \"spellcastingEntry\",\n system: spellcastingEntity,\n };\n this.result.casters.push(data);\n return data;\n }\n\n #generateFocusSpellCaster(proficiency, ability, tradition) {\n const data = {\n _id: foundry.utils.randomID(),\n name: `${utils.capitalize(tradition)} Focus Tradition`,\n type: \"spellcastingEntry\",\n system: {\n ability: {\n value: ability,\n },\n proficiency: {\n value: proficiency / 2,\n },\n spelldc: {\n item: 0,\n },\n tradition: {\n value: tradition,\n },\n prepared: {\n value: \"focus\",\n flexible: false,\n },\n showUnpreparedSpells: { value: true },\n },\n };\n this.result.casters.push(data);\n return data;\n }\n\n async #loadSpell(spell, casterId, debugData) {\n const spellName = spellRename(spell.split(\"(\")[0].trim());\n logger.debug(\"focus spell details\", { spell, spellName, debugData });\n\n const indexMatch = this.compendiumMatchers[\"spells\"].getMatch(spell, spellName, true);\n if (!indexMatch) {\n if (debugData.psychicAmpSpell) return undefined;\n logger.error(`Unable to match focus spell ${spell}`, { spell, spellName, debugData });\n this.bad.push({ pbName: spell, type: \"spell\", details: { originalName: spell, name: spellName, debugData } });\n return undefined;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n itemData.system.location.value = casterId;\n\n return itemData;\n }\n\n // eslint-disable-next-line complexity\n async #processCasterSpells(instance, caster, spellEnhancements, forcePrepare = false) {\n const spellNames = {};\n for (const spellSelection of caster.spells) {\n const level = spellSelection.spellLevel;\n const preparedAtLevel = caster.prepared?.length > 0\n ? (caster.prepared.find((p) => p.spellLevel === level)?.list ?? [])\n : [];\n let preparedValue = 0;\n\n // const preparedMap = preparedAtLevel.reduce((acc, e) => acc.set(e, (acc.get(e) || 0) + 1), new Map());\n\n for (const [i, spell] of spellSelection.list.entries()) {\n logger.debug(`Checking spell at ${i} for level ${level}`, { spell });\n const itemData = await this.#loadSpell(spell, instance._id, {\n spellSelection,\n list: spellSelection.list,\n level,\n instance,\n });\n if (itemData) {\n itemData.system.location.heightenedLevel = level;\n spellNames[spell] = itemData._id;\n this.result.spells.push(itemData);\n\n // if the caster is prepared we don't prepare spells as all known spells come through in JSON\n if (instance.system.prepared.value !== \"prepared\"\n || spellEnhancements?.preparePBSpells\n || forcePrepare\n || (caster.spellcastingType === \"prepared\"\n && preparedAtLevel.length === 0 && spellSelection.list.length <= caster.perDay[level])\n ) {\n logger.debug(`Preparing spell ${itemData.name} for level ${level}`, { spell });\n // eslint-disable-next-line require-atomic-updates\n instance.system.slots[`slot${level}`].prepared[preparedValue] = { id: itemData._id };\n preparedValue++;\n }\n }\n }\n\n for (const spell of preparedAtLevel) {\n // if (spellNames.includes(spellName)) continue;\n const parsedSpell = getProperty(spellNames, spell);\n const itemData = parsedSpell\n ? this.result.spells.find((s) => s._id === parsedSpell)\n : await this.#loadSpell(spell, instance._id, {\n spellSelection,\n level,\n instance,\n });\n if (itemData) {\n itemData.system.location.heightenedLevel = level;\n if (itemData && !parsedSpell) {\n spellNames[spell] = itemData._id;\n this.result.spells.push(itemData);\n }\n\n logger.debug(`Preparing spell ${itemData.name} for level ${level}`, { spellName: spell });\n // eslint-disable-next-line require-atomic-updates\n instance.system.slots[`slot${level}`].prepared[preparedValue] = { id: itemData._id };\n preparedValue++;\n } else {\n logger.warn(`Unable to find spell ${spell}`);\n }\n }\n\n if (spellEnhancements?.knownSpells) {\n for (const spell of spellEnhancements.knownSpells) {\n const itemData = await this.#loadSpell(spell, instance._id, {\n spellEnhancements,\n instance,\n });\n if (itemData && !hasProperty(spellNames, itemData.name)) {\n itemData.system.location.heightenedLevel = level;\n spellNames[spell] = itemData._id;\n this.result.spells.push(itemData);\n }\n }\n }\n }\n }\n\n async #processFocusSpells(instance, spells) {\n for (const spell of spells) {\n const itemData = await this.#loadSpell(spell, instance._id, {\n instance,\n spells,\n spell,\n });\n if (itemData) this.result.spells.push(itemData);\n if (spell.endsWith(\"(Amped)\")) {\n const psychicSpell = spell.replace(\"(Amped)\", \"(Psychic)\");\n const psychicItemData = await this.#loadSpell(psychicSpell, instance._id, {\n instance,\n spells,\n spell: psychicSpell,\n psychicAmpSpell: true,\n });\n if (psychicItemData) {\n this.result.spells.push(psychicItemData);\n }\n }\n }\n }\n\n async #processRituals() {\n if (!this.source.rituals) return;\n const ritualCompendium = new CompendiumMatcher({\n type: \"spells\",\n indexFields: [\"name\", \"type\", \"system.slug\", \"system.ritual\"],\n });\n await ritualCompendium.loadCompendiums();\n\n for (const ritual of this.source.rituals) {\n const ritualName = ritual.split(\"(\")[0].trim();\n logger.debug(\"focus spell details\", { ritual, spellName: ritualName });\n\n const indexMatch = this.compendiumMatchers[\"spells\"].getNameMatchWithFilter(ritualName, ritualName);\n if (!indexMatch || !hasProperty(indexMatch, \"system.ritual\")) {\n logger.error(`Unable to match ritual spell ${ritual}`, { spell: ritual, spellName: ritualName });\n this.bad.push({ pbName: ritual, type: \"spell\", details: { originalName: ritual, name: ritualName } });\n continue;\n }\n\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n\n this.result.spells.push(itemData);\n }\n }\n\n async #processSpells() {\n for (const caster of this.source.spellCasters) {\n logger.debug(\"Generating caster for\", caster);\n if (Number.isInteger(parseInt(caster.focusPoints))) this.result.focusPool += caster.focusPoints;\n const instance = this.#generateSpellCaster(caster);\n logger.debug(\"Generated caster instance\", instance);\n const spellEnhancements = Seasoning.getSpellCastingFeatureAdjustment(caster.name);\n let forcePrepare = false;\n if (hasProperty(spellEnhancements, \"showSlotless\")) {\n instance.system.showSlotlessLevels.value = getProperty(spellEnhancements, \"showSlotless\");\n } else if (\n caster.spellcastingType === \"prepared\"\n && ![this.source.class, this.source.dualClass].includes(caster.name)\n ) {\n const slotToPreparedMatch = caster.spells.every((spellBlock) => {\n const spellCount = spellBlock.list.length;\n const perDay = caster.perDay[spellBlock.spellLevel];\n return perDay === spellCount;\n });\n logger.debug(`Setting ${caster.name} show all slots to ${!slotToPreparedMatch}`);\n instance.system.showSlotlessLevels.value = !slotToPreparedMatch;\n forcePrepare = slotToPreparedMatch;\n }\n await this.#processCasterSpells(instance, caster, spellEnhancements, forcePrepare);\n }\n\n for (const tradition of [\"occult\", \"primal\", \"divine\", \"arcane\"]) {\n const traditionData = getProperty(this.source, `focus.${tradition}`);\n logger.debug(`Checking for focus tradition ${tradition}`);\n if (!traditionData) continue;\n for (const ability of [\"str\", \"dex\", \"con\", \"int\", \"wis\", \"cha\"]) {\n const abilityData = getProperty(traditionData, ability);\n logger.debug(`Checking for focus tradition ${tradition} with ability ${ability}`);\n if (!abilityData) continue;\n logger.debug(\"Generating focus spellcasting \", { tradition, traditionData, ability });\n const instance = this.#generateFocusSpellCaster(abilityData.proficiency, ability, tradition);\n if (abilityData.focusCantrips && abilityData.focusCantrips.length > 0) {\n await this.#processFocusSpells(instance, abilityData.focusCantrips);\n }\n if (abilityData.focusSpells && abilityData.focusSpells.length > 0) {\n await this.#processFocusSpells(instance, abilityData.focusSpells);\n }\n }\n }\n\n setProperty(this.result.character, \"system.resources.focus.max\", this.source.focusPoints);\n setProperty(this.result.character, \"system.resources.focus.value\", this.source.focusPoints);\n }\n\n async #generateLores() {\n for (const lore of this.source.lores) {\n const data = {\n name: lore[0],\n type: \"lore\",\n system: {\n proficient: {\n value: lore[1] / 2,\n },\n featType: \"\",\n mod: {\n value: 0,\n },\n item: {\n value: 0,\n },\n },\n };\n this.result.lores.push(data);\n }\n }\n\n async #generateMoney() {\n const compendium = game.packs.get(\"pf2e.equipment-srd\");\n const index = await compendium.getIndex({ fields: [\"name\", \"type\", \"system.slug\"] });\n const moneyLookup = [\n { slug: \"platinum-pieces\", type: \"pp\" },\n { slug: \"gold-pieces\", type: \"gp\" },\n { slug: \"silver-pieces\", type: \"sp\" },\n { slug: \"copper-pieces\", type: \"cp\" },\n ];\n\n for (const lookup of moneyLookup) {\n const indexMatch = index.find((i) => i.system.slug === lookup.slug);\n if (indexMatch) {\n const doc = await compendium.getDocument(indexMatch._id);\n const itemData = doc.toObject();\n itemData._id = foundry.utils.randomID();\n itemData.system.quantity = this.source.money[lookup.type];\n this.result.money.push(itemData);\n }\n }\n }\n\n async #processFormulas() {\n const uuids = [];\n\n for (const formulaSource of this.source.formula) {\n for (const formulaName of formulaSource.known) {\n const indexMatch = this.compendiumMatchers[\"formulas\"].getMatch(formulaName, formulaName);\n if (!indexMatch) {\n logger.error(`Unable to match formula ${formulaName}`, { formulaSource, name: formulaName });\n this.bad.push({ pbName: formulaName, type: \"formula\", details: { formulaSource, name: formulaName } });\n continue;\n }\n const doc = await indexMatch.pack.getDocument(indexMatch.i._id);\n uuids.push({ uuid: doc.uuid });\n }\n }\n setProperty(this.result.character, \"system.crafting.formulas\", uuids);\n }\n\n async #processFeats() {\n this.#sortParsedFeats();\n // pre pass for standard items\n for (let i = 1; i <= this.result.character.system.details.level.value; i++) {\n await this.#generateFeatItems(\"feats\", { typeFilter: \"Ancestry Feat\", levelCap: i, excludeChild: true, excludeParents: true });\n await this.#generateFeatItems(\"feats\", { typeFilter: \"Skill Feat\", levelCap: i, excludeChild: true, excludeParents: true });\n await this.#generateFeatItems(\"feats\", { typeFilter: \"Class Feat\", levelCap: i, excludeChild: true, excludeParents: true });\n await this.#generateFeatItems(\"feats\", { typeFilter: \"General Feat\", levelCap: i, excludeChild: true, excludeParents: true });\n }\n await this.#generateFeatItems(\"ancestryFeatures\", { excludeChild: true, excludeParents: true });\n // prepass for non-child items\n for (let i = 1; i <= this.result.character.system.details.level.value; i++) {\n await this.#generateFeatItems(\"feats\", { typeFilter: \"Ancestry Feat\", levelCap: i, excludeChild: true });\n await this.#generateFeatItems(\"feats\", { typeFilter: \"Skill Feat\", levelCap: i, excludeChild: true });\n await this.#generateFeatItems(\"feats\", { typeFilter: \"Class Feat\", levelCap: i, excludeChild: true });\n await this.#generateFeatItems(\"feats\", { typeFilter: \"General Feat\", levelCap: i, excludeChild: true });\n await this.#generateFeatItems(\"feats\", { typeFilter: \"Archetype Feat\", levelCap: i, excludeChild: true });\n }\n await this.#generateFeatItems(\"ancestryFeatures\", { excludeChild: true });\n\n this.#setSkills();\n // final pass, include all\n this.#statusUpdate(1, 5, \"Feats\");\n await this.#generateFeatItems(\"feats\");\n this.#statusUpdate(2, 5, \"Feats\");\n await this.#generateFeatItems(\"ancestryFeatures\");\n this.#statusUpdate(3, 5, \"Feats\");\n await this.#generateSpecialItems(\"ancestryFeatures\");\n this.#statusUpdate(4, 5, \"Feats\");\n await this.#generateSpecialItems(\"classFeatures\");\n this.#statusUpdate(5, 5, \"Feats\");\n await this.#generateSpecialItems(\"actions\");\n }\n\n async #processEquipment() {\n this.#statusUpdate(1, 4, \"Equipment\");\n await this.#processEquipmentItems();\n this.#statusUpdate(2, 4, \"Weapons\");\n await this.#generateWeaponItems();\n this.#statusUpdate(3, 4, \"Armor\");\n await this.#generateArmorItems();\n this.#statusUpdate(2, 4, \"Money\");\n await this.#generateMoney();\n }\n\n async #generateTempActor(documents = [], includePassedDocumentsRules = false, includeGrants = false, includeFlagsOnly = false) {\n const actorData = mergeObject({ type: \"character\" }, this.result.character);\n actorData.name = `Mr Temp (${this.result.character.name})`;\n if (documents.map((d) => d.name.split(\"(\")[0].trim().toLowerCase()).includes(\"skill training\")) {\n delete actorData.system.skills;\n }\n\n const actor = await Actor.create(actorData, { renderSheet: false });\n const currentState = duplicate(this.result);\n\n // console.warn(\"Initial temp actor\", deepClone(actor));\n\n const currentItems = [\n ...currentState.deity,\n ...currentState.ancestry,\n ...currentState.heritage,\n ...currentState.background,\n ...currentState.class,\n ...currentState.lores,\n ...currentState.feats,\n ...currentState.casters,\n // ...currentState.spells,\n // ...currentState.equipment,\n // ...currentState.weapons,\n // ...currentState.armor,\n // ...currentState.treasure,\n // ...currentState.money,\n ];\n for (const doc of documents) {\n if (!currentItems.some((d) => d._id === doc._id)) {\n currentItems.push(deepClone(doc));\n }\n }\n try {\n // if the rule selected is an object, id doesn't take on import\n const ruleUpdates = [];\n for (const i of deepClone(currentItems)) {\n if (!i.system.rules || i.system.rules.length === 0) continue;\n const isPassedDocument = documents.some((d) => d._id === i._id);\n if (isPassedDocument && !includePassedDocumentsRules && !includeFlagsOnly) continue;\n\n const objectSelectionRules = i.system.rules\n .filter((r) => {\n const evaluateRules = [\"RollOption\", \"ChoiceSet\"].includes(r.key) && r.selection;\n return !includeFlagsOnly || evaluateRules; // && [\"RollOption\", \"GrantItem\", \"ChoiceSet\", \"ActiveEffectLike\"].includes(r.key);\n // || ([\"ChoiceSet\"].includes(r.key) && r.selection);\n })\n .map((r) => {\n r.ignored = false;\n return r;\n });\n\n if (objectSelectionRules.length > 0) {\n ruleUpdates.push({\n _id: i._id,\n system: {\n rules: objectSelectionRules,\n },\n });\n }\n }\n\n // console.warn(\"Rule updates\", duplicate(ruleUpdates));\n\n const items = duplicate(currentItems).map((i) => {\n if (i.system.items) i.system.items = [];\n if (i.system.rules) {\n i.system.rules = i.system.rules\n .filter((r) => {\n const isPassedDocument = documents.some((d) => d._id === i._id);\n const isChoiceSetSelection = [\"ChoiceSet\"].includes(r.key) && r.selection;\n // const choiceSetSelectionObject = isChoiceSetSelection && utils.isObject(r.selection);\n const choiceSetSelectionNotObject = isChoiceSetSelection && !utils.isObject(r.selection);\n // const grantRuleWithFlag = includeGrants && [\"GrantItem\"].includes(r.key) && r.flag;\n const grantRuleWithoutFlag = includeGrants && [\"GrantItem\"].includes(r.key) && !r.flag;\n // const genericDiscardRule = [\"ChoiceSet\", \"GrantItem\", \"ActiveEffectLike\", \"Resistance\", \"Strike\", \"AdjustModifier\"].includes(r.key);\n const genericDiscardRule = [\"ChoiceSet\", \"GrantItem\"].includes(r.key);\n const grantRuleFromItemFlag\n = includeGrants && [\"GrantItem\"].includes(r.key) && r.uuid.startsWith(\"{item|flags\");\n const rollOptionsRule = [\"RollOption\"].includes(r.key);\n\n const notPassedDocumentRules\n = !isPassedDocument\n && (choiceSetSelectionNotObject\n // || grantRuleWithFlag\n || grantRuleWithoutFlag\n || !genericDiscardRule);\n\n const passedDocumentRules\n = isPassedDocument\n && includePassedDocumentsRules\n && (isChoiceSetSelection || grantRuleWithoutFlag || grantRuleFromItemFlag || rollOptionsRule);\n\n return notPassedDocumentRules || passedDocumentRules;\n })\n .map((r) => {\n // if choices is a string or an object then we replace with the query string results\n if ((utils.isString(r.choices) || utils.isObject(r.choices)) && r.choiceQueryResults) {\n r.choices = r.choiceQueryResults;\n }\n r.ignored = false;\n return r;\n });\n }\n return i;\n });\n\n // const items2 = duplicate(currentItems).map((i) => {\n // if (i.system.items) i.system.items = [];\n // if (i.system.rules) i.system.rules = i.system.rules.filter((r) =>\n // (!documents.some((d) => d._id === i._id)\n // && (([\"ChoiceSet\",].includes(r.key) && r.selection)\n // // || ([\"GrantItem\"].includes(r.key) && r.flag)\n // || ![\"ChoiceSet\", \"GrantItem\"].includes(r.key)\n // ))\n // || (includePassedDocumentsRules && documents.some((d) => d._id === i._id) && [\"ChoiceSet\",].includes(r.key) && r.selection)\n // ).map((r) => {\n // if ((typeof r.choices === 'string' || r.choices instanceof String)\n // || (typeof r.choices === 'object' && !Array.isArray(r.choices) && r.choices !== null && r.choiceQueryResults)\n // ) {\n // r.choices = r.choiceQueryResults;\n // }\n // r.ignored = false;\n // return r;\n // });\n // return i;\n // });\n\n // console.warn(\"temp items\", {\n // documents: deepClone(currentItems),\n // items: deepClone(items),\n // // items2: deepClone(items2),\n // // diff: diffObject(items, items2),\n // includePassedDocumentsRules,\n // includeGrants,\n // });\n await actor.createEmbeddedDocuments(\"Item\", items, { keepId: true });\n // console.warn(\"restoring selection rules to temp items\", ruleUpdates);\n await actor.updateEmbeddedDocuments(\"Item\", ruleUpdates);\n\n const itemUpdates = [];\n for (const [key, value] of Object.entries(this.autoAddedFeatureItems)) {\n itemUpdates.push({\n _id: `${key}`,\n system: {\n items: deepClone(value),\n },\n });\n }\n\n // console.warn(\"restoring feature items to temp items\", itemUpdates);\n await actor.updateEmbeddedDocuments(\"Item\", itemUpdates);\n\n logger.debug(\"Final temp actor\", actor);\n } catch (err) {\n logger.error(\"Temp actor creation failed\", {\n actor,\n documents,\n thisData: deepClone(this.result),\n actorData,\n err,\n currentItems,\n this: this,\n });\n }\n return actor;\n }\n\n async processCharacter() {\n if (!this.source) return;\n await this.#prepare();\n this.#statusUpdate(1, 12, \"Character\");\n await this.#processCore();\n this.#statusUpdate(2, 12, \"Formula\");\n await this.#processFormulas();\n this.#statusUpdate(3, 12, \"Deity\");\n await this.#processGenericCompendiumLookup(\"deities\", this.source.deity, \"deity\");\n\n this.#statusUpdate(4, 12, \"Ancestry\");\n await this.#processGenericCompendiumLookup(\"ancestries\", this.source.ancestry, \"ancestry\");\n this.#statusUpdate(5, 12, \"Heritage\");\n await this.#processGenericCompendiumLookup(\"heritages\", this.source.heritage, \"heritage\");\n this.#statusUpdate(6, 12, \"Background\");\n await this.#processGenericCompendiumLookup(\"backgrounds\", this.source.background, \"background\");\n\n this.#setSkills(true);\n\n this.#statusUpdate(7, 12, \"Class\");\n await this.#processGenericCompendiumLookup(\"classes\", this.source.class, \"class\");\n\n this.#setAbilityBoosts();\n\n this.#statusUpdate(8, 12, \"FeatureRec\");\n await this.#processFeats();\n this.#statusUpdate(10, 12, \"Equipment\");\n await this.#processEquipment();\n this.#statusUpdate(11, 12, \"Spells\");\n await this.#processSpells();\n this.#statusUpdate(11, 12, \"Rituals\");\n await this.#processRituals();\n this.#statusUpdate(12, 12, \"Lores\");\n await this.#generateLores();\n }\n\n async #removeDocumentsToBeUpdated() {\n const moneyIds = this.actor.items.filter((i) =>\n i.type === \"treasure\"\n && [\"Platinum Pieces\", \"Gold Pieces\", \"Silver Pieces\", \"Copper Pieces\"].includes(i.name)\n );\n const classIds = this.actor.items.filter((i) => i.type === \"class\").map((i) => i._id);\n const deityIds = this.actor.items.filter((i) => i.type === \"deity\").map((i) => i._id);\n const backgroundIds = this.actor.items.filter((i) => i.type === \"background\").map((i) => i._id);\n const heritageIds = this.actor.items.filter((i) => i.type === \"heritage\").map((i) => i._id);\n const ancestryIds = this.actor.items.filter((i) => i.type === \"ancestry\").map((i) => i._id);\n const treasureIds = this.actor.items\n .filter((i) => i.type === \"treasure\" && !moneyIds.includes(i.id))\n .map((i) => i._id);\n const featIds = this.actor.items.filter((i) => i.type === \"feat\").map((i) => i._id);\n const actionIds = this.actor.items.filter((i) => i.type === \"action\").map((i) => i._id);\n const equipmentIds = this.actor.items\n .filter((i) => i.type === \"equipment\" || i.type === \"backpack\" || i.type === \"consumable\")\n .map((i) => i._id);\n const weaponIds = this.actor.items.filter((i) => i.type === \"weapon\").map((i) => i._id);\n const armorIds = this.actor.items.filter((i) => i.type === \"armor\").map((i) => i._id);\n const loreIds = this.actor.items.filter((i) => i.type === \"lore\").map((i) => i._id);\n const spellIds = this.actor.items\n .filter((i) => i.type === \"spell\" || i.type === \"spellcastingEntry\")\n .map((i) => i._id);\n const formulaIds = this.actor.system.formulas;\n\n logger.debug(\"ids\", {\n moneyIds,\n deityIds,\n classIds,\n backgroundIds,\n heritageIds,\n ancestryIds,\n treasureIds,\n featIds,\n actionIds,\n equipmentIds,\n weaponIds,\n armorIds,\n loreIds,\n spellIds,\n formulaIds,\n });\n // eslint-disable-next-line complexity\n const keepIds = this.actor.items.filter((i) =>\n (!this.options.addMoney && moneyIds.includes(i._id))\n || (!this.options.addClass && classIds.includes(i._id))\n || (!this.options.addDeity && deityIds.includes(i._id))\n || (!this.options.addBackground && backgroundIds.includes(i._id))\n || (!this.options.addHeritage && heritageIds.includes(i._id))\n || (!this.options.addAncestry && ancestryIds.includes(i._id))\n || (!this.options.addTreasure && treasureIds.includes(i._id))\n || (!this.options.addFeats && (featIds.includes(i._id) || actionIds.includes(i._id)))\n || (!this.options.addEquipment && equipmentIds.includes(i._id))\n || (!this.options.addWeapons && weaponIds.includes(i._id))\n || (!this.options.addArmor && armorIds.includes(i._id))\n || (!this.options.addLores && loreIds.includes(i._id))\n || (!this.options.addSpells && spellIds.includes(i._id))\n ).map((i) => i._id);\n\n const deleteIds = this.actor.items.filter((i) => !keepIds.includes(i._id)).map((i) => i._id);\n logger.debug(\"ids\", {\n deleteIds,\n keepIds,\n });\n await this.actor.deleteEmbeddedDocuments(\"Item\", deleteIds);\n }\n\n async #createAndUpdateItemsWithRuleRestore(items) {\n const ruleUpdates = [];\n\n const newItems = deepClone(items);\n\n for (const item of newItems) {\n if (item.system.rules?.length > 0) {\n ruleUpdates.push({\n _id: item._id,\n system: {\n rules: deepClone(item.system.rules).map((r) => {\n delete r.choiceQueryResults;\n return r;\n }),\n },\n });\n item.system.rules = item.system.rules\n .filter((r) => {\n const excludedKeys = [\"ActiveEffectLike\", \"AdjustModifier\", \"Resistance\", \"Strike\"].includes(r.key);\n const grantItemWithFlags = [\"GrantItem\"].includes(r.key) && (hasProperty(r, \"flag\") || getProperty(r, \"pathmuncherImport\"));\n const objectSelection = [\"ChoiceSet\"].includes(r.key) && utils.isObject(r.selection);\n return !excludedKeys && !grantItemWithFlags && !objectSelection;\n })\n .map((r) => {\n if (r.key === \"ChoiceSet\") {\n if ((utils.isString(r.choices) || utils.isObject(r.choices)) && r.choiceQueryResults) {\n r.choices = r.choiceQueryResults;\n }\n }\n if (r.pathmuncherImport) delete r.pathmuncherImport;\n return r;\n });\n }\n }\n\n logger.debug(\"Creating items\", newItems);\n await this.actor.createEmbeddedDocuments(\"Item\", newItems, { keepId: true });\n logger.debug(\"Rule updates\", ruleUpdates);\n await this.actor.updateEmbeddedDocuments(\"Item\", ruleUpdates);\n }\n\n async #updateItems(type) {\n logger.debug(`Updating ${type}`, this.result[type]);\n await this.actor.updateEmbeddedDocuments(\"Item\", this.result[type]);\n }\n\n async #createActorEmbeddedDocuments() {\n this.#statusUpdate(1, 12, \"Character\", \"Eating\");\n if (this.options.addDeity) await this.#createAndUpdateItemsWithRuleRestore(this.result.deity);\n if (this.options.addAncestry) await this.#createAndUpdateItemsWithRuleRestore(this.result.ancestry);\n if (this.options.addHeritage) await this.#createAndUpdateItemsWithRuleRestore(this.result.heritage);\n if (this.options.addBackground) await this.#createAndUpdateItemsWithRuleRestore(this.result.background);\n if (this.options.addClass) await this.#createAndUpdateItemsWithRuleRestore(this.result.class);\n if (this.options.addLores) await this.#createAndUpdateItemsWithRuleRestore(this.result.lores);\n\n const featNums = this.result.feats.length;\n if (this.options.addFeats) {\n for (const [i, feat] of this.result.feats.entries()) {\n // console.warn(`creating ${feat.name}`, feat);\n this.#statusUpdate(i, featNums, \"Feats\", \"Eating\");\n await this.#createAndUpdateItemsWithRuleRestore([feat]);\n }\n }\n // if (this.options.addFeats) await this.#createAndUpdateItemsWithRuleRestore(this.result.feats);\n if (this.options.addSpells) {\n this.#statusUpdate(3, 12, \"Spells\", \"Eating\");\n await this.#createAndUpdateItemsWithRuleRestore(this.result.casters);\n await this.#createAndUpdateItemsWithRuleRestore(this.result.spells);\n }\n this.#statusUpdate(4, 12, \"Equipment\", \"Eating\");\n if (this.options.addEquipment) {\n await this.#createAndUpdateItemsWithRuleRestore(this.result.equipment);\n await this.#updateItems(\"equipment\");\n }\n if (this.options.addWeapons) await this.#createAndUpdateItemsWithRuleRestore(this.result.weapons);\n if (this.options.addArmor) {\n await this.#createAndUpdateItemsWithRuleRestore(this.result.armor);\n await this.#updateItems(\"armor\");\n }\n if (this.options.addTreasure) await this.#createAndUpdateItemsWithRuleRestore(this.result.treasure);\n if (this.options.addMoney) await this.#createAndUpdateItemsWithRuleRestore(this.result.money);\n }\n\n async #restoreEmbeddedRuleLogic() {\n const importedItems = this.actor.items.map((i) => i._id);\n // Loop back over items and add rule and item progression data back in.\n logger.debug(\"Restoring logic\", { currentActor: duplicate(this.actor) });\n const itemUpdates = [];\n for (const [key, value] of Object.entries(this.autoAddedFeatureItems)) {\n if (importedItems.includes(key)) {\n itemUpdates.push({\n _id: `${key}`,\n system: {\n items: deepClone(value),\n },\n });\n }\n }\n this.#statusUpdate(1, 12, \"Feats\", \"Clearing\");\n logger.debug(\"Restoring granted item logic\", itemUpdates);\n await this.actor.updateEmbeddedDocuments(\"Item\", itemUpdates);\n\n await this.actor.update({\n \"system.resources.focus\": this.result.character.system.resources.focus,\n });\n }\n\n async updateActor() {\n await this.#removeDocumentsToBeUpdated();\n\n if (!this.options.addName) {\n delete this.result.character.name;\n delete this.result.character.prototypeToken.name;\n }\n if (!this.options.addFormulas) {\n delete this.result.character.system.formulas;\n }\n\n if (!this.boosts.custom) {\n setProperty(this.result.character, `system.abilities`, null);\n }\n\n logger.debug(\"Generated result\", this.result);\n await this.actor.update(this.result.character);\n await this.#createActorEmbeddedDocuments();\n await this.#restoreEmbeddedRuleLogic();\n }\n\n async postImportCheck() {\n const badClass = this.options.addClass\n ? this.bad.filter((b) => b.type === \"class\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Class\")}: ${b.pbName}</li>`)\n : [];\n const badHeritage = this.options.addHeritage\n ? this.bad.filter((b) => b.type === \"heritage\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Heritage\")}: ${b.pbName}</li>`)\n : [];\n const badAncestry = this.options.addAncestry\n ? this.bad.filter((b) => b.type === \"ancestry\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Ancestry\")}: ${b.pbName}</li>`)\n : [];\n const badBackground = this.options.addBackground\n ? this.bad.filter((b) => b.type === \"background\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Background\")}: ${b.pbName}</li>`)\n : [];\n const badDeity = this.options.addDeity\n ? this.bad.filter((b) => b.type === \"deity\" && b.pbName !== \"Not set\" && b.pbName !== \"\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Deity\")}: ${b.pbName}</li>`)\n : [];\n const badFeats = this.options.addFeats\n ? this.bad.filter((b) => b.type === \"feat\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Feats\")}: ${b.pbName}</li>`)\n : [];\n const badFeats2 = this.options.addFeats\n ? Object.values(this.check).filter((b) =>\n b.type === \"feat\"\n && this.parsed.feats.some((f) => f.name === b.details.name && !f.added)\n ).map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Feats\")}: ${b.details.name}</li>`)\n : [];\n const badSpecials = this.options.addFeats\n ? Object.values(this.check).filter((b) =>\n (b.type === \"special\")\n && this.parsed.specials.some((f) => f.name === b.details.name && !f.added)\n ).map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Specials\")}: ${b.details.originalName}</li>`)\n : [];\n const badEquipment = this.options.addEquipment\n ? this.bad.filter((b) => b.type === \"equipment\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Equipment\")}: ${b.pbName}</li>`)\n : [];\n const badWeapons = this.options.addWeapons\n ? this.bad.filter((b) => b.type === \"weapons\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Weapons\")}: ${b.pbName}</li>`)\n : [];\n const badArmor = this.options.addArmor\n ? this.bad.filter((b) => b.type === \"armor\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Armor\")}: ${b.pbName}</li>`)\n : [];\n const badSpellcasting = this.options.addSpells\n ? this.bad.filter((b) => b.type === \"spellcasting\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Spellcasting\")}: ${b.pbName}</li>`)\n : [];\n const badSpells = this.options.addSpells\n ? this.bad.filter((b) => b.type === \"spells\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Spells\")}: ${b.pbName}</li>`)\n : [];\n const badFamiliars = this.options.addFamiliars\n ? this.bad.filter((b) => b.type === \"familiars\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Familiars\")}: ${b.pbName}</li>`)\n : [];\n const badFormulas = this.options.addFormulas\n ? this.bad.filter((b) => b.type === \"formulas\").map((b) => `<li>${game.i18n.localize(\"pathmuncher.Labels.Formulas\")}: ${b.pbName}</li>`)\n : [];\n const totalBad = [\n ...badClass,\n ...badAncestry,\n ...badHeritage,\n ...badBackground,\n ...badDeity,\n ...badFeats,\n ...badFeats2,\n ...badSpecials,\n ...badEquipment,\n ...badWeapons,\n ...badArmor,\n ...badSpellcasting,\n ...badSpells,\n ...badFamiliars,\n ...badFormulas,\n ];\n\n let warning = \"\";\n\n if (totalBad.length > 0) {\n warning += `<p>${game.i18n.localize(\"pathmuncher.Dialogs.Pathmuncher.MissingItemsOpen\")}</p><ul>${totalBad.join(\"\\n\")}</ul><br>`;\n }\n\n logger.debug(\"Bad thing check\", {\n badClass,\n badAncestry,\n badHeritage,\n badBackground,\n badDeity,\n badFeats,\n badFeats2,\n badSpecials,\n badEquipment,\n badWeapons,\n badArmor,\n badSpellcasting,\n badSpells,\n badFamiliars,\n badFormulas,\n totalBad,\n count: totalBad.length,\n focusPool: this.result.focusPool,\n warning,\n });\n\n if (totalBad.length > 0) {\n ui.notifications.warn(game.i18n.localize(\"pathmuncher.Dialogs.Pathmuncher.CompletedWithNotes\"));\n new Dialog({\n title: game.i18n.localize(\"pathmuncher.Dialogs.Pathmuncher.ImportNotes\"),\n content: warning,\n buttons: {\n yes: {\n icon: \"<i class='fas fa-check'></i>\",\n label: game.i18n.localize(\"pathmuncher.Labels.Finished\"),\n },\n },\n default: \"yes\",\n }).render(true);\n } else {\n ui.notifications.info(game.i18n.localize(\"pathmuncher.Dialogs.Pathmuncher.CompletedSuccess\"));\n }\n }\n}\n","/* eslint-disable no-await-in-loop */\n/* eslint-disable no-continue */\n\nimport CONSTANTS from \"../constants.js\";\nimport logger from \"../logger.js\";\nimport utils from \"../utils.js\";\n\n/**\n * The PetShop class looks for familiars in a Pathmunch data set and creates/updates as appropriate.\n */\nexport class PetShop {\n\n\n constructor ({ type = \"familiar\", parent, pathbuilderJson } = {}) {\n this.parent = parent;\n this.pathbuilderJson = pathbuilderJson;\n this.type = type;\n\n this.result = {\n pets: [],\n features: {},\n };\n\n this.bad = {};\n this.folders = {};\n }\n\n\n async ensureFolder(type) {\n const folderName = game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Folders.${type}`);\n this.folders[type] = await utils.getOrCreateFolder(this.parent.folder, \"Actor\", folderName);\n }\n\n async #existingPetCheck(petName, type) {\n const existingPet = game.actors.find((a) =>\n a.type === type.toLowerCase()\n && a.name === petName\n && a.system.master.id === this.parent._id\n );\n\n if (existingPet) return existingPet.toObject();\n\n const actorData = {\n type: type.toLowerCase(),\n name: petName,\n system: {\n master: {\n id: this.parent._id,\n ability: this.parent.system.details.keyability.value,\n },\n },\n prototypeToken: {\n name: petName,\n },\n folder: this.folders[type].id,\n };\n const actor = await Actor.create(actorData);\n return actor.toObject();\n\n }\n\n #buildCore(petData) {\n setProperty(petData, \"system.attributes.value\", this.parent.system.details.level.value * 5);\n return petData;\n }\n\n async #generatePetFeatures(pet, json) {\n const compendium = game.packs.get(\"pf2e.familiar-abilities\");\n const index = await compendium.getIndex({ fields: [\"name\", \"type\", \"system.slug\"] });\n this.result.features[pet._id] = [];\n this.bad[pet._id] = [];\n\n for (const featureName of json.abilities) {\n const indexMatch = index.find((i) => i.system.slug === game.pf2e.system.sluggify(featureName));\n if (!indexMatch) {\n logger.warn(`Unable to match pet feature ${featureName}`, { pet, json, name: featureName });\n this.bad[pet._id].push({ pbName: featureName, type: \"feature\", details: { pet, json, name: featureName } });\n continue;\n }\n const doc = (await compendium.getDocument(indexMatch._id)).toObject();\n doc._id = foundry.utils.randomID();\n this.result.features[pet._id].push(doc);\n }\n }\n\n async buildPet(json) {\n const name = json.name === json.type || !json.name.includes(\"(\")\n ? `${this.parent.name}'s ${json.type}`\n : json.name.split(\"(\")[1].split(\")\")[0];\n const petData = await this.#existingPetCheck(name, json.type);\n const pet = this.#buildCore(petData);\n await this.#generatePetFeatures(pet, json);\n this.result.pets.push(pet);\n }\n\n async updatePets() {\n for (const petData of this.result.pets) {\n const actor = game.actors.get(petData._id);\n await actor.deleteEmbeddedDocuments(\"Item\", [], { deleteAll: true });\n await actor.update(petData);\n await actor.createEmbeddedDocuments(\"Item\", this.result.features[petData._id], { keepId: true });\n }\n }\n\n async processPets() {\n const petData = this.type === \"familiar\" && this.pathbuilderJson.familiars\n ? this.pathbuilderJson.familiars\n : this.pathbuilderJson.pets.filter((p) => this.type === p.type.toLowerCase());\n await this.ensureFolder(utils.capitalize(this.type));\n for (const petJson of petData) {\n await this.buildPet(petJson);\n }\n\n await this.updatePets();\n\n logger.debug(\"Pets\", {\n results: this.results,\n bad: this.bad,\n });\n }\n\n async addPetEffects() {\n const features = [];\n for (const petData of this.result.pets) {\n for (const feature of this.result.features[petData._id].filter((f) => f.system.rules?.some((r) => r.key === \"ActiveEffectLike\"))) {\n if (!this.parent.items.some((i) => i.type === \"effect\" && i.system.slug === feature.system.slug)) {\n features.push(feature);\n }\n }\n }\n await this.parent.createEmbeddedDocuments(\"Item\", features);\n }\n\n}\n","import CONSTANTS from \"../constants.js\";\nimport logger from \"../logger.js\";\nimport utils from \"../utils.js\";\nimport { Pathmuncher } from \"./Pathmuncher.js\";\nimport { PetShop } from \"./PetShop.js\";\n\nexport class PathmuncherImporter extends FormApplication {\n\n constructor(options, actor) {\n super(options);\n this.actor = game.actors.get(actor.id ? actor.id : actor._id);\n this.backup = duplicate(this.actor);\n this.mode = \"number\";\n }\n\n static get defaultOptions() {\n const options = super.defaultOptions;\n options.title = game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.PathmuncherImporter.Title`);\n options.template = `${CONSTANTS.PATH}/templates/pathmuncher.hbs`;\n options.classes = [\"pathmuncher\"];\n options.id = \"pathmuncher\";\n options.width = 400;\n options.closeOnSubmit = false;\n options.tabs = [{ navSelector: \".tabs\", contentSelector: \"form\", initial: \"number\" }];\n return options;\n }\n\n /** @override */\n async getData() {\n const flags = utils.getFlags(this.actor);\n\n return {\n flags,\n id: flags?.pathbuilderId ?? \"\",\n actor: this.actor,\n };\n }\n\n /** @override */\n activateListeners(html) {\n super.activateListeners(html);\n $(\"#pathmuncher\").css(\"height\", \"auto\");\n\n $(html)\n .find('.item')\n .on(\"click\", (event) => {\n if (!event.target?.dataset?.tab) return;\n this.mode = event.target.dataset.tab;\n });\n }\n\n static _updateProgress(total, count, type, prefixLabel = \"Cooking\") {\n const localizedType = game.i18n.localize(`pathmuncher.Labels.${type}`);\n const progressBar = document.getElementById(\"pathmuncher-status\");\n progressBar.style.width = `${Math.trunc((count / total) * 100)}%`;\n progressBar.innerHTML = `<span>${game.i18n.localize(`pathmuncher.Labels.${prefixLabel}`)} (${localizedType})...</span>`;\n }\n\n async _updateObject(event, formData) {\n document.getElementById(\"pathmuncher-button\").disabled = true;\n const pathbuilderId = formData.textBoxBuildID;\n const options = {\n pathbuilderId,\n addMoney: formData.checkBoxMoney,\n addFeats: formData.checkBoxFeats,\n addSpells: formData.checkBoxSpells,\n adjustBlendedSlots: formData.checkBoxBlendedSlots,\n addEquipment: formData.checkBoxEquipment,\n addTreasure: formData.checkBoxTreasure,\n addLores: formData.checkBoxLores,\n addWeapons: formData.checkBoxWeapons,\n addArmor: formData.checkBoxArmor,\n addDeity: formData.checkBoxDeity,\n addName: formData.checkBoxName,\n addClass: formData.checkBoxClass,\n addBackground: formData.checkBoxBackground,\n addHeritage: formData.checkBoxHeritage,\n addAncestry: formData.checkBoxAncestry,\n addFamiliars: formData.checkBoxFamiliars,\n addFormulas: formData.checkBoxFormulas,\n statusCallback: PathmuncherImporter._updateProgress.bind(this),\n };\n logger.debug(\"Pathmuncher options\", options);\n\n await utils.setFlags(this.actor, options);\n\n const statusBar = document.getElementById(\"pathmuncher-import-progress\");\n statusBar.classList.toggle(\"import-hidden\");\n\n const pathmuncher = new Pathmuncher(this.actor, options);\n if (this.mode === \"number\") {\n await pathmuncher.fetchPathbuilder(pathbuilderId);\n } else if (this.mode === \"json\") {\n try {\n const jsonData = JSON.parse(formData.textBoxBuildJSON.trim());\n pathmuncher.source = jsonData.build;\n } catch (err) {\n ui.notifications.error(\"Unable to parse JSON data\");\n return;\n }\n }\n\n logger.debug(\"Pathmuncher Source\", pathmuncher.source);\n await pathmuncher.processCharacter();\n logger.debug(\"Post processed character\", pathmuncher);\n await pathmuncher.updateActor();\n logger.debug(\"Final import details\", {\n actor: this.actor,\n pathmuncher,\n options,\n pathbuilderSource: pathmuncher.source,\n pathbuilderId,\n });\n\n if (options.addFamiliars) {\n const petShop = new PetShop({\n type: \"familiar\",\n parent: this.actor,\n pathbuilderJson: pathmuncher.source\n });\n await petShop.processPets();\n await petShop.addPetEffects();\n }\n this.close();\n await pathmuncher.postImportCheck();\n }\n\n}\n","import { CompendiumMatcher } from \"../app/CompendiumMatcher.js\";\nimport { CompendiumSelector } from \"../app/CompendiumSelector.js\";\nimport { Pathmuncher } from \"../app/Pathmuncher.js\";\nimport { PathmuncherImporter } from \"../app/PathmuncherImporter.js\";\nimport { PetShop } from \"../app/PetShop.js\";\nimport { Seasoning } from \"../app/Seasoning.js\";\nimport CONSTANTS from \"../constants.js\";\nimport { EQUIPMENT_RENAME_MAP, RESTRICTED_EQUIPMENT } from \"../data/equipment.js\";\nimport { FEAT_RENAME_MAP } from \"../data/features.js\";\nimport utils from \"../utils.js\";\n\nexport function registerAPI() {\n game.modules.get(CONSTANTS.MODULE_NAME).api = {\n Pathmuncher,\n PathmuncherImporter,\n PetShop,\n CompendiumMatcher,\n Seasoning,\n CompendiumSelector,\n data: {\n generateFeatMap: FEAT_RENAME_MAP,\n equipment: EQUIPMENT_RENAME_MAP,\n restrictedEquipment: RESTRICTED_EQUIPMENT,\n feats: FEAT_RENAME_MAP(),\n },\n utils: utils,\n CONSTANTS,\n };\n}\n","import { CompendiumSelector } from \"../app/CompendiumSelector.js\";\nimport CONSTANTS from \"../constants.js\";\n\nasync function resetSettings() {\n for (const [name, data] of Object.entries(CONSTANTS.GET_DEFAULT_SETTINGS())) {\n // eslint-disable-next-line no-await-in-loop\n await game.settings.set(CONSTANTS.MODULE_NAME, name, data.default);\n }\n window.location.reload();\n}\n\nclass ResetSettingsDialog extends FormApplication {\n constructor(...args) {\n super(...args);\n // eslint-disable-next-line no-constructor-return\n return new Dialog({\n title: game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.ResetSettings.Title`),\n content: `<p class=\"${CONSTANTS.FLAG_NAME}-dialog-important\">${game.i18n.localize(\n `${CONSTANTS.FLAG_NAME}.Dialogs.ResetSettings.Content`\n )}</p>`,\n buttons: {\n confirm: {\n icon: '<i class=\"fas fa-check\"></i>',\n label: game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.ResetSettings.Confirm`),\n callback: () => {\n resetSettings();\n },\n },\n cancel: {\n icon: '<i class=\"fas fa-times\"></i>',\n label: game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Dialogs.ResetSettings.Cancel`),\n },\n },\n default: \"cancel\",\n });\n }\n}\n\nexport function registerSettings() {\n game.settings.registerMenu(CONSTANTS.MODULE_NAME, \"resetToDefaults\", {\n name: `${CONSTANTS.FLAG_NAME}.Settings.Reset.Title`,\n label: `${CONSTANTS.FLAG_NAME}.Settings.Reset.Label`,\n hint: `${CONSTANTS.FLAG_NAME}.Settings.Reset.Hint`,\n icon: \"fas fa-refresh\",\n type: ResetSettingsDialog,\n restricted: true,\n });\n\n for (const [name, data] of Object.entries(CONSTANTS.GET_DEFAULT_SETTINGS())) {\n game.settings.register(CONSTANTS.MODULE_NAME, name, data);\n }\n\n game.settings.registerMenu(CONSTANTS.MODULE_NAME, \"selectCustomCompendiums\", {\n name: `${CONSTANTS.FLAG_NAME}.Settings.UseCustomCompendiumMappings.Title`,\n label: `${CONSTANTS.FLAG_NAME}.Settings.UseCustomCompendiumMappings.Label`,\n hint: `${CONSTANTS.FLAG_NAME}.Settings.UseCustomCompendiumMappings.Hint`,\n icon: \"fas fa-book\",\n type: CompendiumSelector,\n restricted: true,\n });\n\n}\n","import { PathmuncherImporter } from \"../app/PathmuncherImporter.js\";\nimport CONSTANTS from \"../constants.js\";\nimport utils from \"../utils.js\";\n\nexport function registerSheetButton() {\n\n const trustedUsersOnly = utils.setting(\"RESTRICT_TO_TRUSTED\");\n if (trustedUsersOnly && !game.user.isTrusted) return;\n\n /**\n * Character sheets\n */\n const pcSheetNames = Object.values(CONFIG.Actor.sheetClasses.character)\n .map((sheetClass) => sheetClass.cls)\n .map((sheet) => sheet.name);\n\n pcSheetNames.forEach((sheetName) => {\n Hooks.on(\"render\" + sheetName, (app, html, data) => {\n // only for GMs or the owner of this character\n if (!data.owner || !data.actor) return;\n\n const button = $(`<a class=\"pathmuncher-open\" title=\"${CONSTANTS.MODULE_FULL_NAME}\"><i class=\"fas fa-hat-wizard\"></i> ${CONSTANTS.MODULE_FULL_NAME}</a>`);\n\n button.click(() => {\n if (game.user.can(\"ACTOR_CREATE\")) {\n const muncher = new PathmuncherImporter(PathmuncherImporter.defaultOptions, data.actor);\n muncher.render(true);\n } else {\n ui.notifications.warn(game.i18n.localize(`${CONSTANTS.FLAG_NAME}.Notifications.CreateActorPermission`), { permanent: true });\n }\n });\n\n html.closest('.app').find('.pathmuncher-open').remove();\n let titleElement = html.closest('.app').find('.window-title');\n if (!app._minimized) button.insertAfter(titleElement);\n });\n });\n\n}\n","import { registerAPI } from \"./hooks/api.js\";\nimport { registerSettings } from \"./hooks/settings.js\";\nimport { registerSheetButton } from \"./hooks/sheets.js\";\n\nHooks.once(\"init\", () => {\n registerSettings();\n});\n\nHooks.once(\"ready\", () => {\n registerSheetButton();\n registerAPI();\n});\n"],"names":[],"sourceRoot":""}
|