2
0
Эх сурвалжийг харах

Merge branch 'develop' into feature/nullkiller2

Mircea TheHonestCTO 3 сар өмнө
parent
commit
54ad621357

+ 1 - 1
.github/workflows/aab-from-build.yml

@@ -18,7 +18,7 @@ jobs:
         sparse-checkout: CI/android
 
     - name: Install JDK
-      uses: actions/setup-java@v4
+      uses: actions/setup-java@v5
       with:
         distribution: 'temurin'
         java-version: '11'

+ 1 - 1
.github/workflows/github.yml

@@ -203,7 +203,7 @@ jobs:
       run: sudo ln -s -T /home/runner/.conan/data/android-ndk/r25c/_/_/package/4db1be536558d833e52e862fd84d64d75c2b3656/bin /usr/local/lib/android/sdk/ndk/25.2.9519653
 
     - name: Install Java
-      uses: actions/setup-java@v4
+      uses: actions/setup-java@v5
       if: ${{ startsWith(matrix.platform, 'android') }}
       with:
         distribution: 'temurin'

+ 272 - 1
Mods/vcmi/Content/config/chinese.json

@@ -262,6 +262,276 @@
 	"vcmi.settingsMainWindow.adventureTab.hover" : "冒险地图",
 	"vcmi.settingsMainWindow.adventureTab.help"  : "切换到“冒险地图”选项卡 - 冒险地图即玩家能操作英雄移动的界面",
 
+	"vcmi.keyBindings.button.hover" : "快捷键",
+	"vcmi.keyBindings.button.help"  : "{快捷键}\n\n显示查看和调整快捷键的菜单",
+	"vcmi.keyBindings.editButton.help" : "编辑快捷键",
+	"vcmi.keyBindings.input" : "更改{%s}的快捷键.\n\n请输入一个按键或按键组合,单击外部区域可取消设置",
+	"vcmi.keyBindings.inputSet" : "{%s}的快捷键将更改为{%s}.\n\n是否追加到已有快捷键表?若否,它将被替换。",
+	"vcmi.keyBindings.popup" : "{%s}设置为下列按键:\n\n",
+	"vcmi.keyBindings.reset" : "重置",
+	"vcmi.keyBindings.reset.help" : "{重置}\n\n将快捷键重置为默认值",
+	"vcmi.keyBindings.resetConfirm" : "你确定要重置所有快捷键为默认值?",
+	"vcmi.keyBindings.group.keyboard" : "键盘",
+	"vcmi.keyBindings.group.joystickAxes" : "手柄轴",
+	"vcmi.keyBindings.group.joystickButtons" : "手柄按键",
+	"vcmi.keyBindings.keyBinding.adventureCastSpell": "冒险地图 - 施放法术",
+	"vcmi.keyBindings.keyBinding.adventureDigGrail": "冒险地图 - 挖掘神器",
+	"vcmi.keyBindings.keyBinding.adventureEndTurn": "冒险地图 - 结束回合",
+	"vcmi.keyBindings.keyBinding.adventureExitWorldView": "冒险地图 - 退出查看世界",
+	"vcmi.keyBindings.keyBinding.adventureFirstHero": "冒险地图 - 选取第一个英雄",
+	"vcmi.keyBindings.keyBinding.adventureFirstTown": "冒险地图 - 选取第一座城镇",
+	"vcmi.keyBindings.keyBinding.adventureGameOptions": "冒险地图 - 游戏选项",
+	"vcmi.keyBindings.keyBinding.adventureKingdomOverview": "冒险地图 - 王国概况",
+	"vcmi.keyBindings.keyBinding.adventureLoadGame": "冒险地图 - 载入进度",
+	"vcmi.keyBindings.keyBinding.adventureMainMenu": "冒险地图 - 返回主菜单",
+	"vcmi.keyBindings.keyBinding.adventureMarketplace": "冒险地图 - 打开市场",
+	"vcmi.keyBindings.keyBinding.adventureMoveHero": "冒险地图 - 移动英雄",
+	"vcmi.keyBindings.keyBinding.adventureMoveHeroEE": "冒险地图 - 将英雄向东移动",
+	"vcmi.keyBindings.keyBinding.adventureMoveHeroNE": "冒险地图 - 将英雄向东北移动",
+	"vcmi.keyBindings.keyBinding.adventureMoveHeroNN": "冒险地图 - 将英雄向北移动",
+	"vcmi.keyBindings.keyBinding.adventureMoveHeroNW": "冒险地图 - 将英雄向西北移动",
+	"vcmi.keyBindings.keyBinding.adventureMoveHeroSE": "冒险地图 - 将英雄向东南移动",
+	"vcmi.keyBindings.keyBinding.adventureMoveHeroSS": "冒险地图 - 将英雄向南移动",
+	"vcmi.keyBindings.keyBinding.adventureMoveHeroSW": "冒险地图 - 将英雄向西南移动",
+	"vcmi.keyBindings.keyBinding.adventureMoveHeroWW": "冒险地图 - 将英雄向西移动",
+	"vcmi.keyBindings.keyBinding.adventureNewGame": "冒险地图 - 开始新游戏",
+	"vcmi.keyBindings.keyBinding.adventureNextHero": "冒险地图 - 选取下一个英雄",
+	"vcmi.keyBindings.keyBinding.adventureNextObject": "冒险地图 - 选取下一个物体",
+	"vcmi.keyBindings.keyBinding.adventureNextTown": "冒险地图 - 选取下一个城镇",
+	"vcmi.keyBindings.keyBinding.adventureQuestLog": "冒险地图 - 任务日志",
+	"vcmi.keyBindings.keyBinding.adventureQuitGame": "冒险地图 - 退出游戏",
+	"vcmi.keyBindings.keyBinding.adventureReplayTurn": "冒险地图 - 重放对手行动",
+	"vcmi.keyBindings.keyBinding.adventureRestartGame": "冒险地图 - 重新开始游戏",
+	"vcmi.keyBindings.keyBinding.adventureSaveGame": "冒险地图 - 保存进度",
+	"vcmi.keyBindings.keyBinding.adventureSetHeroAsleep": "冒险地图 - 睡眠英雄",
+	"vcmi.keyBindings.keyBinding.adventureSetHeroAwake": "冒险地图 - 唤醒英雄",
+	"vcmi.keyBindings.keyBinding.adventureThievesGuild": "冒险地图 - 盗贼行会",
+	"vcmi.keyBindings.keyBinding.adventureToggleGrid": "冒险地图 - 开关网格",
+	"vcmi.keyBindings.keyBinding.adventureToggleVisitable": "冒险地图 - 开关可访问信息",
+	"vcmi.keyBindings.keyBinding.adventureToggleBlocked": "冒险地图 - 开关阻挡信息",
+	"vcmi.keyBindings.keyBinding.adventureToggleMapLevel": "冒险地图 - 切换地上地下",
+	"vcmi.keyBindings.keyBinding.adventureToggleSleep": "冒险地图 - 切换睡眠唤醒",
+	"vcmi.keyBindings.keyBinding.adventureTrackHero": "冒险地图 - 追踪英雄",
+	"vcmi.keyBindings.keyBinding.adventureViewPuzzle": "冒险地图 - 藏宝图",
+	"vcmi.keyBindings.keyBinding.adventureViewScenario": "冒险地图 - 场景信息",
+	"vcmi.keyBindings.keyBinding.adventureViewSelected": "冒险地图 - 查看选取对象",
+	"vcmi.keyBindings.keyBinding.adventureViewWorld": "冒险地图 - 查看世界",
+	"vcmi.keyBindings.keyBinding.adventureViewWorld1": "冒险地图 - 查看世界1",
+	"vcmi.keyBindings.keyBinding.adventureViewWorld2": "冒险地图 - 查看世界2",
+	"vcmi.keyBindings.keyBinding.adventureViewWorld4": "冒险地图 - 查看世界4",
+	"vcmi.keyBindings.keyBinding.adventureVisitObject": "冒险地图 - 访问物体",
+	"vcmi.keyBindings.keyBinding.adventureZoomIn": "冒险地图 - 放大",
+	"vcmi.keyBindings.keyBinding.adventureZoomOut": "冒险地图 - 缩小",
+	"vcmi.keyBindings.keyBinding.adventureZoomReset": "冒险地图 - 重置缩放",
+	"vcmi.keyBindings.keyBinding.adventureSearch": "冒险地图 - 搜索",
+	"vcmi.keyBindings.keyBinding.adventureSearchContinue": "冒险地图 - 继续搜索",
+	"vcmi.keyBindings.keyBinding.battleAutocombat": "战斗 - 自动战斗",
+	"vcmi.keyBindings.keyBinding.battleAutocombatEnd": "战斗 - 结束自动战斗",
+	"vcmi.keyBindings.keyBinding.battleCastSpell": "战斗 - 施放法术",
+	"vcmi.keyBindings.keyBinding.battleConsoleDown": "战斗 - 控制台向下滚动",
+	"vcmi.keyBindings.keyBinding.battleConsoleUp": "战斗 - 控制台向上滚动",
+	"vcmi.keyBindings.keyBinding.battleDefend": "战斗 - 防御",
+	"vcmi.keyBindings.keyBinding.battleOpenActiveUnit": "战斗 - 开启当前单位菜单",
+	"vcmi.keyBindings.keyBinding.battleOpenHoveredUnit": "战斗 - 开启指针覆盖的单位菜单",
+	"vcmi.keyBindings.keyBinding.battleRetreat": "战斗 - 撤退",
+	"vcmi.keyBindings.keyBinding.battleToggleQuickSpell": "战斗 - 开关快捷法术",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut0": "战斗 - 快捷法术0",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut1": "战斗 - 快捷法术1",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut2": "战斗 - 快捷法术2",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut3": "战斗 - 快捷法术3",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut4": "战斗 - 快捷法术4",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut5": "战斗 - 快捷法术5",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut6": "战斗 - 快捷法术6",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut7": "战斗 - 快捷法术7",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut8": "战斗 - 快捷法术8",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut9": "战斗 - 快捷法术9",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut10": "战斗 - 快捷法术10",
+	"vcmi.keyBindings.keyBinding.battleSpellShortcut11": "战斗 - 快捷法术11",
+	"vcmi.keyBindings.keyBinding.battleSurrender": "战斗 - 投降",
+	"vcmi.keyBindings.keyBinding.battleTacticsEnd": "战斗 - 结束布阵",
+	"vcmi.keyBindings.keyBinding.battleTacticsNext": "战斗 -布阵下一个单位",
+	"vcmi.keyBindings.keyBinding.battleToggleHeroesStats": "战斗 - 开关英雄状态",
+	"vcmi.keyBindings.keyBinding.battleToggleQueue": "战斗 - 开关队列",
+	"vcmi.keyBindings.keyBinding.battleUseCreatureSpell": "战斗 - 使用生物法术",
+	"vcmi.keyBindings.keyBinding.battleWait": "战斗 - 等待",
+	"vcmi.keyBindings.keyBinding.exchangeArmySwap": "交换 - 交换军队",
+	"vcmi.keyBindings.keyBinding.exchangeArmyToLeft": "交换 - 军队移到左侧",
+	"vcmi.keyBindings.keyBinding.exchangeArmyToRight": "交换 - 军队移到右侧",
+	"vcmi.keyBindings.keyBinding.exchangeArtifactsSwap": "交换 - 交换宝物",
+	"vcmi.keyBindings.keyBinding.exchangeArtifactsToLeft": "交换 - 宝物移到左侧",
+	"vcmi.keyBindings.keyBinding.exchangeArtifactsToRight": "交换 - 宝物移到右侧",
+	"vcmi.keyBindings.keyBinding.exchangeBackpackLeft": "交换 - 行囊中宝物左移",
+	"vcmi.keyBindings.keyBinding.exchangeBackpackRight": "交换 - 行囊中宝物右移",
+	"vcmi.keyBindings.keyBinding.exchangeBackpackSwap": "交换 - 交换行囊",
+	"vcmi.keyBindings.keyBinding.exchangeBackpackToLeft": "交换 - 行囊中宝物移到左侧",
+	"vcmi.keyBindings.keyBinding.exchangeBackpackToRight": "交换 - 行囊中宝物移到右侧",
+	"vcmi.keyBindings.keyBinding.exchangeEquippedSwap": "交换 - 交换装备",
+	"vcmi.keyBindings.keyBinding.exchangeEquippedToLeft": "交换 - 装备移到左侧",
+	"vcmi.keyBindings.keyBinding.exchangeEquippedToRight": "E交换 - 装备移到右侧",
+	"vcmi.keyBindings.keyBinding.gameActivateConsole": "打开游戏控制台",
+	"vcmi.keyBindings.keyBinding.globalAccept": "全局 - 接受",
+	"vcmi.keyBindings.keyBinding.globalBackspace": "全局 - 回退",
+	"vcmi.keyBindings.keyBinding.globalCancel": "全局 - 取消",
+	"vcmi.keyBindings.keyBinding.globalFullscreen": "全局 - 全屏",
+	"vcmi.keyBindings.keyBinding.globalMoveFocus": "全局 - 移动焦点",
+	"vcmi.keyBindings.keyBinding.globalOptions": "全局 - 选项",
+	"vcmi.keyBindings.keyBinding.globalReturn": "全局 - 返回",
+	"vcmi.keyBindings.keyBinding.heroArmySplit": "英雄 - 拆分军队",
+	"vcmi.keyBindings.keyBinding.heroBackpack": "英雄 - 行囊",
+	"vcmi.keyBindings.keyBinding.heroCommander": "英雄 - 指挥官",
+	"vcmi.keyBindings.keyBinding.heroCostumeLoad0": "英雄 - 载入配装0",
+	"vcmi.keyBindings.keyBinding.heroCostumeLoad1": "英雄 - 载入配装1",
+	"vcmi.keyBindings.keyBinding.heroCostumeLoad2": "英雄 - 载入配装2",
+	"vcmi.keyBindings.keyBinding.heroCostumeLoad3": "英雄 - 载入配装3",
+	"vcmi.keyBindings.keyBinding.heroCostumeLoad4": "英雄 - 载入配装4",
+	"vcmi.keyBindings.keyBinding.heroCostumeLoad5": "英雄 - 载入配装5",
+	"vcmi.keyBindings.keyBinding.heroCostumeLoad6": "英雄 - 载入配装6",
+	"vcmi.keyBindings.keyBinding.heroCostumeLoad7": "英雄 - 载入配装7",
+	"vcmi.keyBindings.keyBinding.heroCostumeLoad8": "英雄 - 载入配装8",
+	"vcmi.keyBindings.keyBinding.heroCostumeLoad9": "英雄 - 载入配装9",
+	"vcmi.keyBindings.keyBinding.heroCostumeSave0": "英雄 - 保存配装0",
+	"vcmi.keyBindings.keyBinding.heroCostumeSave1": "英雄 - 保存配装1",
+	"vcmi.keyBindings.keyBinding.heroCostumeSave2": "英雄 - 保存配装2",
+	"vcmi.keyBindings.keyBinding.heroCostumeSave3": "英雄 - 保存配装3",
+	"vcmi.keyBindings.keyBinding.heroCostumeSave4": "英雄 - 保存配装4",
+	"vcmi.keyBindings.keyBinding.heroCostumeSave5": "英雄 - 保存配装5",
+	"vcmi.keyBindings.keyBinding.heroCostumeSave6": "英雄 - 保存配装6",
+	"vcmi.keyBindings.keyBinding.heroCostumeSave7": "英雄 - 保存配装7",
+	"vcmi.keyBindings.keyBinding.heroCostumeSave8": "英雄 - 保存配装8",
+	"vcmi.keyBindings.keyBinding.heroCostumeSave9": "英雄 - 保存配装9",
+	"vcmi.keyBindings.keyBinding.heroDismiss": "英雄 - 解雇",
+	"vcmi.keyBindings.keyBinding.heroLooseFormation": "英雄 - 松散阵型",
+	"vcmi.keyBindings.keyBinding.heroTightFormation": "英雄 - 紧密阵型",
+	"vcmi.keyBindings.keyBinding.heroToggleTactics": "英雄 - 开关布阵",
+	"vcmi.keyBindings.keyBinding.highScoresCampaigns": "最高得分 - 战役",
+	"vcmi.keyBindings.keyBinding.highScoresReset": "最高得分 - 重置",
+	"vcmi.keyBindings.keyBinding.highScoresStatistics": "最高得分 - 统计",
+	"vcmi.keyBindings.keyBinding.highScoresScenarios": "最高得分 - 场景",
+	"vcmi.keyBindings.keyBinding.kingdomHeroesTab": "王国概况 - 英雄标签",
+	"vcmi.keyBindings.keyBinding.kingdomTownsTab": "王国概况 - 城镇标签",
+	"vcmi.keyBindings.keyBinding.lobbyAdditionalOptions": "大厅 - 附加选项",
+	"vcmi.keyBindings.keyBinding.lobbyBeginCampaign": "大厅 - 开启战役",
+	"vcmi.keyBindings.keyBinding.lobbyBeginStandardGame": "大厅 - 开启标准游戏",
+	"vcmi.keyBindings.keyBinding.lobbyExtraOptions": "大厅 - 额外选项",
+	"vcmi.keyBindings.keyBinding.lobbyFlipCoin": "大厅 - 掷硬币",
+	"vcmi.keyBindings.keyBinding.lobbyInvitePlayers": "大厅 - 邀请玩家",
+	"vcmi.keyBindings.keyBinding.lobbyLoadGame": "大厅 - 载入进度",
+	"vcmi.keyBindings.keyBinding.lobbyRandomMap": "大厅 - 随机地图",
+	"vcmi.keyBindings.keyBinding.lobbyRandomTown": "大厅 - 随机城镇",
+	"vcmi.keyBindings.keyBinding.lobbyRandomTownVs": "大厅 - 随机城镇对战",
+	"vcmi.keyBindings.keyBinding.lobbyHandicap": "大厅 - 障碍",
+	"vcmi.keyBindings.keyBinding.lobbyReplayVideo": "大厅 - 重放动画",
+	"vcmi.keyBindings.keyBinding.lobbySaveGame": "大厅 - 保存游戏",
+	"vcmi.keyBindings.keyBinding.lobbySelectScenario": "大厅 - 选择场景",
+	"vcmi.keyBindings.keyBinding.lobbyToggleChat": "大厅 - 开关聊天",
+	"vcmi.keyBindings.keyBinding.lobbyTurnOptions": "大厅 - 回合选项",
+	"vcmi.keyBindings.keyBinding.mainMenuBack": "主菜单 - 返回",
+	"vcmi.keyBindings.keyBinding.mainMenuCampaign": "主菜单 - 战役",
+	"vcmi.keyBindings.keyBinding.mainMenuCampaignAb": "主菜单 - 末日之刃战役",
+	"vcmi.keyBindings.keyBinding.mainMenuCampaignCustom": "主菜单 - 自定义战役",
+	"vcmi.keyBindings.keyBinding.mainMenuCampaignRoe": "主菜单 - 埃拉西亚的光复战役",
+	"vcmi.keyBindings.keyBinding.mainMenuCampaignSod": "主菜单 - 死亡阴影战役",
+	"vcmi.keyBindings.keyBinding.mainMenuCampaignChr": "主菜单 - 历代记战役",
+	"vcmi.keyBindings.keyBinding.mainMenuCampaignHota": "主菜单 - 深渊号角战役",
+	"vcmi.keyBindings.keyBinding.mainMenuCampaignWog": "主菜单 - 神之苏醒战役",
+	"vcmi.keyBindings.keyBinding.mainMenuCampaignVCMI": "主菜单 - VCMI战役",
+	"vcmi.keyBindings.keyBinding.mainMenuCredits": "主菜单 - 制作组",
+	"vcmi.keyBindings.keyBinding.mainMenuHighScores": "主菜单 - 最高得分",
+	"vcmi.keyBindings.keyBinding.mainMenuHostGame": "主菜单 - 主持游戏",
+	"vcmi.keyBindings.keyBinding.mainMenuHotseat": "主菜单 - 热座",
+	"vcmi.keyBindings.keyBinding.mainMenuJoinGame": "主菜单 - 加入游戏",
+	"vcmi.keyBindings.keyBinding.mainMenuLoadGame": "主菜单 - 载入进度",
+	"vcmi.keyBindings.keyBinding.mainMenuLobby": "主菜单 - 大厅",
+	"vcmi.keyBindings.keyBinding.mainMenuMultiplayer": "主菜单 - 多人游戏",
+	"vcmi.keyBindings.keyBinding.mainMenuNewGame": "主菜单 - 新游戏",
+	"vcmi.keyBindings.keyBinding.mainMenuQuit": "主菜单 - 退出",
+	"vcmi.keyBindings.keyBinding.mainMenuSingleplayer": "主菜单 - 单人场景",
+	"vcmi.keyBindings.keyBinding.mainMenuTutorial": "主菜单 - 训练",
+	"vcmi.keyBindings.keyBinding.mapsSizeAll": "地图 - 所有大学",
+	"vcmi.keyBindings.keyBinding.mapsSizeL": "地图 - 大",
+	"vcmi.keyBindings.keyBinding.mapsSizeM": "地图 - 中",
+	"vcmi.keyBindings.keyBinding.mapsSizeS": "地图 - 小",
+	"vcmi.keyBindings.keyBinding.mapsSizeXl": "地图 - 特大",
+	"vcmi.keyBindings.keyBinding.mapsSortChangedate": "地图 - 按修改时间排序",
+	"vcmi.keyBindings.keyBinding.mapsSortDefeat": "地图 - 按失败条件排序",
+	"vcmi.keyBindings.keyBinding.mapsSortFormat": "地图 - 按游戏版本排序",
+	"vcmi.keyBindings.keyBinding.mapsSortMaps": "地图 - 按地图排序",
+	"vcmi.keyBindings.keyBinding.mapsSortName": "地图 - 按名称排序",
+	"vcmi.keyBindings.keyBinding.mapsSortPlayers": "地图 - 按玩家数量排序",
+	"vcmi.keyBindings.keyBinding.mapsSortSize": "地图 - 按地图尺寸排序",
+	"vcmi.keyBindings.keyBinding.mapsSortVictory": "地图 - 按胜利条件排序",
+	"vcmi.keyBindings.keyBinding.marketArtifactExperience": "市场 - 宝物交换经验",
+	"vcmi.keyBindings.keyBinding.marketArtifactResource": "市场 - 宝物交换资源",
+	"vcmi.keyBindings.keyBinding.marketCreatureExperience": "市场 - 生物交换经验",
+	"vcmi.keyBindings.keyBinding.marketCreatureResource": "市场 - 生物交换资源",
+	"vcmi.keyBindings.keyBinding.marketDeal": "市场 - 成交",
+	"vcmi.keyBindings.keyBinding.marketMaxAmount": "市场 - 最大数量",
+	"vcmi.keyBindings.keyBinding.marketResourceArtifact": "市场 - 资源交换宝物",
+	"vcmi.keyBindings.keyBinding.marketResourcePlayer": "市场 - 给玩家资源",
+	"vcmi.keyBindings.keyBinding.marketResourceResource": "市场 - 资源交换资源",
+	"vcmi.keyBindings.keyBinding.marketSacrificeAll": "市场 - 献上所有",
+	"vcmi.keyBindings.keyBinding.marketSacrificeBackpack": "市场 - 献上行囊",
+	"vcmi.keyBindings.keyBinding.moveDown": "向下移动",
+	"vcmi.keyBindings.keyBinding.moveFirst": "移动到第一个",
+	"vcmi.keyBindings.keyBinding.moveLast": "移动到最后一个",
+	"vcmi.keyBindings.keyBinding.moveLeft": "向左移动",
+	"vcmi.keyBindings.keyBinding.movePageDown": "向下翻页",
+	"vcmi.keyBindings.keyBinding.movePageUp": "向上翻页",
+	"vcmi.keyBindings.keyBinding.moveRight": "向右移动",
+	"vcmi.keyBindings.keyBinding.moveUp": "向上移动",
+	"vcmi.keyBindings.keyBinding.recruitmentMax": "招募最大数量",
+	"vcmi.keyBindings.keyBinding.recruitmentMin": "招募最小数量",
+	"vcmi.keyBindings.keyBinding.recruitmentSwitchLevel": "切换招募生物级别",
+	"vcmi.keyBindings.keyBinding.recruitmentUpgrade": "招募升级",
+	"vcmi.keyBindings.keyBinding.recruitmentUpgradeAll": "招募全部升级",
+	"vcmi.keyBindings.keyBinding.selectIndex1": "选取第1个",
+	"vcmi.keyBindings.keyBinding.selectIndex2": "选取第2个",
+	"vcmi.keyBindings.keyBinding.selectIndex3": "选取第3个",
+	"vcmi.keyBindings.keyBinding.selectIndex4": "选取第4个",
+	"vcmi.keyBindings.keyBinding.selectIndex5": "选取第5个",
+	"vcmi.keyBindings.keyBinding.selectIndex6": "选取第6个",
+	"vcmi.keyBindings.keyBinding.selectIndex7": "选取第7个",
+	"vcmi.keyBindings.keyBinding.selectIndex8": "选取第8个",
+	"vcmi.keyBindings.keyBinding.settingsLoadGame": "设置 - 载入进度",
+	"vcmi.keyBindings.keyBinding.settingsNewGame": "设置 - 新游戏",
+	"vcmi.keyBindings.keyBinding.settingsQuitGame": "设置 - 退出游戏",
+	"vcmi.keyBindings.keyBinding.settingsRestartGame": "设置 - 重新开始e",
+	"vcmi.keyBindings.keyBinding.settingsSaveGame": "设置 - 保存进度",
+	"vcmi.keyBindings.keyBinding.settingsToMainMenu": "设置 - 主菜单",
+	"vcmi.keyBindings.keyBinding.spectateSkipBattle": "观战 - 跳过战斗",
+	"vcmi.keyBindings.keyBinding.spectateSkipBattleResult": "观战 - 跳过战斗结果",
+	"vcmi.keyBindings.keyBinding.spectateTrackHero": "观战 - 追踪英雄",
+	"vcmi.keyBindings.keyBinding.spellbookTabAdventure": "魔法书 - 冒险魔法标签",
+	"vcmi.keyBindings.keyBinding.spellbookTabCombat": "魔法书 - 战斗魔法标签",
+	"vcmi.keyBindings.keyBinding.spellbookSearchFocus": "魔法书 - 激活搜索框",
+	"vcmi.keyBindings.keyBinding.townOpenFort": "城镇 - 打开要塞",
+	"vcmi.keyBindings.keyBinding.townOpenGarrisonedHero": "城镇 - 打开驻守英雄",
+	"vcmi.keyBindings.keyBinding.townOpenHall": "城镇 - 打开建造大厅",
+	"vcmi.keyBindings.keyBinding.townOpenHero": "城镇 - 打开英雄",
+	"vcmi.keyBindings.keyBinding.townOpenHeroExchange": "城镇 - 打开英雄交换",
+	"vcmi.keyBindings.keyBinding.townOpenMageGuild": "城镇 - 打开魔法行会",
+	"vcmi.keyBindings.keyBinding.townOpenMarket": "城镇 - 打开市场",
+	"vcmi.keyBindings.keyBinding.townOpenRecruitment": "城镇 - 打开招募生物",
+	"vcmi.keyBindings.keyBinding.townOpenTavern": "城镇 - 打开酒馆",
+	"vcmi.keyBindings.keyBinding.townOpenThievesGuild": "城镇 - 打开盗贼行会",
+	"vcmi.keyBindings.keyBinding.townOpenVisitingHero": "城镇 - 打开来访英雄",
+	"vcmi.keyBindings.keyBinding.townSwapArmies": "城镇 - 交换军队",
+	"vcmi.keyBindings.keyBinding.listHeroUp": "英雄列表 - 上移",
+	"vcmi.keyBindings.keyBinding.listHeroDown": "英雄列表 - 下移",
+	"vcmi.keyBindings.keyBinding.listHeroTop": "英雄列表 - 置顶",
+	"vcmi.keyBindings.keyBinding.listHeroBottom": "英雄列表 - 置底",
+	"vcmi.keyBindings.keyBinding.listHeroDismiss": "英雄列表 - 解雇",
+	"vcmi.keyBindings.keyBinding.listTownUp": "城镇列表 - 上移",
+	"vcmi.keyBindings.keyBinding.listTownDown": "城镇列表 - 下移",
+	"vcmi.keyBindings.keyBinding.listTownTop": "城镇列表 - 置顶",
+	"vcmi.keyBindings.keyBinding.listTownBottom": "城镇列表 - 置底",
+	"vcmi.keyBindings.keyBinding.mouseCursorX" : "鼠标光标X轴",
+	"vcmi.keyBindings.keyBinding.mouseCursorY" : "鼠标光标Y轴",
+	"vcmi.keyBindings.keyBinding.mouseSwipeX" : "鼠标拖动X轴",
+	"vcmi.keyBindings.keyBinding.mouseSwipeY" : "鼠标拖动Y轴",
+	"vcmi.keyBindings.keyBinding.mouseClickLeft": "鼠标左键点击",
+	"vcmi.keyBindings.keyBinding.mouseClickRight": "鼠标右键点击",
+
 	"vcmi.systemOptions.videoGroup" : "视频设置",
 	"vcmi.systemOptions.audioGroup" : "音频设置",
 	"vcmi.systemOptions.otherGroup" : "其他设置", // unused right now
@@ -428,7 +698,7 @@
 	"vcmi.credits.idea" : "创意",
 	"vcmi.credits.developing" : "开发",
 	"vcmi.credits.testing" : "测试",
-	"core.credits.createdBy" : "创作者y",
+	"core.credits.createdBy" : "创作者",
 	"core.credits.executiveProducer" : "执行制作人",
 	"core.credits.producer" : "制作人",
 	"core.credits.director" : "导演",
@@ -495,6 +765,7 @@
 	"vcmi.heroWindow.sortBackpackByClass.hover"  : "按类型排序",
 	"vcmi.heroWindow.sortBackpackByClass.help"  : "{按类型排序}\n\n将行囊里的宝物按装备槽排序:低级宝物、中级宝物、高级宝物、圣物。",
 	"vcmi.heroWindow.fusingArtifact.fusing" : "你已拥有融合%s所需的全部组件,想现在进行融合吗?{所有组件在融合后将被消耗。}",
+	"vcmi.heroWindow.lockedartifact.hover" : "被%s占用",
 
 	"vcmi.tavernWindow.inviteHero"  : "邀请英雄",
 

+ 1 - 1
Mods/vcmi/Content/config/rmg/symmetric/6lm10a.json

@@ -272,7 +272,7 @@
 			{ "a" : "4", "b" : "23", "guard" : 3000, "road" : "false" },
 			{ "a" : "4", "b" : "25", "guard" : 3000, "road" : "true" },
 
-			{ "a" : "5", "b" : "13", "guard" : 6000, "road" : "random " },
+			{ "a" : "5", "b" : "13", "guard" : 6000, "road" : "random" },
 			{ "a" : "5", "b" : "24", "guard" : 3000, "road" : "random" },
 			{ "a" : "5", "b" : "24", "guard" : 3000, "road" : "random" },
 

+ 0 - 18
clientapp/icons/generate_icns.py

@@ -1,18 +0,0 @@
-from PIL import Image
-import os, sys, shutil
-
-img = Image.open(sys.argv[1])
-if img.size != (1024,1024):
-    print("Input image must be 1024x1024. Provided image is %dx%d" % img.size)
-
-os.mkdir("vcmi.iconset")
-for i in [16, 32, 128, 256, 512]:
-    resized = img.resize((i, i), Image.ANTIALIAS)
-    resized.save("vcmi.iconset/icon_%dx%d.png" % (i, i))
-
-    resized2x = img.resize((2*i, 2*i), Image.ANTIALIAS)
-    resized2x.save("vcmi.iconset/icon_%dx%[email protected]" % (i, i))
-
-os.system("iconutil -c icns vcmi.iconset")
-shutil.rmtree("vcmi.iconset")
-

+ 2 - 2
config/gameConfig.json

@@ -655,7 +655,7 @@
 				"creatureBankNarrow" : {
 					"tacticsAllowed" : false,
 					"obstaclesAllowed" : false,
-					"attackerCommander" : 95,
+					"attackerCommander" : 94,
 					"defenderCommander" : 8,
 					"attackerUnits": [ 57, 61, 90, 93, 96, 125, 129 ],
 					"defenderUnits": [ 15, 185, 172, 2, 100, 87, 8 ]
@@ -664,7 +664,7 @@
 				"creatureBankWide" : {
 					"tacticsAllowed" : false,
 					"obstaclesAllowed" : false,
-					"attackerCommander" : 95,
+					"attackerCommander" : 94,
 					"defenderCommander" : 8,
 					"attackerUnits": [ 57, 61, 90, 93, 96, 125, 129 ],
 					"defenderUnits": [ 15, 185, 171, 1, 100, 86, 8 ]

+ 1 - 2
config/schemas/template.json

@@ -186,10 +186,9 @@
 	},
 	
 	"additionalProperties" : false,
+	"required" : ["zones", "connections", "minSize", "maxSize", "players"],
 	"properties" :
 	{
-		"required" : ["zones", "connections", "minSize", "maxSize", "players"],
-		
 		"players" : {
 			"description" : "Number of players that will be present on map (human or AI)",
 			"type": "string"

+ 10 - 0
launcher/main.cpp

@@ -15,6 +15,8 @@
 #include "../lib/VCMIDirs.h"
 
 #include <QApplication>
+#include <QNetworkProxy>
+#include <QNetworkProxyFactory>
 
 // Conan workaround https://github.com/conan-io/conan-center-index/issues/13332
 #ifdef VCMI_IOS
@@ -49,6 +51,14 @@ int MAIN_EXPORT main(int argc, char * argv[])
 #endif
 	QApplication vcmilauncher(argc, argv);
 
+	// use system proxy
+	{
+		QNetworkProxyFactory::setUseSystemConfiguration(true);
+		const auto systemProxies = QNetworkProxyFactory::systemProxyForQuery();
+		if(!systemProxies.isEmpty())
+			QNetworkProxy::setApplicationProxy(systemProxies[0]);
+	}
+
 	launcher::prepare();
 
 	MainWindow mainWindow;

+ 3 - 3
launcher/modManager/cdownloadmanager_moc.cpp

@@ -122,7 +122,7 @@ void CDownloadManager::downloadFinished(QNetworkReply * reply)
 	}
 
 	if(downloadComplete)
-		finished(successful, failed, encounteredErrors);
+		Q_EMIT finished(successful, failed, encounteredErrors);
 
 	file.reply->deleteLater();
 	file.reply = nullptr;
@@ -145,11 +145,11 @@ void CDownloadManager::downloadProgressChanged(qint64 bytesReceived, qint64 byte
 	quint64 received = 0;
 	for(auto & entry : currentDownloads)
 		received += entry.bytesReceived > 0 ? entry.bytesReceived : 0;
-	
+
 	if(received > total)
 		total = received;
 
-	downloadProgress(received, total);
+	Q_EMIT downloadProgress(received, total);
 }
 
 bool CDownloadManager::downloadInProgress(const QUrl & url) const

+ 16 - 16
launcher/modManager/cmodlistview_moc.cpp

@@ -97,7 +97,7 @@ void CModListView::setupModsView()
 	ui->allModsView->setUniformRowHeights(true);
 
 	ui->allModsView->setContextMenuPolicy(Qt::CustomContextMenu);
-	
+
 	connect(ui->allModsView, SIGNAL(customContextMenuRequested(const QPoint &)),
 		this, SLOT(onCustomContextMenu(const QPoint &)));
 
@@ -332,7 +332,7 @@ QString CModListView::genModInfoText(const ModState & mod)
 
 	if((!mod.isInstalled() || mod.isUpdateAvailable()) && !mod.getDownloadSizeFormatted().isEmpty())
 		result += replaceIfNotEmpty(mod.getDownloadSizeFormatted(), lineTemplate.arg(tr("Download size")));
-	
+
 	result += replaceIfNotEmpty(mod.getAuthors(), lineTemplate.arg(tr("Authors")));
 
 	if(!mod.getLicenseName().isEmpty())
@@ -750,7 +750,7 @@ void CModListView::on_uninstallButton_clicked()
 	QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
 
 	doUninstallMod(modName);
-	
+
 	checkManagerErrors();
 }
 
@@ -845,13 +845,13 @@ void CModListView::downloadFinished(QStringList savedFiles, QStringList failedFi
 	enqueuedModDownloads.clear();
 	dlManager->deleteLater();
 	dlManager = nullptr;
-	
+
 	ui->progressBar->setMaximum(0);
 	ui->progressBar->setValue(0);
 
 	if(doInstallFiles)
 		installFiles(savedFiles);
-	
+
 	hideProgressBar();
 }
 
@@ -976,7 +976,7 @@ void CModListView::installFiles(QStringList files)
 		logGlobal->info("Installing chronicles: started");
 		ui->progressBar->setFormat(tr("Installing Heroes Chronicles"));
 		ui->progressWidget->setVisible(true);
-		ui->pushButton->setEnabled(false);
+		ui->abortButton->setEnabled(false);
 
 		float prog = 0.0;
 
@@ -986,17 +986,17 @@ void CModListView::installFiles(QStringList files)
 			ce.installChronicles(exe);
 			return true;
 		});
-		
+
 		while(futureExtract.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready)
 		{
 			extractionProgress(static_cast<int>(prog * 1000.f), 1000);
 			qApp->processEvents();
 		}
-		
+
 		if(futureExtract.get())
 		{
 			hideProgressBar();
-			ui->pushButton->setEnabled(true);
+			ui->abortButton->setEnabled(true);
 			ui->progressWidget->setVisible(false);
 			//update
 			reload("chronicles");
@@ -1062,7 +1062,7 @@ void CModListView::installMods(QStringList archives)
 	}
 
 
-	reload(lastInstalled);	
+	reload(lastInstalled);
 
 	if (!modsToEnable.empty())
 	{
@@ -1228,7 +1228,7 @@ void CModListView::on_refreshButton_clicked()
 	loadRepositories();
 }
 
-void CModListView::on_pushButton_clicked()
+void CModListView::on_abortButton_clicked()
 {
 	delete dlManager;
 	dlManager = nullptr;
@@ -1266,7 +1266,7 @@ void CModListView::loadScreenshots()
 
 	if (!ui->allModsView->currentIndex().isValid())
 		return;
-		
+
 	ui->screenshotsList->clear();
 	QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
 	assert(modStateModel->isModExists(modName)); //should be filtered out by check above
@@ -1404,10 +1404,10 @@ void CModListView::on_allModsView_doubleClicked(const QModelIndex &index)
 {
 	if(!index.isValid())
 		return;
-	
+
 	auto modName = index.data(ModRoles::ModNameRole).toString();
 	auto mod = modStateModel->getMod(modName);
-	
+
 	QStringList notInstalledDependencies = this->getModsToInstall(mod.getID());
 	QStringList unavailableDependencies = this->findUnavailableMods(notInstalledDependencies);
 
@@ -1422,14 +1422,14 @@ void CModListView::on_allModsView_doubleClicked(const QModelIndex &index)
 		on_updateButton_clicked();
 		return;
 	}
-	
+
 	if(index.column() == ModFields::NAME)
 	{
 		if(ui->allModsView->isExpanded(index))
 			ui->allModsView->collapse(index);
 		else
 			ui->allModsView->expand(index);
-		
+
 		return;
 	}
 

+ 1 - 1
launcher/modManager/cmodlistview_moc.h

@@ -147,7 +147,7 @@ private slots:
 	void on_updateButton_clicked();
 	void on_uninstallButton_clicked();
 	void on_installButton_clicked();
-	void on_pushButton_clicked();
+	void on_abortButton_clicked();
 	void on_refreshButton_clicked();
 	void on_allModsView_activated(const QModelIndex & index);
 	void on_tabWidget_currentChanged(int index);

+ 1 - 1
launcher/modManager/cmodlistview_moc.ui

@@ -337,7 +337,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
        </widget>
       </item>
       <item>
-       <widget class="QPushButton" name="pushButton">
+       <widget class="QPushButton" name="abortButton">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
           <horstretch>0</horstretch>

+ 1 - 1
lib/entities/faction/CTownHandler.cpp

@@ -331,7 +331,7 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
 	//MODS COMPATIBILITY FOR pre-1.6
 	if(ret->produce.empty() && ret->bid == BuildingID::RESOURCE_SILO)
 	{
-		logGlobal->warn("Resource silo in town '%s' does not produces any resources!", ret->town->faction->getJsonKey());
+		logGlobal->warn("Resource silo in town '%s' does not produce any resources!", ret->town->faction->getJsonKey());
 		switch (ret->town->primaryRes.toEnum())
 		{
 			case EGameResID::GOLD:

+ 3 - 3
lib/json/JsonUtils.cpp

@@ -34,7 +34,7 @@ static std::optional<int> getIndexSafe(const JsonNode & node, const std::string
 	}
 	catch(const std::out_of_range & )
 	{
-		logMod->warn("Failed to replace index when replacing individual items in array. Value '%s' does not exists in targeted array of %d items", keyName, node.Vector().size());
+		logMod->warn("Failed to replace index when replacing individual items in array. Value '%s' does not exist in targeted array of %d items", keyName, node.Vector().size());
 		return std::nullopt;
 	}
 };
@@ -253,14 +253,14 @@ void JsonUtils::merge(JsonNode & dest, JsonNode & source, bool ignoreOverride, b
 						else if (boost::algorithm::starts_with(node.first, "insert@"))
 						{
 							constexpr int numberPosition = std::char_traits<char>::length("insert@");
-							auto index = getIndexSafe(node.second, node.first.substr(numberPosition));
+							auto index = getIndexSafe(dest, node.first.substr(numberPosition));
 							if (index)
 								dest.Vector().insert(dest.Vector().begin() + index.value(), std::move(node.second));
 						}
 						else if (boost::algorithm::starts_with(node.first, "modify@"))
 						{
 							constexpr int numberPosition = std::char_traits<char>::length("modify@");
-							auto index = getIndexSafe(node.second,	node.first.substr(numberPosition));
+							auto index = getIndexSafe(dest,	node.first.substr(numberPosition));
 							if (index)
 								merge(dest.Vector().at(index.value()), node.second, ignoreOverride);
 						}

+ 1 - 1
lib/modding/ContentTypeHandler.cpp

@@ -154,7 +154,7 @@ bool ContentTypeHandler::loadMod(const std::string & modName, bool validate)
 		{
 			// normal new object
 			logMod->trace("no index in loadMod(%s)", name);
-			performValidate(data,name);
+			performValidate(data, name);
 			handler->loadObject(modName, name, data);
 		}
 	}

+ 19 - 0
osx/generate_icns.sh

@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+iconset='vcmi.iconset'
+mkdir "$iconset"
+
+cd "$iconset"
+for multiplier in 1 2 ; do
+	if [[ $multiplier != 1 ]] ; then
+		suffix="@${multiplier}x"
+	fi
+	for size in 16 32 128 256 512 ; do
+		realSize=$(( $size * $multiplier ))
+		ln "../../clientapp/icons/vcmiclient.${realSize}x${realSize}.png" "icon_${size}x${size}${suffix}.png"
+	done
+done
+cd ..
+
+iconutil -c icns "$iconset"
+rm -rf "$iconset"

BIN
osx/vcmi.icns