This commit is contained in:
qwerdvd 2023-10-30 14:31:15 +08:00
parent f59c23288e
commit acab733bd8
No known key found for this signature in database
GPG Key ID: A3AF89C783404769
74 changed files with 111215 additions and 0 deletions

164
.gitignore vendored Normal file
View File

@ -0,0 +1,164 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.ruff_cache

1
README.md Normal file
View File

@ -0,0 +1 @@
# StarRailDamageCal

395
pdm.lock generated Normal file
View File

@ -0,0 +1,395 @@
# This file is @generated by PDM.
# It is not intended for manual editing.
[metadata]
groups = ["default", "test", "lint"]
cross_platform = true
static_urls = false
lock_version = "4.3"
content_hash = "sha256:1b338e97a2e31cf80be528667db03a0aaf04dec9a222fc70c4bb9c326736b754"
[[package]]
name = "anyio"
version = "4.0.0"
requires_python = ">=3.8"
summary = "High level compatibility layer for multiple asynchronous event loop implementations"
dependencies = [
"exceptiongroup>=1.0.2; python_version < \"3.11\"",
"idna>=2.8",
"sniffio>=1.1",
]
files = [
{file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"},
{file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"},
]
[[package]]
name = "certifi"
version = "2023.7.22"
requires_python = ">=3.6"
summary = "Python package for providing Mozilla's CA Bundle."
files = [
{file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"},
{file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
]
[[package]]
name = "colorama"
version = "0.4.6"
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
summary = "Cross-platform colored terminal text."
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "coverage"
version = "7.3.2"
requires_python = ">=3.8"
summary = "Code coverage measurement for Python"
files = [
{file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"},
{file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"},
{file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"},
{file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"},
{file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"},
{file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"},
{file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"},
{file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"},
{file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"},
{file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"},
{file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"},
{file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"},
{file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"},
{file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"},
{file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"},
{file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"},
{file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"},
{file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"},
{file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"},
{file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"},
{file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"},
{file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"},
{file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"},
{file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"},
{file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"},
{file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"},
{file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"},
{file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"},
{file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"},
{file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"},
{file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"},
{file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"},
{file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"},
{file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"},
{file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"},
{file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"},
{file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"},
{file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"},
{file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"},
{file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"},
{file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"},
{file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"},
{file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"},
{file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"},
{file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"},
{file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"},
{file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"},
{file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"},
{file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"},
{file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"},
{file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"},
{file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"},
]
[[package]]
name = "coverage"
version = "7.3.2"
extras = ["toml"]
requires_python = ">=3.8"
summary = "Code coverage measurement for Python"
dependencies = [
"coverage==7.3.2",
"tomli; python_full_version <= \"3.11.0a6\"",
]
files = [
{file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"},
{file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"},
{file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"},
{file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"},
{file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"},
{file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"},
{file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"},
{file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"},
{file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"},
{file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"},
{file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"},
{file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"},
{file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"},
{file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"},
{file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"},
{file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"},
{file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"},
{file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"},
{file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"},
{file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"},
{file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"},
{file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"},
{file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"},
{file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"},
{file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"},
{file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"},
{file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"},
{file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"},
{file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"},
{file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"},
{file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"},
{file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"},
{file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"},
{file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"},
{file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"},
{file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"},
{file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"},
{file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"},
{file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"},
{file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"},
{file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"},
{file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"},
{file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"},
{file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"},
{file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"},
{file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"},
{file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"},
{file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"},
{file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"},
{file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"},
{file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"},
{file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"},
]
[[package]]
name = "exceptiongroup"
version = "1.1.3"
requires_python = ">=3.7"
summary = "Backport of PEP 654 (exception groups)"
files = [
{file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"},
{file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"},
]
[[package]]
name = "h11"
version = "0.14.0"
requires_python = ">=3.7"
summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
files = [
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
]
[[package]]
name = "httpcore"
version = "0.18.0"
requires_python = ">=3.8"
summary = "A minimal low-level HTTP client."
dependencies = [
"anyio<5.0,>=3.0",
"certifi",
"h11<0.15,>=0.13",
"sniffio==1.*",
]
files = [
{file = "httpcore-0.18.0-py3-none-any.whl", hash = "sha256:adc5398ee0a476567bf87467063ee63584a8bce86078bf748e48754f60202ced"},
{file = "httpcore-0.18.0.tar.gz", hash = "sha256:13b5e5cd1dca1a6636a6aaea212b19f4f85cd88c366a2b82304181b769aab3c9"},
]
[[package]]
name = "httpx"
version = "0.25.0"
requires_python = ">=3.8"
summary = "The next generation HTTP client."
dependencies = [
"certifi",
"httpcore<0.19.0,>=0.18.0",
"idna",
"sniffio",
]
files = [
{file = "httpx-0.25.0-py3-none-any.whl", hash = "sha256:181ea7f8ba3a82578be86ef4171554dd45fec26a02556a744db029a0a27b7100"},
{file = "httpx-0.25.0.tar.gz", hash = "sha256:47ecda285389cb32bb2691cc6e069e3ab0205956f681c5b2ad2325719751d875"},
]
[[package]]
name = "idna"
version = "3.4"
requires_python = ">=3.5"
summary = "Internationalized Domain Names in Applications (IDNA)"
files = [
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
]
[[package]]
name = "iniconfig"
version = "2.0.0"
requires_python = ">=3.7"
summary = "brain-dead simple config-ini parsing"
files = [
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
[[package]]
name = "msgspec"
version = "0.18.4"
requires_python = ">=3.8"
summary = "A fast serialization and validation library, with builtin support for JSON, MessagePack, YAML, and TOML."
files = [
{file = "msgspec-0.18.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4d24a291a3c94a7f5e26e8f5ef93e72bf26c10dfeed4d6ae8fc87ead02f4e265"},
{file = "msgspec-0.18.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9714b78965047638c01c818b4b418133d77e849017de17b0655ee37b714b47a6"},
{file = "msgspec-0.18.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:241277eed9fd91037372519fca62aecf823f7229c1d351030d0be5e3302580c1"},
{file = "msgspec-0.18.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d08175cbb55c1a87dd258645dce6cd00705d6088bf88e7cf510a9d5c24b0720b"},
{file = "msgspec-0.18.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:da13a06e77d683204eee3b134b08ecd5e4759a79014027b1bcd7a12c614b466d"},
{file = "msgspec-0.18.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73e70217ff5e4ac244c8f1b0769215cbc81e1c904e135597a5b71162857e6c27"},
{file = "msgspec-0.18.4-cp310-cp310-win_amd64.whl", hash = "sha256:dc25e6100026f5e1ecb5120150f4e78beb909cbeb0eb724b9982361b75c86c6b"},
{file = "msgspec-0.18.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e14287c3405093645b3812e3436598edd383b9ed724c686852e65d569f39f953"},
{file = "msgspec-0.18.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:acdcef2fccfff02f80ac8673dbeab205c288b680d81e05bfb5ae0be6b1502a7e"},
{file = "msgspec-0.18.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b052fd7d25a8aa2ffde10126ee1d97b4c6f3d81f3f3ab1258ff759a2bd794874"},
{file = "msgspec-0.18.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:826dcb0dfaac0abbcf3a3ae991749900671796eb688b017a69a82bde1e624662"},
{file = "msgspec-0.18.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:86800265f87f192a0daefe668e0a9634c35bf8af94b1f297e1352ac62d2e26da"},
{file = "msgspec-0.18.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:227fee75a25080a8b3677cdd95b9c0c3652e27869004a084886c65eb558b3dd6"},
{file = "msgspec-0.18.4-cp311-cp311-win_amd64.whl", hash = "sha256:828ef92f6654915c36ef6c7d8fec92404a13be48f9ff85f060e73b30299bafe1"},
{file = "msgspec-0.18.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8476848f4937da8faec53700891694df2e412453cb7445991f0664cdd1e2dd16"},
{file = "msgspec-0.18.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f668102958841c5bbd3ba7cf569a65d17aa3bdcf22124f394dfcfcf53cc5a9b9"},
{file = "msgspec-0.18.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc2405dba5af6478dedd3512bb92197b6f9d1bc0095655afbe9b54d7a426f19f"},
{file = "msgspec-0.18.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99f3c13569a5add0980b0d8c6e0bd94a656f6363b26107435b3091df979d228"},
{file = "msgspec-0.18.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8a198409f672f93534c9c36bdc9eea9fb536827bd63ea846882365516a961356"},
{file = "msgspec-0.18.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e21bc5aae6b80dfe4eb75dc1bb29af65483f967d5522e9e3812115a0ba285cac"},
{file = "msgspec-0.18.4-cp312-cp312-win_amd64.whl", hash = "sha256:44d551aee1ec8aa2d7b64762557c266bcbf7d5109f2246955718d05becc509d6"},
{file = "msgspec-0.18.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bbbc08d59f74de5791bda63569f26a35ae1dd6bd20c55c3ceba5567b0e5a8ef1"},
{file = "msgspec-0.18.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87bc01949a35970398f5267df8ed4189c340727bb6feec99efdb9969dd05cf30"},
{file = "msgspec-0.18.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96ccaef83adc0ce96d95328a03289cd5aead4fe400aac21fbe2008855a124a01"},
{file = "msgspec-0.18.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6229dd49438d81ed7a3470e3cbc9646b1cc1b120d415a1786df880dabb1d1c4"},
{file = "msgspec-0.18.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:55e578fd921c88de0d3a209fe5fd392bb66623924c6525b42cea37c72bf8d558"},
{file = "msgspec-0.18.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e95bd0a946b5b7206f27c0f654f490231c9ad5e5a4ff65af8c986f5114dfaf0e"},
{file = "msgspec-0.18.4-cp38-cp38-win_amd64.whl", hash = "sha256:7e95817021db96c43fd81244228e185b13b085cca3d5169af4e2dfe3ff412954"},
{file = "msgspec-0.18.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:847d79f6f0b698671ff390aa5a66e207108f2c23b077ef9314ca4fe7819fa4ec"},
{file = "msgspec-0.18.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e4294158c233884f3b3220f0e96a30d3e916a4781f9502ae6d477bd57bbc80ad"},
{file = "msgspec-0.18.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deb11ba2709019192636042df5c8db8738e45946735627021b7e7934714526e4"},
{file = "msgspec-0.18.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b01efbf80a987a99e9079257c893c026dc661d4cd05caa1f7eabf4accc7f1fbc"},
{file = "msgspec-0.18.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:991aa3c76d1b1ec84e840d0b3c96692af834e1f8a1e1a3974cbd189eaf0f2276"},
{file = "msgspec-0.18.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8064908ddb3d95d3261aaca48fd38abb16ccf59dc3f2d01eb4e04591fc1e9bd4"},
{file = "msgspec-0.18.4-cp39-cp39-win_amd64.whl", hash = "sha256:5f446f16ea57d70cceec29b7cb85ec0b3bea032e3dec316806e38575ea3a69b4"},
{file = "msgspec-0.18.4.tar.gz", hash = "sha256:cb62030bd6b1a00b01a2fcb09735016011696304e6b1d3321e58022548268d3e"},
]
[[package]]
name = "packaging"
version = "23.2"
requires_python = ">=3.7"
summary = "Core utilities for Python packages"
files = [
{file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
]
[[package]]
name = "pluggy"
version = "1.3.0"
requires_python = ">=3.8"
summary = "plugin and hook calling mechanisms for python"
files = [
{file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"},
{file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"},
]
[[package]]
name = "pytest"
version = "7.4.3"
requires_python = ">=3.7"
summary = "pytest: simple powerful testing with Python"
dependencies = [
"colorama; sys_platform == \"win32\"",
"exceptiongroup>=1.0.0rc8; python_version < \"3.11\"",
"iniconfig",
"packaging",
"pluggy<2.0,>=0.12",
"tomli>=1.0.0; python_version < \"3.11\"",
]
files = [
{file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"},
{file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"},
]
[[package]]
name = "pytest-asyncio"
version = "0.21.1"
requires_python = ">=3.7"
summary = "Pytest support for asyncio"
dependencies = [
"pytest>=7.0.0",
]
files = [
{file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"},
{file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"},
]
[[package]]
name = "pytest-cov"
version = "4.1.0"
requires_python = ">=3.7"
summary = "Pytest plugin for measuring coverage."
dependencies = [
"coverage[toml]>=5.2.1",
"pytest>=4.6",
]
files = [
{file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
{file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
]
[[package]]
name = "ruff"
version = "0.1.3"
requires_python = ">=3.7"
summary = "An extremely fast Python linter, written in Rust."
files = [
{file = "ruff-0.1.3-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:b46d43d51f7061652eeadb426a9e3caa1e0002470229ab2fc19de8a7b0766901"},
{file = "ruff-0.1.3-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:b8afeb9abd26b4029c72adc9921b8363374f4e7edb78385ffaa80278313a15f9"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca3cf365bf32e9ba7e6db3f48a4d3e2c446cd19ebee04f05338bc3910114528b"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4874c165f96c14a00590dcc727a04dca0cfd110334c24b039458c06cf78a672e"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eec2dd31eed114e48ea42dbffc443e9b7221976554a504767ceaee3dd38edeb8"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dc3ec4edb3b73f21b4aa51337e16674c752f1d76a4a543af56d7d04e97769613"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e3de9ed2e39160800281848ff4670e1698037ca039bda7b9274f849258d26ce"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c595193881922cc0556a90f3af99b1c5681f0c552e7a2a189956141d8666fe8"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f75e670d529aa2288cd00fc0e9b9287603d95e1536d7a7e0cafe00f75e0dd9d"},
{file = "ruff-0.1.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:76dd49f6cd945d82d9d4a9a6622c54a994689d8d7b22fa1322983389b4892e20"},
{file = "ruff-0.1.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:918b454bc4f8874a616f0d725590277c42949431ceb303950e87fef7a7d94cb3"},
{file = "ruff-0.1.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d8859605e729cd5e53aa38275568dbbdb4fe882d2ea2714c5453b678dca83784"},
{file = "ruff-0.1.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0b6c55f5ef8d9dd05b230bb6ab80bc4381ecb60ae56db0330f660ea240cb0d4a"},
{file = "ruff-0.1.3-py3-none-win32.whl", hash = "sha256:3e7afcbdcfbe3399c34e0f6370c30f6e529193c731b885316c5a09c9e4317eef"},
{file = "ruff-0.1.3-py3-none-win_amd64.whl", hash = "sha256:7a18df6638cec4a5bd75350639b2bb2a2366e01222825562c7346674bdceb7ea"},
{file = "ruff-0.1.3-py3-none-win_arm64.whl", hash = "sha256:12fd53696c83a194a2db7f9a46337ce06445fb9aa7d25ea6f293cf75b21aca9f"},
{file = "ruff-0.1.3.tar.gz", hash = "sha256:3ba6145369a151401d5db79f0a47d50e470384d0d89d0d6f7fab0b589ad07c34"},
]
[[package]]
name = "sniffio"
version = "1.3.0"
requires_python = ">=3.7"
summary = "Sniff out which async library your code is running under"
files = [
{file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"},
{file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"},
]
[[package]]
name = "tomli"
version = "2.0.1"
requires_python = ">=3.7"
summary = "A lil' TOML parser"
files = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]

67
pyproject.toml Normal file
View File

@ -0,0 +1,67 @@
[project]
name = "StarRailDamageCal"
version = "0.1.0"
description = "For StarRail Role Damage Cal"
authors = [
{name = "qwerdvd", email = "105906879+qwerdvd@users.noreply.github.com"},
]
dependencies = [
"msgspec>=0.18.4",
"httpx>=0.25.0",
]
requires-python = ">=3.8"
readme = "README.md"
license = {text = "MIT"}
packages = [{ include = "StarRailDamageCal" }]
[tool.ruff]
select = ["ALL"]
ignore = [
"E402",
"B008",
"F403",
"F405",
"RET505",
"N816",
"N815",
"ANN101",
"N806",
"FA100",
"PLR",
"C901",
"N803",
"N802",
"ANN",
"ERA001",
"E501",
"D",
"N999",
"ARG",
"COM812",
"N801",
"ISC"
]
line-length = 88
target-version = "py38"
ignore-init-module-imports = true
[tool.pdm.dev-dependencies]
test = [
"pytest>=7.4.3",
"pytest-asyncio>=0.21.1",
"pytest-cov>=4.1.0",
]
lint = [
"ruff>=0.1.3",
]
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[tool.pyright]
reportShadowedImports = false
pythonVersion = "3.8"
pythonPlatform = "All"
executionEnvironments = [{ root = "./starrail_damage_cal/" }]

View File

@ -0,0 +1 @@
from .cal_damage import DamageCal # noqa: F401

View File

@ -0,0 +1,107 @@
from typing import Dict
from msgspec import convert
from starrail_damage_cal.damage.Avatar import AvatarInstance
from starrail_damage_cal.exception import (
CharNameError,
MihomoRequestError,
NotInCharacterShowcaseError,
)
from starrail_damage_cal.map.name_covert import alias_to_char_name, name_to_avatar_id
from starrail_damage_cal.mihomo.models import MihomoData
from starrail_damage_cal.mono.Character import Character
from starrail_damage_cal.to_data import api_to_dict
class DamageCal:
@classmethod
async def cal_info(cls, char_data: Dict):
char = Character(char_data)
await char.get_equipment_info()
await char.get_char_attribute_bonus()
await char.get_relic_info()
avatar = AvatarInstance(char)
return await avatar.get_damage_info()
@classmethod
async def get_damage_data_by_uid(cls, uid: str, avatar_name: str):
char_name = alias_to_char_name(avatar_name)
char_id = name_to_avatar_id(char_name)
if char_id == "":
raise CharNameError(char_name)
char_id_list, char_data_dict = await api_to_dict(uid)
if isinstance(char_id_list, str):
raise MihomoRequestError
if char_data_dict is None:
raise MihomoRequestError
if char_id not in char_id_list:
raise NotInCharacterShowcaseError
char_data = char_data_dict[char_id]
return await cls.cal_info(char_data)
@classmethod
async def get_damage_data_by_mihomo_raw(cls, mihomo_raw: Dict, avatar_name: str):
char_name = alias_to_char_name(avatar_name)
char_id = name_to_avatar_id(char_name)
if char_id == "":
raise CharNameError(char_name)
mihomo_data = convert(mihomo_raw, type=MihomoData)
char_id_list, char_data_dict = await api_to_dict(mihomo_raw=mihomo_data)
if isinstance(char_id_list, str):
raise MihomoRequestError
if char_data_dict is None:
raise MihomoRequestError
if char_id not in char_id_list:
raise NotInCharacterShowcaseError
char_data = char_data_dict[char_id]
return await cls.cal_info(char_data)
@classmethod
async def get_all_damage_data_by_mihomo_raw(cls, mihomo_raw: Dict):
mihomo_data = convert(mihomo_raw, type=MihomoData)
char_id_list, char_data_dict = await api_to_dict(mihomo_raw=mihomo_data)
if isinstance(char_id_list, str):
raise MihomoRequestError
if char_data_dict is None:
raise MihomoRequestError
damage_dict = {}
for char_id in char_id_list:
char_data = char_data_dict[char_id]
damage_dict[char_id] = await cls.cal_info(char_data)
return damage_dict
@classmethod
async def get_all_damage_data_by_uid(cls, uid: str):
char_id_list, char_data_dict = await api_to_dict(sr_uid=uid)
if isinstance(char_id_list, str):
raise MihomoRequestError
if char_data_dict is None:
raise MihomoRequestError
damage_dict = {}
for char_id in char_id_list:
char_data = char_data_dict[char_id]
damage_dict[char_id] = await cls.cal_info(char_data)
return damage_dict

View File

@ -0,0 +1,106 @@
import json
from pathlib import Path
from typing import Dict
from starrail_damage_cal.damage.AvatarDamage.AvatarDamage import AvatarDamage
from starrail_damage_cal.damage.Base.AvatarBase import BaseAvatarinfo
from starrail_damage_cal.damage.Base.model import DamageInstance
from starrail_damage_cal.damage.Relic.Relic import RelicSet, SingleRelic
from starrail_damage_cal.damage.Weapon.Weapon import Weapon
from starrail_damage_cal.mono.Character import Character
Excel_path = Path(__file__).parent
with Path.open(Excel_path / "Excel" / "SkillData.json", encoding="utf-8") as f:
skill_dict = json.load(f)
class AvatarInstance:
def __init__(self, raw_data: Character):
self.raw_data = DamageInstance(raw_data)
self.avatardamage = AvatarDamage.create(
self.raw_data.avatar,
self.raw_data.skill,
)
self.avatar = BaseAvatarinfo(self.raw_data.avatar)
self.weapon = Weapon.create(self.raw_data.weapon)
self.relic_set = RelicSet().create(self.raw_data.relic)
self.base_attr = self.cal_role_base_attr()
self.attribute_bonus: Dict[str, float] = {}
self.cal_relic_attr_add()
self.cal_avatar_attr_add()
self.cal_avatar_eidolon_add()
self.cal_weapon_attr_add()
def merge_attribute_bonus(self, add_attribute: Dict[str, float]):
for attribute in add_attribute:
if attribute in self.attribute_bonus:
self.attribute_bonus[attribute] += add_attribute[attribute]
else:
self.attribute_bonus[attribute] = add_attribute[attribute]
def cal_role_base_attr(self):
base_attr: Dict[str, float] = {}
avatar_attribute = self.avatar.avatar_attribute
for attr_name, attr_value in avatar_attribute.items():
if attr_name in base_attr:
base_attr[attr_name] += attr_value
else:
base_attr[attr_name] = attr_value
weapon_attribute = self.weapon.weapon_base_attribute
for attr_name, attr_value in weapon_attribute.items():
if attr_name in base_attr:
base_attr[attr_name] += attr_value
else:
base_attr[attr_name] = attr_value
return base_attr
def cal_relic_attr_add(self):
# 单件属性
for relic_type in self.relic_set.__dict__:
if type(self.relic_set.__dict__[relic_type]) == SingleRelic:
relic: SingleRelic = self.relic_set.__dict__[relic_type]
self.merge_attribute_bonus(relic.relic_attribute_bonus)
# 套装面板加成属性
for set_skill in self.relic_set.SetSkill:
self.merge_attribute_bonus(set_skill.relicSetAttribute)
def cal_avatar_eidolon_add(self):
self.merge_attribute_bonus(self.avatardamage.eidolon_attribute)
self.merge_attribute_bonus(self.avatardamage.extra_ability_attribute)
def cal_avatar_attr_add(self):
attribute_bonus = self.avatar.avatar_attribute_bonus
if attribute_bonus:
for bonus in attribute_bonus:
status_add = bonus.statusAdd
bonus_property = status_add.property_
value = status_add.value
if bonus_property in self.attribute_bonus:
self.attribute_bonus[bonus_property] += value
else:
self.attribute_bonus[bonus_property] = value
def cal_weapon_attr_add(self):
self.merge_attribute_bonus(self.weapon.weapon_attribute)
async def get_damage_info(self):
Ultra_Use = self.avatar.Ultra_Use()
self.attribute_bonus = await self.weapon.weapon_ability(
Ultra_Use,
self.base_attr,
self.attribute_bonus,
)
for set_skill in self.relic_set.SetSkill:
self.attribute_bonus = await set_skill.set_skill_ability(
self.base_attr,
self.attribute_bonus,
)
if self.attribute_bonus is None:
msg = "attribute_bonus is None"
raise Exception(msg) # noqa: TRY002
return await self.avatardamage.getdamage(self.base_attr, self.attribute_bonus)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,168 @@
import json
from abc import abstractmethod
from pathlib import Path
from typing import List, Tuple, Union
import msgspec
from msgspec import Struct
from starrail_damage_cal.damage.Base.model import (
DamageInstanceAvatar,
DamageInstanceSkill,
)
from starrail_damage_cal.damage.Base.SkillBase import BaseSkills
from starrail_damage_cal.excel.model import AvatarPromotionConfig
path = Path(__file__).parent.parent
with Path.open(path / "Excel" / "SkillData.json", encoding="utf-8") as f:
skill_dict = json.load(f)
class BaseAvatarAttribute(Struct):
attack: float
defence: float
hp: float
speed: float
CriticalChanceBase: float
CriticalDamageBase: float
BaseAggro: float
def items(self) -> List[Tuple[str, float]]:
return [
("attack", self.attack),
("defence", self.defence),
("hp", self.hp),
("speed", self.speed),
("CriticalChanceBase", self.CriticalChanceBase),
("CriticalDamageBase", self.CriticalDamageBase),
("BaseAggro", self.BaseAggro),
]
class BaseAvatarBuff:
@classmethod
def create(cls, char: DamageInstanceAvatar, skills: List[DamageInstanceSkill]):
cls.extra_ability_id = []
if char.extra_ability:
for extra_ability in char.extra_ability:
cls.extra_ability_id.append(extra_ability["extraAbilityId"])
return cls
@abstractmethod
async def Technique(self):
...
@abstractmethod
async def eidolons(self):
...
@abstractmethod
async def extra_ability(self):
...
class BaseAvatarinfo:
def __init__(self, char: DamageInstanceAvatar):
self.avatar_id = char.id_
self.avatar_level = char.level
self.avatar_rank = char.rank
self.avatar_element = char.element
self.avatar_promotion = char.promotion
self.avatar_attribute_bonus = char.attribute_bonus
self.avatar_extra_ability = char.extra_ability
self.avatar_attribute = self.get_attribute()
def get_attribute(self):
promotion = AvatarPromotionConfig.Avatar[str(self.avatar_id)][
str(self.avatar_promotion)
]
return BaseAvatarAttribute(
# 攻击力
attack=(
promotion.AttackBase.Value
+ promotion.AttackAdd.Value * (self.avatar_level - 1)
),
# 防御力
defence=(
promotion.DefenceBase.Value
+ promotion.DefenceAdd.Value * (self.avatar_level - 1)
),
# 血量
hp=(
promotion.HPBase.Value + promotion.HPAdd.Value * (self.avatar_level - 1)
),
# 速度
speed=promotion.SpeedBase.Value,
# 暴击率
CriticalChanceBase=promotion.CriticalChance.Value,
# 暴击伤害
CriticalDamageBase=promotion.CriticalDamage.Value,
# 嘲讽
BaseAggro=promotion.BaseAggro.Value,
)
def Ultra_Use(self):
skill_info = skill_dict[str(self.avatar_id)]["Ultra_Use"][0]
return msgspec.convert(skill_info, type=float)
class BaseAvatar:
def __init__(self, char: DamageInstanceAvatar, skills: List[DamageInstanceSkill]):
self.Skill = BaseSkills.create(char=char, skills=skills)
self.Buff = BaseAvatarBuff.create(char=char, skills=skills)
self.avatar_id = char.id_
self.avatar_level = char.level
self.avatar_rank = char.rank
self.avatar_element = char.element
self.avatar_promotion = char.promotion
self.avatar_attribute_bonus = char.attribute_bonus
self.avatar_extra_ability = char.extra_ability
self.avatar_attribute = self.get_attribute()
def get_attribute(self):
promotion = AvatarPromotionConfig.Avatar[str(self.avatar_id)][
str(self.avatar_promotion)
]
return BaseAvatarAttribute(
# 攻击力
attack=(
promotion.AttackBase.Value
+ promotion.AttackAdd.Value * (self.avatar_level - 1)
),
# 防御力
defence=(
promotion.DefenceBase.Value
+ promotion.DefenceAdd.Value * (self.avatar_level - 1)
),
# 血量
hp=(
promotion.HPBase.Value + promotion.HPAdd.Value * (self.avatar_level - 1)
),
# 速度
speed=promotion.SpeedBase.Value,
# 暴击率
CriticalChanceBase=promotion.CriticalChance.Value,
# 暴击伤害
CriticalDamageBase=promotion.CriticalDamage.Value,
# 嘲讽
BaseAggro=promotion.BaseAggro.Value,
)
def Skill_Info(self, skill_type: str):
skill_info = skill_dict[str(self.avatar_id)]["skillList"][skill_type]
return msgspec.convert(skill_info, type=List[Union[str, int]])
def Skill_num(self, skill: Union[str, int], skill_type: str):
skill_level = 0
if skill == "Normal":
skill_level = self.Skill.Normal_.level - 1
if skill == "BPSkill":
skill_level = self.Skill.BPSkill_.level - 1
if skill == "Ultra":
skill_level = self.Skill.Ultra_.level - 1
if skill == "Talent":
skill_level = self.Skill.Talent_.level - 1
skill_info = skill_dict[str(self.avatar_id)][skill_type][skill_level]
return msgspec.convert(skill_info, type=float)

View File

@ -0,0 +1,93 @@
from abc import abstractmethod
from typing import Dict
from starrail_damage_cal.damage.Base.model import DamageInstanceRelic
from starrail_damage_cal.logger import logger
from starrail_damage_cal.map.model.RelicSetSkill import RelicSetStatusAdd
from starrail_damage_cal.map.SR_MAP_PATH import RelicSetSkill
class SingleRelic:
def __init__(self, relic: DamageInstanceRelic):
self.raw_relic = relic
self.relic_id = relic.relicId
self.set_id = relic.SetId
self.relic_type = relic.Type
self.relic_level = relic.Level
self.relic_attribute_bonus: Dict[str, float] = {}
def get_attribute_(self):
# MainAffix
if self.raw_relic.MainAffix.Property in self.relic_attribute_bonus:
self.relic_attribute_bonus[
self.raw_relic.MainAffix.Property
] += self.raw_relic.MainAffix.Value
else:
self.relic_attribute_bonus[
self.raw_relic.MainAffix.Property
] = self.raw_relic.MainAffix.Value
# SubAffix
if self.raw_relic.SubAffixList:
for sub_affix in self.raw_relic.SubAffixList:
sub_affix_property = sub_affix.Property
value = sub_affix.Value
if sub_affix_property in self.relic_attribute_bonus:
self.relic_attribute_bonus[sub_affix_property] += value
else:
self.relic_attribute_bonus[sub_affix_property] = value
class BaseRelicSetSkill:
setId: int
pieces2: bool = False
pieces4: bool = False
def __init__(self, set_id: int, count: int):
self.setId = set_id
if count >= 2:
self.pieces2 = True
logger.info(f"Relic {set_id} 2 pieces set activated")
if count == 4:
self.pieces4 = True
logger.info(f"Relic {set_id} 4 pieces set activated")
self.relicSetAttribute = self.set_skill_property_ability()
@abstractmethod
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
...
@abstractmethod
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""战斗加成属性, 与 set_skill_property() 互斥"""
...
def set_skill_property_ability(self):
def add_relic_set_attribute(status_add: RelicSetStatusAdd):
set_property = status_add.Property
set_value = status_add.Value
if set_property != "":
relic_set_attribute[set_property] = (
relic_set_attribute.get(set_property, 0) + set_value
)
relic_set_attribute: Dict[str, float] = {}
if self.pieces2:
status_add = RelicSetSkill.RelicSet[str(self.setId)]["2"]
if status_add:
add_relic_set_attribute(status_add)
if self.pieces4:
status_add = RelicSetSkill.RelicSet[str(self.setId)]["4"]
if status_add:
add_relic_set_attribute(status_add)
return relic_set_attribute

View File

@ -0,0 +1,45 @@
import json
from pathlib import Path
from typing import List
from starrail_damage_cal.damage.Base.model import (
DamageInstanceAvatar,
DamageInstanceSkill,
)
path = Path(__file__).parent.parent
with Path.open(path / "Excel" / "SkillData.json", encoding="utf-8") as f:
skill_dict = json.load(f)
skill_types = {
"Normal": "Normal_",
"BPSkill": "BPSkill_",
"Ultra": "Ultra_",
"Maze": "Maze_",
"": "Talent_",
}
class SingleSkill:
def __init__(self, skill: DamageInstanceSkill):
self.id = skill.skillId
self.level = skill.skillLevel
class BaseSkills:
Normal_: SingleSkill
BPSkill_: SingleSkill
Ultra_: SingleSkill
Maze_: SingleSkill
Talent_: SingleSkill
@classmethod
def create(cls, char: DamageInstanceAvatar, skills: List[DamageInstanceSkill]):
for skill in skills:
skill_attack_type = skill.skillAttackType
if skill_attack_type not in skill_types:
msg = f"Unknown skillAttackType: {skill_attack_type}"
raise ValueError(msg)
setattr(cls, skill_types[skill_attack_type], SingleSkill(skill))
return cls

View File

@ -0,0 +1,74 @@
from abc import abstractmethod
from typing import Dict, List, Tuple
from msgspec import Struct
from starrail_damage_cal.damage.Base.model import DamageInstanceWeapon
from starrail_damage_cal.excel.model import EquipmentPromotionConfig
from starrail_damage_cal.map.SR_MAP_PATH import EquipmentID2AbilityProperty
class BaseWeaponAttribute(Struct):
hp: float
attack: float
defence: float
def items(self) -> List[Tuple[str, float]]:
return [
("hp", self.hp),
("attack", self.attack),
("defence", self.defence),
]
class BaseWeapon:
def __init__(self, weapon: DamageInstanceWeapon):
self.weapon_id = weapon.id_
self.weapon_level = weapon.level
self.weapon_rank = weapon.rank
self.weapon_promotion = weapon.promotion
self.weapon_base_attribute = self.get_attribute()
self.weapon_attribute: Dict[str, float] = {}
self.get_attribute()
self.weapon_property_ability()
@abstractmethod
async def weapon_ability(self, base_attr: Dict, attribute_bonus: Dict):
"""战斗加成属性, 与 weapon_property_ability() 互斥"""
...
def weapon_property_ability(self):
"""面板加成属性, 与 weapon_ability() 互斥"""
ability_property = EquipmentID2AbilityProperty[str(self.weapon_id)]
equip_ability_property = ability_property[str(self.weapon_rank)]
for equip_ability in equip_ability_property:
property_type = equip_ability["PropertyType"]
value = equip_ability["Value"]["Value"]
if property_type in self.weapon_attribute:
self.weapon_attribute[property_type] += value
else:
self.weapon_attribute[property_type] = value
@abstractmethod
async def check(self):
...
def get_attribute(self):
promotion = EquipmentPromotionConfig.Equipment[str(self.weapon_id)][
str(self.weapon_promotion)
]
return BaseWeaponAttribute(
hp=(
promotion.BaseHP.Value
+ promotion.BaseHPAdd.Value * (self.weapon_level - 1)
),
attack=(
promotion.BaseAttack.Value
+ promotion.BaseAttackAdd.Value * (self.weapon_level - 1)
),
defence=(
promotion.BaseDefence.Value
+ promotion.BaseDefenceAdd.Value * (self.weapon_level - 1)
),
)

View File

@ -0,0 +1,104 @@
from typing import List, Union
import msgspec
from msgspec import Struct, field
class DamageInstanceSkill(Struct):
skillId: int
skillName: str
skillEffect: str
skillAttackType: str
skillLevel: int
class DamageInstanceRelicSubAffix(Struct):
SubAffixID: int
Property: str
Name: str
Cnt: int
Step: int
Value: float
class DamageInstanceRelicMainAffix(Struct):
AffixID: int
Property: str
Name: str
Value: float
class DamageInstanceRelic(Struct):
relicId: int
relicName: str
SetId: int
SetName: str
Type: int
MainAffix: DamageInstanceRelicMainAffix
SubAffixList: Union[List[DamageInstanceRelicSubAffix], None]
Level: int = 0
class DamageInstanceWeapon(Struct):
id_: str = field(name="id")
level: int
rank: int
promotion: int
class AttributeBounsStatusAdd(Struct):
property_: str = field(name="property")
name: str
value: float
class DamageInstanceAvatarAttributeBouns(Struct):
attributeBonusId: int
attributeBonusLevel: int
statusAdd: AttributeBounsStatusAdd
class DamageInstanceAvatar(Struct):
id_: str = field(name="id")
level: int
rank: int
element: str
promotion: int
attribute_bonus: Union[List[DamageInstanceAvatarAttributeBouns], None]
extra_ability: Union[List, None]
class DamageInstance:
avatar: DamageInstanceAvatar
weapon: DamageInstanceWeapon
relic: List[DamageInstanceRelic]
skill: List[DamageInstanceSkill]
def __init__(self, char):
self.avatar = DamageInstanceAvatar(
id_=char.char_id,
level=char.char_level,
rank=char.char_rank,
element=char.char_element,
promotion=char.char_promotion,
attribute_bonus=msgspec.convert(
char.attribute_bonus,
Union[List[DamageInstanceAvatarAttributeBouns], None],
),
extra_ability=msgspec.convert(
char.extra_ability,
Union[List, None],
),
)
self.weapon = DamageInstanceWeapon(
id_=char.equipment["equipmentID"],
level=char.equipment["equipmentLevel"],
rank=char.equipment["equipmentRank"],
promotion=char.equipment["equipmentPromotion"],
)
self.relic = []
for relic in char.char_relic:
self.relic.append(msgspec.convert(relic, DamageInstanceRelic))
self.skill = []
for skill in char.char_skill:
self.skill.append(msgspec.convert(skill, DamageInstanceSkill))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,576 @@
{
"23001": {
"Param": {
"CriticalChance": [
0.18000000016763806, 0.21000000019557774, 0.24000000022351742,
0.2700000002514571, 0.3000000002793968
],
"a_dmg": [
0.060000000055879354, 0.07000000006519258, 0.0800000000745058,
0.09000000008381903, 0.10000000009313226
],
"e_dmg": [
0.060000000055879354, 0.07000000006519258, 0.0800000000745058,
0.09000000008381903, 0.10000000009313226
],
"q_crit_dmg": [
0.12000000011175871, 0.14000000013038516, 0.1600000001490116,
0.18000000016763806, 0.20000000018626451
]
},
"AbilityProperty": [
0.18000000016763806, 0.21000000019557774, 0.24000000022351742,
0.2700000002514571, 0.3000000002793968
]
},
"21003": {
"Param": {
"CriticalChance": [
0.12000000011175871, 0.1500000001396984, 0.18000000016763806,
0.21000000019557774, 0.24000000022351742
]
}
},
"24001": {
"Param": {
"CriticalChance": [
0.0800000000745058, 0.10000000009313226, 0.12000000011175871,
0.14000000013038516, 0.1600000001490116
],
"AttackAddedRatio": [
0.20000000018626451, 0.25000000023283064, 0.3000000002793968,
0.3500000003259629, 0.40000000037252903
]
},
"AbilityProperty": [
0.0800000000745058, 0.10000000009313226, 0.12000000011175871,
0.14000000013038516, 0.1600000001490116
]
},
"21024": {
"Param": {
"SpeedAddedRatio": [
0.0800000000745058, 0.09000000008381903, 0.10000000009313226,
0.11000000010244548, 0.12000000011175871
],
"AllDamageAddedRatio": [
0.12000000011175871, 0.1500000001396984, 0.18000000016763806,
0.21000000019557774, 0.24000000022351742
]
}
},
"21017": {
"Param": {
"a_dmg": [
0.24000000022351742, 0.3000000002793968, 0.3600000003352761,
0.4200000003911555, 0.48000000044703484
],
"e_dmg": [
0.24000000022351742, 0.3000000002793968, 0.3600000003352761,
0.4200000003911555, 0.48000000044703484
]
}
},
"23010": {
"Param": {
"CriticalDamageBase": [
0.36000000022351742, 0.4200000002793968, 0.4800000003352761,
0.5400000003911555, 0.60000000044703484
],
"e_dmg": [
0.18000000022351742, 0.2100000002793968, 0.2400000003352761,
0.2700000003911555, 0.30000000044703484
],
"r_dmg": [
0.18000000022351742, 0.2100000002793968, 0.2400000003352761,
0.2700000003911555, 0.30000000044703484
],
"t_dmg": [
0.48000000022351742, 0.5600000002793968, 0.6400000003352761,
0.7200000003911555, 0.80000000044703484
]
}
},
"23018": {
"Param": {
"r_dmg": [
0.0036000001709908247, 0.00419999985024333, 0.004800000227987766,
0.005399999907240272, 0.005999999586492777
]
}
},
"20002": {
"Param": {
"a_dmg": [
0.20000000022351742, 0.2500000002793968, 0.3000000003352761,
0.3500000003911555, 0.40000000044703484
],
"e_dmg": [
0.20000000022351742, 0.2500000002793968, 0.3000000003352761,
0.3500000003911555, 0.40000000044703484
]
}
},
"21006": {
"Param": {
"t_dmg": [
0.48000000022351742, 0.6000000002793968, 0.7200000003352761,
0.8400000003911555, 0.96000000044703484
]
}
},
"21012": {
"Param": {
"AllDamageAddedRatio": [
0.40000000022351742, 0.5000000002793968, 0.6000000003352761,
0.7000000003911555, 0.80000000044703484
]
}
},
"20011": {
"Param": {
"AllDamageAddedRatio": [
0.24000000022351742, 0.3000000002793968, 0.3600000003352761,
0.4200000003911555, 0.48000000044703484
]
}
},
"20004": {
"Param": {
"StatusProbability": [
0.20000000022351742, 0.2500000002793968, 0.3000000003352761,
0.3500000003911555, 0.40000000044703484
]
}
},
"20020": {
"Param": {
"A3_AttackAddedRatio": [
0.24000000022351742, 0.3000000002793968, 0.3600000003352761,
0.4200000003911555, 0.48000000044703484
]
}
},
"21013": {
"Param": {
"r_dmg": [
0.32000000022351742, 0.4000000002793968, 0.4800000003352761,
0.5600000003911555, 0.64000000044703484
]
}
},
"20006": {
"Param": {
"r_dmg": [
0.28000000022351742, 0.3500000002793968, 0.4200000003352761,
0.4900000003911555, 0.56000000044703484
]
}
},
"20014": {
"Param": {
"SpeedAddedRatio": [
0.10000000009313226, 0.12000000011175871, 0.14000000013038516,
0.1600000001490116, 0.18000000016763806
]
}
},
"20007": {
"Param": {
"AttackAddedRatio": [
0.24000000022351742, 0.3000000002793968, 0.3600000003352761,
0.4200000003911555, 0.48000000044703484
]
}
},
"23000": {
"Param": {
"AttackAddedRatio": [
0.09000000022351742, 0.1050000002793968, 0.1200000003352761,
0.1350000003911555, 0.15000000044703484
],
"AllDamageAddedRatio": [
0.30000000022351742, 0.3500000002793968, 0.4000000003352761,
0.4500000003911555, 0.50000000044703484
]
}
},
"21001": {
"Param": {
"AllDamageAddedRatio": [
0.12000000022351742, 0.1500000002793968, 0.1800000003352761,
0.2100000003911555, 0.24000000044703484
]
}
},
"23011": {
"Param": {
"AllDamageAddedRatio": [
0.09000000022351742, 0.1050000002793968, 0.1200000003352761,
0.1350000003911555, 0.15000000044703484
]
}
},
"23005": {
"Param": {
"DefenceAddedRatio": [
0.2400000000745058, 0.28000000009313226, 0.32000000011175871,
0.36000000013038516, 0.4000000001490116
]
}
},
"20003": {
"Param": {
"DefenceAddedRatio": [
0.1600000000745058, 0.20000000009313226, 0.24000000011175871,
0.28000000013038516, 0.3200000001490116
]
}
},
"21022": {
"Param": {
"AllDamageAddedRatio": [
0.16000000022351742, 0.2050000002793968, 0.2400000003352761,
0.2850000003911555, 0.32000000044703484
]
}
},
"21015": {
"Param": {
"ignore_defence": [
0.12000000022351742, 0.1300000002793968, 0.1400000003352761,
0.1500000003911555, 0.16000000044703484
]
}
},
"23004": {
"Param": {
"AllDamageAddedRatio": [
0.2400000000745058, 0.28000000009313226, 0.32000000011175871,
0.36000000013038516, 0.4000000001490116
],
"A2_StatusProbability": [
0.18000000022351742, 0.2100000002793968, 0.2400000003352761,
0.2700000003911555, 0.30000000044703484
],
"A2_AttackAddedRatio": [
0.2400000000745058, 0.28000000009313226, 0.32000000011175871,
0.36000000013038516, 0.4000000001490116
]
}
},
"23007": {
"Param": {
"DmgRatio": [
0.12000000022351742, 0.1400000002793968, 0.1600000003352761,
0.1800000003911555, 0.20000000044703484
],
"CriticalChance": [
0.12000000022351742, 0.1400000002793968, 0.1600000003352761,
0.1800000003911555, 0.20000000044703484
]
}
},
"23006": {
"Param": {
"SpeedAddedRatio": [
0.04800000022351742, 0.0560000002793968, 0.0640000003352761,
0.0720000003911555, 0.0800000044703484
],
"AllDamageAddedRatio": [
0.2400000000745058, 0.28000000009313226, 0.32000000011175871,
0.36000000013038516, 0.4000000001490116
]
}
},
"21020": {
"Param": {
"AttackAddedRatio": [
0.16000000022351742, 0.2050000002793968, 0.2400000003352761,
0.2850000003911555, 0.32000000044703484
],
"CriticalDamageBase": [
0.24000000022351742, 0.3000000002793968, 0.3600000003352761,
0.4200000003911555, 0.48000000044703484
]
}
},
"23015": {
"Param": {
"AttackAddedRatio": [
0.18000000022351742, 0.2150000002793968, 0.2400000003352761,
0.2750000003911555, 0.30000000044703484
],
"CriticalChance": [
0.18000000022351742, 0.2100000002793968, 0.2400000003352761,
0.2700000003911555, 0.30000000044703484
]
}
},
"20016": {
"Param": {
"CriticalChance": [
0.12000000022351742, 0.1500000002793968, 0.1800000003352761,
0.2100000003911555, 0.24000000044703484
]
}
},
"21005": {
"Param": {
"AttackAddedRatio": [
0.12000000022351742, 0.1500000002793968, 0.1800000003352761,
0.2100000003911555, 0.24000000044703484
]
}
},
"21019": {
"Param": {
"AttackAddedRatio": [
0.16000000022351742, 0.200000002793968, 0.2400000003352761,
0.2850000003911555, 0.32000000044703484
],
"CriticalChance": [
0.12000000022351742, 0.1500000002793968, 0.1800000003352761,
0.2100000003911555, 0.24000000044703484
]
}
},
"23009": {
"Param": {
"CriticalChance": [
0.18000000022351742, 0.2100000002793968, 0.2400000003352761,
0.2700000003911555, 0.30000000044703484
],
"HPAddedRatio": [
0.18000000022351742, 0.2100000002793968, 0.2400000003352761,
0.2700000003911555, 0.30000000044703484
],
"AllDamageAddedRatio": [
0.2400000000745058, 0.28000000009313226, 0.32000000011175871,
0.36000000013038516, 0.4000000001490116
]
}
},
"21008": {
"Param": {
"DOTDmgAdd": [
0.2400000000745058, 0.28000000009313226, 0.32000000011175871,
0.36000000013038516, 0.4000000001490116
]
}
},
"22001": {
"Param": {
"HealRatioBase": [0.16, 0.19, 0.22, 0.25, 0.28]
}
},
"21034": {
"Param": {
"AllDamageAddedRatio": [
0.0020000022351742, 0.0025000002793968, 0.0030000003352761,
0.0035000003911555, 0.0040000044703484
]
}
},
"20009": {
"Param": {
"AllDamageAddedRatio": [
0.2000000000745058, 0.25000000009313226, 0.30000000011175871,
0.35000000013038516, 0.4100000001490116
]
}
},
"23008": {
"Param": {
"speed": [
12, 14, 16, 18, 20
]
}
},
"20019": {
"Param": {
"speed": [
12, 14, 16, 18, 20
]
}
},
"23017": {
"Param": {
"AttackAddedRatio": [
0.02399999974295497, 0.027999999467283487, 0.031999999890103936,
0.035999999614432454, 0.0400000000372529
]
}
},
"21000": {
"Param": {
"Ultra_HealRatioBase": [
0.12000000011175871, 0.1500000001396984, 0.18000000016763806,
0.21000000019557774, 0.24000000022351742
]
}
},
"21014": {
"Param": {
"StatusResistance": [
0.33000000030733645, 0.3600000003352761, 0.3900000003632158,
0.4200000003911555, 0.45000000041909516
],
"HealRatioBase": [
0.1500000001396984, 0.18000000016763806, 0.21000000019557774,
0.24000000022351742, 0.2700000002514571
]
}
},
"21032": {
"Param": {
"AttackAddedRatio": [
0.10000000009313226, 0.12499999976716936, 0.1500000001396984,
0.17499999981373549, 0.20000000018626451
],
"CriticalDamage": [
0.12000000011175871, 0.1500000001396984, 0.18000000016763806,
0.21000000019557774, 0.24000000022351742
]
}
},
"20005": {
"Param": {
"AttackAddedRatio": [
0.0800000000745058, 0.09000000008381903, 0.10000000009313226,
0.11000000010244548, 0.12000000011175871
]
}
},
"22001": {
"Param": {
"HealRatioBase": [
0.1600000001490116, 0.1900000001769513, 0.22000000020489097,
0.25000000023283064, 0.2800000002607703
]
}
},
"20001": {
"Param": {
"HealRatioBase": [
0.12000000011175871, 0.1500000001396984, 0.18000000016763806,
0.21000000019557774, 0.24000000022351742
]
}
},
"21011": {
"Param": {
"AllDamageAddedRatio": [
0.12000000011175871, 0.1500000001396984, 0.18000000016763806,
0.21000000019557774, 0.24000000022351742
]
}
},
"21010": {
"Param": {
"AllDamageAddedRatio": [
0.0800000000745058, 0.10000000009313226, 0.12000000011175871,
0.14000000013038516, 0.1600000001490116
]
}
},
"21033": {
"Param": {
"AllDamageAddedRatio": [
0.2400000000745058, 0.28000000009313226, 0.32000000011175871,
0.36000000013038516, 0.4000000001490116
],
"AttackAddedRatio": [
0.2400000000745058, 0.28000000009313226, 0.32000000011175871,
0.36000000013038516, 0.4000000001490116
]
}
},
"23014": {
"Param": {
"AllDamageAddedRatio": [
0.1400000000745058, 0.16400000009313226, 0.19000000011175871,
0.21400000013038516, 0.2400000001490116
],
"ResistancePenetration": [
0.1200000000745058, 0.14000000009313226, 0.16000000011175871,
0.18000000013038516, 0.2000000001490116
]
}
},
"23002": {
"Param": {
"AllDamageAddedRatio": [
0.2400000000745058, 0.28000000009313226, 0.32000000011175871,
0.36000000013038516, 0.4000000001490116
]
}
},
"21026": {
"Param": {
"AllDamageAddedRatio": [
0.16000000011175871, 0.2000000001396984, 0.24000000016763806,
0.28000000019557774, 0.32000000022351742
],
"AttackAddedRatio": [
0.1000000000745058, 0.12500000009313226, 0.15000000011175871,
0.17500000013038516, 0.2000000001490116
]
}
},
"24000": {
"Param": {
"AllDamageAddedRatio": [
0.12000000011175871, 0.1500000001396984, 0.18000000016763806,
0.21000000019557774, 0.24000000022351742
],
"AttackAddedRatio": [
0.0800000000745058, 0.10000000009313226, 0.12000000011175871,
0.14000000013038516, 0.1600000001490116
]
}
},
"21027": {
"Param": {
"AllDamageAddedRatio": [
0.12000000011175871, 0.1500000001396984, 0.18000000016763806,
0.21000000019557774, 0.24000000022351742
],
"AttackAddedRatio": [
0.04000000011175871, 0.0500000001396984, 0.06000000016763806,
0.07000000019557774, 0.08000000022351742
]
}
},
"23012": {
"Param": {
"CriticalChance": [
0.36000000011175871, 0.4200000001396984, 0.48000000016763806,
0.54000000019557774, 0.60000000022351742
]
}
},
"23016": {
"Param": {
"CriticalDamageBase": [
0.12000000011175871, 0.14000000013038516, 0.1600000001490116,
0.18000000016763806, 0.20000000018626451
],
"TalentDmgAdd": [
0.30000000011175871, 0.3500000001396984, 0.40000000016763806,
0.45000000019557774, 0.50000000022351742
]
}
},
"21031": {
"enable": false
},
"20000": {
"Param": {
"CriticalChance": [
0.12000000011175871, 0.1500000001396984, 0.18000000016763806,
0.21000000019557774, 0.24000000022351742
]
}
}
}

View File

@ -0,0 +1,790 @@
from collections import Counter
from typing import Dict, List, Union
from starrail_damage_cal.damage.Base.model import DamageInstanceRelic
from starrail_damage_cal.damage.Base.RelicBase import BaseRelicSetSkill, SingleRelic
from starrail_damage_cal.damage.utils import merge_attribute
from starrail_damage_cal.logger import logger
class Relic101(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""在战斗开始时"""
logger.info("Relic101 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
pass
return attribute_bonus
class Relic102(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
""""""
logger.info("Relic102 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
a_dmg = attribute_bonus.get("NormalDmgAdd", 0)
attribute_bonus["NormalDmgAdd"] = a_dmg + 0.10000000018626451
return attribute_bonus
class Relic103(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""战斗中生效:装备者提供的护盾量提高."""
logger.info("Relic103 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
shield_added_ratio = attribute_bonus.get("shield_added_ratio", 0)
attribute_bonus["shield_added_ratio"] = (
shield_added_ratio + 0.20000000018626451
)
return attribute_bonus
class Relic104(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者施放终结技."""
logger.info("Relic104 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
critical_damage_base = attribute_bonus.get("CriticalDamageBase", 0)
attribute_bonus["CriticalDamageBase"] = (
critical_damage_base + 0.25000000023283064
)
return attribute_bonus
class Relic105(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""施放攻击或受到攻击时, 默认叠满."""
logger.info("Relic105 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
attack_added_ratio = attribute_bonus.get("AttackAddedRatio", 0)
attribute_bonus["AttackAddedRatio"] = (
attack_added_ratio + 0.05000000004656613 * 5
)
return attribute_bonus
class Relic106(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""无."""
logger.info("Relic106 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
pass
return attribute_bonus
class Relic107(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""TODO: 检查是否是火属性伤害."""
logger.info("Relic107 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4:
e_dmg = attribute_bonus.get("BPSkillDmgAdd", 0)
attribute_bonus["BPSkillDmgAdd"] = e_dmg + 0.12000000011175871
if self.pieces4 and await self.check(base_attr, attribute_bonus):
fire_added_ratio = attribute_bonus.get("FireAddedRatio", 0)
attribute_bonus["FireAddedRatio"] = fire_added_ratio + 0.12000000011175871
return attribute_bonus
class Relic108(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者对敌方目标造成伤害
目标拥有量子属性弱点
"""
logger.info("Relic108 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
logger.info(attribute_bonus)
ignore_defence = attribute_bonus.get("ignore_defence", 0)
attribute_bonus["ignore_defence"] = ignore_defence + 0.10000000009313226 * 2
return attribute_bonus
class Relic109(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""TODO: 检查是否释放战技"""
logger.info("Relic109 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
logger.info(attribute_bonus)
attack_added_ratio = attribute_bonus.get("AttackAddedRatio", 0)
attribute_bonus["AttackAddedRatio"] = (
attack_added_ratio + 0.20000000018626451
)
return attribute_bonus
class Relic110(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者施放终结技"""
logger.info("Relic110 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
logger.info("ModifyActionDelay")
return attribute_bonus
class Relic111(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
self._count = count
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者击破敌方目标弱点"""
logger.info("Relic111 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
logger.info("ModifySPNew")
return attribute_bonus
class Relic112(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
self._count = count
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者对陷入负面效果的敌方目标造成伤害
对陷入禁锢状态的敌方目标造成伤害
"""
logger.info("Relic111 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
logger.info("对陷入负面效果的敌方目标造成伤害")
critical_chance_base = attribute_bonus.get("CriticalChanceBase", 0)
attribute_bonus["CriticalChanceBase"] = (
critical_chance_base + 0.10000000009313226
)
if self.pieces4 and await self.check(base_attr, attribute_bonus):
logger.info("对陷入禁锢状态的敌方目标造成伤害")
critical_damage_base = attribute_bonus.get("CriticalDamageBase", 0)
attribute_bonus["CriticalDamageBase"] = (
critical_damage_base + 0.20000000018626451
)
return attribute_bonus
class Relic113(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
self._count = count
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""当装备者受到攻击或被我方目标消耗生命值后, 暴击率提高8%, 持续2回合, 该效果最多叠加2层。"""
logger.info("Relic113 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
logger.info("当装备者受到攻击或被我方目标消耗生命值后")
critical_chance_base = attribute_bonus.get("CriticalChanceBase", 0)
attribute_bonus["CriticalChanceBase"] = (
critical_chance_base + 0.08000000009313226 * 2
)
return attribute_bonus
class Relic114(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
self._count = count
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""当装备者对我方目标施放终结技时, 我方全体速度提高12%, 持续1回合, 该效果无法叠加。"""
logger.info("Relic114 check success")
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces4 and await self.check(base_attr, attribute_bonus):
speed_added_ratio = attribute_bonus.get("SpeedAddedRatio", 0)
attribute_bonus["SpeedAddedRatio"] = speed_added_ratio + 0.12000000011175871
return attribute_bonus
class Relic301(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者的速度大于等于120"""
merged_attr = await merge_attribute(base_attr, attribute_bonus)
if merged_attr["speed"] >= 120:
logger.info("Relic306 check success")
return True
return False
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces2 and await self.check(base_attr, attribute_bonus):
attack_added_ratio = attribute_bonus.get("AttackAddedRatio", 0)
attribute_bonus["AttackAddedRatio"] = (
attack_added_ratio + 0.12000000011175871
)
return attribute_bonus
class Relic302(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者的速度大于等于120"""
merged_attr = await merge_attribute(base_attr, attribute_bonus)
if merged_attr["speed"] >= 120:
logger.info("Relic306 check success")
return True
return False
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces2 and await self.check(base_attr, attribute_bonus):
attack_added_ratio = attribute_bonus.get("AttackAddedRatio", 0)
attribute_bonus["AttackAddedRatio"] = (
attack_added_ratio + 0.0800000000745058
)
return attribute_bonus
class Relic303(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
# 提高装备者等同于当前效果命中25%的攻击力,最多提高25%
return True
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces2 and await self.check(base_attr, attribute_bonus):
attack_added_ratio = attribute_bonus.get("AttackAddedRatio", 0)
merged_attr = await merge_attribute(base_attr, attribute_bonus)
status_probability = merged_attr.get("StatusProbabilityBase", 0)
# 提高装备者等同于当前效果命中25%的攻击力,最多提高25%
attribute_bonus["AttackAddedRatio"] = attack_added_ratio + min(
0.25000000023283064,
status_probability / 0.25,
)
return attribute_bonus
class Relic304(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""备者的效果命中大于等于50%"""
merged_attr = await merge_attribute(base_attr, attribute_bonus)
if merged_attr["StatusResistanceBase"] >= 0.5000000004656613:
logger.info("Relic306 check success")
return True
return False
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces2 and await self.check(base_attr, attribute_bonus):
defence_added_ratio = attribute_bonus.get("DefenceAddedRatio", 0)
attribute_bonus["DefenceAddedRatio"] = (
defence_added_ratio + 0.1500000001396984
)
return attribute_bonus
class Relic305(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者的暴击伤害大于等于120%"""
merged_attr = await merge_attribute(base_attr, attribute_bonus)
if merged_attr["CriticalDamageBase"] >= 1.2000000001862645:
logger.info("Relic306 check success")
return True
return False
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces2 and await self.check(base_attr, attribute_bonus):
critical_chance_base = attribute_bonus.get("CriticalChanceBase", 0)
attribute_bonus["CriticalChanceBase"] = (
critical_chance_base + 0.6000000005587935
)
return attribute_bonus
class Relic306(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者当前暴击率大于等于50%"""
merged_attr = await merge_attribute(base_attr, attribute_bonus)
if merged_attr["CriticalChanceBase"] >= 0.5:
logger.info("Relic306 check success")
return True
return False
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces2 and await self.check(base_attr, attribute_bonus):
q_dmg = attribute_bonus.get("UltraDmgAdd", 0)
attribute_bonus["UltraDmgAdd"] = q_dmg + 0.1500000001396984
a3_dmg = attribute_bonus.get("TalentDmgAdd", 0)
attribute_bonus["TalentDmgAdd"] = a3_dmg + 0.1500000001396984
return attribute_bonus
class Relic307(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者的速度大于等于145"""
merged_attr = await merge_attribute(base_attr, attribute_bonus)
if merged_attr["speed"] >= 145:
logger.info("Relic306 check success")
return True
return False
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces2 and await self.check(base_attr, attribute_bonus):
break_damage_added_ratio_base = attribute_bonus.get(
"BreakDamageAddedRatioBase",
0,
)
attribute_bonus["BreakDamageAddedRatioBase"] = (
break_damage_added_ratio_base + 0.20000000018626451
)
return attribute_bonus
class Relic308(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""装备者的速度大于等于120"""
merged_attr = await merge_attribute(base_attr, attribute_bonus)
if merged_attr["speed"] >= 120:
logger.info("Relic306 check success")
return True
return False
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces2 and await self.check(base_attr, attribute_bonus):
logger.info("ModifyActionDelay")
return attribute_bonus
class Relic309(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""当装备者的当前暴击率大于等于70%时, 普攻和战技造成的伤害提高20%"""
merged_attr = await merge_attribute(base_attr, attribute_bonus)
if merged_attr["CriticalChanceBase"] >= 0.7:
logger.info("Relic309 check success")
return True
return False
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces2 and await self.check(base_attr, attribute_bonus):
a_dmg = attribute_bonus.get("NormalDmgAdd", 0)
attribute_bonus["NormalDmgAdd"] = a_dmg + 0.20000000018626451
a2_dmg = attribute_bonus.get("BPSkillDmgAdd", 0)
attribute_bonus["BPSkillDmgAdd"] = a2_dmg + 0.20000000018626451
return attribute_bonus
class Relic310(BaseRelicSetSkill):
def __init__(self, set_id: int, count: int):
super().__init__(set_id, count)
async def check(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
"""当装备者的效果抵抗大于等于30%时, 我方全体暴击伤害提高10%"""
merged_attr = await merge_attribute(base_attr, attribute_bonus)
if merged_attr["StatusResistanceBase"] >= 0.3:
logger.info("Relic310 check success")
return True
return False
async def set_skill_ability(
self,
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
):
if self.pieces2 and await self.check(base_attr, attribute_bonus):
critical_damage_base = attribute_bonus.get("CriticalDamageBase", 0)
attribute_bonus["CriticalDamageBase"] = (
critical_damage_base + 0.10000000018626451
)
return attribute_bonus
class RelicSet:
HEAD: SingleRelic
HAND: SingleRelic
BODY: SingleRelic
FOOT: SingleRelic
NECK: SingleRelic
OBJECT: SingleRelic
Unknow: SingleRelic
SetSkill: List[
Union[
Relic101,
Relic102,
Relic103,
Relic104,
Relic105,
Relic106,
Relic107,
Relic108,
Relic109,
Relic110,
Relic111,
Relic112,
Relic113,
Relic114,
Relic301,
Relic302,
Relic303,
Relic304,
Relic305,
Relic306,
Relic307,
Relic308,
Relic309,
Relic310,
]
]
def create(self, relic_list: List[DamageInstanceRelic]):
set_id_list: List[int] = []
for relic in relic_list:
set_id_list.append(relic.SetId)
if relic.Type == 1:
self.HEAD = SingleRelic(relic)
elif relic.Type == 2:
self.HAND = SingleRelic(relic)
elif relic.Type == 3:
self.BODY = SingleRelic(relic)
elif relic.Type == 4:
self.FOOT = SingleRelic(relic)
elif relic.Type == 5:
self.NECK = SingleRelic(relic)
elif relic.Type == 6:
self.OBJECT = SingleRelic(relic)
else:
self.Unknow = SingleRelic(relic)
self.set_id_counter = Counter(set_id_list).most_common()
self.check_set()
self.get_attribute()
return self
def get_attribute(self):
for item in self.__dict__:
if type(self.__dict__[item]) == SingleRelic:
itme__: SingleRelic = self.__dict__[item]
itme__.get_attribute_()
def check_set(self):
self.SetSkill = []
for item in self.set_id_counter:
set_id = item[0]
count = item[1]
if set_id == 101:
self.SetSkill.append(Relic101(set_id, count))
elif set_id == 102:
self.SetSkill.append(Relic102(set_id, count))
elif set_id == 103:
self.SetSkill.append(Relic103(set_id, count))
elif set_id == 104:
self.SetSkill.append(Relic104(set_id, count))
elif set_id == 105:
self.SetSkill.append(Relic105(set_id, count))
elif set_id == 106:
self.SetSkill.append(Relic106(set_id, count))
elif set_id == 107:
self.SetSkill.append(Relic107(set_id, count))
elif set_id == 108:
self.SetSkill.append(Relic108(set_id, count))
elif set_id == 109:
self.SetSkill.append(Relic109(set_id, count))
elif set_id == 110:
self.SetSkill.append(Relic110(set_id, count))
elif set_id == 111:
self.SetSkill.append(Relic111(set_id, count))
elif set_id == 112:
self.SetSkill.append(Relic112(set_id, count))
elif set_id == 113:
self.SetSkill.append(Relic113(set_id, count))
elif set_id == 114:
self.SetSkill.append(Relic114(set_id, count))
elif set_id == 301:
self.SetSkill.append(Relic301(set_id, count))
elif set_id == 302:
self.SetSkill.append(Relic302(set_id, count))
elif set_id == 303:
self.SetSkill.append(Relic303(set_id, count))
elif set_id == 304:
self.SetSkill.append(Relic304(set_id, count))
elif set_id == 305:
self.SetSkill.append(Relic305(set_id, count))
elif set_id == 306:
self.SetSkill.append(Relic306(set_id, count))
elif set_id == 307:
self.SetSkill.append(Relic307(set_id, count))
elif set_id == 308:
self.SetSkill.append(Relic308(set_id, count))
elif set_id == 309:
self.SetSkill.append(Relic309(set_id, count))
elif set_id == 310:
self.SetSkill.append(Relic310(set_id, count))
else:
msg = f"Unknow SetId: {set_id}"
raise ValueError(msg)

View File

@ -0,0 +1,365 @@
import copy
from typing import Dict
from starrail_damage_cal.damage.utils import merge_attribute
async def calculate_heal(
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
skill_type: str,
skill_multiplier: float,
skill_num: float,
is_atk=0,
):
add_attr_bonus = copy.deepcopy(attribute_bonus)
merged_attr = await merge_attribute(base_attr, add_attr_bonus)
hp = merged_attr.get("attack", 0) if is_atk == 1 else merged_attr.get("hp", 0)
# 检查是否有治疗量加成
heal_ratio_base = merged_attr.get("HealRatioBase", 0)
for attr in merged_attr:
if "_HealRatioBase" in attr and attr.split("_")[0] in (skill_type):
heal_ratio_base += merged_attr[attr]
heal_ratio = heal_ratio_base + 1
heal_num = (hp * skill_multiplier + skill_num) * heal_ratio
return [heal_num]
async def calculate_shield(
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
skill_multiplier: float,
skill_num: float,
is_atk=0,
):
add_attr_bonus = copy.deepcopy(attribute_bonus)
merged_attr = await merge_attribute(base_attr, add_attr_bonus)
if is_atk == 1:
defence = merged_attr.get("attack", 0)
else:
defence = merged_attr.get("defence", 0)
# 检查是否有护盾加成
shield_added_ratio = merged_attr.get("shield_added_ratio", 0)
shield_added = shield_added_ratio + 1
defence_num = (defence * skill_multiplier + skill_num) * shield_added
return [defence_num]
async def calculate_damage(
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
skill_type: str,
add_skill_type: str,
element: str,
skill_multiplier: float,
level: int,
is_hp=0,
):
add_attr_bonus = copy.deepcopy(attribute_bonus)
add_attr_bonus = apply_attribute_bonus(add_attr_bonus, skill_type, add_skill_type)
merged_attr = await merge_attribute(base_attr, add_attr_bonus)
if is_hp == 1:
attack = merged_attr.get("hp", 0)
elif is_hp == 2:
attack = merged_attr.get("defence", 0)
else:
attack = merged_attr.get("attack", 0)
damage_reduction = calculate_damage_reduction(level)
resistance_area = calculate_resistance_area(
merged_attr,
skill_type,
add_skill_type,
element,
)
defence_multiplier = calculate_defence_multiplier(level, merged_attr)
injury_area, element_area = calculate_injury_area(
merged_attr,
skill_type,
add_skill_type,
element,
)
damage_ratio = calculate_damage_ratio(merged_attr, skill_type, add_skill_type)
critical_damage = calculate_critical_damage(merged_attr, skill_type, add_skill_type)
critical_chance = calculate_critical_chance(merged_attr, skill_type, add_skill_type)
expected_damage = calculate_expected_damage(critical_chance, critical_damage)
damage_cd = calculate_damage_cd(
attack,
skill_multiplier,
damage_ratio,
injury_area,
defence_multiplier,
resistance_area,
damage_reduction,
critical_damage,
)
damage_qw = calculate_damage_qw(
attack,
skill_multiplier,
damage_ratio,
injury_area,
defence_multiplier,
resistance_area,
damage_reduction,
expected_damage,
)
damage_tz = calculate_damage_tz(
attack,
skill_multiplier,
damage_ratio,
injury_area,
defence_multiplier,
resistance_area,
damage_reduction,
critical_damage,
element,
element_area,
base_attr,
)
return [damage_cd, damage_qw, damage_tz]
def apply_attribute_bonus(
add_attr_bonus: Dict[str, float],
skill_type: str,
add_skill_type: str,
):
# Apply attribute bonuses to attack and status probability
for attr in add_attr_bonus:
if "AttackAddedRatio" in attr and attr.split("AttackAddedRatio")[0] in (
skill_type,
add_skill_type,
):
add_attr_bonus["AttackAddedRatio"] += add_attr_bonus[attr]
if "StatusProbabilityBase" in attr and attr.split("StatusProbabilityBase")[
0
] in (skill_type, add_skill_type):
add_attr_bonus["StatusProbabilityBase"] += add_attr_bonus[attr]
return add_attr_bonus
def calculate_damage_reduction(level: int):
enemy_damage_reduction = 0.1
return 1 - enemy_damage_reduction
def calculate_resistance_area(
merged_attr: Dict[str, float],
skill_type: str,
add_skill_type: str,
element: str,
):
enemy_status_resistance = 0.0
for attr in merged_attr:
if "ResistancePenetration" in attr:
# 检查是否有某一属性的抗性穿透
attr_name = attr.split("ResistancePenetration")[0]
if attr_name in (element, "AllDamage"):
# logger.info(f'{attr_name}属性有{merged_attr[attr]}穿透加成')
enemy_status_resistance += merged_attr[attr]
# 检查是否有某一技能属性的抗性穿透
if "_" in attr_name:
skill_name = attr_name.split("_")[0]
skillattr_name = attr_name.split("_")[1]
if skill_name == add_skill_type and skillattr_name in (
element,
"AllDamage",
):
enemy_status_resistance += merged_attr[attr]
# logger.info(
# f'{skill_name}对{skillattr_name}属性有{merged_attr[attr]}穿透加成'
# )
return 1.0 - (0 - enemy_status_resistance)
def calculate_defence_multiplier(
level: int,
merged_attr: Dict[str, float],
):
ignore_defence = merged_attr.get("ignore_defence", 0.0)
enemy_defence = (level * 10 + 200) * (1 - ignore_defence)
return (level * 10 + 200) / (level * 10 + 200 + enemy_defence)
def calculate_injury_area(
merged_attr: Dict[str, float],
skill_type: str,
add_skill_type: str,
element: str,
):
injury_area = 0.0
element_area = 0.0
for attr in merged_attr:
attr_name = attr.split("AddedRatio")[0]
skill_name = attr.split("DmgAdd")[0]
if "DmgAdd" in attr and skill_name in (
skill_type,
add_skill_type,
):
# logger.info(
# f'{attr} 对 {skill_type} 有 {merged_attr[attr]} 伤害加成'
# )
injury_area += merged_attr[attr]
if "AddedRatio" in attr and attr_name in (
element,
"AllDamage",
):
# logger.info(
# f'{attr} 对 {element} 属性有 {merged_attr[attr]} 伤害加成'
# )
if attr_name == element:
element_area += merged_attr[attr]
injury_area += merged_attr[attr]
return injury_area + 1, element_area
def calculate_damage_ratio(
merged_attr: Dict[str, float],
skill_type: str,
add_skill_type: str,
):
damage_ratio = merged_attr.get("DmgRatio", 0)
for attr in merged_attr:
if "_DmgRatio" in attr and attr.split("_")[0] in (
skill_type,
add_skill_type,
):
damage_ratio += merged_attr[attr]
return damage_ratio + 1
def calculate_critical_damage(
merged_attr: Dict[str, float],
skill_type: str,
add_skill_type: str,
):
if skill_type == "DOT":
return 1.0
critical_damage_base = merged_attr.get("CriticalDamageBase", 0)
for attr in merged_attr:
if "_CriticalDamageBase" in attr and attr.split("_")[0] in (
skill_type,
add_skill_type,
):
critical_damage_base += merged_attr[attr]
return critical_damage_base + 1
def calculate_critical_chance(
merged_attr: Dict[str, float],
skill_type: str,
add_skill_type: str,
):
critical_chance_base = merged_attr["CriticalChanceBase"]
for attr in merged_attr:
if "_CriticalChance" in attr and attr.split("_")[0] in (
skill_type,
add_skill_type,
):
critical_chance_base += merged_attr[attr]
return min(1, critical_chance_base)
def calculate_expected_damage(
critical_chance_base: float,
critical_damage_base: float,
):
return critical_chance_base * (critical_damage_base - 1) + 1
def calculate_damage_cd(
attack: float,
skill_multiplier: float,
damage_ratio: float,
injury_area: float,
defence_multiplier: float,
resistance_area: float,
damage_reduction: float,
critical_damage: float,
):
return (
attack
* skill_multiplier
* damage_ratio
* injury_area
* defence_multiplier
* resistance_area
* damage_reduction
* critical_damage
)
def calculate_damage_qw(
attack: float,
skill_multiplier: float,
damage_ratio: float,
injury_area: float,
defence_multiplier: float,
resistance_area: float,
damage_reduction: float,
expected_damage: float,
):
return (
attack
* skill_multiplier
* damage_ratio
* injury_area
* defence_multiplier
* resistance_area
* damage_reduction
* expected_damage
)
def calculate_damage_tz(
attack: float,
skill_multiplier: float,
damage_ratio: float,
injury_area: float,
defence_multiplier: float,
resistance_area: float,
damage_reduction: float,
critical_damage: float,
element: str,
element_area: float,
base_attr: Dict[str, float],
):
injury_add_tz = 0.0
attack_tz = attack + 355 + base_attr["attack"] * 2.334
# logger.info(f'attack_tz: {attack_tz}')
if element == "Imaginary":
injury_add_tz = 0.12
return (
attack_tz
* skill_multiplier
* damage_ratio
* (injury_area + injury_add_tz + 2.626)
* defence_multiplier
* resistance_area
* damage_reduction
* (critical_damage + 1.794)
* 10
)

File diff suppressed because it is too large Load Diff

View File

View File

@ -0,0 +1,75 @@
from typing import Dict
from starrail_damage_cal.excel.model import RelicMainAffixConfig, RelicSubAffixConfig
from starrail_damage_cal.map.SR_MAP_PATH import RelicId2MainAffixGroup
async def cal_relic_main_affix(
relic_id: int,
set_id: str,
affix_id: int,
relic_type: int,
relic_level: int,
):
if set_id[0] == 3:
rarity = int(str(relic_id)[0]) - 1
group_id = str(rarity) + str(relic_type)
else:
group_id = str(RelicId2MainAffixGroup[str(relic_id)])
relic_data = RelicMainAffixConfig.Relic[group_id][str(affix_id)]
base_value = relic_data.BaseValue.Value
level_add = relic_data.LevelAdd.Value
value = base_value + level_add * relic_level
affix_property = relic_data.Property
return affix_property, value
async def cal_relic_sub_affix(relic_id: int, affix_id: int, cnt: int, step: int):
rarity = int(str(relic_id)[0]) - 1
relic_data = RelicSubAffixConfig.Relic[str(rarity)][str(affix_id)]
base_value = relic_data.BaseValue.Value
step_value = relic_data.StepValue.Value
value = base_value * cnt + step_value * step
affix_property = relic_data.Property
return affix_property, value
async def merge_attribute(
base_attr: Dict[str, float],
attribute_bonus: Dict[str, float],
) -> Dict[str, float]:
merged_attr = base_attr.copy()
for attribute, value in attribute_bonus.items():
if attribute.endswith("Delta"):
attr = attribute.split("Delta")[0].lower()
if attr in merged_attr:
merged_attr[attr] += value
else:
merged_attr[attribute] = attribute_bonus[attribute]
elif attribute.endswith("AddedRatio"):
attr = attribute.split("AddedRatio")[0].lower()
if attr in merged_attr:
merged_attr[attr] += base_attr[attr] * value
else:
merged_attr[attribute] = attribute_bonus[attribute]
# elif attribute in [
# "ignore_defence",
# "Atk_buff",
# "Normal_buff",
# "shield_added_ratio",
# ]:
# merged_attr[attribute] = base_attr.get(attribute, 0) + value
elif attribute.endswith(
("ResistancePenetration", "DmgAdd", "DmgRatio", "Base"),
) or attribute in [
"ignore_defence",
"Atk_buff",
"Normal_buff",
"shield_added_ratio",
]:
merged_attr[attribute] = base_attr.get(attribute, 0) + value
# elif attribute.endswith("Base"):
# merged_attr[attribute] = base_attr.get(attribute, 0) + value
else:
merged_attr[attribute] = attribute_bonus[attribute]
return merged_attr

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,586 @@
{
"2": {
"1": {
"GroupID": 2,
"AffixID": 1,
"Property": "HPDelta",
"BaseValue": {
"Value": 13.548016000073403
},
"StepValue": {
"Value": 1.693502000765875
},
"StepNum": 2
},
"2": {
"GroupID": 2,
"AffixID": 2,
"Property": "AttackDelta",
"BaseValue": {
"Value": 6.774008000502363
},
"StepValue": {
"Value": 0.8467510011978447
},
"StepNum": 2
},
"3": {
"GroupID": 2,
"AffixID": 3,
"Property": "DefenceDelta",
"BaseValue": {
"Value": 6.774008000502363
},
"StepValue": {
"Value": 0.8467510011978447
},
"StepNum": 2
},
"4": {
"GroupID": 2,
"AffixID": 4,
"Property": "HPAddedRatio",
"BaseValue": {
"Value": 0.013824000488966703
},
"StepValue": {
"Value": 0.0017280005849897861
},
"StepNum": 2
},
"5": {
"GroupID": 2,
"AffixID": 5,
"Property": "AttackAddedRatio",
"BaseValue": {
"Value": 0.013824000488966703
},
"StepValue": {
"Value": 0.0017280005849897861
},
"StepNum": 2
},
"6": {
"GroupID": 2,
"AffixID": 6,
"Property": "DefenceAddedRatio",
"BaseValue": {
"Value": 0.017280000261962414
},
"StepValue": {
"Value": 0.002160000381991267
},
"StepNum": 2
},
"7": {
"GroupID": 2,
"AffixID": 7,
"Property": "SpeedDelta",
"BaseValue": {
"Value": 1
},
"StepValue": {
"Value": 0.10000000009313226
},
"StepNum": 2
},
"8": {
"GroupID": 2,
"AffixID": 8,
"Property": "CriticalChanceBase",
"BaseValue": {
"Value": 0.010368000715970993
},
"StepValue": {
"Value": 0.001296000787988305
},
"StepNum": 2
},
"9": {
"GroupID": 2,
"AffixID": 9,
"Property": "CriticalDamageBase",
"BaseValue": {
"Value": 0.020736000733450055
},
"StepValue": {
"Value": 0.0025920008774846792
},
"StepNum": 2
},
"10": {
"GroupID": 2,
"AffixID": 10,
"Property": "StatusProbabilityBase",
"BaseValue": {
"Value": 0.013824000488966703
},
"StepValue": {
"Value": 0.0017280005849897861
},
"StepNum": 2
},
"11": {
"GroupID": 2,
"AffixID": 11,
"Property": "StatusResistanceBase",
"BaseValue": {
"Value": 0.013824000488966703
},
"StepValue": {
"Value": 0.0017280005849897861
},
"StepNum": 2
},
"12": {
"GroupID": 2,
"AffixID": 12,
"Property": "BreakDamageAddedRatioBase",
"BaseValue": {
"Value": 0.020736000733450055
},
"StepValue": {
"Value": 0.0025920008774846792
},
"StepNum": 2
}
},
"3": {
"1": {
"GroupID": 3,
"AffixID": 1,
"Property": "HPDelta",
"BaseValue": {
"Value": 20.32202300033532
},
"StepValue": {
"Value": 2.540253001032397
},
"StepNum": 2
},
"2": {
"GroupID": 3,
"AffixID": 2,
"Property": "AttackDelta",
"BaseValue": {
"Value": 10.161012000171468
},
"StepValue": {
"Value": 1.2701260005123913
},
"StepNum": 2
},
"3": {
"GroupID": 3,
"AffixID": 3,
"Property": "DefenceDelta",
"BaseValue": {
"Value": 10.161012000171468
},
"StepValue": {
"Value": 1.2701260005123913
},
"StepNum": 2
},
"4": {
"GroupID": 3,
"AffixID": 4,
"Property": "HPAddedRatio",
"BaseValue": {
"Value": 0.020736000733450055
},
"StepValue": {
"Value": 0.0025920008774846792
},
"StepNum": 2
},
"5": {
"GroupID": 3,
"AffixID": 5,
"Property": "AttackAddedRatio",
"BaseValue": {
"Value": 0.020736000733450055
},
"StepValue": {
"Value": 0.0025920008774846792
},
"StepNum": 2
},
"6": {
"GroupID": 3,
"AffixID": 6,
"Property": "DefenceAddedRatio",
"BaseValue": {
"Value": 0.02592000039294362
},
"StepValue": {
"Value": 0.0032400002237409353
},
"StepNum": 2
},
"7": {
"GroupID": 3,
"AffixID": 7,
"Property": "SpeedDelta",
"BaseValue": {
"Value": 1.2000000001862645
},
"StepValue": {
"Value": 0.10000000009313226
},
"StepNum": 2
},
"8": {
"GroupID": 3,
"AffixID": 8,
"Property": "CriticalChanceBase",
"BaseValue": {
"Value": 0.015552000375464559
},
"StepValue": {
"Value": 0.0019440008327364922
},
"StepNum": 2
},
"9": {
"GroupID": 3,
"AffixID": 9,
"Property": "CriticalDamageBase",
"BaseValue": {
"Value": 0.031104000052437186
},
"StepValue": {
"Value": 0.0038880009669810534
},
"StepNum": 2
},
"10": {
"GroupID": 3,
"AffixID": 10,
"Property": "StatusProbabilityBase",
"BaseValue": {
"Value": 0.020736000733450055
},
"StepValue": {
"Value": 0.0025920008774846792
},
"StepNum": 2
},
"11": {
"GroupID": 3,
"AffixID": 11,
"Property": "StatusResistanceBase",
"BaseValue": {
"Value": 0.020736000733450055
},
"StepValue": {
"Value": 0.0025920008774846792
},
"StepNum": 2
},
"12": {
"GroupID": 3,
"AffixID": 12,
"Property": "BreakDamageAddedRatioBase",
"BaseValue": {
"Value": 0.031104000052437186
},
"StepValue": {
"Value": 0.0038880009669810534
},
"StepNum": 2
}
},
"4": {
"1": {
"GroupID": 4,
"AffixID": 1,
"Property": "HPDelta",
"BaseValue": {
"Value": 27.09603099990636
},
"StepValue": {
"Value": 3.3870039999019355
},
"StepNum": 2
},
"2": {
"GroupID": 4,
"AffixID": 2,
"Property": "AttackDelta",
"BaseValue": {
"Value": 13.548016000073403
},
"StepValue": {
"Value": 1.693502000765875
},
"StepNum": 2
},
"3": {
"GroupID": 4,
"AffixID": 3,
"Property": "DefenceDelta",
"BaseValue": {
"Value": 13.548016000073403
},
"StepValue": {
"Value": 1.693502000765875
},
"StepNum": 2
},
"4": {
"GroupID": 4,
"AffixID": 4,
"Property": "HPAddedRatio",
"BaseValue": {
"Value": 0.027648000279441476
},
"StepValue": {
"Value": 0.0034560004714876413
},
"StepNum": 2
},
"5": {
"GroupID": 4,
"AffixID": 5,
"Property": "AttackAddedRatio",
"BaseValue": {
"Value": 0.027648000279441476
},
"StepValue": {
"Value": 0.0034560004714876413
},
"StepNum": 2
},
"6": {
"GroupID": 4,
"AffixID": 6,
"Property": "DefenceAddedRatio",
"BaseValue": {
"Value": 0.03456000052392483
},
"StepValue": {
"Value": 0.0043200000654906034
},
"StepNum": 2
},
"7": {
"GroupID": 4,
"AffixID": 7,
"Property": "SpeedDelta",
"BaseValue": {
"Value": 1.6000000005587935
},
"StepValue": {
"Value": 0.20000000018626451
},
"StepNum": 2
},
"8": {
"GroupID": 4,
"AffixID": 8,
"Property": "CriticalChanceBase",
"BaseValue": {
"Value": 0.020736000733450055
},
"StepValue": {
"Value": 0.0025920008774846792
},
"StepNum": 2
},
"9": {
"GroupID": 4,
"AffixID": 9,
"Property": "CriticalDamageBase",
"BaseValue": {
"Value": 0.04147200076840818
},
"StepValue": {
"Value": 0.0051840003579854965
},
"StepNum": 2
},
"10": {
"GroupID": 4,
"AffixID": 10,
"Property": "StatusProbabilityBase",
"BaseValue": {
"Value": 0.027648000279441476
},
"StepValue": {
"Value": 0.0034560004714876413
},
"StepNum": 2
},
"11": {
"GroupID": 4,
"AffixID": 11,
"Property": "StatusResistanceBase",
"BaseValue": {
"Value": 0.027648000279441476
},
"StepValue": {
"Value": 0.0034560004714876413
},
"StepNum": 2
},
"12": {
"GroupID": 4,
"AffixID": 12,
"Property": "BreakDamageAddedRatioBase",
"BaseValue": {
"Value": 0.04147200076840818
},
"StepValue": {
"Value": 0.0051840003579854965
},
"StepNum": 2
}
},
"5": {
"1": {
"GroupID": 5,
"AffixID": 1,
"Property": "HPDelta",
"BaseValue": {
"Value": 33.870039001107216
},
"StepValue": {
"Value": 4.23375500086695
},
"StepNum": 2
},
"2": {
"GroupID": 5,
"AffixID": 2,
"Property": "AttackDelta",
"BaseValue": {
"Value": 16.935019000666216
},
"StepValue": {
"Value": 2.1168770007789135
},
"StepNum": 2
},
"3": {
"GroupID": 5,
"AffixID": 3,
"Property": "DefenceDelta",
"BaseValue": {
"Value": 16.935019000666216
},
"StepValue": {
"Value": 2.1168770007789135
},
"StepNum": 2
},
"4": {
"GroupID": 5,
"AffixID": 4,
"Property": "HPAddedRatio",
"BaseValue": {
"Value": 0.03456000052392483
},
"StepValue": {
"Value": 0.0043200000654906034
},
"StepNum": 2
},
"5": {
"GroupID": 5,
"AffixID": 5,
"Property": "AttackAddedRatio",
"BaseValue": {
"Value": 0.03456000052392483
},
"StepValue": {
"Value": 0.0043200000654906034
},
"StepNum": 2
},
"6": {
"GroupID": 5,
"AffixID": 6,
"Property": "DefenceAddedRatio",
"BaseValue": {
"Value": 0.043199999956414104
},
"StepValue": {
"Value": 0.005399999907240272
},
"StepNum": 2
},
"7": {
"GroupID": 5,
"AffixID": 7,
"Property": "SpeedDelta",
"BaseValue": {
"Value": 2
},
"StepValue": {
"Value": 0.3000000002793968
},
"StepNum": 2
},
"8": {
"GroupID": 5,
"AffixID": 8,
"Property": "CriticalChanceBase",
"BaseValue": {
"Value": 0.02592000039294362
},
"StepValue": {
"Value": 0.0032400002237409353
},
"StepNum": 2
},
"9": {
"GroupID": 5,
"AffixID": 9,
"Property": "CriticalDamageBase",
"BaseValue": {
"Value": 0.05184000078588724
},
"StepValue": {
"Value": 0.006480000447481871
},
"StepNum": 2
},
"10": {
"GroupID": 5,
"AffixID": 10,
"Property": "StatusProbabilityBase",
"BaseValue": {
"Value": 0.03456000052392483
},
"StepValue": {
"Value": 0.0043200000654906034
},
"StepNum": 2
},
"11": {
"GroupID": 5,
"AffixID": 11,
"Property": "StatusResistanceBase",
"BaseValue": {
"Value": 0.03456000052392483
},
"StepValue": {
"Value": 0.0043200000654906034
},
"StepNum": 2
},
"12": {
"GroupID": 5,
"AffixID": 12,
"Property": "BreakDamageAddedRatioBase",
"BaseValue": {
"Value": 0.05184000078588724
},
"StepValue": {
"Value": 0.006480000447481871
},
"StepNum": 2
}
}
}

View File

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,249 @@
from typing import Dict, List, Union
from msgspec import Struct
from starrail_damage_cal.excel.read_excel import (
AvatarPromotion,
EquipmentPromotion,
RelicMainAffix,
RelicSubAffix,
)
class PromotionCost(Struct):
ItemID: int
ItemNum: int
class PromotionAttr(Struct):
Value: float
class SingleAvatarPromotion(Struct):
AvatarID: int
Promotion: int
PromotionCostList: List[PromotionCost]
MaxLevel: int
PlayerLevelRequire: Union[int, None]
WorldLevelRequire: Union[int, None]
AttackBase: PromotionAttr
AttackAdd: PromotionAttr
DefenceBase: PromotionAttr
DefenceAdd: PromotionAttr
HPBase: PromotionAttr
HPAdd: PromotionAttr
SpeedBase: PromotionAttr
CriticalChance: PromotionAttr
CriticalDamage: PromotionAttr
BaseAggro: PromotionAttr
class SingleEquipmentPromotion(Struct):
EquipmentID: int
Promotion: int
PromotionCostList: List[PromotionCost]
MaxLevel: int
PlayerLevelRequire: Union[int, None]
WorldLevelRequire: Union[int, None]
BaseHP: PromotionAttr
BaseHPAdd: PromotionAttr
BaseAttack: PromotionAttr
BaseAttackAdd: PromotionAttr
BaseDefence: PromotionAttr
BaseDefenceAdd: PromotionAttr
class SingleRelicMainAffix(Struct):
GroupID: int
AffixID: int
Property: str
BaseValue: PromotionAttr
LevelAdd: PromotionAttr
IsAvailable: bool
class SingleRelicSubAffix(Struct):
GroupID: int
AffixID: int
Property: str
BaseValue: PromotionAttr
StepValue: PromotionAttr
StepNum: int
class AvatarPromotionConfigModel(Struct):
Avatar: Dict[str, Dict[str, SingleAvatarPromotion]]
@classmethod
def from_json(cls, data: Dict):
return cls(
Avatar={
avatar_id: {
promotion: SingleAvatarPromotion(
AvatarID=promotion_dict[promotion]["AvatarID"],
Promotion=promotion_dict[promotion]["Promotion"],
PromotionCostList=[
PromotionCost(
ItemID=item["ItemID"],
ItemNum=item["ItemNum"],
)
for item in promotion_dict[promotion]["PromotionCostList"]
],
PlayerLevelRequire=promotion_dict[promotion].get(
"PlayerLevelRequire",
None,
),
WorldLevelRequire=promotion_dict[promotion].get(
"WorldLevelRequire",
None,
),
MaxLevel=promotion_dict[promotion]["MaxLevel"],
AttackBase=PromotionAttr(
Value=promotion_dict[promotion]["AttackBase"]["Value"],
),
AttackAdd=PromotionAttr(
Value=promotion_dict[promotion]["AttackAdd"]["Value"],
),
DefenceBase=PromotionAttr(
Value=promotion_dict[promotion]["DefenceBase"]["Value"],
),
DefenceAdd=PromotionAttr(
Value=promotion_dict[promotion]["DefenceAdd"]["Value"],
),
HPBase=PromotionAttr(
Value=promotion_dict[promotion]["HPBase"]["Value"],
),
HPAdd=PromotionAttr(
Value=promotion_dict[promotion]["HPAdd"]["Value"],
),
SpeedBase=PromotionAttr(
Value=promotion_dict[promotion]["SpeedBase"]["Value"],
),
CriticalChance=PromotionAttr(
Value=promotion_dict[promotion]["CriticalChance"]["Value"],
),
CriticalDamage=PromotionAttr(
Value=promotion_dict[promotion]["CriticalDamage"]["Value"],
),
BaseAggro=PromotionAttr(
Value=promotion_dict[promotion]["BaseAggro"]["Value"],
),
)
for promotion in promotion_dict
}
for avatar_id, promotion_dict in data.items()
},
)
class EquipmentPromotionConfigModel(Struct):
Equipment: Dict[str, Dict[str, SingleEquipmentPromotion]]
@classmethod
def from_json(cls, data: Dict):
return cls(
Equipment={
equipment_id: {
promotion: SingleEquipmentPromotion(
EquipmentID=promotion_dict[promotion]["EquipmentID"],
Promotion=promotion_dict[promotion]["Promotion"],
PromotionCostList=[
PromotionCost(
ItemID=item["ItemID"],
ItemNum=item["ItemNum"],
)
for item in promotion_dict[promotion]["PromotionCostList"]
],
PlayerLevelRequire=promotion_dict[promotion].get(
"PlayerLevelRequire",
None,
),
WorldLevelRequire=promotion_dict[promotion].get(
"WorldLevelRequire",
None,
),
MaxLevel=promotion_dict[promotion]["MaxLevel"],
BaseHP=PromotionAttr(
Value=promotion_dict[promotion]["BaseHP"]["Value"],
),
BaseHPAdd=PromotionAttr(
Value=promotion_dict[promotion]["BaseHPAdd"]["Value"],
),
BaseAttack=PromotionAttr(
Value=promotion_dict[promotion]["BaseAttack"]["Value"],
),
BaseAttackAdd=PromotionAttr(
Value=promotion_dict[promotion]["BaseAttackAdd"]["Value"],
),
BaseDefence=PromotionAttr(
Value=promotion_dict[promotion]["BaseDefence"]["Value"],
),
BaseDefenceAdd=PromotionAttr(
Value=promotion_dict[promotion]["BaseDefenceAdd"]["Value"],
),
)
for promotion in promotion_dict
}
for equipment_id, promotion_dict in data.items()
},
)
class RelicMainAffixConfigModel(Struct):
Relic: Dict[str, Dict[str, SingleRelicMainAffix]]
@classmethod
def from_json(cls, data: Dict):
return cls(
Relic={
relic_id: {
group_id: SingleRelicMainAffix(
GroupID=affix_dict[group_id]["GroupID"],
AffixID=affix_dict[group_id]["AffixID"],
Property=affix_dict[group_id]["Property"],
BaseValue=PromotionAttr(
Value=affix_dict[group_id]["BaseValue"]["Value"],
),
LevelAdd=PromotionAttr(
Value=affix_dict[group_id]["LevelAdd"]["Value"],
),
IsAvailable=affix_dict[group_id]["IsAvailable"],
)
for group_id in affix_dict
}
for relic_id, affix_dict in data.items()
},
)
class RelicSubAffixConfigModel(Struct):
Relic: Dict[str, Dict[str, SingleRelicSubAffix]]
@classmethod
def from_json(cls, data: Dict):
return cls(
Relic={
relic_id: {
group_id: SingleRelicSubAffix(
GroupID=affix_dict[group_id]["GroupID"],
AffixID=affix_dict[group_id]["AffixID"],
Property=affix_dict[group_id]["Property"],
BaseValue=PromotionAttr(
Value=affix_dict[group_id]["BaseValue"]["Value"],
),
StepValue=PromotionAttr(
Value=affix_dict[group_id]["StepValue"]["Value"],
),
StepNum=affix_dict[group_id]["StepNum"],
)
for group_id in affix_dict
}
for relic_id, affix_dict in data.items()
},
)
AvatarPromotionConfig = AvatarPromotionConfigModel.from_json(AvatarPromotion)
EquipmentPromotionConfig = EquipmentPromotionConfigModel.from_json(EquipmentPromotion)
RelicMainAffixConfig = RelicMainAffixConfigModel.from_json(RelicMainAffix)
RelicSubAffixConfig = RelicSubAffixConfigModel.from_json(RelicSubAffix)

View File

@ -0,0 +1,19 @@
import json
from pathlib import Path
EXCEL = Path(__file__).parent
with Path.open(EXCEL / "RelicMainAffixConfig.json", encoding="utf8") as f:
RelicMainAffix = json.load(f)
with Path.open(EXCEL / "RelicSubAffixConfig.json", encoding="utf8") as f:
RelicSubAffix = json.load(f)
with Path.open(EXCEL / "AvatarPromotionConfig.json", encoding="utf8") as f:
AvatarPromotion = json.load(f)
with Path.open(EXCEL / "EquipmentPromotionConfig.json", encoding="utf8") as f:
EquipmentPromotion = json.load(f)
with Path.open(EXCEL / "light_cone_ranks.json", encoding="utf8") as f:
light_cone_ranks = json.load(f)

View File

@ -0,0 +1,30 @@
class UidNotfoundError(Exception):
def __init__(self, uid: str):
self.uid = uid
def __str__(self):
return repr(self.uid)
class CharNameError(Exception):
def __init__(self, char_name: str):
self.char_name = char_name
def __str__(self):
return repr(self.char_name)
class MihomoRequestError(Exception):
pass
class NotInCharacterShowcaseError(Exception):
pass
class CharacterShowcaseNotOpenError(Exception):
def __init__(self, uid: str):
self.uid = uid
def __str__(self):
return repr(self.uid)

View File

@ -0,0 +1,3 @@
import logging
logger = logging.getLogger("StarRailDamageCal")

View File

@ -0,0 +1,109 @@
import json
from pathlib import Path
from typing import Dict, List, TypedDict, Union
from msgspec import json as msgjson
from starrail_damage_cal.map.model.RelicSetSkill import RelicSetSkillModel
from starrail_damage_cal.version import StarRail_version
MAP = Path(__file__).parent / "data"
version = StarRail_version
avatarId2Name_fileName = f"avatarId2Name_mapping_{version}.json"
avatarId2EnName_fileName = f"avatarId2EnName_mapping_{version}.json"
EquipmentID2Name_fileName = f"EquipmentID2Name_mapping_{version}.json"
skillId2Name_fileName = f"skillId2Name_mapping_{version}.json"
skillId2Type_fileName = f"skillId2Type_mapping_{version}.json"
Property2Name_fileName = "Property2Name.json"
RelicId2SetId_fileName = f"RelicId2SetId_mapping_{version}.json"
SetId2Name_fileName = f"SetId2Name_mapping_{version}.json"
rankId2Name_fileName = f"rankId2Name_mapping_{version}.json"
characterSkillTree_fileName = f"characterSkillTree_mapping_{version}.json"
avatarId2DamageType_fileName = f"avatarId2DamageType_mapping_{version}.json"
avatarId2Rarity_fileName = f"avatarId2Rarity_mapping_{version}.json"
EquipmentID2AbilityProperty_fileName = (
f"EquipmentID2AbilityProperty_mapping_{version}.json"
)
RelicSetSkill_fileName = f"RelicSetSkill_mapping_{version}.json"
skillId2AttackType_fileName = f"skillId2AttackType_mapping_{version}.json"
EquipmentID2Rarity_fileName = f"EquipmentID2Rarity_mapping_{version}.json"
ItemId2Name_fileName = f"ItemId2Name_mapping_{version}.json"
RelicId2MainAffixGroup_fileName = f"RelicId2MainAffixGroup_mapping_{version}.json"
avatarRankSkillUp_fileName = f"avatarRankSkillUp_mapping_{version}.json"
class TS(TypedDict):
Name: Dict[str, str]
Icon: Dict[str, str]
class LU(TypedDict):
id: str
num: int
with Path.open(MAP / avatarId2Name_fileName, encoding="UTF-8") as f:
avatarId2Name = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / avatarId2EnName_fileName, encoding="UTF-8") as f:
avatarId2EnName = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / EquipmentID2Name_fileName, encoding="UTF-8") as f:
EquipmentID2Name = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / skillId2Name_fileName, encoding="UTF-8") as f:
skillId2Name = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / skillId2Type_fileName, encoding="UTF-8") as f:
skillId2Effect = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / Property2Name_fileName, encoding="UTF-8") as f:
Property2Name = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / RelicId2SetId_fileName, encoding="UTF-8") as f:
RelicId2SetId = msgjson.decode(f.read(), type=Dict[str, int])
with Path.open(MAP / SetId2Name_fileName, encoding="UTF-8") as f:
SetId2Name = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / rankId2Name_fileName, encoding="UTF-8") as f:
rankId2Name = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / characterSkillTree_fileName, encoding="UTF-8") as f:
characterSkillTree = msgjson.decode(f.read(), type=Dict[str, Dict])
with Path.open(MAP / avatarId2DamageType_fileName, encoding="UTF-8") as f:
avatarId2DamageType = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / "char_alias.json", encoding="UTF-8") as f:
alias_data = msgjson.decode(f.read(), type=Dict[str, Dict[str, List]])
with Path.open(MAP / avatarId2Rarity_fileName, encoding="UTF-8") as f:
avatarId2Rarity = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / EquipmentID2AbilityProperty_fileName, encoding="UTF-8") as f:
EquipmentID2AbilityProperty = msgjson.decode(
f.read(),
type=Dict[str, Dict[str, List]],
)
with Path.open(MAP / RelicSetSkill_fileName, encoding="UTF-8") as f:
data = json.load(f)
RelicSetSkill = RelicSetSkillModel.from_json(data)
with Path.open(MAP / skillId2AttackType_fileName, encoding="UTF-8") as f:
skillId2AttackType = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / EquipmentID2Rarity_fileName, encoding="UTF-8") as f:
EquipmentID2Rarity = msgjson.decode(f.read(), type=Dict[str, int])
with Path.open(MAP / ItemId2Name_fileName, encoding="UTF-8") as f:
ItemId2Name = msgjson.decode(f.read(), type=Dict[str, str])
with Path.open(MAP / RelicId2MainAffixGroup_fileName, encoding="UTF-8") as f:
RelicId2MainAffixGroup = msgjson.decode(f.read(), type=Dict[str, int])
with Path.open(MAP / avatarRankSkillUp_fileName, encoding="UTF-8") as f:
AvatarRankSkillUp = msgjson.decode(f.read(), type=Dict[str, Union[List[LU], None]])

View File

View File

@ -0,0 +1,668 @@
[
{
"role": "景元",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "希儿",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "布洛妮娅",
"HPDelta": 0.75,
"HPAddedRatio": 0.75,
"AttackDelta": 0.5,
"AttackAddedRatio": 0.5,
"DefenceDelta": 0.5,
"DefenceAddedRatio": 0.5,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 1.0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 1.0,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.5,
"AttributeAddedRatio": 0.0
},
{
"role": "杰帕德",
"HPDelta": 0.5,
"HPAddedRatio": 0.5,
"AttackDelta": 0.0,
"AttackAddedRatio": 0.0,
"DefenceDelta": 1.0,
"DefenceAddedRatio": 1.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 1.0,
"StatusProbabilityBase": 0.5,
"StatusResistanceBase": 0.5,
"AttributeAddedRatio": 0
},
{
"role": "姬子",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.5,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "瓦尔特",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 1.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "卡芙卡",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 1.0,
"AttackAddedRatio": 1.0,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0.5,
"CriticalDamageBase": 0.0,
"BreakDamageAddedRatioBase": 0.5,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.75,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "彦卿",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.75,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "镜流",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.75,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "白露",
"HPDelta": 1.0,
"HPAddedRatio": 1.0,
"AttackDelta": 0.0,
"AttackAddedRatio": 0.0,
"DefenceDelta": 0.5,
"DefenceAddedRatio": 0.5,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 1,
"SPRatio": 1.0,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.75,
"AttributeAddedRatio": 0
},
{
"role": "玲可",
"HPDelta": 1.0,
"HPAddedRatio": 1.0,
"AttackDelta": 0.0,
"AttackAddedRatio": 0.0,
"DefenceDelta": 0.5,
"DefenceAddedRatio": 0.5,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 1,
"SPRatio": 1.0,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.75,
"AttributeAddedRatio": 0
},
{
"role": "藿藿",
"HPDelta": 1.0,
"HPAddedRatio": 1.0,
"AttackDelta": 0.0,
"AttackAddedRatio": 0.0,
"DefenceDelta": 0.5,
"DefenceAddedRatio": 0.5,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 1,
"SPRatio": 1.0,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.75,
"AttributeAddedRatio": 0
},
{
"role": "符玄",
"HPDelta": 1.0,
"HPAddedRatio": 1.0,
"AttackDelta": 0.0,
"AttackAddedRatio": 0.0,
"DefenceDelta": 0.5,
"DefenceAddedRatio": 0.5,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0.0,
"SPRatio": 0.1,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 1.0,
"AttributeAddedRatio": 0
},
{
"role": "罗刹",
"HPDelta": 0.75,
"HPAddedRatio": 0.75,
"AttackDelta": 1.0,
"AttackAddedRatio": 1.0,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 1,
"SPRatio": 1,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.75,
"AttributeAddedRatio": 0
},
{
"role": "桂乃芬",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 1,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "驭空",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.5,
"AttackAddedRatio": 0.5,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 1,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "克拉拉",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "三月七",
"HPDelta": 0.5,
"HPAddedRatio": 0.5,
"AttackDelta": 0.0,
"AttackAddedRatio": 0.0,
"DefenceDelta": 1.0,
"DefenceAddedRatio": 1.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 1.0,
"StatusProbabilityBase": 0.5,
"StatusResistanceBase": 0.5,
"AttributeAddedRatio": 0
},
{
"role": "丹恒",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "阿兰",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "艾丝妲",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.75,
"HealRatio": 0,
"SPRatio": 1.0,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "黑塔",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "希露瓦",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "娜塔莎",
"HPDelta": 1.0,
"HPAddedRatio": 1.0,
"AttackDelta": 0.0,
"AttackAddedRatio": 0.0,
"DefenceDelta": 0.5,
"DefenceAddedRatio": 0.5,
"SpeedDelta": 0.75,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 1,
"SPRatio": 0.75,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.5,
"AttributeAddedRatio": 0
},
{
"role": "佩拉",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 1.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "桑博",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 1.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "虎克",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "青雀",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "停云",
"HPDelta": 0.5,
"HPAddedRatio": 0.5,
"AttackDelta": 1.0,
"AttackAddedRatio": 1.0,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 1.0,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 0
},
{
"role": "素裳",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.5,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "开拓者火",
"HPDelta": 0.5,
"HPAddedRatio": 0.5,
"AttackDelta": 0.0,
"AttackAddedRatio": 0.0,
"DefenceDelta": 0.1,
"DefenceAddedRatio": 0.1,
"SpeedDelta": 1.0,
"CriticalChanceBase": 0,
"CriticalDamageBase": 0,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.0,
"StatusProbabilityBase": 1.0,
"StatusResistanceBase": 0.5,
"AttributeAddedRatio": 0
},
{
"role": "开拓者物理",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "刃",
"HPDelta": 0.75,
"HPAddedRatio": 0.75,
"AttackDelta": 0.0,
"AttackAddedRatio": 0.0,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "丹恒•饮月",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "银狼",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 1.0,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 1.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "托帕&账账",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
},
{
"role": "银枝",
"HPDelta": 0.0,
"HPAddedRatio": 0.0,
"AttackDelta": 0.75,
"AttackAddedRatio": 0.75,
"DefenceDelta": 0.0,
"DefenceAddedRatio": 0.0,
"SpeedDelta": 0.75,
"CriticalChanceBase": 1,
"CriticalDamageBase": 1,
"BreakDamageAddedRatioBase": 0.0,
"HealRatio": 0,
"SPRatio": 0.5,
"StatusProbabilityBase": 0.0,
"StatusResistanceBase": 0.0,
"AttributeAddedRatio": 1
}
]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
{
"20000": "Arrows",
"20001": "Cornucopia",
"20002": "CollapsingSky",
"20003": "Amber",
"20004": "Void",
"20005": "Chorus",
"20006": "DataBank",
"20007": "DartingArrow",
"20008": "FineFruit",
"20009": "ShatteredHome",
"20010": "Defense",
"20011": "Loop",
"20012": "MeshingCogs",
"20013": "Passkey",
"20014": "Adversarial",
"20015": "Multiplication",
"20016": "MutualDemise",
"20017": "Pioneering",
"20018": "HiddenShadow",
"20019": "Mediation",
"20020": "Sagacity",
"21000": "Post-OpConversation",
"21001": "GoodNightandSleepWell",
"21002": "DayOneofMyNewLife",
"21003": "OnlySilenceRemains",
"21004": "MemoriesofthePast",
"21005": "TheMolesWelcomeYou",
"21006": "TheBirthoftheSelf",
"21007": "SharedFeeling",
"21008": "EyesofthePrey",
"21009": "Landau'sChoice",
"21010": "Swordplay",
"21011": "PlanetaryRendezvous",
"21012": "ASecretVow",
"21013": "MaketheWorldClamor",
"21014": "PerfectTiming",
"21015": "ResolutionShinesAsPearlsofSweat",
"21016": "TrendoftheUniversalMarket",
"21017": "SubscribeforMore!",
"21018": "Dance!Dance!Dance!",
"21019": "UndertheBlueSky",
"21020": "Geniuses'Repose",
"21021": "QuidProQuo",
"21022": "Fermata",
"21023": "WeAreWildfire",
"21024": "RiverFlowsinSpring",
"21026": "Woof!WalkTime!",
"21027": "TheSeriousnessofBreakfast",
"21028": "WarmthShortensColdNights",
"21029": "WeWillMeetAgain",
"21030": "ThisIsMe!",
"21031": "ReturntoDarkness",
"21032": "CarvetheMoon,WeavetheClouds",
"21033": "NowheretoRun",
"21034": "TodayIsAnotherPeacefulDay",
"22000": "BeforetheTutorialMissionStarts",
"23000": "NightontheMilkyWay",
"23001": "IntheNight",
"23002": "SomethingIrreplaceable",
"23003": "ButtheBattleIsn'tOver",
"23004": "IntheNameoftheWorld",
"23005": "MomentofVictory",
"23006": "PatienceIsAllYouNeed",
"23007": "IncessantRain",
"23008": "EchoesoftheCoffin",
"23009": "TheUnreachableSide",
"23010": "BeforeDawn",
"23011": "SheAlreadyShutHerEyes",
"23012": "SleepLiketheDead",
"23013": "TimeWaitsforNoOne",
"23014": "IShallBeMyOwnSword",
"23015": "BrighterThantheSun",
"23016": "Worrisome,Blissful",
"24000": "OntheFallofanAeon",
"24001": "CruisingintheStellarSea",
"24002": "TextureofMemories",
"21025": "PastandFuture",
"24003": "SolitaryHealing",
"23018": "AnInstanceForeverCherished",
"23017": "NightofFright",
"22001": "Hey,OverHere"
}

View File

@ -0,0 +1,83 @@
{
"20000": "锋镝",
"20001": "物穰",
"20002": "天倾",
"20003": "琥珀",
"20004": "幽邃",
"20005": "齐颂",
"20006": "智库",
"20007": "离弦",
"20008": "嘉果",
"20009": "乐圮",
"20010": "戍御",
"20011": "渊环",
"20012": "轮契",
"20013": "灵钥",
"20014": "相抗",
"20015": "蕃息",
"20016": "俱殁",
"20017": "开疆",
"20018": "匿影",
"20019": "调和",
"20020": "睿见",
"21000": "一场术后对话",
"21001": "晚安与睡颜",
"21002": "余生的第一天",
"21003": "唯有沉默",
"21004": "记忆中的模样",
"21005": "鼹鼠党欢迎你",
"21006": "「我」的诞生",
"21007": "同一种心情",
"21008": "猎物的视线",
"21009": "朗道的选择",
"21010": "论剑",
"21011": "与行星相会",
"21012": "秘密誓心",
"21013": "别让世界静下来",
"21014": "此时恰好",
"21015": "决心如汗珠般闪耀",
"21016": "宇宙市场趋势",
"21017": "点个关注吧!",
"21018": "舞!舞!舞!",
"21019": "在蓝天下",
"21020": "天才们的休憩",
"21021": "等价交换",
"21022": "延长记号",
"21023": "我们是地火",
"21024": "春水初生",
"21026": "汪!散步时间!",
"21027": "早餐的仪式感",
"21028": "暖夜不会漫长",
"21029": "后会有期",
"21030": "这就是我啦!",
"21031": "重返幽冥",
"21032": "镂月裁云之意",
"21033": "无处可逃",
"21034": "今日亦是和平的一日",
"22000": "新手任务开始前",
"23000": "银河铁道之夜",
"23001": "于夜色中",
"23002": "无可取代的东西",
"23003": "但战斗还未结束",
"23004": "以世界之名",
"23005": "制胜的瞬间",
"23006": "只需等待",
"23007": "雨一直下",
"23008": "棺的回响",
"23009": "到不了的彼岸",
"23010": "拂晓之前",
"23011": "她已闭上双眼",
"23012": "如泥酣眠",
"23013": "时节不居",
"23014": "此身为剑",
"23015": "比阳光更明亮的",
"23016": "烦恼着,幸福着",
"24000": "记一位星神的陨落",
"24001": "星海巡航",
"24002": "记忆的质料",
"21025": "过往未来",
"24003": "孤独的疗愈",
"23018": "片刻,留在眼底",
"23017": "惊魂夜",
"22001": "嘿,我在这儿"
}

View File

@ -0,0 +1,83 @@
{
"20000": 3,
"20001": 3,
"20002": 3,
"20003": 3,
"20004": 3,
"20005": 3,
"20006": 3,
"20007": 3,
"20008": 3,
"20009": 3,
"20010": 3,
"20011": 3,
"20012": 3,
"20013": 3,
"20014": 3,
"20015": 3,
"20016": 3,
"20017": 3,
"20018": 3,
"20019": 3,
"20020": 3,
"21000": 4,
"21001": 4,
"21002": 4,
"21003": 4,
"21004": 4,
"21005": 4,
"21006": 4,
"21007": 4,
"21008": 4,
"21009": 4,
"21010": 4,
"21011": 4,
"21012": 4,
"21013": 4,
"21014": 4,
"21015": 4,
"21016": 4,
"21017": 4,
"21018": 4,
"21019": 4,
"21020": 4,
"21021": 4,
"21022": 4,
"21023": 4,
"21024": 4,
"21025": 4,
"21026": 4,
"21027": 4,
"21028": 4,
"21029": 4,
"21030": 4,
"21031": 4,
"21032": 4,
"21033": 4,
"21034": 4,
"22000": 4,
"23000": 5,
"23001": 5,
"23002": 5,
"23003": 5,
"23004": 5,
"23005": 5,
"23006": 5,
"23007": 5,
"23008": 5,
"23009": 5,
"23010": 5,
"23011": 5,
"23012": 5,
"23013": 5,
"23014": 5,
"23015": 5,
"23016": 5,
"24000": 5,
"24001": 5,
"24002": 5,
"24003": 5,
"23018": 5,
"23017": 5,
"22001": 4
}

View File

@ -0,0 +1,312 @@
{
"31011": "过客的逢春木簪",
"41011": "过客的逢春木簪",
"51011": "过客的逢春木簪",
"61011": "过客的逢春木簪",
"31012": "过客的游龙臂鞲",
"41012": "过客的游龙臂鞲",
"51012": "过客的游龙臂鞲",
"61012": "过客的游龙臂鞲",
"31013": "过客的残绣风衣",
"41013": "过客的残绣风衣",
"51013": "过客的残绣风衣",
"61013": "过客的残绣风衣",
"31014": "过客的冥途游履",
"41014": "过客的冥途游履",
"51014": "过客的冥途游履",
"61014": "过客的冥途游履",
"31021": "快枪手的野穗毡帽",
"41021": "快枪手的野穗毡帽",
"51021": "快枪手的野穗毡帽",
"61021": "快枪手的野穗毡帽",
"31022": "快枪手的粗革手套",
"41022": "快枪手的粗革手套",
"51022": "快枪手的粗革手套",
"61022": "快枪手的粗革手套",
"31023": "快枪手的猎风披肩",
"41023": "快枪手的猎风披肩",
"51023": "快枪手的猎风披肩",
"61023": "快枪手的猎风披肩",
"31024": "快枪手的铆钉马靴",
"41024": "快枪手的铆钉马靴",
"51024": "快枪手的铆钉马靴",
"61024": "快枪手的铆钉马靴",
"31031": "圣骑的宽恕盔面",
"41031": "圣骑的宽恕盔面",
"51031": "圣骑的宽恕盔面",
"61031": "圣骑的宽恕盔面",
"31032": "圣骑的沉默誓环",
"41032": "圣骑的沉默誓环",
"51032": "圣骑的沉默誓环",
"61032": "圣骑的沉默誓环",
"31033": "圣骑的肃穆胸甲",
"41033": "圣骑的肃穆胸甲",
"51033": "圣骑的肃穆胸甲",
"61033": "圣骑的肃穆胸甲",
"31034": "圣骑的秩序铁靴",
"41034": "圣骑的秩序铁靴",
"51034": "圣骑的秩序铁靴",
"61034": "圣骑的秩序铁靴",
"31041": "雪猎的荒神兜帽",
"41041": "雪猎的荒神兜帽",
"51041": "雪猎的荒神兜帽",
"61041": "雪猎的荒神兜帽",
"31042": "雪猎的巨蜥手套",
"41042": "雪猎的巨蜥手套",
"51042": "雪猎的巨蜥手套",
"61042": "雪猎的巨蜥手套",
"31043": "雪猎的冰龙披风",
"41043": "雪猎的冰龙披风",
"51043": "雪猎的冰龙披风",
"61043": "雪猎的冰龙披风",
"31044": "雪猎的鹿皮软靴",
"41044": "雪猎的鹿皮软靴",
"51044": "雪猎的鹿皮软靴",
"61044": "雪猎的鹿皮软靴",
"31051": "拳王的冠军护头",
"41051": "拳王的冠军护头",
"51051": "拳王的冠军护头",
"61051": "拳王的冠军护头",
"31052": "拳王的重炮拳套",
"41052": "拳王的重炮拳套",
"51052": "拳王的重炮拳套",
"61052": "拳王的重炮拳套",
"31053": "拳王的贴身护胸",
"41053": "拳王的贴身护胸",
"51053": "拳王的贴身护胸",
"61053": "拳王的贴身护胸",
"31054": "拳王的弧步战靴",
"41054": "拳王的弧步战靴",
"51054": "拳王的弧步战靴",
"61054": "拳王的弧步战靴",
"31061": "铁卫的铸铁面盔",
"41061": "铁卫的铸铁面盔",
"51061": "铁卫的铸铁面盔",
"61061": "铁卫的铸铁面盔",
"31062": "铁卫的银鳞手甲",
"41062": "铁卫的银鳞手甲",
"51062": "铁卫的银鳞手甲",
"61062": "铁卫的银鳞手甲",
"31063": "铁卫的旧制军服",
"41063": "铁卫的旧制军服",
"51063": "铁卫的旧制军服",
"61063": "铁卫的旧制军服",
"31064": "铁卫的白银护胫",
"41064": "铁卫的白银护胫",
"51064": "铁卫的白银护胫",
"61064": "铁卫的白银护胫",
"31071": "火匠的黑曜目镜",
"41071": "火匠的黑曜目镜",
"51071": "火匠的黑曜目镜",
"61071": "火匠的黑曜目镜",
"31072": "火匠的御火戒指",
"41072": "火匠的御火戒指",
"51072": "火匠的御火戒指",
"61072": "火匠的御火戒指",
"31073": "火匠的阻燃围裙",
"41073": "火匠的阻燃围裙",
"51073": "火匠的阻燃围裙",
"61073": "火匠的阻燃围裙",
"31074": "火匠的合金义肢",
"41074": "火匠的合金义肢",
"51074": "火匠的合金义肢",
"61074": "火匠的合金义肢",
"31081": "天才的超距遥感",
"41081": "天才的超距遥感",
"51081": "天才的超距遥感",
"61081": "天才的超距遥感",
"31082": "天才的频变捕手",
"41082": "天才的频变捕手",
"51082": "天才的频变捕手",
"61082": "天才的频变捕手",
"31083": "天才的元域深潜",
"41083": "天才的元域深潜",
"51083": "天才的元域深潜",
"61083": "天才的元域深潜",
"31084": "天才的引力漫步",
"41084": "天才的引力漫步",
"51084": "天才的引力漫步",
"61084": "天才的引力漫步",
"31091": "乐队的偏光墨镜",
"41091": "乐队的偏光墨镜",
"51091": "乐队的偏光墨镜",
"61091": "乐队的偏光墨镜",
"31092": "乐队的巡演手绳",
"41092": "乐队的巡演手绳",
"51092": "乐队的巡演手绳",
"61092": "乐队的巡演手绳",
"31093": "乐队的钉刺皮衣",
"41093": "乐队的钉刺皮衣",
"51093": "乐队的钉刺皮衣",
"61093": "乐队的钉刺皮衣",
"31094": "乐队的铆钉短靴",
"41094": "乐队的铆钉短靴",
"51094": "乐队的铆钉短靴",
"61094": "乐队的铆钉短靴",
"31101": "翔鹰的长喙头盔",
"41101": "翔鹰的长喙头盔",
"51101": "翔鹰的长喙头盔",
"61101": "翔鹰的长喙头盔",
"31102": "翔鹰的鹰击指环",
"41102": "翔鹰的鹰击指环",
"51102": "翔鹰的鹰击指环",
"61102": "翔鹰的鹰击指环",
"31103": "翔鹰的翼装束带",
"41103": "翔鹰的翼装束带",
"51103": "翔鹰的翼装束带",
"61103": "翔鹰的翼装束带",
"31104": "翔鹰的绒羽绑带",
"41104": "翔鹰的绒羽绑带",
"51104": "翔鹰的绒羽绑带",
"61104": "翔鹰的绒羽绑带",
"31111": "怪盗的千人假面",
"41111": "怪盗的千人假面",
"51111": "怪盗的千人假面",
"61111": "怪盗的千人假面",
"31112": "怪盗的绘纹手套",
"41112": "怪盗的绘纹手套",
"51112": "怪盗的绘纹手套",
"61112": "怪盗的绘纹手套",
"31113": "怪盗的纤钢爪钩",
"41113": "怪盗的纤钢爪钩",
"51113": "怪盗的纤钢爪钩",
"61113": "怪盗的纤钢爪钩",
"31114": "怪盗的流星快靴",
"41114": "怪盗的流星快靴",
"51114": "怪盗的流星快靴",
"61114": "怪盗的流星快靴",
"31121": "废土客的呼吸面罩",
"41121": "废土客的呼吸面罩",
"51121": "废土客的呼吸面罩",
"61121": "废土客的呼吸面罩",
"31122": "废土客的荒漠终端",
"41122": "废土客的荒漠终端",
"51122": "废土客的荒漠终端",
"61122": "废土客的荒漠终端",
"31123": "废土客的修士长袍",
"41123": "废土客的修士长袍",
"51123": "废土客的修士长袍",
"61123": "废土客的修士长袍",
"31124": "废土客的动力腿甲",
"41124": "废土客的动力腿甲",
"51124": "废土客的动力腿甲",
"61124": "废土客的动力腿甲",
"33015": "「黑塔」的空间站点",
"43015": "「黑塔」的空间站点",
"53015": "「黑塔」的空间站点",
"63015": "「黑塔」的空间站点",
"33016": "「黑塔」的漫历轨迹",
"43016": "「黑塔」的漫历轨迹",
"53016": "「黑塔」的漫历轨迹",
"63016": "「黑塔」的漫历轨迹",
"33025": "罗浮仙舟的天外楼船",
"43025": "罗浮仙舟的天外楼船",
"53025": "罗浮仙舟的天外楼船",
"63025": "罗浮仙舟的天外楼船",
"33026": "罗浮仙舟的建木枝蔓",
"43026": "罗浮仙舟的建木枝蔓",
"53026": "罗浮仙舟的建木枝蔓",
"63026": "罗浮仙舟的建木枝蔓",
"33035": "公司的巨构总部",
"43035": "公司的巨构总部",
"53035": "公司的巨构总部",
"63035": "公司的巨构总部",
"33036": "公司的贸易航道",
"43036": "公司的贸易航道",
"53036": "公司的贸易航道",
"63036": "公司的贸易航道",
"33045": "贝洛伯格的存护堡垒",
"43045": "贝洛伯格的存护堡垒",
"53045": "贝洛伯格的存护堡垒",
"63045": "贝洛伯格的存护堡垒",
"33046": "贝洛伯格的铁卫防线",
"43046": "贝洛伯格的铁卫防线",
"53046": "贝洛伯格的铁卫防线",
"63046": "贝洛伯格的铁卫防线",
"33055": "螺丝星的机械烈阳",
"43055": "螺丝星的机械烈阳",
"53055": "螺丝星的机械烈阳",
"63055": "螺丝星的机械烈阳",
"33056": "螺丝星的环星孔带",
"43056": "螺丝星的环星孔带",
"53056": "螺丝星的环星孔带",
"63056": "螺丝星的环星孔带",
"33065": "萨尔索图的移动城市",
"43065": "萨尔索图的移动城市",
"53065": "萨尔索图的移动城市",
"63065": "萨尔索图的移动城市",
"33066": "萨尔索图的晨昏界线",
"43066": "萨尔索图的晨昏界线",
"53066": "萨尔索图的晨昏界线",
"63066": "萨尔索图的晨昏界线",
"33075": "塔利亚的钉壳小镇",
"43075": "塔利亚的钉壳小镇",
"53075": "塔利亚的钉壳小镇",
"63075": "塔利亚的钉壳小镇",
"33076": "塔利亚的裸皮电线",
"43076": "塔利亚的裸皮电线",
"53076": "塔利亚的裸皮电线",
"63076": "塔利亚的裸皮电线",
"33085": "翁瓦克的诞生之岛",
"43085": "翁瓦克的诞生之岛",
"53085": "翁瓦克的诞生之岛",
"63085": "翁瓦克的诞生之岛",
"33086": "翁瓦克的环岛海岸",
"43086": "翁瓦克的环岛海岸",
"53086": "翁瓦克的环岛海岸",
"63086": "翁瓦克的环岛海岸",
"33095": "泰科铵的镭射球场",
"43095": "泰科铵的镭射球场",
"53095": "泰科铵的镭射球场",
"63095": "泰科铵的镭射球场",
"33096": "泰科铵的弧光赛道",
"43096": "泰科铵的弧光赛道",
"53096": "泰科铵的弧光赛道",
"63096": "泰科铵的弧光赛道",
"33105": "伊须磨洲的残船鲸落",
"43105": "伊须磨洲的残船鲸落",
"53105": "伊须磨洲的残船鲸落",
"63105": "伊须磨洲的残船鲸落",
"33106": "伊须磨洲的坼裂缆索",
"43106": "伊须磨洲的坼裂缆索",
"53106": "伊须磨洲的坼裂缆索",
"63106": "伊须磨洲的坼裂缆索",
"55001": "过客的残绣风衣",
"55002": "过客的冥途游履",
"55003": "快枪手的猎风披肩",
"55004": "圣骑的肃穆胸甲",
"55005": "圣骑的秩序铁靴",
"55006": "拳王的贴身护胸",
"31131": "莳者的复明义眼",
"41131": "莳者的复明义眼",
"51131": "莳者的复明义眼",
"61131": "莳者的复明义眼",
"31132": "莳者的机巧木手",
"41132": "莳者的机巧木手",
"51132": "莳者的机巧木手",
"61132": "莳者的机巧木手",
"31133": "莳者的承露羽衣",
"41133": "莳者的承露羽衣",
"51133": "莳者的承露羽衣",
"61133": "莳者的承露羽衣",
"31134": "莳者的天人丝履",
"41134": "莳者的天人丝履",
"51134": "莳者的天人丝履",
"61134": "莳者的天人丝履",
"31141": "信使的全息目镜",
"41141": "信使的全息目镜",
"51141": "信使的全息目镜",
"61141": "信使的全息目镜",
"31142": "信使的百变义手",
"41142": "信使的百变义手",
"51142": "信使的百变义手",
"61142": "信使的百变义手",
"31143": "信使的密信挎包",
"41143": "信使的密信挎包",
"51143": "信使的密信挎包",
"61143": "信使的密信挎包",
"31144": "信使的酷跑板鞋",
"41144": "信使的酷跑板鞋",
"51144": "信使的酷跑板鞋",
"61144": "信使的酷跑板鞋"
}

View File

@ -0,0 +1,55 @@
{
"MaxHP": "生命值",
"Attack": "攻击力",
"Defence": "防御力",
"Speed": "速度",
"CriticalChance": "暴击率",
"CriticalDamage": "暴击伤害",
"BreakDamageAddedRatio": "击破特攻",
"BreakDamageAddedRatioBase": "击破特攻",
"HealRatio": "治疗量加成",
"MaxSP": "能量上限",
"SPRatio": "能量恢复效率",
"StatusProbability": "效果命中",
"StatusResistance": "效果抵抗",
"CriticalChanceBase": "暴击率",
"CriticalDamageBase": "暴击伤害",
"HealRatioBase": "治疗量加成",
"StanceBreakAddedRatio": "dev_失效字段",
"SPRatioBase": "能量恢复效率",
"StatusProbabilityBase": "效果命中",
"StatusResistanceBase": "效果抵抗",
"PhysicalAddedRatio": "物理属性伤害提高",
"PhysicalResistance": "物理属性抗性提高",
"FireAddedRatio": "火属性伤害提高",
"FireResistance": "火属性抗性提高",
"IceAddedRatio": "冰属性伤害提高",
"IceResistance": "冰属性抗性提高",
"ThunderAddedRatio": "雷属性伤害提高",
"ThunderResistance": "雷属性抗性提高",
"WindAddedRatio": "风属性伤害提高",
"WindResistance": "风属性抗性提高",
"QuantumAddedRatio": "量子属性伤害提高",
"QuantumResistance": "量子属性抗性提高",
"ImaginaryAddedRatio": "虚数属性伤害提高",
"ImaginaryResistance": "虚数属性抗性提高",
"BaseHP": "基础生命值提高<unbreak>#1[i]</unbreak>",
"HPDelta": "生命值",
"HPAddedRatio": "生命值百分比",
"BaseAttack": "基础攻击力提高<unbreak>#1[i]</unbreak>",
"AttackDelta": "攻击力",
"AttackAddedRatio": "攻击力百分比",
"BaseDefence": "基础防御力提高<unbreak>#1[i]</unbreak>",
"DefenceDelta": "防御力",
"DefenceAddedRatio": "防御力百分比",
"BaseSpeed": "速度",
"HealTakenRatio": "治疗量加成",
"PhysicalResistanceDelta": "物理属性抗性提高",
"FireResistanceDelta": "火属性抗性提高",
"IceResistanceDelta": "冰属性抗性提高",
"ThunderResistanceDelta": "雷属性抗性提高",
"WindResistanceDelta": "风属性抗性提高",
"QuantumResistanceDelta": "量子属性抗性提高",
"ImaginaryResistanceDelta": "虚数属性抗性提高",
"SpeedDelta": "速度"
}

View File

@ -0,0 +1,55 @@
{
"MaxHP": "生命值",
"Attack": "攻击力",
"Defence": "防御力",
"Speed": "速度",
"CriticalChance": "暴击率",
"CriticalDamage": "暴击伤害",
"BreakDamageAddedRatio": "击破特攻",
"BreakDamageAddedRatioBase": "击破特攻",
"HealRatio": "治疗量加成",
"MaxSP": "能量上限",
"SPRatio": "能量恢复效率",
"StatusProbability": "效果命中",
"StatusResistance": "效果抵抗",
"CriticalChanceBase": "暴击率",
"CriticalDamageBase": "暴击伤害",
"HealRatioBase": "治疗量加成",
"StanceBreakAddedRatio": "dev_失效字段",
"SPRatioBase": "能量恢复效率",
"StatusProbabilityBase": "效果命中",
"StatusResistanceBase": "效果抵抗",
"PhysicalAddedRatio": "物理属性伤害提高",
"PhysicalResistance": "物理属性抗性提高",
"FireAddedRatio": "火属性伤害提高",
"FireResistance": "火属性抗性提高",
"IceAddedRatio": "冰属性伤害提高",
"IceResistance": "冰属性抗性提高",
"ThunderAddedRatio": "雷属性伤害提高",
"ThunderResistance": "雷属性抗性提高",
"WindAddedRatio": "风属性伤害提高",
"WindResistance": "风属性抗性提高",
"QuantumAddedRatio": "量子属性伤害提高",
"QuantumResistance": "量子属性抗性提高",
"ImaginaryAddedRatio": "虚数属性伤害提高",
"ImaginaryResistance": "虚数属性抗性提高",
"BaseHP": "基础生命值提高<unbreak>#1[i]</unbreak>",
"HPDelta": "生命值",
"HPAddedRatio": "生命值百分比",
"BaseAttack": "基础攻击力提高<unbreak>#1[i]</unbreak>",
"AttackDelta": "攻击力",
"AttackAddedRatio": "攻击力百分比",
"BaseDefence": "基础防御力提高<unbreak>#1[i]</unbreak>",
"DefenceDelta": "防御力",
"DefenceAddedRatio": "防御力百分比",
"BaseSpeed": "速度",
"HealTakenRatio": "治疗量加成",
"PhysicalResistanceDelta": "物理属性抗性提高",
"FireResistanceDelta": "火属性抗性提高",
"IceResistanceDelta": "冰属性抗性提高",
"ThunderResistanceDelta": "雷属性抗性提高",
"WindResistanceDelta": "风属性抗性提高",
"QuantumResistanceDelta": "量子属性抗性提高",
"ImaginaryResistanceDelta": "虚数属性抗性提高",
"SpeedDelta": "速度"
}

View File

@ -0,0 +1,312 @@
{
"31011": 21,
"41011": 31,
"51011": 41,
"61011": 51,
"31012": 22,
"41012": 32,
"51012": 42,
"61012": 52,
"31013": 23,
"41013": 33,
"51013": 43,
"61013": 53,
"31014": 24,
"41014": 34,
"51014": 44,
"61014": 54,
"31021": 21,
"41021": 31,
"51021": 41,
"61021": 51,
"31022": 22,
"41022": 32,
"51022": 42,
"61022": 52,
"31023": 23,
"41023": 33,
"51023": 43,
"61023": 53,
"31024": 24,
"41024": 34,
"51024": 44,
"61024": 54,
"31031": 21,
"41031": 31,
"51031": 41,
"61031": 51,
"31032": 22,
"41032": 32,
"51032": 42,
"61032": 52,
"31033": 23,
"41033": 33,
"51033": 43,
"61033": 53,
"31034": 24,
"41034": 34,
"51034": 44,
"61034": 54,
"31041": 21,
"41041": 31,
"51041": 41,
"61041": 51,
"31042": 22,
"41042": 32,
"51042": 42,
"61042": 52,
"31043": 23,
"41043": 33,
"51043": 43,
"61043": 53,
"31044": 24,
"41044": 34,
"51044": 44,
"61044": 54,
"31051": 21,
"41051": 31,
"51051": 41,
"61051": 51,
"31052": 22,
"41052": 32,
"51052": 42,
"61052": 52,
"31053": 23,
"41053": 33,
"51053": 43,
"61053": 53,
"31054": 24,
"41054": 34,
"51054": 44,
"61054": 54,
"31061": 21,
"41061": 31,
"51061": 41,
"61061": 51,
"31062": 22,
"41062": 32,
"51062": 42,
"61062": 52,
"31063": 23,
"41063": 33,
"51063": 43,
"61063": 53,
"31064": 24,
"41064": 34,
"51064": 44,
"61064": 54,
"31071": 21,
"41071": 31,
"51071": 41,
"61071": 51,
"31072": 22,
"41072": 32,
"51072": 42,
"61072": 52,
"31073": 23,
"41073": 33,
"51073": 43,
"61073": 53,
"31074": 24,
"41074": 34,
"51074": 44,
"61074": 54,
"31081": 21,
"41081": 31,
"51081": 41,
"61081": 51,
"31082": 22,
"41082": 32,
"51082": 42,
"61082": 52,
"31083": 23,
"41083": 33,
"51083": 43,
"61083": 53,
"31084": 24,
"41084": 34,
"51084": 44,
"61084": 54,
"31091": 21,
"41091": 31,
"51091": 41,
"61091": 51,
"31092": 22,
"41092": 32,
"51092": 42,
"61092": 52,
"31093": 23,
"41093": 33,
"51093": 43,
"61093": 53,
"31094": 24,
"41094": 34,
"51094": 44,
"61094": 54,
"31101": 21,
"41101": 31,
"51101": 41,
"61101": 51,
"31102": 22,
"41102": 32,
"51102": 42,
"61102": 52,
"31103": 23,
"41103": 33,
"51103": 43,
"61103": 53,
"31104": 24,
"41104": 34,
"51104": 44,
"61104": 54,
"31111": 21,
"41111": 31,
"51111": 41,
"61111": 51,
"31112": 22,
"41112": 32,
"51112": 42,
"61112": 52,
"31113": 23,
"41113": 33,
"51113": 43,
"61113": 53,
"31114": 24,
"41114": 34,
"51114": 44,
"61114": 54,
"31121": 21,
"41121": 31,
"51121": 41,
"61121": 51,
"31122": 22,
"41122": 32,
"51122": 42,
"61122": 52,
"31123": 23,
"41123": 33,
"51123": 43,
"61123": 53,
"31124": 24,
"41124": 34,
"51124": 44,
"61124": 54,
"33015": 25,
"43015": 35,
"53015": 45,
"63015": 55,
"33016": 26,
"43016": 36,
"53016": 46,
"63016": 56,
"33025": 25,
"43025": 35,
"53025": 45,
"63025": 55,
"33026": 26,
"43026": 36,
"53026": 46,
"63026": 56,
"33035": 25,
"43035": 35,
"53035": 45,
"63035": 55,
"33036": 26,
"43036": 36,
"53036": 46,
"63036": 56,
"33045": 25,
"43045": 35,
"53045": 45,
"63045": 55,
"33046": 26,
"43046": 36,
"53046": 46,
"63046": 56,
"33055": 25,
"43055": 35,
"53055": 45,
"63055": 55,
"33056": 26,
"43056": 36,
"53056": 46,
"63056": 56,
"33065": 25,
"43065": 35,
"53065": 45,
"63065": 55,
"33066": 26,
"43066": 36,
"53066": 46,
"63066": 56,
"33075": 25,
"43075": 35,
"53075": 45,
"63075": 55,
"33076": 26,
"43076": 36,
"53076": 46,
"63076": 56,
"33085": 25,
"43085": 35,
"53085": 45,
"63085": 55,
"33086": 26,
"43086": 36,
"53086": 46,
"63086": 56,
"33095": 25,
"43095": 35,
"53095": 45,
"63095": 55,
"33096": 26,
"43096": 36,
"53096": 46,
"63096": 56,
"33105": 25,
"43105": 35,
"53105": 45,
"63105": 55,
"33106": 26,
"43106": 36,
"53106": 46,
"63106": 56,
"55001": 436,
"55002": 441,
"55003": 434,
"55004": 433,
"55005": 443,
"55006": 434,
"31131": 21,
"41131": 31,
"51131": 41,
"61131": 51,
"31132": 22,
"41132": 32,
"51132": 42,
"61132": 52,
"31133": 23,
"41133": 33,
"51133": 43,
"61133": 53,
"31134": 24,
"41134": 34,
"51134": 44,
"61134": 54,
"31141": 21,
"41141": 31,
"51141": 41,
"61141": 51,
"31142": 22,
"41142": 32,
"51142": 42,
"61142": 52,
"31143": 23,
"41143": 33,
"51143": 43,
"61143": 53,
"31144": 24,
"41144": 34,
"51144": 44,
"61144": 54
}

View File

@ -0,0 +1,312 @@
{
"31011": 2,
"31012": 2,
"31013": 2,
"31014": 2,
"31021": 2,
"31022": 2,
"31023": 2,
"31024": 2,
"31031": 2,
"31032": 2,
"31033": 2,
"31034": 2,
"31041": 2,
"31042": 2,
"31043": 2,
"31044": 2,
"31051": 2,
"31052": 2,
"31053": 2,
"31054": 2,
"31061": 2,
"31062": 2,
"31063": 2,
"31064": 2,
"31071": 2,
"31072": 2,
"31073": 2,
"31074": 2,
"31081": 2,
"31082": 2,
"31083": 2,
"31084": 2,
"31091": 2,
"31092": 2,
"31093": 2,
"31094": 2,
"31101": 2,
"31102": 2,
"31103": 2,
"31104": 2,
"31111": 2,
"31112": 2,
"31113": 2,
"31114": 2,
"31121": 2,
"31122": 2,
"31123": 2,
"31124": 2,
"31131": 2,
"31132": 2,
"31133": 2,
"31134": 2,
"31141": 2,
"31142": 2,
"31143": 2,
"31144": 2,
"33015": 2,
"33016": 2,
"33025": 2,
"33026": 2,
"33035": 2,
"33036": 2,
"33045": 2,
"33046": 2,
"33055": 2,
"33056": 2,
"33065": 2,
"33066": 2,
"33075": 2,
"33076": 2,
"33085": 2,
"33086": 2,
"33095": 2,
"33096": 2,
"33105": 2,
"33106": 2,
"41011": 3,
"41012": 3,
"41013": 3,
"41014": 3,
"41021": 3,
"41022": 3,
"41023": 3,
"41024": 3,
"41031": 3,
"41032": 3,
"41033": 3,
"41034": 3,
"41041": 3,
"41042": 3,
"41043": 3,
"41044": 3,
"41051": 3,
"41052": 3,
"41053": 3,
"41054": 3,
"41061": 3,
"41062": 3,
"41063": 3,
"41064": 3,
"41071": 3,
"41072": 3,
"41073": 3,
"41074": 3,
"41081": 3,
"41082": 3,
"41083": 3,
"41084": 3,
"41091": 3,
"41092": 3,
"41093": 3,
"41094": 3,
"41101": 3,
"41102": 3,
"41103": 3,
"41104": 3,
"41111": 3,
"41112": 3,
"41113": 3,
"41114": 3,
"41121": 3,
"41122": 3,
"41123": 3,
"41124": 3,
"41131": 3,
"41132": 3,
"41133": 3,
"41134": 3,
"41141": 3,
"41142": 3,
"41143": 3,
"41144": 3,
"43015": 3,
"43016": 3,
"43025": 3,
"43026": 3,
"43035": 3,
"43036": 3,
"43045": 3,
"43046": 3,
"43055": 3,
"43056": 3,
"43065": 3,
"43066": 3,
"43075": 3,
"43076": 3,
"43085": 3,
"43086": 3,
"43095": 3,
"43096": 3,
"43105": 3,
"43106": 3,
"51011": 4,
"51012": 4,
"51013": 4,
"51014": 4,
"51021": 4,
"51022": 4,
"51023": 4,
"51024": 4,
"51031": 4,
"51032": 4,
"51033": 4,
"51034": 4,
"51041": 4,
"51042": 4,
"51043": 4,
"51044": 4,
"51051": 4,
"51052": 4,
"51053": 4,
"51054": 4,
"51061": 4,
"51062": 4,
"51063": 4,
"51064": 4,
"51071": 4,
"51072": 4,
"51073": 4,
"51074": 4,
"51081": 4,
"51082": 4,
"51083": 4,
"51084": 4,
"51091": 4,
"51092": 4,
"51093": 4,
"51094": 4,
"51101": 4,
"51102": 4,
"51103": 4,
"51104": 4,
"51111": 4,
"51112": 4,
"51113": 4,
"51114": 4,
"51121": 4,
"51122": 4,
"51123": 4,
"51124": 4,
"51131": 4,
"51132": 4,
"51133": 4,
"51134": 4,
"51141": 4,
"51142": 4,
"51143": 4,
"51144": 4,
"53015": 4,
"53016": 4,
"53025": 4,
"53026": 4,
"53035": 4,
"53036": 4,
"53045": 4,
"53046": 4,
"53055": 4,
"53056": 4,
"53065": 4,
"53066": 4,
"53075": 4,
"53076": 4,
"53085": 4,
"53086": 4,
"53095": 4,
"53096": 4,
"53105": 4,
"53106": 4,
"55001": 4,
"55002": 4,
"55003": 4,
"55004": 4,
"55005": 4,
"55006": 4,
"61011": 5,
"61012": 5,
"61013": 5,
"61014": 5,
"61021": 5,
"61022": 5,
"61023": 5,
"61024": 5,
"61031": 5,
"61032": 5,
"61033": 5,
"61034": 5,
"61041": 5,
"61042": 5,
"61043": 5,
"61044": 5,
"61051": 5,
"61052": 5,
"61053": 5,
"61054": 5,
"61061": 5,
"61062": 5,
"61063": 5,
"61064": 5,
"61071": 5,
"61072": 5,
"61073": 5,
"61074": 5,
"61081": 5,
"61082": 5,
"61083": 5,
"61084": 5,
"61091": 5,
"61092": 5,
"61093": 5,
"61094": 5,
"61101": 5,
"61102": 5,
"61103": 5,
"61104": 5,
"61111": 5,
"61112": 5,
"61113": 5,
"61114": 5,
"61121": 5,
"61122": 5,
"61123": 5,
"61124": 5,
"61131": 5,
"61132": 5,
"61133": 5,
"61134": 5,
"61141": 5,
"61142": 5,
"61143": 5,
"61144": 5,
"63015": 5,
"63016": 5,
"63025": 5,
"63026": 5,
"63035": 5,
"63036": 5,
"63045": 5,
"63046": 5,
"63055": 5,
"63056": 5,
"63065": 5,
"63066": 5,
"63075": 5,
"63076": 5,
"63085": 5,
"63086": 5,
"63095": 5,
"63096": 5,
"63105": 5,
"63106": 5
}

View File

@ -0,0 +1,312 @@
{
"31011": 101,
"41011": 101,
"51011": 101,
"61011": 101,
"31012": 101,
"41012": 101,
"51012": 101,
"61012": 101,
"31013": 101,
"41013": 101,
"51013": 101,
"61013": 101,
"31014": 101,
"41014": 101,
"51014": 101,
"61014": 101,
"31021": 102,
"41021": 102,
"51021": 102,
"61021": 102,
"31022": 102,
"41022": 102,
"51022": 102,
"61022": 102,
"31023": 102,
"41023": 102,
"51023": 102,
"61023": 102,
"31024": 102,
"41024": 102,
"51024": 102,
"61024": 102,
"31031": 103,
"41031": 103,
"51031": 103,
"61031": 103,
"31032": 103,
"41032": 103,
"51032": 103,
"61032": 103,
"31033": 103,
"41033": 103,
"51033": 103,
"61033": 103,
"31034": 103,
"41034": 103,
"51034": 103,
"61034": 103,
"31041": 104,
"41041": 104,
"51041": 104,
"61041": 104,
"31042": 104,
"41042": 104,
"51042": 104,
"61042": 104,
"31043": 104,
"41043": 104,
"51043": 104,
"61043": 104,
"31044": 104,
"41044": 104,
"51044": 104,
"61044": 104,
"31051": 105,
"41051": 105,
"51051": 105,
"61051": 105,
"31052": 105,
"41052": 105,
"51052": 105,
"61052": 105,
"31053": 105,
"41053": 105,
"51053": 105,
"61053": 105,
"31054": 105,
"41054": 105,
"51054": 105,
"61054": 105,
"31061": 106,
"41061": 106,
"51061": 106,
"61061": 106,
"31062": 106,
"41062": 106,
"51062": 106,
"61062": 106,
"31063": 106,
"41063": 106,
"51063": 106,
"61063": 106,
"31064": 106,
"41064": 106,
"51064": 106,
"61064": 106,
"31071": 107,
"41071": 107,
"51071": 107,
"61071": 107,
"31072": 107,
"41072": 107,
"51072": 107,
"61072": 107,
"31073": 107,
"41073": 107,
"51073": 107,
"61073": 107,
"31074": 107,
"41074": 107,
"51074": 107,
"61074": 107,
"31081": 108,
"41081": 108,
"51081": 108,
"61081": 108,
"31082": 108,
"41082": 108,
"51082": 108,
"61082": 108,
"31083": 108,
"41083": 108,
"51083": 108,
"61083": 108,
"31084": 108,
"41084": 108,
"51084": 108,
"61084": 108,
"31091": 109,
"41091": 109,
"51091": 109,
"61091": 109,
"31092": 109,
"41092": 109,
"51092": 109,
"61092": 109,
"31093": 109,
"41093": 109,
"51093": 109,
"61093": 109,
"31094": 109,
"41094": 109,
"51094": 109,
"61094": 109,
"31101": 110,
"41101": 110,
"51101": 110,
"61101": 110,
"31102": 110,
"41102": 110,
"51102": 110,
"61102": 110,
"31103": 110,
"41103": 110,
"51103": 110,
"61103": 110,
"31104": 110,
"41104": 110,
"51104": 110,
"61104": 110,
"31111": 111,
"41111": 111,
"51111": 111,
"61111": 111,
"31112": 111,
"41112": 111,
"51112": 111,
"61112": 111,
"31113": 111,
"41113": 111,
"51113": 111,
"61113": 111,
"31114": 111,
"41114": 111,
"51114": 111,
"61114": 111,
"31121": 112,
"41121": 112,
"51121": 112,
"61121": 112,
"31122": 112,
"41122": 112,
"51122": 112,
"61122": 112,
"31123": 112,
"41123": 112,
"51123": 112,
"61123": 112,
"31124": 112,
"41124": 112,
"51124": 112,
"61124": 112,
"33015": 301,
"43015": 301,
"53015": 301,
"63015": 301,
"33016": 301,
"43016": 301,
"53016": 301,
"63016": 301,
"33025": 302,
"43025": 302,
"53025": 302,
"63025": 302,
"33026": 302,
"43026": 302,
"53026": 302,
"63026": 302,
"33035": 303,
"43035": 303,
"53035": 303,
"63035": 303,
"33036": 303,
"43036": 303,
"53036": 303,
"63036": 303,
"33045": 304,
"43045": 304,
"53045": 304,
"63045": 304,
"33046": 304,
"43046": 304,
"53046": 304,
"63046": 304,
"33055": 305,
"43055": 305,
"53055": 305,
"63055": 305,
"33056": 305,
"43056": 305,
"53056": 305,
"63056": 305,
"33065": 306,
"43065": 306,
"53065": 306,
"63065": 306,
"33066": 306,
"43066": 306,
"53066": 306,
"63066": 306,
"33075": 307,
"43075": 307,
"53075": 307,
"63075": 307,
"33076": 307,
"43076": 307,
"53076": 307,
"63076": 307,
"33085": 308,
"43085": 308,
"53085": 308,
"63085": 308,
"33086": 308,
"43086": 308,
"53086": 308,
"63086": 308,
"33095": 309,
"43095": 309,
"53095": 309,
"63095": 309,
"33096": 309,
"43096": 309,
"53096": 309,
"63096": 309,
"33105": 310,
"43105": 310,
"53105": 310,
"63105": 310,
"33106": 310,
"43106": 310,
"53106": 310,
"63106": 310,
"55001": 101,
"55002": 101,
"55003": 102,
"55004": 103,
"55005": 103,
"55006": 105,
"31131": 113,
"41131": 113,
"51131": 113,
"61131": 113,
"31132": 113,
"41132": 113,
"51132": 113,
"61132": 113,
"31133": 113,
"41133": 113,
"51133": 113,
"61133": 113,
"31134": 113,
"41134": 113,
"51134": 113,
"61134": 113,
"31141": 114,
"41141": 114,
"51141": 114,
"61141": 114,
"31142": 114,
"41142": 114,
"51142": 114,
"61142": 114,
"31143": 114,
"41143": 114,
"51143": 114,
"61143": 114,
"31144": 114,
"41144": 114,
"51144": 114,
"61144": 114
}

View File

@ -0,0 +1,163 @@
{
"101": {
"2": {
"Property": "HealRatioBase",
"Value": 0.10000000009313226
},
"4": {}
},
"102": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12000000011175871
},
"4": {
"Property": "SpeedAddedRatio",
"Value": 0.060000000055879354
}
},
"103": {
"2": {
"Property": "DefenceAddedRatio",
"Value": 0.1500000001396984
},
"4": {}
},
"104": {
"2": {
"Property": "IceAddedRatio",
"Value": 0.10000000009313226
},
"4": {}
},
"105": {
"2": {
"Property": "PhysicalAddedRatio",
"Value": 0.10000000009313226
},
"4": {}
},
"106": {
"2": {},
"4": {}
},
"107": {
"2": {
"Property": "FireAddedRatio",
"Value": 0.10000000009313226
},
"4": {}
},
"108": {
"2": {
"Property": "QuantumAddedRatio",
"Value": 0.10000000009313226
},
"4": {}
},
"109": {
"2": {
"Property": "ThunderAddedRatio",
"Value": 0.10000000009313226
},
"4": {}
},
"110": {
"2": {
"Property": "WindAddedRatio",
"Value": 0.10000000009313226
},
"4": {}
},
"111": {
"2": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.1600000001490116
},
"4": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.1600000001490116
}
},
"112": {
"2": {
"Property": "ImaginaryAddedRatio",
"Value": 0.10000000009313226
},
"4": {}
},
"301": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12000000011175871
}
},
"302": {
"2": {
"Property": "HPAddedRatio",
"Value": 0.12000000011175871
}
},
"303": {
"2": {
"Property": "StatusProbabilityBase",
"Value": 0.10000000009313226
}
},
"304": {
"2": {
"Property": "DefenceAddedRatio",
"Value": 0.1500000001396984
}
},
"305": {
"2": {
"Property": "CriticalDamageBase",
"Value": 0.1600000001490116
}
},
"306": {
"2": {
"Property": "CriticalChanceBase",
"Value": 0.0800000000745058
}
},
"307": {
"2": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.1600000001490116
}
},
"308": {
"2": {
"Property": "SPRatioBase",
"Value": 0.05000000004656613
}
},
"309": {
"2": {
"Property": "CriticalChanceBase",
"Value": 0.0800000000745058
}
},
"310": {
"2": {
"Property": "StatusResistanceBase",
"Value": 0.10000000009313226
}
},
"113": {
"2": {
"Property": "HPAddedRatio",
"Value": 0.12000000011175871
},
"4": {}
},
"114": {
"2": {
"Property": "SpeedAddedRatio",
"Value": 0.060000000055879354
},
"4": {}
}
}

View File

@ -0,0 +1,26 @@
{
"101": "云无留迹的过客",
"102": "野穗伴行的快枪手",
"103": "净庭教宗的圣骑士",
"104": "密林卧雪的猎人",
"105": "街头出身的拳王",
"106": "戍卫风雪的铁卫",
"107": "熔岩锻铸的火匠",
"108": "繁星璀璨的天才",
"109": "激奏雷电的乐队",
"110": "晨昏交界的翔鹰",
"111": "流星追迹的怪盗",
"112": "盗匪荒漠的废土客",
"113": "宝命长存的莳者",
"114": "骇域漫游的信使",
"301": "太空封印站",
"302": "不老者的仙舟",
"303": "泛银河商业公司",
"304": "筑城者的贝洛伯格",
"305": "星体差分机",
"306": "停转的萨尔索图",
"307": "盗贼公国塔利亚",
"308": "生命的翁瓦克",
"309": "繁星竞技场",
"310": "折断的龙骨"
}

View File

@ -0,0 +1,43 @@
{
"1001": "Ice",
"1002": "Wind",
"1003": "Fire",
"1004": "Imaginary",
"1005": "Thunder",
"1006": "Quantum",
"1008": "Thunder",
"1009": "Fire",
"1013": "Ice",
"1101": "Wind",
"1102": "Quantum",
"1103": "Thunder",
"1104": "Ice",
"1105": "Physical",
"1106": "Ice",
"1107": "Physical",
"1108": "Wind",
"1109": "Fire",
"1110": "Quantum",
"1111": "Physical",
"1112": "Fire",
"1201": "Quantum",
"1202": "Thunder",
"1203": "Imaginary",
"1204": "Thunder",
"1205": "Wind",
"1206": "Physical",
"1207": "Imaginary",
"1208": "Quantum",
"1209": "Ice",
"1210": "Fire",
"1211": "Thunder",
"1212": "Ice",
"1213": "Imaginary",
"8001": "Physical",
"8002": "Physical",
"8003": "Fire",
"8004": "Fire",
"1302": "Physical",
"1217": "Wind",
"1215": "Physical"
}

View File

@ -0,0 +1,43 @@
{
"1001": "March7th",
"1002": "DanHeng",
"1003": "Himeko",
"1004": "Welt",
"1005": "Kafka",
"1006": "SilverWolf",
"1008": "Arlan",
"1009": "Asta",
"1013": "Herta",
"1101": "Bronya",
"1102": "Seele",
"1103": "Serval",
"1104": "Gepard",
"1105": "Natasha",
"1106": "Pela",
"1107": "Clara",
"1108": "Sampo",
"1109": "Hook",
"1110": "Lynx",
"1111": "Luka",
"1112": "TopazandNumby",
"1201": "Qingque",
"1202": "Tingyun",
"1203": "Luocha",
"1204": "JingYuan",
"1205": "Blade",
"1206": "Sushang",
"1207": "Yukong",
"1208": "FuXuan",
"1209": "Yanqing",
"1210": "Guinaifen",
"1211": "Bailu",
"1212": "Jingliu",
"1213": "DanHeng•ImbibitorLunae",
"8001": "{NICKNAME}",
"8002": "{NICKNAME}",
"8003": "{NICKNAME}",
"8004": "{NICKNAME}",
"1302": "Argenti",
"1217": "Huohuo",
"1215": "Hanya"
}

View File

@ -0,0 +1,43 @@
{
"1001": "三月七",
"1002": "丹恒",
"1003": "姬子",
"1004": "瓦尔特",
"1005": "卡芙卡",
"1006": "银狼",
"1008": "阿兰",
"1009": "艾丝妲",
"1013": "黑塔",
"1101": "布洛妮娅",
"1102": "希儿",
"1103": "希露瓦",
"1104": "杰帕德",
"1105": "娜塔莎",
"1106": "佩拉",
"1107": "克拉拉",
"1108": "桑博",
"1109": "虎克",
"1110": "玲可",
"1111": "卢卡",
"1112": "托帕&账账",
"1201": "青雀",
"1202": "停云",
"1203": "罗刹",
"1204": "景元",
"1205": "刃",
"1206": "素裳",
"1207": "驭空",
"1208": "符玄",
"1209": "彦卿",
"1210": "桂乃芬",
"1211": "白露",
"1212": "镜流",
"1213": "丹恒•饮月",
"8001": "开拓者",
"8002": "开拓者",
"8003": "开拓者",
"8004": "开拓者",
"1302": "银枝",
"1217": "藿藿",
"1215": "寒鸦"
}

View File

@ -0,0 +1,43 @@
{
"1001": "4",
"1002": "4",
"1003": "5",
"1004": "5",
"1005": "5",
"1006": "5",
"1008": "4",
"1009": "4",
"1013": "4",
"1101": "5",
"1102": "5",
"1103": "4",
"1104": "5",
"1105": "4",
"1106": "4",
"1107": "5",
"1108": "4",
"1109": "4",
"1110": "4",
"1111": "4",
"1112": "5",
"1201": "4",
"1202": "4",
"1203": "5",
"1204": "5",
"1205": "5",
"1206": "4",
"1207": "4",
"1208": "5",
"1209": "5",
"1210": "4",
"1211": "5",
"1212": "5",
"1213": "5",
"8001": "5",
"8002": "5",
"8003": "5",
"8004": "5",
"1302": "5",
"1217": "5",
"1215": "4"
}

View File

@ -0,0 +1,43 @@
{
"1001": "4",
"1002": "4",
"1003": "5",
"1004": "5",
"1005": "5",
"1006": "5",
"1008": "4",
"1009": "4",
"1013": "4",
"1101": "5",
"1102": "5",
"1103": "4",
"1104": "5",
"1105": "4",
"1106": "4",
"1107": "5",
"1108": "4",
"1109": "4",
"1110": "4",
"1111": "4",
"1112": "5",
"1201": "4",
"1202": "4",
"1203": "5",
"1204": "5",
"1205": "5",
"1206": "4",
"1207": "4",
"1208": "5",
"1209": "5",
"1210": "4",
"1211": "5",
"1212": "5",
"1213": "5",
"8001": "5",
"8002": "5",
"8003": "5",
"8004": "5",
"1302": "5",
"1217": "5",
"1215": "4"
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,603 @@
{
"characters": {
"1001": [
"三月七",
"三月",
"小三月",
"阿七",
"冷面小粉龙",
"纠缠之缘",
"小仓唯",
"xcw"
],
"1002": [
"丹恒",
"冷面小青龙",
"闷葫芦"
],
"1003": [
"姬子",
"姬子阿姐"
],
"1004": [
"瓦尔特",
"瓦尔特杨",
"杨叔",
"牧月忍冬",
"约阿希姆诺基安维塔宁"
],
"1005": [
"卡芙卡",
"妈",
"妈妈"
],
"1006": [
"银狼",
"小板鸭",
"酷鸭",
"超级骇客"
],
"1008": [
"阿兰"
],
"1009": [
"艾丝妲",
"富婆",
"代理站长",
"知名不具"
],
"1013": [
"黑塔",
"天才俱乐部#83",
"天才俱乐部第83席",
"天才俱乐部第八十三席",
"黑塔女士"
],
"1101": [
"布洛妮娅",
"布洛妮娅兰德",
"兰德鸭",
"大板鸭",
"三涡轮增鸭"
],
"1102": [
"希儿",
"蝴蝶",
"希尔"
],
"1103": [
"希露瓦",
"希露瓦朗道",
"朗道家长女",
"贝洛伯格机械师"
],
"1104": [
"杰帕德",
"杰帕德朗道",
"杰哥",
"小杰杰"
],
"1105": [
"娜塔莎",
"娜塔",
"娜塔莎姐姐",
"老巫婆"
],
"1106": [
"佩拉",
"佩拉格娅谢尔盖耶夫娜",
"佩拉格娅",
"谢尔盖耶夫娜"
],
"1107": [
"克拉拉",
"猩红兔子",
"天才侦探少女",
"史瓦罗",
"史瓦罗发射器"
],
"1108": [
"桑博",
"桑博科斯基",
"深蓝帅哥",
"布鲁海尔波桑"
],
"1109": [
"虎克",
"漆黑的虎克大人"
],
"1110": [
"玲可"
],
"1111": [
"卢卡",
"铁臂卢卡",
"熔锤镇的卢卡"
],
"1112": [
"托帕&账账",
"托帕",
"账账",
"账账启动器"
],
"1201": [
"青雀",
"QQ"
],
"1202": [
"停云",
"屑狐狸",
"骚狐狸"
],
"1203": [
"罗刹",
"主教"
],
"1204": [
"景元",
"云骑将军",
"闭目将军"
],
"1205": [
"刃",
"应星",
"阿刃",
"点刀哥",
"笑面小黑龙"
],
"1206": [
"素裳",
"李素裳",
"李大枕头"
],
"1207": [
"驭空",
"星火之狐",
"司舵"
],
"1208": [
"符玄"
],
"1209": [
"彦卿",
"马彦卿",
"老马"
],
"1211": [
"白露",
"衔药龙女"
],
"1212": [
"镜流"
],
"1213": [
"丹恒•饮月",
"饮月君",
"饮月",
"龙丹"
],
"1217": [
"藿藿"
],
"1302": [
"银枝"
],
"8000": [
"开拓者",
"爷",
"星爷",
"恩公",
"复读机",
"脸接大招",
"银河球棒侠",
"机巧鸟捕手",
"天才少女侦探的助手"
],
"8001": [
"物理开拓者",
"毁灭开拓者",
"物主",
"物理主",
"毁灭主",
"开拓者物理",
"开拓者毁灭"
],
"8002": [
"物理女开拓者",
"毁灭女开拓者",
"物女主",
"物理女主",
"毁灭女主"
],
"8003": [
"火开拓者",
"存护开拓者",
"火主",
"存护主",
"开拓者火",
"开拓者存护"
],
"8004": [
"火女开拓者",
"存护女开拓者",
"火女主",
"存护女主"
]
},
"light_cones": {
"20000": [
"锋镝"
],
"20001": [
"物穰"
],
"20002": [
"天倾"
],
"20003": [
"琥珀"
],
"20004": [
"幽邃"
],
"20005": [
"齐颂"
],
"20006": [
"智库"
],
"20007": [
"离弦"
],
"20008": [
"嘉果"
],
"20009": [
"乐圮"
],
"20010": [
"戍御"
],
"20011": [
"渊环"
],
"20012": [
"轮契"
],
"20013": [
"灵钥"
],
"20014": [
"相抗"
],
"20015": [
"蕃息"
],
"20016": [
"俱殁"
],
"20017": [
"开疆"
],
"20018": [
"匿影"
],
"20019": [
"调和"
],
"20020": [
"睿见"
],
"21000": [
"一场术后对话"
],
"21001": [
"晚安与睡颜",
"晚安睡颜"
],
"21002": [
"余生的第一天"
],
"21003": [
"唯有沉默"
],
"21004": [
"记忆中的模样"
],
"21005": [
"鼹鼠党欢迎你",
"鼹鼠党"
],
"21006": [
"「我」的诞生",
"我的诞生"
],
"21007": [
"同一种心情"
],
"21008": [
"猎物的视线"
],
"21009": [
"朗道的选择"
],
"21010": [
"论剑"
],
"21011": [
"与行星相会"
],
"21012": [
"秘密誓心"
],
"21013": [
"别让世界静下来"
],
"21014": [
"此时恰好"
],
"21015": [
"决心如汗珠般闪耀"
],
"21016": [
"宇宙市场趋势"
],
"21017": [
"点个关注吧!",
"点个关注吧",
"点个关注"
],
"21018": [
"舞!舞!舞!",
"舞舞舞"
],
"21019": [
"在蓝天下"
],
"21020": [
"天才们的休憩"
],
"21021": [
"等价交换"
],
"21022": [
"延长记号"
],
"21023": [
"我们是地火"
],
"21024": [
"春水初生"
],
"21025": [
"过往未来"
],
"21026": [
"汪!散步时间!",
"汪散步时间",
"散步时间"
],
"21027": [
"早餐的仪式感"
],
"21028": [
"暖夜不会漫长"
],
"21029": [
"后会有期"
],
"21030": [
"这就是我啦!",
"这就是我啦"
],
"21031": [
"重返幽冥"
],
"21032": [
"镂月裁云之意",
"镂月裁云"
],
"21033": [
"无处可逃"
],
"21034": [
"今日亦是和平的一日",
"和平的一日"
],
"22000": [
"新手任务开始前"
],
"23000": [
"银河铁道之夜"
],
"23001": [
"于夜色中",
"希儿专武"
],
"23002": [
"无可取代的东西"
],
"23003": [
"但战斗还未结束"
],
"23004": [
"以世界之名"
],
"23005": [
"制胜的瞬间"
],
"23006": [
"只需等待"
],
"23007": [
"雨一直下"
],
"23016": [
"烦恼着,幸福着",
"烦恼着幸福着"
],
"23008": [
"棺的回响"
],
"23009": [
"到不了的彼岸"
],
"23010": [
"拂晓之前",
"景元专武"
],
"23011": [
"她已闭上双眼"
],
"23012": [
"如泥酣眠"
],
"23013": [
"时节不居"
],
"23015": [
"比阳光更明亮的"
],
"23017": [
"惊魂夜"
],
"23018": [
"片刻,留在眼底",
"片刻留在眼底",
"留在眼底"
],
"24000": [
"记一位星神的陨落",
"星神陨落",
"星神的陨落"
],
"24001": [
"星海巡航"
],
"24002": [
"记忆的质料"
],
"24003": [
"孤独的疗愈"
]
},
"relic_sets": {
"101": [
"云无留迹的过客",
"治疗套",
"过客"
],
"102": [
"野穗伴行的快枪手",
"攻击套",
"快枪手"
],
"103": [
"净庭教宗的圣骑士",
"防御套",
"圣骑士"
],
"104": [
"密林卧雪的猎人",
"冰套",
"猎人"
],
"105": [
"街头出身的拳王",
"物理套",
"拳王"
],
"106": [
"戍卫风雪的铁卫",
"减伤套",
"铁卫"
],
"107": [
"熔岩锻铸的火匠",
"火套",
"火匠"
],
"108": [
"繁星璀璨的天才",
"量子套",
"天才"
],
"109": [
"激奏雷电的乐队",
"雷套",
"乐队"
],
"110": [
"晨昏交界的翔鹰",
"风套",
"翔鹰"
],
"111": [
"流星追迹的怪盗",
"破盾套",
"怪盗"
],
"112": [
"盗匪荒漠的废土客",
"虚数套",
"废土客"
],
"113": [
"宝命长存的莳者",
"生命套",
"莳者"
],
"114": [
"骇域漫游的信使",
"速度套",
"信使"
],
"301": [
"太空封印站",
"太空站"
],
"302": [
"不老者的仙舟",
"不老者仙舟",
"不老仙舟",
"仙舟"
],
"303": [
"泛银河商业公司",
"银河商业公司",
"商业公司",
"公司"
],
"304": [
"筑城者的贝洛伯格",
"贝洛伯格",
"筑城者"
],
"305": [
"星体差分机",
"差分机"
],
"306": [
"停转的萨尔索图",
"萨尔索图",
"停转"
],
"307": [
"盗贼公国塔利亚",
"盗贼公国",
"塔利亚"
],
"308": [
"生命的翁瓦克",
"翁瓦克"
],
"309": [
"繁星竞技场",
"竞技场"
],
"310": [
"折断的龙骨",
"龙骨"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,248 @@
{
"100101": "记忆中的你",
"100102": "记忆中的它",
"100103": "记忆中的一切",
"100104": "不愿再失去",
"100105": "不想再忘却",
"100106": "就这样,一直…",
"100201": "穷高极天,亢盈难久",
"100202": "威制八毒,灭却炎烟",
"100203": "幽明变化,自在蟠跃",
"100204": "奋迅三昧,如日空居",
"100205": "一渧天水,六虚洪流",
"100206": "须绳缚身,沉潜勿用",
"100301": "童年",
"100302": "邂逅",
"100303": "自我",
"100304": "投入",
"100305": "梦想",
"100306": "开拓!",
"100401": "名的传承",
"100402": "星的凝聚",
"100403": "和平的祈愿",
"100404": "义的名号",
"100405": "善的力量",
"100406": "光明的未来",
"100501": "无穷动!无穷",
"100502": "狂想者,呜咽",
"100503": "我赞美,即兴",
"100504": "把宣叙呈献给",
"100505": "只有今晚奏鸣",
"100506": "回旋,悄悄地",
"100601": "社会工程",
"100602": "僵尸网络",
"100603": "攻击载荷",
"100604": "反弹端口",
"100605": "暴力破解",
"100606": "重叠网络",
"100801": "万死不辞",
"100802": "除制去缚",
"100803": "重剑强攻",
"100804": "绝处反击",
"100805": "全力倾注",
"100806": "以身作引",
"100901": "星有无言之歌",
"100902": "月见圆缺之意",
"100903": "黄道陨石之变",
"100904": "极光显现之时",
"100905": "深空天体之谜",
"100906": "眠于银河之下",
"101301": "落井当下石",
"101302": "得胜必追击",
"101303": "我就是这样女子",
"101304": "打人要打脸",
"101305": "骂人不留口",
"101306": "世上没人能负我",
"110101": "养精蓄锐",
"110102": "快速行军",
"110103": "鼓炮齐鸣",
"110104": "攻其不备",
"110105": "所向克捷",
"110106": "气贯长虹",
"110201": "斩尽",
"110202": "蝶舞",
"110203": "缭乱",
"110204": "掠影",
"110205": "锋锐",
"110206": "离析",
"110301": "余音绕梁",
"110302": "安可!",
"110303": "听,齿轮的心跳",
"110304": "制造噪音吧!",
"110305": "贝洛伯格最强音!",
"110306": "这一曲,贯穿天穹!",
"110401": "恪尽职守",
"110402": "余寒",
"110403": "永不陷落",
"110404": "精诚所至",
"110405": "拳似寒铁",
"110406": "不屈的决意",
"110501": "遍识药理",
"110502": "临床研学",
"110503": "对症下药",
"110504": "妙手回春",
"110505": "医治未病",
"110506": "医者仁心",
"110601": "胜利反馈",
"110602": "疾进不止",
"110603": "压制升级",
"110604": "完全剖析",
"110605": "零度妨害",
"110606": "疲弱追击",
"110701": "高大的背影",
"110702": "紧紧的拥抱",
"110703": "冰冷的钢甲",
"110704": "家人的温暖",
"110705": "小小的承诺",
"110706": "长久的陪伴",
"110801": "加码的爱",
"110802": "热情会传染",
"110803": "大数字!",
"110804": "爱之深,恨之切",
"110805": "超大数字!",
"110806": "消费升级",
"110901": "早睡早起很健康",
"110902": "吃好喝好长身体",
"110903": "不挑不选全都要",
"110904": "稀里糊涂没关系",
"110905": "好事留名鼹鼠党",
"110906": "随时准备打坏人",
"111001": "远行雪杖的清晨",
"111002": "便携炉具的正午",
"111003": "雪崩信标的午后",
"111004": "露营篝火的薄暮",
"111005": "极光红茶的新夜",
"111006": "测绘图纸的黎明",
"111101": "争斗不休",
"111102": "敌弱,我强",
"111103": "为擂台而生",
"111104": "百折不回",
"111105": "地火之魂",
"111106": "冠军应得的喝彩",
"111201": "未来市场",
"111202": "善意收购",
"111203": "抓大放小",
"111204": "敏捷处理",
"111205": "需求膨胀",
"111206": "激励机制",
"120101": "散勇化骁摸幺鱼",
"120102": "棋枰作枕好入眠",
"120103": "观琼视茕门前清",
"120104": "帝垣翔鳞和绝张",
"120105": "七星流离全不靠",
"120106": "虚心平意候枭卢",
"120201": "春风得意,时运驰骋",
"120202": "君子惠渥,晏笑承之",
"120203": "青丘遗泽",
"120204": "鸣火机变,度时察势",
"120205": "绥绥狐魅",
"120206": "和气生财,泽盈四方",
"120301": "濯洗生者",
"120302": "净庭赐礼",
"120303": "愚人试探",
"120304": "荆冠审判",
"120305": "受难之痕",
"120306": "皆归尘土",
"120401": "星流霆击碎昆冈",
"120402": "戎戈动地开天阵",
"120403": "移锋惊电冲霄汉",
"120404": "刃卷横云落玉沙",
"120405": "百战弃躯轻死生",
"120406": "威灵有应破敌雠",
"120501": "剑录大限,地狱变相",
"120502": "支离旧梦,万端遗恨",
"120503": "冶炼玄钢,铣淬寒芒",
"120504": "泉台歧路,百骸回春",
"120505": "十王判死,业镜悬照",
"120506": "命留魂销,复返此身",
"120601": "游刃有余",
"120602": "其身百炼",
"120603": "传古剑流",
"120604": "其心百辟",
"120605": "太虚神意",
"120606": "上善若水",
"120701": "天舶飞将,枕弧待战",
"120702": "青霄驰骋,驱驭苍穹",
"120703": "危弓未辍,执射不宁",
"120704": "百里闻风,九曲响镝",
"120705": "井仪贯侯,疾羽参连",
"120706": "弦栝如雷,铣珧激荡",
"120801": "司危",
"120802": "柔兆",
"120803": "直符",
"120804": "格泽",
"120805": "计神",
"120806": "种陵",
"120901": "素刃",
"120902": "空明",
"120903": "剑胎",
"120904": "霜厉",
"120905": "武骨",
"120906": "自在",
"121001": "倒立吃面条",
"121002": "刷牙吹口哨",
"121003": "胸口碎大石",
"121004": "金枪锁咽喉",
"121005": "吞剑通脊背",
"121006": "徒手接子弹",
"121101": "百脉甘津宁神久",
"121102": "壶中洞天云螭眠",
"121103": "掌间乾坤便通玄",
"121104": "肘后备急除外障",
"121105": "方定一倾浣俗尘",
"121106": "龙漦吐哺胜金丹",
"121201": "月犯天关",
"121202": "朔晕七星",
"121203": "半璧迫望",
"121204": "持秉玄烛",
"121205": "晦入三台",
"121206": "蚀变于娄",
"121301": "萦天",
"121302": "九斿",
"121303": "云旂",
"121304": "嘲风",
"121305": "偃蹇",
"121306": "见谯",
"800101": "坠临万界的星芒",
"800102": "因缘假合的人身",
"800103": "揭示前路的言灵",
"800104": "凝眸毁灭的瞬间",
"800105": "劫余重生的希望",
"800106": "拓宇行天的意志",
"800201": "坠临万界的星芒",
"800202": "因缘假合的人身",
"800203": "揭示前路的言灵",
"800204": "凝眸毁灭的瞬间",
"800205": "劫余重生的希望",
"800206": "拓宇行天的意志",
"800301": "大地芯髓的鸣动",
"800302": "古老寒铁的坚守",
"800303": "砌造未来的蓝图",
"800304": "驻留文明的誓言",
"800305": "点燃光焰的勇气",
"800306": "永屹城垣的壁垒",
"800401": "大地芯髓的鸣动",
"800402": "古老寒铁的坚守",
"800403": "砌造未来的蓝图",
"800404": "驻留文明的誓言",
"800405": "点燃光焰的勇气",
"800406": "永屹城垣的壁垒",
"130201": "审美王国的缺口",
"130202": "玛瑙石的谦卑",
"130203": "荆棘路的荣光",
"130204": "号角的奉献",
"130205": "宇宙某处的雪",
"130206": "「你」的光芒",
"121701": "岁阳寄体,妖邪依凭",
"121702": "判官书符,镇尾锁灵",
"121703": "贞凶体质,烛火招萤",
"121704": "坐卧不离,争拗难宁",
"121705": "降妖捉鬼,十王敕令",
"121706": "同休共戚,相须而行",
"121501": "一心",
"121502": "二观",
"121503": "三尘",
"121504": "四谛",
"121505": "五阴",
"121506": "六正"
}

View File

@ -0,0 +1,262 @@
{
"100101": "Normal",
"100103": "Ultra",
"100104": "",
"100106": "MazeNormal",
"100107": "Maze",
"100201": "Normal",
"100202": "BPSkill",
"100203": "Ultra",
"100204": "",
"100206": "MazeNormal",
"100207": "Maze",
"100301": "Normal",
"100302": "BPSkill",
"100303": "Ultra",
"100304": "",
"100306": "MazeNormal",
"100307": "Maze",
"100401": "Normal",
"100402": "BPSkill",
"100403": "Ultra",
"100404": "",
"100406": "MazeNormal",
"100407": "Maze",
"100501": "Normal",
"100502": "BPSkill",
"100503": "Ultra",
"100504": "",
"100506": "MazeNormal",
"100507": "Maze",
"100801": "Normal",
"100802": "BPSkill",
"100803": "Ultra",
"100804": "",
"100806": "MazeNormal",
"100807": "Maze",
"100901": "Normal",
"100902": "BPSkill",
"100903": "Ultra",
"100904": "",
"100906": "MazeNormal",
"100907": "Maze",
"101301": "Normal",
"101302": "BPSkill",
"101303": "Ultra",
"101304": "",
"101306": "MazeNormal",
"101307": "Maze",
"110101": "Normal",
"110102": "BPSkill",
"110103": "Ultra",
"110104": "",
"110106": "MazeNormal",
"110107": "Maze",
"110201": "Normal",
"110202": "BPSkill",
"110203": "Ultra",
"110204": "",
"110206": "MazeNormal",
"110207": "Maze",
"110301": "Normal",
"110302": "BPSkill",
"110303": "Ultra",
"110304": "",
"110306": "MazeNormal",
"110307": "Maze",
"110401": "Normal",
"110402": "BPSkill",
"110403": "Ultra",
"110404": "",
"110406": "MazeNormal",
"110407": "Maze",
"110501": "Normal",
"110502": "BPSkill",
"110503": "Ultra",
"110504": "",
"110506": "MazeNormal",
"110601": "Normal",
"110602": "BPSkill",
"110604": "",
"110606": "MazeNormal",
"110607": "Maze",
"110701": "Normal",
"110702": "BPSkill",
"110703": "Ultra",
"110704": "",
"110706": "MazeNormal",
"110707": "Maze",
"110801": "Normal",
"110802": "BPSkill",
"110806": "MazeNormal",
"110807": "Maze",
"110901": "Normal",
"110902": "BPSkill",
"110903": "Ultra",
"110904": "",
"110906": "MazeNormal",
"110907": "Maze",
"110909": "BPSkill",
"111001": "Normal",
"111002": "BPSkill",
"111003": "Ultra",
"111004": "",
"111006": "MazeNormal",
"111007": "Maze",
"111101": "Normal",
"111108": "Normal",
"111103": "Ultra",
"111106": "MazeNormal",
"120101": "Normal",
"120108": "Normal",
"120103": "Ultra",
"120106": "MazeNormal",
"120107": "Maze",
"120201": "Normal",
"120206": "MazeNormal",
"120301": "Normal",
"120306": "MazeNormal",
"120307": "Maze",
"120501": "Normal",
"120508": "Normal",
"120502": "BPSkill",
"120503": "Ultra",
"120504": "",
"120506": "MazeNormal",
"120507": "Maze",
"120601": "Normal",
"120604": "",
"120606": "MazeNormal",
"120607": "Maze",
"120701": "Normal",
"120702": "BPSkill",
"120703": "Ultra",
"120704": "",
"120706": "MazeNormal",
"120707": "Maze",
"120801": "Normal",
"120802": "BPSkill",
"120803": "Ultra",
"120804": "",
"120806": "MazeNormal",
"120807": "Maze",
"120901": "Normal",
"120902": "BPSkill",
"120903": "Ultra",
"120904": "",
"120906": "MazeNormal",
"120907": "Maze",
"121001": "Normal",
"121002": "BPSkill",
"121003": "Ultra",
"121004": "",
"121006": "MazeNormal",
"121007": "Maze",
"121101": "Normal",
"121102": "BPSkill",
"121103": "Ultra",
"121104": "",
"121106": "MazeNormal",
"121107": "Maze",
"121301": "Normal",
"121308": "Normal",
"121310": "Normal",
"121312": "Normal",
"121302": "BPSkill",
"121303": "Ultra",
"121304": "",
"121306": "MazeNormal",
"121307": "Maze",
"800101": "Normal",
"800102": "BPSkill",
"800103": "Ultra",
"800104": "",
"800106": "MazeNormal",
"800107": "Maze",
"800108": "Ultra",
"800109": "Ultra",
"800201": "Normal",
"800202": "BPSkill",
"800203": "Ultra",
"800204": "",
"800206": "MazeNormal",
"800207": "Maze",
"800208": "Ultra",
"800209": "Ultra",
"800301": "Normal",
"800308": "Normal",
"800302": "BPSkill",
"800303": "Ultra",
"800304": "",
"800306": "MazeNormal",
"800307": "Maze",
"800401": "Normal",
"800408": "Normal",
"800402": "BPSkill",
"800403": "Ultra",
"800404": "",
"800406": "MazeNormal",
"800407": "Maze",
"100601": "Normal",
"100602": "BPSkill",
"100603": "Ultra",
"100604": "",
"100606": "MazeNormal",
"100607": "Maze",
"120401": "Normal",
"120402": "BPSkill",
"120403": "Ultra",
"120404": "",
"120406": "MazeNormal",
"120407": "Maze",
"909807": "Maze",
"110603": "Ultra",
"110507": "Maze",
"120302": "BPSkill",
"111201": "Normal",
"111206": "MazeNormal",
"111207": "Maze",
"120303": "Ultra",
"120304": "",
"100102": "BPSkill",
"121309": "BPSkill",
"110803": "Ultra",
"110804": "",
"111102": "BPSkill",
"111104": "",
"111107": "Maze",
"120202": "BPSkill",
"120203": "Ultra",
"120204": "",
"120207": "Maze",
"120102": "BPSkill",
"120104": "",
"120602": "BPSkill",
"120603": "Ultra",
"111202": "BPSkill",
"111203": "Ultra",
"111204": "",
"121203": "Ultra",
"121204": "",
"121202": "BPSkill",
"121201": "Normal",
"121209": "BPSkill",
"121206": "MazeNormal",
"121207": "Maze",
"130201": "Normal",
"130202": "BPSkill",
"130203": "Ultra",
"130214": "Ultra",
"130204": "",
"130207": "Maze",
"121701": "Normal",
"121702": "BPSkill",
"121703": "Ultra",
"121704": "",
"121707": "Maze",
"121501": "Normal",
"121502": "BPSkill",
"121503": "Ultra",
"121504": "",
"121507": "Maze"
}

View File

@ -0,0 +1,262 @@
{
"100101": "极寒的弓矢",
"100103": "冰刻箭雨之时",
"100104": "少女的特权",
"100106": "攻击",
"100107": "冻人的瞬间",
"100201": "云骑枪术•朔风",
"100202": "云骑枪术•疾雨",
"100203": "洞天幻化,长梦一觉",
"100204": "寸长寸强",
"100206": "攻击",
"100207": "破敌锋芒",
"100301": "武装调律",
"100302": "熔核爆裂",
"100303": "天坠之火",
"100304": "乘胜追击",
"100306": "攻击",
"100307": "不完全燃烧",
"100401": "重力压制",
"100402": "虚空断界",
"100403": "拟似黑洞",
"100404": "时空扭曲",
"100406": "攻击",
"100407": "画地为牢",
"100501": "夜间喧嚣不止",
"100502": "月光摩挲连绵",
"100503": "悲剧尽头的颤音",
"100504": "温柔亦同残酷",
"100506": "攻击",
"100507": "宽恕无关慈悲",
"100801": "如雷疾行",
"100802": "禁锢解除",
"100803": "狂者制裁",
"100804": "至痛至怒",
"100806": "攻击",
"100807": "极速收割",
"100901": "光谱射线",
"100902": "流星群落",
"100903": "星空祝言",
"100904": "天象学",
"100906": "攻击",
"100907": "灵光一现",
"101301": "看什么看",
"101302": "一锤子买卖",
"101303": "是魔法,我加了魔法",
"101304": "还是我来吧",
"101306": "攻击",
"101307": "可以优化一下",
"110101": "驭风的子弹",
"110102": "作战再部署",
"110103": "贝洛伯格进行曲",
"110104": "先人一步",
"110106": "攻击",
"110107": "在旗帜下",
"110201": "强袭",
"110202": "归刃",
"110203": "乱蝶",
"110204": "再现",
"110206": "攻击",
"110207": "幻身",
"110301": "雷鸣音阶",
"110302": "电光石火间",
"110303": "机械热潮登场!",
"110304": "燃情和弦",
"110306": "攻击",
"110307": "晚安,贝洛伯格",
"110401": "一意之拳",
"110402": "震慑之击",
"110403": "永屹之壁",
"110404": "不屈之身",
"110406": "攻击",
"110407": "有情之证",
"110501": "仁慈的背面",
"110502": "爱,救护与抉择",
"110503": "新生之礼",
"110504": "生机焕发",
"110506": "攻击",
"110601": "冰点射击",
"110602": "低温妨害",
"110604": "数据采集",
"110606": "攻击",
"110607": "先发制人",
"110701": "我也想帮上忙",
"110702": "史瓦罗在看着你",
"110703": "是约定不是命令",
"110704": "因为我们是家人",
"110706": "攻击",
"110707": "胜利的小小代价",
"110801": "酷炫的刀花",
"110802": "反复横跳的爱",
"110806": "攻击",
"110807": "你最闪亮",
"110901": "喂!小心火烛",
"110902": "嘿!记得虎克吗",
"110903": "轰!飞来焰火",
"110904": "哈!火上浇油",
"110906": "攻击",
"110907": "哎!瞧这一团糟",
"110909": "嘿!记得虎克吗",
"111001": "冰攀前齿技术",
"111002": "盐渍野营罐头",
"111003": "雪原急救方案",
"111004": "户外生存经验",
"111006": "攻击",
"111007": "巧克力能量棒",
"111101": "直冲拳",
"111108": "直冲碎天拳",
"111103": "制胜一击",
"111106": "攻击",
"120101": "门前清",
"120108": "杠上开花!",
"120103": "四幺暗刻?和!",
"120106": "攻击",
"120107": "独弈之乐",
"120201": "逐客令",
"120206": "攻击",
"120301": "黑渊的棘刺",
"120306": "攻击",
"120307": "愚者的悲悯",
"120501": "支离剑",
"120508": "无间剑树",
"120502": "地狱变",
"120503": "大辟万死",
"120504": "倏忽恩赐",
"120506": "攻击",
"120507": "业途风",
"120601": "云骑剑经 • 素霓",
"120604": "游刃若水",
"120606": "攻击",
"120607": "云骑剑经 • 叩阵",
"120701": "流镝",
"120702": "天阙鸣弦",
"120703": "贯云饮羽",
"120704": "箭彻七札",
"120706": "攻击",
"120707": "云鸢逐风",
"120801": "始击岁星",
"120802": "太微行棋,灵台示影",
"120803": "天律大衍,历劫归一",
"120804": "乾清坤夷,否极泰来",
"120806": "攻击",
"120807": "岁记否泰,固守四郭",
"120901": "霜锋点寒芒",
"120902": "遥击三尺水",
"120903": "快雨燕相逐",
"120904": "呼剑如影",
"120906": "攻击",
"120907": "御剑真诀",
"121001": "劈头满堂彩",
"121002": "迎面开门红",
"121003": "给您来段看家戏",
"121004": "古来君子养艺人",
"121006": "攻击",
"121007": "耍耍把式卖卖艺",
"121101": "望 、闻、问…蹴!",
"121102": "云吟乍涌坠珠露",
"121103": "匏蛟跃渊先雷音",
"121104": "奔走悬壶济世长",
"121106": "攻击",
"121107": "徜徉灵泽病恙短",
"121301": "泽芝",
"121308": "瞬华",
"121310": "天矢阴",
"121312": "盘拏耀跃",
"121302": "龙力自在",
"121303": "苍龙傲睨,劫水濯世",
"121304": "亢心",
"121306": "攻击",
"121307": "掣空如虹",
"800101": "再见安打",
"800102": "安息全垒打",
"800103": "星尘王牌",
"800104": "牵制盗垒",
"800106": "攻击",
"800107": "不灭三振",
"800108": "全胜•再见安打",
"800109": "全胜•安息全垒打",
"800201": "再见安打",
"800202": "安息全垒打",
"800203": "星尘王牌",
"800204": "牵制盗垒",
"800206": "攻击",
"800207": "不灭三振",
"800208": "全胜•再见安打",
"800209": "全胜•安息全垒打",
"800301": "穿彻坚冰的烈芒",
"800308": "穿彻坚冰的烈芒",
"800302": "炽燃不灭的琥珀",
"800303": "陷阵无回的炎枪",
"800304": "筑城者遗宝",
"800306": "攻击",
"800307": "守护者召令",
"800401": "穿彻坚冰的烈芒",
"800408": "穿彻坚冰的烈芒",
"800402": "炽燃不灭的琥珀",
"800403": "陷阵无回的炎枪",
"800404": "筑城者遗宝",
"800406": "攻击",
"800407": "守护者召令",
"100601": "|系统警告|",
"100602": "是否允许更改?",
"100603": "|账号已封禁|",
"100604": "等待程序响应…",
"100606": "攻击",
"100607": "|强制结束进程|",
"120401": "石火流光",
"120402": "紫霄震曜",
"120403": "吾身光明",
"120404": "斩勘神形",
"120406": "攻击",
"120407": "摄召威灵",
"909807": "dev_秘技",
"110603": "领域压制",
"110507": "催眠研习",
"120302": "白花的祈望",
"111201": "赤字…",
"111206": "攻击",
"111207": "明补",
"120303": "归葬的遂愿",
"120304": "生息的轮转",
"100102": "可爱即是正义",
"121309": "取消",
"110803": "惊喜礼盒",
"110804": "撕风的匕首",
"111102": "裂伤拳",
"111104": "火花四溅",
"111107": "抢先者",
"120202": "祥音和韵",
"120203": "庆云光覆仪祷",
"120204": "紫电扶摇",
"120207": "惠风和畅",
"120102": "海底捞月",
"120104": "帝垣琼玉",
"120602": "云骑剑经 • 山倾",
"120603": "太虚形蕴 • 烛夜",
"111202": "支付困难?",
"111203": "扭亏为盈!",
"111204": "猪市?!",
"121203": "昙华生灭,天河泻梦",
"121204": "澹月转魄",
"121202": "无罅飞光",
"121201": "流影方晖",
"121209": "寒川映月",
"121206": "攻击",
"121207": "古镜照神",
"130201": "芬芳一现",
"130202": "公正,此处盛放",
"130203": "驻于花庭,赐与尽美",
"130214": "驻「我」华庭,授予至勋",
"130204": "崇高的客体",
"130207": "纯粹高洁宣言",
"121701": "令旗•征风召雨",
"121702": "灵符•保命护身",
"121703": "尾巴•遣神役鬼",
"121704": "凭附•气通天真",
"121707": "凶煞•劾压鬼物",
"121501": "冥谶天笔",
"121502": "生灭系缚",
"121503": "十王敕令,遍土遵行",
"121504": "罚恶",
"121507": "判冥"
}

View File

@ -0,0 +1,262 @@
{
"100101": "单攻",
"100103": "群攻",
"100104": "单攻",
"100106": "",
"100107": "",
"100201": "单攻",
"100202": "单攻",
"100203": "单攻",
"100204": "强化",
"100206": "",
"100207": "强化",
"100301": "单攻",
"100302": "扩散",
"100303": "群攻",
"100304": "群攻",
"100306": "",
"100307": "妨害",
"100401": "单攻",
"100402": "弹射",
"100403": "群攻",
"100404": "强化",
"100406": "",
"100407": "妨害",
"100501": "单攻",
"100502": "扩散",
"100503": "群攻",
"100504": "单攻",
"100506": "",
"100507": "",
"100801": "单攻",
"100802": "单攻",
"100803": "扩散",
"100804": "强化",
"100806": "",
"100807": "",
"100901": "单攻",
"100902": "弹射",
"100903": "辅助",
"100904": "辅助",
"100906": "",
"100907": "",
"101301": "单攻",
"101302": "群攻",
"101303": "群攻",
"101304": "群攻",
"101306": "",
"101307": "强化",
"110101": "单攻",
"110102": "辅助",
"110103": "辅助",
"110104": "强化",
"110106": "",
"110107": "辅助",
"110201": "单攻",
"110202": "单攻",
"110203": "单攻",
"110204": "强化",
"110206": "",
"110207": "强化",
"110301": "单攻",
"110302": "扩散",
"110303": "群攻",
"110304": "强化",
"110306": "",
"110307": "",
"110401": "单攻",
"110402": "妨害",
"110403": "防御",
"110404": "回复",
"110406": "",
"110407": "防御",
"110501": "单攻",
"110502": "回复",
"110503": "回复",
"110504": "强化",
"110506": "",
"110601": "单攻",
"110602": "妨害",
"110604": "辅助",
"110606": "",
"110607": "",
"110701": "单攻",
"110702": "群攻",
"110703": "强化",
"110704": "单攻",
"110706": "",
"110707": "",
"110801": "单攻",
"110802": "弹射",
"110806": "",
"110807": "妨害",
"110901": "单攻",
"110902": "单攻",
"110903": "单攻",
"110904": "强化",
"110906": "",
"110907": "",
"110909": "扩散",
"111001": "单攻",
"111002": "回复",
"111003": "回复",
"111004": "回复",
"111006": "单攻",
"111007": "回复",
"111101": "单攻",
"111108": "单攻",
"111103": "单攻",
"111106": "",
"120101": "单攻",
"120108": "扩散",
"120103": "群攻",
"120106": "",
"120107": "强化",
"120201": "单攻",
"120206": "",
"120301": "单攻",
"120306": "",
"120307": "回复",
"120501": "单攻",
"120508": "扩散",
"120502": "强化",
"120503": "扩散",
"120504": "群攻",
"120506": "",
"120507": "",
"120601": "单攻",
"120604": "强化",
"120606": "",
"120607": "",
"120701": "单攻",
"120702": "辅助",
"120703": "单攻",
"120704": "强化",
"120706": "",
"120707": "强化",
"120801": "单攻",
"120802": "防御",
"120803": "群攻",
"120804": "回复",
"120806": "",
"120807": "防御",
"120901": "单攻",
"120902": "单攻",
"120903": "单攻",
"120904": "单攻",
"120906": "",
"120907": "强化",
"121001": "单攻",
"121002": "扩散",
"121003": "群攻",
"121004": "妨害",
"121006": "",
"121007": "",
"121101": "单攻",
"121102": "回复",
"121103": "回复",
"121104": "回复",
"121106": "",
"121107": "回复",
"121301": "单攻",
"121308": "单攻",
"121310": "扩散",
"121312": "扩散",
"121302": "强化",
"121303": "扩散",
"121304": "强化",
"121306": "",
"121307": "强化",
"800101": "单攻",
"800102": "扩散",
"800103": "强化",
"800104": "强化",
"800106": "",
"800107": "回复",
"800108": "单攻",
"800109": "扩散",
"800201": "单攻",
"800202": "扩散",
"800203": "强化",
"800204": "强化",
"800206": "",
"800207": "回复",
"800208": "单攻",
"800209": "扩散",
"800301": "单攻",
"800308": "扩散",
"800302": "防御",
"800303": "群攻",
"800304": "强化",
"800306": "",
"800307": "防御",
"800401": "单攻",
"800408": "扩散",
"800402": "防御",
"800403": "群攻",
"800404": "强化",
"800406": "",
"800407": "防御",
"100601": "单攻",
"100602": "妨害",
"100603": "妨害",
"100604": "妨害",
"100606": "",
"100607": "",
"120401": "单攻",
"120402": "群攻",
"120403": "群攻",
"120404": "弹射",
"120406": "",
"120407": "强化",
"909807": "回复",
"110603": "妨害",
"110507": "",
"120302": "回复",
"111201": "单攻",
"111206": "",
"111207": "强化",
"120303": "群攻",
"120304": "回复",
"100102": "防御",
"121309": "取消",
"110803": "妨害",
"110804": "强化",
"111102": "单攻",
"111104": "强化",
"111107": "",
"120202": "辅助",
"120203": "辅助",
"120204": "强化",
"120207": "辅助",
"120102": "强化",
"120104": "强化",
"120602": "单攻",
"120603": "单攻",
"111202": "单攻",
"111203": "强化",
"111204": "单攻",
"121203": "扩散",
"121204": "强化",
"121202": "单攻",
"121201": "单攻",
"121209": "扩散",
"121206": "",
"121207": "妨害",
"130201": "单攻",
"130202": "群攻",
"130203": "群攻",
"130214": "群攻",
"130204": "强化",
"130207": "妨害",
"121701": "单攻",
"121702": "回复",
"121703": "辅助",
"121704": "回复",
"121707": "妨害",
"121501": "单攻",
"121502": "单攻",
"121503": "强化",
"121504": "辅助",
"121507": ""
}

View File

@ -0,0 +1,29 @@
from typing import Dict, Union
from msgspec import Struct
class RelicSetStatusAdd(Struct):
Property: str
Value: float
class RelicSetSkillModel(Struct):
RelicSet: Dict[str, Dict[str, Union[RelicSetStatusAdd, None]]]
@classmethod
def from_json(cls, data: Dict):
return cls(
RelicSet={
str(k): {
str(k2): RelicSetStatusAdd(
Property=v2["Property"],
Value=v2["Value"],
)
if v2
else None
for k2, v2 in v.items()
}
for k, v in data.items()
},
)

View File

@ -0,0 +1,20 @@
from starrail_damage_cal.map.SR_MAP_PATH import (
alias_data,
avatarId2Name,
)
def name_to_avatar_id(name: str) -> str:
avatar_id = ""
for i in avatarId2Name:
if avatarId2Name[i] == name:
avatar_id = i
break
return avatar_id
def alias_to_char_name(char_name: str) -> str:
for i in alias_data["characters"]:
if char_name in alias_data["characters"][i]:
return alias_data["characters"][i][0]
return char_name

View File

@ -0,0 +1,5 @@
"""Mihomo.me api 包装"""
from starrail_damage_cal.mihomo.models import MihomoData
from starrail_damage_cal.mihomo.requests import get_char_card_info as requests
__all__ = ["requests", "MihomoData"]

View File

@ -0,0 +1,74 @@
from typing import List, Union
from msgspec import Struct, field
class Behavior(Struct):
pointId: int
level: int
class Equipment(Struct):
level: Union[int, None] = field(default=0)
tid: Union[int, None] = None
promotion: Union[int, None] = field(default=0)
rank: Union[int, None] = field(default=0)
class SubAffix(Struct):
affixId: int
cnt: int
step: Union[int, None] = field(default=0)
class Relic(Struct):
tid: int
mainAffixId: int
type_: int = field(name="type")
subAffixList: Union[List[SubAffix], None] = field(default=[])
level: Union[int, None] = field(default=0)
class Avatar(Struct):
skillTreeList: List[Behavior]
avatarId: int
level: int
equipment: Union[Equipment, None] = None
relicList: Union[List[Relic], None] = field(default=[])
pos: Union[int, None] = field(default=0)
rank: Union[int, None] = field(default=0)
promotion: Union[int, None] = field(default=0)
class Challenge(Struct):
scheduleMaxLevel: Union[int, None] = None
MazeGroupIndex: Union[int, None] = None
PreMazeGroupIndex: Union[int, None] = None
class PlayerSpaceInfo(Struct):
challengeInfo: Challenge
maxRogueChallengeScore: int
equipmentCount: int
avatarCount: int
achievementCount: int
class PlayerDetailInfo(Struct):
assistAvatarDetail: Avatar
platform: str
isDisplayAvatar: bool
avatarDetailList: Union[List[Avatar], None]
uid: int
friendCount: int
worldLevel: int
nickname: str
level: int
recordInfo: Union[PlayerSpaceInfo, None]
headIcon: int
signature: Union[str, None] = None
Birthday: Union[int, None] = None
class MihomoData(Struct):
detailInfo: PlayerDetailInfo

View File

@ -0,0 +1,18 @@
from __future__ import annotations
from httpx import AsyncClient
from msgspec import convert
from starrail_damage_cal.mihomo.models import MihomoData
_HEADER = {"User-Agent": "StarRailDamageCal/"}
async def get_char_card_info(uid: str) -> MihomoData:
async with AsyncClient(
base_url="http://api.mihomo.me",
headers=_HEADER,
timeout=30,
) as client:
req = await client.get(f"/sr_info/{uid}")
return convert(req.json(), type=MihomoData)

View File

@ -0,0 +1,105 @@
from collections import Counter
from typing import Dict, List
from starrail_damage_cal.map.SR_MAP_PATH import (
EquipmentID2AbilityProperty,
RelicSetSkill,
)
class Character:
def __init__(self, card_prop: Dict):
self.char_level: int = int(card_prop["avatarLevel"])
self.char_id: str = card_prop["avatarId"]
self.char_name: str = card_prop["avatarName"]
self.char_rank = card_prop["rank"] if card_prop.get("rank") else 0
self.char_rarity = card_prop["avatarRarity"]
self.char_element = card_prop["avatarElement"]
self.char_promotion = card_prop["avatarPromotion"]
self.char_skill = card_prop["avatarSkill"]
self.extra_ability = card_prop["avatarExtraAbility"]
self.attribute_bonus = card_prop["avatarAttributeBonus"]
self.char_relic = card_prop["RelicInfo"]
self.base_attributes = card_prop["baseAttributes"]
self.add_attr = {}
self.equipment = card_prop["equipmentInfo"]
self.rarity = card_prop["avatarRarity"]
self.eidolons = card_prop["rankList"] if card_prop.get("rankList") else []
async def get_equipment_info(self):
if self.equipment == {}:
return
base_attr = self.base_attributes
equip = self.equipment
ability_property = EquipmentID2AbilityProperty[str(equip["equipmentID"])]
equip_rank = equip["equipmentRank"]
equip_ability_property = ability_property[str(equip_rank)]
equip_add_base_attr = equip["baseAttributes"]
base_attr["hp"] = base_attr["hp"] + equip_add_base_attr["hp"]
base_attr["attack"] = base_attr["attack"] + equip_add_base_attr["attack"]
base_attr["defence"] = base_attr["defence"] + equip_add_base_attr["defence"]
self.base_attributes = base_attr
for equip_ability in equip_ability_property:
property_type = equip_ability["PropertyType"]
value = equip_ability["Value"]["Value"]
self.add_attr[property_type] = value + self.add_attr.get(property_type, 0)
async def get_char_attribute_bonus(self):
attribute_bonus = self.attribute_bonus
for bonus in attribute_bonus:
status_add = bonus["statusAdd"]
bonus_property = status_add["property"]
value = status_add["value"]
self.add_attr[bonus_property] = value + self.add_attr.get(bonus_property, 0)
async def get_relic_info(self):
# 计算圣遗物效果
set_id_list: List[int] = []
for relic in self.char_relic:
set_id_list.append(relic["SetId"])
# 处理主属性
relic_property = relic["MainAffix"]["Property"]
property_value = relic["MainAffix"]["Value"]
self.add_attr[relic_property] = property_value + self.add_attr.get(
relic_property,
0,
)
# 处理副词条
for sub in relic["SubAffixList"]:
sub_property = sub["Property"]
sub_value = sub["Value"]
self.add_attr[sub_property] = sub_value + self.add_attr.get(
sub_property,
0,
)
# 处理套装属性
set_id_dict = Counter(set_id_list)
# logger.info(set_id_dict.most_common())
for item in set_id_dict.most_common():
set_property = ""
set_id = item[0]
count = item[1]
set_value = 0
if count >= 2:
status_add = RelicSetSkill.RelicSet[str(set_id)]["2"]
if status_add:
set_property = status_add.Property
set_value = status_add.Value
if set_property != "":
self.add_attr[set_property] = set_value + self.add_attr.get(
set_property,
0,
)
if count == 4:
status_add = RelicSetSkill.RelicSet[str(set_id)]["4"]
if status_add:
set_property = status_add.Property
set_value = status_add.Value
if set_property != "":
self.add_attr[set_property] = set_value + self.add_attr.get(
set_property,
0,
)

View File

View File

@ -0,0 +1,285 @@
from typing import Any, Dict, List, Tuple, Union
from starrail_damage_cal.damage.utils import cal_relic_main_affix, cal_relic_sub_affix
from starrail_damage_cal.excel.model import (
AvatarPromotionConfig,
EquipmentPromotionConfig,
)
from starrail_damage_cal.exception import (
CharacterShowcaseNotOpenError,
MihomoRequestError,
)
from starrail_damage_cal.map.SR_MAP_PATH import (
AvatarRankSkillUp,
EquipmentID2Name,
EquipmentID2Rarity,
ItemId2Name,
Property2Name,
RelicId2SetId,
SetId2Name,
avatarId2DamageType,
avatarId2EnName,
avatarId2Name,
avatarId2Rarity,
characterSkillTree,
rankId2Name,
skillId2AttackType,
skillId2Effect,
skillId2Name,
)
from starrail_damage_cal.mihomo.models import Avatar, MihomoData
from starrail_damage_cal.mihomo.requests import get_char_card_info
async def api_to_dict(
sr_uid: Union[str, None] = None,
mihomo_raw: Union[MihomoData, None] = None,
) -> Tuple[List[str], Dict[str, Dict[str, Any]]]:
if not mihomo_raw:
if not sr_uid:
raise KeyError
try:
sr_data = await get_char_card_info(sr_uid)
except Exception as e: # noqa: BLE001
raise MihomoRequestError from e
else:
sr_data = mihomo_raw
PlayerDetailInfo = sr_data.detailInfo
uid = str(PlayerDetailInfo.uid)
if sr_data.detailInfo is None:
raise CharacterShowcaseNotOpenError(uid)
char_name_list: List[str] = []
char_id_list: List[str] = []
char_data_list: Dict[str, Dict] = {}
nickName = PlayerDetailInfo.nickname
if (
PlayerDetailInfo.assistAvatarDetail
and PlayerDetailInfo.assistAvatarDetail.avatarId not in char_id_list
):
char_data, avatarName = await get_data(
PlayerDetailInfo.assistAvatarDetail,
nickName,
uid,
)
char_name_list.append(avatarName)
char_id_list.append(str(PlayerDetailInfo.assistAvatarDetail.avatarId))
char_data_list[str(PlayerDetailInfo.assistAvatarDetail.avatarId)] = char_data
if (
PlayerDetailInfo.avatarDetailList
and PlayerDetailInfo.avatarDetailList is not None
):
for char in PlayerDetailInfo.avatarDetailList:
if char.avatarId in char_id_list:
continue
char_data, avatarName = await get_data(char, nickName, uid)
char_name_list.append(avatarName)
char_id_list.append(str(char.avatarId))
char_data_list[str(char.avatarId)] = char_data
if not char_name_list:
raise CharacterShowcaseNotOpenError(uid)
return (char_id_list, char_data_list)
async def get_data(char: Avatar, nick_name: str, sr_uid: str):
# 处理基本信息
char_data = {
"uid": str(sr_uid),
"nickName": nick_name,
"avatarId": char.avatarId,
"avatarName": avatarId2Name[str(char.avatarId)],
"avatarElement": avatarId2DamageType[str(char.avatarId)],
"avatarRarity": avatarId2Rarity[str(char.avatarId)],
"avatarPromotion": char.promotion,
"avatarLevel": char.level,
"avatarSkill": [],
"avatarExtraAbility": [],
"avatarAttributeBonus": [],
"RelicInfo": [],
}
avatarName = avatarId2Name[str(char.avatarId)]
char_data["avatarEnName"] = avatarId2EnName[str(char.avatarId)]
# 处理技能
for behavior in char.skillTreeList:
# 处理技能
if f"{char.avatarId}0" == str(behavior.pointId)[0:5]:
skill_temp = {}
skill_temp["skillId"] = char.avatarId * 100 + behavior.pointId % 10
skill_temp["skillName"] = skillId2Name[str(skill_temp["skillId"])]
skill_temp["skillEffect"] = skillId2Effect[str(skill_temp["skillId"])]
skill_temp["skillAttackType"] = skillId2AttackType[
str(skill_temp["skillId"])
]
skill_temp["skillLevel"] = behavior.level
char_data["avatarSkill"].append(skill_temp)
# 处理技能树中的额外能力
if f"{char.avatarId}1" == str(behavior.pointId)[0:5]:
extra_ability_temp = {}
extra_ability_temp["extraAbilityId"] = behavior.pointId
extra_ability_temp["extraAbilityLevel"] = behavior.level
char_data["avatarExtraAbility"].append(extra_ability_temp)
# 处理技能树中的属性加成
if f"{char.avatarId}2" == str(behavior.pointId)[0:5]:
attribute_bonus_temp = {}
attribute_bonus_temp["attributeBonusId"] = behavior.pointId
attribute_bonus_temp["attributeBonusLevel"] = behavior.level
status_add = characterSkillTree[str(char.avatarId)][str(behavior.pointId)][
"levels"
][behavior.level - 1]["properties"]
attribute_bonus_temp["statusAdd"] = {}
if status_add:
for property_ in status_add:
attribute_bonus_temp["statusAdd"]["property"] = property_["type"]
attribute_bonus_temp["statusAdd"]["name"] = Property2Name[
property_["type"]
]
attribute_bonus_temp["statusAdd"]["value"] = property_["value"]
char_data["avatarAttributeBonus"].append(attribute_bonus_temp)
# 处理遗器
if char.relicList:
for relic in char.relicList:
relic_temp = {}
relic_temp["relicId"] = relic.tid
relic_temp["relicName"] = ItemId2Name[str(relic.tid)]
relic_temp["SetId"] = int(RelicId2SetId[str(relic.tid)])
relic_temp["SetName"] = SetId2Name[str(relic_temp["SetId"])]
relic_temp["Level"] = relic.level if relic.level else 0
relic_temp["Type"] = relic.type_
relic_temp["MainAffix"] = {}
relic_temp["MainAffix"]["AffixID"] = relic.mainAffixId
affix_property, value = await cal_relic_main_affix(
relic_id=relic.tid,
set_id=str(relic_temp["SetId"]),
affix_id=relic.mainAffixId,
relic_type=relic.type_,
relic_level=relic_temp["Level"],
)
relic_temp["MainAffix"]["Property"] = affix_property
relic_temp["MainAffix"]["Name"] = Property2Name[affix_property]
relic_temp["MainAffix"]["Value"] = value
relic_temp["SubAffixList"] = []
if relic.subAffixList:
for sub_affix in relic.subAffixList:
sub_affix_temp = {}
sub_affix_temp["SubAffixID"] = sub_affix.affixId
sub_affix_property, value = await cal_relic_sub_affix(
relic_id=relic.tid,
affix_id=sub_affix.affixId,
cnt=sub_affix.cnt,
step=sub_affix.step if sub_affix.step else 0,
)
sub_affix_temp["Property"] = sub_affix_property
sub_affix_temp["Name"] = Property2Name[sub_affix_property]
sub_affix_temp["Cnt"] = sub_affix.cnt
sub_affix_temp["Step"] = sub_affix.step if sub_affix.step else 0
sub_affix_temp["Value"] = value
relic_temp["SubAffixList"].append(sub_affix_temp)
char_data["RelicInfo"].append(relic_temp)
# 处理命座
rank_temp = []
if char.rank and char.rank is not None:
char_data["rank"] = char.rank
for index in range(char.rank):
rankTemp = {}
rank_id = int(str(char.avatarId) + "0" + str(index + 1))
rankTemp["rankId"] = rank_id
rankTemp["rankName"] = rankId2Name[str(rank_id)]
rank_temp.append(rankTemp)
char_data["rankList"] = rank_temp
# 处理命座中的 level_up_skills
if char_data.get("rankList"):
for rank_item in char_data["rankList"]:
rank_id = rank_item["rankId"]
level_up_skill = AvatarRankSkillUp[str(rank_id)]
if level_up_skill:
for item in level_up_skill:
skill_id = item["id"]
skill_up_num = item["num"]
# 查找skill_id在不在avatarSkill中
for index, skill_item in enumerate(char_data["avatarSkill"]):
if str(skill_id) == str(skill_item["skillId"]):
char_data["avatarSkill"][index][
"skillLevel"
] += skill_up_num
break
# 处理基础属性
base_attributes = {}
avatar_promotion_base = AvatarPromotionConfig.Avatar[str(char.avatarId)][
str(char.promotion)
]
# 攻击力
base_attributes["attack"] = (
avatar_promotion_base.AttackBase.Value
+ avatar_promotion_base.AttackAdd.Value * (char.level - 1)
)
# 防御力
base_attributes["defence"] = (
avatar_promotion_base.DefenceBase.Value
+ avatar_promotion_base.DefenceAdd.Value * (char.level - 1)
)
# 血量
base_attributes["hp"] = (
avatar_promotion_base.HPBase.Value
+ avatar_promotion_base.HPAdd.Value * (char.level - 1)
)
# 速度
base_attributes["speed"] = avatar_promotion_base.SpeedBase.Value
# 暴击率
base_attributes["CriticalChanceBase"] = avatar_promotion_base.CriticalChance.Value
# 暴击伤害
base_attributes["CriticalDamageBase"] = avatar_promotion_base.CriticalDamage.Value
# 嘲讽
base_attributes["BaseAggro"] = avatar_promotion_base.BaseAggro.Value
char_data["baseAttributes"] = base_attributes
# 处理武器
equipment_info = {}
if char.equipment and char.equipment.tid is not None:
equipment_info["equipmentID"] = char.equipment.tid
equipment_info["equipmentName"] = EquipmentID2Name[str(char.equipment.tid)]
equipment_info["equipmentLevel"] = char.equipment.level
equipment_info["equipmentPromotion"] = char.equipment.promotion
equipment_info["equipmentRank"] = char.equipment.rank
equipment_info["equipmentRarity"] = EquipmentID2Rarity[str(char.equipment.tid)]
equipment_base_attributes = {}
equipment_promotion_base = EquipmentPromotionConfig.Equipment[
str(char.equipment.tid)
][str(equipment_info["equipmentPromotion"])]
equipment_level = char.equipment.level if char.equipment.level else 1
# 生命值
equipment_base_attributes["hp"] = (
equipment_promotion_base.BaseHP.Value
+ equipment_promotion_base.BaseHPAdd.Value * (equipment_level - 1)
)
# 攻击力
equipment_base_attributes["attack"] = (
equipment_promotion_base.BaseAttack.Value
+ equipment_promotion_base.BaseAttackAdd.Value * (equipment_level - 1)
)
# 防御力
equipment_base_attributes["defence"] = (
equipment_promotion_base.BaseDefence.Value
+ equipment_promotion_base.BaseDefenceAdd.Value * (equipment_level - 1)
)
equipment_info["baseAttributes"] = equipment_base_attributes
char_data["equipmentInfo"] = equipment_info
return char_data, avatarName

View File

@ -0,0 +1 @@
StarRail_version = "1.4.0"

0
test/__init__.py Normal file
View File

425
test/test.json Normal file
View File

@ -0,0 +1,425 @@
{
"detailInfo": {
"level": 69,
"worldLevel": 6,
"nickname": "qwerdvd",
"headIcon": 201102,
"avatarDetailList": [
{
"relicList": [
{
"mainAffixId": 1,
"tid": 61021,
"type": 1,
"subAffixList": [
{ "affixId": 3, "cnt": 1 },
{ "affixId": 5, "cnt": 3, "step": 5 },
{ "affixId": 6, "cnt": 1, "step": 1 },
{ "affixId": 8, "cnt": 3, "step": 4 }
],
"level": 15
},
{
"mainAffixId": 1,
"tid": 61022,
"type": 2,
"subAffixList": [
{ "affixId": 3, "cnt": 2, "step": 4 },
{ "affixId": 5, "cnt": 2, "step": 4 },
{ "affixId": 8, "cnt": 3, "step": 3 },
{ "affixId": 10, "cnt": 1, "step": 1 }
],
"level": 15
},
{
"mainAffixId": 5,
"tid": 61023,
"type": 3,
"subAffixList": [
{ "affixId": 1, "cnt": 1, "step": 1 },
{ "affixId": 5, "cnt": 3, "step": 4 },
{ "affixId": 6, "cnt": 2, "step": 1 },
{ "affixId": 8, "cnt": 2, "step": 2 }
],
"level": 15
},
{
"mainAffixId": 2,
"tid": 61024,
"type": 4,
"subAffixList": [
{ "affixId": 1, "cnt": 1, "step": 2 },
{ "affixId": 4, "cnt": 3, "step": 3 },
{ "affixId": 8, "cnt": 3, "step": 4 },
{ "affixId": 12, "cnt": 1, "step": 2 }
],
"level": 15
},
{
"mainAffixId": 10,
"tid": 63095,
"type": 5,
"subAffixList": [
{ "affixId": 3, "cnt": 2, "step": 2 },
{ "affixId": 9, "cnt": 2, "step": 3 },
{ "affixId": 10, "cnt": 2, "step": 1 },
{ "affixId": 12, "cnt": 2, "step": 2 }
],
"level": 15
},
{
"mainAffixId": 4,
"tid": 63096,
"type": 6,
"subAffixList": [
{ "affixId": 2, "cnt": 2, "step": 1 },
{ "affixId": 8, "cnt": 2, "step": 1 },
{ "affixId": 9, "cnt": 1, "step": 1 },
{ "affixId": 12, "cnt": 3, "step": 3 }
],
"level": 15
}
],
"equipment": { "tid": 23015, "promotion": 6, "rank": 1, "level": 80 },
"level": 80,
"avatarId": 1213,
"promotion": 6,
"skillTreeList": [
{ "pointId": 1213001, "level": 6 },
{ "pointId": 1213002, "level": 10 },
{ "pointId": 1213003, "level": 10 },
{ "pointId": 1213004, "level": 10 },
{ "pointId": 1213007, "level": 1 },
{ "pointId": 1213101, "level": 1 },
{ "pointId": 1213102, "level": 1 },
{ "pointId": 1213103, "level": 1 },
{ "pointId": 1213201, "level": 1 },
{ "pointId": 1213202, "level": 1 },
{ "pointId": 1213203, "level": 1 },
{ "pointId": 1213204, "level": 1 },
{ "pointId": 1213205, "level": 1 },
{ "pointId": 1213206, "level": 1 },
{ "pointId": 1213207, "level": 1 },
{ "pointId": 1213208, "level": 1 },
{ "pointId": 1213209, "level": 1 },
{ "pointId": 1213210, "level": 1 }
]
},
{
"relicList": [
{
"mainAffixId": 1,
"tid": 61081,
"type": 1,
"subAffixList": [
{ "affixId": 8, "cnt": 1 },
{ "affixId": 9, "cnt": 2, "step": 3 },
{ "affixId": 11, "cnt": 2, "step": 3 },
{ "affixId": 12, "cnt": 3, "step": 3 }
],
"level": 15
},
{
"mainAffixId": 1,
"tid": 61082,
"type": 2,
"subAffixList": [
{ "affixId": 1, "cnt": 3, "step": 4 },
{ "affixId": 3, "cnt": 3, "step": 5 },
{ "affixId": 5, "cnt": 1, "step": 2 },
{ "affixId": 12, "cnt": 1, "step": 2 }
],
"level": 15
},
{
"mainAffixId": 4,
"tid": 61083,
"type": 3,
"subAffixList": [
{ "affixId": 3, "cnt": 2, "step": 1 },
{ "affixId": 4, "cnt": 3, "step": 2 },
{ "affixId": 5, "cnt": 1, "step": 2 },
{ "affixId": 10, "cnt": 2, "step": 2 }
],
"level": 15
},
{
"mainAffixId": 2,
"tid": 61084,
"type": 4,
"subAffixList": [
{ "affixId": 3, "cnt": 4, "step": 6 },
{ "affixId": 4, "cnt": 1, "step": 2 },
{ "affixId": 7, "cnt": 1, "step": 1 },
{ "affixId": 10, "cnt": 2, "step": 1 }
],
"level": 15
},
{
"mainAffixId": 3,
"tid": 63035,
"type": 5,
"exp": 830,
"subAffixList": [
{ "affixId": 5, "cnt": 2, "step": 3 },
{ "affixId": 8, "cnt": 1 },
{ "affixId": 9, "cnt": 2, "step": 1 },
{ "affixId": 10, "cnt": 1, "step": 2 }
],
"level": 11
},
{
"mainAffixId": 2,
"tid": 63036,
"type": 6,
"subAffixList": [
{ "affixId": 2, "cnt": 3, "step": 5 },
{ "affixId": 5, "cnt": 1, "step": 2 },
{ "affixId": 8, "cnt": 2, "step": 2 },
{ "affixId": 12, "cnt": 2, "step": 4 }
],
"level": 15
}
],
"equipment": { "tid": 22000, "promotion": 6, "rank": 5, "level": 80 },
"level": 80,
"avatarId": 1006,
"rank": 1,
"promotion": 6,
"pos": 1,
"skillTreeList": [
{ "pointId": 1006001, "level": 6 },
{ "pointId": 1006002, "level": 10 },
{ "pointId": 1006003, "level": 10 },
{ "pointId": 1006004, "level": 10 },
{ "pointId": 1006007, "level": 1 },
{ "pointId": 1006101, "level": 1 },
{ "pointId": 1006102, "level": 1 },
{ "pointId": 1006103, "level": 1 },
{ "pointId": 1006201, "level": 1 },
{ "pointId": 1006202, "level": 1 },
{ "pointId": 1006203, "level": 1 },
{ "pointId": 1006204, "level": 1 },
{ "pointId": 1006205, "level": 1 },
{ "pointId": 1006206, "level": 1 },
{ "pointId": 1006207, "level": 1 },
{ "pointId": 1006208, "level": 1 },
{ "pointId": 1006209, "level": 1 },
{ "pointId": 1006210, "level": 1 }
]
},
{
"relicList": [
{
"mainAffixId": 1,
"tid": 61081,
"type": 1,
"subAffixList": [
{ "affixId": 4, "cnt": 2, "step": 3 },
{ "affixId": 8, "cnt": 2, "step": 2 },
{ "affixId": 9, "cnt": 3, "step": 4 },
{ "affixId": 12, "cnt": 1 }
],
"level": 15
},
{
"mainAffixId": 1,
"tid": 61082,
"type": 2,
"subAffixList": [
{ "affixId": 6, "cnt": 1, "step": 2 },
{ "affixId": 8, "cnt": 2, "step": 2 },
{ "affixId": 9, "cnt": 2, "step": 2 },
{ "affixId": 10, "cnt": 3, "step": 1 }
],
"level": 15
},
{
"mainAffixId": 5,
"tid": 61083,
"type": 3,
"subAffixList": [
{ "affixId": 3, "cnt": 2, "step": 4 },
{ "affixId": 5, "cnt": 3, "step": 1 },
{ "affixId": 6, "cnt": 1 },
{ "affixId": 8, "cnt": 2, "step": 3 }
],
"level": 15
},
{
"mainAffixId": 2,
"tid": 61084,
"type": 4,
"subAffixList": [
{ "affixId": 1, "cnt": 2, "step": 3 },
{ "affixId": 7, "cnt": 3, "step": 3 },
{ "affixId": 11, "cnt": 2, "step": 3 },
{ "affixId": 12, "cnt": 1, "step": 2 }
],
"level": 15
},
{
"mainAffixId": 9,
"tid": 63065,
"type": 5,
"subAffixList": [
{ "affixId": 2, "cnt": 2, "step": 2 },
{ "affixId": 3, "cnt": 1 },
{ "affixId": 8, "cnt": 3, "step": 6 },
{ "affixId": 12, "cnt": 2, "step": 1 }
],
"level": 15
},
{
"mainAffixId": 4,
"tid": 63066,
"type": 6,
"subAffixList": [
{ "affixId": 2, "cnt": 1, "step": 2 },
{ "affixId": 3, "cnt": 2, "step": 4 },
{ "affixId": 8, "cnt": 5, "step": 6 },
{ "affixId": 11, "cnt": 1, "step": 2 }
],
"level": 15
}
],
"equipment": { "tid": 24001, "promotion": 6, "rank": 5, "level": 80 },
"level": 80,
"avatarId": 1102,
"promotion": 6,
"pos": 2,
"skillTreeList": [
{ "pointId": 1102001, "level": 6 },
{ "pointId": 1102002, "level": 10 },
{ "pointId": 1102003, "level": 10 },
{ "pointId": 1102004, "level": 10 },
{ "pointId": 1102007, "level": 1 },
{ "pointId": 1102101, "level": 1 },
{ "pointId": 1102102, "level": 1 },
{ "pointId": 1102103, "level": 1 },
{ "pointId": 1102201, "level": 1 },
{ "pointId": 1102202, "level": 1 },
{ "pointId": 1102203, "level": 1 },
{ "pointId": 1102204, "level": 1 },
{ "pointId": 1102205, "level": 1 },
{ "pointId": 1102206, "level": 1 },
{ "pointId": 1102207, "level": 1 },
{ "pointId": 1102208, "level": 1 },
{ "pointId": 1102209, "level": 1 },
{ "pointId": 1102210, "level": 1 }
]
}
],
"assistAvatarDetail": {
"relicList": [
{
"mainAffixId": 1,
"tid": 61021,
"type": 1,
"subAffixList": [
{ "affixId": 3, "cnt": 1 },
{ "affixId": 5, "cnt": 3, "step": 5 },
{ "affixId": 6, "cnt": 1, "step": 1 },
{ "affixId": 8, "cnt": 3, "step": 4 }
],
"level": 15
},
{
"mainAffixId": 1,
"tid": 61022,
"type": 2,
"subAffixList": [
{ "affixId": 3, "cnt": 2, "step": 4 },
{ "affixId": 5, "cnt": 2, "step": 4 },
{ "affixId": 8, "cnt": 3, "step": 3 },
{ "affixId": 10, "cnt": 1, "step": 1 }
],
"level": 15
},
{
"mainAffixId": 5,
"tid": 61023,
"type": 3,
"subAffixList": [
{ "affixId": 1, "cnt": 1, "step": 1 },
{ "affixId": 5, "cnt": 3, "step": 4 },
{ "affixId": 6, "cnt": 2, "step": 1 },
{ "affixId": 8, "cnt": 2, "step": 2 }
],
"level": 15
},
{
"mainAffixId": 2,
"tid": 61024,
"type": 4,
"subAffixList": [
{ "affixId": 1, "cnt": 1, "step": 2 },
{ "affixId": 4, "cnt": 3, "step": 3 },
{ "affixId": 8, "cnt": 3, "step": 4 },
{ "affixId": 12, "cnt": 1, "step": 2 }
],
"level": 15
},
{
"mainAffixId": 10,
"tid": 63095,
"type": 5,
"subAffixList": [
{ "affixId": 3, "cnt": 2, "step": 2 },
{ "affixId": 9, "cnt": 2, "step": 3 },
{ "affixId": 10, "cnt": 2, "step": 1 },
{ "affixId": 12, "cnt": 2, "step": 2 }
],
"level": 15
},
{
"mainAffixId": 4,
"tid": 63096,
"type": 6,
"subAffixList": [
{ "affixId": 2, "cnt": 2, "step": 1 },
{ "affixId": 8, "cnt": 2, "step": 1 },
{ "affixId": 9, "cnt": 1, "step": 1 },
{ "affixId": 12, "cnt": 3, "step": 3 }
],
"level": 15
}
],
"equipment": { "tid": 23015, "promotion": 6, "rank": 1, "level": 80 },
"level": 80,
"avatarId": 1213,
"promotion": 6,
"skillTreeList": [
{ "pointId": 1213001, "level": 6 },
{ "pointId": 1213002, "level": 10 },
{ "pointId": 1213003, "level": 10 },
{ "pointId": 1213004, "level": 10 },
{ "pointId": 1213007, "level": 1 },
{ "pointId": 1213101, "level": 1 },
{ "pointId": 1213102, "level": 1 },
{ "pointId": 1213103, "level": 1 },
{ "pointId": 1213201, "level": 1 },
{ "pointId": 1213202, "level": 1 },
{ "pointId": 1213203, "level": 1 },
{ "pointId": 1213204, "level": 1 },
{ "pointId": 1213205, "level": 1 },
{ "pointId": 1213206, "level": 1 },
{ "pointId": 1213207, "level": 1 },
{ "pointId": 1213208, "level": 1 },
{ "pointId": 1213209, "level": 1 },
{ "pointId": 1213210, "level": 1 }
]
},
"friendCount": 18,
"recordInfo": {
"achievementCount": 276,
"avatarCount": 24,
"maxRogueChallengeScore": 7,
"challengeInfo": { "noneScheduleMaxLevel": 16 },
"equipmentCount": 154
},
"uid": 100086290,
"platform": "PC",
"isDisplayAvatar": true
}
}

40
test/test_get_char.py Normal file
View File

@ -0,0 +1,40 @@
import json
from pathlib import Path
from typing import Dict
import pytest
from starrail_damage_cal import DamageCal
with Path.open(Path("test/test.json"), encoding="utf-8") as f:
test_data = json.load(f)
@pytest.mark.asyncio()
async def test_get_damage_data_by_uid():
data = await DamageCal.get_damage_data_by_uid(uid="100086290", avatar_name="希儿")
if isinstance(data, Dict):
print(json.dumps(data, ensure_ascii=False, indent=4))
@pytest.mark.asyncio()
async def test_get_damage_data_by_mihomo_raw():
data = await DamageCal.get_damage_data_by_mihomo_raw(
mihomo_raw=test_data, avatar_name="希儿"
)
if isinstance(data, Dict):
print(json.dumps(data, ensure_ascii=False, indent=4))
@pytest.mark.asyncio()
async def test_get_all_damage_data_by_mihomo_raw():
data = await DamageCal.get_all_damage_data_by_mihomo_raw(mihomo_raw=test_data)
if isinstance(data, Dict):
print(json.dumps(data, ensure_ascii=False, indent=4))
@pytest.mark.asyncio()
async def test_get_all_damage_data_by_uid():
data = await DamageCal.get_all_damage_data_by_uid(uid="100086290")
if isinstance(data, Dict):
print(json.dumps(data, ensure_ascii=False, indent=4))