├── README.md ├── addons ├── BattleEssential.py ├── CharsEssential.py ├── JT82.py ├── __init__.py ├── allChars.py ├── fakeGacha.py ├── gachaSimulation.py ├── graduateChars.py ├── moreChars.py ├── unlockSkins.py └── userStatus.py ├── capturedData ├── FriendAssest.txt ├── battleFinish.txt └── crisisBattle.txt ├── data ├── arkhack_data.json ├── arkhack_pool.json ├── arkhack_troop.json ├── character_table.json └── skin_table.json ├── dataProcess.py ├── frida_hooks └── keyivhook_1280.js ├── main.py ├── model ├── __init__.py └── troopBuilder.py ├── script └── allCharPlus.py └── troopEditor.py /README.md: -------------------------------------------------------------------------------- 1 | # Arknights-Dolos 2 | 3 | ## 该项目已停止开发 4 | 5 | ## Update 该项目被[Rhine-DFramwork](https://github.com/Rhine-Department-0xf/Rhine-DFramwork)整合. 我不会再进行任何更新和开发了. 6 | 7 | ## 免责申明 8 | 9 | ### 本软件仅供个人学习测试使用,请在下载后24小时内删除,不得用于商业用途,否则后果自负。 10 | 11 | ### 使用本软件对自己以及相关公司造成的所有损失和法律责任一律与本人无关,一切后果自负。 12 | 13 | ### 禁止使用者对其进行以任何方式的发行,传播,宣传。上述行为对自己以及相关公司造成的所有损失和法律责任一律与本人无关,一切后果自负。 14 | 15 | ### 好好游戏,别开外挂 16 | 17 | --- 18 | 19 | 20 | ## 简介 21 | 22 | Arknights-Dolos/明日方舟中间人攻击框架 23 | 24 | 使用 mitmproxy来捕获明日方舟的数据,借此来修改指定数据。 25 | 26 | 灵感来源: 27 | 28 | [GhostStar/Arknights-Armada](https://github.com/GhostStar/Arknights-Armada) 29 | 30 | [Tao0Lu/Arknights-Cheater](https://github.com/Tao0Lu/Arknights-Cheater) 31 | 32 | [破解未成年时间限制](https://www.bilibili.com/read/cv7795601) 33 | 34 | ## 原理 35 | 36 | 直接获取明日方舟的数据是获取不到的,因为明日方舟使用了本地服务器进行转发 37 | 38 | 利用mitmproxy可以将把数据传给服务器,略过本地服务器的转发 39 | 40 | ``` 41 | 原来的: 42 | 43 | Request -> ak-gs-localhost.hypergryph.com -> ak-gs.hypergryph.com 44 | 45 | Request -> ak-gs-b-localhost.hypergryph.com -> ak-gs.hypergryph.com 46 | 47 | Request -> ak-as-localhost.hypergryph.com -> ak-as.hypergryph.com 48 | 49 | mitmproxy修改后的 50 | 51 | Request -> ak-gs.hypergryph.com 52 | 53 | Request -> ak-as.hypergryph.com 54 | 55 | ``` 56 | 57 | 破解本地服务器转发的方法来自 [GhostStar/Arknights-Armada](https://github.com/GhostStar/Arknights-Armada) 58 | 59 | ## 使用说明 60 | 61 | 1. clone本repository 62 | 63 | 2. 安装mitmproxy, `pip3 install mitmproxy` 64 | 65 | 2. 手机/模拟器上设置代理服务器 66 | 67 | 3. 在手机、模拟器中信任mitmproxy证书 68 | 69 | 4. 启动main,要启动网页还是命令行可以自己改代码 70 | 71 | 5. 重新进入游戏,开始 72 | 73 | ps: 对如何配置mitmproxy有疑问的建议参照 [Tao0Lu/Arknights-Cheater](https://github.com/Tao0Lu/Arknights-Cheater) 74 | 75 | ## 数据更新说明 76 | 77 | 从[ArknightsGameData/tree/master/zh_CN/gamedata/excel](https://github.com/Kengxxiao/ArknightsGameData)中 78 | 79 | 下载 80 | 81 | [character_table.json](https://github.com/Kengxxiao/ArknightsGameData/blob/master/zh_CN/gamedata/excel/character_table.json) 82 | 83 | [skin_table.json](https://github.com/Kengxxiao/ArknightsGameData/blob/master/zh_CN/gamedata/excel/skin_table.json) 84 | 85 | 86 | 放入 /data 文件夹内 87 | 88 | 运行 `python dataProcess.py` 89 | 90 | ## 已实现addons 91 | 92 | 1. ArkEssential: 转发本地服务器 93 | 94 | 2. CharsEssential: 自定义角色前置 95 | 96 | 3. BattleEssential: 自定义角色前置 97 | 98 | 4. fakeGacha: 虚假10连 99 | 100 | 5. graduateChars: 全满潜能,满级,满专精 (前置CharsEssential,BattleEssential) 101 | 102 | 6. unlockSkins: 解锁全皮肤 (前置CharsEssential) 103 | 104 | 7. userStatus: 自定义用户信息以及原石,只能拿来看. 105 | 106 | 8. allChars: 全干员 (前置CharsEssential,BattleEssential) 107 | 108 | 9. moreChars: 自定义干员 (前置CharsEssential,BattleEssential) 109 | 110 | 10. gachaSimulation: 抽卡模拟器 (前置CharsEssential,allChars) 111 | 112 | ## 效果 113 | 自定义十连 114 | 115 | ![tengacha](https://user-images.githubusercontent.com/32156054/100481260-8126ea80-312e-11eb-9d04-f855ae813f28.png) 116 | 117 | 全角色,全满级 118 | 119 | ![allchar](https://user-images.githubusercontent.com/32156054/100481261-82581780-312e-11eb-8de6-9501c0c4e69d.png) 120 | 121 | 修改信息 122 | 123 | ![infoedit](https://user-images.githubusercontent.com/32156054/100481264-83894480-312e-11eb-90fb-e55654d6c05e.png) 124 | 125 | 自定义角色 126 | 127 | ![customChar](https://user-images.githubusercontent.com/32156054/100485093-c69ce500-3139-11eb-82e7-e21373f953ab.png) 128 | -------------------------------------------------------------------------------- /addons/BattleEssential.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow, HTTPResponse 2 | from addons import ArkInterceptor 3 | from model.troopBuilder import troopBuilder 4 | import json,copy 5 | 6 | class BattleEssential(ArkInterceptor): 7 | ''' 8 | Require: CharsEssential 9 | ''' 10 | 11 | def __init__(self): 12 | self.info("Loading success") 13 | 14 | def request(self, flow:HTTPFlow): 15 | """ 16 | { 17 | "changeSkill": 0, 18 | "slots": [{ 19 | "charInstId": 1, 20 | "skillIndex": 0 21 | },null,null,null,null,null,null 22 | ], 23 | "squadId": "0" 24 | } 25 | """ 26 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/quest/squadFormation"): 27 | self.info("Receive squad change request") 28 | req = json.loads(flow.request.get_text()) 29 | self.tBuilder.squads[req["squadId"]]["slots"] = req["slots"] 30 | req = copy.deepcopy(req) 31 | req["slots"] = [{ 32 | "charInstId": 2, 33 | "skillIndex": -1 34 | }, None, None, None, None, None, None, None, None, None, None, None] 35 | flow.request.set_text(json.dumps(req)) 36 | self.info("complete") 37 | 38 | if self.inServersList(flow.request.host) and (flow.request.path.startswith("/quest/battleStart") or 39 | flow.request.path.startswith("/campaignV2/battleStart")): 40 | self.info("battle %s start: setting squad for remote server" % flow.request.path.split("/")[1]) 41 | req = json.loads(flow.request.get_text()) 42 | req['squad']['slots'] = [{ 43 | "charInstId": 2, 44 | "skillIndex": -1 45 | }, None, None, None, None, None, None, None, None, None, None, None] 46 | flow.request.set_text(json.dumps(req)) 47 | self.info("complete") 48 | 49 | def response(self, flow: HTTPFlow): 50 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/quest/squadFormation"): 51 | data = json.loads(flow.response.get_text()) 52 | self.info('setting squad data for local modification') 53 | for sid in data['playerDataDelta']['modified']['troop']['squads'].keys(): 54 | data['playerDataDelta']['modified']['troop']['squads'][sid] = self.tBuilder.squads[sid] 55 | flow.response.set_text(json.dumps(data)) 56 | self.info("complete") 57 | 58 | #master.addons.add(BattleEssential()) 59 | 60 | # Deprecated 61 | # def _weak_request(self,flow: HTTPFlow): 62 | # if self.inServersList(flow.request.host) and flow.request.path.startswith("/quest/squadFormation"): 63 | # self.info("setting squad for remote server sync") 64 | # req = json.loads(flow.request.get_text()) 65 | # self.tBuilder.squads[req["squadId"]]["slots"] = req["slots"] 66 | # req = copy.deepcopy(req) 67 | # for s in req['slots']: 68 | # if s is not None and s["skillIndex"] != -1: 69 | # s["skillIndex"] = 0 70 | # flow.request.set_text(json.dumps(req)) 71 | # self.info("complete") 72 | # if self.inServersList(flow.request.host) and flow.request.path.startswith("/charBuild/setDefaultSkill"): 73 | # self.info("Receive default skill change change request") 74 | # req = json.loads(flow.request.get_text()) 75 | # self.tBuilder.chars[str(req["charInstId"])]["defaultSkillIndex"] = req["defaultSkillIndex"] 76 | # resp = {"playerDataDelta": {"deleted": {}, 77 | # "modified": { 78 | # "troop": {"chars": {str(req["charInstId"]): {"defaultSkillIndex": req["defaultSkillIndex"]}}}}}} 79 | # self.info("make response") 80 | # flow.response = HTTPResponse.make(200, 81 | # json.dumps(resp), 82 | # {"Content-Type": "application/json; charset=utf-8"}) 83 | # self.info("Reply Complete") 84 | # if self.inServersList(flow.request.host) and flow.request.path.startswith("/quest/battleStart"): 85 | # self.info("battle start: setting squad for remote server") 86 | # req = json.loads(flow.request.get_text()) 87 | # for s in req['squad']['slots']: 88 | # if s is not None and s["skillIndex"] != -1: 89 | # s["skillIndex"] = 0 90 | # flow.request.set_text(json.dumps(req)) 91 | # self.info("complete") 92 | # 93 | # 94 | # def _weak_response(self,flow: HTTPFlow): 95 | # if self.inServersList(flow.request.host) and flow.request.path.startswith("/quest/squadFormation"): 96 | # data = json.loads(flow.response.get_text()) 97 | # self.info('setting squad data for local modification') 98 | # for sid in data['playerDataDelta']['modified']['troop']['squads'].keys(): 99 | # data['playerDataDelta']['modified']['troop']['squads'][sid] = self.tBuilder.squads[sid] 100 | # flow.response.set_text(json.dumps(data)) 101 | # self.info("complete") 102 | -------------------------------------------------------------------------------- /addons/CharsEssential.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow, HTTPResponse 2 | from addons import ArkInterceptor 3 | from model.troopBuilder import troopBuilder 4 | import json,copy 5 | 6 | 7 | class CharsEssential(ArkInterceptor): 8 | def __init__(self,mode="weak"): 9 | self.mode = mode 10 | self.info("Loading success, mode %s" %self.mode) 11 | 12 | def request(self, flow:HTTPFlow): 13 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/charBuild/setDefaultSkill"): 14 | self.info("Receive default skill change change request") 15 | req = json.loads(flow.request.get_text()) 16 | self.tBuilder.chars[str(req["charInstId"])]["defaultSkillIndex"] = req["defaultSkillIndex"] 17 | resp = {"playerDataDelta": {"deleted": {}, 18 | "modified": { 19 | "troop": {"chars": {str(req["charInstId"]): { 20 | "defaultSkillIndex": req["defaultSkillIndex"]}}}}}} 21 | self.info("make response") 22 | flow.response = HTTPResponse.make(200, 23 | json.dumps(resp), 24 | {"Content-Type": "application/json; charset=utf-8"}) 25 | self.info("Reply Complete") 26 | 27 | def response(self, flow: HTTPFlow): 28 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/account/syncData"): 29 | data = json.loads(flow.response.get_text()) 30 | if self.tBuilder is None: 31 | self.info("Troop builder not found, create from response data") 32 | ArkInterceptor.tBuilder = troopBuilder(data["user"]["troop"]["curCharInstId"], 33 | data["user"]["troop"]["curSquadCount"], 34 | data["user"]["troop"]["squads"], 35 | data["user"]["troop"]["chars"]) 36 | else: 37 | self.info("Find exist troop builder, write config to response") 38 | data["user"]["troop"] = self.tBuilder.dump() 39 | flow.response.set_text(json.dumps(data)) 40 | ArkInterceptor.tBuilder.setCharacterBuilder(ArkInterceptor.cBuilder) 41 | self.info("Complete") 42 | 43 | #master.addons.add(CharsEssential()) -------------------------------------------------------------------------------- /addons/JT82.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow, HTTPResponse 2 | from addons import ArkInterceptor 3 | from model.troopBuilder import troopBuilder 4 | import json, copy 5 | 6 | 7 | class JT82(ArkInterceptor): 8 | ''' 9 | Require: BattleEssential 10 | ''' 11 | 12 | def __init__(self): 13 | self.info("Loading success") 14 | 15 | def response(self, flow: HTTPFlow): 16 | if flow.request.host in self.ServersList and flow.request.path.startswith("/account/syncData"): 17 | data = json.loads(flow.response.get_text()) 18 | data["user"]["dungeon"]["stages"]["main_08-17"] = {"stageId": "main_08-17", "completeTimes": 0, "startTimes": 0, "practiceTimes": 0, "state": 0, 19 | "hasBattleReplay": 0, "noCostCnt": 1} 20 | flow.response.set_text(json.dumps(data)) 21 | self.info("Complete") 22 | 23 | def request(self, flow: HTTPFlow): 24 | if flow.request.host in self.ServersList and flow.request.path.startswith("/quest/battleStart"): 25 | req = json.loads(flow.request.get_text()) 26 | if (req["stageId"] != "main_08-16"): 27 | return 28 | self.info("Receive JT8-2 battle start request") 29 | fakeData = { 30 | "apFailReturn": 20, 31 | "battleId": "6c86c7c0-3373-11eb-9784-0d36b8275660", 32 | "isApProtect": 0, 33 | "notifyPowerScoreNotEnoughIfFailed": False, 34 | "playerDataDelta": { 35 | "deleted": {}, 36 | "modified": { 37 | # "dungeon": { 38 | # "stages": { 39 | # "main_07-01": { 40 | # "completeTimes": 1, 41 | # "hasBattleReplay": 1, 42 | # "noCostCnt": 0, 43 | # "practiceTimes": 0, 44 | # "stageId": "main_07-01", 45 | # "startTimes": 2, 46 | # "state": 3 47 | # } 48 | # } 49 | # } 50 | } 51 | }, 52 | "result": 0 53 | } 54 | flow.response = HTTPResponse.make(200, json.dumps(fakeData), 55 | {"Content-Type": "application/json; charset=utf-8"}) 56 | self.info("complete") 57 | -------------------------------------------------------------------------------- /addons/__init__.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow 2 | from model.troopBuilder import troopBuilder,characterBuilder 3 | from functools import wraps 4 | import re 5 | 6 | class ArkInterceptor(): 7 | # from https://github.com/GhostStar/Arknights-Armada/ 8 | Servers = {"ak-gs-localhost.hypergryph.com": ("ak-gs.hypergryph.com", 8443), 9 | "ak-gs-b-localhost.hypergryph.com": ("ak-gs.hypergryph.com", 8443), 10 | "ak-as-localhost.hypergryph.com": ("ak-as.hypergryph.com", 9443)} 11 | 12 | ServersList = [key for key in Servers.keys()] + [val[0] for val in Servers.values()] 13 | 14 | tBuilder = None # type:troopBuilder 15 | cBuilder = characterBuilder.init() 16 | 17 | 18 | @staticmethod 19 | def setTroopBuilder(tb): 20 | ArkInterceptor.tBuilder = tb 21 | 22 | @staticmethod 23 | def checkExecutable(func): 24 | @wraps(func) 25 | def check(self,*args,**kwargs): 26 | if self.executable(): 27 | func(self,*args,**kwargs) 28 | return check 29 | 30 | def executable(self): 31 | return True 32 | 33 | def http_connect(self, flow: HTTPFlow): 34 | pass 35 | 36 | def request(self, flow:HTTPFlow): 37 | pass 38 | 39 | def response(self, flow: HTTPFlow): 40 | pass 41 | 42 | def inServersList(self,url): 43 | return re.match(r"ak-.*\.hypergryph.com",url) != None 44 | 45 | def info(self,msg): 46 | print("Arkhack - %s > %s" %(self.__class__.__name__,msg)) 47 | 48 | 49 | class ArkEssential(ArkInterceptor): 50 | def __init__(self): 51 | self.info("Load success") 52 | def http_connect(self, flow: HTTPFlow): 53 | # replace all localhost server to correct server 54 | if (flow.request.host in self.Servers.keys()): 55 | flow.request.host, flow.request.port = self.Servers.get(flow.request.host) -------------------------------------------------------------------------------- /addons/allChars.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow 2 | from addons import ArkInterceptor 3 | import json 4 | 5 | class allChars(ArkInterceptor): 6 | ''' 7 | Require: CharsEssential,BattleEssential 8 | ''' 9 | def __init__(self): 10 | self.execute = True 11 | self.info("Loading success") 12 | def executable(self): 13 | return self.execute 14 | 15 | @ArkInterceptor.checkExecutable 16 | def response(self, flow: HTTPFlow): 17 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/account/syncData"): 18 | self.info("Receive response") 19 | data = json.loads(flow.response.get_text()) 20 | char = [] 21 | self.info("Get character list") 22 | for c in self.tBuilder.cBuilder.characters.keys(): 23 | if "char" in c: 24 | char.append(c) 25 | self.info("add characters.....") 26 | for c in char: 27 | self.tBuilder.addCharacter(c) 28 | data["user"]["troop"] = self.tBuilder.dump() 29 | flow.response.set_text(json.dumps(data)) 30 | self.info("Complete") 31 | self.execute = False 32 | 33 | 34 | #master.addons.add(allChars()) -------------------------------------------------------------------------------- /addons/fakeGacha.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow 2 | from addons import ArkInterceptor 3 | import json 4 | 5 | class fakeGacha(ArkInterceptor): 6 | def response(self, flow: HTTPFlow): 7 | # do something in response 8 | if flow.request.host in self.ServersList and flow.request.path.startswith("/gacha/tenAdvancedGacha"): 9 | print("开始制作虚假的10连") 10 | data = json.loads(flow.response.get_text()) 11 | for index, gacha in enumerate(data["gachaResultList"]): 12 | if (index == 0): 13 | gacha["isNew"] = 1 14 | gacha["charInstId"] = 42 15 | gacha["itemGet"] = [ 16 | { 17 | "count": 1, 18 | "id": "4004", 19 | "type": "HGG_SHD" 20 | } 21 | ] 22 | else: 23 | gacha["isNew"] = 0 24 | gacha["charInstId"] = 42 25 | gacha["itemGet"] = [ 26 | { 27 | "count": 10, 28 | "id": "4004", 29 | "type": "HGG_SHD" 30 | }, 31 | { 32 | "count": 1, 33 | "id": "p_char_2013_cerber", 34 | "type": "MATERIAL" 35 | } 36 | ] 37 | gacha["charId"] = "char_2013_cerber" 38 | flow.response.set_text(json.dumps(data)) 39 | print("修改完成") -------------------------------------------------------------------------------- /addons/gachaSimulation.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow,HTTPResponse 2 | from addons import ArkInterceptor 3 | import json,random 4 | 5 | 6 | class gachaSimulation(ArkInterceptor): 7 | ''' 8 | Require: CharsEssential,allChars 9 | ''' 10 | dataPath = "./data/arkhack_pool.json" 11 | 12 | def __init__(self, dp=dataPath,baodi = True): 13 | self.poolData = { 14 | "poolInfo": [ 15 | {"rarityRank": 5,"charIdList": ["char_103_angel"],"totalPercent": 0.02,"upPercent":0.5}, 16 | {"rarityRank": 4,"charIdList": ["char_103_angel"],"totalPercent": 0.08,"upPercent":0.5}, 17 | {"rarityRank": 3,"charIdList": ["char_103_angel"],"totalPercent": 0.5,"upPercent":0.2}, 18 | {"rarityRank": 2, "charIdList": ["char_103_angel"], "totalPercent": 0.4,"upPercent":0} 19 | ]} 20 | try: 21 | with open(dp,"r",encoding="utf-8") as f: 22 | self.poolData = json.loads(f.read().strip()) 23 | except Exception as e: 24 | pass 25 | self.rarityList = [] 26 | self.gachaList = {} 27 | self.upChar = {"char_103_angel"} 28 | self.updateInfo() 29 | self.count = 0 30 | self.baodi = baodi 31 | self.info("Loading success") 32 | 33 | def setUp(self,*args): 34 | self.upChar = set(args) 35 | self.updateInfo() 36 | 37 | def addUp(self,*args): 38 | for arg in args: 39 | self.upChar.add(arg) 40 | self.updateInfo() 41 | 42 | def updateInfo(self): 43 | self.rarityList = [str(x["rarityRank"]) for x in self.poolData["poolInfo"] for i in range(int(x["totalPercent"]*100))] 44 | random.shuffle(self.rarityList) 45 | self.upnormalList = {} 46 | for x in self.poolData["poolInfo"]: 47 | rarity = str(x["rarityRank"]) 48 | self.upnormalList[rarity] = ["up" for i in range(int(x["upPercent"]*100))]+["normal" for i in range(100-int(x["upPercent"]*100))] 49 | self.gachaList[rarity] = {} 50 | self.gachaList[rarity]["normal"] = list(set(x["charIdList"]).difference(self.upChar)) 51 | self.gachaList[rarity]["up"] = list(set(x["charIdList"]).intersection(self.upChar)) 52 | if len(self.gachaList[rarity]["normal"]) == 0: 53 | self.gachaList[rarity]["normal"] = x["charIdList"] 54 | if len(self.gachaList[rarity]["up"]) == 0: 55 | self.gachaList[rarity]["up"] = x["charIdList"] 56 | 57 | def updateRarityList(self): 58 | for i in range(len(self.rarityList)): 59 | if self.rarityList[i] != "5": 60 | self.rarityList[i] = "5" 61 | return 62 | def getOne(self): 63 | self.count +=1 64 | if self.baodi and self.count >50: 65 | for i in range(2): 66 | self.updateRarityList() 67 | rarity = random.choice(self.rarityList) 68 | if rarity == "5": 69 | self.count =0 70 | self.updateInfo() 71 | pl = random.choice(self.upnormalList[rarity]) 72 | return (random.choice(self.gachaList[rarity][pl]),rarity) 73 | 74 | def getTen(self): 75 | return [self.getOne() for x in range(10)] 76 | 77 | def request(self, flow:HTTPFlow): 78 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/gacha/tenAdvancedGacha"): 79 | respData= {"gachaResultList":[],"playerDataDelta":{"deleted":{},"modified":{}}, "result": 0} 80 | self.info("十连中...") 81 | charlist = self.getTen() 82 | for charId,rarity in charlist: 83 | gacha = {} 84 | gacha["isNew"] = 0 85 | gacha["charId"] = charId 86 | cdata = self.tBuilder.getCharData(charId) 87 | if cdata == None: 88 | continue 89 | gacha["charInstId"] = cdata["instId"] 90 | if rarity == "5": 91 | gacha["itemGet"] = [ 92 | { 93 | "count": 15, 94 | "id": "4004", 95 | "type": "HGG_SHD" 96 | }, 97 | { 98 | "count": 1, 99 | "id": "p_"+charId, 100 | "type": "MATERIAL" 101 | } 102 | ] 103 | if rarity == "4": 104 | gacha["itemGet"] = [ 105 | { 106 | "count": 8, 107 | "id": "4004", 108 | "type": "HGG_SHD" 109 | }, 110 | { 111 | "count": 1, 112 | "id": "p_"+charId, 113 | "type": "MATERIAL" 114 | } 115 | ] 116 | if rarity == "3": 117 | gacha["itemGet"] = [ 118 | { 119 | "count": 30, 120 | "id": "4005", 121 | "type": "LGG_SHD" 122 | }, 123 | { 124 | "count": 1, 125 | "id": "p_"+charId, 126 | "type": "MATERIAL" 127 | } 128 | ] 129 | if rarity == "2": 130 | gacha["itemGet"] = [ 131 | { 132 | "count": 5, 133 | "id": "4005", 134 | "type": "LGG_SHD" 135 | }, 136 | { 137 | "count": 1, 138 | "id": "p_"+charId, 139 | "type": "MATERIAL" 140 | } 141 | ] 142 | respData["gachaResultList"].append(gacha) 143 | flow.response = HTTPResponse.make(200, json.dumps(respData), 144 | {"Content-Type": "application/json; charset=utf-8"}) 145 | self.info("完成") 146 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/gacha/advancedGacha"): 147 | respData= {"charGet":{},"playerDataDelta":{"deleted":{},"modified":{}}, "result": 0} 148 | self.info("单抽中...") 149 | charId,rarity = self.getOne() 150 | gacha = {} 151 | gacha["isNew"] = 0 152 | gacha["charId"] = charId 153 | cdata = self.tBuilder.getCharData(charId) 154 | gacha["charInstId"] = cdata["instId"] 155 | if rarity == "5": 156 | gacha["itemGet"] = [ 157 | { 158 | "count": 15, 159 | "id": "4004", 160 | "type": "HGG_SHD" 161 | }, 162 | { 163 | "count": 1, 164 | "id": "p_" + charId, 165 | "type": "MATERIAL" 166 | } 167 | ] 168 | if rarity == "4": 169 | gacha["itemGet"] = [ 170 | { 171 | "count": 8, 172 | "id": "4004", 173 | "type": "HGG_SHD" 174 | }, 175 | { 176 | "count": 1, 177 | "id": "p_" + charId, 178 | "type": "MATERIAL" 179 | } 180 | ] 181 | if rarity == "3": 182 | gacha["itemGet"] = [ 183 | { 184 | "count": 30, 185 | "id": "4005", 186 | "type": "LGG_SHD" 187 | }, 188 | { 189 | "count": 1, 190 | "id": "p_" + charId, 191 | "type": "MATERIAL" 192 | } 193 | ] 194 | if rarity == "2": 195 | gacha["itemGet"] = [ 196 | { 197 | "count": 5, 198 | "id": "4005", 199 | "type": "LGG_SHD" 200 | }, 201 | { 202 | "count": 1, 203 | "id": "p_" + charId, 204 | "type": "MATERIAL" 205 | } 206 | ] 207 | 208 | respData["charGet"] = gacha 209 | flow.response = HTTPResponse.make(200, json.dumps(respData), 210 | {"Content-Type": "application/json; charset=utf-8"}) 211 | self.info("完成") 212 | 213 | -------------------------------------------------------------------------------- /addons/graduateChars.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow 2 | from addons import ArkInterceptor 3 | from model.troopBuilder import troopBuilder 4 | import json 5 | 6 | class graduateChars(ArkInterceptor): 7 | ''' 8 | Require: CharsEssential,BattleEssential 9 | ''' 10 | def __init__(self): 11 | self.e = True 12 | self.info("Loading success") 13 | 14 | def executable(self): 15 | return self.e 16 | 17 | @ArkInterceptor.checkExecutable 18 | def response(self, flow: HTTPFlow): 19 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/account/syncData"): 20 | self.info("Receive response") 21 | data = json.loads(flow.response.get_text()) 22 | for key,char in self.tBuilder.chars.items(): 23 | self.info("Upgrade: %s-%s" %(key,char["charId"])) 24 | self.tBuilder.chars[key] = self.cBuilder.graduate(self.tBuilder.chars[key]) 25 | data["user"]["troop"] = self.tBuilder.dump() 26 | flow.response.set_text(json.dumps(data)) 27 | self.info("Complete") 28 | self.e = False 29 | 30 | #master.addons.add(graduateChars()) -------------------------------------------------------------------------------- /addons/moreChars.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow 2 | from addons import ArkInterceptor 3 | import json 4 | 5 | class moreChars(ArkInterceptor): 6 | ''' 7 | Require: CharsEssential,BattleEssential 8 | ''' 9 | def __init__(self): 10 | self.execute = True 11 | self.extraChars = [] 12 | self.info("Loading success") 13 | 14 | def addChar(self,char): 15 | self.extraChars.append(char) 16 | 17 | def addChars(self,chars): 18 | self.extraChars.extend(chars) 19 | 20 | def executable(self): 21 | return self.execute 22 | 23 | @ArkInterceptor.checkExecutable 24 | def response(self, flow: HTTPFlow): 25 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/account/syncData"): 26 | self.info("Receive response") 27 | data = json.loads(flow.response.get_text()) 28 | for c in self.extraChars: 29 | self.info("Adding extra character - %s" %c) 30 | self.tBuilder.addCharacter(c,force=True) 31 | data["user"]["troop"] = self.tBuilder.dump() 32 | flow.response.set_text(json.dumps(data)) 33 | self.info("Complete") 34 | self.execute = False 35 | 36 | # mc = moreChars() 37 | # mc.addChar("char_350_surtr") 38 | # mc.addChars(["char_350_surtr"]*10+["char_172_svrash"]*10+["char_180_amgoat"]*10+["char_151_myrtle"]*5+["char_222_bpipe"]*5+["char_400_weedy"]*12) 39 | # master.addons.add(mc) -------------------------------------------------------------------------------- /addons/unlockSkins.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow,HTTPResponse 2 | from addons import ArkInterceptor 3 | import json 4 | 5 | 6 | class unlockSkins(ArkInterceptor): 7 | ''' 8 | Require: CharsEssential 9 | ''' 10 | def __init__(self): 11 | self.info("Loading success") 12 | 13 | def request(self, flow: HTTPFlow): 14 | """ 15 | { 16 | "charInstId": 9, 17 | "skinId": "char_123_fang#1" 18 | } 19 | """ 20 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/charBuild/changeCharSkin"): 21 | self.info("Receive skin change request") 22 | req = json.loads(flow.request.get_text()) 23 | resp = {"playerDataDelta": {"deleted": {}, 24 | "modified": { "troop": {"chars": {str(req["charInstId"]): {"skin": req["skinId"]}}}}}} 25 | self.info("make response") 26 | self.tBuilder.chars[str(req["charInstId"])]["skin"] = req["skinId"] 27 | flow.response = HTTPResponse.make(200, 28 | json.dumps(resp), 29 | {"Content-Type":"application/json; charset=utf-8"}) 30 | self.info("Reply Complete") 31 | 32 | def response(self, flow: HTTPFlow): 33 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/account/syncData"): 34 | self.info("Receive response") 35 | data = json.loads(flow.response.get_text()) 36 | self.info("Unlocking....") 37 | data["user"]["skin"]["characterSkins"] = dict((key, 1) for key in self.cBuilder.skins) 38 | flow.response.set_text(json.dumps(data)) 39 | self.info("Complete") 40 | 41 | #master.addons.add(unlockSkins()) -------------------------------------------------------------------------------- /addons/userStatus.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow 2 | from addons import ArkInterceptor 3 | import json 4 | 5 | class userInfo(ArkInterceptor): 6 | mapper = {"nickName":lambda x:x.nickName, 7 | "nickNumber":lambda x:x.nickNumber, 8 | "level": lambda x:x.level, 9 | "exp":lambda x:x.exp, 10 | "resume":lambda x:x.resume, 11 | "uid":lambda x:x.uid} 12 | types = {"level":lambda x:int(x), 13 | "exp":lambda x:int(x)} 14 | 15 | def __init__(self): 16 | self.nickName,self.nickNumber,self.level,self.exp = [None] *4 17 | self.resume = None 18 | self.uid = None 19 | self.info("Loading success") 20 | 21 | @classmethod 22 | # 能用的只有nickname, nicknumber, level 和exp 23 | def init(cls,name,nums,level,exp): 24 | self = cls() 25 | self.nickName, self.nickNumber, self.level, self.exp = name,nums,level,exp 26 | #self.resume = resume 27 | # self.uid = uid 28 | return self 29 | 30 | 31 | def response(self, flow: HTTPFlow): 32 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/account/syncData"): 33 | self.info("Receive response") 34 | data = json.loads(flow.response.get_text()) 35 | for key,value in self.mapper.items(): 36 | val = value(self) 37 | if val is not None: 38 | self.info("Change %s: %s -> %s" %(key,data["user"]["status"][key],val)) 39 | if (key in self.types.keys()): 40 | data["user"]["status"][key] = self.types[key](val) 41 | else: 42 | data["user"]["status"][key] = val 43 | flow.response.set_text(json.dumps(data)) 44 | self.info("Complete") 45 | 46 | 47 | class userData(ArkInterceptor): 48 | mapper = {"ap":lambda x:x.ap, 49 | "maxAp":lambda x:x.maxAp, 50 | "androidDiamond": lambda x:x.diamond, 51 | "iosDiamond":lambda x:x.diamond, 52 | "diamondShard":lambda x:x.diamondShard, 53 | "gold":lambda x:x.gold 54 | } 55 | types = {"ap":lambda x:int(x), 56 | "maxAp":lambda x:int(x), 57 | "androidDiamond": lambda x:int(x), 58 | "iosDiamond":lambda x:int(x), 59 | "diamondShard":lambda x:int(x), 60 | "gold":lambda x:int(x) 61 | } 62 | 63 | def __init__(self): 64 | self.ap,self.maxAp,self.diamond,self.diamondShard,self.gold = [None] *5 65 | self.info("Loading success") 66 | 67 | @classmethod 68 | # 能用的只有nickname, nicknumber, level 和exp 69 | def init(cls,ap,maxAp,diamond,diamondShard,gold): 70 | self = cls() 71 | self.ap,self.maxAp,self.diamond,self.diamondShard,self.gold = ap,maxAp,diamond,diamondShard,gold 72 | return self 73 | 74 | def response(self, flow: HTTPFlow): 75 | if self.inServersList(flow.request.host) and flow.request.path.startswith("/account/syncData"): 76 | self.info("Receive response") 77 | data = json.loads(flow.response.get_text()) 78 | for key,value in self.mapper.items(): 79 | val = value(self) 80 | if val is not None: 81 | self.info("Change %s: %s -> %s" %(key,data["user"]["status"][key],val)) 82 | if (key in self.types.keys()): 83 | data["user"]["status"][key] = self.types[key](val) 84 | else: 85 | data["user"]["status"][key] = val 86 | flow.response.set_text(json.dumps(data)) 87 | self.info("Complete") 88 | 89 | # 90 | #info = userInfo.init("Rua牛","0000",120,0) 91 | #data = userData.init(999,999,1919810,114514,6666666) 92 | 93 | # master.addons.add(info) 94 | # master.addons.add(data) -------------------------------------------------------------------------------- /capturedData/FriendAssest.txt: -------------------------------------------------------------------------------- 1 | POST https://ak-gs-localhost.hypergryph.com:8443/quest/getFriendAssistCharList HTTP/1.1 2 | uid: 50968260 3 | X-Unity-Version: 2017.4.39f1 4 | secret: pnKGte/A86oo6rhS7WqN6gFIYWFdK9bj 5 | Content-Type: application/json 6 | seqnum: 5 7 | User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; MuMu Build/V417IR) 8 | Host: ak-gs-localhost.hypergryph.com:38023 9 | Connection: Keep-Alive 10 | Accept-Encoding: gzip 11 | Content-Length: 13 12 | { 13 | "refresh": 0 14 | } 15 | 16 | 17 | { 18 | "assistFriendCharList": [], 19 | "assistNotFriendCharList": [ 20 | { 21 | "assistChar": { 22 | "charId": "char_102_texas", 23 | "crisisRecord": {}, 24 | "evolvePhase": 1, 25 | "favorPoint": 3943, 26 | "level": 52, 27 | "mainSkillLvl": 3, 28 | "potentialRank": 3, 29 | "skillIndex": 0, 30 | "skills": [ 31 | { 32 | "completeUpgradeTime": -1, 33 | "skillId": "skcom_charge_cost[3]", 34 | "specializeLevel": 0, 35 | "state": 0, 36 | "unlock": 1 37 | }, 38 | { 39 | "completeUpgradeTime": -1, 40 | "skillId": "skchr_texas_2", 41 | "specializeLevel": 0, 42 | "state": 0, 43 | "unlock": 1 44 | } 45 | ], 46 | "skinId": "char_102_texas@winter#1" 47 | }, 48 | "assistSlotIndex": 0, 49 | "avatarId": "0", 50 | "board": [ 51 | "URSUS", 52 | "KJERAG", 53 | "GLASGOW", 54 | "RHODES", 55 | "PENGUIN" 56 | ], 57 | "charCnt": 82, 58 | "friendNumLimit": 25, 59 | "furnCnt": 44, 60 | "infoShare": 0, 61 | "lastOnlineTime": 1588321474, 62 | "level": 31, 63 | "mainStageProgress": "main_05-01", 64 | "medalBoard": { 65 | "custom": null, 66 | "template": null, 67 | "type": "EMPTY" 68 | }, 69 | "nickName": "百合式达瑟", 70 | "nickNumber": "5419", 71 | "registerTs": 1556920413, 72 | "resume": "相关功能优化中,签名暂无法保存,请等待后续开放。(修改任务不受影响)", 73 | "secretary": "char_179_cgbird", 74 | "secretarySkinId": "char_179_cgbird@witch#1", 75 | "serverName": "泰拉", 76 | "team": { 77 | "1": 4, 78 | "11": 3, 79 | "12": 1, 80 | "13": 4, 81 | "15": 1, 82 | "19": 5, 83 | "2": 5, 84 | "3": 5, 85 | "4": 3, 86 | "5": 1, 87 | "6": 5, 88 | "8": 2, 89 | "9": 3 90 | }, 91 | "uid": "5096287" 92 | }, 93 | { 94 | "assistChar": { 95 | "charId": "char_415_flint", 96 | "crisisRecord": {}, 97 | "evolvePhase": 0, 98 | "favorPoint": 684, 99 | "level": 50, 100 | "mainSkillLvl": 1, 101 | "potentialRank": 0, 102 | "skillIndex": 0, 103 | "skills": [ 104 | { 105 | "completeUpgradeTime": -1, 106 | "skillId": "skchr_flint_1", 107 | "specializeLevel": 0, 108 | "state": 0, 109 | "unlock": 1 110 | }, 111 | { 112 | "completeUpgradeTime": -1, 113 | "skillId": "skchr_flint_2", 114 | "specializeLevel": 0, 115 | "state": 0, 116 | "unlock": 0 117 | } 118 | ], 119 | "skinId": "char_415_flint#1" 120 | }, 121 | "assistSlotIndex": 0, 122 | "avatarId": "0", 123 | "board": [ 124 | "GLASGOW", 125 | "URSUS", 126 | "KJERAG", 127 | "RHODES", 128 | "RHINE" 129 | ], 130 | "charCnt": 83, 131 | "friendNumLimit": 25, 132 | "furnCnt": 22, 133 | "infoShare": 0, 134 | "lastOnlineTime": 1600078708, 135 | "level": 31, 136 | "mainStageProgress": "sub_02-05", 137 | "medalBoard": { 138 | "custom": null, 139 | "template": null, 140 | "type": "EMPTY" 141 | }, 142 | "nickName": "Yc诮亢文淌", 143 | "nickNumber": "2122", 144 | "registerTs": 1557254804, 145 | "resume": "相关功能优化中,签名暂无法保存,请等待后续开放。(修改任务不受影响)", 146 | "secretary": "char_2014_nian", 147 | "secretarySkinId": "char_2014_nian#1", 148 | "serverName": "泰拉", 149 | "team": { 150 | "1": 4, 151 | "11": 2, 152 | "12": 1, 153 | "13": 2, 154 | "15": 1, 155 | "19": 5, 156 | "2": 5, 157 | "3": 5, 158 | "4": 2, 159 | "5": 1, 160 | "6": 5, 161 | "8": 1, 162 | "9": 1 163 | }, 164 | "uid": "50965505" 165 | }, 166 | { 167 | "assistChar": { 168 | "charId": "char_199_yak", 169 | "crisisRecord": {}, 170 | "evolvePhase": 1, 171 | "favorPoint": 4750, 172 | "level": 35, 173 | "mainSkillLvl": 4, 174 | "potentialRank": 5, 175 | "skillIndex": 0, 176 | "skills": [ 177 | { 178 | "completeUpgradeTime": -1, 179 | "skillId": "skchr_yak_1", 180 | "specializeLevel": 0, 181 | "state": 0, 182 | "unlock": 1 183 | }, 184 | { 185 | "completeUpgradeTime": -1, 186 | "skillId": "skchr_yak_2", 187 | "specializeLevel": 0, 188 | "state": 0, 189 | "unlock": 1 190 | } 191 | ], 192 | "skinId": "char_199_yak#1" 193 | }, 194 | "assistSlotIndex": 0, 195 | "avatarId": "0", 196 | "board": [ 197 | "RHINE", 198 | "RHODES", 199 | "KJERAG", 200 | "URSUS" 201 | ], 202 | "charCnt": 75, 203 | "friendNumLimit": 35, 204 | "furnCnt": 37, 205 | "infoShare": 1562942849, 206 | "lastOnlineTime": 1604298958, 207 | "level": 31, 208 | "mainStageProgress": "main_05-01", 209 | "medalBoard": { 210 | "custom": null, 211 | "template": null, 212 | "type": "EMPTY" 213 | }, 214 | "nickName": "ばか野郎", 215 | "nickNumber": "1318", 216 | "registerTs": 1558534031, 217 | "resume": "相关功能优化中,签名暂无法保存,请等待后续开放。(修改任务不受影响)", 218 | "secretary": "char_263_skadi", 219 | "secretarySkinId": "char_263_skadi#1", 220 | "serverName": "泰拉", 221 | "team": { 222 | "1": 4, 223 | "10": 1, 224 | "11": 1, 225 | "13": 4, 226 | "15": 1, 227 | "19": 5, 228 | "2": 5, 229 | "3": 5, 230 | "4": 2, 231 | "5": 1, 232 | "6": 3, 233 | "8": 2, 234 | "9": 1 235 | }, 236 | "uid": "50965620" 237 | }, 238 | { 239 | "assistChar": { 240 | "charId": "char_400_weedy", 241 | "crisisRecord": { 242 | "rune_season_2_1": -1 243 | }, 244 | "evolvePhase": 1, 245 | "favorPoint": 1945, 246 | "level": 66, 247 | "mainSkillLvl": 5, 248 | "potentialRank": 0, 249 | "skillIndex": 1, 250 | "skills": [ 251 | { 252 | "completeUpgradeTime": -1, 253 | "skillId": "skchr_weedy_1", 254 | "specializeLevel": 0, 255 | "state": 0, 256 | "unlock": 1 257 | }, 258 | { 259 | "completeUpgradeTime": -1, 260 | "skillId": "skchr_weedy_2", 261 | "specializeLevel": 0, 262 | "state": 0, 263 | "unlock": 1 264 | }, 265 | { 266 | "completeUpgradeTime": -1, 267 | "skillId": "skchr_weedy_3", 268 | "specializeLevel": 0, 269 | "state": 0, 270 | "unlock": 0 271 | } 272 | ], 273 | "skinId": "char_400_weedy#1" 274 | }, 275 | "assistSlotIndex": 1, 276 | "avatarId": "0", 277 | "board": [ 278 | "GLASGOW", 279 | "URSUS", 280 | "PENGUIN", 281 | "RHODES" 282 | ], 283 | "charCnt": 83, 284 | "friendNumLimit": 35, 285 | "furnCnt": 32, 286 | "infoShare": 1595813817, 287 | "lastOnlineTime": 1595929010, 288 | "level": 31, 289 | "mainStageProgress": "main_04-07", 290 | "medalBoard": { 291 | "custom": null, 292 | "template": null, 293 | "type": "EMPTY" 294 | }, 295 | "nickName": "再重名我打你哦", 296 | "nickNumber": "1358", 297 | "registerTs": 1584348868, 298 | "resume": "相关功能优化中,签名暂无法保存,请等待后续开放。(修改任务不受影响)", 299 | "secretary": "char_213_mostma", 300 | "secretarySkinId": "char_213_mostma@epoque#5", 301 | "serverName": "泰拉", 302 | "team": { 303 | "1": 4, 304 | "11": 2, 305 | "13": 3, 306 | "15": 1, 307 | "19": 5, 308 | "2": 5, 309 | "3": 5, 310 | "4": 2, 311 | "5": 2, 312 | "6": 5, 313 | "8": 2 314 | }, 315 | "uid": "509706330" 316 | }, 317 | { 318 | "assistChar": { 319 | "charId": "char_010_chen", 320 | "evolvePhase": 1, 321 | "favorPoint": 2979, 322 | "level": 50, 323 | "mainSkillLvl": 3, 324 | "potentialRank": 1, 325 | "skillIndex": 1, 326 | "skills": [ 327 | { 328 | "completeUpgradeTime": -1, 329 | "skillId": "skchr_chen_1", 330 | "specializeLevel": 0, 331 | "state": 0, 332 | "unlock": 1 333 | }, 334 | { 335 | "completeUpgradeTime": -1, 336 | "skillId": "skchr_chen_2", 337 | "specializeLevel": 0, 338 | "state": 0, 339 | "unlock": 1 340 | }, 341 | { 342 | "completeUpgradeTime": -1, 343 | "skillId": "skchr_chen_3", 344 | "specializeLevel": 0, 345 | "state": 0, 346 | "unlock": 0 347 | } 348 | ], 349 | "skinId": "char_010_chen#1" 350 | }, 351 | "assistSlotIndex": 1, 352 | "avatarId": "0", 353 | "board": [ 354 | "GLASGOW", 355 | "PENGUIN", 356 | "BLACKSTEEL", 357 | "KJERAG", 358 | "RHODES" 359 | ], 360 | "charCnt": 75, 361 | "friendNumLimit": 35, 362 | "furnCnt": 52, 363 | "infoShare": 1571549218, 364 | "lastOnlineTime": 1571462784, 365 | "level": 31, 366 | "mainStageProgress": "main_05-01", 367 | "nickName": "栾院天磊", 368 | "nickNumber": "3979", 369 | "registerTs": 1558925143, 370 | "resume": "相关功能优化中,签名暂无法保存,请等待后续开放。(修改任务不受影响)", 371 | "secretary": "char_172_svrash", 372 | "secretarySkinId": "char_172_svrash#1", 373 | "serverName": "泰拉", 374 | "team": { 375 | "1": 4, 376 | "11": 2, 377 | "12": 2, 378 | "13": 4, 379 | "19": 5, 380 | "2": 5, 381 | "3": 5, 382 | "4": 3, 383 | "5": 2, 384 | "6": 4, 385 | "8": 2, 386 | "9": 1 387 | }, 388 | "uid": "50977627" 389 | }, 390 | { 391 | "assistChar": { 392 | "charId": "char_208_melan", 393 | "crisisRecord": {}, 394 | "evolvePhase": 1, 395 | "favorPoint": 5305, 396 | "level": 55, 397 | "mainSkillLvl": 4, 398 | "potentialRank": 5, 399 | "skillIndex": 0, 400 | "skills": [ 401 | { 402 | "completeUpgradeTime": -1, 403 | "skillId": "skcom_atk_up[1]", 404 | "specializeLevel": 0, 405 | "state": 0, 406 | "unlock": 1 407 | } 408 | ], 409 | "skinId": "char_208_melan#1" 410 | }, 411 | "assistSlotIndex": 0, 412 | "avatarId": "0", 413 | "board": [ 414 | "KJERAG", 415 | "RHODES", 416 | "PENGUIN", 417 | "BLACKSTEEL", 418 | "URSUS" 419 | ], 420 | "charCnt": 92, 421 | "friendNumLimit": 25, 422 | "furnCnt": 32, 423 | "infoShare": 0, 424 | "lastOnlineTime": 1604852725, 425 | "level": 31, 426 | "mainStageProgress": "main_03-08", 427 | "medalBoard": { 428 | "custom": null, 429 | "template": null, 430 | "type": "EMPTY" 431 | }, 432 | "nickName": "强壮的如天", 433 | "nickNumber": "2918", 434 | "registerTs": 1556796510, 435 | "resume": "相关功能优化中,签名暂无法保存,请等待后续开放。(修改任务不受影响)", 436 | "secretary": "char_222_bpipe", 437 | "secretarySkinId": "char_222_bpipe#1", 438 | "serverName": "泰拉", 439 | "team": { 440 | "1": 4, 441 | "11": 3, 442 | "13": 2, 443 | "19": 5, 444 | "2": 5, 445 | "3": 5, 446 | "4": 3, 447 | "5": 1, 448 | "6": 3, 449 | "8": 2, 450 | "9": 1 451 | }, 452 | "uid": "50967226" 453 | } 454 | ], 455 | "friendAliasList": [], 456 | "playerDataDelta": { 457 | "deleted": {}, 458 | "modified": {} 459 | }, 460 | "refreshTimes": 10, 461 | "result": 0 462 | } 463 | 464 | POST https://ak-gs-localhost.hypergryph.com:8443/quest/battleStart HTTP/1.1 465 | uid: 50968260 466 | X-Unity-Version: 2017.4.39f1 467 | secret: pnKGte/A86oo6rhS7WqN6gFIYWFdK9bj 468 | Content-Type: application/json 469 | seqnum: 6 470 | User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; MuMu Build/V417IR) 471 | Host: ak-gs-localhost.hypergryph.com:38023 472 | Connection: Keep-Alive 473 | Accept-Encoding: gzip 474 | Content-Length: 738 475 | 476 | 477 | { 478 | "assistFriend": { 479 | "assistChar": { 480 | "charId": "char_102_texas", 481 | "crisisRecord": {}, 482 | "currentTmpl": null, 483 | "evolvePhase": 0, 484 | "favorPoint": 1184, 485 | "level": 50, 486 | "mainSkillLvl": 1, 487 | "potentialRank": 3, 488 | "skillIndex": 0, 489 | "skills": [ 490 | { 491 | "skillId": "skcom_charge_cost[3]", 492 | "specializeLevel": 0 493 | }, 494 | { 495 | "skillId": "skchr_texas_2", 496 | "specializeLevel": 0 497 | } 498 | ], 499 | "skinId": "char_102_texas@winter#1", 500 | "tmpl": null 501 | }, 502 | "assistSlotIndex": 0, 503 | "lastOnlineTime": 1588321474, 504 | "level": 31, 505 | "nickName": "百合式达瑟", 506 | "nickNumber": "5419", 507 | "recentVisited": 0, 508 | "serverName": "泰拉", 509 | "uid": "5096287" 510 | }, 511 | "isReplay": 0, 512 | "squad": { 513 | "name": "第一编队", 514 | "slots": [ 515 | { 516 | "charInstId": 1, 517 | "skillIndex": 0 518 | }, 519 | null, 520 | null, 521 | null, 522 | null, 523 | null, 524 | null, 525 | null, 526 | null, 527 | null, 528 | null, 529 | null 530 | ], 531 | "squadId": "0" 532 | }, 533 | "stageId": "main_00-01", 534 | "startTs": 1606501359, 535 | "usePracticeTicket": 0 536 | } -------------------------------------------------------------------------------- /capturedData/battleFinish.txt: -------------------------------------------------------------------------------- 1 | POST https://ak-gs-localhost.hypergryph.com:8443/quest/battleFinish HTTP/1.1 2 | uid: 50968260 3 | X-Unity-Version: 2017.4.39f1 4 | secret: pnKGte/A86oo6rhS7WqN6gFbW7/O7lh2 5 | Content-Type: application/json 6 | seqnum: 6 7 | User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; MuMu Build/V417IR) 8 | Host: ak-gs-localhost.hypergryph.com:56859 9 | Connection: Keep-Alive 10 | Accept-Encoding: gzip 11 | Content-Length: 3860 12 | 13 | { 14 | "battleData": { 15 | "completeTime": 41, 16 | "isCheat": "bGw4OGhsPjc0Ojc/OTQ4OGxpNGltPzc0NzhpaGhsbGk6PTlA", 17 | "stats": {} 18 | }, 19 | "data": "2BB54E6B7C92EBE325F9CFDDAA5388BBBB49F035DBB61B1DCC46602263E0D6F605D6693B34FD2EFBF69ED6DAB3DE246C3E15D4C7D95C3935C9401C0A01EA975B9E232B174B54BECB5948357E9B5EF66C55395F9E3E1C641C6E44094797F271C7A02BB689910AF92EE6C3E129D6D5AC775075216BA1A0EFC7C7F195BD44A0A1445B387123291DFF8F9D5CE3560F1E6099B423F5265236CF2DF9B10AAE7D6CE3657C33F574B246BEB2BD73D3DE8E3F52C2157301FD70DCDC613311AA470E0DB08E9B29335B9AF97B031AF49249CCAB2B26365B1F7A68BCD40315ED9A4F4C8FDED21B809947E22E79A3D9B8AAFCA63B40BE920BD318FF55EF30BA9066FAB8BE3312E6F32E65E105C911109FED7F344FDD62EB1DC47E4F222A2F41F390742F21C85B16619AFD298AE02BC434C2C578F01852B698BAD91A176F2B1ACE3103E26A102C7F170954F1206ACFE2BEED135F43C03D73E1A410E491139BB51FCDC9846E27D1BB6E5C1496733781AA750ADFAC566E8D26DB230F8C8AD1267CAAB7CB16924BA767CD0A281CC1E310C797A45608A35C740385236D141CE09E214502337C6C4168CD379ABD6113911BF7E9DE36CFFD15EB472E1493F17B6E1455A3226D26AD2F16B66178F73CA7A8579FCAFBE623C6A1824DBA8A85DD65C23C6DFFEB6BE278A52547D1F3A4AB8B64F8DDBB9EC5B947621E899337BBD6FB435896753728C7313381674A35D7F40874CC6603FA168B10B358B8922A340802EAA1BDCD521AD4D13A2E23E145F902B108CABF6ED5295951267AB2C3F030DA5B7B99CB6F04F129745F49D5CB66DEC5F620AEF295EF1954BE4BCEC3D16A800CC1DD0ECF37BFEF2DD4FCF4E04858B387D016656E0F9DFB841FAFD0B18C2907AEFE4633BECEBB7B31CE2D6776088E3E73C2F78AFAD7B685DE676D549BA867869B82834B680EDFA4F4E07B033AB986222DD844FC8EDA7A52A101D91D7D46F1A50B703FF50BE64E9FAC569BA7C934B7A7CFEB5B4EA5262EA11A2958C1BEC876D37D115AC309C2F9C1E615159E23D650E5F7CDD94DA28CF59D1EC8701EF0AA9435B27779517E084C8F9B36D53C9EC1D8282DB3977138074EB8A9326BEED558FC716F476C2844D1919A74BC4A1D5938D72783BBE37A50803F8810DF131B7CCE12005FF5B87098118899D1642620F9C952A2ED85E629B6CE574DF932BD90760F0110501B0B4603E3900A7E8221C82B0119F5142369639E46181E47BF4E6D7B2211E20BADD82ABA7D94C36ED2F48DDAC7B3BB46C7216361C61ED1B737D9782B3AF3864726F8EC6D72081B06D411DC0A78C9E14B28A778C3B237C2C85D1E410C5C974DC435644C4517645FCFFAE40A70B0F636EA00CF1FBFE4DBD6210B0C1A7BB43DB6833740A71353C30EEDE3804EDBBDC53529BF7A9842EF3BAA96A6CD1C71C5CD56FCF088E344E77997234E7BC5985918CF542F7959A469D2509BDC5CE5E6347C57155E536ACAE8EDDDC8152DA0048F7FD2BAF9075332931A064D97ACE0B308E1E896C56D4E4B3473AA470D5288343CD8B6F91B429C9D1845F4E39F3B57890643C520BB10F243054AF8A5FB3BD6CA89DDED7781960DE97A7432B7570C2E6928E9BBCF6550CA65DF06D0A7359F3745451C3E7D000FB91E9F504EC9964426A7300BBE5F7A131990EFB704DAA9A125F9055DC8211329FA2BB236AE9E29A9E781E415FBC4621FF9CDB25CDCE6140973183E0D32DCE379657AC62E9C4E39AF815DDD4C972C89B57B6A2BA7B05A3BF2542A9451217CA6C3F5CB5884D59304A9C0D87BA5B1B45BF720AFC234E06AE40C52AE896E2842A487B486673C44953C230DFFEB96AC3044CEF600F2C5AF47B5FAC02747012CEBEB16E6F9A2AC0C92050505D9D0509BE1C69CB0A12E15631FBBCDBD63CE762AC75B32ABE3A61B9BD1A901802F5A515D995DC5EA83852D15615C2CC8586DE360E1EE00CE3FEFB92A5D01FDBB2ED6DFB4EBBA58E743CE69E170B683FE4D58BB500C47214B1E38D965DE00BACA821F7F9DDAD86E1E350D975C8EC4B1AB05FC74883FDBD7B25F07BA40CD47CA0B7ACC5B1FC5975D24B2BDB42B3A135E2DBF4A94C9694A4311146CC8147402F2DE868DDF8621EB381F6CA9B92CEF290FDD12D3D09A44A2404A86C481D1AB3E1253BA06DD337E084B1A4FBD7DE9BB01F92E9795E3526EC142633F2E1D8D97E04DFF61BAD121947D82373B978CE2D9B637AED1E6213DD6ACE0799A136AE7717227C33F2E429263C14D39B2D7C36297297EADADADFD8C74F0D81C421696D8273338ECBB6A8EE4C55DF7696D339849C14F01C0707BC6C17F2A34A5C53512A741F18EA68B7573AC8C2A2A1FB793F7B0BAFF837A66492326B5EFA2C195A298ACD8956F2391F3C65C6E86DE6C48FD958F6DB12F097A9CE1011A8CC9BF8ADEC079296544C1A5EB98352D2C792E7ED05CAF41095D50F842173A01E622753AD517ED471B8C09A0EC4907C4F7E5CB13871ACF543643B1BB43750E257A4210D4BA79562973DB1E43FC520E717ED6BA9A84BFB0FBCFD02D4435635A132F6AB9A61295C7D6CD718671B1DBA01FCC1E299C0AFCF28C490D96F735E49590CA804C4E51F3B4A7C10FE14EB766492B27C69DDEBC489EC98933DC136D4207000265D837CC6811F14AC4E7" 20 | } 21 | 22 | POST https://ak-gs-localhost.hypergryph.com:8443/quest/saveBattleReplay HTTP/1.1 23 | uid: 50968260 24 | X-Unity-Version: 2017.4.39f1 25 | secret: pnKGte/A86oo6rhS7WqN6gFbW7/O7lh2 26 | Content-Type: application/json 27 | seqnum: 7 28 | User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; MuMu Build/V417IR) 29 | Host: ak-gs-localhost.hypergryph.com:56859 30 | Connection: Keep-Alive 31 | Accept-Encoding: gzip 32 | Content-Length: 1141 33 | { 34 | "battleId": "ee11ae70-3082-11eb-bf80-01baaeeb3629", 35 | "battleReplay": "UEsDBC0AAAAIAGF8e1HFG7gV//////////8NABQAZGVmYXVsdF9lbnRyeQEAEABjCQAAAAAAAH8CAAAAAAAAzZbfT9swEMf/F/PaFttJ3CZvG9oDGhOIoT0MoehoTOrVsYvtdKtQ//ed0zH6g4k8wMRbcrk7f77ni30PZArNAlRtzo1efZPOK2tIQQckqEb6gB9JQZigIhU8o5wMyA/bOgOaFA+kkQEqCBCf0ddU4KoLDasrjCWFyEdCZGM+IDU08lL6VgdSsAHxsJQbF8Ipp0PGhnx8xbIiyQpKR4ILkeffcSknG1BGmfrEegzN6JbpTN3JC6sM2jna50prWX0yslHSn0Qrw5Ua5f2uFV21XEp9WuHq57fh+AumO+5MZcxcUjqkDNdGPbXsvHbMS9Cq+vzMYmsMuW8BA66xqDNwp8aHGB8Fz5XpUkU7puIlNGoFR7GcoVl0MKbVuvPUGzY/n9oGkWo1LR2iXCc35PG7qeSvTkr3erbEzWCPwkgxwcfFDDzWF2u/sEGaoEBfgpljDQfkDpbWfYQQtLzYuDGKIcp/8F75cIKMpLgD7eV6sCuF70vBjijNrYZKHrF/a9l+3aAP2Tb7Ezr7S05flzw5JKelscpN3zl4egieYD+Y+p1zZ/vcjIvSz2zw4aW2n7k/jiXr2fHjN+t4Qfd18JyVUGtloIeOjWNvHfmb6UgPfl1OWVJOpbuVroeQjWPJ94Sw/y5ETA6E8KycAcx7qIhu72AzBDtsqrSEVa+diG69NbziVXCDSW3tu+ttazbIR2MhRBLbC4cIFVon4zTQGnXfdtcnZ+k4nSQilrMrwnMdSPD2tItOR6WcnIZuCumQfUzn7M/uKJxaFJWuY0G3GNLxKBeCZi8yZMk+w9Op9DwC20XgTwhYDzyGK9t8lTIukfCE4diC1tbIMxXnlbiB6/VvUEsBAjMALQAAAAgAYXx7UcUbuBX//////////w0AFAAAAAAAAAAAAAAAAAAAAGRlZmF1bHRfZW50cnkBABAAYwkAAAAAAAB/AgAAAAAAAFBLBQYAAAAAAQABAE8AAAC+AgAAAAA=" 36 | } -------------------------------------------------------------------------------- /capturedData/crisisBattle.txt: -------------------------------------------------------------------------------- 1 | POST https://ak-gs-localhost.hypergryph.com:8443/crisis/battleStart HTTP/1.1 2 | uid: 50968260 3 | X-Unity-Version: 2017.4.39f1 4 | secret: pnKGte/A86oo6rhS7WqN6gEeWKTfhAmX 5 | Content-Type: application/json 6 | seqnum: 5 7 | User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; MuMu Build/V417IR) 8 | Host: ak-gs-localhost.hypergryph.com:38023 9 | Connection: Keep-Alive 10 | Accept-Encoding: gzip 11 | Content-Length: 382 12 | // seed 可能用来验证编队,如果编队不对的话就会报错. 13 | // 所以要打crisis可能得用有干员的号。然后graduate 14 | { 15 | "assistFriend": null, 16 | "rune": [ 17 | "enemy_atk_1", 18 | "enemy_dbskar_1", 19 | "enemy_dmgswd_1", 20 | "enemy_dscout_1", 21 | "enemy_dlancer_1" 22 | ], 23 | "seed": "wGKWuZHG1606502344", 24 | "squad": { 25 | "name": "", 26 | "slots": [ 27 | { 28 | "charInstId": 1, 29 | "skillIndex": 0 30 | }, 31 | null, 32 | null, 33 | null, 34 | null, 35 | null, 36 | null, 37 | null, 38 | null, 39 | null, 40 | null, 41 | null 42 | ], 43 | "squadId": "0" 44 | }, 45 | "stageId": "level_rune_05-01", 46 | "stageType": "PERMANENT", 47 | "startTs": 1606502344 48 | } -------------------------------------------------------------------------------- /data/arkhack_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "character": { 3 | "char_285_medic2": { 4 | "rarity": 0, 5 | "obtainable": true, 6 | "skills": [], 7 | "skins": [ 8 | "char_285_medic2#1" 9 | ] 10 | }, 11 | "char_286_cast3": { 12 | "rarity": 0, 13 | "obtainable": true, 14 | "skills": [], 15 | "skins": [ 16 | "char_286_cast3#1", 17 | "char_286_cast3@summer#1" 18 | ] 19 | }, 20 | "char_376_therex": { 21 | "rarity": 0, 22 | "obtainable": true, 23 | "skills": [], 24 | "skins": [ 25 | "char_376_therex#1" 26 | ] 27 | }, 28 | "char_502_nblade": { 29 | "rarity": 1, 30 | "obtainable": true, 31 | "skills": [], 32 | "skins": [ 33 | "char_502_nblade#1" 34 | ] 35 | }, 36 | "char_500_noirc": { 37 | "rarity": 1, 38 | "obtainable": true, 39 | "skills": [], 40 | "skins": [ 41 | "char_500_noirc#1" 42 | ] 43 | }, 44 | "char_503_rang": { 45 | "rarity": 1, 46 | "obtainable": true, 47 | "skills": [], 48 | "skins": [ 49 | "char_503_rang#1" 50 | ] 51 | }, 52 | "char_501_durin": { 53 | "rarity": 1, 54 | "obtainable": true, 55 | "skills": [], 56 | "skins": [ 57 | "char_501_durin#1" 58 | ] 59 | }, 60 | "char_009_12fce": { 61 | "rarity": 1, 62 | "obtainable": true, 63 | "skills": [], 64 | "skins": [ 65 | "char_009_12fce#1" 66 | ] 67 | }, 68 | "char_123_fang": { 69 | "rarity": 2, 70 | "obtainable": true, 71 | "skills": [ 72 | "skcom_charge_cost[1]" 73 | ], 74 | "skins": [ 75 | "char_123_fang#1", 76 | "char_123_fang@winter#1" 77 | ] 78 | }, 79 | "char_240_wyvern": { 80 | "rarity": 2, 81 | "obtainable": true, 82 | "skills": [ 83 | "skchr_wyvern_1" 84 | ], 85 | "skins": [ 86 | "char_240_wyvern#1" 87 | ] 88 | }, 89 | "char_504_rguard": { 90 | "rarity": 2, 91 | "obtainable": false, 92 | "skills": [], 93 | "skins": [ 94 | "char_504_rguard#1" 95 | ] 96 | }, 97 | "char_192_falco": { 98 | "rarity": 2, 99 | "obtainable": true, 100 | "skills": [ 101 | "skcom_quickattack[1]" 102 | ], 103 | "skins": [ 104 | "char_192_falco#1" 105 | ] 106 | }, 107 | "char_208_melan": { 108 | "rarity": 2, 109 | "obtainable": true, 110 | "skills": [ 111 | "skcom_atk_up[1]" 112 | ], 113 | "skins": [ 114 | "char_208_melan#1", 115 | "char_208_melan@epoque#1" 116 | ] 117 | }, 118 | "char_281_popka": { 119 | "rarity": 2, 120 | "obtainable": true, 121 | "skills": [ 122 | "skcom_atk_up[1]" 123 | ], 124 | "skins": [ 125 | "char_281_popka#1" 126 | ] 127 | }, 128 | "char_209_ardign": { 129 | "rarity": 2, 130 | "obtainable": true, 131 | "skills": [ 132 | "skcom_heal_self[1]" 133 | ], 134 | "skins": [ 135 | "char_209_ardign#1", 136 | "char_209_ardign@snow#1" 137 | ] 138 | }, 139 | "char_122_beagle": { 140 | "rarity": 2, 141 | "obtainable": true, 142 | "skills": [ 143 | "skcom_def_up[1]" 144 | ], 145 | "skins": [ 146 | "char_122_beagle#1", 147 | "char_122_beagle@boc#1" 148 | ] 149 | }, 150 | "char_284_spot": { 151 | "rarity": 2, 152 | "obtainable": true, 153 | "skills": [ 154 | "skchr_spot_1" 155 | ], 156 | "skins": [ 157 | "char_284_spot#1" 158 | ] 159 | }, 160 | "char_124_kroos": { 161 | "rarity": 2, 162 | "obtainable": true, 163 | "skills": [ 164 | "skchr_kroos_1" 165 | ], 166 | "skins": [ 167 | "char_124_kroos#1", 168 | "char_124_kroos@witch#1" 169 | ] 170 | }, 171 | "char_211_adnach": { 172 | "rarity": 2, 173 | "obtainable": true, 174 | "skills": [ 175 | "skcom_atk_up[1]" 176 | ], 177 | "skins": [ 178 | "char_211_adnach#1" 179 | ] 180 | }, 181 | "char_507_rsnipe": { 182 | "rarity": 2, 183 | "obtainable": false, 184 | "skills": [], 185 | "skins": [ 186 | "char_507_rsnipe#1" 187 | ] 188 | }, 189 | "char_121_lava": { 190 | "rarity": 2, 191 | "obtainable": true, 192 | "skills": [ 193 | "skcom_magic_rage[1]" 194 | ], 195 | "skins": [ 196 | "char_121_lava#1" 197 | ] 198 | }, 199 | "char_120_hibisc": { 200 | "rarity": 2, 201 | "obtainable": true, 202 | "skills": [ 203 | "skcom_heal_up[1]" 204 | ], 205 | "skins": [ 206 | "char_120_hibisc#1", 207 | "char_120_hibisc@nian#1" 208 | ] 209 | }, 210 | "char_212_ansel": { 211 | "rarity": 2, 212 | "obtainable": true, 213 | "skills": [ 214 | "skcom_range_extend" 215 | ], 216 | "skins": [ 217 | "char_212_ansel#1", 218 | "char_212_ansel@summer#1" 219 | ] 220 | }, 221 | "char_506_rmedic": { 222 | "rarity": 2, 223 | "obtainable": false, 224 | "skills": [], 225 | "skins": [ 226 | "char_506_rmedic#1" 227 | ] 228 | }, 229 | "char_210_stward": { 230 | "rarity": 2, 231 | "obtainable": true, 232 | "skills": [ 233 | "skchr_stward_1" 234 | ], 235 | "skins": [ 236 | "char_210_stward#1" 237 | ] 238 | }, 239 | "char_505_rcast": { 240 | "rarity": 2, 241 | "obtainable": false, 242 | "skills": [], 243 | "skins": [ 244 | "char_505_rcast#1" 245 | ] 246 | }, 247 | "char_278_orchid": { 248 | "rarity": 2, 249 | "obtainable": true, 250 | "skills": [ 251 | "skcom_quickattack[1]" 252 | ], 253 | "skins": [ 254 | "char_278_orchid#1" 255 | ] 256 | }, 257 | "char_141_nights": { 258 | "rarity": 3, 259 | "obtainable": true, 260 | "skills": [ 261 | "skcom_atk_up[2]", 262 | "skchr_nights_2" 263 | ], 264 | "skins": [ 265 | "char_141_nights#1", 266 | "char_141_nights#2" 267 | ] 268 | }, 269 | "char_109_fmout": { 270 | "rarity": 3, 271 | "obtainable": true, 272 | "skills": [ 273 | "skcom_magic_rage[2]", 274 | "skchr_fmout_2" 275 | ], 276 | "skins": [ 277 | "char_109_fmout#1", 278 | "char_109_fmout#2", 279 | "char_109_fmout@epoque#2" 280 | ] 281 | }, 282 | "char_253_greyy": { 283 | "rarity": 3, 284 | "obtainable": true, 285 | "skills": [ 286 | "skcom_magic_rage[2]", 287 | "skchr_greyy_2" 288 | ], 289 | "skins": [ 290 | "char_253_greyy#1", 291 | "char_253_greyy#2", 292 | "char_253_greyy@epoque#8" 293 | ] 294 | }, 295 | "char_328_cammou": { 296 | "rarity": 3, 297 | "obtainable": true, 298 | "skills": [ 299 | "skcom_atk_up[2]", 300 | "skchr_cammou_2" 301 | ], 302 | "skins": [ 303 | "char_328_cammou#1", 304 | "char_328_cammou#2" 305 | ] 306 | }, 307 | "char_235_jesica": { 308 | "rarity": 3, 309 | "obtainable": true, 310 | "skills": [ 311 | "skchr_jesica_1", 312 | "skchr_jesica_2" 313 | ], 314 | "skins": [ 315 | "char_235_jesica#1", 316 | "char_235_jesica#2", 317 | "char_235_jesica@nian#2", 318 | "char_235_jesica@wild#2", 319 | "char_235_jesica@sweep#1" 320 | ] 321 | }, 322 | "char_126_shotst": { 323 | "rarity": 3, 324 | "obtainable": true, 325 | "skills": [ 326 | "skchr_shotst_1", 327 | "skchr_shotst_2" 328 | ], 329 | "skins": [ 330 | "char_126_shotst#1", 331 | "char_126_shotst#2" 332 | ] 333 | }, 334 | "char_190_clour": { 335 | "rarity": 3, 336 | "obtainable": true, 337 | "skills": [ 338 | "skcom_atk_up[2]", 339 | "skchr_clour_2" 340 | ], 341 | "skins": [ 342 | "char_190_clour#1", 343 | "char_190_clour#2" 344 | ] 345 | }, 346 | "char_133_mm": { 347 | "rarity": 3, 348 | "obtainable": true, 349 | "skills": [ 350 | "skchr_mm_1", 351 | "skchr_mm_2" 352 | ], 353 | "skins": [ 354 | "char_133_mm#1", 355 | "char_133_mm#2" 356 | ] 357 | }, 358 | "char_118_yuki": { 359 | "rarity": 3, 360 | "obtainable": true, 361 | "skills": [ 362 | "skchr_yuki_1", 363 | "skchr_yuki_2" 364 | ], 365 | "skins": [ 366 | "char_118_yuki#1", 367 | "char_118_yuki#2" 368 | ] 369 | }, 370 | "char_440_pinecn": { 371 | "rarity": 3, 372 | "obtainable": true, 373 | "skills": [ 374 | "skchr_pinecn_1", 375 | "skchr_pinecn_2" 376 | ], 377 | "skins": [ 378 | "char_440_pinecn#1", 379 | "char_440_pinecn#2" 380 | ] 381 | }, 382 | "char_302_glaze": { 383 | "rarity": 3, 384 | "obtainable": true, 385 | "skills": [ 386 | "skchr_glaze_1", 387 | "skchr_glaze_2" 388 | ], 389 | "skins": [ 390 | "char_302_glaze#1", 391 | "char_302_glaze#2" 392 | ] 393 | }, 394 | "char_366_acdrop": { 395 | "rarity": 3, 396 | "obtainable": true, 397 | "skills": [ 398 | "skchr_acdrop_1", 399 | "skchr_acdrop_2" 400 | ], 401 | "skins": [ 402 | "char_366_acdrop#1", 403 | "char_366_acdrop#2" 404 | ] 405 | }, 406 | "char_198_blackd": { 407 | "rarity": 3, 408 | "obtainable": true, 409 | "skills": [ 410 | "skcom_charge_cost[2]", 411 | "skchr_blackd_2" 412 | ], 413 | "skins": [ 414 | "char_198_blackd#1", 415 | "char_198_blackd#2", 416 | "char_198_blackd@winter#1" 417 | ] 418 | }, 419 | "char_149_scave": { 420 | "rarity": 3, 421 | "obtainable": true, 422 | "skills": [ 423 | "skcom_charge_cost[2]", 424 | "skchr_scave_2" 425 | ], 426 | "skins": [ 427 | "char_149_scave#1", 428 | "char_149_scave#2" 429 | ] 430 | }, 431 | "char_290_vigna": { 432 | "rarity": 3, 433 | "obtainable": true, 434 | "skills": [ 435 | "skchr_vigna_1", 436 | "skchr_vigna_2" 437 | ], 438 | "skins": [ 439 | "char_290_vigna#1", 440 | "char_290_vigna#2", 441 | "char_290_vigna@summer#1" 442 | ] 443 | }, 444 | "char_151_myrtle": { 445 | "rarity": 3, 446 | "obtainable": true, 447 | "skills": [ 448 | "skcom_assist_cost[2]", 449 | "skchr_myrtle_2" 450 | ], 451 | "skins": [ 452 | "char_151_myrtle#1", 453 | "char_151_myrtle#2" 454 | ] 455 | }, 456 | "char_452_bstalk": { 457 | "rarity": 3, 458 | "obtainable": true, 459 | "skills": [ 460 | "skchr_bstalk_1", 461 | "skchr_bstalk_2" 462 | ], 463 | "skins": [ 464 | "char_452_bstalk#1", 465 | "char_452_bstalk#2" 466 | ] 467 | }, 468 | "char_130_doberm": { 469 | "rarity": 3, 470 | "obtainable": true, 471 | "skills": [ 472 | "skchr_doberm_1", 473 | "skchr_doberm_2" 474 | ], 475 | "skins": [ 476 | "char_130_doberm#1", 477 | "char_130_doberm#2", 478 | "char_130_doberm@epoque#7" 479 | ] 480 | }, 481 | "char_289_gyuki": { 482 | "rarity": 3, 483 | "obtainable": true, 484 | "skills": [ 485 | "skcom_heal_self[2]", 486 | "skchr_gyuki_2" 487 | ], 488 | "skins": [ 489 | "char_289_gyuki#1", 490 | "char_289_gyuki#2" 491 | ] 492 | }, 493 | "char_159_peacok": { 494 | "rarity": 3, 495 | "obtainable": true, 496 | "skills": [ 497 | "skchr_peacok_1", 498 | "skchr_peacok_2" 499 | ], 500 | "skins": [ 501 | "char_159_peacok#1", 502 | "char_159_peacok#2" 503 | ] 504 | }, 505 | "char_193_frostl": { 506 | "rarity": 3, 507 | "obtainable": true, 508 | "skills": [ 509 | "skchr_frostl_1", 510 | "skchr_frostl_2" 511 | ], 512 | "skins": [ 513 | "char_193_frostl#1", 514 | "char_193_frostl#2" 515 | ] 516 | }, 517 | "char_127_estell": { 518 | "rarity": 3, 519 | "obtainable": true, 520 | "skills": [ 521 | "skcom_atk_up[2]", 522 | "skchr_estell_2" 523 | ], 524 | "skins": [ 525 | "char_127_estell#1", 526 | "char_127_estell#2" 527 | ] 528 | }, 529 | "char_185_frncat": { 530 | "rarity": 3, 531 | "obtainable": true, 532 | "skills": [ 533 | "skchr_frncat_1", 534 | "skchr_frncat_2" 535 | ], 536 | "skins": [ 537 | "char_185_frncat#1", 538 | "char_185_frncat#2" 539 | ] 540 | }, 541 | "char_301_cutter": { 542 | "rarity": 3, 543 | "obtainable": true, 544 | "skills": [ 545 | "skchr_cutter_1", 546 | "skchr_cutter_2" 547 | ], 548 | "skins": [ 549 | "char_301_cutter#1", 550 | "char_301_cutter#2" 551 | ] 552 | }, 553 | "char_337_utage": { 554 | "rarity": 3, 555 | "obtainable": true, 556 | "skills": [ 557 | "skchr_utage_1", 558 | "skchr_utage_2" 559 | ], 560 | "skins": [ 561 | "char_337_utage#1", 562 | "char_337_utage#2", 563 | "char_337_utage@summer#4" 564 | ] 565 | }, 566 | "char_271_spikes": { 567 | "rarity": 3, 568 | "obtainable": true, 569 | "skills": [ 570 | "skchr_spikes_1", 571 | "skchr_spikes_2" 572 | ], 573 | "skins": [ 574 | "char_271_spikes#1", 575 | "char_271_spikes#2", 576 | "char_271_spikes@winter#2" 577 | ] 578 | }, 579 | "char_237_gravel": { 580 | "rarity": 3, 581 | "obtainable": true, 582 | "skills": [ 583 | "skchr_gravel_1", 584 | "skchr_gravel_2" 585 | ], 586 | "skins": [ 587 | "char_237_gravel#1", 588 | "char_237_gravel#2", 589 | "char_237_gravel@winter#2" 590 | ] 591 | }, 592 | "char_272_strong": { 593 | "rarity": 3, 594 | "obtainable": true, 595 | "skills": [ 596 | "skchr_strong_1", 597 | "skchr_strong_2" 598 | ], 599 | "skins": [ 600 | "char_272_strong#1", 601 | "char_272_strong#2" 602 | ] 603 | }, 604 | "char_236_rope": { 605 | "rarity": 3, 606 | "obtainable": true, 607 | "skills": [ 608 | "skchr_rope_1", 609 | "skchr_rope_2" 610 | ], 611 | "skins": [ 612 | "char_236_rope#1", 613 | "char_236_rope#2", 614 | "char_236_rope@summer#2", 615 | "char_236_rope@witch#1" 616 | ] 617 | }, 618 | "char_117_myrrh": { 619 | "rarity": 3, 620 | "obtainable": true, 621 | "skills": [ 622 | "skchr_myrrh_1", 623 | "skchr_myrrh_2" 624 | ], 625 | "skins": [ 626 | "char_117_myrrh#1", 627 | "char_117_myrrh#2", 628 | "char_117_myrrh@wild#1" 629 | ] 630 | }, 631 | "char_187_ccheal": { 632 | "rarity": 3, 633 | "obtainable": true, 634 | "skills": [ 635 | "skchr_ccheal_1", 636 | "skchr_ccheal_2" 637 | ], 638 | "skins": [ 639 | "char_187_ccheal#1", 640 | "char_187_ccheal#2", 641 | "char_187_ccheal@epoque#2" 642 | ] 643 | }, 644 | "char_298_susuro": { 645 | "rarity": 3, 646 | "obtainable": true, 647 | "skills": [ 648 | "skcom_heal_up[2]", 649 | "skchr_susuro_2" 650 | ], 651 | "skins": [ 652 | "char_298_susuro#1", 653 | "char_298_susuro#2" 654 | ] 655 | }, 656 | "char_181_flower": { 657 | "rarity": 3, 658 | "obtainable": true, 659 | "skills": [ 660 | "skcom_heal_up[2]", 661 | "skchr_flower_2" 662 | ], 663 | "skins": [ 664 | "char_181_flower#1", 665 | "char_181_flower#2", 666 | "char_181_flower@daily#1" 667 | ] 668 | }, 669 | "char_385_finlpp": { 670 | "rarity": 3, 671 | "obtainable": true, 672 | "skills": [ 673 | "skchr_finlpp_1", 674 | "skchr_finlpp_2" 675 | ], 676 | "skins": [ 677 | "char_385_finlpp#1", 678 | "char_385_finlpp#2" 679 | ] 680 | }, 681 | "char_199_yak": { 682 | "rarity": 3, 683 | "obtainable": true, 684 | "skills": [ 685 | "skchr_yak_1", 686 | "skchr_yak_2" 687 | ], 688 | "skins": [ 689 | "char_199_yak#1", 690 | "char_199_yak#2", 691 | "char_199_yak@summer#1" 692 | ] 693 | }, 694 | "char_150_snakek": { 695 | "rarity": 3, 696 | "obtainable": true, 697 | "skills": [ 698 | "skcom_def_up[2]", 699 | "skchr_snakek_2" 700 | ], 701 | "skins": [ 702 | "char_150_snakek#1", 703 | "char_150_snakek#2", 704 | "char_150_snakek@wild#1" 705 | ] 706 | }, 707 | "char_381_bubble": { 708 | "rarity": 3, 709 | "obtainable": true, 710 | "skills": [ 711 | "skcom_def_up[2]", 712 | "skchr_bubble_2" 713 | ], 714 | "skins": [ 715 | "char_381_bubble#1", 716 | "char_381_bubble#2" 717 | ] 718 | }, 719 | "char_196_sunbr": { 720 | "rarity": 3, 721 | "obtainable": true, 722 | "skills": [ 723 | "skchr_sunbr_1", 724 | "skchr_sunbr_2" 725 | ], 726 | "skins": [ 727 | "char_196_sunbr#1", 728 | "char_196_sunbr#2", 729 | "char_196_sunbr@summer#1" 730 | ] 731 | }, 732 | "char_260_durnar": { 733 | "rarity": 3, 734 | "obtainable": true, 735 | "skills": [ 736 | "skcom_atk_up[2]", 737 | "skchr_durnar_2" 738 | ], 739 | "skins": [ 740 | "char_260_durnar#1", 741 | "char_260_durnar#2" 742 | ] 743 | }, 744 | "char_110_deepcl": { 745 | "rarity": 3, 746 | "obtainable": true, 747 | "skills": [ 748 | "skchr_deepcl_1", 749 | "skchr_deepcl_2" 750 | ], 751 | "skins": [ 752 | "char_110_deepcl#1", 753 | "char_110_deepcl#2" 754 | ] 755 | }, 756 | "char_183_skgoat": { 757 | "rarity": 3, 758 | "obtainable": true, 759 | "skills": [ 760 | "skcom_atk_up[2]", 761 | "skchr_skgoat_2" 762 | ], 763 | "skins": [ 764 | "char_183_skgoat#1", 765 | "char_183_skgoat#2" 766 | ] 767 | }, 768 | "char_258_podego": { 769 | "rarity": 3, 770 | "obtainable": true, 771 | "skills": [ 772 | "skchr_podego_1", 773 | "skchr_podego_2" 774 | ], 775 | "skins": [ 776 | "char_258_podego#1", 777 | "char_258_podego#2" 778 | ] 779 | }, 780 | "char_355_ethan": { 781 | "rarity": 3, 782 | "obtainable": true, 783 | "skills": [ 784 | "skchr_ethan_1", 785 | "skchr_ethan_2" 786 | ], 787 | "skins": [ 788 | "char_355_ethan#1", 789 | "char_355_ethan#2", 790 | "char_355_ethan@epoque#7" 791 | ] 792 | }, 793 | "char_277_sqrrel": { 794 | "rarity": 3, 795 | "obtainable": true, 796 | "skills": [ 797 | "skchr_sqrrel_1", 798 | "skchr_sqrrel_2" 799 | ], 800 | "skins": [ 801 | "char_277_sqrrel#1", 802 | "char_277_sqrrel#2", 803 | "char_277_sqrrel@ghost#1" 804 | ] 805 | }, 806 | "char_128_plosis": { 807 | "rarity": 4, 808 | "obtainable": true, 809 | "skills": [ 810 | "skcom_heal_up[3]", 811 | "skchr_plosis_2" 812 | ], 813 | "skins": [ 814 | "char_128_plosis#1", 815 | "char_128_plosis#2", 816 | "char_128_plosis@epoque#3" 817 | ] 818 | }, 819 | "char_275_breeze": { 820 | "rarity": 4, 821 | "obtainable": true, 822 | "skills": [ 823 | "skchr_breeze_1", 824 | "skchr_breeze_2" 825 | ], 826 | "skins": [ 827 | "char_275_breeze#1", 828 | "char_275_breeze#2" 829 | ] 830 | }, 831 | "char_115_headbr": { 832 | "rarity": 4, 833 | "obtainable": true, 834 | "skills": [ 835 | "skcom_charge_cost[3]", 836 | "skchr_headbr_2" 837 | ], 838 | "skins": [ 839 | "char_115_headbr#1", 840 | "char_115_headbr#2", 841 | "char_115_headbr@marthe#2" 842 | ] 843 | }, 844 | "char_102_texas": { 845 | "rarity": 4, 846 | "obtainable": true, 847 | "skills": [ 848 | "skcom_charge_cost[3]", 849 | "skchr_texas_2" 850 | ], 851 | "skins": [ 852 | "char_102_texas#1", 853 | "char_102_texas#2", 854 | "char_102_texas@epoque#7", 855 | "char_102_texas@winter#1" 856 | ] 857 | }, 858 | "char_349_chiave": { 859 | "rarity": 4, 860 | "obtainable": true, 861 | "skills": [ 862 | "skcom_charge_cost[3]", 863 | "skchr_chiave_2" 864 | ], 865 | "skins": [ 866 | "char_349_chiave#1", 867 | "char_349_chiave#2" 868 | ] 869 | }, 870 | "char_261_sddrag": { 871 | "rarity": 4, 872 | "obtainable": true, 873 | "skills": [ 874 | "skcom_quickattack[3]", 875 | "skchr_sddrag_2" 876 | ], 877 | "skins": [ 878 | "char_261_sddrag#1", 879 | "char_261_sddrag#2" 880 | ] 881 | }, 882 | "char_401_elysm": { 883 | "rarity": 4, 884 | "obtainable": true, 885 | "skills": [ 886 | "skcom_assist_cost[3]", 887 | "skchr_elysm_2" 888 | ], 889 | "skins": [ 890 | "char_401_elysm#1", 891 | "char_401_elysm#2", 892 | "char_401_elysm@snow#2" 893 | ] 894 | }, 895 | "char_308_swire": { 896 | "rarity": 4, 897 | "obtainable": true, 898 | "skills": [ 899 | "skchr_swire_1", 900 | "skchr_swire_2" 901 | ], 902 | "skins": [ 903 | "char_308_swire#1", 904 | "char_308_swire#2", 905 | "char_308_swire@nian#2" 906 | ] 907 | }, 908 | "char_265_sophia": { 909 | "rarity": 4, 910 | "obtainable": true, 911 | "skills": [ 912 | "skchr_sophia_1", 913 | "skchr_sophia_2" 914 | ], 915 | "skins": [ 916 | "char_265_sophia#1", 917 | "char_265_sophia#2" 918 | ] 919 | }, 920 | "char_106_franka": { 921 | "rarity": 4, 922 | "obtainable": true, 923 | "skills": [ 924 | "skcom_quickattack[3]", 925 | "skchr_franka_2" 926 | ], 927 | "skins": [ 928 | "char_106_franka#1", 929 | "char_106_franka#2" 930 | ] 931 | }, 932 | "char_131_flameb": { 933 | "rarity": 4, 934 | "obtainable": true, 935 | "skills": [ 936 | "skchr_flameb_1", 937 | "skchr_flameb_2" 938 | ], 939 | "skins": [ 940 | "char_131_flameb#1", 941 | "char_131_flameb#2" 942 | ] 943 | }, 944 | "char_508_aguard": { 945 | "rarity": 4, 946 | "obtainable": false, 947 | "skills": [ 948 | "skchr_aguard_1" 949 | ], 950 | "skins": [ 951 | "char_508_aguard#1" 952 | ] 953 | }, 954 | "char_155_tiger": { 955 | "rarity": 4, 956 | "obtainable": true, 957 | "skills": [ 958 | "skchr_tiger_1", 959 | "skchr_tiger_2" 960 | ], 961 | "skins": [ 962 | "char_155_tiger#1", 963 | "char_155_tiger#2" 964 | ] 965 | }, 966 | "char_415_flint": { 967 | "rarity": 4, 968 | "obtainable": true, 969 | "skills": [ 970 | "skchr_flint_1", 971 | "skchr_flint_2" 972 | ], 973 | "skins": [ 974 | "char_415_flint#1", 975 | "char_415_flint#2" 976 | ] 977 | }, 978 | "char_140_whitew": { 979 | "rarity": 4, 980 | "obtainable": true, 981 | "skills": [ 982 | "skchr_whitew_1", 983 | "skchr_whitew_2" 984 | ], 985 | "skins": [ 986 | "char_140_whitew#1", 987 | "char_140_whitew#2", 988 | "char_140_whitew@boc#1" 989 | ] 990 | }, 991 | "char_294_ayer": { 992 | "rarity": 4, 993 | "obtainable": true, 994 | "skills": [ 995 | "skchr_ayer_1", 996 | "skchr_ayer_2" 997 | ], 998 | "skins": [ 999 | "char_294_ayer#1", 1000 | "char_294_ayer#2" 1001 | ] 1002 | }, 1003 | "char_252_bibeak": { 1004 | "rarity": 4, 1005 | "obtainable": true, 1006 | "skills": [ 1007 | "skchr_bibeak_1", 1008 | "skchr_bibeak_2" 1009 | ], 1010 | "skins": [ 1011 | "char_252_bibeak#1", 1012 | "char_252_bibeak#2", 1013 | "char_252_bibeak@winter#2" 1014 | ] 1015 | }, 1016 | "char_143_ghost": { 1017 | "rarity": 4, 1018 | "obtainable": true, 1019 | "skills": [ 1020 | "skcom_atk_up[3]", 1021 | "skchr_ghost_2" 1022 | ], 1023 | "skins": [ 1024 | "char_143_ghost#1", 1025 | "char_143_ghost#2", 1026 | "char_143_ghost@winter#1" 1027 | ] 1028 | }, 1029 | "char_356_broca": { 1030 | "rarity": 4, 1031 | "obtainable": true, 1032 | "skills": [ 1033 | "skchr_broca_1", 1034 | "skchr_broca_2" 1035 | ], 1036 | "skins": [ 1037 | "char_356_broca#1", 1038 | "char_356_broca#2" 1039 | ] 1040 | }, 1041 | "char_274_astesi": { 1042 | "rarity": 4, 1043 | "obtainable": true, 1044 | "skills": [ 1045 | "skchr_astesi_1", 1046 | "skchr_astesi_2" 1047 | ], 1048 | "skins": [ 1049 | "char_274_astesi#1", 1050 | "char_274_astesi#2", 1051 | "char_274_astesi@epoque#5" 1052 | ] 1053 | }, 1054 | "char_333_sidero": { 1055 | "rarity": 4, 1056 | "obtainable": true, 1057 | "skills": [ 1058 | "skcom_heal_self[3]", 1059 | "skchr_sidero_2" 1060 | ], 1061 | "skins": [ 1062 | "char_333_sidero#1", 1063 | "char_333_sidero#2" 1064 | ] 1065 | }, 1066 | "char_129_bluep": { 1067 | "rarity": 4, 1068 | "obtainable": true, 1069 | "skills": [ 1070 | "skchr_bluep_1", 1071 | "skchr_bluep_2" 1072 | ], 1073 | "skins": [ 1074 | "char_129_bluep#1", 1075 | "char_129_bluep#2" 1076 | ] 1077 | }, 1078 | "char_204_platnm": { 1079 | "rarity": 4, 1080 | "obtainable": true, 1081 | "skills": [ 1082 | "skcom_atk_up[3]", 1083 | "skchr_platnm_2" 1084 | ], 1085 | "skins": [ 1086 | "char_204_platnm#1", 1087 | "char_204_platnm#2", 1088 | "char_204_platnm@summer#3" 1089 | ] 1090 | }, 1091 | "char_367_swllow": { 1092 | "rarity": 4, 1093 | "obtainable": true, 1094 | "skills": [ 1095 | "skchr_swllow_1", 1096 | "skchr_swllow_2" 1097 | ], 1098 | "skins": [ 1099 | "char_367_swllow#1", 1100 | "char_367_swllow#2", 1101 | "char_367_swllow@boc#1" 1102 | ] 1103 | }, 1104 | "char_511_asnipe": { 1105 | "rarity": 4, 1106 | "obtainable": false, 1107 | "skills": [ 1108 | "skchr_asnipe_1" 1109 | ], 1110 | "skins": [ 1111 | "char_511_asnipe#1" 1112 | ] 1113 | }, 1114 | "char_365_aprl": { 1115 | "rarity": 4, 1116 | "obtainable": true, 1117 | "skills": [ 1118 | "skchr_aprl_1", 1119 | "skchr_aprl_2" 1120 | ], 1121 | "skins": [ 1122 | "char_365_aprl#1", 1123 | "char_365_aprl#2", 1124 | "char_365_aprl@wild#3" 1125 | ] 1126 | }, 1127 | "char_219_meteo": { 1128 | "rarity": 4, 1129 | "obtainable": true, 1130 | "skills": [ 1131 | "skchr_meteo_1", 1132 | "skchr_meteo_2" 1133 | ], 1134 | "skins": [ 1135 | "char_219_meteo#1", 1136 | "char_219_meteo#2", 1137 | "char_219_meteo@sweep#1" 1138 | ] 1139 | }, 1140 | "char_379_sesa": { 1141 | "rarity": 4, 1142 | "obtainable": true, 1143 | "skills": [ 1144 | "skcom_atk_up[3]", 1145 | "skchr_sesa_2" 1146 | ], 1147 | "skins": [ 1148 | "char_379_sesa#1", 1149 | "char_379_sesa#2" 1150 | ] 1151 | }, 1152 | "char_279_excu": { 1153 | "rarity": 4, 1154 | "obtainable": true, 1155 | "skills": [ 1156 | "skchr_excu_1", 1157 | "skchr_excu_2" 1158 | ], 1159 | "skins": [ 1160 | "char_279_excu#1", 1161 | "char_279_excu#2", 1162 | "char_279_excu@boc#1" 1163 | ] 1164 | }, 1165 | "char_346_aosta": { 1166 | "rarity": 4, 1167 | "obtainable": true, 1168 | "skills": [ 1169 | "skcom_quickattack[3]", 1170 | "skchr_aosta_2" 1171 | ], 1172 | "skins": [ 1173 | "char_346_aosta#1", 1174 | "char_346_aosta#2" 1175 | ] 1176 | }, 1177 | "char_002_amiya": { 1178 | "rarity": 4, 1179 | "obtainable": true, 1180 | "skills": [ 1181 | "skcom_magic_rage[3]", 1182 | "skchr_amiya_2", 1183 | "skchr_amiya_3" 1184 | ], 1185 | "skins": [ 1186 | "char_002_amiya#1", 1187 | "char_002_amiya#1+", 1188 | "char_002_amiya#2", 1189 | "char_002_amiya@winter#1", 1190 | "char_002_amiya@epoque#4", 1191 | "char_1001_amiya2#2" 1192 | ] 1193 | }, 1194 | "char_405_absin": { 1195 | "rarity": 4, 1196 | "obtainable": true, 1197 | "skills": [ 1198 | "skchr_absin_1", 1199 | "skchr_absin_2" 1200 | ], 1201 | "skins": [ 1202 | "char_405_absin#1", 1203 | "char_405_absin#2" 1204 | ] 1205 | }, 1206 | "char_411_tomimi": { 1207 | "rarity": 4, 1208 | "obtainable": true, 1209 | "skills": [ 1210 | "skchr_tomimi_1", 1211 | "skchr_tomimi_2" 1212 | ], 1213 | "skins": [ 1214 | "char_411_tomimi#1", 1215 | "char_411_tomimi#2" 1216 | ] 1217 | }, 1218 | "char_166_skfire": { 1219 | "rarity": 4, 1220 | "obtainable": true, 1221 | "skills": [ 1222 | "skcom_atk_up[3]", 1223 | "skchr_skfire_2" 1224 | ], 1225 | "skins": [ 1226 | "char_166_skfire#1", 1227 | "char_166_skfire#2", 1228 | "char_166_skfire@summer#1" 1229 | ] 1230 | }, 1231 | "char_509_acast": { 1232 | "rarity": 4, 1233 | "obtainable": false, 1234 | "skills": [ 1235 | "skchr_acast_1" 1236 | ], 1237 | "skins": [ 1238 | "char_509_acast#1" 1239 | ] 1240 | }, 1241 | "char_306_leizi": { 1242 | "rarity": 4, 1243 | "obtainable": true, 1244 | "skills": [ 1245 | "skcom_atk_up[3]", 1246 | "skchr_leizi_2" 1247 | ], 1248 | "skins": [ 1249 | "char_306_leizi#1", 1250 | "char_306_leizi#2" 1251 | ] 1252 | }, 1253 | "char_344_beewax": { 1254 | "rarity": 4, 1255 | "obtainable": true, 1256 | "skills": [ 1257 | "skchr_beewax_1", 1258 | "skchr_beewax_2" 1259 | ], 1260 | "skins": [ 1261 | "char_344_beewax#1", 1262 | "char_344_beewax#2" 1263 | ] 1264 | }, 1265 | "char_373_lionhd": { 1266 | "rarity": 4, 1267 | "obtainable": true, 1268 | "skills": [ 1269 | "skcom_atk_up[3]", 1270 | "skchr_lionhd_2" 1271 | ], 1272 | "skins": [ 1273 | "char_373_lionhd#1", 1274 | "char_373_lionhd#2", 1275 | "char_373_lionhd@wild#3" 1276 | ] 1277 | }, 1278 | "char_388_mint": { 1279 | "rarity": 4, 1280 | "obtainable": true, 1281 | "skills": [ 1282 | "skchr_mint_1", 1283 | "skchr_mint_2" 1284 | ], 1285 | "skins": [ 1286 | "char_388_mint#1", 1287 | "char_388_mint#2" 1288 | ] 1289 | }, 1290 | "char_338_iris": { 1291 | "rarity": 4, 1292 | "obtainable": true, 1293 | "skills": [ 1294 | "skchr_iris_1", 1295 | "skchr_iris_2" 1296 | ], 1297 | "skins": [ 1298 | "char_338_iris#1", 1299 | "char_338_iris#2" 1300 | ] 1301 | }, 1302 | "char_1011_lava2": { 1303 | "rarity": 4, 1304 | "obtainable": true, 1305 | "skills": [ 1306 | "skchr_lava2_1", 1307 | "skchr_lava2_2" 1308 | ], 1309 | "skins": [ 1310 | "char_1011_lava2#1", 1311 | "char_1011_lava2#2" 1312 | ] 1313 | }, 1314 | "char_242_otter": { 1315 | "rarity": 4, 1316 | "obtainable": true, 1317 | "skills": [ 1318 | "skchr_otter_1", 1319 | "skchr_otter_2" 1320 | ], 1321 | "skins": [ 1322 | "char_242_otter#1", 1323 | "char_242_otter#2", 1324 | "char_242_otter@ghost#1" 1325 | ] 1326 | }, 1327 | "char_336_folivo": { 1328 | "rarity": 4, 1329 | "obtainable": true, 1330 | "skills": [ 1331 | "skchr_folivo_1", 1332 | "skchr_folivo_2" 1333 | ], 1334 | "skins": [ 1335 | "char_336_folivo#1", 1336 | "char_336_folivo#2" 1337 | ] 1338 | }, 1339 | "char_108_silent": { 1340 | "rarity": 4, 1341 | "obtainable": true, 1342 | "skills": [ 1343 | "skcom_heal_up[3]", 1344 | "skchr_silent_2" 1345 | ], 1346 | "skins": [ 1347 | "char_108_silent#1", 1348 | "char_108_silent#2", 1349 | "char_108_silent@winter#2", 1350 | "char_108_silent@sweep#1" 1351 | ] 1352 | }, 1353 | "char_171_bldsk": { 1354 | "rarity": 4, 1355 | "obtainable": true, 1356 | "skills": [ 1357 | "skchr_bldsk_1", 1358 | "skchr_bldsk_2" 1359 | ], 1360 | "skins": [ 1361 | "char_171_bldsk#1", 1362 | "char_171_bldsk#2", 1363 | "char_171_bldsk@witch#1" 1364 | ] 1365 | }, 1366 | "char_345_folnic": { 1367 | "rarity": 4, 1368 | "obtainable": true, 1369 | "skills": [ 1370 | "skchr_folnic_1", 1371 | "skchr_folnic_2" 1372 | ], 1373 | "skins": [ 1374 | "char_345_folnic#1", 1375 | "char_345_folnic#2" 1376 | ] 1377 | }, 1378 | "char_510_amedic": { 1379 | "rarity": 4, 1380 | "obtainable": false, 1381 | "skills": [ 1382 | "skchr_amedic_1" 1383 | ], 1384 | "skins": [ 1385 | "char_510_amedic#1" 1386 | ] 1387 | }, 1388 | "char_348_ceylon": { 1389 | "rarity": 4, 1390 | "obtainable": true, 1391 | "skills": [ 1392 | "skchr_ceylon_1", 1393 | "skchr_ceylon_2" 1394 | ], 1395 | "skins": [ 1396 | "char_348_ceylon#1", 1397 | "char_348_ceylon#2" 1398 | ] 1399 | }, 1400 | "char_436_whispr": { 1401 | "rarity": 4, 1402 | "obtainable": true, 1403 | "skills": [ 1404 | "skchr_whispr_1", 1405 | "skchr_whispr_2" 1406 | ], 1407 | "skins": [ 1408 | "char_436_whispr#1", 1409 | "char_436_whispr#2", 1410 | "char_436_whispr@nian#4" 1411 | ] 1412 | }, 1413 | "char_402_tuye": { 1414 | "rarity": 4, 1415 | "obtainable": true, 1416 | "skills": [ 1417 | "skchr_tuye_1", 1418 | "skchr_tuye_2" 1419 | ], 1420 | "skins": [ 1421 | "char_402_tuye#1", 1422 | "char_402_tuye#2" 1423 | ] 1424 | }, 1425 | "char_148_nearl": { 1426 | "rarity": 4, 1427 | "obtainable": true, 1428 | "skills": [ 1429 | "skchr_nearl_1", 1430 | "skchr_nearl_2" 1431 | ], 1432 | "skins": [ 1433 | "char_148_nearl#1", 1434 | "char_148_nearl#2", 1435 | "char_148_nearl@summer#2" 1436 | ] 1437 | }, 1438 | "char_226_hmau": { 1439 | "rarity": 4, 1440 | "obtainable": true, 1441 | "skills": [ 1442 | "skchr_hmau_1", 1443 | "skchr_hmau_2" 1444 | ], 1445 | "skins": [ 1446 | "char_226_hmau#1", 1447 | "char_226_hmau#2", 1448 | "char_226_hmau@nian#4" 1449 | ] 1450 | }, 1451 | "char_144_red": { 1452 | "rarity": 4, 1453 | "obtainable": true, 1454 | "skills": [ 1455 | "skchr_red_1", 1456 | "skchr_red_2" 1457 | ], 1458 | "skins": [ 1459 | "char_144_red#1", 1460 | "char_144_red#2" 1461 | ] 1462 | }, 1463 | "char_243_waaifu": { 1464 | "rarity": 4, 1465 | "obtainable": true, 1466 | "skills": [ 1467 | "skchr_waaifu_1", 1468 | "skchr_waaifu_2" 1469 | ], 1470 | "skins": [ 1471 | "char_243_waaifu#1", 1472 | "char_243_waaifu#2" 1473 | ] 1474 | }, 1475 | "char_214_kafka": { 1476 | "rarity": 4, 1477 | "obtainable": true, 1478 | "skills": [ 1479 | "skchr_kafka_1", 1480 | "skchr_kafka_2" 1481 | ], 1482 | "skins": [ 1483 | "char_214_kafka#1", 1484 | "char_214_kafka#2" 1485 | ] 1486 | }, 1487 | "char_455_nothin": { 1488 | "rarity": 4, 1489 | "obtainable": true, 1490 | "skills": [ 1491 | "skchr_nothin_1", 1492 | "skchr_nothin_2" 1493 | ], 1494 | "skins": [ 1495 | "char_455_nothin#1", 1496 | "char_455_nothin#2" 1497 | ] 1498 | }, 1499 | "char_107_liskam": { 1500 | "rarity": 4, 1501 | "obtainable": true, 1502 | "skills": [ 1503 | "skchr_liskam_1", 1504 | "skchr_liskam_2" 1505 | ], 1506 | "skins": [ 1507 | "char_107_liskam#1", 1508 | "char_107_liskam#2", 1509 | "char_107_liskam@nian#2" 1510 | ] 1511 | }, 1512 | "char_201_moeshd": { 1513 | "rarity": 4, 1514 | "obtainable": true, 1515 | "skills": [ 1516 | "skchr_moeshd_1", 1517 | "skchr_moeshd_2" 1518 | ], 1519 | "skins": [ 1520 | "char_201_moeshd#1", 1521 | "char_201_moeshd#2", 1522 | "char_201_moeshd@summer#4", 1523 | "char_201_moeshd@kfc#1" 1524 | ] 1525 | }, 1526 | "char_325_bison": { 1527 | "rarity": 4, 1528 | "obtainable": true, 1529 | "skills": [ 1530 | "skcom_def_up[3]", 1531 | "skchr_bison_2" 1532 | ], 1533 | "skins": [ 1534 | "char_325_bison#1", 1535 | "char_325_bison#2" 1536 | ] 1537 | }, 1538 | "char_163_hpsts": { 1539 | "rarity": 4, 1540 | "obtainable": true, 1541 | "skills": [ 1542 | "skchr_hpsts_1", 1543 | "skchr_hpsts_2" 1544 | ], 1545 | "skins": [ 1546 | "char_163_hpsts#1", 1547 | "char_163_hpsts#2" 1548 | ] 1549 | }, 1550 | "char_378_asbest": { 1551 | "rarity": 4, 1552 | "obtainable": true, 1553 | "skills": [ 1554 | "skchr_asbest_1", 1555 | "skchr_asbest_2" 1556 | ], 1557 | "skins": [ 1558 | "char_378_asbest#1", 1559 | "char_378_asbest#2" 1560 | ] 1561 | }, 1562 | "char_145_prove": { 1563 | "rarity": 4, 1564 | "obtainable": true, 1565 | "skills": [ 1566 | "skchr_prove_1", 1567 | "skchr_prove_2" 1568 | ], 1569 | "skins": [ 1570 | "char_145_prove#1", 1571 | "char_145_prove#2", 1572 | "char_145_prove@summer#3" 1573 | ] 1574 | }, 1575 | "char_158_milu": { 1576 | "rarity": 4, 1577 | "obtainable": true, 1578 | "skills": [ 1579 | "skchr_milu_1", 1580 | "skchr_milu_2" 1581 | ], 1582 | "skins": [ 1583 | "char_158_milu#1", 1584 | "char_158_milu#2", 1585 | "char_158_milu@snow#2", 1586 | "char_158_milu@wild#2" 1587 | ] 1588 | }, 1589 | "char_218_cuttle": { 1590 | "rarity": 4, 1591 | "obtainable": true, 1592 | "skills": [ 1593 | "skcom_atk_up[3]", 1594 | "skchr_cuttle_2" 1595 | ], 1596 | "skins": [ 1597 | "char_218_cuttle#1", 1598 | "char_218_cuttle#2" 1599 | ] 1600 | }, 1601 | "char_173_slchan": { 1602 | "rarity": 4, 1603 | "obtainable": true, 1604 | "skills": [ 1605 | "skchr_slchan_1", 1606 | "skchr_slchan_2" 1607 | ], 1608 | "skins": [ 1609 | "char_173_slchan#1", 1610 | "char_173_slchan#2", 1611 | "char_173_slchan@wild#1", 1612 | "char_173_slchan@wwf#1" 1613 | ] 1614 | }, 1615 | "char_383_snsant": { 1616 | "rarity": 4, 1617 | "obtainable": true, 1618 | "skills": [ 1619 | "skchr_snsant_1", 1620 | "skchr_snsant_2" 1621 | ], 1622 | "skins": [ 1623 | "char_383_snsant#1", 1624 | "char_383_snsant#2" 1625 | ] 1626 | }, 1627 | "char_174_slbell": { 1628 | "rarity": 4, 1629 | "obtainable": true, 1630 | "skills": [ 1631 | "skchr_slbell_1", 1632 | "skchr_slbell_2" 1633 | ], 1634 | "skins": [ 1635 | "char_174_slbell#1", 1636 | "char_174_slbell#2", 1637 | "char_174_slbell@snow#1" 1638 | ] 1639 | }, 1640 | "char_254_vodfox": { 1641 | "rarity": 4, 1642 | "obtainable": true, 1643 | "skills": [ 1644 | "skchr_vodfox_1", 1645 | "skchr_vodfox_2" 1646 | ], 1647 | "skins": [ 1648 | "char_254_vodfox#1", 1649 | "char_254_vodfox#2" 1650 | ] 1651 | }, 1652 | "char_195_glassb": { 1653 | "rarity": 4, 1654 | "obtainable": true, 1655 | "skills": [ 1656 | "skchr_glassb_1", 1657 | "skchr_glassb_2" 1658 | ], 1659 | "skins": [ 1660 | "char_195_glassb#1", 1661 | "char_195_glassb#2", 1662 | "char_195_glassb@kitchen#1" 1663 | ] 1664 | }, 1665 | "char_326_glacus": { 1666 | "rarity": 4, 1667 | "obtainable": true, 1668 | "skills": [ 1669 | "skchr_glacus_1", 1670 | "skchr_glacus_2" 1671 | ], 1672 | "skins": [ 1673 | "char_326_glacus#1", 1674 | "char_326_glacus#2", 1675 | "char_326_glacus@ghost#1" 1676 | ] 1677 | }, 1678 | "char_101_sora": { 1679 | "rarity": 4, 1680 | "obtainable": true, 1681 | "skills": [ 1682 | "skchr_sora_1", 1683 | "skchr_sora_2" 1684 | ], 1685 | "skins": [ 1686 | "char_101_sora#1", 1687 | "char_101_sora#2", 1688 | "char_101_sora@summer#1" 1689 | ] 1690 | }, 1691 | "char_343_tknogi": { 1692 | "rarity": 4, 1693 | "obtainable": true, 1694 | "skills": [ 1695 | "skchr_tknogi_1", 1696 | "skchr_tknogi_2" 1697 | ], 1698 | "skins": [ 1699 | "char_343_tknogi#1", 1700 | "char_343_tknogi#2" 1701 | ] 1702 | }, 1703 | "char_215_mantic": { 1704 | "rarity": 4, 1705 | "obtainable": true, 1706 | "skills": [ 1707 | "skchr_mantic_1", 1708 | "skchr_mantic_2" 1709 | ], 1710 | "skins": [ 1711 | "char_215_mantic#1", 1712 | "char_215_mantic#2", 1713 | "char_215_mantic@epoque#4" 1714 | ] 1715 | }, 1716 | "char_241_panda": { 1717 | "rarity": 4, 1718 | "obtainable": true, 1719 | "skills": [ 1720 | "skchr_panda_1", 1721 | "skchr_panda_2" 1722 | ], 1723 | "skins": [ 1724 | "char_241_panda#1", 1725 | "char_241_panda#2", 1726 | "char_241_panda@marthe#1" 1727 | ] 1728 | }, 1729 | "char_451_robin": { 1730 | "rarity": 4, 1731 | "obtainable": true, 1732 | "skills": [ 1733 | "skchr_robin_1", 1734 | "skchr_robin_2" 1735 | ], 1736 | "skins": [ 1737 | "char_451_robin#1", 1738 | "char_451_robin#2" 1739 | ] 1740 | }, 1741 | "char_103_angel": { 1742 | "rarity": 5, 1743 | "obtainable": true, 1744 | "skills": [ 1745 | "skchr_angel_1", 1746 | "skchr_angel_2", 1747 | "skchr_angel_3" 1748 | ], 1749 | "skins": [ 1750 | "char_103_angel#1", 1751 | "char_103_angel#2", 1752 | "char_103_angel@wild#1", 1753 | "char_103_angel@kfc#1" 1754 | ] 1755 | }, 1756 | "char_332_archet": { 1757 | "rarity": 5, 1758 | "obtainable": true, 1759 | "skills": [ 1760 | "skchr_archet_1", 1761 | "skchr_archet_2", 1762 | "skchr_archet_3" 1763 | ], 1764 | "skins": [ 1765 | "char_332_archet#1", 1766 | "char_332_archet#2" 1767 | ] 1768 | }, 1769 | "char_340_shwaz": { 1770 | "rarity": 5, 1771 | "obtainable": true, 1772 | "skills": [ 1773 | "skchr_shwaz_1", 1774 | "skchr_shwaz_2", 1775 | "skchr_shwaz_3" 1776 | ], 1777 | "skins": [ 1778 | "char_340_shwaz#1", 1779 | "char_340_shwaz#2", 1780 | "char_340_shwaz@snow#1" 1781 | ] 1782 | }, 1783 | "char_113_cqbw": { 1784 | "rarity": 5, 1785 | "obtainable": true, 1786 | "skills": [ 1787 | "skchr_cqbw_1", 1788 | "skchr_cqbw_2", 1789 | "skchr_cqbw_3" 1790 | ], 1791 | "skins": [ 1792 | "char_113_cqbw#1", 1793 | "char_113_cqbw#2", 1794 | "char_113_cqbw@epoque#7" 1795 | ] 1796 | }, 1797 | "char_197_poca": { 1798 | "rarity": 5, 1799 | "obtainable": true, 1800 | "skills": [ 1801 | "skcom_atk_up[3]", 1802 | "skchr_poca_2", 1803 | "skchr_poca_3" 1804 | ], 1805 | "skins": [ 1806 | "char_197_poca#1", 1807 | "char_197_poca#2" 1808 | ] 1809 | }, 1810 | "char_391_rosmon": { 1811 | "rarity": 5, 1812 | "obtainable": true, 1813 | "skills": [ 1814 | "skchr_rosmon_1", 1815 | "skchr_rosmon_2", 1816 | "skchr_rosmon_3" 1817 | ], 1818 | "skins": [ 1819 | "char_391_rosmon#1", 1820 | "char_391_rosmon#2" 1821 | ] 1822 | }, 1823 | "char_112_siege": { 1824 | "rarity": 5, 1825 | "obtainable": true, 1826 | "skills": [ 1827 | "skcom_charge_cost[3]", 1828 | "skchr_siege_2", 1829 | "skchr_siege_3" 1830 | ], 1831 | "skins": [ 1832 | "char_112_siege#1", 1833 | "char_112_siege#2", 1834 | "char_112_siege@wild#2" 1835 | ] 1836 | }, 1837 | "char_222_bpipe": { 1838 | "rarity": 5, 1839 | "obtainable": true, 1840 | "skills": [ 1841 | "skcom_quickattack[3]", 1842 | "skchr_bpipe_2", 1843 | "skchr_bpipe_3" 1844 | ], 1845 | "skins": [ 1846 | "char_222_bpipe#1", 1847 | "char_222_bpipe#2", 1848 | "char_222_bpipe@race#1" 1849 | ] 1850 | }, 1851 | "char_362_saga": { 1852 | "rarity": 5, 1853 | "obtainable": true, 1854 | "skills": [ 1855 | "skcom_charge_cost[3]", 1856 | "skchr_saga_2", 1857 | "skchr_saga_3" 1858 | ], 1859 | "skins": [ 1860 | "char_362_saga#1", 1861 | "char_362_saga#2" 1862 | ] 1863 | }, 1864 | "char_134_ifrit": { 1865 | "rarity": 5, 1866 | "obtainable": true, 1867 | "skills": [ 1868 | "skchr_ifrit_1", 1869 | "skchr_ifrit_2", 1870 | "skchr_ifrit_3" 1871 | ], 1872 | "skins": [ 1873 | "char_134_ifrit#1", 1874 | "char_134_ifrit#2", 1875 | "char_134_ifrit@summer#1", 1876 | "char_134_ifrit@kfc#1" 1877 | ] 1878 | }, 1879 | "char_213_mostma": { 1880 | "rarity": 5, 1881 | "obtainable": true, 1882 | "skills": [ 1883 | "skcom_atk_up[3]", 1884 | "skchr_mostma_2", 1885 | "skchr_mostma_3" 1886 | ], 1887 | "skins": [ 1888 | "char_213_mostma#1", 1889 | "char_213_mostma#2", 1890 | "char_213_mostma@epoque#5" 1891 | ] 1892 | }, 1893 | "char_180_amgoat": { 1894 | "rarity": 5, 1895 | "obtainable": true, 1896 | "skills": [ 1897 | "skchr_amgoat_1", 1898 | "skchr_amgoat_2", 1899 | "skchr_amgoat_3" 1900 | ], 1901 | "skins": [ 1902 | "char_180_amgoat#1", 1903 | "char_180_amgoat#2" 1904 | ] 1905 | }, 1906 | "char_2013_cerber": { 1907 | "rarity": 5, 1908 | "obtainable": true, 1909 | "skills": [ 1910 | "skchr_cerber_1", 1911 | "skchr_cerber_2", 1912 | "skchr_cerber_3" 1913 | ], 1914 | "skins": [ 1915 | "char_2013_cerber#1", 1916 | "char_2013_cerber#2", 1917 | "char_2013_cerber@summer#4" 1918 | ] 1919 | }, 1920 | "char_2015_dusk": { 1921 | "rarity": 5, 1922 | "obtainable": true, 1923 | "skills": [ 1924 | "skchr_dusk_1", 1925 | "skchr_dusk_2", 1926 | "skchr_dusk_3" 1927 | ], 1928 | "skins": [ 1929 | "char_2015_dusk#1", 1930 | "char_2015_dusk#2" 1931 | ] 1932 | }, 1933 | "char_291_aglina": { 1934 | "rarity": 5, 1935 | "obtainable": true, 1936 | "skills": [ 1937 | "skchr_aglina_1", 1938 | "skchr_aglina_2", 1939 | "skchr_aglina_3" 1940 | ], 1941 | "skins": [ 1942 | "char_291_aglina#1", 1943 | "char_291_aglina#2", 1944 | "char_291_aglina@boc#1" 1945 | ] 1946 | }, 1947 | "char_358_lisa": { 1948 | "rarity": 5, 1949 | "obtainable": true, 1950 | "skills": [ 1951 | "skchr_lisa_1", 1952 | "skchr_lisa_2", 1953 | "skchr_lisa_3" 1954 | ], 1955 | "skins": [ 1956 | "char_358_lisa#1", 1957 | "char_358_lisa#2", 1958 | "char_358_lisa@wild#3" 1959 | ] 1960 | }, 1961 | "char_248_mgllan": { 1962 | "rarity": 5, 1963 | "obtainable": true, 1964 | "skills": [ 1965 | "skchr_mgllan_1", 1966 | "skchr_mgllan_2", 1967 | "skchr_mgllan_3" 1968 | ], 1969 | "skins": [ 1970 | "char_248_mgllan#1", 1971 | "char_248_mgllan#2", 1972 | "char_248_mgllan@kitchen#1" 1973 | ] 1974 | }, 1975 | "char_250_phatom": { 1976 | "rarity": 5, 1977 | "obtainable": true, 1978 | "skills": [ 1979 | "skchr_phatom_1", 1980 | "skchr_phatom_2", 1981 | "skchr_phatom_3" 1982 | ], 1983 | "skins": [ 1984 | "char_250_phatom#1", 1985 | "char_250_phatom#2", 1986 | "char_250_phatom@ghost#1" 1987 | ] 1988 | }, 1989 | "char_400_weedy": { 1990 | "rarity": 5, 1991 | "obtainable": true, 1992 | "skills": [ 1993 | "skchr_weedy_1", 1994 | "skchr_weedy_2", 1995 | "skchr_weedy_3" 1996 | ], 1997 | "skins": [ 1998 | "char_400_weedy#1", 1999 | "char_400_weedy#2", 2000 | "char_400_weedy@snow#2" 2001 | ] 2002 | }, 2003 | "char_225_haak": { 2004 | "rarity": 5, 2005 | "obtainable": true, 2006 | "skills": [ 2007 | "skchr_haak_1", 2008 | "skchr_haak_2", 2009 | "skchr_haak_3" 2010 | ], 2011 | "skins": [ 2012 | "char_225_haak#1", 2013 | "char_225_haak#2", 2014 | "char_225_haak@nian#4" 2015 | ] 2016 | }, 2017 | "char_147_shining": { 2018 | "rarity": 5, 2019 | "obtainable": true, 2020 | "skills": [ 2021 | "skchr_shining_1", 2022 | "skchr_shining_2", 2023 | "skchr_shining_3" 2024 | ], 2025 | "skins": [ 2026 | "char_147_shining#1", 2027 | "char_147_shining#2", 2028 | "char_147_shining@summer#1" 2029 | ] 2030 | }, 2031 | "char_179_cgbird": { 2032 | "rarity": 5, 2033 | "obtainable": true, 2034 | "skills": [ 2035 | "skcom_heal_up[3]", 2036 | "skchr_cgbird_2", 2037 | "skchr_cgbird_3" 2038 | ], 2039 | "skins": [ 2040 | "char_179_cgbird#1", 2041 | "char_179_cgbird#2", 2042 | "char_179_cgbird@witch#1" 2043 | ] 2044 | }, 2045 | "char_136_hsguma": { 2046 | "rarity": 5, 2047 | "obtainable": true, 2048 | "skills": [ 2049 | "skchr_hsguma_1", 2050 | "skchr_hsguma_2", 2051 | "skchr_hsguma_3" 2052 | ], 2053 | "skins": [ 2054 | "char_136_hsguma#1", 2055 | "char_136_hsguma#2", 2056 | "char_136_hsguma@nian#3" 2057 | ] 2058 | }, 2059 | "char_202_demkni": { 2060 | "rarity": 5, 2061 | "obtainable": true, 2062 | "skills": [ 2063 | "skchr_demkni_1", 2064 | "skchr_demkni_2", 2065 | "skchr_demkni_3" 2066 | ], 2067 | "skins": [ 2068 | "char_202_demkni#1", 2069 | "char_202_demkni#2", 2070 | "char_202_demkni@test#1", 2071 | "char_202_demkni@boc#1" 2072 | ] 2073 | }, 2074 | "char_423_blemsh": { 2075 | "rarity": 5, 2076 | "obtainable": true, 2077 | "skills": [ 2078 | "skchr_blemsh_1", 2079 | "skchr_blemsh_2", 2080 | "skchr_blemsh_3" 2081 | ], 2082 | "skins": [ 2083 | "char_423_blemsh#1", 2084 | "char_423_blemsh#2" 2085 | ] 2086 | }, 2087 | "char_2014_nian": { 2088 | "rarity": 5, 2089 | "obtainable": true, 2090 | "skills": [ 2091 | "skchr_nian_1", 2092 | "skchr_nian_2", 2093 | "skchr_nian_3" 2094 | ], 2095 | "skins": [ 2096 | "char_2014_nian#1", 2097 | "char_2014_nian#2", 2098 | "char_2014_nian@nian#4" 2099 | ] 2100 | }, 2101 | "char_311_mudrok": { 2102 | "rarity": 5, 2103 | "obtainable": true, 2104 | "skills": [ 2105 | "skcom_def_up[3]", 2106 | "skchr_mudrok_2", 2107 | "skchr_mudrok_3" 2108 | ], 2109 | "skins": [ 2110 | "char_311_mudrok#1", 2111 | "char_311_mudrok#2" 2112 | ] 2113 | }, 2114 | "char_416_zumama": { 2115 | "rarity": 5, 2116 | "obtainable": true, 2117 | "skills": [ 2118 | "skchr_zumama_1", 2119 | "skchr_zumama_2", 2120 | "skchr_zumama_3" 2121 | ], 2122 | "skins": [ 2123 | "char_416_zumama#1", 2124 | "char_416_zumama#2" 2125 | ] 2126 | }, 2127 | "char_264_f12yin": { 2128 | "rarity": 5, 2129 | "obtainable": true, 2130 | "skills": [ 2131 | "skchr_f12yin_1", 2132 | "skchr_f12yin_2", 2133 | "skchr_f12yin_3" 2134 | ], 2135 | "skins": [ 2136 | "char_264_f12yin#1", 2137 | "char_264_f12yin#2" 2138 | ] 2139 | }, 2140 | "char_172_svrash": { 2141 | "rarity": 5, 2142 | "obtainable": true, 2143 | "skills": [ 2144 | "skchr_svrash_1", 2145 | "skchr_svrash_2", 2146 | "skchr_svrash_3" 2147 | ], 2148 | "skins": [ 2149 | "char_172_svrash#1", 2150 | "char_172_svrash#2", 2151 | "char_172_svrash@summer#4", 2152 | "char_172_svrash@snow#1" 2153 | ] 2154 | }, 2155 | "char_293_thorns": { 2156 | "rarity": 5, 2157 | "obtainable": true, 2158 | "skills": [ 2159 | "skcom_atk_up[3]", 2160 | "skchr_thorns_2", 2161 | "skchr_thorns_3" 2162 | ], 2163 | "skins": [ 2164 | "char_293_thorns#1", 2165 | "char_293_thorns#2" 2166 | ] 2167 | }, 2168 | "char_010_chen": { 2169 | "rarity": 5, 2170 | "obtainable": true, 2171 | "skills": [ 2172 | "skchr_chen_1", 2173 | "skchr_chen_2", 2174 | "skchr_chen_3" 2175 | ], 2176 | "skins": [ 2177 | "char_010_chen#1", 2178 | "char_010_chen#2", 2179 | "char_010_chen@nian#2" 2180 | ] 2181 | }, 2182 | "char_017_huang": { 2183 | "rarity": 5, 2184 | "obtainable": true, 2185 | "skills": [ 2186 | "skchr_huang_1", 2187 | "skchr_huang_2", 2188 | "skchr_huang_3" 2189 | ], 2190 | "skins": [ 2191 | "char_017_huang#1", 2192 | "char_017_huang#2" 2193 | ] 2194 | }, 2195 | "char_350_surtr": { 2196 | "rarity": 5, 2197 | "obtainable": true, 2198 | "skills": [ 2199 | "skchr_surtr_1", 2200 | "skchr_surtr_2", 2201 | "skchr_surtr_3" 2202 | ], 2203 | "skins": [ 2204 | "char_350_surtr#1", 2205 | "char_350_surtr#2" 2206 | ] 2207 | }, 2208 | "char_188_helage": { 2209 | "rarity": 5, 2210 | "obtainable": true, 2211 | "skills": [ 2212 | "skchr_helage_1", 2213 | "skchr_helage_2", 2214 | "skchr_helage_3" 2215 | ], 2216 | "skins": [ 2217 | "char_188_helage#1", 2218 | "char_188_helage#2" 2219 | ] 2220 | }, 2221 | "token_10000_silent_healrb": { 2222 | "rarity": 4, 2223 | "obtainable": true, 2224 | "skills": [ 2225 | "skcom_withdraw", 2226 | "skcom_withdraw" 2227 | ], 2228 | "skins": [ 2229 | "token_10000_silent_healrb#1", 2230 | "token_10000_silent_healrb_winter#1", 2231 | "token_10000_silent_healrb_sweep#1" 2232 | ] 2233 | }, 2234 | "token_10001_deepcl_tentac": { 2235 | "rarity": 3, 2236 | "obtainable": true, 2237 | "skills": [ 2238 | null, 2239 | null 2240 | ], 2241 | "skins": [ 2242 | "token_10001_deepcl_tentac#1" 2243 | ] 2244 | }, 2245 | "token_10003_cgbird_bird": { 2246 | "rarity": 5, 2247 | "obtainable": true, 2248 | "skills": [ 2249 | null, 2250 | null, 2251 | null 2252 | ], 2253 | "skins": [ 2254 | "token_10003_cgbird_bird#1", 2255 | "token_10003_cgbird_bird_witch#1" 2256 | ] 2257 | }, 2258 | "token_10004_otter_motter": { 2259 | "rarity": 4, 2260 | "obtainable": true, 2261 | "skills": [ 2262 | "sktok_motter_1", 2263 | "sktok_motter_2" 2264 | ], 2265 | "skins": [ 2266 | "token_10004_otter_motter#1", 2267 | "token_10004_otter_motter_ghost#1" 2268 | ] 2269 | }, 2270 | "token_10005_mgllan_drone1": { 2271 | "rarity": 5, 2272 | "obtainable": true, 2273 | "skills": [ 2274 | "sktok_mgllan_drone1", 2275 | "sktok_mgllan_drone1", 2276 | "sktok_mgllan_drone1" 2277 | ], 2278 | "skins": [ 2279 | "token_10005_mgllan_drone1#1", 2280 | "token_10005_mgllan_drone1_kitchen#1" 2281 | ] 2282 | }, 2283 | "token_10005_mgllan_drone2": { 2284 | "rarity": 5, 2285 | "obtainable": true, 2286 | "skills": [ 2287 | "sktok_mgllan_drone2", 2288 | "sktok_mgllan_drone2", 2289 | "sktok_mgllan_drone2" 2290 | ], 2291 | "skins": [ 2292 | "token_10005_mgllan_drone2#1", 2293 | "token_10005_mgllan_drone2_kitchen#1" 2294 | ] 2295 | }, 2296 | "token_10005_mgllan_drone3": { 2297 | "rarity": 5, 2298 | "obtainable": true, 2299 | "skills": [ 2300 | "sktok_mgllan_drone3", 2301 | "sktok_mgllan_drone3", 2302 | "sktok_mgllan_drone3" 2303 | ], 2304 | "skins": [ 2305 | "token_10005_mgllan_drone3#1", 2306 | "token_10005_mgllan_drone3_kitchen#1" 2307 | ] 2308 | }, 2309 | "token_10006_vodfox_doll": { 2310 | "rarity": 4, 2311 | "obtainable": true, 2312 | "skills": [ 2313 | null, 2314 | "sktok_vodfox_token" 2315 | ], 2316 | "skins": [ 2317 | "token_10006_vodfox_doll#1" 2318 | ] 2319 | }, 2320 | "token_10007_phatom_twin": { 2321 | "rarity": 5, 2322 | "obtainable": true, 2323 | "skills": [ 2324 | "sktok_phatom_1", 2325 | "sktok_phatom_2", 2326 | "sktok_phatom_3" 2327 | ], 2328 | "skins": [ 2329 | "token_10007_phatom_twin#1", 2330 | "token_10007_phatom_twin_ghost#1" 2331 | ] 2332 | }, 2333 | "token_10008_cqbw_box": { 2334 | "rarity": 5, 2335 | "obtainable": true, 2336 | "skills": [ 2337 | null, 2338 | "sktok_cqbw_token", 2339 | null 2340 | ], 2341 | "skins": [ 2342 | "token_10008_cqbw_box#1", 2343 | "token_10008_cqbw_box_epoque#7" 2344 | ] 2345 | }, 2346 | "token_10009_weedy_cannon": { 2347 | "rarity": 5, 2348 | "obtainable": true, 2349 | "skills": [ 2350 | null, 2351 | null, 2352 | "sktok_weedy_token" 2353 | ], 2354 | "skins": [ 2355 | "token_10009_weedy_cannon#1", 2356 | "token_10009_weedy_cannon_snow#2" 2357 | ] 2358 | }, 2359 | "token_10010_folivo_car": { 2360 | "rarity": 4, 2361 | "obtainable": true, 2362 | "skills": [ 2363 | null, 2364 | "sktok_folivo_2" 2365 | ], 2366 | "skins": [ 2367 | "token_10010_folivo_car#1" 2368 | ] 2369 | }, 2370 | "token_10011_beewax_oblisk": { 2371 | "rarity": 4, 2372 | "obtainable": true, 2373 | "skills": [ 2374 | null, 2375 | "sktok_beewax" 2376 | ], 2377 | "skins": [ 2378 | "token_10011_beewax_oblisk#1" 2379 | ] 2380 | }, 2381 | "token_10012_rosmon_shield": { 2382 | "rarity": 5, 2383 | "obtainable": true, 2384 | "skills": [ 2385 | null, 2386 | null, 2387 | "sktok_rosmon" 2388 | ], 2389 | "skins": [ 2390 | "token_10012_rosmon_shield#1", 2391 | "token_10012_rosmon_shield#2" 2392 | ] 2393 | }, 2394 | "token_10013_robin_mine": { 2395 | "rarity": 4, 2396 | "obtainable": true, 2397 | "skills": [ 2398 | "sktok_robin_1", 2399 | "sktok_robin_2" 2400 | ], 2401 | "skins": [ 2402 | "token_10013_robin_mine#1" 2403 | ] 2404 | }, 2405 | "token_10014_bstalk_crab": { 2406 | "rarity": 3, 2407 | "obtainable": true, 2408 | "skills": [ 2409 | null, 2410 | null 2411 | ], 2412 | "skins": [ 2413 | "token_10014_bstalk_crab#1" 2414 | ] 2415 | }, 2416 | "token_10015_dusk_drgn": { 2417 | "rarity": 5, 2418 | "obtainable": true, 2419 | "skills": [ 2420 | null, 2421 | null, 2422 | null 2423 | ], 2424 | "skins": [ 2425 | "token_10015_dusk_drgn#1", 2426 | "token_10015_dusk_drgn#2" 2427 | ] 2428 | }, 2429 | "trap_001_crate": { 2430 | "rarity": 0, 2431 | "obtainable": true, 2432 | "skills": [ 2433 | "sktok_crate" 2434 | ], 2435 | "skins": [ 2436 | "trap_001_crate#1" 2437 | ] 2438 | }, 2439 | "trap_002_emp": { 2440 | "rarity": 0, 2441 | "obtainable": true, 2442 | "skills": [ 2443 | "sktok_emp" 2444 | ], 2445 | "skins": [ 2446 | "trap_002_emp#1" 2447 | ] 2448 | }, 2449 | "trap_003_gate": { 2450 | "rarity": 0, 2451 | "obtainable": true, 2452 | "skills": [ 2453 | "sktok_gate" 2454 | ], 2455 | "skins": [ 2456 | "trap_003_gate#1" 2457 | ] 2458 | }, 2459 | "trap_005_sensor": { 2460 | "rarity": 0, 2461 | "obtainable": true, 2462 | "skills": [ 2463 | "sktok_sensor" 2464 | ], 2465 | "skins": [ 2466 | "trap_005_sensor#1" 2467 | ] 2468 | }, 2469 | "trap_006_antidr": { 2470 | "rarity": 0, 2471 | "obtainable": true, 2472 | "skills": [ 2473 | "sktok_antidr" 2474 | ], 2475 | "skins": [ 2476 | "trap_006_antidr#1" 2477 | ] 2478 | }, 2479 | "trap_007_ballis": { 2480 | "rarity": 0, 2481 | "obtainable": true, 2482 | "skills": [ 2483 | "sktok_ballis" 2484 | ], 2485 | "skins": [ 2486 | "trap_007_ballis#1" 2487 | ] 2488 | }, 2489 | "trap_008_farm": { 2490 | "rarity": 0, 2491 | "obtainable": true, 2492 | "skills": [ 2493 | "sktok_farm" 2494 | ], 2495 | "skins": [ 2496 | "trap_008_farm#1" 2497 | ] 2498 | }, 2499 | "trap_009_battery": { 2500 | "rarity": 0, 2501 | "obtainable": true, 2502 | "skills": [], 2503 | "skins": [ 2504 | "trap_009_battery#1" 2505 | ] 2506 | }, 2507 | "trap_010_frosts": { 2508 | "rarity": 0, 2509 | "obtainable": true, 2510 | "skills": [ 2511 | "sktok_frosts" 2512 | ], 2513 | "skins": [ 2514 | "trap_010_frosts#1" 2515 | ] 2516 | }, 2517 | "trap_011_ore": { 2518 | "rarity": 0, 2519 | "obtainable": true, 2520 | "skills": [ 2521 | "sktok_ore" 2522 | ], 2523 | "skins": [ 2524 | "trap_011_ore#1" 2525 | ] 2526 | }, 2527 | "trap_012_mine": { 2528 | "rarity": 0, 2529 | "obtainable": true, 2530 | "skills": [ 2531 | "sktok_mine" 2532 | ], 2533 | "skins": [ 2534 | "trap_012_mine#1" 2535 | ] 2536 | }, 2537 | "trap_013_blower": { 2538 | "rarity": 0, 2539 | "obtainable": true, 2540 | "skills": [ 2541 | "sktok_blower" 2542 | ], 2543 | "skins": [ 2544 | "trap_013_blower#1" 2545 | ] 2546 | }, 2547 | "trap_014_tower": { 2548 | "rarity": 0, 2549 | "obtainable": true, 2550 | "skills": [ 2551 | "sktok_tower" 2552 | ], 2553 | "skins": [ 2554 | "trap_014_tower#1" 2555 | ] 2556 | }, 2557 | "trap_015_tree": { 2558 | "rarity": 0, 2559 | "obtainable": true, 2560 | "skills": [ 2561 | "sktok_tree" 2562 | ], 2563 | "skins": [ 2564 | "trap_015_tree#1" 2565 | ] 2566 | }, 2567 | "trap_016_peon": { 2568 | "rarity": 0, 2569 | "obtainable": true, 2570 | "skills": [], 2571 | "skins": [ 2572 | "trap_016_peon#1" 2573 | ] 2574 | }, 2575 | "trap_018_bomb": { 2576 | "rarity": 0, 2577 | "obtainable": true, 2578 | "skills": [ 2579 | "sktok_bomb" 2580 | ], 2581 | "skins": [ 2582 | "trap_018_bomb#1" 2583 | ] 2584 | }, 2585 | "trap_019_electric": { 2586 | "rarity": 0, 2587 | "obtainable": true, 2588 | "skills": [ 2589 | "sktok_electric" 2590 | ], 2591 | "skins": [ 2592 | "trap_019_electric#1" 2593 | ] 2594 | }, 2595 | "trap_020_roadblock": { 2596 | "rarity": 0, 2597 | "obtainable": true, 2598 | "skills": [ 2599 | "sktok_roadblock" 2600 | ], 2601 | "skins": [ 2602 | "trap_020_roadblock#1" 2603 | ] 2604 | }, 2605 | "trap_021_flame": { 2606 | "rarity": 0, 2607 | "obtainable": true, 2608 | "skills": [ 2609 | "sktok_flame" 2610 | ], 2611 | "skins": [ 2612 | "trap_021_flame#1" 2613 | ] 2614 | }, 2615 | "trap_022_frosts_friend": { 2616 | "rarity": 0, 2617 | "obtainable": true, 2618 | "skills": [ 2619 | "sktok_frosts_friend" 2620 | ], 2621 | "skins": [ 2622 | "trap_022_frosts_friend#1" 2623 | ] 2624 | }, 2625 | "trap_023_ore_friend": { 2626 | "rarity": 0, 2627 | "obtainable": true, 2628 | "skills": [ 2629 | "sktok_ore_friend" 2630 | ], 2631 | "skins": [ 2632 | "trap_023_ore_friend#1" 2633 | ] 2634 | }, 2635 | "trap_024_npcsld": { 2636 | "rarity": 0, 2637 | "obtainable": true, 2638 | "skills": [ 2639 | "sktok_npcsld" 2640 | ], 2641 | "skins": [ 2642 | "trap_024_npcsld#1" 2643 | ] 2644 | }, 2645 | "trap_025_prison": { 2646 | "rarity": 0, 2647 | "obtainable": true, 2648 | "skills": [ 2649 | "sktok_prison" 2650 | ], 2651 | "skins": [ 2652 | "trap_025_prison#1" 2653 | ] 2654 | }, 2655 | "trap_026_inverter": { 2656 | "rarity": 0, 2657 | "obtainable": true, 2658 | "skills": [ 2659 | "sktok_inverter" 2660 | ], 2661 | "skins": [ 2662 | "trap_026_inverter#1" 2663 | ] 2664 | }, 2665 | "trap_027_stone": { 2666 | "rarity": 0, 2667 | "obtainable": true, 2668 | "skills": [ 2669 | "sktok_stone" 2670 | ], 2671 | "skins": [ 2672 | "trap_027_stone#1" 2673 | ] 2674 | }, 2675 | "char_230_savage": { 2676 | "rarity": 4, 2677 | "obtainable": true, 2678 | "skills": [ 2679 | "skchr_savage_1", 2680 | "skchr_savage_2" 2681 | ], 2682 | "skins": [ 2683 | "char_230_savage#1", 2684 | "char_230_savage#2" 2685 | ] 2686 | }, 2687 | "char_282_catap": { 2688 | "rarity": 2, 2689 | "obtainable": true, 2690 | "skills": [ 2691 | "skchr_catap_1" 2692 | ], 2693 | "skins": [ 2694 | "char_282_catap#1" 2695 | ] 2696 | }, 2697 | "char_283_midn": { 2698 | "rarity": 2, 2699 | "obtainable": true, 2700 | "skills": [ 2701 | "skchr_midn_1" 2702 | ], 2703 | "skins": [ 2704 | "char_283_midn#1", 2705 | "char_283_midn@boc#1" 2706 | ] 2707 | }, 2708 | "char_137_brownb": { 2709 | "rarity": 3, 2710 | "obtainable": true, 2711 | "skills": [ 2712 | "skchr_brownb_1", 2713 | "skchr_brownb_2" 2714 | ], 2715 | "skins": [ 2716 | "char_137_brownb#1", 2717 | "char_137_brownb#2", 2718 | "char_137_brownb@kitchen#1" 2719 | ] 2720 | }, 2721 | "char_347_jaksel": { 2722 | "rarity": 3, 2723 | "obtainable": true, 2724 | "skills": [ 2725 | "skchr_jaksel_1", 2726 | "skchr_jaksel_2" 2727 | ], 2728 | "skins": [ 2729 | "char_347_jaksel#1", 2730 | "char_347_jaksel#2" 2731 | ] 2732 | }, 2733 | "char_164_nightm": { 2734 | "rarity": 4, 2735 | "obtainable": true, 2736 | "skills": [ 2737 | "skchr_nightm_1", 2738 | "skchr_nightm_2" 2739 | ], 2740 | "skins": [ 2741 | "char_164_nightm#1", 2742 | "char_164_nightm#2", 2743 | "char_164_nightm@epoque#5" 2744 | ] 2745 | }, 2746 | "char_220_grani": { 2747 | "rarity": 4, 2748 | "obtainable": true, 2749 | "skills": [ 2750 | "skcom_def_up[3]", 2751 | "skchr_grani_2" 2752 | ], 2753 | "skins": [ 2754 | "char_220_grani#1", 2755 | "char_220_grani#2", 2756 | "char_220_grani@epoque#6" 2757 | ] 2758 | }, 2759 | "char_263_skadi": { 2760 | "rarity": 5, 2761 | "obtainable": true, 2762 | "skills": [ 2763 | "skcom_quickattack[3]", 2764 | "skchr_skadi_2", 2765 | "skchr_skadi_3" 2766 | ], 2767 | "skins": [ 2768 | "char_263_skadi#1", 2769 | "char_263_skadi#2", 2770 | "char_263_skadi@summer#3" 2771 | ] 2772 | } 2773 | }, 2774 | "shopskins": [ 2775 | "char_002_amiya@winter#1", 2776 | "char_181_flower@daily#1", 2777 | "char_002_amiya@epoque#4", 2778 | "char_202_demkni@test#1", 2779 | "char_208_melan@epoque#1", 2780 | "char_109_fmout@epoque#2", 2781 | "char_187_ccheal@epoque#2", 2782 | "char_128_plosis@epoque#3", 2783 | "char_215_mantic@epoque#4", 2784 | "char_164_nightm@epoque#5", 2785 | "char_213_mostma@epoque#5", 2786 | "char_274_astesi@epoque#5", 2787 | "char_220_grani@epoque#6", 2788 | "char_113_cqbw@epoque#7", 2789 | "char_102_texas@epoque#7", 2790 | "char_130_doberm@epoque#7", 2791 | "char_355_ethan@epoque#7", 2792 | "char_253_greyy@epoque#8", 2793 | "char_120_hibisc@nian#1", 2794 | "char_010_chen@nian#2", 2795 | "char_308_swire@nian#2", 2796 | "char_107_liskam@nian#2", 2797 | "char_235_jesica@nian#2", 2798 | "char_136_hsguma@nian#3", 2799 | "char_2014_nian@nian#4", 2800 | "char_225_haak@nian#4", 2801 | "char_226_hmau@nian#4", 2802 | "char_436_whispr@nian#4", 2803 | "char_147_shining@summer#1", 2804 | "char_166_skfire@summer#1", 2805 | "char_290_vigna@summer#1", 2806 | "char_212_ansel@summer#1", 2807 | "char_134_ifrit@summer#1", 2808 | "char_101_sora@summer#1", 2809 | "char_196_sunbr@summer#1", 2810 | "char_199_yak@summer#1", 2811 | "char_286_cast3@summer#1", 2812 | "char_148_nearl@summer#2", 2813 | "char_236_rope@summer#2", 2814 | "char_263_skadi@summer#3", 2815 | "char_145_prove@summer#3", 2816 | "char_204_platnm@summer#3", 2817 | "char_172_svrash@summer#4", 2818 | "char_2013_cerber@summer#4", 2819 | "char_201_moeshd@summer#4", 2820 | "char_337_utage@summer#4", 2821 | "char_241_panda@marthe#1", 2822 | "char_115_headbr@marthe#2", 2823 | "char_179_cgbird@witch#1", 2824 | "char_171_bldsk@witch#1", 2825 | "char_236_rope@witch#1", 2826 | "char_124_kroos@witch#1", 2827 | "char_102_texas@winter#1", 2828 | "char_143_ghost@winter#1", 2829 | "char_198_blackd@winter#1", 2830 | "char_123_fang@winter#1", 2831 | "char_252_bibeak@winter#2", 2832 | "char_271_spikes@winter#2", 2833 | "char_237_gravel@winter#2", 2834 | "char_108_silent@winter#2", 2835 | "char_340_shwaz@snow#1", 2836 | "char_172_svrash@snow#1", 2837 | "char_174_slbell@snow#1", 2838 | "char_209_ardign@snow#1", 2839 | "char_400_weedy@snow#2", 2840 | "char_401_elysm@snow#2", 2841 | "char_158_milu@snow#2", 2842 | "char_103_angel@wild#1", 2843 | "char_173_slchan@wild#1", 2844 | "char_117_myrrh@wild#1", 2845 | "char_150_snakek@wild#1", 2846 | "char_112_siege@wild#2", 2847 | "char_158_milu@wild#2", 2848 | "char_235_jesica@wild#2", 2849 | "char_358_lisa@wild#3", 2850 | "char_373_lionhd@wild#3", 2851 | "char_365_aprl@wild#3", 2852 | "char_219_meteo@sweep#1", 2853 | "char_108_silent@sweep#1", 2854 | "char_235_jesica@sweep#1", 2855 | "char_103_angel@kfc#1", 2856 | "char_134_ifrit@kfc#1", 2857 | "char_201_moeshd@kfc#1", 2858 | "char_173_slchan@wwf#1", 2859 | "char_202_demkni@boc#1", 2860 | "char_291_aglina@boc#1", 2861 | "char_140_whitew@boc#1", 2862 | "char_279_excu@boc#1", 2863 | "char_367_swllow@boc#1", 2864 | "char_283_midn@boc#1", 2865 | "char_122_beagle@boc#1", 2866 | "char_248_mgllan@kitchen#1", 2867 | "char_195_glassb@kitchen#1", 2868 | "char_137_brownb@kitchen#1", 2869 | "char_250_phatom@ghost#1", 2870 | "char_242_otter@ghost#1", 2871 | "char_326_glacus@ghost#1", 2872 | "char_277_sqrrel@ghost#1", 2873 | "char_222_bpipe@race#1" 2874 | ], 2875 | "maxstatus": { 2876 | "0": { 2877 | "level": 30, 2878 | "potentialRank": 5, 2879 | "mainSkillLvl": 1, 2880 | "favorPoint": 240000 2881 | }, 2882 | "1": {}, 2883 | "2": { 2884 | "level": 55, 2885 | "mainSkillLvl": 7, 2886 | "evolvePhase": 1 2887 | }, 2888 | "3": { 2889 | "level": 70, 2890 | "evolvePhase": 2 2891 | }, 2892 | "4": { 2893 | "level": 80 2894 | }, 2895 | "5": { 2896 | "level": 90 2897 | } 2898 | } 2899 | } -------------------------------------------------------------------------------- /data/arkhack_pool.json: -------------------------------------------------------------------------------- 1 | { 2 | "poolInfo": [ 3 | { 4 | "rarityRank": 5, 5 | "charIdList": [ 6 | "char_103_angel", 7 | "char_112_siege", 8 | "char_134_ifrit", 9 | "char_180_amgoat", 10 | "char_291_aglina", 11 | "char_147_shining", 12 | "char_179_cgbird", 13 | "char_136_hsguma", 14 | "char_202_demkni", 15 | "char_172_svrash", 16 | "char_263_skadi", 17 | "char_010_chen", 18 | "char_340_shwaz", 19 | "char_188_helage", 20 | "char_248_mgllan", 21 | "char_213_mostma", 22 | "char_017_huang", 23 | "char_225_haak", 24 | "char_2013_cerber", 25 | "char_222_bpipe", 26 | "char_250_phatom", 27 | "char_400_weedy", 28 | "char_197_poca", 29 | "char_358_lisa", 30 | "char_293_thorns", 31 | "char_416_zumama", 32 | "char_350_surtr", 33 | "char_423_blemsh", 34 | "char_311_mudrok", 35 | "char_264_f12yin", 36 | "char_332_archet" 37 | ], 38 | "totalPercent": 0.02, 39 | "upPercent":0.5 40 | }, 41 | { 42 | "rarityRank": 4, 43 | "charIdList": [ 44 | "char_128_plosis", 45 | "char_115_headbr", 46 | "char_102_texas", 47 | "char_106_franka", 48 | "char_140_whitew", 49 | "char_143_ghost", 50 | "char_129_bluep", 51 | "char_204_platnm", 52 | "char_219_meteo", 53 | "char_166_skfire", 54 | "char_242_otter", 55 | "char_108_silent", 56 | "char_171_bldsk", 57 | "char_148_nearl", 58 | "char_144_red", 59 | "char_107_liskam", 60 | "char_201_moeshd", 61 | "char_145_prove", 62 | "char_158_milu", 63 | "char_173_slchan", 64 | "char_174_slbell", 65 | "char_195_glassb", 66 | "char_101_sora", 67 | "char_215_mantic", 68 | "char_241_panda", 69 | "char_164_nightm", 70 | "char_308_swire", 71 | "char_326_glacus", 72 | "char_274_astesi", 73 | "char_279_excu", 74 | "char_243_waaifu", 75 | "char_261_sddrag", 76 | "char_356_broca", 77 | "char_367_swllow", 78 | "char_226_hmau", 79 | "char_306_leizi", 80 | "char_379_sesa", 81 | "char_254_vodfox", 82 | "char_401_elysm", 83 | "char_378_asbest", 84 | "char_343_tknogi", 85 | "char_373_lionhd", 86 | "char_294_ayer", 87 | "char_344_beewax", 88 | "char_349_chiave", 89 | "char_218_cuttle", 90 | "char_415_flint", 91 | "char_365_aprl", 92 | "char_346_aosta", 93 | "char_436_whispr", 94 | "char_214_kafka", 95 | "char_338_iris" 96 | ], 97 | "totalPercent": 0.08, 98 | "upPercent":0.5 99 | }, 100 | { 101 | "rarityRank": 3, 102 | "charIdList": [ 103 | "char_141_nights", 104 | "char_109_fmout", 105 | "char_235_jesica", 106 | "char_126_shotst", 107 | "char_118_yuki", 108 | "char_149_scave", 109 | "char_290_vigna", 110 | "char_130_doberm", 111 | "char_289_gyuki", 112 | "char_193_frostl", 113 | "char_185_frncat", 114 | "char_237_gravel", 115 | "char_236_rope", 116 | "char_117_myrrh", 117 | "char_181_flower", 118 | "char_199_yak", 119 | "char_150_snakek", 120 | "char_196_sunbr", 121 | "char_110_deepcl", 122 | "char_183_skgoat", 123 | "char_277_sqrrel", 124 | "char_137_brownb", 125 | "char_253_greyy", 126 | "char_298_susuro", 127 | "char_151_myrtle", 128 | "char_190_clour", 129 | "char_133_mm", 130 | "char_302_glaze", 131 | "char_337_utage", 132 | "char_301_cutter", 133 | "char_258_podego", 134 | "char_328_cammou", 135 | "char_272_strong", 136 | "char_366_acdrop", 137 | "char_271_spikes", 138 | "char_381_bubble", 139 | "char_347_jaksel", 140 | "char_440_pinecn", 141 | "char_452_bstalk" 142 | ], 143 | "totalPercent": 0.5, 144 | "upPercent":0.2 145 | }, 146 | { 147 | "rarityRank": 2, 148 | "charIdList": [ 149 | "char_123_fang", 150 | "char_240_wyvern", 151 | "char_192_falco", 152 | "char_208_melan", 153 | "char_209_ardign", 154 | "char_122_beagle", 155 | "char_124_kroos", 156 | "char_121_lava", 157 | "char_120_hibisc", 158 | "char_212_ansel", 159 | "char_210_stward", 160 | "char_278_orchid", 161 | "char_282_catap", 162 | "char_283_midn", 163 | "char_284_spot", 164 | "char_281_popka" 165 | ], 166 | "totalPercent": 0.4, 167 | "upPercent":0 168 | } 169 | ] 170 | } -------------------------------------------------------------------------------- /dataProcess.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | character_table = "./data/character_table.json" 4 | skin_table = "./data/skin_table.json" 5 | maxStatus = {0:{"level":30,"potentialRank":5,"mainSkillLvl":1,"favorPoint":240000}, 6 | 1:{}, 7 | 2:{"level":55,"mainSkillLvl":7,"evolvePhase":1}, 8 | 3:{"level":70,"evolvePhase":2}, 9 | 4:{"level":80}, 10 | 5:{"level":90}} 11 | 12 | def processCharacter(ct,st): 13 | newdata = {} 14 | skinlist = [] 15 | with open(ct,"r",encoding="utf8") as f: 16 | data = json.loads(f.read().strip()) 17 | for key,value in data.items(): 18 | newdata[key] = {"rarity":value["rarity"],"obtainable":not value["isNotObtainable"],"skills":[skill["skillId"] for skill in value["skills"]],"skins":[]} 19 | with open(st,"r",encoding="utf8") as f: 20 | data = json.loads(f.read().strip()) 21 | for key,value in data["charSkins"].items(): 22 | newdata[value["charId"]]["skins"].append(value["skinId"]) 23 | if ("@" in value["skinId"]): 24 | skinlist.append(value["skinId"]) 25 | 26 | with open("./data/arkhack_data.json","w",encoding="utf8") as f: 27 | f.write(json.dumps({"character":newdata,"shopskins":skinlist,"maxstatus":maxStatus},indent=2)) 28 | 29 | processCharacter(character_table,skin_table) -------------------------------------------------------------------------------- /frida_hooks/keyivhook_1280.js: -------------------------------------------------------------------------------- 1 | function get_func_by_offset(module_name,offset){ 2 | var module=Process.getModuleByName(module_name) 3 | var addr=module.base.add(offset); 4 | return new NativePointer(addr.toString()); 5 | } 6 | 7 | function BinaryToHexString(){ 8 | var func = get_func_by_offset("libil2cpp.so",0x10F6B6D) 9 | console.log('[+] hook '+func.toString()) 10 | var len = 0; 11 | Interceptor.attach(func, { 12 | onEnter: function (args) { 13 | console.log('******BinaryToHexString********') 14 | console.log('[index] '+args[2].toInt32()) 15 | console.log('[length] '+args[3].toInt32()) 16 | // len = args[3].toInt32() 17 | console.log('******BinaryToHexString********') 18 | }, 19 | onLeave: function (retval) { 20 | console.log('-------BinaryToHexString-------') 21 | console.log(retval.readByteArray(len*4+12)) 22 | console.log('-------BinaryToHexString-------') 23 | } 24 | }); 25 | } 26 | 27 | function padding(){ 28 | var func = get_func_by_offset("libil2cpp.so",0x222B3E2) 29 | console.log('[+] hook '+func.toString()) 30 | Interceptor.attach(func, { 31 | onEnter: function (args) { 32 | }, 33 | onLeave: function (retval) { 34 | console.log('[padding] '+retval.toInt32()) 35 | } 36 | }); 37 | } 38 | 39 | function modee(){ 40 | var func = get_func_by_offset("libil2cpp.so",0x222B2AE) 41 | console.log('[+] hook '+func.toString()) 42 | Interceptor.attach(func, { 43 | onEnter: function (args) { 44 | }, 45 | onLeave: function (retval) { 46 | console.log('[modee] '+retval.toInt32()) 47 | } 48 | }); 49 | } 50 | 51 | function ivget(){ 52 | var func = get_func_by_offset("libil2cpp.so",0x222ACE9) 53 | console.log('[+] hook '+func.toString()) 54 | Interceptor.attach(func, { 55 | onEnter: function (args) { 56 | }, 57 | onLeave: function (retval) { 58 | console.log('[iv get]') 59 | console.log(retval.readByteArray(16+16)) 60 | } 61 | }); 62 | } 63 | 64 | function ivset(){ 65 | var func = get_func_by_offset("libil2cpp.so",0x222ADD3) 66 | console.log('[+] hook '+func.toString()) 67 | Interceptor.attach(func, { 68 | onEnter: function (args) { 69 | console.log('[iv set]') 70 | console.log(args[1].readByteArray(16+16)) 71 | }, 72 | onLeave: function (retval) { 73 | 74 | } 75 | }); 76 | } 77 | 78 | function keyget(){ 79 | var func = get_func_by_offset("libil2cpp.so",0x222AF53) 80 | console.log('[+] hook '+func.toString()) 81 | Interceptor.attach(func, { 82 | onEnter: function (args) { 83 | }, 84 | onLeave: function (retval) { 85 | console.log('[key get]') 86 | console.log(retval.readByteArray(16+16)) 87 | } 88 | }); 89 | } 90 | 91 | function keyset(){ 92 | var func = get_func_by_offset("libil2cpp.so",0x222B03D) 93 | console.log('[+] hook '+func.toString()) 94 | Interceptor.attach(func, { 95 | onEnter: function (args) { 96 | console.log('[key set]') 97 | console.log(args[1].readByteArray(16+16+32)) 98 | }, 99 | onLeave: function (retval) { 100 | 101 | } 102 | }); 103 | } 104 | 105 | function test2(){ 106 | var func = get_func_by_offset("libil2cpp.so",0x222B56D) 107 | console.log('[+] hook '+func.toString()) 108 | Interceptor.attach(func, { 109 | onEnter: function (args) { 110 | console.log("key") 111 | console.log(args[1].readByteArray(64)); 112 | console.log("iv") 113 | console.log(args[2].readByteArray(64)); 114 | }, 115 | onLeave: function (retval) { 116 | 117 | } 118 | }); 119 | } 120 | 121 | /* 122 | see https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rijndaelmanaged?view=net-5.0 123 | 124 | padding = 2 = PKCS7 125 | ciphermode = 1 = CBC 126 | 127 | iv length = 32 in hex = 16 hex pair = 16 in bytes 128 | key length = 32 in hex str = 16 hex pair = 16 in bytes 129 | */ 130 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.options import Options 2 | from mitmproxy.proxy.config import ProxyConfig 3 | from mitmproxy.proxy.server import ProxyServer 4 | from mitmproxy.tools.dump import DumpMaster 5 | from mitmproxy.tools.web.master import WebMaster 6 | from mitmproxy.tools.console.master import ConsoleMaster 7 | from mitmproxy import master 8 | from addons import ArkEssential,ArkInterceptor 9 | from addons.allChars import allChars 10 | from addons.moreChars import moreChars 11 | from addons.gachaSimulation import gachaSimulation 12 | from addons.userStatus import userInfo,userData 13 | from addons.graduateChars import graduateChars 14 | 15 | 16 | from addons.unlockSkins import unlockSkins 17 | from addons.CharsEssential import CharsEssential 18 | from addons.BattleEssential import BattleEssential 19 | from model.troopBuilder import troopBuilder,characterBuilder 20 | import json 21 | 22 | def run_web(options): 23 | webserver = WebMaster(options) 24 | webserver.server = ProxyServer(ProxyConfig(options)) 25 | return webserver # type: master.Master 26 | 27 | 28 | def run_dump(options): 29 | server = DumpMaster(options, with_termlog=False, with_dumper=False) 30 | server.server = ProxyServer(ProxyConfig(options)) 31 | return server # type: master.Master 32 | 33 | def run_console(options): 34 | server = ConsoleMaster(options) 35 | server.server = ProxyServer(ProxyConfig(options)) 36 | return server # type: master.Master 37 | from mitmproxy.http import HTTPFlow 38 | 39 | if __name__ == "__main__": 40 | ops = Options(listen_host='0.0.0.0', listen_port=8080, http2=True, ssl_insecure=True) 41 | master = run_web(ops) 42 | #ArkInterceptor.tBuilder = troopBuilder.init() 43 | master.addons.add(ArkEssential()) 44 | # master.addons.add(CharsEssential()) 45 | # master.addons.add(BattleEssential()) 46 | # master.addons.add(allChars()) 47 | # master.addons.add(graduateChars()) 48 | # master.addons.add(unlockSkins()) 49 | # mc = moreChars() 50 | # mc.addChars(["char_252_bibeak"]) 51 | # master.addons.add(mc) 52 | # master.addons.add(fakeGacha()) 53 | # master.addons.add(userInfo.init("123","0000",120,0)) 54 | # master.addons.add(userData.init(999,999,666,233,101)) 55 | 56 | # gs = gachaSimulation() 57 | # gs.addUp("char_340_shwaz","char_350_surtr") 58 | # gs.addUp("char_107_liskam", 59 | # "char_173_slchan", 60 | # "char_346_aosta") 61 | # master.addons.add(gs) 62 | master.run() 63 | -------------------------------------------------------------------------------- /model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aynakeya/Arknights-Dolos/25fbccf1287ddfb4b5abbe9c3f9f4bfa8c69020c/model/__init__.py -------------------------------------------------------------------------------- /model/troopBuilder.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | class characterBuilder(): 5 | def __init__(self,characterlist,skinslist,maxstatus): 6 | self.characters = characterlist # type:dict 7 | self.skins = skinslist # type: dict 8 | self.maxStatus = maxstatus 9 | self.starttime = 1559453208 10 | 11 | @classmethod 12 | def init(cls,filepath="./data/arkhack_data.json"): 13 | try: 14 | with open(filepath,"r",encoding="utf-8") as f: 15 | data = json.loads(f.read().strip()) 16 | return cls(data["character"],data["shopskins"],data["maxstatus"]) 17 | except: 18 | return None 19 | 20 | def getCharacter(self,instId,charId): 21 | if (charId not in self.characters.keys()): 22 | return None 23 | self.starttime +=1 24 | return {"instId":int(instId), 25 | "charId":charId, 26 | "favorPoint":0, 27 | "potentialRank":0, 28 | "mainSkillLvl":1, 29 | "skin":self.characters[charId]["skins"][0], 30 | "level":1, 31 | "exp":0, 32 | "evolvePhase":0, 33 | "defaultSkillIndex":-1 if self.characters[charId]["rarity"] <=1 else 0, 34 | "gainTime":self.starttime, 35 | "skills":[{"skillId":skillId, 36 | "unlock":1 if index == 0 else 0, 37 | "state":0, 38 | "specializeLevel":0, 39 | "completeUpgradeTime":-1} for index,skillId in enumerate(self.characters[charId]["skills"])]} 40 | 41 | def graduate(self,cdata): 42 | rarity = self.characters[cdata["charId"]]["rarity"] 43 | for r,v in self.maxStatus.items(): 44 | if rarity>=int(r): 45 | for key,val in v.items(): 46 | cdata[key] = val 47 | # 4星及其以上干员设置衣服, 专精 48 | if rarity >= 3: 49 | if (len(self.characters[cdata["charId"]]["skins"])>=3): 50 | cdata["skin"] = self.characters[cdata["charId"]]["skins"][2] 51 | elif (len(self.characters[cdata["charId"]]["skins"]) < 2): 52 | cdata["skin"] = self.characters[cdata["charId"]]["skins"][0] 53 | else: 54 | cdata["skin"] = self.characters[cdata["charId"]]["skins"][1] 55 | for skill in cdata["skills"]: 56 | skill["unlock"] = 1 57 | skill["specializeLevel"] = 3 58 | return cdata 59 | 60 | 61 | class troopBuilder(): 62 | def __init__(self,curCharInstId,curSquadCount,squads,chars,cBuilder: characterBuilder=None): 63 | self.curCharInstId = curCharInstId 64 | self.curSquadCount = curSquadCount 65 | # dict string key "0","1","2","3" 66 | self.squads = squads # type:dict 67 | # dict string key start from 1 68 | self.chars = chars # type:dict 69 | self.cBuilder = cBuilder # type 70 | 71 | @classmethod 72 | def init(cls,filepath="./data/arkhack_troop.json"): 73 | try: 74 | with open(filepath, "r", encoding="utf-8") as f: 75 | data = json.loads(f.read().strip()) 76 | return cls(data["curCharInstId"],data["curSquadCount"],data["squads"],data["chars"]) 77 | except: 78 | return None 79 | 80 | def setCharacterBuilder(self,cb: characterBuilder): 81 | self.cBuilder =cb 82 | 83 | def getCharData(self,charId): 84 | for char in self.chars.values(): 85 | if char["charId"] == charId: 86 | return char 87 | return None 88 | 89 | def getCharInstIds(self,charId): 90 | ids = [] 91 | for key,char in self.chars.items(): 92 | if char["charId"] == charId: 93 | ids.append(key) 94 | return ids 95 | 96 | def addCharacter(self,charId,force=False): 97 | if not force: 98 | for c in self.chars.values(): 99 | if c["charId"] == charId: 100 | return False 101 | cdata = self.cBuilder.getCharacter(self.curCharInstId,charId) 102 | if cdata == None: 103 | return False 104 | self.chars[str(self.curCharInstId)] = cdata 105 | self.curCharInstId +=1 106 | return True 107 | 108 | def dump(self): 109 | return {"curCharInstId": self.curCharInstId, "curSquadCount": self.curSquadCount, 110 | "squads": self.squads, "chars": self.chars} 111 | 112 | def save(self,filepath="./data/arkhack_troop.json",indent=2): 113 | with open(filepath, "w", encoding="utf8") as f: 114 | f.write(json.dumps({"curCharInstId": self.curCharInstId, "curSquadCount": self.curSquadCount, 115 | "squads":self.squads,"chars":self.chars}, indent=indent)) 116 | 117 | -------------------------------------------------------------------------------- /script/allCharPlus.py: -------------------------------------------------------------------------------- 1 | from mitmproxy.http import HTTPFlow, HTTPResponse 2 | import json,copy 3 | 4 | class characterBuilder(): 5 | def __init__(self,characterlist,skinslist,maxstatus): 6 | self.characters = characterlist # type:dict 7 | self.skins = skinslist # type: dict 8 | self.maxStatus = maxstatus 9 | self.starttime = 1559453208 10 | 11 | @classmethod 12 | def init(cls,filepath="./data/arkhack_data.json"): 13 | try: 14 | with open(filepath,"r",encoding="utf-8") as f: 15 | data = json.loads(f.read().strip()) 16 | return cls(data["character"],data["shopskins"],data["maxstatus"]) 17 | except: 18 | return None 19 | 20 | def getCharacter(self,instId,charId): 21 | if (charId not in self.characters.keys()): 22 | return None 23 | self.starttime +=1 24 | return {"instId":int(instId), 25 | "charId":charId, 26 | "favorPoint":0, 27 | "potentialRank":0, 28 | "mainSkillLvl":1, 29 | "skin":self.characters[charId]["skins"][0], 30 | "level":1, 31 | "exp":0, 32 | "evolvePhase":0, 33 | "defaultSkillIndex":-1 if self.characters[charId]["rarity"] <=1 else 0, 34 | "gainTime":self.starttime, 35 | "skills":[{"skillId":skillId, 36 | "unlock":1 if index == 0 else 0, 37 | "state":0, 38 | "specializeLevel":0, 39 | "completeUpgradeTime":-1} for index,skillId in enumerate(self.characters[charId]["skills"])]} 40 | 41 | def graduate(self,cdata): 42 | rarity = self.characters[cdata["charId"]]["rarity"] 43 | for r,v in self.maxStatus.items(): 44 | if rarity>=int(r): 45 | for key,val in v.items(): 46 | cdata[key] = val 47 | # 4星及其以上干员设置衣服, 专精 48 | if rarity >= 3: 49 | if (len(self.characters[cdata["charId"]]["skins"])>=2): 50 | cdata["skin"] = self.characters[cdata["charId"]]["skins"][1] 51 | else: 52 | cdata["skin"] = self.characters[cdata["charId"]]["skins"][0] 53 | for skill in cdata["skills"]: 54 | skill["unlock"] = 1 55 | skill["specializeLevel"] = 3 56 | return cdata 57 | 58 | 59 | class troopBuilder(): 60 | def __init__(self,curCharInstId,curSquadCount,squads,chars,cBuilder: characterBuilder=None): 61 | self.curCharInstId = curCharInstId 62 | self.curSquadCount = curSquadCount 63 | # dict string key "0","1","2","3" 64 | self.squads = squads # type:dict 65 | # dict string key start from 1 66 | self.chars = chars # type:dict 67 | self.cBuilder = cBuilder # type 68 | 69 | @classmethod 70 | def init(cls,filepath="./data/arkhack_troop.json"): 71 | try: 72 | with open(filepath, "r", encoding="utf-8") as f: 73 | data = json.loads(f.read().strip()) 74 | return cls(data["curCharInstId"],data["curSquadCount"],data["squads"],data["chars"]) 75 | except: 76 | return None 77 | 78 | def setCharacterBuilder(self,cb: characterBuilder): 79 | self.cBuilder =cb 80 | 81 | def addCharacter(self,charId,force=False): 82 | if not force: 83 | for c in self.chars.values(): 84 | if c["charId"] == charId: 85 | return False 86 | cdata = self.cBuilder.getCharacter(self.curCharInstId,charId) 87 | if cdata == None: 88 | return False 89 | self.chars[str(self.curCharInstId)] = cdata 90 | self.curCharInstId +=1 91 | return True 92 | 93 | def dump(self): 94 | return {"curCharInstId": self.curCharInstId, "curSquadCount": self.curSquadCount, 95 | "squads": self.squads, "chars": self.chars} 96 | 97 | def save(self,filepath="./data/arkhack_troop.json",indent=2): 98 | with open(filepath, "w", encoding="utf8") as f: 99 | f.write(json.dumps({"curCharInstId": self.curCharInstId, "curSquadCount": self.curSquadCount, 100 | "squads":self.squads,"chars":self.chars}, indent=indent)) 101 | 102 | class ArkInterceptor(): 103 | # from https://github.com/GhostStar/Arknights-Armada/ 104 | Servers = {"ak-gs-localhost.hypergryph.com": ("ak-gs.hypergryph.com", 8443), 105 | "ak-gs-b-localhost.hypergryph.com": ("ak-gs.hypergryph.com", 8443), 106 | "ak-as-localhost.hypergryph.com": ("ak-as.hypergryph.com", 9443)} 107 | 108 | ServersList = [key for key in Servers.keys()] + [val[0] for val in Servers.values()] 109 | tBuilder = None # type:troopBuilder 110 | cBuilder = characterBuilder.init() 111 | 112 | @staticmethod 113 | def setTroopBuilder(tb): 114 | ArkInterceptor.tBuilder = tb 115 | 116 | def http_connect(self, flow: HTTPFlow): 117 | pass 118 | 119 | def request(self, flow:HTTPFlow): 120 | pass 121 | 122 | def response(self, flow: HTTPFlow): 123 | pass 124 | 125 | def info(self,msg): 126 | print("Arkhack - %s > %s" %(self.__class__.__name__,msg)) 127 | 128 | class ArkEssential(ArkInterceptor): 129 | def http_connect(self, flow: HTTPFlow): 130 | # replace all localhost server to correct server 131 | if (flow.request.host in self.Servers.keys()): 132 | flow.request.host, flow.request.port = self.Servers.get(flow.request.host) 133 | 134 | class BattleEssential(ArkInterceptor): 135 | ''' 136 | Require: CharsEssential 137 | ''' 138 | 139 | def __init__(self): 140 | self.info("Loading success") 141 | 142 | def request(self, flow:HTTPFlow): 143 | """ 144 | { 145 | "changeSkill": 0, 146 | "slots": [{ 147 | "charInstId": 1, 148 | "skillIndex": 0 149 | },null,null,null,null,null,null 150 | ], 151 | "squadId": "0" 152 | } 153 | """ 154 | if flow.request.host in self.ServersList and flow.request.path.startswith("/quest/squadFormation"): 155 | self.info("Receive squad change request") 156 | req = json.loads(flow.request.get_text()) 157 | self.tBuilder.squads[req["squadId"]]["slots"] = req["slots"] 158 | req = copy.deepcopy(req) 159 | req["slots"] = [{ 160 | "charInstId": 1, 161 | "skillIndex": 0 162 | }, None, None, None, None, None, None, None, None, None, None, None] 163 | flow.request.set_text(json.dumps(req)) 164 | self.info("complete") 165 | 166 | if flow.request.host in self.ServersList and (flow.request.path.startswith("/quest/battleStart") or 167 | flow.request.path.startswith("/campaignV2/battleStart")): 168 | self.info("battle %s start: setting squad for remote server" % flow.request.path.split("/")[1]) 169 | req = json.loads(flow.request.get_text()) 170 | req['squad']['slots'] = [{ 171 | "charInstId": 1, 172 | "skillIndex": 0 173 | }, None, None, None, None, None, None, None, None, None, None, None] 174 | flow.request.set_text(json.dumps(req)) 175 | self.info("complete") 176 | 177 | def response(self, flow: HTTPFlow): 178 | if flow.request.host in self.ServersList and flow.request.path.startswith("/quest/squadFormation"): 179 | data = json.loads(flow.response.get_text()) 180 | self.info('setting squad data for local modification') 181 | for sid in data['playerDataDelta']['modified']['troop']['squads'].keys(): 182 | data['playerDataDelta']['modified']['troop']['squads'][sid] = self.tBuilder.squads[sid] 183 | flow.response.set_text(json.dumps(data)) 184 | self.info("complete") 185 | 186 | class CharsEssential(ArkInterceptor): 187 | def __init__(self,mode="weak"): 188 | self.mode = mode 189 | self.info("Loading success, mode %s" %self.mode) 190 | 191 | def request(self, flow:HTTPFlow): 192 | if flow.request.host in self.ServersList and flow.request.path.startswith("/charBuild/setDefaultSkill"): 193 | self.info("Receive default skill change change request") 194 | req = json.loads(flow.request.get_text()) 195 | self.tBuilder.chars[str(req["charInstId"])]["defaultSkillIndex"] = req["defaultSkillIndex"] 196 | resp = {"playerDataDelta": {"deleted": {}, 197 | "modified": { 198 | "troop": {"chars": {str(req["charInstId"]): { 199 | "defaultSkillIndex": req["defaultSkillIndex"]}}}}}} 200 | self.info("make response") 201 | flow.response = HTTPResponse.make(200, 202 | json.dumps(resp), 203 | {"Content-Type": "application/json; charset=utf-8"}) 204 | self.info("Reply Complete") 205 | 206 | def response(self, flow: HTTPFlow): 207 | if flow.request.host in self.ServersList and flow.request.path.startswith("/account/syncData"): 208 | data = json.loads(flow.response.get_text()) 209 | if self.tBuilder is None: 210 | self.info("Troop builder not found, create from response data") 211 | ArkInterceptor.tBuilder = troopBuilder(data["user"]["troop"]["curCharInstId"], 212 | data["user"]["troop"]["curSquadCount"], 213 | data["user"]["troop"]["squads"], 214 | data["user"]["troop"]["chars"]) 215 | else: 216 | self.info("Find exist troop builder, write config to response") 217 | data["user"]["troop"] = self.tBuilder.dump() 218 | flow.response.set_text(json.dumps(data)) 219 | ArkInterceptor.tBuilder.setCharacterBuilder(ArkInterceptor.cBuilder) 220 | self.info("Complete") 221 | 222 | class graduateChars(ArkInterceptor): 223 | ''' 224 | Require: CharsEssential,BattleEssential 225 | ''' 226 | def __init__(self): 227 | self.info("Loading success") 228 | 229 | def response(self, flow: HTTPFlow): 230 | if flow.request.host in self.ServersList and flow.request.path.startswith("/account/syncData"): 231 | self.info("Receive response") 232 | data = json.loads(flow.response.get_text()) 233 | for key,char in self.tBuilder.chars.items(): 234 | self.info("Upgrade: %s-%s" %(key,char["charId"])) 235 | self.tBuilder.chars[key] = self.cBuilder.graduate(self.tBuilder.chars[key]) 236 | data["user"]["troop"] = self.tBuilder.dump() 237 | flow.response.set_text(json.dumps(data)) 238 | self.info("Complete") 239 | class unlockSkins(ArkInterceptor): 240 | ''' 241 | Require: CharsEssential 242 | ''' 243 | def __init__(self): 244 | self.info("Loading success") 245 | 246 | def request(self, flow: HTTPFlow): 247 | """ 248 | { 249 | "charInstId": 9, 250 | "skinId": "char_123_fang#1" 251 | } 252 | """ 253 | if flow.request.host in self.ServersList and flow.request.path.startswith("/charBuild/changeCharSkin"): 254 | self.info("Receive skin change request") 255 | req = json.loads(flow.request.get_text()) 256 | resp = {"playerDataDelta": {"deleted": {}, 257 | "modified": { "troop": {"chars": {str(req["charInstId"]): {"skin": req["skinId"]}}}}}} 258 | self.info("make response") 259 | self.tBuilder.chars[req["charInstId"]]["skin"] = req["skinId"] 260 | flow.response = HTTPResponse.make(200, 261 | json.dumps(resp), 262 | {"Content-Type":"application/json; charset=utf-8"}) 263 | self.info("Reply Complete") 264 | 265 | def response(self, flow: HTTPFlow): 266 | if flow.request.host in self.ServersList and flow.request.path.startswith("/account/syncData"): 267 | self.info("Receive response") 268 | data = json.loads(flow.response.get_text()) 269 | self.info("Unlocking....") 270 | data["user"]["skin"]["characterSkins"] = dict((key, 1) for key in self.cBuilder.skins) 271 | flow.response.set_text(json.dumps(data)) 272 | self.info("Complete") 273 | 274 | class allChars(ArkInterceptor): 275 | ''' 276 | Require: CharsEssential,BattleEssential 277 | ''' 278 | def __init__(self): 279 | self.info("Loading success") 280 | 281 | def response(self, flow: HTTPFlow): 282 | if flow.request.host in self.ServersList and flow.request.path.startswith("/account/syncData"): 283 | self.info("Receive response") 284 | data = json.loads(flow.response.get_text()) 285 | char = [] 286 | self.info("Get character list") 287 | for c in self.tBuilder.cBuilder.characters.keys(): 288 | if "char" in c: 289 | char.append(c) 290 | self.info("add characters.....") 291 | for c in char: 292 | self.tBuilder.addCharacter(c) 293 | data["user"]["troop"] = self.tBuilder.dump() 294 | flow.response.set_text(json.dumps(data)) 295 | self.info("Complete") 296 | 297 | 298 | ArkInterceptor.cBuilder = characterBuilder.init("arkhack_data.json") 299 | 300 | addons = [ 301 | ArkEssential(), 302 | CharsEssential(), 303 | BattleEssential(), 304 | allChars(), 305 | graduateChars(), 306 | unlockSkins() 307 | ] 308 | -------------------------------------------------------------------------------- /troopEditor.py: -------------------------------------------------------------------------------- 1 | from model.troopBuilder import troopBuilder,characterBuilder 2 | 3 | tb = troopBuilder.init() 4 | tb.setCharacterBuilder(characterBuilder.init()) 5 | char = [] 6 | for c in tb.cBuilder.characters.keys(): 7 | if "char" in c and tb.cBuilder.characters[c]["obtainable"]: 8 | char.append(c) 9 | 10 | for c in char: 11 | tb.addCharacter(c) 12 | 13 | for key, char in tb.chars.items(): 14 | tb.chars[key] = tb.cBuilder.graduate(tb.chars[key]) 15 | tb.save(indent=2) --------------------------------------------------------------------------------