@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 +20 -0
- package/lib/index.js +51 -51
- package/lib/templates/images/dotamap_7.40.png +0 -0
- package/lib/templates/match/match_2+/extra.css +1 -1
- package/lib/templates/match/match_2+/map.ejs +47 -47
- package/package.json +1 -1
- package/lib/templates/images/7.38_simple_minimap.png +0 -0
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(
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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 =
|
|
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],
|
|
1362
|
+
return this.fuzzySearchItems(alias.length ? alias : [keyword], items);
|
|
1365
1363
|
}
|
|
1366
|
-
fuzzySearchItems(keywords,
|
|
1364
|
+
fuzzySearchItems(keywords, items) {
|
|
1367
1365
|
const resultMap = /* @__PURE__ */ new Map();
|
|
1368
1366
|
if (!keywords.length) return [];
|
|
1369
|
-
for (const item of
|
|
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 =
|
|
1774
|
+
const itemName = dotaconstants.item_ids[item.itemId];
|
|
1778
1775
|
if (itemName) {
|
|
1779
|
-
const itemDetails =
|
|
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:
|
|
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 (
|
|
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 =
|
|
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
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
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(
|
|
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:
|
|
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:
|
|
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:
|
|
3828
|
-
shortName:
|
|
3829
|
-
facets: [...
|
|
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:
|
|
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[
|
|
3989
|
+
return map[dotaconstants.lobby_type[openDotaLobbyType].name] || "EVENT" /* Event */;
|
|
3993
3990
|
}
|
|
3994
3991
|
__name(convertLobbyType, "convertLobbyType");
|
|
3995
|
-
function convertGameMode(openDotaGameModeId) {
|
|
3996
|
-
const gameModeName =
|
|
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);
|
|
Binary file
|
|
@@ -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:
|
|
6
|
-
{ id: 19, name: 'Rad Top T2', type: 'tower', lane: "top", bit: 1, team: 'radiant', x:
|
|
7
|
-
{ id: 22, name: 'Rad Top T3', type: 'tower', lane: "top", bit: 2, team: 'radiant', x:
|
|
8
|
-
{ id: 38, name: 'Rad Top Melee', type: 'rax', lane: "top", bit: 0, team: 'radiant', x:
|
|
9
|
-
{ id: 41, name: 'Rad Top Range', type: 'rax', lane: "top", bit: 1, team: 'radiant', x:
|
|
10
|
-
{ id: 38, name: 'Rad Top HG Time', type: 'rax_time', lane: "top", bit: 0, team: 'radiant', x:
|
|
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:
|
|
14
|
-
{ id: 20, name: 'Rad Mid T2', type: 'tower', lane: "mid", bit: 4, team: 'radiant', x:
|
|
15
|
-
{ id: 23, name: 'Rad Mid T3', type: 'tower', lane: "mid", bit: 5, team: 'radiant', x:
|
|
16
|
-
{ id: 39, name: 'Rad Mid Melee', type: 'rax', lane: "mid", bit: 2, team: 'radiant', x:
|
|
17
|
-
{ id: 42, name: 'Rad Mid Range', type: 'rax', lane: "mid", bit: 3, team: 'radiant', x:
|
|
18
|
-
{ id: 39, name: 'Rad Mid HG Time', type: 'rax_time', lane: "mid", bit: 2, team: 'radiant', x:
|
|
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:
|
|
22
|
-
{ id: 21, name: 'Rad Bot T2', type: 'tower', lane: "bot", bit: 7, team: 'radiant', x:
|
|
23
|
-
{ id: 24, name: 'Rad Bot T3', type: 'tower', lane: "bot", bit: 8, team: 'radiant', x:
|
|
24
|
-
{ id: 40, name: 'Rad Bot Melee', type: 'rax', lane: "bot", bit: 4, team: 'radiant', x:
|
|
25
|
-
{ id: 43, name: 'Rad Bot Range', type: 'rax', lane: "bot", bit: 5, team: 'radiant', x:
|
|
26
|
-
{ id: 40, name: 'Rad Bot HG Time', type: 'rax_time', lane: "bot", bit: 4, team: 'radiant', x:
|
|
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:
|
|
30
|
-
{ id: 25, name: 'Rad T4 Right', type: 'tower', lane: "mid", bit: 10, team: 'radiant', x:
|
|
31
|
-
{ id: 25, name: 'Rad T4 Time', type: 't4_time', lane: "mid", bit: [9,10], team: 'radiant', x:
|
|
32
|
-
{ id: 50, name: 'Rad Ancient', type: 'fort', lane: "", bit: -1, team: 'radiant', x:
|
|
33
|
-
{ id: 50, name: 'Rad Ancient Time', type: 'fort_time', lane: "", bit: -1, team: 'radiant', x:
|
|
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:
|
|
38
|
-
{ id: 29, name: 'Dire Top T2', type: 'tower', lane: "top", bit: 1, team: 'dire', x: 120, y:
|
|
39
|
-
{ id: 32, name: 'Dire Top T3', type: 'tower', lane: "top", bit: 2, team: 'dire', x:
|
|
40
|
-
{ id: 44, name: 'Dire Top Melee', type: 'rax', lane: "top", bit: 0, team: 'dire', x:
|
|
41
|
-
{ id: 47, name: 'Dire Top Range', type: 'rax', lane: "top", bit: 1, team: 'dire', x:
|
|
42
|
-
{ id: 44, name: 'Dire Top HG Time', type: 'rax_time', lane: "top", bit: 0, team: 'dire', x:
|
|
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:
|
|
46
|
-
{ id: 30, name: 'Dire Mid T2', type: 'tower', lane: "mid", bit: 4, team: 'dire', x:
|
|
47
|
-
{ id: 33, name: 'Dire Mid T3', type: 'tower', lane: "mid", bit: 5, team: 'dire', x:
|
|
48
|
-
{ id: 45, name: 'Dire Mid Melee', type: 'rax', lane: "mid", bit: 2, team: 'dire', x:
|
|
49
|
-
{ id: 48, name: 'Dire Mid Range', type: 'rax', lane: "mid", bit: 3, team: 'dire', x:
|
|
50
|
-
{ id: 45, name: 'Dire Mid HG Time', type: 'rax_time', lane: "mid", bit: 2, team: 'dire', x:
|
|
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:
|
|
54
|
-
{ id: 31, name: 'Dire Bot T2', type: 'tower', lane: "bot", bit: 7, team: 'dire', x:
|
|
55
|
-
{ id: 34, name: 'Dire Bot T3', type: 'tower', lane: "bot", bit: 8, team: 'dire', x:
|
|
56
|
-
{ id: 46, name: 'Dire Bot Melee', type: 'rax', lane: "bot", bit: 4, team: 'dire', x:
|
|
57
|
-
{ id: 49, name: 'Dire Bot Range', type: 'rax', lane: "bot", bit: 5, team: 'dire', x:
|
|
58
|
-
{ id: 46, name: 'Dire Bot HG Time', type: 'rax_time', lane: "bot", bit: 4, team: 'dire', x:
|
|
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:
|
|
62
|
-
{ id: 35, name: 'Dire T4 Right', type: 'tower', lane: "mid", bit: 10, team: 'dire', x:
|
|
63
|
-
{ id: 35, name: 'Dire T4 Time', type: 't4_time', lane: "mid", bit: 10, team: 'dire', x:
|
|
64
|
-
{ id: 51, name: 'Dire Ancient', type: 'fort', lane: "", bit: -1, team: 'dire', x:
|
|
65
|
-
{ id: 51, name: 'Dire Ancient Time', type: 'fort_time', lane: "", bit: -1, team: 'dire', x:
|
|
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: "
|
|
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
|
Binary file
|