-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathextractByNode.js
311 lines (286 loc) · 10.6 KB
/
extractByNode.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
const fs = require('fs');
const crypto = require('crypto');
const Card = require('./official-API/parseCard');
const Skill = require('./official-API/parseSkill');
const runDate = new Date();
const officialAPI = [ //来源于官方API
{
code: "ja",
customName: ["cht", "chs"]
},
{
code: "en",
customName: []
},
{
code: "ko",
customName: []
}
];
//数组去重
Array.prototype.distinct = function () {
let _set = new Set(this);
return Array.from(_set)
}
//比较两只怪物是否是同一只(在不同语言服务器)
function sameCard(m1, m2) {
//不管那么多了,懒得判断了
return true;
if (m1 == undefined || m2 == undefined) return false; //是否存在
if (m1.attrs[0] != m2.attrs[0]) return false; //主属性
//if (m1.attrs[1] != m2.attrs[1]) return false; //副属性
//全部类型有任意不同的时候也返回false,但是考虑到上修,不要求总数一致
for (let i = 0; i < Math.min(m1.types.length, m2.types.length); i++) {
if (m1.types[i] != m2.types[i]) return false;
}
if (m1.maxLevel != m2.maxLevel) return false; //最大等级
if (m1.seriesId != m2.seriesId) return false; //系列ID
return true;
}
//查找到真正起作用的那一个技能
function getActuallySkills(skillsDataset, skillid, skillTypes, searchRandom = true) {
const skill = skillsDataset[skillid];
if (skill) {
if (skillTypes.includes(skill.type)) {
return [skill];
} else if (skill.type == 116 || //主动技
(searchRandom && skill.type == 118) || //随机主动技
skill.type == 138 || //队长技
skill.type == 232 || //进化技能1,不循环
skill.type == 233) { //进化技能2,循环
//因为可能有多层调用,特别是随机118再调用组合116的,所以需要递归
let subSkills = skill.params.flatMap(id => getActuallySkills(skillsDataset, id, skillTypes, searchRandom));
subSkills = subSkills.filter(s => s);
return subSkills;
} else {
return [];
}
} else {
return [];
}
}
/*
* 正式流程
*/
officialAPI.forEach(function (lang) {
console.log("正在读取官方 %s 信息", lang.code);
const cardJson = fs.readFileSync("official-API/" + lang.code + "-card.json", 'utf-8'); //使用同步读取怪物
const cardJsonObj = JSON.parse(cardJson);
const oCards = lang.cardOriginal = cardJsonObj.card;//将字符串转换为json对象
const monCards = lang.cards = [];
//const monCards = lang.cards = oCards.map(ocard=>new Card(ocard));
/*oCards.forEach((oCard, idx)=>{
let mid = oCard[0];
if (mid === idx) //原始怪物
{
monCards.push(new Card(oCard));
}else
{
const nCard = monCards[mid % 100000];
if (!nCard.specialVersion) nCard.specialVersion = {};
nCard.specialVersion[Math.floor(mid / 100000)] = new Card(oCard);
}
});*/
//为了减小数据文件容量,删掉一些用不上的,有的可以后面游戏内再重新加上
for (let cardIndex = 0; oCards[cardIndex][0] < 1e5; cardIndex++) {
const card = new Card(oCards[cardIndex]);
delete card.enemy; //不做地下城解析,用不上
delete card.onlyAssist; //数量太少了,游戏内再加
delete card.unk01;
delete card.unk02;
delete card.unk03;
delete card.unk04;
delete card.unk05;
delete card.unk06;
delete card.unk07;
delete card.unk08;
if (card.searchFlags.every(num => isNaN(num)))
delete card.searchFlags; //没有队长技能的,用不上
if (!card.syncAwakening)
delete card.syncAwakeningConditions; //没有同步觉醒
monCards.push(card);
}
//加入自定义的语言
lang.customName.forEach(function (lcode) {
console.log("正在读取自定义 " + lcode + " 信息");
const ljson = fs.readFileSync("custom/" + lcode + ".json", 'utf-8'); //使用同步读取
const ccard = JSON.parse(ljson);//将字符串转换为json对象
ccard.forEach(function (cm) { //每个文件内的名字循环
let m = monCards[cm.id];
if (m) {
if (!m.otLangName) //如果没有其他语言名称属性,则添加一个对象属性
m.otLangName = {};
m.otLangName[lcode] = cm.name;
if (!m.otTags) //如果没有其他语言名称属性,则添加一个对象属性
m.otTags = [];
let newTags = Array.from(new Set(cm.tags));
newTags = newTags.filter(tag => !m.altName.includes(tag) && !m.otTags.includes(tag));
m.otTags.push(...newTags);
}
});
});
const skillJson = fs.readFileSync("official-API/" + lang.code + "-skill.json", 'utf-8'); //使用同步读取技能
const skillJsonObj = JSON.parse(skillJson);
const oSkills = lang.skillOriginal = skillJsonObj.skill;//将字符串转换为json对象
lang.skills = oSkills.map((oc, idx) => new Skill(idx, oc)); //每一项生成分析对象
lang.cards.forEach((m, cardId, cardArr) => {
let henshinTo = null;
const henshinSkill = getActuallySkills(lang.skills, m.activeSkillId, [202, 236]);
if (henshinSkill.length) {
const skill = henshinSkill[0];
henshinTo = skill.params.distinct();
if (Array.isArray(henshinTo)) {
m.henshinTo = henshinTo;
//变身来源可能有多个,因此将变身来源修改为数组
for (let toId of henshinTo) {
let henshinFrom = cardArr[toId].henshinFrom;
if (Array.isArray(henshinFrom)) {
henshinFrom.push(cardId);
} else {
cardArr[toId].henshinFrom = [cardId];
}
}
}
}
});
//const eskillJson = fs.readFileSync("official-API/" + lang.code +"-enemy_skill.json", 'utf-8'); //使用同步读取技能
//const eskillJsonObj = JSON.parse(eskillJson);
//lang.enemy_skills = eskillJsonObj.enemy_skills;
});
//加入其他服务器相同角色的名字
for (let li = 0; li < officialAPI.length; li++) {
const otherLangs = officialAPI.concat(); //复制一份原始数组,储存其他语言
const lang = otherLangs.splice(li, 1)[0]; //删掉并取得当前的语言
const langCard = lang.cards;
const langCardCount = langCard.length;
for (let mi = 0; mi < langCardCount; mi++) {
const m = langCard[mi];
const name = m.name; //当前语言的名字
//名字对象
otherLangs.forEach((otLang) => {
let _m = otLang.cards[mi]; //获得这种其他语言的当前这个怪物数据
let isSame = false; //与原语言怪物是否是同一只
const l1 = lang.code, l2 = otLang.code;
if (
l1 == 'ja' && (l2 == 'en' || l2 == 'ko') ||
l2 == 'ja' && (l1 == 'en' || l1 == 'ko')
) { //当同id两者不同,日服和英韩服比较时的一些人工确认相同的特殊id差异卡片
const langIsJa = l1 == 'ja' ? true : false; //原始语言是否是日语
let diff = 0; //日语和其它语言的id差异
switch (true) {
case (langIsJa && mi >= 671 && mi <= 680) ||
(!langIsJa && mi >= 1049 && mi <= 1058):
//神罗 日服 671-680 等于英韩服 1049-1058
diff = 378;
break;
case (langIsJa && mi >= 669 && mi <= 670) ||
(!langIsJa && mi >= 934 && mi <= 935):
//神罗 日服 669-670 等于英韩服 934-935
diff = 265;
break;
case (langIsJa && mi >= 924 && mi <= 935) ||
(!langIsJa && mi >= 669 && mi <= 680):
//蝙蝠侠 日服 924-935 等于英韩服 669-680
diff = -255;
break;
case (langIsJa && mi >= 1049 && mi <= 1058) ||
(!langIsJa && mi >= 924 && mi <= 933):
//蝙蝠侠 日服 1049-1058 等于英韩服 924-933
diff = -125;
break;
}
if (diff != 0) {
_m = langIsJa ? otLang.cards[mi + diff] : otLang.cards[mi - diff];
isSame = true;
}
}
if (!isSame) isSame = sameCard(m, _m); //不属于特殊指定区间的情况下,判断与原语言怪物是否是同一只
if (_m && isSame) //如果有这个怪物,且与原语言怪物是同一只
{
const otName = _m.name;
if (/^(?:\?+|\*+|초월\s*\?+)/i.test(otName)) //名字以问号、星号、韩文的问号开头
{
return; //跳过
} else {
if (!m.otLangName) //如果没有其他语言名称属性,则添加一个对象属性
m.otLangName = {};
m.otLangName[otLang.code] = otName;
if (_m.otLangName) { //增加储存当前语言的全部其他语言
Object.entries(_m.otLangName).forEach(entry => {
const lcode = entry[0];
if (lcode != l1 && !Object.keys(m.otLangName).includes(lcode)) //如果不是本来的的语言
m.otLangName[lcode] = entry[1];
});
}
}
if (!m.otTags) //如果没有其他语言标签属性,则添加一个数组属性
m.otTags = [];
let otTags = Array.from(new Set(_m.otTags ? _m.altName.concat(_m.otTags) : _m.altName));
otTags = otTags.filter(tag => !m.altName.includes(tag) && !m.otTags.includes(tag));
m.otTags.push(...otTags);
}
});
}
}
var newCkeyObjs = officialAPI.map(lang => {
const lcode = lang.code;
const cardStr = JSON.stringify(lang.cards);
const skillStr = JSON.stringify(lang.skills);
//写入Cards
fs.writeFile(`./mon_${lcode}.json`, cardStr, function (err) {
if (err) {
console.error(err);
}
console.log(`mon_${lcode}.json 导出成功`);
});
//写入Skills
fs.writeFile(`./skill_${lcode}.json`, skillStr, function (err) {
if (err) {
console.error(err);
}
console.log(`skill_${lcode}.json 导出成功`);
});
//const enemy_skillsStr = lang.enemy_skills;
//写入enemy_skills
//fs.writeFile(`./enemy_skills_${lcode}.json`,enemy_skillsStr,function(err){
// if(err){
// console.error(err);
// }
// console.log(`enemy_skills_${lcode}.json 导出成功`);
//});
const cardHash = crypto.createHash('md5');
const skillHash = crypto.createHash('md5');
cardHash.update(cardStr, 'utf8');
skillHash.update(skillStr, 'utf8');
const ckeyOutObj = {
code: lcode,
ckey: {
card: cardHash.digest('hex'),
skill: skillHash.digest('hex'),
},
updateTime: runDate.getTime(),
};
return ckeyOutObj;
});
//读取旧的ckeyObj
var ckeyObjs;
fs.readFile('./ckey.json', 'utf-8', function (err, data) {
if (err) { //如果读取错误,直接使用全新ckey
ckeyObjs = newCkeyObjs;
} else { //如果读取正确,则读入JSON,并判断是否和旧有的一致
ckeyObjs = JSON.parse(data);
for (let ci = 0; ci < ckeyObjs.length; ci++) {
const oldCkey = ckeyObjs[ci];
const newCkey = newCkeyObjs.find(nckey => nckey.code === oldCkey.code);
if (newCkey && (oldCkey.ckey.card != newCkey.ckey.card || oldCkey.ckey.skill != newCkey.ckey.skill)) {
ckeyObjs[ci] = newCkey;
}
}
}
fs.writeFile('./ckey.json', JSON.stringify(ckeyObjs, null, '\t'), function (err) {
if (err) {
console.error(err);
}
console.log('ckey.json 导出成功');
});
});