@sjtdev/koishi-plugin-dota2tracker 2.3.0 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/changelog.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # 更新日志
2
2
 
3
+ ### [2.3.2](https://github.com/sjtdev/koishi-plugin-dota2tracker/compare/v2.3.1...v2.3.2) (2025-12-18)
4
+
5
+ ### 🚀 功能优化
6
+
7
+ * **templates/match_2+:** 更换至`7.40`版地图,并调整了建筑坐标使位置更合理;修复了部分近战/远程兵营位置错乱的问题。 ([cb88644](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/cb88644d0f519d44bc983f975d62c8aea33879eb))
8
+
9
+ ### 🐛 Bug 修复
10
+
11
+ * **locale:** 补充新英雄在`本地化`词典中的词条。 ([8a72813](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/8a728134e15ca1f570d06dd8c215c25fcab23286))
12
+
13
+ ### 📝 文档
14
+
15
+ * 更新图片构建、补充对`match_2+`的说明。 ([9193c21](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/9193c21981c5ced74f6c759c82f137871efd163c))
16
+
17
+ ### [2.3.1](https://github.com/sjtdev/koishi-plugin-dota2tracker/compare/v2.3.0...v2.3.1) (2025-12-17)
18
+
19
+ ### 🐛 Bug 修复
20
+
21
+ * 修复依赖`dotaconstants`的新版本在部分环境中无法引用导致插件启用失败的问题。 ([045cd0c](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/045cd0c8a66dda2bf084a3b5d6470250a372a366))
22
+
3
23
  ## [2.3.0](https://github.com/sjtdev/koishi-plugin-dota2tracker/compare/v2.2.3...v2.3.0) (2025-12-17)
4
24
 
5
25
  ### ✨ 新增功能
package/lib/index.js CHANGED
@@ -789,7 +789,7 @@ var require_en_US_template = __commonJS({
789
789
  // src/locales/en-US.yml
790
790
  var require_en_US = __commonJS({
791
791
  "src/locales/en-US.yml"(exports2, module2) {
792
- module2.exports = { dota2tracker: { heroes_nicknames: { "0": 'Please strictly follow the format of "", "" when filling out, if the format is incorrect, only the default name of the hero will be used. The default name of the hero may be omitted.', "1": '"Anti-Mage"', "2": '"Axe"', "3": '"Bane"', "4": '"Bloodseeker"', "5": '"Crystal Maiden"', "6": '"Drow Ranger"', "7": '"Earthshaker"', "8": '"Juggernaut"', "9": '"Mirana"', "10": '"Morphling"', "11": '"Shadow Fiend"', "12": '"Phantom Lancer"', "13": '"Puck"', "14": '"Pudge"', "15": '"Razor"', "16": '"Sand King"', "17": '"Storm Spirit"', "18": '"Sven"', "19": '"Tiny"', "20": '"Vengeful Spirit"', "21": '"Windranger"', "22": '"Zeus"', "23": '"Kunkka"', "25": '"Lina"', "26": '"Lion"', "27": '"Shadow Shaman"', "28": '"Slardar"', "29": '"Tidehunter"', "30": '"Witch Doctor"', "31": '"Lich"', "32": '"Riki"', "33": '"Enigma"', "34": '"Tinker"', "35": '"Sniper"', "36": '"Necrophos"', "37": '"Warlock"', "38": '"Beastmaster"', "39": '"Queen of Pain"', "40": '"Venomancer"', "41": '"Faceless Void"', "42": '"Wraith King"', "43": '"Death Prophet"', "44": '"Phantom Assassin"', "45": '"Pugna"', "46": '"Templar Assassin"', "47": '"Viper"', "48": '"Luna"', "49": '"Dragon Knight"', "50": '"Dazzle"', "51": '"Clockwerk"', "52": '"Leshrac"', "53": `"Nature's Prophet"`, "54": '"Lifestealer"', "55": '"Dark Seer"', "56": '"Clinkz"', "57": '"Omniknight"', "58": '"Enchantress"', "59": '"Huskar"', "60": '"Night Stalker"', "61": '"Broodmother"', "62": '"Bounty Hunter"', "63": '"Weaver"', "64": '"Jakiro"', "65": '"Batrider"', "66": '"Chen"', "67": '"Spectre"', "68": '"Ancient Apparition"', "69": '"Doom"', "70": '"Ursa"', "71": '"Spirit Breaker"', "72": '"Gyrocopter"', "73": '"Alchemist"', "74": '"Invoker"', "75": '"Silencer"', "76": '"Outworld Devourer"', "77": '"Lycan"', "78": '"Brewmaster"', "79": '"Shadow Demon"', "80": '"Lone Druid"', "81": '"Chaos Knight"', "82": '"Meepo"', "83": '"Treant Protector"', "84": '"Ogre Magi"', "85": '"Undying"', "86": '"Rubick"', "87": '"Disruptor"', "88": '"Nyx Assassin"', "89": '"Naga Siren"', "90": '"Keeper of the Light"', "91": '"Io"', "92": '"Visage"', "93": '"Slark"', "94": '"Medusa"', "95": '"Troll Warlord"', "96": '"Centaur Warrunner"', "97": '"Magnus"', "98": '"Timbersaw"', "99": '"Bristleback"', "100": '"Tusk"', "101": '"Skywrath Mage"', "102": '"Abaddon"', "103": '"Elder Titan"', "104": '"Legion Commander"', "105": '"Techies"', "106": '"Ember Spirit"', "107": '"Earth Spirit"', "108": '"Underlord"', "109": '"Terrorblade"', "110": '"Phoenix"', "111": '"Oracle"', "112": '"Winter Wyvern"', "113": '"Arc Warden"', "114": '"Monkey King"', "119": '"Dark Willow"', "120": '"Pangolier"', "121": '"Grimstroke"', "123": '"Hoodwink"', "126": '"Void Spirit"', "128": '"Snapfire"', "129": '"Mars"', "131": '"Ring Master"', "135": '"Dawnbreaker"', "136": '"Marci"', "137": '"Primal Beast"', "138": '"Muerta"', "145": '"Kez"' }, broadcast: { WIN_NEGATIVE: `"Won the match by sheer luck", "Won the match by a stroke of bad luck", "Coasted to victory", "Didn't even show up for the team fight, but my teammates won 4v5"`, WIN_POSITIVE: '"Led the team to victory", "Dominated the opponents and secured the win", "Carried the game to victory", "Treated the opponents like pigs and won", "Won again; this game is just so monotonous and dull", "Simply achieved a win in the match"', LOSE_NEGATIVE: '"Got crushed and lost the match", "Lost the match miserably", "Got my head knocked sideways and lost the match with a blown mindset", "Went fishing but got eaten by the fish, lost the match", "Played terribly", "Simply suffered a loss in the match"', LOSE_POSITIVE: `"Lost the match with no way to turn it around", "Gave it my all, but still lost the match", "Though we lost, we still have honor", "Couldn't carry my teammates, lost the match", "Lost again, it hurts; I'd rather it be me losing"`, message: "{name}'s {hero_name} {comment}.\nKDA: {kda}, GPM/XPM: {gpm_xpm}, Last Hits/Denies: {lh_dn}, Damage/Tower Damage: {damage}, Kill/Death Contribution Rate: {kc_dc}", rank_changed: "Player {name} rank changed: {prev.medal} {prev.star} → {curr.medal} {curr.star}" }, logger: { fetch_guilds_failed: "Failed to fetch guild information.", match_tracked: "Tracked new match {match.id} from {#each messageToLogger as item}users in guild {item.platform}:{item.guildId} [{#each item.players as player}{player.nickname}({player.steamId}){#if player !== item.players[item.players.length - 1]}, {/if}{/each}]{#if item !== messageToLogger[messageToLogger.length - 1]}, {/if}{/each}.", parse_request_sent: "The parsing request for match {matchId} has been successfully sent to the STRATZ server.", parse_request_failed: "The parsing request for match {matchId} failed to send.", match_parsed: "Match {matchId} has been parsed{#if odParsed} by OpenDota{/if}, an image was generated and published to {#each guilds as guild}{guild.platform}:{guild.guildId}{#if guild !== guilds[guilds.length - 1]}, {/if}{/each}.", match_unparsed: "Match {matchId} exceeded the waiting time [{timeout}] and remains unparsed, an image was generated and published to {#each guilds as guild}{guild.platform}:{guild.guildId}{#if guild !== guilds[guilds.length - 1]}, {/if}{/each}.", waiting_for_parse: "Match {matchId} has not been parsed yet, has been waiting for {time} minutes.", report_sent: "Posted {title} on {platform}:{guildId}.", rank_sent: "Posted rank change information of {player.nickName} ({player.steamId}) on {platform}:{guildId}.", ejs_error: "Error rendering EJS template: {error}", cron_not_enabled: "Cron service is not enabled; match report tracking cannot run.", stratz_token_banned: "Stratz API request rejected (403). This usually means your token or IP has been temporarily restricted due to unusual activity. For details, see the documentation: http://sjtdev.github.io/koishi-plugin-dota2tracker/en-US/api-403.html", opendota_token_banned: "OpenDota API request rejected (403). Please check if the access limit has been exceeded.", stratz_api_query_error: "Stratz API returned partial data with errors: {cause}", opendota_parse_request_sent: "Parse request for match {matchId} has been sent to OpenDota servers successfully.", opendota_parse_request_failed: "Failed to send parse request for match {matchId} to OpenDota servers." }, time: { years_months_ago: "{years} years and {months} months ago", years_ago: "{years} years ago" } } };
792
+ module2.exports = { dota2tracker: { heroes_nicknames: { "0": 'Please strictly follow the format of "", "" when filling out, if the format is incorrect, only the default name of the hero will be used. The default name of the hero may be omitted.', "1": '"Anti-Mage"', "2": '"Axe"', "3": '"Bane"', "4": '"Bloodseeker"', "5": '"Crystal Maiden"', "6": '"Drow Ranger"', "7": '"Earthshaker"', "8": '"Juggernaut"', "9": '"Mirana"', "10": '"Morphling"', "11": '"Shadow Fiend"', "12": '"Phantom Lancer"', "13": '"Puck"', "14": '"Pudge"', "15": '"Razor"', "16": '"Sand King"', "17": '"Storm Spirit"', "18": '"Sven"', "19": '"Tiny"', "20": '"Vengeful Spirit"', "21": '"Windranger"', "22": '"Zeus"', "23": '"Kunkka"', "25": '"Lina"', "26": '"Lion"', "27": '"Shadow Shaman"', "28": '"Slardar"', "29": '"Tidehunter"', "30": '"Witch Doctor"', "31": '"Lich"', "32": '"Riki"', "33": '"Enigma"', "34": '"Tinker"', "35": '"Sniper"', "36": '"Necrophos"', "37": '"Warlock"', "38": '"Beastmaster"', "39": '"Queen of Pain"', "40": '"Venomancer"', "41": '"Faceless Void"', "42": '"Wraith King"', "43": '"Death Prophet"', "44": '"Phantom Assassin"', "45": '"Pugna"', "46": '"Templar Assassin"', "47": '"Viper"', "48": '"Luna"', "49": '"Dragon Knight"', "50": '"Dazzle"', "51": '"Clockwerk"', "52": '"Leshrac"', "53": `"Nature's Prophet"`, "54": '"Lifestealer"', "55": '"Dark Seer"', "56": '"Clinkz"', "57": '"Omniknight"', "58": '"Enchantress"', "59": '"Huskar"', "60": '"Night Stalker"', "61": '"Broodmother"', "62": '"Bounty Hunter"', "63": '"Weaver"', "64": '"Jakiro"', "65": '"Batrider"', "66": '"Chen"', "67": '"Spectre"', "68": '"Ancient Apparition"', "69": '"Doom"', "70": '"Ursa"', "71": '"Spirit Breaker"', "72": '"Gyrocopter"', "73": '"Alchemist"', "74": '"Invoker"', "75": '"Silencer"', "76": '"Outworld Devourer"', "77": '"Lycan"', "78": '"Brewmaster"', "79": '"Shadow Demon"', "80": '"Lone Druid"', "81": '"Chaos Knight"', "82": '"Meepo"', "83": '"Treant Protector"', "84": '"Ogre Magi"', "85": '"Undying"', "86": '"Rubick"', "87": '"Disruptor"', "88": '"Nyx Assassin"', "89": '"Naga Siren"', "90": '"Keeper of the Light"', "91": '"Io"', "92": '"Visage"', "93": '"Slark"', "94": '"Medusa"', "95": '"Troll Warlord"', "96": '"Centaur Warrunner"', "97": '"Magnus"', "98": '"Timbersaw"', "99": '"Bristleback"', "100": '"Tusk"', "101": '"Skywrath Mage"', "102": '"Abaddon"', "103": '"Elder Titan"', "104": '"Legion Commander"', "105": '"Techies"', "106": '"Ember Spirit"', "107": '"Earth Spirit"', "108": '"Underlord"', "109": '"Terrorblade"', "110": '"Phoenix"', "111": '"Oracle"', "112": '"Winter Wyvern"', "113": '"Arc Warden"', "114": '"Monkey King"', "119": '"Dark Willow"', "120": '"Pangolier"', "121": '"Grimstroke"', "123": '"Hoodwink"', "126": '"Void Spirit"', "128": '"Snapfire"', "129": '"Mars"', "131": '"Ring Master"', "135": '"Dawnbreaker"', "136": '"Marci"', "137": '"Primal Beast"', "138": '"Muerta"', "145": '"Kez"', "155": '"Largo"' }, broadcast: { WIN_NEGATIVE: `"Won the match by sheer luck", "Won the match by a stroke of bad luck", "Coasted to victory", "Didn't even show up for the team fight, but my teammates won 4v5"`, WIN_POSITIVE: '"Led the team to victory", "Dominated the opponents and secured the win", "Carried the game to victory", "Treated the opponents like pigs and won", "Won again; this game is just so monotonous and dull", "Simply achieved a win in the match"', LOSE_NEGATIVE: '"Got crushed and lost the match", "Lost the match miserably", "Got my head knocked sideways and lost the match with a blown mindset", "Went fishing but got eaten by the fish, lost the match", "Played terribly", "Simply suffered a loss in the match"', LOSE_POSITIVE: `"Lost the match with no way to turn it around", "Gave it my all, but still lost the match", "Though we lost, we still have honor", "Couldn't carry my teammates, lost the match", "Lost again, it hurts; I'd rather it be me losing"`, message: "{name}'s {hero_name} {comment}.\nKDA: {kda}, GPM/XPM: {gpm_xpm}, Last Hits/Denies: {lh_dn}, Damage/Tower Damage: {damage}, Kill/Death Contribution Rate: {kc_dc}", rank_changed: "Player {name} rank changed: {prev.medal} {prev.star} → {curr.medal} {curr.star}" }, logger: { fetch_guilds_failed: "Failed to fetch guild information.", match_tracked: "Tracked new match {match.id} from {#each messageToLogger as item}users in guild {item.platform}:{item.guildId} [{#each item.players as player}{player.nickname}({player.steamId}){#if player !== item.players[item.players.length - 1]}, {/if}{/each}]{#if item !== messageToLogger[messageToLogger.length - 1]}, {/if}{/each}.", parse_request_sent: "The parsing request for match {matchId} has been successfully sent to the STRATZ server.", parse_request_failed: "The parsing request for match {matchId} failed to send.", match_parsed: "Match {matchId} has been parsed{#if odParsed} by OpenDota{/if}, an image was generated and published to {#each guilds as guild}{guild.platform}:{guild.guildId}{#if guild !== guilds[guilds.length - 1]}, {/if}{/each}.", match_unparsed: "Match {matchId} exceeded the waiting time [{timeout}] and remains unparsed, an image was generated and published to {#each guilds as guild}{guild.platform}:{guild.guildId}{#if guild !== guilds[guilds.length - 1]}, {/if}{/each}.", waiting_for_parse: "Match {matchId} has not been parsed yet, has been waiting for {time} minutes.", report_sent: "Posted {title} on {platform}:{guildId}.", rank_sent: "Posted rank change information of {player.nickName} ({player.steamId}) on {platform}:{guildId}.", ejs_error: "Error rendering EJS template: {error}", cron_not_enabled: "Cron service is not enabled; match report tracking cannot run.", stratz_token_banned: "Stratz API request rejected (403). This usually means your token or IP has been temporarily restricted due to unusual activity. For details, see the documentation: http://sjtdev.github.io/koishi-plugin-dota2tracker/en-US/api-403.html", opendota_token_banned: "OpenDota API request rejected (403). Please check if the access limit has been exceeded.", stratz_api_query_error: "Stratz API returned partial data with errors: {cause}", opendota_parse_request_sent: "Parse request for match {matchId} has been sent to OpenDota servers successfully.", opendota_parse_request_failed: "Failed to send parse request for match {matchId} to OpenDota servers." }, time: { years_months_ago: "{years} years and {months} months ago", years_ago: "{years} years ago" } } };
793
793
  }
794
794
  });
795
795
 
@@ -817,7 +817,7 @@ var require_zh_CN_template = __commonJS({
817
817
  // src/locales/zh-CN.yml
818
818
  var require_zh_CN = __commonJS({
819
819
  "src/locales/zh-CN.yml"(exports2, module2) {
820
- module2.exports = { dota2tracker: { heroes_nicknames: { "0": '请严格遵循 "", "" 格式填写(如下方默认数据,注意是英文半角符号),如果格式有误将仅使用英雄默认名称。可以不包含英雄默认名称。', "1": '"敌法师", "敌法", "AM"', "2": '"斧王"', "3": '"祸乱之源", "祸乱", "水桶腰"', "4": '"血魔"', "5": '"水晶室女", "冰女", "CM"', "6": '"卓尔游侠", "小黑"', "7": '"撼地者", "小牛", "牛头"', "8": '"主宰", "剑圣", "jugg", "奶棒人"', "9": '"米拉娜", "白虎", "pom"', "10": '"变体精灵", "水人"', "11": '"影魔", "影魔王", "SF", "影儿魔儿"', "12": '"幻影长矛手", "PL"', "13": '"帕克"', "14": '"帕吉", "屠夫", "扒鸡", "啪唧"', "15": '"雷泽", "电魂", "电棍"', "16": '"沙王", "SK"', "17": '"风暴之灵", "蓝猫"', "18": '"斯温", "流浪剑客", "流浪"', "19": '"小小"', "20": '"复仇之魂", "复仇", "VS"', "21": '"风行者", "风行", "WR"', "22": '"宙斯"', "23": '"昆卡", "船长"', "25": '"莉娜", "火女"', "26": '"莱恩", "恶魔巫师", "Lion"', "27": '"暗影萨满", "小Y", "小歪"', "28": '"斯拉达", "大鱼", "大鱼人"', "29": '"潮汐猎人", "潮汐", "西瓜皮"', "30": '"巫医"', "31": '"巫妖"', "32": '"力丸", "隐形刺客", "隐刺"', "33": '"谜团"', "34": '"修补匠", "TK", "Tinker"', "35": '"狙击手", "矮人火枪手", "火枪", "传说哥"', "36": '"瘟疫法师", "死灵法", "NEC"', "37": '"术士", "Warlock"', "38": '"兽王"', "39": '"痛苦女王", "女王", "QOP"', "40": '"剧毒术士", "剧毒"', "41": '"虚空假面", "虚空", "JB脸"', "42": '"冥魂大帝", "骷髅王"', "43": '"死亡先知", "DP"', "44": '"幻影刺客", "幻刺", "PA"', "45": '"帕格纳", "骨法", "湮灭法师"', "46": '"圣堂刺客", "圣堂", "TA"', "47": '"冥界亚龙", "毒龙", "Viper"', "48": '"露娜", "月骑", "Luna"', "49": '"龙骑士", "龙骑"', "50": '"戴泽", "暗影牧师", "暗牧"', "51": '"发条技师", "发条"', "52": '"拉席克", "老鹿"', "53": '"先知"', "54": '"噬魂鬼", "小狗"', "55": '"黑暗贤者", "黑贤"', "56": '"克林克兹", "小骷髅"', "57": '"全能骑士", "全能"', "58": '"魅惑魔女", "小鹿"', "59": '"哈斯卡", "神灵", "神灵武士"', "60": '"暗夜魔王", "夜魔"', "61": '"育母蜘蛛", "蜘蛛"', "62": '"赏金猎人", "赏金"', "63": '"编织者", "蚂蚁"', "64": '"杰奇洛", "双头龙"', "65": '"蝙蝠骑士", "蝙蝠"', "66": '"陈", "老陈"', "67": '"幽鬼", "SPE", "UG"', "68": '"远古冰魄", "冰魂"', "69": '"末日使者", "末日", "Doom"', "70": '"熊战士", "拍拍", "拍拍熊"', "71": '"裂魂人", "白牛", "sb"', "72": '"矮人直升机", "飞机"', "73": '"炼金术士", "炼金"', "74": '"祈求者", "卡尔"', "75": '"沉默术士", "沉默"', "76": '"殁境神蚀者", "黑鸟"', "77": '"狼人"', "78": '"酒仙", "熊猫", "熊猫酒仙"', "79": '"暗影恶魔", "毒狗"', "80": '"德鲁伊", "熊德"', "81": '"混沌骑士", "混沌", "CK"', "82": '"米波"', "83": '"树精卫士", "大树", "树精"', "84": '"食人魔魔法师", "蓝胖"', "85": '"不朽尸王", "尸王"', "86": '"拉比克"', "87": '"干扰者", "萨尔"', "88": '"司夜刺客", "小强"', "89": '"娜迦海妖", "小娜迦"', "90": '"光之守卫", "光法"', "91": '"艾欧", "小精灵", "精灵", "IO"', "92": '"维萨吉", "死灵龙", "死灵飞龙"', "93": '"斯拉克", "小鱼", "小鱼人"', "94": '"美杜莎", "一姐", "美杜莎"', "95": '"巨魔战将", "巨魔", "巨馍蘸酱"', "96": '"半人马战行者", "人马", "半人马"', "97": '"马格纳斯", "猛犸"', "98": '"伐木机", "花母鸡"', "99": '"钢背兽", "钢背"', "100": '"巨牙海民", "海民"', "101": '"天怒法师", "天怒"', "102": '"亚巴顿"', "103": '"上古巨神", "大牛"', "104": '"军团指挥官", "军团"', "105": '"工程师", "炸弹", "炸弹人"', "106": '"灰烬之灵", "火猫"', "107": '"大地之灵", "土猫"', "108": '"孽主", "大屁股"', "109": '"恐怖利刃", "TB"', "110": '"凤凰", "烧鸡"', "111": '"神谕者", "神谕"', "112": '"寒冬飞龙", "冰龙"', "113": '"天穹守望者", "电狗"', "114": '"齐天大圣", "大圣"', "119": '"邪影芳灵", "小仙女", "花仙子"', "120": '"石鳞剑士", "滚滚"', "121": '"天涯墨客", "墨客"', "123": '"森海飞霞", "松鼠", "小松鼠", "小松许"', "126": '"虚无之灵", "紫猫"', "128": '"电炎绝手", "老奶奶"', "129": '"玛尔斯"', "131": '"百戏大王"', "135": '"破晓辰星", "大锤"', "136": '"玛西"', "137": '"獸", "畜"', "138": '"琼英碧灵", "奶绿", "绿奶奶"', "145": '"凯", "鸟人"' }, broadcast: { WIN_NEGATIVE: '"侥幸赢得了比赛", "走狗屎运赢得了比赛", "躺赢了比赛", "打团都没来, 队友4V5赢得了比赛"', WIN_POSITIVE: '"带领团队走向了胜利", "暴打对面后赢得了胜利", " CARRY全场赢得了胜利", "把对面当猪宰了, 赢得了胜利", "又赢了, 这游戏就是这么枯燥, 且乏味", "直接进行一个比赛的赢"', LOSE_NEGATIVE: '"被人按在地上摩擦, 输掉了这场比赛", "悲惨地输掉了比赛", "头都被打歪了, 心态爆炸地输掉了比赛", "捕鱼被鱼吃了, 输掉了比赛", "打的是个几把", "直接进行一个比赛的输"', LOSE_POSITIVE: '"无力回天输掉了比赛", "尽力了, 但还是输了比赛", "背靠世界树, 虽败犹荣", "带不动队友, 输了比赛", "又输了, 很难受, 宁愿输的是我"', message: "{name}的{hero_name}{comment}。\nKDA:{kda},GPM/XPM:{gpm_xpm},补刀/反补:{lh_dn},伤害/塔伤:{damage},参战/参葬率:{kc_dc}", rank_changed: "群友 {name} 段位变动:{prev.medal}{prev.star} → {curr.medal}{curr.star}" }, logger: { fetch_guilds_failed: "获取群组信息失败,将继续后续步骤。", match_tracked: "追踪到最新比赛 {match.id} 来自{#each messageToLogger as item}群组 {item.platform}:{item.guildId} 的玩家 [{#each item.players as player}{player.nickname}({player.steamId}){#if player !== item.players[item.players.length - 1]}、{/if}{/each}]{#if item !== messageToLogger[messageToLogger.length - 1]}、{/if}{/each}。", parse_request_sent: "比赛 {matchId} 解析请求已成功发送至STRATZ服务器。", parse_request_failed: "比赛 {matchId} 解析请求发送失败。", match_parsed: "比赛 {matchId} 已{#if odParsed}由 OpenDota {/if}解析,生成图片并发布于{#each guilds as guild}{guild.platform}:{guild.guildId}{#if guild !== guilds[guilds.length - 1]}、{/if}{/each}。", match_unparsed: "比赛 {matchId} 超过等待时间[{timeout}分钟]仍未解析,生成图片并发布于{#each guilds as guild}{guild.platform}:{guild.guildId}{#if guild !== guilds[guilds.length - 1]}、{/if}{/each}。", waiting_for_parse: "比赛 {matchId} 尚未解析完成,已等待{time}分钟。", report_sent: "发布{title}于{platform}:{guildId}。", rank_sent: "向{platform}:{guildId}发布{player.nickName}({player.steamId})的段位变动信息。", ejs_error: "EJS模板渲染错误:{error}", cron_not_enabled: "未启用cron服务,无法运行战报追踪等定时任务。", stratz_token_banned: "Stratz API 请求被拒绝(403),若频繁发生很有可能意味着您的Token或IP因异常使用被临时限制访问。有关此报错请见文档:http://sjtdev.github.io/koishi-plugin-dota2tracker/api-403.html", opendota_token_banned: "OpenDota API 请求被拒绝(403),请注意访问次数是否超限。", stratz_api_query_error: "Stratz API 返回了有效数据,但同时也返回了查询报错。错误信息: {cause}", opendota_parse_request_sent: "比赛 {matchId} 解析请求已成功发送至 OpenDota 服务器。", opendota_parse_request_failed: "比赛 {matchId} 解析请求向 OpenDota 服务器发送失败。" }, time: { years_months_ago: "{years}年{months}个月前", years_ago: "{years}年前" } } };
820
+ module2.exports = { dota2tracker: { heroes_nicknames: { "0": '请严格遵循 "", "" 格式填写(如下方默认数据,注意是英文半角符号),如果格式有误将仅使用英雄默认名称。可以不包含英雄默认名称。', "1": '"敌法师", "敌法", "AM"', "2": '"斧王"', "3": '"祸乱之源", "祸乱", "水桶腰"', "4": '"血魔"', "5": '"水晶室女", "冰女", "CM"', "6": '"卓尔游侠", "小黑"', "7": '"撼地者", "小牛", "牛头"', "8": '"主宰", "剑圣", "jugg", "奶棒人"', "9": '"米拉娜", "白虎", "pom"', "10": '"变体精灵", "水人"', "11": '"影魔", "影魔王", "SF", "影儿魔儿"', "12": '"幻影长矛手", "PL"', "13": '"帕克"', "14": '"帕吉", "屠夫", "扒鸡", "啪唧"', "15": '"雷泽", "电魂", "电棍"', "16": '"沙王", "SK"', "17": '"风暴之灵", "蓝猫"', "18": '"斯温", "流浪剑客", "流浪"', "19": '"小小"', "20": '"复仇之魂", "复仇", "VS"', "21": '"风行者", "风行", "WR"', "22": '"宙斯"', "23": '"昆卡", "船长"', "25": '"莉娜", "火女"', "26": '"莱恩", "恶魔巫师", "Lion"', "27": '"暗影萨满", "小Y", "小歪"', "28": '"斯拉达", "大鱼", "大鱼人"', "29": '"潮汐猎人", "潮汐", "西瓜皮"', "30": '"巫医"', "31": '"巫妖"', "32": '"力丸", "隐形刺客", "隐刺"', "33": '"谜团"', "34": '"修补匠", "TK", "Tinker"', "35": '"狙击手", "矮人火枪手", "火枪", "传说哥"', "36": '"瘟疫法师", "死灵法", "NEC"', "37": '"术士", "Warlock"', "38": '"兽王"', "39": '"痛苦女王", "女王", "QOP"', "40": '"剧毒术士", "剧毒"', "41": '"虚空假面", "虚空", "JB脸"', "42": '"冥魂大帝", "骷髅王"', "43": '"死亡先知", "DP"', "44": '"幻影刺客", "幻刺", "PA"', "45": '"帕格纳", "骨法", "湮灭法师"', "46": '"圣堂刺客", "圣堂", "TA"', "47": '"冥界亚龙", "毒龙", "Viper"', "48": '"露娜", "月骑", "Luna"', "49": '"龙骑士", "龙骑"', "50": '"戴泽", "暗影牧师", "暗牧"', "51": '"发条技师", "发条"', "52": '"拉席克", "老鹿"', "53": '"先知"', "54": '"噬魂鬼", "小狗"', "55": '"黑暗贤者", "黑贤"', "56": '"克林克兹", "小骷髅"', "57": '"全能骑士", "全能"', "58": '"魅惑魔女", "小鹿"', "59": '"哈斯卡", "神灵", "神灵武士"', "60": '"暗夜魔王", "夜魔"', "61": '"育母蜘蛛", "蜘蛛"', "62": '"赏金猎人", "赏金"', "63": '"编织者", "蚂蚁"', "64": '"杰奇洛", "双头龙"', "65": '"蝙蝠骑士", "蝙蝠"', "66": '"陈", "老陈"', "67": '"幽鬼", "SPE", "UG"', "68": '"远古冰魄", "冰魂"', "69": '"末日使者", "末日", "Doom"', "70": '"熊战士", "拍拍", "拍拍熊"', "71": '"裂魂人", "白牛", "sb"', "72": '"矮人直升机", "飞机"', "73": '"炼金术士", "炼金"', "74": '"祈求者", "卡尔"', "75": '"沉默术士", "沉默"', "76": '"殁境神蚀者", "黑鸟"', "77": '"狼人"', "78": '"酒仙", "熊猫", "熊猫酒仙"', "79": '"暗影恶魔", "毒狗"', "80": '"德鲁伊", "熊德"', "81": '"混沌骑士", "混沌", "CK"', "82": '"米波"', "83": '"树精卫士", "大树", "树精"', "84": '"食人魔魔法师", "蓝胖"', "85": '"不朽尸王", "尸王"', "86": '"拉比克"', "87": '"干扰者", "萨尔"', "88": '"司夜刺客", "小强"', "89": '"娜迦海妖", "小娜迦"', "90": '"光之守卫", "光法"', "91": '"艾欧", "小精灵", "精灵", "IO"', "92": '"维萨吉", "死灵龙", "死灵飞龙"', "93": '"斯拉克", "小鱼", "小鱼人"', "94": '"美杜莎", "一姐", "美杜莎"', "95": '"巨魔战将", "巨魔", "巨馍蘸酱"', "96": '"半人马战行者", "人马", "半人马"', "97": '"马格纳斯", "猛犸"', "98": '"伐木机", "花母鸡"', "99": '"钢背兽", "钢背"', "100": '"巨牙海民", "海民"', "101": '"天怒法师", "天怒"', "102": '"亚巴顿"', "103": '"上古巨神", "大牛"', "104": '"军团指挥官", "军团"', "105": '"工程师", "炸弹", "炸弹人"', "106": '"灰烬之灵", "火猫"', "107": '"大地之灵", "土猫"', "108": '"孽主", "大屁股"', "109": '"恐怖利刃", "TB"', "110": '"凤凰", "烧鸡"', "111": '"神谕者", "神谕"', "112": '"寒冬飞龙", "冰龙"', "113": '"天穹守望者", "电狗"', "114": '"齐天大圣", "大圣"', "119": '"邪影芳灵", "小仙女", "花仙子"', "120": '"石鳞剑士", "滚滚"', "121": '"天涯墨客", "墨客"', "123": '"森海飞霞", "松鼠", "小松鼠", "小松许"', "126": '"虚无之灵", "紫猫"', "128": '"电炎绝手", "老奶奶"', "129": '"玛尔斯"', "131": '"百戏大王"', "135": '"破晓辰星", "大锤"', "136": '"玛西"', "137": '"獸", "畜"', "138": '"琼英碧灵", "奶绿", "绿奶奶"', "145": '"凯", "鸟人"', "155": '"朗戈"' }, broadcast: { WIN_NEGATIVE: '"侥幸赢得了比赛", "走狗屎运赢得了比赛", "躺赢了比赛", "打团都没来, 队友4V5赢得了比赛"', WIN_POSITIVE: '"带领团队走向了胜利", "暴打对面后赢得了胜利", " CARRY全场赢得了胜利", "把对面当猪宰了, 赢得了胜利", "又赢了, 这游戏就是这么枯燥, 且乏味", "直接进行一个比赛的赢"', LOSE_NEGATIVE: '"被人按在地上摩擦, 输掉了这场比赛", "悲惨地输掉了比赛", "头都被打歪了, 心态爆炸地输掉了比赛", "捕鱼被鱼吃了, 输掉了比赛", "打的是个几把", "直接进行一个比赛的输"', LOSE_POSITIVE: '"无力回天输掉了比赛", "尽力了, 但还是输了比赛", "背靠世界树, 虽败犹荣", "带不动队友, 输了比赛", "又输了, 很难受, 宁愿输的是我"', message: "{name}的{hero_name}{comment}。\nKDA:{kda},GPM/XPM:{gpm_xpm},补刀/反补:{lh_dn},伤害/塔伤:{damage},参战/参葬率:{kc_dc}", rank_changed: "群友 {name} 段位变动:{prev.medal}{prev.star} → {curr.medal}{curr.star}" }, logger: { fetch_guilds_failed: "获取群组信息失败,将继续后续步骤。", match_tracked: "追踪到最新比赛 {match.id} 来自{#each messageToLogger as item}群组 {item.platform}:{item.guildId} 的玩家 [{#each item.players as player}{player.nickname}({player.steamId}){#if player !== item.players[item.players.length - 1]}、{/if}{/each}]{#if item !== messageToLogger[messageToLogger.length - 1]}、{/if}{/each}。", parse_request_sent: "比赛 {matchId} 解析请求已成功发送至STRATZ服务器。", parse_request_failed: "比赛 {matchId} 解析请求发送失败。", match_parsed: "比赛 {matchId} 已{#if odParsed}由 OpenDota {/if}解析,生成图片并发布于{#each guilds as guild}{guild.platform}:{guild.guildId}{#if guild !== guilds[guilds.length - 1]}、{/if}{/each}。", match_unparsed: "比赛 {matchId} 超过等待时间[{timeout}分钟]仍未解析,生成图片并发布于{#each guilds as guild}{guild.platform}:{guild.guildId}{#if guild !== guilds[guilds.length - 1]}、{/if}{/each}。", waiting_for_parse: "比赛 {matchId} 尚未解析完成,已等待{time}分钟。", report_sent: "发布{title}于{platform}:{guildId}。", rank_sent: "向{platform}:{guildId}发布{player.nickName}({player.steamId})的段位变动信息。", ejs_error: "EJS模板渲染错误:{error}", cron_not_enabled: "未启用cron服务,无法运行战报追踪等定时任务。", stratz_token_banned: "Stratz API 请求被拒绝(403),若频繁发生很有可能意味着您的Token或IP因异常使用被临时限制访问。有关此报错请见文档:http://sjtdev.github.io/koishi-plugin-dota2tracker/api-403.html", opendota_token_banned: "OpenDota API 请求被拒绝(403),请注意访问次数是否超限。", stratz_api_query_error: "Stratz API 返回了有效数据,但同时也返回了查询报错。错误信息: {cause}", opendota_parse_request_sent: "比赛 {matchId} 解析请求已成功发送至 OpenDota 服务器。", opendota_parse_request_failed: "比赛 {matchId} 解析请求向 OpenDota 服务器发送失败。" }, time: { years_months_ago: "{years}年{months}个月前", years_ago: "{years}年前" } } };
821
821
  }
822
822
  });
823
823
 
@@ -835,7 +835,6 @@ var import_path5 = __toESM(require("path"));
835
835
 
836
836
  // src/app/common/i18n.ts
837
837
  var import_koishi = require("koishi");
838
- var dotaconstants = __toESM(require("dotaconstants"));
839
838
 
840
839
  // src/app/common/utils.ts
841
840
  var import_luxon = require("luxon");
@@ -1050,7 +1049,7 @@ var I18NService = class extends import_koishi.Service {
1050
1049
  */
1051
1050
  _buildNicknameMap(languageTag) {
1052
1051
  this.logger.debug(`Building nickname map for ${languageTag}...`);
1053
- const heroIds = Object.keys(dotaconstants.heroes).map(Number);
1052
+ const heroIds = Object.keys(this.ctx.dota2tracker.dotaconstants.heroes).map(Number);
1054
1053
  const nicknameMap = /* @__PURE__ */ new Map();
1055
1054
  for (const heroId of heroIds) {
1056
1055
  const allNames = this._getAllHeroNames(heroId, languageTag);
@@ -1065,7 +1064,7 @@ var I18NService = class extends import_koishi.Service {
1065
1064
  const inputStr = String(input).toLowerCase();
1066
1065
  if (/^\d+$/.test(inputStr)) {
1067
1066
  const heroId = Number(inputStr);
1068
- if (dotaconstants.heroes[heroId]) {
1067
+ if (this.ctx.dota2tracker.dotaconstants.heroes[heroId]) {
1069
1068
  return heroId;
1070
1069
  }
1071
1070
  }
@@ -1091,7 +1090,6 @@ var I18NService = class extends import_koishi.Service {
1091
1090
 
1092
1091
  // src/app/core/hero.service.ts
1093
1092
  var import_koishi2 = require("koishi");
1094
- var dotaconstants2 = __toESM(require("dotaconstants"));
1095
1093
  var import_luxon2 = require("luxon");
1096
1094
 
1097
1095
  // src/app/common/constants.ts
@@ -1140,7 +1138,7 @@ var HeroService = class _HeroService extends import_koishi2.Service {
1140
1138
  return weeklyHeroMeta;
1141
1139
  }
1142
1140
  async getHeroDetails(input, languageTag, isRandom = false) {
1143
- const heroId = this.ctx.dota2tracker.i18n.findHeroIdInLocale(isRandom ? import_koishi2.Random.pick(Object.keys(dotaconstants2.heroes)) : input);
1141
+ const heroId = this.ctx.dota2tracker.i18n.findHeroIdInLocale(isRandom ? import_koishi2.Random.pick(Object.keys(this.ctx.dota2tracker.dotaconstants.heroes)) : input);
1144
1142
  if (!heroId) return;
1145
1143
  return _HeroService.formatHeroDetails(await this.ctx.dota2tracker.valveAPI.queryHeroDetailsFromValve(heroId, languageTag));
1146
1144
  }
@@ -1300,7 +1298,7 @@ var ItemService = class _ItemService extends import_koishi3.Service {
1300
1298
  }
1301
1299
  static getFormattedItemListData(rawItems) {
1302
1300
  const processItemName = /* @__PURE__ */ __name((name2) => name2.replace(/^item_/i, "").replace(/^recipe_/i, "recipe_"), "processItemName");
1303
- const [recipes, items3] = rawItems.reduce(
1301
+ const [recipes, items] = rawItems.reduce(
1304
1302
  (acc, item) => {
1305
1303
  const processed = {
1306
1304
  ...item,
@@ -1314,14 +1312,14 @@ var ItemService = class _ItemService extends import_koishi3.Service {
1314
1312
  [[], []]
1315
1313
  );
1316
1314
  const itemMap = /* @__PURE__ */ new Map();
1317
- items3.concat(recipes).forEach(
1315
+ items.concat(recipes).forEach(
1318
1316
  (item) => itemMap.set(item.id, {
1319
1317
  id: item.id,
1320
1318
  name: item.name,
1321
1319
  name_loc: item.name_loc
1322
1320
  })
1323
1321
  );
1324
- const processedItems = items3.map((baseItem) => {
1322
+ const processedItems = items.map((baseItem) => {
1325
1323
  const recipe = recipes.find((r) => r.name === `recipe_${baseItem.name.replace("item_", "")}`);
1326
1324
  return {
1327
1325
  ...baseItem,
@@ -1354,19 +1352,19 @@ var ItemService = class _ItemService extends import_koishi3.Service {
1354
1352
  }))
1355
1353
  }));
1356
1354
  }
1357
- searchItems(items3, keyword, languageTag, config) {
1355
+ searchItems(items, keyword, languageTag, config) {
1358
1356
  if (!keyword) return [];
1359
1357
  const alias = this.ctx.dota2tracker.i18n.getConstantLocale(languageTag).dota2tracker.items_alias?.[keyword] ?? config.customItemAlias.filter((cia) => cia.alias == keyword).map((cia) => cia.keyword);
1360
- const exactMatch = items3.filter(
1358
+ const exactMatch = items.filter(
1361
1359
  (item) => alias?.some((a) => item.name_loc.trim().toLowerCase() == a.toLowerCase()) || item.name_loc.trim().toLowerCase() === keyword.trim().toLowerCase() || Number.isInteger(Number(keyword)) && item.id === Number(keyword)
1362
1360
  );
1363
1361
  if (exactMatch.length) return exactMatch;
1364
- return this.fuzzySearchItems(alias.length ? alias : [keyword], items3);
1362
+ return this.fuzzySearchItems(alias.length ? alias : [keyword], items);
1365
1363
  }
1366
- fuzzySearchItems(keywords, items3) {
1364
+ fuzzySearchItems(keywords, items) {
1367
1365
  const resultMap = /* @__PURE__ */ new Map();
1368
1366
  if (!keywords.length) return [];
1369
- for (const item of items3) {
1367
+ for (const item of items) {
1370
1368
  const cleanName = item.name_loc.toLowerCase().replace(/[^\p{L}\p{N}]/gu, "").trim();
1371
1369
  let matchAllKeywords = true;
1372
1370
  for (const keyword of keywords) {
@@ -1393,7 +1391,6 @@ var ItemService = class _ItemService extends import_koishi3.Service {
1393
1391
 
1394
1392
  // src/app/core/match.service.ts
1395
1393
  var import_koishi4 = require("koishi");
1396
- var dotaconstants3 = __toESM(require("dotaconstants"));
1397
1394
 
1398
1395
  // src/app/common/error.ts
1399
1396
  var import_util = require("util");
@@ -1629,7 +1626,7 @@ var MatchService = class _MatchService extends import_koishi4.Service {
1629
1626
  }
1630
1627
  const facetData = await _MatchService.constantsInjectFacetData(constantsQuery, matchQuery, languageTag, this.ctx.dota2tracker.hero);
1631
1628
  this.ctx.dota2tracker.cache.setFacetConstantsCache(languageTag, constantsQuery);
1632
- const match = _MatchService.extendMatchData(matchQuery, facetData);
1629
+ const match = _MatchService.extendMatchData(matchQuery, facetData, this.ctx.dota2tracker.dotaconstants);
1633
1630
  return match;
1634
1631
  } catch (error) {
1635
1632
  this.ctx.dota2tracker.cache.deleteFacetConstantsCache(languageTag);
@@ -1654,7 +1651,7 @@ var MatchService = class _MatchService extends import_koishi4.Service {
1654
1651
  return facetData;
1655
1652
  }
1656
1653
  // 对比赛数据进行补充以供生成模板函数使用
1657
- static extendMatchData(matchQuery, facetData) {
1654
+ static extendMatchData(matchQuery, facetData, dotaconstants) {
1658
1655
  const match = matchQuery.match;
1659
1656
  const matchParsed = _MatchService.isMatchParsed(matchQuery);
1660
1657
  ["radiant", "dire"].forEach((team) => {
@@ -1774,9 +1771,9 @@ var MatchService = class _MatchService extends import_koishi4.Service {
1774
1771
  }
1775
1772
  purchaseTimesMap[item.itemId].push(item.time);
1776
1773
  } else {
1777
- const itemName = dotaconstants3.item_ids[item.itemId];
1774
+ const itemName = dotaconstants.item_ids[item.itemId];
1778
1775
  if (itemName) {
1779
- const itemDetails = dotaconstants3.items[itemName];
1776
+ const itemDetails = dotaconstants.items[itemName];
1780
1777
  if (itemDetails && itemDetails.cost) {
1781
1778
  player.utilityScore += itemDetails.cost;
1782
1779
  }
@@ -1789,7 +1786,7 @@ var MatchService = class _MatchService extends import_koishi4.Service {
1789
1786
  for (let itemId in supportItemsCount) {
1790
1787
  if (supportItemsCount[itemId] === 0) continue;
1791
1788
  player.supportItemsCount.push({
1792
- name: dotaconstants3.item_ids[itemId],
1789
+ name: dotaconstants.item_ids[itemId],
1793
1790
  count: supportItemsCount[itemId]
1794
1791
  });
1795
1792
  }
@@ -1797,13 +1794,13 @@ var MatchService = class _MatchService extends import_koishi4.Service {
1797
1794
  player.items = [];
1798
1795
  for (let i = 0; i <= 5; i++) {
1799
1796
  const itemId = player[`item${i}Id`];
1800
- const itemObject = createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices);
1797
+ const itemObject = createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices, dotaconstants);
1801
1798
  player.items.push(itemObject);
1802
1799
  }
1803
1800
  player.backpacks = [];
1804
1801
  for (let i = 0; i <= 2; i++) {
1805
1802
  const itemId = player[`backpack${i}Id`];
1806
- const itemObject = createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices);
1803
+ const itemObject = createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices, dotaconstants);
1807
1804
  player.backpacks.push(itemObject);
1808
1805
  }
1809
1806
  if (player.additionalUnit) {
@@ -1811,12 +1808,12 @@ var MatchService = class _MatchService extends import_koishi4.Service {
1811
1808
  player.unitBackpacks = [];
1812
1809
  for (let i = 0; i <= 5; i++) {
1813
1810
  const itemId = player.additionalUnit[`item${i}Id`];
1814
- const itemObject = createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices);
1811
+ const itemObject = createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices, dotaconstants);
1815
1812
  player.unitItems.push(itemObject);
1816
1813
  }
1817
1814
  for (let i = 0; i <= 2; i++) {
1818
1815
  const itemId = player.additionalUnit[`backpack${i}Id`];
1819
- const itemObject = createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices);
1816
+ const itemObject = createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices, dotaconstants);
1820
1817
  player.unitBackpacks.push(itemObject);
1821
1818
  }
1822
1819
  }
@@ -1895,15 +1892,15 @@ var MatchService = class _MatchService extends import_koishi4.Service {
1895
1892
  return matchQuery?.match?.parsedDateTime && matchQuery?.match?.players.filter((player) => player?.stats?.heroDamageReport?.dealtTotal).length > 0;
1896
1893
  }
1897
1894
  };
1898
- function createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices) {
1895
+ function createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices, dotaconstants) {
1899
1896
  if (itemId === void 0 || itemId === null) {
1900
1897
  return null;
1901
1898
  }
1902
- if (dotaconstants3.item_ids[itemId]) {
1899
+ if (dotaconstants.item_ids[itemId]) {
1903
1900
  const currentIndex = purchaseTimeIndices.get(itemId) || 0;
1904
1901
  const seconds = purchaseTimesMap[itemId]?.[currentIndex];
1905
1902
  purchaseTimeIndices.set(itemId, currentIndex + 1);
1906
- const name2 = dotaconstants3.item_ids[itemId];
1903
+ const name2 = dotaconstants.item_ids[itemId];
1907
1904
  const prefix = "recipe_";
1908
1905
  const isRecipe = name2.startsWith(prefix);
1909
1906
  const cleanName = isRecipe ? name2.substring(prefix.length) : name2;
@@ -1921,7 +1918,6 @@ __name(createItemObject, "createItemObject");
1921
1918
 
1922
1919
  // src/app/core/player.service.ts
1923
1920
  var import_koishi5 = require("koishi");
1924
- var dotaconstants4 = __toESM(require("dotaconstants"));
1925
1921
  var import_luxon3 = require("luxon");
1926
1922
  var PlayerService = class _PlayerService extends import_koishi5.Service {
1927
1923
  static {
@@ -2051,12 +2047,15 @@ var PlayerService = class _PlayerService extends import_koishi5.Service {
2051
2047
  dotaPlus: null
2052
2048
  }
2053
2049
  };
2054
- const player = _PlayerService.extendPlayerData({
2055
- playerQuery,
2056
- playerExtraQuery,
2057
- genHero: heroId ? { heroId, name: this.ctx.dota2tracker.i18n.getConstantLocale(languageTag).dota2tracker.template.hero_names[heroId] } : null,
2058
- estimateRank: this.config.playerRankEstimate
2059
- });
2050
+ const player = _PlayerService.extendPlayerData(
2051
+ {
2052
+ playerQuery,
2053
+ playerExtraQuery,
2054
+ genHero: heroId ? { heroId, name: this.ctx.dota2tracker.i18n.getConstantLocale(languageTag).dota2tracker.template.hero_names[heroId] } : null,
2055
+ estimateRank: this.config.playerRankEstimate
2056
+ },
2057
+ this.ctx.dota2tracker.dotaconstants
2058
+ );
2060
2059
  return player;
2061
2060
  }
2062
2061
  async validateSteamId(steamId) {
@@ -2078,14 +2077,14 @@ var PlayerService = class _PlayerService extends import_koishi5.Service {
2078
2077
  };
2079
2078
  }
2080
2079
  }
2081
- static extendPlayerData(param) {
2080
+ static extendPlayerData(param, dotaconstants) {
2082
2081
  const { playerQuery, playerExtraQuery, genHero, estimateRank } = param;
2083
2082
  const player = playerQuery.player;
2084
2083
  const playerExtra = playerExtraQuery?.player;
2085
2084
  if (player.steamAccount.isAnonymous) {
2086
2085
  for (let index = 0; index < 25; index++) {
2087
2086
  const random = new import_koishi5.Random(() => enhancedSimpleHashToSeed(`${player.steamAccount.id}-${index}`));
2088
- const heroId = random.pick(Object.keys(dotaconstants4.heroes));
2087
+ const heroId = random.pick(Object.keys(dotaconstants.heroes));
2089
2088
  player.matches.push({
2090
2089
  id: 1e9 + index,
2091
2090
  gameMode: "UNKNOWN",
@@ -2102,7 +2101,7 @@ var PlayerService = class _PlayerService extends import_koishi5.Service {
2102
2101
  kills: random.int(0, 20),
2103
2102
  deaths: random.int(0, 20),
2104
2103
  assists: random.int(0, 20),
2105
- hero: { id: heroId, shortName: dotaconstants4.heroes[heroId].name.match(/^npc_dota_hero_(.+)$/)[1] }
2104
+ hero: { id: heroId, shortName: dotaconstants.heroes[heroId].name.match(/^npc_dota_hero_(.+)$/)[1] }
2106
2105
  }
2107
2106
  ]
2108
2107
  });
@@ -2646,7 +2645,6 @@ var import_koishi10 = require("koishi");
2646
2645
  var import_ejs = __toESM(require("ejs"));
2647
2646
  var import_fs2 = __toESM(require("fs"));
2648
2647
  var import_path2 = __toESM(require("path"));
2649
- var dotaconstants5 = __toESM(require("dotaconstants"));
2650
2648
 
2651
2649
  // src/app/common/types.ts
2652
2650
  var ImageType = /* @__PURE__ */ ((ImageType2) => {
@@ -2694,7 +2692,7 @@ var ImageRenderer = class extends import_koishi10.Service {
2694
2692
  data,
2695
2693
  ImageType,
2696
2694
  ImageFormat,
2697
- dotaconstants: dotaconstants5,
2695
+ dotaconstants: this.ctx.dota2tracker.dotaconstants,
2698
2696
  DateTime: import_luxon5.DateTime,
2699
2697
  $t: /* @__PURE__ */ __name((key, params) => this.ctx.dota2tracker.i18n.$t(languageTag, key, params), "$t"),
2700
2698
  languageTag,
@@ -3769,7 +3767,6 @@ var OpenDotaAPI = class extends import_koishi15.Service {
3769
3767
 
3770
3768
  // src/app/core/opendota.adapter.ts
3771
3769
  var import_koishi16 = require("koishi");
3772
- var dotaconstants6 = __toESM(require("dotaconstants"));
3773
3770
  var OpenDotaAdapter = class extends import_koishi16.Service {
3774
3771
  static {
3775
3772
  __name(this, "OpenDotaAdapter");
@@ -3824,9 +3821,9 @@ var OpenDotaAdapter = class extends import_koishi16.Service {
3824
3821
  steamAccount: { name: _player.personaname, seasonRank: _player.rank_tier, seasonLeaderboardRank: null },
3825
3822
  hero: {
3826
3823
  id: _player.hero_id,
3827
- name: dotaconstants6.heroes[_player.hero_id].name,
3828
- shortName: dotaconstants6.heroes[_player.hero_id].name.match(/^npc_dota_hero_(.+)$/)[1],
3829
- facets: [...dotaconstants6.hero_abilities[dotaconstants6.heroes[_player.hero_id].name].facets.map((f) => ({ id: -1, name: f.name }))]
3824
+ name: this.ctx.dota2tracker.dotaconstants.heroes[_player.hero_id].name,
3825
+ shortName: this.ctx.dota2tracker.dotaconstants.heroes[_player.hero_id].name.match(/^npc_dota_hero_(.+)$/)[1],
3826
+ facets: [...this.ctx.dota2tracker.dotaconstants.hero_abilities[this.ctx.dota2tracker.dotaconstants.heroes[_player.hero_id].name].facets.map((f) => ({ id: -1, name: f.name }))]
3830
3827
  },
3831
3828
  dotaPlus: null,
3832
3829
  stats: {
@@ -3857,7 +3854,7 @@ var OpenDotaAdapter = class extends import_koishi16.Service {
3857
3854
  disableCount: 0
3858
3855
  }
3859
3856
  },
3860
- itemPurchases: _player.purchase_log.map((p) => ({ time: p.time, itemId: dotaconstants6.items[p.key].id }))
3857
+ itemPurchases: _player.purchase_log.map((p) => ({ time: p.time, itemId: this.ctx.dota2tracker.dotaconstants.items[p.key].id }))
3861
3858
  },
3862
3859
  additionalUnit: null
3863
3860
  };
@@ -3886,8 +3883,8 @@ var OpenDotaAdapter = class extends import_koishi16.Service {
3886
3883
  const match = {
3887
3884
  id: _match.match_id,
3888
3885
  didRadiantWin: _match.radiant_win,
3889
- lobbyType: convertLobbyType(_match.lobby_type),
3890
- gameMode: convertGameMode(_match.game_mode),
3886
+ lobbyType: convertLobbyType(_match.lobby_type, this.ctx.dota2tracker.dotaconstants),
3887
+ gameMode: convertGameMode(_match.game_mode, this.ctx.dota2tracker.dotaconstants),
3891
3888
  regionId: _match.region,
3892
3889
  parsedDateTime: _match.start_time + _match.duration,
3893
3890
  startDateTime: _match.start_time,
@@ -3972,7 +3969,7 @@ function convertPosition(openDotaPosition) {
3972
3969
  }
3973
3970
  }
3974
3971
  __name(convertPosition, "convertPosition");
3975
- function convertLobbyType(openDotaLobbyType) {
3972
+ function convertLobbyType(openDotaLobbyType, dotaconstants) {
3976
3973
  const map = {
3977
3974
  lobby_type_normal: "UNRANKED" /* Unranked */,
3978
3975
  lobby_type_practice: "PRACTICE" /* Practice */,
@@ -3989,11 +3986,11 @@ function convertLobbyType(openDotaLobbyType) {
3989
3986
  lobby_type_new_player: "COOP_VS_BOTS" /* CoopVsBots */,
3990
3987
  lobby_type_featured: "EVENT" /* Event */
3991
3988
  };
3992
- return map[dotaconstants6.lobby_type[openDotaLobbyType].name] || "EVENT" /* Event */;
3989
+ return map[dotaconstants.lobby_type[openDotaLobbyType].name] || "EVENT" /* Event */;
3993
3990
  }
3994
3991
  __name(convertLobbyType, "convertLobbyType");
3995
- function convertGameMode(openDotaGameModeId) {
3996
- const gameModeName = dotaconstants6.game_mode[openDotaGameModeId]?.name;
3992
+ function convertGameMode(openDotaGameModeId, dotaconstants) {
3993
+ const gameModeName = dotaconstants.game_mode[openDotaGameModeId]?.name;
3997
3994
  switch (gameModeName) {
3998
3995
  case "game_mode_all_pick":
3999
3996
  return "ALL_PICK" /* AllPick */;
@@ -4319,10 +4316,13 @@ var inject = {
4319
4316
  optional: ["cron", "console"]
4320
4317
  };
4321
4318
  async function apply(ctx, config) {
4319
+ const lib = await import("dotaconstants");
4320
+ const dotaconstants = lib.default || lib;
4322
4321
  const logger = ctx.logger("dota2tracker");
4323
4322
  const currentDir = import_path5.default.resolve(__dirname);
4324
4323
  const pluginVersion = require(import_path5.default.join(currentDir, "..", "package.json")).version;
4325
4324
  ctx.dota2tracker = {};
4325
+ ctx.dota2tracker.dotaconstants = dotaconstants;
4326
4326
  ctx.dota2tracker.i18n = new I18NService(ctx);
4327
4327
  ctx.dota2tracker.image = new ImageRenderer(ctx, currentDir);
4328
4328
  ctx.dota2tracker.messageBuilder = new MessageBuilder(ctx);
@@ -1 +1 @@
1
- html{overflow:visible}body{display:flex;flex-direction:column;overflow:visible}#regular{width:800px}#extra{font-size:10px;width:100%;>.tip{width:100%;line-height:4;text-align:center;color:#ccc}#charts{display:flex;>*{width:50%}}.container{height:300px;display:flex;.lane_outcome{position:relative;display:flex;flex-direction:column;width:500px;margin-right:20px;>.title{width:100%;text-align:center;padding:0;margin:0;line-height:50px}.panel{display:flex;flex-direction:column;height:100%;justify-content:space-evenly;.lane{display:flex;flex-direction:column;border-radius:10px;border:#ccc solid 1px;padding:2px;>.title{width:100%;text-align:center;height:32px;>p:nth-child(1){font-size:12px}>p:nth-child(2){font-size:14px}}img.hero{width:24px;height:24px}.kda{height:100%;line-height:32px;text-align:center;font-size:10px}.graph{height:32px;display:flex;align-items:center;justify-content:center;svg{shape-rendering:crispEdges}text{dominant-baseline:middle;white-space:nowrap}}}.details{display:grid;grid-template-columns:24px 32px 44px auto 44px 32px 24px;grid-template-rows:1fr;gap:1px;font-size:12px;height:32px;line-height:32px;align-items:center}}.subtitle{position:absolute;inset:36px 0 0;text-align:center;color:#ccc;font-size:12px;margin:0;z-index:1}}.map{box-sizing:border-box;width:300px;padding:25px;font-size:8px;pointer-events:none;text-shadow:0px 1px 1px rgba(0,0,0,.8);use{&.radiant{color:#95cc4b}&.dire{color:#ca4633}&.dead{color:#555}}}}}
1
+ html{overflow:visible}body{display:flex;flex-direction:column;overflow:visible}#regular{width:800px}#extra{font-size:10px;width:100%;>.tip{width:100%;line-height:4;text-align:center;color:#ccc}#charts{display:flex;>*{width:50%}}.container{height:300px;display:flex;.lane_outcome{position:relative;display:flex;flex-direction:column;width:500px;margin-right:20px;>.title{width:100%;text-align:center;padding:0;margin:0;line-height:50px}.panel{display:flex;flex-direction:column;height:100%;justify-content:space-evenly;.lane{display:flex;flex-direction:column;border-radius:10px;border:#ccc solid 1px;padding:2px;>.title{width:100%;text-align:center;height:32px;>p:nth-child(1){font-size:12px}>p:nth-child(2){font-size:14px}}img.hero{width:24px;height:24px}.kda{height:100%;line-height:32px;text-align:center;font-size:10px}.graph{height:32px;display:flex;align-items:center;justify-content:center;svg{shape-rendering:crispEdges}text{dominant-baseline:middle;white-space:nowrap}}}.details{display:grid;grid-template-columns:24px 32px 44px auto 44px 32px 24px;grid-template-rows:1fr;gap:1px;font-size:12px;height:32px;line-height:32px;align-items:center}}.subtitle{position:absolute;inset:36px 0 0;text-align:center;color:#ccc;font-size:12px;margin:0;z-index:1}}.map{box-sizing:border-box;width:300px;padding:25px;font-size:8px;pointer-events:none;text-shadow:0px 1px 1px rgba(0,0,0,.8);image{clip-path:inset(2% round 12px);opacity:.88;object-fit:contain}use{&.radiant{color:#95cc4b}&.dire{color:#ca4633}&.dead{color:#555}}}}}
@@ -2,67 +2,67 @@
2
2
  const BUILDINGS = [
3
3
  // ================= 天辉 Radiant (左下) =================
4
4
  // 上路
5
- { id: 16, name: 'Rad Top T1', type: 'tower', lane: "top", bit: 0, team: 'radiant', x: 25, y: 93 },
6
- { id: 19, name: 'Rad Top T2', type: 'tower', lane: "top", bit: 1, team: 'radiant', x: 23, y: 135 },
7
- { id: 22, name: 'Rad Top T3', type: 'tower', lane: "top", bit: 2, team: 'radiant', x: 21, y: 174 },
8
- { id: 38, name: 'Rad Top Melee', type: 'rax', lane: "top", bit: 0, team: 'radiant', x: 18, y: 181 },
9
- { id: 41, name: 'Rad Top Range', type: 'rax', lane: "top", bit: 1, team: 'radiant', x: 26, y: 181 },
10
- { id: 38, name: 'Rad Top HG Time', type: 'rax_time', lane: "top", bit: 0, team: 'radiant', x: 27, y: 184 },
5
+ { id: 16, name: 'Rad Top T1', type: 'tower', lane: "top", bit: 0, team: 'radiant', x: 35.8, y: 96.5 },
6
+ { id: 19, name: 'Rad Top T2', type: 'tower', lane: "top", bit: 1, team: 'radiant', x: 33.7, y: 133.8 },
7
+ { id: 22, name: 'Rad Top T3', type: 'tower', lane: "top", bit: 2, team: 'radiant', x: 32.5, y: 168.4 },
8
+ { id: 38, name: 'Rad Top Melee', type: 'rax', lane: "top", bit: 0, team: 'radiant', x: 36.8, y: 174.5 },
9
+ { id: 41, name: 'Rad Top Range', type: 'rax', lane: "top", bit: 1, team: 'radiant', x: 30, y: 174.5 },
10
+ { id: 38, name: 'Rad Top HG Time', type: 'rax_time', lane: "top", bit: 0, team: 'radiant', x: 38.6, y: 180 },
11
11
 
12
12
  // 中路
13
- { id: 17, name: 'Rad Mid T1', type: 'tower', lane: "mid", bit: 3, team: 'radiant', x: 98, y: 143 },
14
- { id: 20, name: 'Rad Mid T2', type: 'tower', lane: "mid", bit: 4, team: 'radiant', x: 73, y: 166 },
15
- { id: 23, name: 'Rad Mid T3', type: 'tower', lane: "mid", bit: 5, team: 'radiant', x: 51, y: 185 },
16
- { id: 39, name: 'Rad Mid Melee', type: 'rax', lane: "mid", bit: 2, team: 'radiant', x: 46, y: 187 },
17
- { id: 42, name: 'Rad Mid Range', type: 'rax', lane: "mid", bit: 3, team: 'radiant', x: 52, y: 193 },
18
- { id: 39, name: 'Rad Mid HG Time', type: 'rax_time', lane: "mid", bit: 2, team: 'radiant', x: 54, y: 194 },
13
+ { id: 17, name: 'Rad Mid T1', type: 'tower', lane: "mid", bit: 3, team: 'radiant', x: 101.2, y: 141 },
14
+ { id: 20, name: 'Rad Mid T2', type: 'tower', lane: "mid", bit: 4, team: 'radiant', x: 78.7, y: 161.8 },
15
+ { id: 23, name: 'Rad Mid T3', type: 'tower', lane: "mid", bit: 5, team: 'radiant', x: 59, y: 178.3 },
16
+ { id: 39, name: 'Rad Mid Melee', type: 'rax', lane: "mid", bit: 2, team: 'radiant', x: 59.8, y: 185.1 },
17
+ { id: 42, name: 'Rad Mid Range', type: 'rax', lane: "mid", bit: 3, team: 'radiant', x: 54.5, y: 180.5 },
18
+ { id: 39, name: 'Rad Mid HG Time', type: 'rax_time', lane: "mid", bit: 2, team: 'radiant', x: 64, y: 187 },
19
19
 
20
20
  // 下路
21
- { id: 18, name: 'Rad Bot T1', type: 'tower', lane: "bot", bit: 6, team: 'radiant', x: 197, y: 217 },
22
- { id: 21, name: 'Rad Bot T2', type: 'tower', lane: "bot", bit: 7, team: 'radiant', x: 116, y: 218 },
23
- { id: 24, name: 'Rad Bot T3', type: 'tower', lane: "bot", bit: 8, team: 'radiant', x: 61, y: 215 },
24
- { id: 40, name: 'Rad Bot Melee', type: 'rax', lane: "bot", bit: 4, team: 'radiant', x: 58, y: 220 },
25
- { id: 43, name: 'Rad Bot Range', type: 'rax', lane: "bot", bit: 5, team: 'radiant', x: 58, y: 212 },
26
- { id: 40, name: 'Rad Bot HG Time', type: 'rax_time', lane: "bot", bit: 4, team: 'radiant', x: 61, y: 220 },
21
+ { id: 18, name: 'Rad Bot T1', type: 'tower', lane: "bot", bit: 6, team: 'radiant', x: 189.3, y: 206.2 },
22
+ { id: 21, name: 'Rad Bot T2', type: 'tower', lane: "bot", bit: 7, team: 'radiant', x: 117.5, y: 207.2 },
23
+ { id: 24, name: 'Rad Bot T3', type: 'tower', lane: "bot", bit: 8, team: 'radiant', x: 68.7, y: 205 },
24
+ { id: 40, name: 'Rad Bot Melee', type: 'rax', lane: "bot", bit: 4, team: 'radiant', x: 65, y: 210 },
25
+ { id: 43, name: 'Rad Bot Range', type: 'rax', lane: "bot", bit: 5, team: 'radiant', x: 65, y: 202.7 },
26
+ { id: 40, name: 'Rad Bot HG Time', type: 'rax_time', lane: "bot", bit: 4, team: 'radiant', x: 70, y: 211 },
27
27
 
28
28
  // 门牙 & 基地
29
- { id: 25, name: 'Rad T4 Left', type: 'tower', lane: "mid", bit: 9, team: 'radiant', x: 34, y: 197 },
30
- { id: 25, name: 'Rad T4 Right', type: 'tower', lane: "mid", bit: 10, team: 'radiant', x: 39, y: 201 },
31
- { id: 25, name: 'Rad T4 Time', type: 't4_time', lane: "mid", bit: [9,10], team: 'radiant', x: 43, y: 204 },
32
- { id: 50, name: 'Rad Ancient', type: 'fort', lane: "", bit: -1, team: 'radiant', x: 29, y: 202 },
33
- { id: 50, name: 'Rad Ancient Time', type: 'fort_time', lane: "", bit: -1, team: 'radiant', x: 35, y: 213 },
29
+ { id: 25, name: 'Rad T4 Left', type: 'tower', lane: "mid", bit: 9, team: 'radiant', x: 44.7, y: 188.7 },
30
+ { id: 25, name: 'Rad T4 Right', type: 'tower', lane: "mid", bit: 10, team: 'radiant', x: 50, y: 193.1 },
31
+ { id: 25, name: 'Rad T4 Time', type: 't4_time', lane: "mid", bit: [9,10], team: 'radiant', x: 53, y: 196 },
32
+ { id: 50, name: 'Rad Ancient', type: 'fort', lane: "", bit: -1, team: 'radiant', x: 39.5, y: 193.5 },
33
+ { id: 50, name: 'Rad Ancient Time', type: 'fort_time', lane: "", bit: -1, team: 'radiant', x: 42, y: 207 },
34
34
 
35
35
  // ================= 夜魔 Dire (右上) =================
36
36
  // 上路
37
- { id: 26, name: 'Dire Top T1', type: 'tower', lane: "top", bit: 0, team: 'dire', x: 41, y: 32 },
38
- { id: 29, name: 'Dire Top T2', type: 'tower', lane: "top", bit: 1, team: 'dire', x: 120, y: 31 },
39
- { id: 32, name: 'Dire Top T3', type: 'tower', lane: "top", bit: 2, team: 'dire', x: 176, y: 34 },
40
- { id: 44, name: 'Dire Top Melee', type: 'rax', lane: "top", bit: 0, team: 'dire', x: 182, y: 40 },
41
- { id: 47, name: 'Dire Top Range', type: 'rax', lane: "top", bit: 1, team: 'dire', x: 182, y: 32 },
42
- { id: 44, name: 'Dire Top HG Time', type: 'rax_time', lane: "top", bit: 0, team: 'dire', x: 185, y: 40 },
37
+ { id: 26, name: 'Dire Top T1', type: 'tower', lane: "top", bit: 0, team: 'dire', x: 50.4, y: 41 },
38
+ { id: 29, name: 'Dire Top T2', type: 'tower', lane: "top", bit: 1, team: 'dire', x: 120.7, y: 39.8 },
39
+ { id: 32, name: 'Dire Top T3', type: 'tower', lane: "top", bit: 2, team: 'dire', x: 170.7, y: 42.9 },
40
+ { id: 44, name: 'Dire Top Melee', type: 'rax', lane: "top", bit: 0, team: 'dire', x: 176.5, y: 48.5 },
41
+ { id: 47, name: 'Dire Top Range', type: 'rax', lane: "top", bit: 1, team: 'dire', x: 176.5, y: 40.8 },
42
+ { id: 44, name: 'Dire Top HG Time', type: 'rax_time', lane: "top", bit: 0, team: 'dire', x: 181.5, y: 49 },
43
43
 
44
44
  // 中路
45
- { id: 27, name: 'Dire Mid T1', type: 'tower', lane: "mid", bit: 3, team: 'dire', x: 130, y: 112 },
46
- { id: 30, name: 'Dire Mid T2', type: 'tower', lane: "mid", bit: 4, team: 'dire', x: 160, y: 90 },
47
- { id: 33, name: 'Dire Mid T3', type: 'tower', lane: "mid", bit: 5, team: 'dire', x: 187, y: 65 },
48
- { id: 45, name: 'Dire Mid Melee', type: 'rax', lane: "mid", bit: 2, team: 'dire', x: 189, y: 60 },
49
- { id: 48, name: 'Dire Mid Range', type: 'rax', lane: "mid", bit: 3, team: 'dire', x: 195, y: 64 },
50
- { id: 45, name: 'Dire Mid HG Time', type: 'rax_time', lane: "mid", bit: 2, team: 'dire', x: 196, y: 68 },
45
+ { id: 27, name: 'Dire Mid T1', type: 'tower', lane: "mid", bit: 3, team: 'dire', x: 129.4, y: 112.7 },
46
+ { id: 30, name: 'Dire Mid T2', type: 'tower', lane: "mid", bit: 4, team: 'dire', x: 156.4, y: 92.8 },
47
+ { id: 33, name: 'Dire Mid T3', type: 'tower', lane: "mid", bit: 5, team: 'dire', x: 180.6, y: 70.5 },
48
+ { id: 45, name: 'Dire Mid Melee', type: 'rax', lane: "mid", bit: 2, team: 'dire', x: 187.5, y: 70.5 },
49
+ { id: 48, name: 'Dire Mid Range', type: 'rax', lane: "mid", bit: 3, team: 'dire', x: 182.7, y: 65.6 },
50
+ { id: 45, name: 'Dire Mid HG Time', type: 'rax_time', lane: "mid", bit: 2, team: 'dire', x: 187, y: 74 },
51
51
 
52
52
  // 下路
53
- { id: 28, name: 'Dire Bot T1', type: 'tower', lane: "bot", bit: 6, team: 'dire', x: 218, y: 157 },
54
- { id: 31, name: 'Dire Bot T2', type: 'tower', lane: "bot", bit: 7, team: 'dire', x: 220, y: 117 },
55
- { id: 34, name: 'Dire Bot T3', type: 'tower', lane: "bot", bit: 8, team: 'dire', x: 219, y: 76 },
56
- { id: 46, name: 'Dire Bot Melee', type: 'rax', lane: "bot", bit: 4, team: 'dire', x: 224, y: 72 },
57
- { id: 49, name: 'Dire Bot Range', type: 'rax', lane: "bot", bit: 5, team: 'dire', x: 216, y: 72 },
58
- { id: 46, name: 'Dire Bot HG Time', type: 'rax_time', lane: "bot", bit: 4, team: 'dire', x: 225, y: 78 },
53
+ { id: 28, name: 'Dire Bot T1', type: 'tower', lane: "bot", bit: 6, team: 'dire', x: 207.8, y: 152.2 },
54
+ { id: 31, name: 'Dire Bot T2', type: 'tower', lane: "bot", bit: 7, team: 'dire', x: 209.75, y: 116.6 },
55
+ { id: 34, name: 'Dire Bot T3', type: 'tower', lane: "bot", bit: 8, team: 'dire', x: 208.7, y: 80.5 },
56
+ { id: 46, name: 'Dire Bot Melee', type: 'rax', lane: "bot", bit: 4, team: 'dire', x: 213.2, y: 76.8 },
57
+ { id: 49, name: 'Dire Bot Range', type: 'rax', lane: "bot", bit: 5, team: 'dire', x: 206.2, y: 76.8 },
58
+ { id: 46, name: 'Dire Bot HG Time', type: 'rax_time', lane: "bot", bit: 4, team: 'dire', x: 214.5, y: 82 },
59
59
 
60
60
  // 门牙 & 基地
61
- { id: 35, name: 'Dire T4 Left', type: 'tower', lane: "mid", bit: 9, team: 'dire', x: 197, y: 49 },
62
- { id: 35, name: 'Dire T4 Right', type: 'tower', lane: "mid", bit: 10, team: 'dire', x: 203, y: 54 },
63
- { id: 35, name: 'Dire T4 Time', type: 't4_time', lane: "mid", bit: 10, team: 'dire', x: 207, y: 57 },
64
- { id: 51, name: 'Dire Ancient', type: 'fort', lane: "", bit: -1, team: 'dire', x: 204, y: 44 },
65
- { id: 51, name: 'Dire Ancient Time', type: 'fort_time', lane: "", bit: -1, team: 'dire', x: 215, y: 48 },
61
+ { id: 35, name: 'Dire T4 Left', type: 'tower', lane: "mid", bit: 9, team: 'dire', x: 189.7, y: 56.4 },
62
+ { id: 35, name: 'Dire T4 Right', type: 'tower', lane: "mid", bit: 10, team: 'dire', x: 194.4, y: 60.2 },
63
+ { id: 35, name: 'Dire T4 Time', type: 't4_time', lane: "mid", bit: 10, team: 'dire', x: 198, y: 63 },
64
+ { id: 51, name: 'Dire Ancient', type: 'fort', lane: "", bit: -1, team: 'dire', x: 195.7, y: 49 },
65
+ { id: 51, name: 'Dire Ancient Time', type: 'fort_time', lane: "", bit: -1, team: 'dire', x: 210, y: 52 },
66
66
  ];
67
67
  %> <%
68
68
  // 1. 算法:提取摧毁时间 (Last Event Algorithm)
@@ -124,7 +124,7 @@ const BUILDINGS = [
124
124
  };
125
125
 
126
126
  const getProps = (type) => buildingProps[type] || buildingProps._default;
127
- %> <% const images = { minimapBase: "7.38_simple_minimap" } %> <section class="map"> <%- include("../../common/components/building_icons") %> <svg id="map" viewBox="0 0 255 255" width="250" height="250"><rect x="0" y="0" width="255" height="255" fill="#f5f5f5" rx="12" ry="12"/><image href="<%= getImageUrl(images.minimapBase) %>" width="255" height="255"/> <%
127
+ %> <% const images = { minimapBase: "dotamap_7.40" } %> <section class="map"> <%- include("../../common/components/building_icons") %> <svg id="map" viewBox="0 0 255 255" width="250" height="250"><rect x="0" y="0" width="255" height="255" fill="#f5f5f5" rx="12" ry="12"/><image href="<%= getImageUrl(images.minimapBase) %>" width="255" height="255"/> <%
128
128
  [...BUILDINGS].sort((a, b) => {
129
129
  return getProps(a.type).z - getProps(b.type).z;
130
130
  }).forEach(b => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sjtdev/koishi-plugin-dota2tracker",
3
3
  "description": "koishi插件-追踪群友的DOTA2对局",
4
- "version": "2.3.0",
4
+ "version": "2.3.2",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [