mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2025-12-23 08:10:38 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c067f4c17b | ||
|
|
b50584c913 | ||
|
|
d9d28c2564 | ||
|
|
8ff70d39ac | ||
|
|
51febcd66e | ||
|
|
1fde68ef46 | ||
|
|
c41c2925dc | ||
|
|
abf3e67c1b | ||
|
|
403d9fb4bf | ||
|
|
211b031633 | ||
|
|
95c3c7cfcd | ||
|
|
538c209e6d | ||
|
|
c23d9b5eb3 | ||
|
|
532a615d0f | ||
|
|
73cd5a4712 | ||
|
|
eb05596dd0 | ||
|
|
1928fd47da | ||
|
|
019ee881ea |
3
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -59,6 +59,7 @@ body:
|
|||||||
label: Version
|
label: Version
|
||||||
description: What version of EE2 are you running? You can see this in Settings -> About
|
description: What version of EE2 are you running? You can see this in Settings -> About
|
||||||
options:
|
options:
|
||||||
|
- 0.13.8
|
||||||
- 0.13.7
|
- 0.13.7
|
||||||
- 0.13.6
|
- 0.13.6
|
||||||
- 0.13.5
|
- 0.13.5
|
||||||
@@ -71,7 +72,7 @@ body:
|
|||||||
- 0.11.x
|
- 0.11.x
|
||||||
- 0.10.x
|
- 0.10.x
|
||||||
- Change me
|
- Change me
|
||||||
default: 11
|
default: 12
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|||||||
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -1,4 +1,8 @@
|
|||||||
on:
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
- 'dev'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#  Exiled Exchange 2
|
#  Exiled Exchange 2
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
// logo: 'TODO', https://github.com/vuejs/vitepress/issues/1401
|
// logo: 'TODO', https://github.com/vuejs/vitepress/issues/1401
|
||||||
appVersion: '0.13.7',
|
appVersion: '0.13.8',
|
||||||
github: {
|
github: {
|
||||||
releasesUrl: 'https://github.com/Kvan7/Exiled-Exchange-2/releases'
|
releasesUrl: 'https://github.com/Kvan7/Exiled-Exchange-2/releases'
|
||||||
},
|
},
|
||||||
|
|||||||
4
main/package-lock.json
generated
4
main/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "exiled-exchange-2",
|
"name": "exiled-exchange-2",
|
||||||
"version": "0.13.7",
|
"version": "0.13.8",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "exiled-exchange-2",
|
"name": "exiled-exchange-2",
|
||||||
"version": "0.13.7",
|
"version": "0.13.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"electron-overlay-window": "4.0.2",
|
"electron-overlay-window": "4.0.2",
|
||||||
"uiohook-napi": "1.5.x"
|
"uiohook-napi": "1.5.x"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "exiled-exchange-2",
|
"name": "exiled-exchange-2",
|
||||||
"version": "0.13.7",
|
"version": "0.13.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node build/script.mjs",
|
"dev": "node build/script.mjs",
|
||||||
|
|||||||
@@ -26,9 +26,8 @@ if (process.platform !== "darwin") {
|
|||||||
app.enableSandbox();
|
app.enableSandbox();
|
||||||
let tray: AppTray;
|
let tray: AppTray;
|
||||||
|
|
||||||
// Ensure accessibility permissions on MacOS.
|
(async () => {
|
||||||
if (process.platform === "darwin") {
|
if (process.platform === "darwin") {
|
||||||
(async () => {
|
|
||||||
async function ensureAccessibilityPermission(): Promise<boolean> {
|
async function ensureAccessibilityPermission(): Promise<boolean> {
|
||||||
if (systemPreferences.isTrustedAccessibilityClient(false)) return true;
|
if (systemPreferences.isTrustedAccessibilityClient(false)) return true;
|
||||||
|
|
||||||
@@ -60,77 +59,8 @@ if (process.platform === "darwin") {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("Accessibility permission granted, starting app");
|
console.log("Accessibility permission granted, starting app");
|
||||||
app.on("ready", async () => {
|
}
|
||||||
tray = new AppTray(eventPipe);
|
|
||||||
const logger = new Logger(eventPipe);
|
|
||||||
const gameLogWatcher = new GameLogWatcher(eventPipe, logger);
|
|
||||||
const gameConfig = new GameConfig(eventPipe, logger);
|
|
||||||
const poeWindow = new GameWindow();
|
|
||||||
const appUpdater = new AppUpdater(eventPipe);
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const _httpProxy = new HttpProxy(server, logger);
|
|
||||||
|
|
||||||
if (process.env.VITE_DEV_SERVER_URL) {
|
|
||||||
try {
|
|
||||||
await installExtension(VUEJS_DEVTOOLS);
|
|
||||||
logger.write("info Vue Devtools installed");
|
|
||||||
} catch (error) {
|
|
||||||
logger.write(`error installing Vue Devtools: ${error}`);
|
|
||||||
console.log(`error installing Vue Devtools: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
process.addListener("uncaughtException", (err) => {
|
|
||||||
logger.write(`error [uncaughtException] ${err.message}, ${err.stack}`);
|
|
||||||
});
|
|
||||||
process.addListener("unhandledRejection", (reason) => {
|
|
||||||
logger.write(`error [unhandledRejection] ${(reason as Error).stack}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(
|
|
||||||
async () => {
|
|
||||||
const overlay = new OverlayWindow(eventPipe, logger, poeWindow);
|
|
||||||
// eslint-disable-next-line no-new
|
|
||||||
new OverlayVisibility(eventPipe, overlay, gameConfig);
|
|
||||||
const shortcuts = await Shortcuts.create(
|
|
||||||
logger,
|
|
||||||
overlay,
|
|
||||||
poeWindow,
|
|
||||||
gameConfig,
|
|
||||||
eventPipe,
|
|
||||||
);
|
|
||||||
eventPipe.onEventAnyClient(
|
|
||||||
"CLIENT->MAIN::update-host-config",
|
|
||||||
(cfg) => {
|
|
||||||
overlay.updateOpts(cfg.overlayKey, cfg.windowTitle);
|
|
||||||
shortcuts.updateActions(
|
|
||||||
cfg.shortcuts,
|
|
||||||
cfg.stashScroll,
|
|
||||||
cfg.logKeys,
|
|
||||||
cfg.restoreClipboard,
|
|
||||||
cfg.language,
|
|
||||||
);
|
|
||||||
gameLogWatcher.restart(cfg.clientLog ?? "", cfg.readClientLog);
|
|
||||||
gameConfig.readConfig(cfg.gameConfig ?? "");
|
|
||||||
appUpdater.checkAtStartup();
|
|
||||||
tray.overlayKey = cfg.overlayKey;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
uIOhook.start();
|
|
||||||
console.log("uIOhook started");
|
|
||||||
const port = await startServer(appUpdater, logger);
|
|
||||||
// TODO: move up (currently crashes)
|
|
||||||
logger.write(
|
|
||||||
`info ${os.type()} ${os.release} / v${app.getVersion()}`,
|
|
||||||
);
|
|
||||||
overlay.loadAppPage(port);
|
|
||||||
tray.serverPort = port;
|
|
||||||
},
|
|
||||||
// fixes(linux): window is black instead of transparent
|
|
||||||
process.platform === "linux" ? 1000 : 0,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
} else {
|
|
||||||
app.on("ready", async () => {
|
app.on("ready", async () => {
|
||||||
tray = new AppTray(eventPipe);
|
tray = new AppTray(eventPipe);
|
||||||
const logger = new Logger(eventPipe);
|
const logger = new Logger(eventPipe);
|
||||||
@@ -150,7 +80,6 @@ if (process.platform === "darwin") {
|
|||||||
console.log(`error installing Vue Devtools: ${error}`);
|
console.log(`error installing Vue Devtools: ${error}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
process.addListener("uncaughtException", (err) => {
|
process.addListener("uncaughtException", (err) => {
|
||||||
logger.write(`error [uncaughtException] ${err.message}, ${err.stack}`);
|
logger.write(`error [uncaughtException] ${err.message}, ${err.stack}`);
|
||||||
});
|
});
|
||||||
@@ -199,4 +128,4 @@ if (process.platform === "darwin") {
|
|||||||
process.platform === "linux" ? 1000 : 0,
|
process.platform === "linux" ? 1000 : 0,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
})();
|
||||||
|
|||||||
@@ -57,6 +57,7 @@
|
|||||||
"has_empty_prefix": "前綴",
|
"has_empty_prefix": "前綴",
|
||||||
"has_empty_suffix": "後綴",
|
"has_empty_suffix": "後綴",
|
||||||
"item_level": "物品等級:{0}",
|
"item_level": "物品等級:{0}",
|
||||||
|
"requires_level": "需求 等級: {0}",
|
||||||
"stock": "庫存:{0}",
|
"stock": "庫存:{0}",
|
||||||
"map_tier": "地圖階級:{0}",
|
"map_tier": "地圖階級:{0}",
|
||||||
"area_level": "區域等級:{0}",
|
"area_level": "區域等級:{0}",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
// autogenerated file, do not edit
|
||||||
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
||||||
export default {
|
export default {
|
||||||
RARITY_NORMAL: '中',
|
RARITY_NORMAL: '中',
|
||||||
@@ -159,4 +160,5 @@ export default {
|
|||||||
LOG_LEVEL_UP: /^(.*) 現在等級 (?<level>\d+)$/,
|
LOG_LEVEL_UP: /^(.*) 現在等級 (?<level>\d+)$/,
|
||||||
// [Manual]
|
// [Manual]
|
||||||
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
||||||
|
REQUIRES_LINE: /^需求: \s*(?:等級[^\d,]*(?<level>\d+))?\D*(?:(?<str>\d+)[^\d,]*力量)?\D*(?:(?<dex>\d+)[^\d,]*敏捷)?\D*(?:(?<int>\d+)[^\d,]*智慧)?$/,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@
|
|||||||
"has_empty_prefix": "Präfix",
|
"has_empty_prefix": "Präfix",
|
||||||
"has_empty_suffix": "Suffix",
|
"has_empty_suffix": "Suffix",
|
||||||
"item_level": "Gegenstandsstufe: {0}",
|
"item_level": "Gegenstandsstufe: {0}",
|
||||||
|
"requires_level": "Erfordert Stufe: {0}",
|
||||||
"stock": "Bestand: {0}",
|
"stock": "Bestand: {0}",
|
||||||
"map_tier": "Kartenstufe: {0}",
|
"map_tier": "Kartenstufe: {0}",
|
||||||
"area_level": "Gebietsstufe: {0}",
|
"area_level": "Gebietsstufe: {0}",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
// autogenerated file, do not edit
|
||||||
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
||||||
export default {
|
export default {
|
||||||
RARITY_NORMAL: 'Normal',
|
RARITY_NORMAL: 'Normal',
|
||||||
@@ -159,4 +160,5 @@ export default {
|
|||||||
LOG_LEVEL_UP: /^(.*) ist jetzt Stufe (?<level>\d+)$/,
|
LOG_LEVEL_UP: /^(.*) ist jetzt Stufe (?<level>\d+)$/,
|
||||||
// [Manual]
|
// [Manual]
|
||||||
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
||||||
|
REQUIRES_LINE: /^Erfordert: \s*(?:Stufe[^\d,]*(?<level>\d+))?\D*(?:(?<str>\d+)[^\d,]*Str)?\D*(?:(?<dex>\d+)[^\d,]*Ges )?\D*(?:(?<int>\d+)[^\d,]*Int)?$/,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@
|
|||||||
"has_empty_prefix": "Prefix",
|
"has_empty_prefix": "Prefix",
|
||||||
"has_empty_suffix": "Suffix",
|
"has_empty_suffix": "Suffix",
|
||||||
"item_level": "Item Level: {0}",
|
"item_level": "Item Level: {0}",
|
||||||
|
"requires_level": "Req. Level: {0}",
|
||||||
"stock": "Stock: {0}",
|
"stock": "Stock: {0}",
|
||||||
"map_tier": "Map Tier: {0}",
|
"map_tier": "Map Tier: {0}",
|
||||||
"area_level": "Area Level: {0}",
|
"area_level": "Area Level: {0}",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
// autogenerated file, do not edit
|
||||||
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
||||||
export default {
|
export default {
|
||||||
RARITY_NORMAL: 'Normal',
|
RARITY_NORMAL: 'Normal',
|
||||||
@@ -159,4 +160,5 @@ export default {
|
|||||||
LOG_LEVEL_UP: /^(.*) is now level (?<level>\d+)$/,
|
LOG_LEVEL_UP: /^(.*) is now level (?<level>\d+)$/,
|
||||||
// [Manual]
|
// [Manual]
|
||||||
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
||||||
|
REQUIRES_LINE: /^Requires: \s*(?:Level[^\d,]*(?<level>\d+))?\D*(?:(?<str>\d+)[^\d,]*Str)?\D*(?:(?<dex>\d+)[^\d,]*Dex)?\D*(?:(?<int>\d+)[^\d,]*Int)?$/,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@
|
|||||||
"has_empty_prefix": "Prefijo",
|
"has_empty_prefix": "Prefijo",
|
||||||
"has_empty_suffix": "Sufijo",
|
"has_empty_suffix": "Sufijo",
|
||||||
"item_level": "Nivel del objeto: {0}",
|
"item_level": "Nivel del objeto: {0}",
|
||||||
|
"requires_level": "Requiere Nivel: {0}",
|
||||||
"stock": "Inventario: {0}",
|
"stock": "Inventario: {0}",
|
||||||
"map_tier": "Nivel del mapa: {0}",
|
"map_tier": "Nivel del mapa: {0}",
|
||||||
"area_level": "Nivel del área: {0}",
|
"area_level": "Nivel del área: {0}",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
// autogenerated file, do not edit
|
||||||
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
||||||
export default {
|
export default {
|
||||||
RARITY_NORMAL: 'Normal',
|
RARITY_NORMAL: 'Normal',
|
||||||
@@ -159,4 +160,5 @@ export default {
|
|||||||
LOG_LEVEL_UP: /^(.*) es ahora nivel (?<level>\d+)$/,
|
LOG_LEVEL_UP: /^(.*) es ahora nivel (?<level>\d+)$/,
|
||||||
// [Manual]
|
// [Manual]
|
||||||
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
||||||
|
REQUIRES_LINE: /^Requiere: \s*(?:Nivel[^\d,]*(?<level>\d+))?\D*(?:(?<str>\d+)[^\d,]*Fue)?\D*(?:(?<dex>\d+)[^\d,]*Des)?\D*(?:(?<int>\d+)[^\d,]*Int)?$/,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@
|
|||||||
"has_empty_prefix": "プレフィックス",
|
"has_empty_prefix": "プレフィックス",
|
||||||
"has_empty_suffix": "サフィックス",
|
"has_empty_suffix": "サフィックス",
|
||||||
"item_level": "アイテムレベル: {0}",
|
"item_level": "アイテムレベル: {0}",
|
||||||
|
"requires_level": "装備条件 レベル: {0}",
|
||||||
"stock": "在庫: {0}",
|
"stock": "在庫: {0}",
|
||||||
"map_tier": "マップティア: {0}",
|
"map_tier": "マップティア: {0}",
|
||||||
"area_level": "エリアレベル: {0}",
|
"area_level": "エリアレベル: {0}",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
// autogenerated file, do not edit
|
||||||
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
||||||
export default {
|
export default {
|
||||||
RARITY_NORMAL: 'ノーマル',
|
RARITY_NORMAL: 'ノーマル',
|
||||||
@@ -159,4 +160,5 @@ export default {
|
|||||||
LOG_LEVEL_UP: /^(.*)は現在レベル(?<level>\d+)です$/,
|
LOG_LEVEL_UP: /^(.*)は現在レベル(?<level>\d+)です$/,
|
||||||
// [Manual]
|
// [Manual]
|
||||||
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
||||||
|
REQUIRES_LINE: /^装備条件:\s*(?:レベル[^\d,]*(?<level>\d+))?\D*(?:(?<str>\d+)[^\d,]*筋力)?\D*(?:(?<dex>\d+)[^\d,]*器用さ)?\D*(?:(?<int>\d+)[^\d,]*知性)?$/,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
"has_empty_suffix": "빈 접미어",
|
"has_empty_suffix": "빈 접미어",
|
||||||
"spirit": "정신력: {0}",
|
"spirit": "정신력: {0}",
|
||||||
"item_level": "아이템 레벨: {0}",
|
"item_level": "아이템 레벨: {0}",
|
||||||
|
"requires_level": "요구 사항 레벨: {0}",
|
||||||
"stock": "홈: {0}",
|
"stock": "홈: {0}",
|
||||||
"map_tier": "지도 등급: {0}",
|
"map_tier": "지도 등급: {0}",
|
||||||
"area_level": "지역 레벨: {0}",
|
"area_level": "지역 레벨: {0}",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
// autogenerated file, do not edit
|
||||||
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
||||||
export default {
|
export default {
|
||||||
RARITY_NORMAL: '일반',
|
RARITY_NORMAL: '일반',
|
||||||
@@ -159,4 +160,5 @@ export default {
|
|||||||
LOG_LEVEL_UP: /^(.*)의 레벨이 (?<level>\d+)이(가) 되었습니다$/,
|
LOG_LEVEL_UP: /^(.*)의 레벨이 (?<level>\d+)이(가) 되었습니다$/,
|
||||||
// [Manual]
|
// [Manual]
|
||||||
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
||||||
|
REQUIRES_LINE: /^요구 사항: \s*(?:레벨[^\d,]*(?<level>\d+))?\D*(?:(?<str>\d+)[^\d,]*힘)?\D*(?:(?<dex>\d+)[^\d,]*민첩)?\D*(?:(?<int>\d+)[^\d,]*지능)?$/,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
"has_empty_prefix": "Prefixo",
|
"has_empty_prefix": "Prefixo",
|
||||||
"has_empty_suffix": "Sufixo",
|
"has_empty_suffix": "Sufixo",
|
||||||
"item_level": "Nível do item: {0}",
|
"item_level": "Nível do item: {0}",
|
||||||
|
"requires_level": "Requer Nível: {0}",
|
||||||
"stock": "Inventário: {0}",
|
"stock": "Inventário: {0}",
|
||||||
"map_tier": "Nível do mapa: {0}",
|
"map_tier": "Nível do mapa: {0}",
|
||||||
"area_level": "Nível da área: {0}",
|
"area_level": "Nível da área: {0}",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
// autogenerated file, do not edit
|
||||||
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
||||||
export default {
|
export default {
|
||||||
RARITY_NORMAL: 'Normal',
|
RARITY_NORMAL: 'Normal',
|
||||||
@@ -159,4 +160,5 @@ export default {
|
|||||||
LOG_LEVEL_UP: /^(.*) agora está no nível (?<level>\d+)$/,
|
LOG_LEVEL_UP: /^(.*) agora está no nível (?<level>\d+)$/,
|
||||||
// [Manual]
|
// [Manual]
|
||||||
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
||||||
|
REQUIRES_LINE: /^Requer: \s*(?:Nível[^\d,]*(?<level>\d+))?\D*(?:(?<str>\d+)[^\d,]*For)?\D*(?:(?<dex>\d+)[^\d,]*Des)?\D*(?:(?<int>\d+)[^\d,]*Int)?$/,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
"has_empty_prefix": "Префикс",
|
"has_empty_prefix": "Префикс",
|
||||||
"has_empty_suffix": "Суффикс",
|
"has_empty_suffix": "Суффикс",
|
||||||
"item_level": "Ур. предмета: {0}",
|
"item_level": "Ур. предмета: {0}",
|
||||||
|
"requires_level": "Требуется Уровень: {0}",
|
||||||
"spirit": "Дух: {0}",
|
"spirit": "Дух: {0}",
|
||||||
"reload_time": "Время перезарядки: {0}",
|
"reload_time": "Время перезарядки: {0}",
|
||||||
"stock": "Запас: {0}",
|
"stock": "Запас: {0}",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
// autogenerated file, do not edit
|
||||||
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
||||||
export default {
|
export default {
|
||||||
RARITY_NORMAL: 'Обычный',
|
RARITY_NORMAL: 'Обычный',
|
||||||
@@ -159,4 +160,5 @@ export default {
|
|||||||
LOG_LEVEL_UP: /^(.*) теперь (?<level>\d+) уровня$/,
|
LOG_LEVEL_UP: /^(.*) теперь (?<level>\d+) уровня$/,
|
||||||
// [Manual]
|
// [Manual]
|
||||||
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
LOG_ZONE_GEN: /^Generating level (?<area_level>\d+) area "(?<zone>.*)" with seed (?<seed>\d+)$/,
|
||||||
|
REQUIRES_LINE: /^Требуется: \s*(?:Уровень[^\d,]*(?<level>\d+))?\D*(?:(?<str>\d+)[^\d,]*Сила)?\D*(?:(?<dex>\d+)[^\d,]*Ловк)?\D*(?:(?<int>\d+)[^\d,]*Инт)?$/,
|
||||||
}
|
}
|
||||||
|
|||||||
73
renderer/specs/Parser/fractureParsers.test.ts
Normal file
73
renderer/specs/Parser/fractureParsers.test.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import { __testExports, ParserState } from "@/parser/Parser";
|
||||||
|
import { beforeEach, describe, expect, it } from "vitest";
|
||||||
|
import { setupTests } from "@specs/vitest.setup";
|
||||||
|
import {
|
||||||
|
FracturedItem,
|
||||||
|
FracturedItemNoModMarked,
|
||||||
|
RareItem,
|
||||||
|
TestItem,
|
||||||
|
} from "./items";
|
||||||
|
import { loadForLang } from "@/assets/data";
|
||||||
|
import { ParsedItem } from "@/parser/ParsedItem";
|
||||||
|
import { ModifierType } from "@/parser/modifiers";
|
||||||
|
|
||||||
|
describe("Parse Fractured Items", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
setupTests();
|
||||||
|
await loadForLang("en");
|
||||||
|
});
|
||||||
|
it.each([
|
||||||
|
[FracturedItem, true],
|
||||||
|
[FracturedItemNoModMarked, true],
|
||||||
|
[RareItem, undefined],
|
||||||
|
])(
|
||||||
|
"%#, Each mod section is recognized",
|
||||||
|
(item: TestItem, isFractured: boolean | undefined) => {
|
||||||
|
const sections = __testExports.itemTextToSections(item.rawText);
|
||||||
|
const parsedItem = {} as ParsedItem;
|
||||||
|
__testExports.parseFracturedText(
|
||||||
|
sections[sections.length - 1],
|
||||||
|
parsedItem,
|
||||||
|
);
|
||||||
|
expect(parsedItem.isFractured).toBe(isFractured);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it("adds fractured if some mod is fractured", () => {
|
||||||
|
const parsedItem = {
|
||||||
|
newMods: [
|
||||||
|
{
|
||||||
|
info: { type: ModifierType.Fractured, tags: [] },
|
||||||
|
stats: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
info: { type: ModifierType.Explicit, tags: [] },
|
||||||
|
stats: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
info: { type: ModifierType.Explicit, tags: [] },
|
||||||
|
stats: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as unknown as ParserState;
|
||||||
|
__testExports.parseFractured(parsedItem);
|
||||||
|
expect(parsedItem.isFractured).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does nothing if no mod is fractured", () => {
|
||||||
|
const parsedItem = {
|
||||||
|
newMods: [
|
||||||
|
{
|
||||||
|
info: { type: ModifierType.Implicit, tags: [] },
|
||||||
|
stats: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
info: { type: ModifierType.Explicit, tags: [] },
|
||||||
|
stats: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as unknown as ParserState;
|
||||||
|
__testExports.parseFractured(parsedItem);
|
||||||
|
expect(parsedItem.isFractured).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -66,6 +66,14 @@ export class TestItem implements ParsedItem {
|
|||||||
|
|
||||||
note?: string;
|
note?: string;
|
||||||
category?: ItemCategory | undefined;
|
category?: ItemCategory | undefined;
|
||||||
|
|
||||||
|
requires?: {
|
||||||
|
level: number;
|
||||||
|
str: number;
|
||||||
|
dex: number;
|
||||||
|
int: number;
|
||||||
|
};
|
||||||
|
|
||||||
info: BaseType = {
|
info: BaseType = {
|
||||||
name: "test",
|
name: "test",
|
||||||
refName: "test",
|
refName: "test",
|
||||||
@@ -125,6 +133,12 @@ NormalItem.quality = 9;
|
|||||||
NormalItem.armourAR = 174;
|
NormalItem.armourAR = 174;
|
||||||
NormalItem.armourES = 60;
|
NormalItem.armourES = 60;
|
||||||
NormalItem.itemLevel = 81;
|
NormalItem.itemLevel = 81;
|
||||||
|
NormalItem.requires = {
|
||||||
|
level: 75,
|
||||||
|
str: 67,
|
||||||
|
dex: 0,
|
||||||
|
int: 67,
|
||||||
|
};
|
||||||
|
|
||||||
NormalItem.info.refName = "Divine Crown";
|
NormalItem.info.refName = "Divine Crown";
|
||||||
NormalItem.sectionCount = 4;
|
NormalItem.sectionCount = 4;
|
||||||
@@ -157,6 +171,12 @@ MagicItem.weaponELEMENTAL = MagicItem.weaponLIGHTNING;
|
|||||||
MagicItem.weaponCRIT = 5;
|
MagicItem.weaponCRIT = 5;
|
||||||
MagicItem.weaponAS = 1.2;
|
MagicItem.weaponAS = 1.2;
|
||||||
MagicItem.itemLevel = 32;
|
MagicItem.itemLevel = 32;
|
||||||
|
MagicItem.requires = {
|
||||||
|
level: 28,
|
||||||
|
str: 57,
|
||||||
|
dex: 0,
|
||||||
|
int: 0,
|
||||||
|
};
|
||||||
|
|
||||||
MagicItem.info.refName = "Temple Maul";
|
MagicItem.info.refName = "Temple Maul";
|
||||||
MagicItem.sectionCount = 5;
|
MagicItem.sectionCount = 5;
|
||||||
@@ -200,6 +220,12 @@ RareItem.weaponELEMENTAL =
|
|||||||
RareItem.weaponAS = 1.2;
|
RareItem.weaponAS = 1.2;
|
||||||
RareItem.weaponCRIT = 5;
|
RareItem.weaponCRIT = 5;
|
||||||
RareItem.itemLevel = 80;
|
RareItem.itemLevel = 80;
|
||||||
|
RareItem.requires = {
|
||||||
|
level: 51,
|
||||||
|
str: 0,
|
||||||
|
dex: 103,
|
||||||
|
int: 0,
|
||||||
|
};
|
||||||
|
|
||||||
RareItem.info.refName = "Rider Bow";
|
RareItem.info.refName = "Rider Bow";
|
||||||
RareItem.sectionCount = 5;
|
RareItem.sectionCount = 5;
|
||||||
@@ -237,6 +263,12 @@ UniqueItem.category = ItemCategory.Focus;
|
|||||||
UniqueItem.rarity = ItemRarity.Unique;
|
UniqueItem.rarity = ItemRarity.Unique;
|
||||||
UniqueItem.armourES = 44;
|
UniqueItem.armourES = 44;
|
||||||
UniqueItem.itemLevel = 81;
|
UniqueItem.itemLevel = 81;
|
||||||
|
UniqueItem.requires = {
|
||||||
|
level: 26,
|
||||||
|
str: 0,
|
||||||
|
dex: 0,
|
||||||
|
int: 43,
|
||||||
|
};
|
||||||
|
|
||||||
// NOTE: requires step through to verify use of Name here is right
|
// NOTE: requires step through to verify use of Name here is right
|
||||||
UniqueItem.info.refName = "The Eternal Spark";
|
UniqueItem.info.refName = "The Eternal Spark";
|
||||||
@@ -271,6 +303,12 @@ Item Level: 79
|
|||||||
RareWithImplicit.category = ItemCategory.Ring;
|
RareWithImplicit.category = ItemCategory.Ring;
|
||||||
RareWithImplicit.rarity = ItemRarity.Rare;
|
RareWithImplicit.rarity = ItemRarity.Rare;
|
||||||
RareWithImplicit.itemLevel = 79;
|
RareWithImplicit.itemLevel = 79;
|
||||||
|
RareWithImplicit.requires = {
|
||||||
|
level: 45,
|
||||||
|
str: 0,
|
||||||
|
dex: 0,
|
||||||
|
int: 0,
|
||||||
|
};
|
||||||
|
|
||||||
RareWithImplicit.info.refName = "Prismatic Ring";
|
RareWithImplicit.info.refName = "Prismatic Ring";
|
||||||
RareWithImplicit.sectionCount = 5;
|
RareWithImplicit.sectionCount = 5;
|
||||||
@@ -401,6 +439,12 @@ HighDamageRareItem.sectionCount = 9;
|
|||||||
HighDamageRareItem.prefixCount = 3;
|
HighDamageRareItem.prefixCount = 3;
|
||||||
HighDamageRareItem.suffixCount = 3;
|
HighDamageRareItem.suffixCount = 3;
|
||||||
HighDamageRareItem.implicitCount = 1;
|
HighDamageRareItem.implicitCount = 1;
|
||||||
|
HighDamageRareItem.requires = {
|
||||||
|
level: 79,
|
||||||
|
str: 89,
|
||||||
|
dex: 89,
|
||||||
|
int: 0,
|
||||||
|
};
|
||||||
|
|
||||||
HighDamageRareItem.runeSockets = {
|
HighDamageRareItem.runeSockets = {
|
||||||
empty: 0,
|
empty: 0,
|
||||||
@@ -447,6 +491,12 @@ ArmourHighValueRareItem.rarity = ItemRarity.Rare;
|
|||||||
ArmourHighValueRareItem.quality = 20;
|
ArmourHighValueRareItem.quality = 20;
|
||||||
ArmourHighValueRareItem.armourAR = 3075;
|
ArmourHighValueRareItem.armourAR = 3075;
|
||||||
ArmourHighValueRareItem.itemLevel = 80;
|
ArmourHighValueRareItem.itemLevel = 80;
|
||||||
|
ArmourHighValueRareItem.requires = {
|
||||||
|
level: 65,
|
||||||
|
str: 121,
|
||||||
|
dex: 0,
|
||||||
|
int: 0,
|
||||||
|
};
|
||||||
|
|
||||||
ArmourHighValueRareItem.info.refName = "Soldier Cuirass";
|
ArmourHighValueRareItem.info.refName = "Soldier Cuirass";
|
||||||
ArmourHighValueRareItem.sectionCount = 8;
|
ArmourHighValueRareItem.sectionCount = 8;
|
||||||
@@ -488,6 +538,12 @@ Note: ~b/o 5 exalted
|
|||||||
WandRareItem.category = ItemCategory.Wand;
|
WandRareItem.category = ItemCategory.Wand;
|
||||||
WandRareItem.rarity = ItemRarity.Rare;
|
WandRareItem.rarity = ItemRarity.Rare;
|
||||||
WandRareItem.itemLevel = 82;
|
WandRareItem.itemLevel = 82;
|
||||||
|
WandRareItem.requires = {
|
||||||
|
level: 90,
|
||||||
|
str: 0,
|
||||||
|
dex: 0,
|
||||||
|
int: 125,
|
||||||
|
};
|
||||||
|
|
||||||
WandRareItem.info.refName = "Withered Wand";
|
WandRareItem.info.refName = "Withered Wand";
|
||||||
WandRareItem.sectionCount = 6;
|
WandRareItem.sectionCount = 6;
|
||||||
@@ -521,6 +577,12 @@ NormalShield.itemLevel = 82;
|
|||||||
NormalShield.armourAR = 71;
|
NormalShield.armourAR = 71;
|
||||||
NormalShield.armourEV = 64;
|
NormalShield.armourEV = 64;
|
||||||
NormalShield.armourBLOCK = 25;
|
NormalShield.armourBLOCK = 25;
|
||||||
|
NormalShield.requires = {
|
||||||
|
level: 54,
|
||||||
|
str: 42,
|
||||||
|
dex: 42,
|
||||||
|
int: 0,
|
||||||
|
};
|
||||||
|
|
||||||
NormalShield.info.refName = "Polished Targe";
|
NormalShield.info.refName = "Polished Targe";
|
||||||
NormalShield.sectionCount = 6;
|
NormalShield.sectionCount = 6;
|
||||||
@@ -558,6 +620,12 @@ Has 2(1-3) Charm Slots
|
|||||||
TwoImplicitItem.category = ItemCategory.Belt;
|
TwoImplicitItem.category = ItemCategory.Belt;
|
||||||
TwoImplicitItem.rarity = ItemRarity.Rare;
|
TwoImplicitItem.rarity = ItemRarity.Rare;
|
||||||
TwoImplicitItem.itemLevel = 80;
|
TwoImplicitItem.itemLevel = 80;
|
||||||
|
TwoImplicitItem.requires = {
|
||||||
|
level: 59,
|
||||||
|
str: 0,
|
||||||
|
dex: 0,
|
||||||
|
int: 0,
|
||||||
|
};
|
||||||
|
|
||||||
TwoImplicitItem.info.refName = "Ornate Belt";
|
TwoImplicitItem.info.refName = "Ornate Belt";
|
||||||
TwoImplicitItem.sectionCount = 5;
|
TwoImplicitItem.sectionCount = 5;
|
||||||
@@ -686,5 +754,147 @@ RareMapFakeAllProps.mapMagicMonsters = 30;
|
|||||||
RareMapFakeAllProps.mapRareMonsters = 71;
|
RareMapFakeAllProps.mapRareMonsters = 71;
|
||||||
RareMapFakeAllProps.mapDropChance = 90;
|
RareMapFakeAllProps.mapDropChance = 90;
|
||||||
RareMapFakeAllProps.mapItemRarity = 17;
|
RareMapFakeAllProps.mapItemRarity = 17;
|
||||||
RareMapFakeAllProps.sectionCount = 5;
|
RareMapFakeAllProps.sectionCount = 6;
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region FracturedItem
|
||||||
|
export const FracturedItem = new TestItem(`Item Class: Bows
|
||||||
|
Rarity: Rare
|
||||||
|
Miracle Siege
|
||||||
|
Obliterator Bow
|
||||||
|
--------
|
||||||
|
Quality: +25% (augmented)
|
||||||
|
Physical Damage: 381-705 (augmented)
|
||||||
|
Critical Hit Chance: 9.40% (augmented)
|
||||||
|
Attacks per Second: 1.15
|
||||||
|
--------
|
||||||
|
Requires: Level 78, 163 (unmet) Dex
|
||||||
|
--------
|
||||||
|
Sockets: S S
|
||||||
|
--------
|
||||||
|
Item Level: 81
|
||||||
|
--------
|
||||||
|
36% increased Physical Damage (rune)
|
||||||
|
--------
|
||||||
|
{ Implicit Modifier }
|
||||||
|
50% reduced Projectile Range
|
||||||
|
--------
|
||||||
|
{ Prefix Modifier "Flaring" (Tier: 1) — Damage, Physical, Attack }
|
||||||
|
Adds 32(26-39) to 59(44-66) Physical Damage (fractured)
|
||||||
|
|
||||||
|
{ Prefix Modifier "Bloodthirsty" (Tier: 4) — Damage, Physical, Attack }
|
||||||
|
134(110-134)% increased Physical Damage
|
||||||
|
|
||||||
|
{ Prefix Modifier "Champion's" (Tier: 4) — Damage, Physical, Attack }
|
||||||
|
54(45-54)% increased Physical Damage
|
||||||
|
+113(98-123) to Accuracy Rating
|
||||||
|
|
||||||
|
{ Suffix Modifier "of the Essence" — Speed }
|
||||||
|
20(20-25)% chance to gain Onslaught on Killing Hits with this Weapon
|
||||||
|
|
||||||
|
{ Suffix Modifier "of the Essence" — Attack }
|
||||||
|
+3 to Level of all Attack Skills
|
||||||
|
|
||||||
|
{ Suffix Modifier "of Ruin" (Tier: 2) — Attack, Critical }
|
||||||
|
+4.4(3.81-4.4)% to Critical Hit Chance
|
||||||
|
|
||||||
|
--------
|
||||||
|
Fractured Item
|
||||||
|
`);
|
||||||
|
FracturedItem.category = ItemCategory.Bow;
|
||||||
|
FracturedItem.rarity = ItemRarity.Rare;
|
||||||
|
FracturedItem.quality = 25;
|
||||||
|
FracturedItem.weaponPHYSICAL = 624;
|
||||||
|
FracturedItem.weaponAS = 1.15;
|
||||||
|
FracturedItem.weaponCRIT = 9.4;
|
||||||
|
FracturedItem.itemLevel = 81;
|
||||||
|
FracturedItem.requires = {
|
||||||
|
level: 78,
|
||||||
|
str: 163,
|
||||||
|
dex: 0,
|
||||||
|
int: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
FracturedItem.info.refName = "Obliterator Bow";
|
||||||
|
FracturedItem.isFractured = true;
|
||||||
|
FracturedItem.prefixCount = 3;
|
||||||
|
FracturedItem.suffixCount = 3;
|
||||||
|
FracturedItem.implicitCount = 1;
|
||||||
|
FracturedItem.sectionCount = 9;
|
||||||
|
FracturedItem.runeSockets = {
|
||||||
|
empty: 0,
|
||||||
|
current: 2,
|
||||||
|
normal: 2,
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region FracturedItemNoModMarked
|
||||||
|
export const FracturedItemNoModMarked = new TestItem(`Item Class: Bows
|
||||||
|
Rarity: Rare
|
||||||
|
Miracle Siege
|
||||||
|
Obliterator Bow
|
||||||
|
--------
|
||||||
|
Quality: +25% (augmented)
|
||||||
|
Physical Damage: 381-705 (augmented)
|
||||||
|
Critical Hit Chance: 9.40% (augmented)
|
||||||
|
Attacks per Second: 1.15
|
||||||
|
--------
|
||||||
|
Requires: Level 78, 163 (unmet) Dex
|
||||||
|
--------
|
||||||
|
Sockets: S S
|
||||||
|
--------
|
||||||
|
Item Level: 81
|
||||||
|
--------
|
||||||
|
36% increased Physical Damage (rune)
|
||||||
|
--------
|
||||||
|
{ Implicit Modifier }
|
||||||
|
50% reduced Projectile Range
|
||||||
|
--------
|
||||||
|
{ Prefix Modifier "Flaring" (Tier: 1) — Damage, Physical, Attack }
|
||||||
|
Adds 32(26-39) to 59(44-66) Physical Damage
|
||||||
|
|
||||||
|
{ Prefix Modifier "Bloodthirsty" (Tier: 4) — Damage, Physical, Attack }
|
||||||
|
134(110-134)% increased Physical Damage
|
||||||
|
|
||||||
|
{ Prefix Modifier "Champion's" (Tier: 4) — Damage, Physical, Attack }
|
||||||
|
54(45-54)% increased Physical Damage
|
||||||
|
+113(98-123) to Accuracy Rating
|
||||||
|
|
||||||
|
{ Suffix Modifier "of the Essence" — Speed }
|
||||||
|
20(20-25)% chance to gain Onslaught on Killing Hits with this Weapon
|
||||||
|
|
||||||
|
{ Suffix Modifier "of the Essence" — Attack }
|
||||||
|
+3 to Level of all Attack Skills
|
||||||
|
|
||||||
|
{ Suffix Modifier "of Ruin" (Tier: 2) — Attack, Critical }
|
||||||
|
+4.4(3.81-4.4)% to Critical Hit Chance
|
||||||
|
|
||||||
|
--------
|
||||||
|
Fractured Item
|
||||||
|
`);
|
||||||
|
FracturedItemNoModMarked.category = ItemCategory.Bow;
|
||||||
|
FracturedItemNoModMarked.rarity = ItemRarity.Rare;
|
||||||
|
FracturedItemNoModMarked.quality = 25;
|
||||||
|
FracturedItemNoModMarked.weaponPHYSICAL = 381.5;
|
||||||
|
FracturedItemNoModMarked.weaponAS = 1.15;
|
||||||
|
FracturedItemNoModMarked.weaponCRIT = 9.4;
|
||||||
|
FracturedItemNoModMarked.itemLevel = 81;
|
||||||
|
FracturedItemNoModMarked.requires = {
|
||||||
|
level: 78,
|
||||||
|
str: 163,
|
||||||
|
dex: 0,
|
||||||
|
int: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
FracturedItemNoModMarked.info.refName = "Obliterator Bow";
|
||||||
|
FracturedItemNoModMarked.isFractured = true;
|
||||||
|
FracturedItemNoModMarked.prefixCount = 3;
|
||||||
|
FracturedItemNoModMarked.suffixCount = 3;
|
||||||
|
FracturedItemNoModMarked.implicitCount = 1;
|
||||||
|
FracturedItemNoModMarked.sectionCount = 9;
|
||||||
|
FracturedItemNoModMarked.runeSockets = {
|
||||||
|
empty: 0,
|
||||||
|
current: 2,
|
||||||
|
normal: 2,
|
||||||
|
};
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { CLIENT_STRINGS as _$ } from "@/assets/data";
|
||||||
import { __testExports } from "@/parser/Parser";
|
import { __testExports } from "@/parser/Parser";
|
||||||
import { beforeEach, describe, expect, it, test } from "vitest";
|
import { beforeEach, describe, expect, it, test } from "vitest";
|
||||||
import { setupTests } from "@specs/vitest.setup";
|
import { setupTests } from "@specs/vitest.setup";
|
||||||
@@ -8,6 +9,7 @@ import {
|
|||||||
NormalItem,
|
NormalItem,
|
||||||
RareItem,
|
RareItem,
|
||||||
RareWithImplicit,
|
RareWithImplicit,
|
||||||
|
TestItem,
|
||||||
UniqueItem,
|
UniqueItem,
|
||||||
WandRareItem,
|
WandRareItem,
|
||||||
} from "./items";
|
} from "./items";
|
||||||
@@ -49,6 +51,8 @@ describe("parseWeapon", () => {
|
|||||||
|
|
||||||
const res = __testExports.parseWeapon(sections[1], parsedItem);
|
const res = __testExports.parseWeapon(sections[1], parsedItem);
|
||||||
|
|
||||||
|
// console.log(sections);
|
||||||
|
|
||||||
expect(res).toBe("SECTION_PARSED");
|
expect(res).toBe("SECTION_PARSED");
|
||||||
expect(parsedItem.weaponPHYSICAL).toBe(MagicItem.weaponPHYSICAL);
|
expect(parsedItem.weaponPHYSICAL).toBe(MagicItem.weaponPHYSICAL);
|
||||||
expect(parsedItem.weaponELEMENTAL).toBe(MagicItem.weaponELEMENTAL);
|
expect(parsedItem.weaponELEMENTAL).toBe(MagicItem.weaponELEMENTAL);
|
||||||
@@ -134,3 +138,86 @@ describe("parseArmour", () => {
|
|||||||
expect(parsedItem.armourBLOCK).toBe(ArmourHighValueRareItem.armourBLOCK);
|
expect(parsedItem.armourBLOCK).toBe(ArmourHighValueRareItem.armourBLOCK);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("parseRequirements", () => {
|
||||||
|
it.each([
|
||||||
|
["Normal", NormalItem],
|
||||||
|
["Magic", MagicItem],
|
||||||
|
["Rare", RareItem],
|
||||||
|
["Unique", UniqueItem],
|
||||||
|
["RareWithImplicit", RareWithImplicit],
|
||||||
|
["HighDamageRare", HighDamageRareItem],
|
||||||
|
["ArmourHighValueRare", ArmourHighValueRareItem],
|
||||||
|
["WandRare", WandRareItem],
|
||||||
|
])(
|
||||||
|
"%s, items parse requirements",
|
||||||
|
async (testName: string, item: TestItem) => {
|
||||||
|
setupTests();
|
||||||
|
await loadForLang("en");
|
||||||
|
const sections = __testExports.itemTextToSections(item.rawText);
|
||||||
|
const parsedItem = {} as ParsedItem;
|
||||||
|
|
||||||
|
const res = __testExports.parseRequirements(
|
||||||
|
sections.find((s) => s.some((l) => l.startsWith(_$.REQUIRES)))!,
|
||||||
|
parsedItem,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(res).toBe("SECTION_PARSED");
|
||||||
|
expect(parsedItem.requires).toEqual(item.requires);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
[
|
||||||
|
"en",
|
||||||
|
"Requires: Level 28, 57 (augmented) Str",
|
||||||
|
{ level: 28, str: 57, dex: 0, int: 0 },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"cmn-Hant",
|
||||||
|
"需求: 等級 80, 108 (unmet) 智慧",
|
||||||
|
{ level: 80, str: 0, dex: 0, int: 108 },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"ja",
|
||||||
|
"装備条件:レベル 72, 70 筋力, 70 知性",
|
||||||
|
{ level: 72, str: 70, dex: 0, int: 70 },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"ko",
|
||||||
|
"요구 사항: 레벨 78, 89 힘, 89 (unmet) 민첩",
|
||||||
|
{ level: 78, str: 89, dex: 89, int: 0 },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"cmn-Hant",
|
||||||
|
"需求: 等級 78, 54 力量, 138 智慧",
|
||||||
|
{ level: 78, str: 54, dex: 0, int: 138 },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"ru",
|
||||||
|
"Требуется: Уровень 80, 59 (unmet) Ловк, 59 Инт",
|
||||||
|
{
|
||||||
|
level: 80,
|
||||||
|
str: 0,
|
||||||
|
dex: 59,
|
||||||
|
int: 59,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
])(
|
||||||
|
"%s requires regex works",
|
||||||
|
async (
|
||||||
|
lang: string,
|
||||||
|
str: string,
|
||||||
|
expectedResult: ParsedItem["requires"],
|
||||||
|
) => {
|
||||||
|
setupTests();
|
||||||
|
await loadForLang(lang);
|
||||||
|
const parsedItem = {} as ParsedItem;
|
||||||
|
|
||||||
|
const res = __testExports.parseRequirements([str], parsedItem);
|
||||||
|
|
||||||
|
expect(res).toBe("SECTION_PARSED");
|
||||||
|
expect(parsedItem.requires).toEqual(expectedResult);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ export interface TranslationDict {
|
|||||||
LOG_ZONE_GEN: RegExp;
|
LOG_ZONE_GEN: RegExp;
|
||||||
DOUBLE_CORRUPTED: string;
|
DOUBLE_CORRUPTED: string;
|
||||||
IMPLICIT_MODIFIER: string;
|
IMPLICIT_MODIFIER: string;
|
||||||
|
REQUIRES_LINE: RegExp;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Filter {
|
export interface Filter {
|
||||||
|
|||||||
@@ -94,6 +94,12 @@ export interface ParsedItem {
|
|||||||
};
|
};
|
||||||
note?: string;
|
note?: string;
|
||||||
category?: ItemCategory;
|
category?: ItemCategory;
|
||||||
|
requires?: {
|
||||||
|
level: number;
|
||||||
|
str: number;
|
||||||
|
dex: number;
|
||||||
|
int: number;
|
||||||
|
};
|
||||||
info: BaseType;
|
info: BaseType;
|
||||||
rawText: string;
|
rawText: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ type SectionParseResult =
|
|||||||
type ParserFn = (section: string[], item: ParserState) => SectionParseResult;
|
type ParserFn = (section: string[], item: ParserState) => SectionParseResult;
|
||||||
type VirtualParserFn = (item: ParserState) => Result<never, string> | void;
|
type VirtualParserFn = (item: ParserState) => Result<never, string> | void;
|
||||||
|
|
||||||
interface ParserState extends ParsedItem {
|
export interface ParserState extends ParsedItem {
|
||||||
name: string;
|
name: string;
|
||||||
baseType: string | undefined;
|
baseType: string | undefined;
|
||||||
infoVariants: BaseType[];
|
infoVariants: BaseType[];
|
||||||
@@ -379,6 +379,7 @@ function parseBlightedMap(item: ParsedItem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parseFractured(item: ParserState) {
|
function parseFractured(item: ParserState) {
|
||||||
|
// NOTE: partially also controlled by parseFracturedText
|
||||||
if (item.newMods.some((mod) => mod.info.type === ModifierType.Fractured)) {
|
if (item.newMods.some((mod) => mod.info.type === ModifierType.Fractured)) {
|
||||||
item.isFractured = true;
|
item.isFractured = true;
|
||||||
}
|
}
|
||||||
@@ -580,13 +581,24 @@ function parseItemLevel(section: string[], item: ParsedItem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parseRequirements(section: string[], item: ParsedItem) {
|
function parseRequirements(section: string[], item: ParsedItem) {
|
||||||
if (
|
if (!section[0].startsWith(_$.REQUIRES)) {
|
||||||
section[0].startsWith(_$.REQUIREMENTS) ||
|
return "SECTION_SKIPPED";
|
||||||
section[0].startsWith(_$.REQUIRES)
|
|
||||||
) {
|
|
||||||
return "SECTION_PARSED";
|
|
||||||
}
|
}
|
||||||
return "SECTION_SKIPPED";
|
|
||||||
|
const match = section[0].match(_$.REQUIRES_LINE);
|
||||||
|
// TODO: remove once validated in other langs
|
||||||
|
if (!match) {
|
||||||
|
throw new Error("Failed to parse requirements");
|
||||||
|
}
|
||||||
|
|
||||||
|
item.requires = {
|
||||||
|
level: parseInt(match.groups!.level ?? "0"),
|
||||||
|
str: parseInt(match.groups!.str ?? "0"),
|
||||||
|
dex: parseInt(match.groups!.dex ?? "0"),
|
||||||
|
int: parseInt(match.groups!.int ?? "0"),
|
||||||
|
};
|
||||||
|
|
||||||
|
return "SECTION_PARSED";
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseTalismanTier(section: string[], item: ParsedItem) {
|
function parseTalismanTier(section: string[], item: ParsedItem) {
|
||||||
@@ -1222,9 +1234,11 @@ function parsePriceNote(section: string[], item: ParsedItem) {
|
|||||||
return "SECTION_SKIPPED";
|
return "SECTION_SKIPPED";
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseFracturedText(section: string[], _item: ParsedItem) {
|
function parseFracturedText(section: string[], item: ParsedItem) {
|
||||||
for (const line of section) {
|
for (const line of section) {
|
||||||
if (line === _$.FRACTURED_ITEM) {
|
if (line === _$.FRACTURED_ITEM) {
|
||||||
|
// HACK: remove once bug is fixed (https://www.pathofexile.com/forum/view-thread/3891367)
|
||||||
|
item.isFractured = true;
|
||||||
return "SECTION_PARSED";
|
return "SECTION_PARSED";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1754,4 +1768,7 @@ export const __testExports = {
|
|||||||
parseArmour,
|
parseArmour,
|
||||||
parseModifiers,
|
parseModifiers,
|
||||||
parseWaystone,
|
parseWaystone,
|
||||||
|
parseRequirements,
|
||||||
|
parseFractured,
|
||||||
|
parseFracturedText,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -61,6 +61,11 @@
|
|||||||
:filter="filters.itemLevel"
|
:filter="filters.itemLevel"
|
||||||
:name="t('item.item_level')"
|
:name="t('item.item_level')"
|
||||||
/>
|
/>
|
||||||
|
<filter-btn-numeric
|
||||||
|
v-if="filters.requires?.level"
|
||||||
|
:filter="filters.requires?.level"
|
||||||
|
:name="t('item.requires_level')"
|
||||||
|
/>
|
||||||
<filter-btn-numeric
|
<filter-btn-numeric
|
||||||
v-if="filters.stackSize"
|
v-if="filters.stackSize"
|
||||||
:filter="filters.stackSize"
|
:filter="filters.stackSize"
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import type { ItemFilters } from "./interfaces";
|
import type { ItemFilters } from "./interfaces";
|
||||||
import {
|
import { ParsedItem, ItemCategory, ItemRarity } from "@/parser";
|
||||||
ParsedItem,
|
|
||||||
ItemCategory,
|
|
||||||
ItemRarity,
|
|
||||||
itemIsModifiable,
|
|
||||||
} from "@/parser";
|
|
||||||
import { tradeTag } from "../trade/common";
|
import { tradeTag } from "../trade/common";
|
||||||
import { ModifierType } from "@/parser/modifiers";
|
import { ModifierType } from "@/parser/modifiers";
|
||||||
import { BaseType, ITEM_BY_REF } from "@/assets/data";
|
import { BaseType, ITEM_BY_REF } from "@/assets/data";
|
||||||
@@ -294,6 +289,22 @@ export function createFilters(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.requires && item.rarity === ItemRarity.Rare && !opts.exact) {
|
||||||
|
if (
|
||||||
|
item.requires.level &&
|
||||||
|
item.requires.level <= 75 &&
|
||||||
|
item.itemLevel &&
|
||||||
|
item.itemLevel <= 75
|
||||||
|
) {
|
||||||
|
filters.requires = {
|
||||||
|
level: {
|
||||||
|
value: item.requires.level,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const forAdornedJewel =
|
const forAdornedJewel =
|
||||||
item.rarity === ItemRarity.Magic &&
|
item.rarity === ItemRarity.Magic &&
|
||||||
// item.isCorrupted && -- let the buyer corrupt
|
// item.isCorrupted && -- let the buyer corrupt
|
||||||
@@ -355,12 +366,12 @@ export function createFilters(
|
|||||||
filters.sanctified = { disabled: false };
|
filters.sanctified = { disabled: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!item.isFractured && itemIsModifiable(item)) {
|
if (!item.isFractured && opts.exact) {
|
||||||
filters.fractured = { value: false };
|
filters.fractured = { value: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.isFoil) {
|
if (item.isFoil) {
|
||||||
filters.foil = { disabled: false };
|
filters.foil = { disabled: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.influences.length && item.influences.length <= 2) {
|
if (item.influences.length && item.influences.length <= 2) {
|
||||||
|
|||||||
@@ -89,6 +89,12 @@ export interface ItemFilters {
|
|||||||
collapseListings: "api" | "app";
|
collapseListings: "api" | "app";
|
||||||
};
|
};
|
||||||
tempRuneStorage?: StatFilter[];
|
tempRuneStorage?: StatFilter[];
|
||||||
|
requires?: {
|
||||||
|
level?: FilterNumeric;
|
||||||
|
str?: FilterNumeric;
|
||||||
|
dex?: FilterNumeric;
|
||||||
|
int?: FilterNumeric;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FilterNumeric {
|
export interface FilterNumeric {
|
||||||
|
|||||||
@@ -433,6 +433,18 @@ export function createTradeRequest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
filters.requires &&
|
||||||
|
filters.requires.level &&
|
||||||
|
!filters.requires.level.disabled
|
||||||
|
) {
|
||||||
|
propSet(
|
||||||
|
query.filters,
|
||||||
|
"req_filters.filters.lvl.max",
|
||||||
|
filters.requires.level.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (filters.quality && !filters.quality.disabled) {
|
if (filters.quality && !filters.quality.disabled) {
|
||||||
propSet(
|
propSet(
|
||||||
query.filters,
|
query.filters,
|
||||||
|
|||||||
Reference in New Issue
Block a user