mirror of
https://github.com/PaiGramTeam/PaiGramMetadata.git
synced 2024-11-21 22:48:05 +00:00
feat: support edit damage rule
This commit is contained in:
parent
eb65dae993
commit
97c8eea821
@ -1,137 +1,141 @@
|
|||||||
{
|
{
|
||||||
"胡桃": {
|
"胡桃": {
|
||||||
"skills": [
|
"skills": [
|
||||||
{
|
{
|
||||||
"name": "普通攻击·往生秘传枪法-重击蒸发伤害",
|
"name": "普通攻击·往生秘传枪法-重击蒸发伤害",
|
||||||
"index": "7",
|
"index": 7,
|
||||||
"damage_key": "vaporize"
|
"damage_key": "vaporize"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "安神秘法-蒸发伤害",
|
"name": "安神秘法-蒸发伤害",
|
||||||
"index": "12",
|
"index": 12,
|
||||||
"damage_key": "vaporize"
|
"damage_key": "vaporize"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "安神秘法-低血量蒸发伤害",
|
"name": "安神秘法-低血量蒸发伤害",
|
||||||
"index": "13",
|
"index": 13,
|
||||||
"damage_key": "vaporize"
|
"damage_key": "vaporize"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"config_skill": {
|
"config": {
|
||||||
"after_e": true
|
"le_50": true
|
||||||
|
},
|
||||||
|
"config_skill": {
|
||||||
|
"after_e": true
|
||||||
|
},
|
||||||
|
"config_weapon": {
|
||||||
|
"StaffOfHoma": {
|
||||||
|
"be50_rate": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"artifact_config": {
|
||||||
|
"config_crimson_witch_of_flames": {
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"config": {
|
"夜兰": {
|
||||||
"le_50": true
|
"skills": [
|
||||||
|
{
|
||||||
|
"name": "普通攻击·潜形隐曜弓-破局矢伤害",
|
||||||
|
"index": 6,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "萦络纵命索-技能伤害",
|
||||||
|
"index": 11,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "渊图玲珑骰-技能伤害",
|
||||||
|
"index": 12,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "渊图玲珑骰-玄掷玲珑伤害",
|
||||||
|
"index": 13,
|
||||||
|
"damage_key": "normal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"config": {
|
||||||
|
"team_element_count": 4
|
||||||
|
},
|
||||||
|
"config_skill": null,
|
||||||
|
"config_weapon": {
|
||||||
|
"AquaSimulacra": {
|
||||||
|
"is_enemy_around": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"artifact_config": null
|
||||||
},
|
},
|
||||||
"config_weapon": {
|
"雷电将军": {
|
||||||
"StaffOfHoma": {
|
"skills": [
|
||||||
"be50_rate": 1
|
{
|
||||||
}
|
"name": "神变•恶曜开眼-技能伤害",
|
||||||
},
|
"index": 10,
|
||||||
"artifact_config": {
|
"damage_key": "normal"
|
||||||
"config_crimson_witch_of_flames": {
|
},
|
||||||
"level": 1
|
{
|
||||||
}
|
"name": "神变•恶曜开眼协-同攻击伤害",
|
||||||
|
"index": 11,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "奥义•梦想真说-梦想一刀基础伤害",
|
||||||
|
"index": 12,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "奥义•梦想真说-一段伤害",
|
||||||
|
"index": 13,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "奥义•梦想真说-二段伤害",
|
||||||
|
"index": 14,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "奥义•梦想真说-三段伤害",
|
||||||
|
"index": 15,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "奥义•梦想真说-四段伤害-1",
|
||||||
|
"index": 16,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "奥义•梦想真说-四段伤害-2",
|
||||||
|
"index": 17,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "奥义•梦想真说-五段伤害",
|
||||||
|
"index": 18,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "奥义•梦想真说-重击伤害-1",
|
||||||
|
"index": 19,
|
||||||
|
"damage_key": "normal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "奥义•梦想真说-重击伤害-2",
|
||||||
|
"index": 20,
|
||||||
|
"damage_key": "normal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"config": null,
|
||||||
|
"config_skill": {
|
||||||
|
"under_e": true,
|
||||||
|
"resolve_stack": 60
|
||||||
|
},
|
||||||
|
"config_weapon": {
|
||||||
|
"EngulfingLightning": {
|
||||||
|
"rate": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"artifact_config": null
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"夜兰": {
|
|
||||||
"skills": [
|
|
||||||
{
|
|
||||||
"name": "普通攻击·潜形隐曜弓-破局矢伤害",
|
|
||||||
"index": "6",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "萦络纵命索-技能伤害",
|
|
||||||
"index": "11",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "渊图玲珑骰-技能伤害",
|
|
||||||
"index": "12",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "渊图玲珑骰-玄掷玲珑伤害",
|
|
||||||
"index": "13",
|
|
||||||
"damage_key": "normal"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config": {
|
|
||||||
"team_element_count": 4
|
|
||||||
},
|
|
||||||
"config_weapon": {
|
|
||||||
"AquaSimulacra": {
|
|
||||||
"is_enemy_around": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"雷电将军": {
|
|
||||||
"skills": [
|
|
||||||
{
|
|
||||||
"name": "神变•恶曜开眼-技能伤害",
|
|
||||||
"index": "10",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "神变•恶曜开眼协-同攻击伤害",
|
|
||||||
"index": "11",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "奥义•梦想真说-梦想一刀基础伤害",
|
|
||||||
"index": "12",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "奥义•梦想真说-一段伤害",
|
|
||||||
"index": "13",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "奥义•梦想真说-二段伤害",
|
|
||||||
"index": "14",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "奥义•梦想真说-三段伤害",
|
|
||||||
"index": "15",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "奥义•梦想真说-四段伤害-1",
|
|
||||||
"index": "16",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "奥义•梦想真说-四段伤害-2",
|
|
||||||
"index": "17",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "奥义•梦想真说-五段伤害",
|
|
||||||
"index": "18",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "奥义•梦想真说-重击伤害-1",
|
|
||||||
"index": "19",
|
|
||||||
"damage_key": "normal"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "奥义•梦想真说-重击伤害-2",
|
|
||||||
"index": "20",
|
|
||||||
"damage_key": "normal"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config_skill": {
|
|
||||||
"under_e": true,
|
|
||||||
"resolve_stack": 60
|
|
||||||
},
|
|
||||||
"config_weapon": {
|
|
||||||
"EngulfingLightning": {
|
|
||||||
"rate": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
14
appveyor.yml
14
appveyor.yml
@ -19,7 +19,7 @@ install:
|
|||||||
- pip install -r requirements.txt
|
- pip install -r requirements.txt
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- flet pack main.py --name FightPropRuleEditor --product-name FightPropRuleEditor
|
- flet pack main.py --name GramBotMetadataEditor --product-name GramBotMetadataEditor
|
||||||
|
|
||||||
test: off
|
test: off
|
||||||
|
|
||||||
@ -40,10 +40,10 @@ for:
|
|||||||
- image: Visual Studio 2019
|
- image: Visual Studio 2019
|
||||||
|
|
||||||
after_build:
|
after_build:
|
||||||
- 7z a FightPropRuleEditor-windows.zip %CD%\dist\*.exe
|
- 7z a GramBotMetadataEditor-windows.zip %CD%\dist\*.exe
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: FightPropRuleEditor-windows.zip
|
- path: GramBotMetadataEditor-windows.zip
|
||||||
|
|
||||||
#
|
#
|
||||||
# macOS package
|
# macOS package
|
||||||
@ -54,10 +54,10 @@ for:
|
|||||||
- image: macOS
|
- image: macOS
|
||||||
|
|
||||||
after_build:
|
after_build:
|
||||||
- tar -czvf FightPropRuleEditor-macos.tar.gz -C dist FightPropRuleEditor.app
|
- tar -czvf GramBotMetadataEditor-macos.tar.gz -C dist GramBotMetadataEditor.app
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: FightPropRuleEditor-macos.tar.gz
|
- path: GramBotMetadataEditor-macos.tar.gz
|
||||||
|
|
||||||
#
|
#
|
||||||
# Linux package
|
# Linux package
|
||||||
@ -68,7 +68,7 @@ for:
|
|||||||
- image: Ubuntu
|
- image: Ubuntu
|
||||||
|
|
||||||
after_build:
|
after_build:
|
||||||
- tar -czvf FightPropRuleEditor-linux.tar.gz -C dist FightPropRuleEditor
|
- tar -czvf GramBotMetadataEditor-linux.tar.gz -C dist GramBotMetadataEditor
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: FightPropRuleEditor-linux.tar.gz
|
- path: GramBotMetadataEditor-linux.tar.gz
|
||||||
|
5
main.py
5
main.py
@ -1,6 +1,7 @@
|
|||||||
import flet as ft
|
import flet as ft
|
||||||
|
|
||||||
from src.choose import choose_view
|
from src.choose import choose_view
|
||||||
|
from src.damage.page import edit_damage_view
|
||||||
from src.data import Page
|
from src.data import Page
|
||||||
from src.edit import edit_view
|
from src.edit import edit_view
|
||||||
|
|
||||||
@ -11,6 +12,8 @@ def main(page: Page):
|
|||||||
choose_view(page)
|
choose_view(page)
|
||||||
if e.route == "/edit":
|
if e.route == "/edit":
|
||||||
edit_view(page)
|
edit_view(page)
|
||||||
|
elif e.route == "/edit_damage":
|
||||||
|
edit_damage_view(page)
|
||||||
page.update()
|
page.update()
|
||||||
|
|
||||||
def view_pop():
|
def view_pop():
|
||||||
@ -18,7 +21,7 @@ def main(page: Page):
|
|||||||
top_view = page.views[-1]
|
top_view = page.views[-1]
|
||||||
page.go(top_view.route)
|
page.go(top_view.route)
|
||||||
|
|
||||||
page.title = "FightPropRuleEditor"
|
page.title = "GramBotMetadataEditor"
|
||||||
page.vertical_alignment = "center"
|
page.vertical_alignment = "center"
|
||||||
page.horizontal_alignment = "center"
|
page.horizontal_alignment = "center"
|
||||||
page.on_route_change = on_route_change
|
page.on_route_change = on_route_change
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
flet
|
flet
|
||||||
PyInstaller
|
PyInstaller
|
||||||
httpx
|
httpx
|
||||||
|
Python-Genshin-Artifact
|
||||||
|
genshin-artifact-core
|
||||||
|
pydantic
|
||||||
|
@ -13,6 +13,10 @@ def choose_view(page: Page):
|
|||||||
page.go("/edit")
|
page.go("/edit")
|
||||||
show_snack_bar(page, "开始编辑原神圣遗物有效词条", ft.colors.GREEN)
|
show_snack_bar(page, "开始编辑原神圣遗物有效词条", ft.colors.GREEN)
|
||||||
|
|
||||||
|
def genshin_damage(_e):
|
||||||
|
page.go("/edit_damage")
|
||||||
|
show_snack_bar(page, "开始编辑原神伤害计算规则", ft.colors.GREEN)
|
||||||
|
|
||||||
def starrail(_e):
|
def starrail(_e):
|
||||||
page.core = Core(starrail_path, Starrail())
|
page.core = Core(starrail_path, Starrail())
|
||||||
page.go("/edit")
|
page.go("/edit")
|
||||||
@ -32,7 +36,7 @@ def choose_view(page: Page):
|
|||||||
[
|
[
|
||||||
ft.Container(
|
ft.Container(
|
||||||
content=ft.Text(
|
content=ft.Text(
|
||||||
"FightPropRuleEditor",
|
"GramBotMetadataEditor",
|
||||||
size=50,
|
size=50,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -46,6 +50,11 @@ def choose_view(page: Page):
|
|||||||
icon=ft.icons.LOGIN,
|
icon=ft.icons.LOGIN,
|
||||||
on_click=starrail,
|
on_click=starrail,
|
||||||
),
|
),
|
||||||
|
ft.FilledButton(
|
||||||
|
"GenshinDamage",
|
||||||
|
icon=ft.icons.LOGIN,
|
||||||
|
on_click=genshin_damage,
|
||||||
|
),
|
||||||
ft.FilledButton(
|
ft.FilledButton(
|
||||||
"Refresh avatars",
|
"Refresh avatars",
|
||||||
icon=ft.icons.LOGIN,
|
icon=ft.icons.LOGIN,
|
||||||
|
0
src/damage/__init__.py
Normal file
0
src/damage/__init__.py
Normal file
30
src/damage/artifact.py
Normal file
30
src/damage/artifact.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import json
|
||||||
|
from typing import Dict, List
|
||||||
|
|
||||||
|
from .assets import assets, locale
|
||||||
|
from .models import Artifact as ArtifactModel, WeaponConfig
|
||||||
|
|
||||||
|
|
||||||
|
class Artifact:
|
||||||
|
def __init__(self):
|
||||||
|
artifacts: List[ArtifactModel] = []
|
||||||
|
artifact_config_map: Dict[str, ArtifactModel] = {}
|
||||||
|
for value in assets.artifact.values():
|
||||||
|
if not value["config4"]:
|
||||||
|
continue
|
||||||
|
cn_name = locale[value["name_locale"]]
|
||||||
|
config_key = ArtifactModel.get_config_name(value["name"])
|
||||||
|
config = []
|
||||||
|
for i in value["config4"]:
|
||||||
|
temp = json.loads(i)
|
||||||
|
temp["title"] = locale[temp["title"]]
|
||||||
|
temp["parent"] = config_key
|
||||||
|
config.append(WeaponConfig(**temp))
|
||||||
|
artifact_ = ArtifactModel(**value, cn_name=cn_name, config=config)
|
||||||
|
artifacts.append(artifact_)
|
||||||
|
artifact_config_map[config_key] = artifact_
|
||||||
|
self.artifacts = artifacts
|
||||||
|
self.artifact_config_map = artifact_config_map
|
||||||
|
|
||||||
|
|
||||||
|
artifact = Artifact()
|
4
src/damage/assets.py
Normal file
4
src/damage/assets.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from python_genshin_artifact.assets import Assets
|
||||||
|
|
||||||
|
assets = Assets()
|
||||||
|
locale = assets.locale["zh-cn"]
|
56
src/damage/character.py
Normal file
56
src/damage/character.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import json
|
||||||
|
from typing import List, Dict
|
||||||
|
|
||||||
|
from .assets import assets, locale
|
||||||
|
from .models import CharacterConfig, CharacterSkill
|
||||||
|
|
||||||
|
|
||||||
|
class Character:
|
||||||
|
def __init__(self):
|
||||||
|
self.current_name = ""
|
||||||
|
self.characters_map = {}
|
||||||
|
self.skills_map = {}
|
||||||
|
self.config_map = {}
|
||||||
|
self.config_skill_map = {}
|
||||||
|
for value in assets.character.values():
|
||||||
|
character_name = locale[value["name_locale"]]
|
||||||
|
self.characters_map[character_name] = value
|
||||||
|
self.skills_map[character_name] = self.gen_skills_model(value)
|
||||||
|
self.config_map[character_name] = self.gen_config_model(value["config"])
|
||||||
|
self.config_skill_map[character_name] = self.gen_config_model(
|
||||||
|
value["config_skill"]
|
||||||
|
)
|
||||||
|
self.characters_name = list(self.characters_map.keys())
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def gen_skills_model(character_: Dict) -> List[CharacterSkill]:
|
||||||
|
skills = []
|
||||||
|
skill1_name = locale[character_.get("skill1_name_index")]
|
||||||
|
skill2_name = locale[character_.get("skill2_name_index")]
|
||||||
|
skill3_name = locale[character_.get("skill3_name_index")]
|
||||||
|
for skill_name, skill in [
|
||||||
|
(skill1_name, character_["skill_map1"]),
|
||||||
|
(skill2_name, character_["skill_map2"]),
|
||||||
|
(skill3_name, character_["skill_map3"]),
|
||||||
|
]:
|
||||||
|
for i in skill:
|
||||||
|
skills.append(
|
||||||
|
CharacterSkill(
|
||||||
|
name=locale[i["locale_index"]],
|
||||||
|
index=i["index"],
|
||||||
|
skill_name=skill_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return skills
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def gen_config_model(config: List[str]) -> List[CharacterConfig]:
|
||||||
|
data = []
|
||||||
|
for i in config:
|
||||||
|
temp = json.loads(i)
|
||||||
|
temp["title"] = locale[temp["title"]]
|
||||||
|
data.append(CharacterConfig(**temp))
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
character = Character()
|
232
src/damage/data.py
Normal file
232
src/damage/data.py
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
import json
|
||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
|
from .character import character
|
||||||
|
from .models import CharacterDamage, CharacterSkill, CharacterConfig, WeaponConfig
|
||||||
|
|
||||||
|
|
||||||
|
class Data:
|
||||||
|
def __init__(self):
|
||||||
|
self.file_name = "GenshinDamageRule.json"
|
||||||
|
self.file_data: Dict[str, CharacterDamage] = self.load()
|
||||||
|
self.patch_character()
|
||||||
|
|
||||||
|
def load(self) -> Dict[str, CharacterDamage]:
|
||||||
|
with open(self.file_name, "r", encoding="utf-8") as f:
|
||||||
|
_data = json.load(f)
|
||||||
|
new_data = {}
|
||||||
|
for k, v in _data.items():
|
||||||
|
new_data[k] = CharacterDamage(**v)
|
||||||
|
return new_data
|
||||||
|
|
||||||
|
def patch_character(self):
|
||||||
|
for c_name, v in self.file_data.items():
|
||||||
|
custom_name_map = {}
|
||||||
|
damage_key_map = {}
|
||||||
|
for skill in v.skills:
|
||||||
|
custom_name_map[skill.index] = skill.name
|
||||||
|
damage_key_map[skill.index] = skill.damage_key
|
||||||
|
for skill in character.skills_map[c_name]:
|
||||||
|
if skill.index in custom_name_map:
|
||||||
|
skill.custom_name = custom_name_map[skill.index]
|
||||||
|
skill.damage_key = damage_key_map[skill.index]
|
||||||
|
|
||||||
|
def dump(self) -> Dict[str, Dict]:
|
||||||
|
new_data = {}
|
||||||
|
for k, v in self.file_data.items():
|
||||||
|
new_data[k] = v.dict()
|
||||||
|
return new_data
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
with open(self.file_name, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(self.dump(), f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
def first_init(self, character_name: str):
|
||||||
|
if character_name in self.file_data:
|
||||||
|
return
|
||||||
|
self.file_data[character_name] = CharacterDamage(skills=[])
|
||||||
|
|
||||||
|
def last_close(self, character_name: str):
|
||||||
|
if character_name not in self.file_data:
|
||||||
|
return
|
||||||
|
data_ = self.file_data[character_name]
|
||||||
|
|
||||||
|
def last_close_weapon_or_artifact():
|
||||||
|
if data_.config_weapon:
|
||||||
|
for k, v in data_.config_weapon.copy().items():
|
||||||
|
if not v:
|
||||||
|
del data_.config_weapon[k]
|
||||||
|
if data_.artifact_config:
|
||||||
|
for k, v in data_.artifact_config.copy().items():
|
||||||
|
if not v:
|
||||||
|
del data_.artifact_config[k]
|
||||||
|
|
||||||
|
last_close_weapon_or_artifact()
|
||||||
|
if len(data_.skills) != 0:
|
||||||
|
return
|
||||||
|
if data_.config is not None and data_.config:
|
||||||
|
return
|
||||||
|
if data_.config_skill is not None and data_.config_skill:
|
||||||
|
return
|
||||||
|
if data_.config_weapon is not None and data_.config_weapon:
|
||||||
|
return
|
||||||
|
if data_.artifact_config is not None and data_.artifact_config:
|
||||||
|
return
|
||||||
|
del self.file_data[character_name]
|
||||||
|
|
||||||
|
def get_skill_value(self, character_name: str, skill: CharacterSkill) -> bool:
|
||||||
|
if not self.file_data.get(character_name):
|
||||||
|
return False
|
||||||
|
skill_id = skill.index
|
||||||
|
for i in self.file_data[character_name].skills:
|
||||||
|
if i.index == skill_id:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def set_skill_value(self, character_name: str, skill: CharacterSkill, enable: bool):
|
||||||
|
self.first_init(character_name)
|
||||||
|
in_data = None
|
||||||
|
for i in self.file_data[character_name].skills:
|
||||||
|
if i.index == skill.index:
|
||||||
|
in_data = i
|
||||||
|
break
|
||||||
|
if enable:
|
||||||
|
if not in_data:
|
||||||
|
self.file_data[character_name].skills.append(skill.to_data())
|
||||||
|
else:
|
||||||
|
in_data.name = skill.custom_name or skill.show_name
|
||||||
|
in_data.damage_key = skill.damage_key
|
||||||
|
else:
|
||||||
|
if in_data:
|
||||||
|
self.file_data[character_name].skills.remove(in_data)
|
||||||
|
self.file_data[character_name].skills.sort(key=lambda x: x.index)
|
||||||
|
self.last_close(character_name)
|
||||||
|
|
||||||
|
def get_character_config_value(
|
||||||
|
self, character_name: str, config_: CharacterConfig
|
||||||
|
) -> Any:
|
||||||
|
if not self.file_data.get(character_name):
|
||||||
|
return None
|
||||||
|
if not self.file_data[character_name].config:
|
||||||
|
return None
|
||||||
|
return self.file_data[character_name].config.get(config_.name, None)
|
||||||
|
|
||||||
|
def set_character_config_value(
|
||||||
|
self, character_name: str, config: CharacterConfig, value: Any
|
||||||
|
):
|
||||||
|
self.first_init(character_name)
|
||||||
|
if not self.file_data[character_name].config:
|
||||||
|
self.file_data[character_name].config = {}
|
||||||
|
if isinstance(config.default, bool):
|
||||||
|
new_value = value == "true"
|
||||||
|
else:
|
||||||
|
value_class = type(config.default)
|
||||||
|
new_value = value_class(value)
|
||||||
|
self.file_data[character_name].config[config.name] = new_value
|
||||||
|
self.last_close(character_name)
|
||||||
|
|
||||||
|
def get_character_skill_config_value(
|
||||||
|
self, character_name: str, config_: CharacterConfig
|
||||||
|
) -> Any:
|
||||||
|
if not self.file_data.get(character_name):
|
||||||
|
return None
|
||||||
|
if not self.file_data[character_name].config_skill:
|
||||||
|
return None
|
||||||
|
return self.file_data[character_name].config_skill.get(config_.name, None)
|
||||||
|
|
||||||
|
def set_character_skill_config_value(
|
||||||
|
self, character_name: str, config: CharacterConfig, value: Any
|
||||||
|
):
|
||||||
|
self.first_init(character_name)
|
||||||
|
if not self.file_data[character_name].config_skill:
|
||||||
|
self.file_data[character_name].config_skill = {}
|
||||||
|
if isinstance(config.default, bool):
|
||||||
|
new_value = value == "true"
|
||||||
|
else:
|
||||||
|
value_class = type(config.default)
|
||||||
|
new_value = value_class(value)
|
||||||
|
self.file_data[character_name].config_skill[config.name] = new_value
|
||||||
|
self.last_close(character_name)
|
||||||
|
|
||||||
|
def get_character_weapon_config_value(
|
||||||
|
self, character_name: str, config_: WeaponConfig
|
||||||
|
) -> Any:
|
||||||
|
if not self.file_data.get(character_name):
|
||||||
|
return None
|
||||||
|
if not self.file_data[character_name].config_weapon:
|
||||||
|
return None
|
||||||
|
data_ = self.file_data[character_name].config_weapon.get(config_.parent, None)
|
||||||
|
if not data_:
|
||||||
|
return None
|
||||||
|
return data_.get(config_.name, None)
|
||||||
|
|
||||||
|
def set_character_weapon_config_value(
|
||||||
|
self, character_name: str, config: WeaponConfig, value: Any
|
||||||
|
):
|
||||||
|
self.first_init(character_name)
|
||||||
|
if not self.file_data[character_name].config_weapon:
|
||||||
|
self.file_data[character_name].config_weapon = {}
|
||||||
|
data_ = self.file_data[character_name].config_weapon.get(config.parent, {})
|
||||||
|
if value == "":
|
||||||
|
if config.name in data_:
|
||||||
|
del data_[config.name]
|
||||||
|
else:
|
||||||
|
if isinstance(config.default, bool):
|
||||||
|
new_value = value == "true"
|
||||||
|
else:
|
||||||
|
value_class = type(config.default)
|
||||||
|
new_value = value_class(value)
|
||||||
|
data_[config.name] = new_value
|
||||||
|
self.file_data[character_name].config_weapon[config.parent] = data_
|
||||||
|
self.last_close(character_name)
|
||||||
|
|
||||||
|
def get_weapon_config_enable(self, character_name: str, weapon_key: str) -> bool:
|
||||||
|
if not self.file_data.get(character_name):
|
||||||
|
return False
|
||||||
|
if not self.file_data[character_name].config_weapon:
|
||||||
|
return False
|
||||||
|
return weapon_key in self.file_data[character_name].config_weapon
|
||||||
|
|
||||||
|
def get_character_artifact_config_value(
|
||||||
|
self, character_name: str, config_: WeaponConfig
|
||||||
|
) -> Any:
|
||||||
|
if not self.file_data.get(character_name):
|
||||||
|
return None
|
||||||
|
if not self.file_data[character_name].artifact_config:
|
||||||
|
return None
|
||||||
|
data_ = self.file_data[character_name].artifact_config.get(config_.parent, None)
|
||||||
|
if not data_:
|
||||||
|
return None
|
||||||
|
return data_.get(config_.name, None)
|
||||||
|
|
||||||
|
def set_character_artifact_config_value(
|
||||||
|
self, character_name: str, config: WeaponConfig, value: Any
|
||||||
|
):
|
||||||
|
self.first_init(character_name)
|
||||||
|
if not self.file_data[character_name].artifact_config:
|
||||||
|
self.file_data[character_name].artifact_config = {}
|
||||||
|
data_ = self.file_data[character_name].artifact_config.get(config.parent, {})
|
||||||
|
if value == "":
|
||||||
|
if config.name in data_:
|
||||||
|
del data_[config.name]
|
||||||
|
else:
|
||||||
|
if isinstance(config.default, bool):
|
||||||
|
new_value = value == "true"
|
||||||
|
else:
|
||||||
|
value_class = type(config.default)
|
||||||
|
new_value = value_class(value)
|
||||||
|
data_[config.name] = new_value
|
||||||
|
self.file_data[character_name].artifact_config[config.parent] = data_
|
||||||
|
self.last_close(character_name)
|
||||||
|
|
||||||
|
def get_artifact_config_enable(
|
||||||
|
self, character_name: str, artifact_key: str
|
||||||
|
) -> bool:
|
||||||
|
if not self.file_data.get(character_name):
|
||||||
|
return False
|
||||||
|
if not self.file_data[character_name].artifact_config:
|
||||||
|
return False
|
||||||
|
return artifact_key in self.file_data[character_name].artifact_config
|
||||||
|
|
||||||
|
|
||||||
|
data = Data()
|
157
src/damage/models.py
Normal file
157
src/damage/models.py
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
import flet
|
||||||
|
from enum import Enum
|
||||||
|
from typing import List, Dict, Any, Optional
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
Element4OP = [
|
||||||
|
flet.dropdown.Option(key="Cyro", text="冰元素"),
|
||||||
|
flet.dropdown.Option(key="Electro", text="雷元素"),
|
||||||
|
flet.dropdown.Option(key="Hydro", text="水元素"),
|
||||||
|
flet.dropdown.Option(key="Pyro", text="火元素"),
|
||||||
|
]
|
||||||
|
Element8OP = Element4OP + [
|
||||||
|
flet.dropdown.Option(key="Anemo", text="风元素"),
|
||||||
|
flet.dropdown.Option(key="Dendro", text="草元素"),
|
||||||
|
flet.dropdown.Option(key="Geo", text="岩元素"),
|
||||||
|
flet.dropdown.Option(key="Physical", text="物理伤害"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class Element4(str, Enum):
|
||||||
|
Cyro = "Cyro"
|
||||||
|
"""冰元素"""
|
||||||
|
Electro = "Electro"
|
||||||
|
"""雷元素"""
|
||||||
|
Hydro = "Hydro"
|
||||||
|
"""水元素"""
|
||||||
|
Pyro = "Pyro"
|
||||||
|
"""火元素"""
|
||||||
|
|
||||||
|
|
||||||
|
class Element8(str, Enum):
|
||||||
|
Cyro = "Cyro"
|
||||||
|
"""冰元素"""
|
||||||
|
Electro = "Electro"
|
||||||
|
"""雷元素"""
|
||||||
|
Hydro = "Hydro"
|
||||||
|
"""水元素"""
|
||||||
|
Pyro = "Pyro"
|
||||||
|
"""火元素"""
|
||||||
|
Anemo = "Anemo"
|
||||||
|
"""风元素"""
|
||||||
|
Dendro = "Dendro"
|
||||||
|
"""草元素"""
|
||||||
|
Geo = "Geo"
|
||||||
|
"""岩元素"""
|
||||||
|
Physical = "Physical"
|
||||||
|
"""物理伤害"""
|
||||||
|
|
||||||
|
|
||||||
|
class CharacterDamageSkillDamageKey(str, Enum):
|
||||||
|
normal = "normal"
|
||||||
|
"""普通伤害结果"""
|
||||||
|
melt = "melt"
|
||||||
|
"""融化伤害结果"""
|
||||||
|
vaporize = "vaporize"
|
||||||
|
"""蒸发伤害结果"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data_map(self) -> Dict[str, str]:
|
||||||
|
return {"普通伤害结果": "normal", "融化伤害结果": "melt", "蒸发伤害结果": "vaporize"}
|
||||||
|
|
||||||
|
|
||||||
|
class CharacterDamageSkill(BaseModel):
|
||||||
|
name: str
|
||||||
|
index: int
|
||||||
|
damage_key: CharacterDamageSkillDamageKey
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
frozen = False
|
||||||
|
|
||||||
|
|
||||||
|
class CharacterDamage(BaseModel):
|
||||||
|
skills: List[CharacterDamageSkill]
|
||||||
|
config: Optional[Dict[str, Any]] = None
|
||||||
|
config_skill: Optional[Dict[str, Any]] = None
|
||||||
|
config_weapon: Optional[Dict[str, Dict[str, Any]]] = None
|
||||||
|
artifact_config: Optional[Dict[str, Dict[str, Any]]] = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
frozen = False
|
||||||
|
|
||||||
|
|
||||||
|
class CharacterConfig(BaseModel):
|
||||||
|
default: Any
|
||||||
|
name: str
|
||||||
|
title: str
|
||||||
|
type: str
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
frozen = False
|
||||||
|
|
||||||
|
|
||||||
|
class CharacterSkill(BaseModel):
|
||||||
|
name: str
|
||||||
|
index: int
|
||||||
|
skill_name: str
|
||||||
|
custom_name: str = ""
|
||||||
|
damage_key: CharacterDamageSkillDamageKey = CharacterDamageSkillDamageKey.normal
|
||||||
|
|
||||||
|
@property
|
||||||
|
def show_name(self) -> str:
|
||||||
|
return f"{self.name} - {self.skill_name}"
|
||||||
|
|
||||||
|
def to_data(self) -> CharacterDamageSkill:
|
||||||
|
return CharacterDamageSkill(
|
||||||
|
name=self.custom_name or self.show_name,
|
||||||
|
index=self.index,
|
||||||
|
damage_key=self.damage_key,
|
||||||
|
)
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
frozen = False
|
||||||
|
|
||||||
|
|
||||||
|
class WeaponConfig(CharacterConfig):
|
||||||
|
max: float = 0
|
||||||
|
min: float = 0
|
||||||
|
parent: str = ""
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
frozen = False
|
||||||
|
|
||||||
|
|
||||||
|
class Weapon(BaseModel):
|
||||||
|
name: str
|
||||||
|
cn_name: str
|
||||||
|
star: int
|
||||||
|
t: str
|
||||||
|
config: List[WeaponConfig]
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
frozen = False
|
||||||
|
|
||||||
|
|
||||||
|
class Artifact(BaseModel):
|
||||||
|
name: str
|
||||||
|
cn_name: str
|
||||||
|
min_star: int
|
||||||
|
max_star: int
|
||||||
|
config: List[WeaponConfig]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config_name(self) -> str:
|
||||||
|
return self.get_config_name(self.name)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_config_name(name: str) -> str:
|
||||||
|
start = "config_"
|
||||||
|
# 将大写转换为下划线加小写
|
||||||
|
# 例如: MaxHp -> max_hp
|
||||||
|
convert_name = "".join(
|
||||||
|
[f"_{i.lower()}" if i.isupper() else i for i in name]
|
||||||
|
).lstrip("_")
|
||||||
|
return f"{start}{convert_name}"
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
frozen = False
|
496
src/damage/page.py
Normal file
496
src/damage/page.py
Normal file
@ -0,0 +1,496 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from flet_core import MainAxisAlignment
|
||||||
|
|
||||||
|
import flet as ft
|
||||||
|
|
||||||
|
from src.data import Page
|
||||||
|
from .artifact import artifact
|
||||||
|
from .character import character
|
||||||
|
from .data import data
|
||||||
|
from .models import (
|
||||||
|
CharacterSkill,
|
||||||
|
CharacterDamageSkillDamageKey,
|
||||||
|
CharacterConfig,
|
||||||
|
Weapon as WeaponModel,
|
||||||
|
Element4OP,
|
||||||
|
Element8OP,
|
||||||
|
)
|
||||||
|
from .weapon import weapon
|
||||||
|
|
||||||
|
|
||||||
|
def edit_damage_view(page: "Page"):
|
||||||
|
name_list = ft.ListView(width=230)
|
||||||
|
skill_list = ft.ListView(expand=True)
|
||||||
|
weapon_list = ft.ListView(expand=True)
|
||||||
|
artifact_list = ft.ListView(expand=True)
|
||||||
|
character_control_list = ft.ListView(expand=True)
|
||||||
|
top_title = ft.Ref[ft.Text]()
|
||||||
|
|
||||||
|
def update_top_title(title: str):
|
||||||
|
"""更新当前页面标题"""
|
||||||
|
top_title.current.value = title
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
def back_choose(_):
|
||||||
|
page.go("/")
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
def save(_):
|
||||||
|
def close_alert(_):
|
||||||
|
success_dialog.open = False
|
||||||
|
top_title.current.value = ""
|
||||||
|
choose_character()
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
data.save()
|
||||||
|
success_dialog = ft.AlertDialog(
|
||||||
|
modal=True,
|
||||||
|
title=ft.Text("保存成功"),
|
||||||
|
content=ft.Text("保存成功"),
|
||||||
|
actions=[
|
||||||
|
ft.TextButton("好", on_click=close_alert),
|
||||||
|
],
|
||||||
|
actions_alignment=MainAxisAlignment.END,
|
||||||
|
)
|
||||||
|
page.dialog = success_dialog
|
||||||
|
success_dialog.open = True
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
def update_skill_component():
|
||||||
|
ch_name = character.current_name
|
||||||
|
skill_list.controls.clear()
|
||||||
|
|
||||||
|
def search_skills(e: ft.ControlEvent = None):
|
||||||
|
temp = skill_list.controls[0]
|
||||||
|
skill_list.controls.clear()
|
||||||
|
skill_list.controls.append(temp)
|
||||||
|
for con in skill_list_data:
|
||||||
|
con: "ft.Container"
|
||||||
|
cb: "ft.Checkbox" = con.content # noqa
|
||||||
|
if e is None or e.data in cb.label:
|
||||||
|
skill_list.controls.append(con)
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
skill_list.controls.append(
|
||||||
|
ft.Container(
|
||||||
|
content=ft.TextField(
|
||||||
|
label="技能配置",
|
||||||
|
on_change=search_skills,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for i in character.skills_map[ch_name]:
|
||||||
|
container = ft.Container(
|
||||||
|
content=ft.Checkbox(
|
||||||
|
label=i.show_name,
|
||||||
|
value=data.get_skill_value(ch_name, i),
|
||||||
|
disabled=True,
|
||||||
|
data=i,
|
||||||
|
),
|
||||||
|
on_click=choose_skill,
|
||||||
|
)
|
||||||
|
skill_list.controls.append(container)
|
||||||
|
skill_list_data = skill_list.controls[1:]
|
||||||
|
|
||||||
|
def update_weapon_component():
|
||||||
|
ch_name = character.current_name
|
||||||
|
character_ = character.characters_map[ch_name]
|
||||||
|
weapon_list.controls.clear()
|
||||||
|
|
||||||
|
def search_weapons(e: ft.ControlEvent = None):
|
||||||
|
temp = weapon_list.controls[0]
|
||||||
|
weapon_list.controls.clear()
|
||||||
|
weapon_list.controls.append(temp)
|
||||||
|
for con in weapon_list_data:
|
||||||
|
con: "ft.Container"
|
||||||
|
cb: "ft.Checkbox" = con.content # noqa
|
||||||
|
if e is None or e.data in cb.label:
|
||||||
|
weapon_list.controls.append(con)
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
weapon_list.controls.append(
|
||||||
|
ft.Container(
|
||||||
|
content=ft.TextField(
|
||||||
|
label="武器配置",
|
||||||
|
on_change=search_weapons,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for i in weapon.weapon_map.get(character_.get("weapon", ""), []):
|
||||||
|
i: "WeaponModel"
|
||||||
|
container = ft.Container(
|
||||||
|
content=ft.Checkbox(
|
||||||
|
label=i.cn_name,
|
||||||
|
value=data.get_weapon_config_enable(ch_name, i.name),
|
||||||
|
disabled=True,
|
||||||
|
data=i,
|
||||||
|
),
|
||||||
|
on_click=choose_weapon,
|
||||||
|
)
|
||||||
|
weapon_list.controls.append(container)
|
||||||
|
weapon_list_data = weapon_list.controls[1:]
|
||||||
|
|
||||||
|
def update_artifact_component():
|
||||||
|
ch_name = character.current_name
|
||||||
|
artifact_list.controls.clear()
|
||||||
|
|
||||||
|
def search_artifacts(e: ft.ControlEvent = None):
|
||||||
|
temp = artifact_list.controls[0]
|
||||||
|
artifact_list.controls.clear()
|
||||||
|
artifact_list.controls.append(temp)
|
||||||
|
for con in artifact_list_data:
|
||||||
|
con: "ft.Container"
|
||||||
|
cb: "ft.Checkbox" = con.content # noqa
|
||||||
|
if e is None or e.data in cb.label:
|
||||||
|
artifact_list.controls.append(con)
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
artifact_list.controls.append(
|
||||||
|
ft.Container(
|
||||||
|
content=ft.TextField(
|
||||||
|
label="圣遗物配置",
|
||||||
|
on_change=search_artifacts,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for i in artifact.artifacts:
|
||||||
|
container = ft.Container(
|
||||||
|
content=ft.Checkbox(
|
||||||
|
label=i.cn_name,
|
||||||
|
value=data.get_artifact_config_enable(ch_name, i.config_name),
|
||||||
|
disabled=True,
|
||||||
|
data=i,
|
||||||
|
),
|
||||||
|
on_click=choose_artifact,
|
||||||
|
)
|
||||||
|
artifact_list.controls.append(container)
|
||||||
|
artifact_list_data = artifact_list.controls[1:]
|
||||||
|
|
||||||
|
def gen_switch_or_text(
|
||||||
|
ch_name, config: CharacterConfig, get_config_value, on_change
|
||||||
|
):
|
||||||
|
ele = None
|
||||||
|
if isinstance(config.default, bool):
|
||||||
|
class_ = ft.Checkbox
|
||||||
|
elif config.type in ["element4", "element8"]:
|
||||||
|
class_ = ft.Dropdown
|
||||||
|
ele = Element4OP if config.type == "element4" else Element8OP
|
||||||
|
else:
|
||||||
|
class_ = ft.TextField
|
||||||
|
ins = class_(
|
||||||
|
label=config.title,
|
||||||
|
value=get_config_value(ch_name, config),
|
||||||
|
data=config,
|
||||||
|
on_change=on_change,
|
||||||
|
)
|
||||||
|
if class_ == ft.Dropdown:
|
||||||
|
ins.options = ele
|
||||||
|
return ins
|
||||||
|
|
||||||
|
def update_config_component(
|
||||||
|
com: List,
|
||||||
|
name: str,
|
||||||
|
config_map,
|
||||||
|
set_character_config_value,
|
||||||
|
get_character_config_value,
|
||||||
|
):
|
||||||
|
ch_name = character.current_name
|
||||||
|
if not character.config_map[ch_name]:
|
||||||
|
return
|
||||||
|
com.append(
|
||||||
|
ft.Container(
|
||||||
|
content=ft.Text(
|
||||||
|
name,
|
||||||
|
size=20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_config_value_change(e: ft.ControlEvent = None):
|
||||||
|
set_character_config_value(ch_name, e.control.data, e.data)
|
||||||
|
|
||||||
|
def reset_all_config_value(_):
|
||||||
|
for config in configs:
|
||||||
|
config.value = config.data.default
|
||||||
|
set_character_config_value(ch_name, config.data, config.data.default)
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
configs = []
|
||||||
|
for i in config_map[ch_name]:
|
||||||
|
content = gen_switch_or_text(
|
||||||
|
ch_name, i, get_character_config_value, on_config_value_change
|
||||||
|
)
|
||||||
|
configs.append(content)
|
||||||
|
com.append(
|
||||||
|
ft.Container(
|
||||||
|
content=content,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if len(configs) != 0:
|
||||||
|
com.append(
|
||||||
|
ft.Container(
|
||||||
|
content=ft.ElevatedButton(
|
||||||
|
"恢复到默认值", on_click=reset_all_config_value
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return com
|
||||||
|
|
||||||
|
def choose_character(e: ft.ControlEvent = None):
|
||||||
|
if e is not None:
|
||||||
|
ch_name = e.control.data[0]
|
||||||
|
character.current_name = ch_name
|
||||||
|
else:
|
||||||
|
ch_name = character.current_name
|
||||||
|
page.update()
|
||||||
|
update_top_title(ch_name)
|
||||||
|
update_skill_component()
|
||||||
|
update_weapon_component()
|
||||||
|
update_artifact_component()
|
||||||
|
character_control_list.controls.clear()
|
||||||
|
com = []
|
||||||
|
character_control_list.controls.append(ft.Column(com))
|
||||||
|
update_config_component(
|
||||||
|
com,
|
||||||
|
" 角色配置",
|
||||||
|
character.config_map,
|
||||||
|
data.set_character_config_value,
|
||||||
|
data.get_character_config_value,
|
||||||
|
)
|
||||||
|
update_config_component(
|
||||||
|
com,
|
||||||
|
" 技能配置",
|
||||||
|
character.config_skill_map,
|
||||||
|
data.set_character_skill_config_value,
|
||||||
|
data.get_character_skill_config_value,
|
||||||
|
)
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
def bs_dismissed(_: ft.ControlEvent = None):
|
||||||
|
choose_character()
|
||||||
|
|
||||||
|
def choose_skill(e: ft.ControlEvent = None):
|
||||||
|
checkbox: ft.Checkbox = e.control.content
|
||||||
|
skill: CharacterSkill = checkbox.data
|
||||||
|
page.overlay.clear()
|
||||||
|
|
||||||
|
def close_bs(_: ft.ControlEvent = None):
|
||||||
|
bs.open = False
|
||||||
|
bs.update()
|
||||||
|
|
||||||
|
def skill_status_change(e_: ft.ControlEvent = None):
|
||||||
|
value = e_.data == "true"
|
||||||
|
data.set_skill_value(character.current_name, skill, value)
|
||||||
|
|
||||||
|
def skill_custom_name_change(e_: ft.ControlEvent = None):
|
||||||
|
skill.custom_name = e_.data
|
||||||
|
data.set_skill_value(character.current_name, skill, True)
|
||||||
|
|
||||||
|
def skill_key_change(e_: ft.ControlEvent = None):
|
||||||
|
skill.damage_key = CharacterDamageSkillDamageKey(e_.data)
|
||||||
|
data.set_skill_value(character.current_name, skill, True)
|
||||||
|
|
||||||
|
bs = ft.BottomSheet(
|
||||||
|
ft.Container(
|
||||||
|
ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text(skill.show_name),
|
||||||
|
ft.Switch(
|
||||||
|
label="显示此数值",
|
||||||
|
value=checkbox.value,
|
||||||
|
on_change=skill_status_change,
|
||||||
|
),
|
||||||
|
ft.TextField(
|
||||||
|
label="自定义显示名称",
|
||||||
|
value=skill.custom_name or skill.show_name,
|
||||||
|
on_change=skill_custom_name_change,
|
||||||
|
),
|
||||||
|
ft.Dropdown(
|
||||||
|
label="输出数据",
|
||||||
|
options=[
|
||||||
|
ft.dropdown.Option(key=v, text=k)
|
||||||
|
for k, v in CharacterDamageSkillDamageKey.normal.data_map.items()
|
||||||
|
],
|
||||||
|
value=skill.damage_key.value,
|
||||||
|
on_change=skill_key_change,
|
||||||
|
),
|
||||||
|
ft.ElevatedButton("关闭", on_click=close_bs),
|
||||||
|
],
|
||||||
|
tight=True,
|
||||||
|
),
|
||||||
|
padding=10,
|
||||||
|
),
|
||||||
|
open=True,
|
||||||
|
on_dismiss=bs_dismissed,
|
||||||
|
)
|
||||||
|
page.overlay.append(bs)
|
||||||
|
page.update()
|
||||||
|
bs.update()
|
||||||
|
|
||||||
|
def choose_weapon(e):
|
||||||
|
choose_weapon_or_artifact(
|
||||||
|
e,
|
||||||
|
data.get_character_weapon_config_value,
|
||||||
|
data.set_character_weapon_config_value,
|
||||||
|
)
|
||||||
|
|
||||||
|
def choose_artifact(e):
|
||||||
|
choose_weapon_or_artifact(
|
||||||
|
e,
|
||||||
|
data.get_character_artifact_config_value,
|
||||||
|
data.set_character_artifact_config_value,
|
||||||
|
)
|
||||||
|
|
||||||
|
def choose_weapon_or_artifact(
|
||||||
|
e: ft.ControlEvent,
|
||||||
|
get_config_value,
|
||||||
|
set_config_value,
|
||||||
|
):
|
||||||
|
ch_name = character.current_name
|
||||||
|
checkbox: ft.Checkbox = e.control.content
|
||||||
|
model: "WeaponModel" = checkbox.data
|
||||||
|
page.overlay.clear()
|
||||||
|
|
||||||
|
def close_bs(_: ft.ControlEvent = None):
|
||||||
|
bs.open = False
|
||||||
|
bs.update()
|
||||||
|
|
||||||
|
def on_config_value_change(e_: ft.ControlEvent = None):
|
||||||
|
set_config_value(ch_name, e_.control.data, e_.data)
|
||||||
|
|
||||||
|
def reset_all_config_value(_):
|
||||||
|
for config in configs:
|
||||||
|
config.value = config.data.default
|
||||||
|
set_config_value(ch_name, config.data, config.data.default)
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
controls = [
|
||||||
|
ft.Text(model.cn_name),
|
||||||
|
]
|
||||||
|
configs = []
|
||||||
|
for i in model.config:
|
||||||
|
content = gen_switch_or_text(
|
||||||
|
ch_name, i, get_config_value, on_config_value_change
|
||||||
|
)
|
||||||
|
configs.append(content)
|
||||||
|
controls.append(content)
|
||||||
|
controls.append(
|
||||||
|
ft.Container(
|
||||||
|
content=ft.ElevatedButton("恢复到默认值", on_click=reset_all_config_value),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
controls.append(ft.ElevatedButton("关闭", on_click=close_bs))
|
||||||
|
|
||||||
|
bs = ft.BottomSheet(
|
||||||
|
ft.Container(
|
||||||
|
ft.Column(
|
||||||
|
controls,
|
||||||
|
tight=True,
|
||||||
|
),
|
||||||
|
padding=10,
|
||||||
|
),
|
||||||
|
open=True,
|
||||||
|
on_dismiss=bs_dismissed,
|
||||||
|
)
|
||||||
|
page.overlay.append(bs)
|
||||||
|
page.update()
|
||||||
|
bs.update()
|
||||||
|
|
||||||
|
def load_names():
|
||||||
|
def search_names(e: ft.ControlEvent = None):
|
||||||
|
temp = name_list.controls[0]
|
||||||
|
name_list.controls.clear()
|
||||||
|
name_list.controls.append(temp)
|
||||||
|
for name_ in name_list_data:
|
||||||
|
if e is None or e.data in name_.text:
|
||||||
|
name_list.controls.append(name_)
|
||||||
|
page.update()
|
||||||
|
|
||||||
|
name_list.controls.append(
|
||||||
|
ft.Container(
|
||||||
|
content=ft.TextField(
|
||||||
|
label="搜索",
|
||||||
|
on_change=search_names,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for index, name in enumerate(character.characters_name):
|
||||||
|
name_list.controls.append(
|
||||||
|
ft.TextButton(
|
||||||
|
text=name,
|
||||||
|
tooltip=name,
|
||||||
|
style=ft.ButtonStyle(
|
||||||
|
shape={
|
||||||
|
"hovered": ft.RoundedRectangleBorder(),
|
||||||
|
"": ft.RoundedRectangleBorder(),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
data=(name,),
|
||||||
|
on_click=choose_character,
|
||||||
|
disabled=False,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
name_list_data = name_list.controls[1:]
|
||||||
|
|
||||||
|
load_names()
|
||||||
|
page.views.append(
|
||||||
|
ft.View(
|
||||||
|
"/edit_damage",
|
||||||
|
[
|
||||||
|
ft.Stack(
|
||||||
|
[
|
||||||
|
ft.Container(
|
||||||
|
content=ft.Row(
|
||||||
|
[
|
||||||
|
ft.Text(
|
||||||
|
ref=top_title,
|
||||||
|
value="请选择需要编辑的角色",
|
||||||
|
size=30,
|
||||||
|
),
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.ElevatedButton(
|
||||||
|
"返回",
|
||||||
|
icon=ft.icons.ARROW_BACK,
|
||||||
|
on_click=back_choose,
|
||||||
|
),
|
||||||
|
ft.ElevatedButton(
|
||||||
|
"保存",
|
||||||
|
icon=ft.icons.DONE,
|
||||||
|
on_click=save,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
alignment=MainAxisAlignment.CENTER,
|
||||||
|
spacing=50,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
alignment=MainAxisAlignment.SPACE_BETWEEN,
|
||||||
|
),
|
||||||
|
padding=10,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
ft.Divider(
|
||||||
|
height=1,
|
||||||
|
),
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
name_list,
|
||||||
|
ft.VerticalDivider(width=1),
|
||||||
|
skill_list,
|
||||||
|
ft.VerticalDivider(width=1),
|
||||||
|
weapon_list,
|
||||||
|
ft.VerticalDivider(width=1),
|
||||||
|
artifact_list,
|
||||||
|
ft.VerticalDivider(width=1),
|
||||||
|
character_control_list,
|
||||||
|
],
|
||||||
|
expand=True,
|
||||||
|
spacing=0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
padding=0,
|
||||||
|
spacing=0,
|
||||||
|
)
|
||||||
|
)
|
28
src/damage/weapon.py
Normal file
28
src/damage/weapon.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import json
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from .assets import assets, locale
|
||||||
|
from .models import Weapon as WeaponModel, WeaponConfig
|
||||||
|
|
||||||
|
|
||||||
|
class Weapon:
|
||||||
|
def __init__(self):
|
||||||
|
weapon_map: Dict[str, WeaponModel] = {}
|
||||||
|
for value in assets.weapon.values():
|
||||||
|
if not value["configs"]:
|
||||||
|
continue
|
||||||
|
cn_name = locale[value["name_index"]]
|
||||||
|
config = []
|
||||||
|
for i in value["configs"]:
|
||||||
|
temp = json.loads(i)
|
||||||
|
temp["title"] = locale[temp["title"]]
|
||||||
|
temp["parent"] = value["name"]
|
||||||
|
config.append(WeaponConfig(**temp))
|
||||||
|
weapon_ = WeaponModel(**value, cn_name=cn_name, config=config)
|
||||||
|
temp = weapon_map.get(value["t"], [])
|
||||||
|
temp.append(weapon_)
|
||||||
|
weapon_map[value["t"]] = temp
|
||||||
|
self.weapon_map = weapon_map
|
||||||
|
|
||||||
|
|
||||||
|
weapon = Weapon()
|
@ -155,7 +155,9 @@ class Core:
|
|||||||
return
|
return
|
||||||
if type_name not in self.data[ch_name]:
|
if type_name not in self.data[ch_name]:
|
||||||
return
|
return
|
||||||
self.data[ch_name] = {k: v for k, v in self.data[ch_name].copy().items() if k != type_name}
|
self.data[ch_name] = {
|
||||||
|
k: v for k, v in self.data[ch_name].copy().items() if k != type_name
|
||||||
|
}
|
||||||
|
|
||||||
def save_value(self):
|
def save_value(self):
|
||||||
self.data = {k: v for k, v in self.data.copy().items() if v}
|
self.data = {k: v for k, v in self.data.copy().items() if v}
|
||||||
|
Loading…
Reference in New Issue
Block a user