✨ Data convertion
This commit is contained in:
parent
0579a6b0ba
commit
8b847e0f9c
3 changed files with 380 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.vscode/
|
38
data/convert/31-0/melee.py
Executable file
38
data/convert/31-0/melee.py
Executable file
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env python3
|
||||
# # -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
with open("../../extraction/raw-31-0/data.cdb.json") as f:
|
||||
raw = json.load(f)
|
||||
with open("../../clean/31-0/main.zh.mo.json") as f:
|
||||
trans = json.load(f)
|
||||
|
||||
lines = raw["sheets"][1]["lines"]
|
||||
melee = []
|
||||
|
||||
for i in lines:
|
||||
if i["group"] == 4:
|
||||
melee.append(i)
|
||||
i["name"] = trans[i["name"]]["msgstr"][0]
|
||||
if "ambiantDesc" in i:
|
||||
i["ambiantDesc"] = trans[i["ambiantDesc"].strip()]["msgstr"][0]
|
||||
if "gameplayDesc" in i:
|
||||
i["gameplayDesc"] = trans[i["gameplayDesc"].strip()]["msgstr"][0]
|
||||
if i["props"]:
|
||||
|
||||
def replace_props(m):
|
||||
result = i["props"][m.group(1)]
|
||||
if isinstance(result, list):
|
||||
result = result[0]
|
||||
if not isinstance(result, str):
|
||||
result = str(result)
|
||||
return result
|
||||
|
||||
i["gameplayDesc"], _ = re.subn(
|
||||
r"::\+?(.*?)::", replace_props, i["gameplayDesc"]
|
||||
)
|
||||
|
||||
|
||||
print(json.dumps(melee, ensure_ascii=False))
|
341
data/convert/README.md
Normal file
341
data/convert/README.md
Normal file
|
@ -0,0 +1,341 @@
|
|||
# 数据转换
|
||||
|
||||
`data.cdb` 中的数据为 JSON 格式,随着死亡细胞版本的升级,里面的内容格式也会发生变化,因此比较好的处理方式是从中抽取需要的数据,保存为 SQLite 数据库文件,便于管理,也比较稳定。
|
||||
|
||||
以下是 `data.cdb` 中数据的解析:
|
||||
|
||||
- `sheets[1]["props"]["separatorTitles"]` 字符串数组,下面的 `group` 字段即为此数组的索引。
|
||||
- `sheets[1]["lines"]` 对象数组,其中为武器、技能等。例:
|
||||
- 双向弩弓塔:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": {
|
||||
"duration2": 0.09,
|
||||
"targetable": true,
|
||||
"dps": [45],
|
||||
"life": 100,
|
||||
"count": 2,
|
||||
"effectCD": 0.4
|
||||
},
|
||||
"gameplayDesc": "Tire sur ::count:: ennemis proches à la fois, chaque tir infligeant ::+dps:: DPS.",
|
||||
"moneyCost": 1750,
|
||||
"group": 0,
|
||||
"castCD": 10,
|
||||
"id": "HorizontalTurret",
|
||||
"icon": { "x": 1, "y": 0, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [{ "affix": "SuperPierce" }],
|
||||
"name": "Auto-balète double",
|
||||
"droppable": true,
|
||||
"tags": [
|
||||
{ "tag": "Ranged" },
|
||||
{ "tag": "HasBullets" },
|
||||
{ "tag": "Deployable" },
|
||||
{ "tag": "NeedPower" },
|
||||
{ "tag": "UnlockInPublicEvent" }
|
||||
],
|
||||
"tier1": "Tactic",
|
||||
"cellCost": 5
|
||||
}
|
||||
```
|
||||
- 步兵手雷:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": { "range": 4.5, "coolDown": 0.6, "power": [90] },
|
||||
"gameplayDesc": "Rapide à utiliser, mais inflige des dégâts modérés.",
|
||||
"moneyCost": 1250,
|
||||
"group": 1,
|
||||
"castCD": 4,
|
||||
"id": "FastGrenade",
|
||||
"icon": { "x": 6, "y": 8, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [{ "affix": "Oil" }],
|
||||
"name": "Grenade d'infanterie",
|
||||
"droppable": true,
|
||||
"tags": [
|
||||
{ "tag": "Ranged" },
|
||||
{ "tag": "Explosive" },
|
||||
{ "tag": "ShortCooldown" },
|
||||
{ "tag": "UnlockInPublicEvent" }
|
||||
],
|
||||
"tier1": "Brutality",
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- 稻草人装束:无瑕:
|
||||
```json
|
||||
{
|
||||
"props": { "movePauseMul": 99999 },
|
||||
"genTags": 544,
|
||||
"pfCost": 1,
|
||||
"blueprints": [],
|
||||
"maxPerRoom": 0,
|
||||
"group": 2,
|
||||
"canBeElite": false,
|
||||
"mobTags": [],
|
||||
"index": 107,
|
||||
"id": "Scarecrow",
|
||||
"weight": 500,
|
||||
"icon": { "x": 44, "y": 23, "file": "cardIcons.png", "size": 24 },
|
||||
"life": 500000,
|
||||
"name": "Scarecrow",
|
||||
"minPfHeight": 0,
|
||||
"minPfSize": 0,
|
||||
"metaItems": [],
|
||||
"maxPerPlatform": 0,
|
||||
"score": 0,
|
||||
"flesh1": 11562569,
|
||||
"skill": []
|
||||
}
|
||||
```
|
||||
- 死亡之球:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": {
|
||||
"speed": 0.11,
|
||||
"power": 50,
|
||||
"dps": 125,
|
||||
"count": 6,
|
||||
"distance": 25,
|
||||
"size": 2,
|
||||
"tick": 0.18,
|
||||
"duration": 12
|
||||
},
|
||||
"gameplayDesc": "Crée une orbe dévastatrice qui se déplace lentement.",
|
||||
"moneyCost": 1750,
|
||||
"group": 3,
|
||||
"castCD": 20,
|
||||
"id": "SlowOrb",
|
||||
"icon": { "x": 13, "y": 0, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [{ "affix": "DoubleSpeed" }],
|
||||
"name": "Orbe de mort",
|
||||
"droppable": true,
|
||||
"tags": [{ "tag": "Ranged" }],
|
||||
"tier1": "Survival",
|
||||
"cellCost": 50
|
||||
}
|
||||
```
|
||||
- 生锈的刀
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": {},
|
||||
"moneyCost": 1,
|
||||
"group": 4,
|
||||
"castCD": 0,
|
||||
"ambiantDesc": "Peut servir à tuer des gens.",
|
||||
"id": "StartSword",
|
||||
"icon": { "x": 18, "y": 0, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Epée rouillée",
|
||||
"droppable": false,
|
||||
"tags": [{ "tag": "NoCritical" }, { "tag": "RustyItem" }],
|
||||
"tier1": "Brutality",
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- 初学者弓箭:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": { "ammo": 6 },
|
||||
"gameplayDesc": "Les munitions reviennent quand vous achevez les ennemis.",
|
||||
"moneyCost": 1,
|
||||
"group": 5,
|
||||
"castCD": 0,
|
||||
"ambiantDesc": "C'est le jouet du fils du geolier. On doit bien pouvoir tuer quelques trucs avec ça.",
|
||||
"id": "StartBow",
|
||||
"icon": { "x": 0, "y": 1, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Arc du fils du geolier",
|
||||
"droppable": false,
|
||||
"tags": [
|
||||
{ "tag": "Ranged" },
|
||||
{ "tag": "NoCritical" },
|
||||
{ "tag": "HasBullets" },
|
||||
{ "tag": "LimitedAmmo" },
|
||||
{ "tag": "RustyItem" }
|
||||
],
|
||||
"tier1": "Tactic",
|
||||
```
|
||||
- 老木盾:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": {},
|
||||
"gameplayDesc": "Maintenir pour absorber une partie des dégâts.\nAppuyer brièvement pour tenter une {parade@PA} et annuler les dégâts.",
|
||||
"moneyCost": 1,
|
||||
"group": 6,
|
||||
"castCD": 0,
|
||||
"id": "StartShield",
|
||||
"icon": { "x": 0, "y": 3, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Vieux bouclier en bois",
|
||||
"droppable": false,
|
||||
"tags": [
|
||||
{ "tag": "Shield" },
|
||||
{ "tag": "NegligibleDamage" },
|
||||
{ "tag": "RustyItem" }
|
||||
],
|
||||
"tier1": "Survival",
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- 囚者颈环:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": {},
|
||||
"moneyCost": 1,
|
||||
"group": 7,
|
||||
"castCD": 0,
|
||||
"ambiantDesc": "Rien de notable, si ce n'est une odeur persistante de rat crevé.",
|
||||
"id": "PrisonerCloth",
|
||||
"icon": { "x": 1, "y": 4, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Collier de prisonnier",
|
||||
"droppable": false,
|
||||
"tags": [{ "tag": "NoDamage" }],
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- 钥匙:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": { "highActivationPriority": true },
|
||||
"gameplayDesc": "Ouvre les portes verrouillées (original, non ?)",
|
||||
"moneyCost": 0,
|
||||
"group": 8,
|
||||
"castCD": 0,
|
||||
"id": "GenericKey",
|
||||
"icon": { "x": 0, "y": 0, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Clé",
|
||||
"droppable": false,
|
||||
"tags": [{ "tag": "Key" }],
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- 藤蔓符文:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": {},
|
||||
"gameplayDesc": "Cette rune {permanente@PE} permet de faire pousser des vignes grimpantes.",
|
||||
"moneyCost": 0,
|
||||
"group": 9,
|
||||
"castCD": 0,
|
||||
"id": "LadderKey",
|
||||
"icon": { "x": 5, "y": 3, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Rune des vignes",
|
||||
"droppable": false,
|
||||
"tags": [{ "tag": "MetaKey" }],
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- 威力卷轴:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": { "highActivationPriority": true },
|
||||
"gameplayDesc": "Améliore l'une de vos 3 caractéristiques au choix !",
|
||||
"moneyCost": 2500,
|
||||
"group": 10,
|
||||
"castCD": 0,
|
||||
"id": "AnyUp",
|
||||
"icon": { "x": 11, "y": 2, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Parchemin de puissance",
|
||||
"droppable": false,
|
||||
"tags": [{ "tag": "TierUpgrade" }],
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- 贤者之石碎片:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": {
|
||||
"power": 75000,
|
||||
"disableFloatAnim": true,
|
||||
"chance": 0,
|
||||
"highActivationPriority": true
|
||||
},
|
||||
"gameplayDesc": "Vous êtes officiellement la créature la plus riche de l'île. Ce petit bijou sans la moindre imperfection vaut ::$power::{iconCoin@img} !",
|
||||
"moneyCost": 0,
|
||||
"group": 11,
|
||||
"castCD": 0,
|
||||
"id": "LegendGem",
|
||||
"icon": { "x": 17, "y": 11, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Fragment de Pierre Philosophale",
|
||||
"droppable": false,
|
||||
"tags": [],
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- 杀戮天性:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": {
|
||||
"scaledValueCap": 3,
|
||||
"actcdrIncPerTier": 0.11,
|
||||
"actcdr": 0.4
|
||||
},
|
||||
"gameplayDesc": "Réduit les délais de réutilisation des compétences de ::actcdr:: sec pour chaque ennemi tué au corps à corps.",
|
||||
"moneyCost": 0,
|
||||
"group": 12,
|
||||
"castCD": 0,
|
||||
"id": "P_CDR_Kill",
|
||||
"icon": { "x": 1, "y": 13, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Inspiration meurtrière",
|
||||
"droppable": true,
|
||||
"tags": [],
|
||||
"tier1": "Brutality",
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- 经典装束:
|
||||
```json
|
||||
{
|
||||
"synergy": [],
|
||||
"props": { "revealedAtStart": true },
|
||||
"gameplayDesc": "Avec elle, vous avez fait (et ferez encore) les 400 coups.",
|
||||
"moneyCost": 0,
|
||||
"group": 13,
|
||||
"castCD": 0,
|
||||
"id": "PrisonerDefault",
|
||||
"icon": { "x": 13, "y": 14, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Tenue classique",
|
||||
"droppable": false,
|
||||
"tags": [],
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- 饮血者:
|
||||
```json
|
||||
{
|
||||
"synergy": [{ "tag": "Bleed", "trigger": false }],
|
||||
"props": { "prct": 0.03 },
|
||||
"gameplayDesc": "Every hit against a bleeding target heals you for ::prct::% of your max health. ",
|
||||
"moneyCost": 0,
|
||||
"group": 14,
|
||||
"castCD": 0,
|
||||
"id": "ASP_BloodDrinker",
|
||||
"icon": { "x": 2, "y": 19, "file": "cardIcons.png", "size": 24 },
|
||||
"legendAffixes": [],
|
||||
"name": "Blood Drinker",
|
||||
"droppable": true,
|
||||
"tags": [{ "tag": "NeedManualUnlock" }],
|
||||
"cellCost": 0
|
||||
}
|
||||
```
|
||||
- `group` 为 15 的是 `BossRushStatueUnlock`,意义不明
|
||||
|
||||
先做近战武器。在 `melee.py` 中提取了所有近战数据。数据的 `name`、`gameplayDesc` 和 `ambiantDesc` 需要翻译。其中 `name` 一定存在,其余两者不一定存在;这两者有可能有多余的空格,所以需要去掉多余的空格;`gameplayDesc` 中有 `::duration::` 格式的部分,对应的值在 `props` 属性中,需要进行替换。
|
Loading…
Reference in a new issue