🚧伤害计算的一小步

This commit is contained in:
qwerdvd 2023-05-26 20:15:22 +08:00
parent a5ce23d38f
commit 965de7721f
12 changed files with 593 additions and 122 deletions

View File

@ -138,12 +138,8 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
attr_bg_draw = ImageDraw.Draw(attr_bg)
# 生命值
hp = mp.mpf(char.base_attributes.get('hp'))
add_hp = mp.mpf(
char.add_attr['HPDelta'] if char.add_attr.get('HPDelta') else 0
) + hp * mp.mpf(
char.add_attr['HPAddedRatio']
if char.add_attr.get('HPAddedRatio')
else 0
add_hp = mp.mpf(char.add_attr.get('HPDelta', 0)) + hp * mp.mpf(
char.add_attr.get('HPAddedRatio', 0)
)
hp = int(mp.floor(hp))
add_hp = int(mp.floor(add_hp))
@ -159,12 +155,8 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
)
# 攻击力
attack = mp.mpf(char.base_attributes['attack'])
add_attack = mp.mpf(
char.add_attr['AttackDelta'] if char.add_attr.get('AttackDelta') else 0
) + attack * mp.mpf(
char.add_attr['AttackAddedRatio']
if char.add_attr.get('AttackAddedRatio')
else 0
add_attack = mp.mpf(char.add_attr.get('AttackDelta', 0)) + attack * mp.mpf(
char.add_attr.get('AttackAddedRatio', 0)
)
atk = int(mp.floor(attack))
add_attack = int(mp.floor(add_attack))
@ -185,14 +177,8 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
# 防御力
defence = mp.mpf(char.base_attributes['defence'])
add_defence = mp.mpf(
char.add_attr.get('DefenceDelta')
if char.add_attr.get('DefenceDelta')
else 0
) + defence * mp.mpf(
char.add_attr.get('DefenceAddedRatio')
if char.add_attr.get('DefenceAddedRatio')
else 0
)
char.add_attr.get('DefenceDelta', 0)
) + defence * mp.mpf(char.add_attr.get('DefenceAddedRatio', 0))
defence = int(mp.floor(defence))
add_defence = int(mp.floor(add_defence))
attr_bg_draw.text(
@ -211,9 +197,7 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
)
# 速度
speed = mp.mpf(char.base_attributes['speed'])
add_speed = mp.mpf(
char.add_attr['SpeedDelta'] if char.add_attr.get('SpeedDelta') else 0
)
add_speed = mp.mpf(char.add_attr.get('SpeedDelta', 0))
speed = int(mp.floor(speed))
add_speed = int(mp.floor(add_speed))
attr_bg_draw.text(
@ -232,11 +216,7 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
)
# 暴击率
critical_chance = mp.mpf(char.base_attributes['CriticalChance'])
critical_chance_base = mp.mpf(
char.add_attr['CriticalChanceBase']
if char.add_attr.get('CriticalChanceBase')
else 0
)
critical_chance_base = mp.mpf(char.add_attr.get('CriticalChanceBase', 0))
critical_chance = (critical_chance + critical_chance_base) * 100
critical_chance = nstr(critical_chance, 3)
attr_bg_draw.text(
@ -248,11 +228,7 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
)
# 暴击伤害
critical_damage = mp.mpf(char.base_attributes['CriticalDamage'])
critical_damage_base = mp.mpf(
char.add_attr['CriticalDamageBase']
if char.add_attr.get('CriticalDamageBase')
else 0
)
critical_damage_base = mp.mpf(char.add_attr.get('CriticalDamageBase', 0))
critical_damage = (critical_damage + critical_damage_base) * 100
critical_damage = nstr(critical_damage, 4)
attr_bg_draw.text(
@ -264,12 +240,7 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
)
# 效果命中
status_probability_base = (
mp.mpf(
char.add_attr.get('StatusProbabilityBase')
if char.add_attr.get('StatusProbabilityBase')
else 0
)
* 100
mp.mpf(char.add_attr.get('StatusProbabilityBase', 0)) * 100
)
status_probability = nstr(status_probability_base, 3)
attr_bg_draw.text(
@ -281,12 +252,7 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
)
# 效果抵抗
status_resistance_base = (
mp.mpf(
char.add_attr['StatusResistanceBase']
if char.add_attr.get('StatusResistanceBase')
else 0
)
* 100
mp.mpf(char.add_attr.get('StatusResistanceBase', 0)) * 100
)
status_resistance = nstr(status_resistance_base, 3)
attr_bg_draw.text(
@ -578,8 +544,8 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
return res
async def cal_char_info(char_data: dict):
char = Character(char_data)
async def cal_char_info(char_data: Dict):
char: Character = Character(char_data)
await char.get_equipment_info()
await char.get_char_attribute_bonus()
await char.get_relic_info()

View File

@ -1,5 +1,5 @@
import json
from typing import Dict, Tuple
from typing import Dict
from collections import Counter
from mpmath import mp
@ -30,6 +30,14 @@ class Character:
self.equipment = card_prop['equipmentInfo']
self.rarity = card_prop['avatarRarity']
# 伤害计算
self.def_ignore = 0
self.q_dmg = 0
self.q_crit_dmg = 0
self.e_dmg = 0
self.a_dmg = 0
self.a3_dmg = 0
# 角色的圣遗物总分
self.artifacts_all_score: float = 0
self.percent: str = '0.0'
@ -127,30 +135,3 @@ class Character:
print(json.dumps(self.base_attributes))
print(json.dumps(self.add_attr))
async def p2v(power: str, power_plus: int) -> Tuple[float, float]:
"""
将power转换为value
"""
# 如果存在123%+123%形式的
if '+' in power:
power_percent = (
float(power.split('+')[0].replace('%', '')) / 100
) * power_plus
power_value = power.split('+')[1]
if '%' in power_value:
power_percent += (
float(power_value.replace('%', '')) / 100 * power_plus
)
power_value = 0
else:
power_value = float(power_value)
elif '%' in power:
power_percent = float(power.replace('%', '')) / 100 * power_plus
power_value = 0
else:
power_percent = 0
power_value = float(power)
return power_percent, power_value

View File

@ -0,0 +1,32 @@
import re
from gsuid_core.sv import SV
from gsuid_core.bot import Bot
from gsuid_core.models import Event
from .cal_damage import cal
from ..utils.convert import get_uid
from ..utils.sr_prefix import PREFIX
from ..utils.error_reply import UID_HINT
from ..starrailuid_charinfo.draw_char_img import get_char_data
sv_char_damage_cal = SV('sr伤害计算')
@sv_char_damage_cal.on_prefix(f'{PREFIX}伤害计算')
async def send_damage_msg(bot: Bot, ev: Event):
msg = ''.join(re.findall('[\u4e00-\u9fa5 ]', ev.text))
if not msg:
return
await bot.logger.info('开始执行[角色伤害计算]')
# 获取uid
sr_uid = await get_uid(bot, ev)
if sr_uid is None:
return await bot.send(UID_HINT)
await bot.logger.info('[角色伤害计算]uid: {}'.format(sr_uid))
char_name = ' '.join(re.findall('[\u4e00-\u9fa5]+', msg))
char_data = await get_char_data(sr_uid, char_name)
im = await cal(char_data)
await bot.send(im)

View File

@ -0,0 +1,31 @@
from typing import Dict
from mpmath import mp
from .effect.Base.Role import RoleInstance
from ..starrailuid_charinfo.mono.Character import Character
from ..starrailuid_charinfo.draw_char_img import cal_char_info
mp.dps = 14
async def cal(char_data: Dict):
char: Character = await cal_char_info(char_data)
raw_data = {"avatar": {}, "weapon": {}, "relic": []}
raw_data['avatar']['id'] = char.char_id
raw_data['avatar']['level'] = char.char_level
raw_data['avatar']['rank'] = char.char_rank
raw_data['avatar']['promotion'] = char.char_promotion
raw_data['weapon']['id'] = char.equipment['equipmentID']
raw_data['weapon']['level'] = char.equipment['equipmentLevel']
raw_data['weapon']['rank'] = char.equipment['equipmentRank']
raw_data['weapon']['promotion'] = char.equipment['equipmentPromotion']
raw_data['relic'] = char.char_relic
role = RoleInstance(raw_data)
await role.cal_role_base_attr()
await role.cal_relic_attr_add()
return '还没写完呢'

View File

@ -0,0 +1,99 @@
from typing import Dict
from abc import abstractmethod
from mpmath import mp
from ....utils.excel.read_excel import AvatarPromotion
mp.dps = 14
class BaseSkills:
@abstractmethod
async def Basic_ATK(self):
...
@abstractmethod
async def Skill(self):
...
@abstractmethod
async def Ultimate(self):
...
@abstractmethod
async def Talent(self):
...
@abstractmethod
async def Technique(self):
...
class BaseAvatar:
def __init__(self, char: Dict):
self.avatar_id = char['id']
self.avatar_level = char['level']
self.avatar_rank = char['rank']
self.avatar_promotion = char['promotion']
self.avatar_attribute = {}
async def get_attribute(self):
promotion = AvatarPromotion[str(self.avatar_id)][
str(self.avatar_promotion)
]
# 攻击力
self.avatar_attribute['attack'] = mp.mpf(
promotion["AttackBase"]['Value']
) + mp.mpf(promotion["AttackAdd"]['Value']) * (self.avatar_level - 1)
# 防御力
self.avatar_attribute['defence'] = mp.mpf(
promotion["DefenceBase"]['Value']
) + mp.mpf(promotion["DefenceAdd"]['Value']) * (self.avatar_level - 1)
# 血量
self.avatar_attribute['hp'] = mp.mpf(
promotion["HPBase"]['Value']
) + mp.mpf(promotion["HPAdd"]['Value']) * (self.avatar_level - 1)
# 速度
self.avatar_attribute['speed'] = mp.mpf(
promotion["SpeedBase"]['Value']
)
# 暴击率
self.avatar_attribute['CriticalChance'] = mp.mpf(
promotion["CriticalChance"]['Value']
)
# 暴击伤害
self.avatar_attribute['CriticalDamage'] = mp.mpf(
promotion["CriticalDamage"]['Value']
)
# 嘲讽
self.avatar_attribute['BaseAggro'] = mp.mpf(
promotion["BaseAggro"]['Value']
)
class Seele(BaseAvatar, BaseSkills):
def __init__(self, char: Dict):
super().__init__(char)
async def Basic_ATK(self):
pass
async def Skill(self):
pass
async def Ultimate(self):
pass
async def Talent(self):
pass
async def Technique(self):
pass
class Avatar:
def __new__(cls, char: Dict):
if char['id'] == 1102:
return Seele(char)

View File

@ -0,0 +1,68 @@
from typing import Dict, List
from collections import Counter
from mpmath import mp
mp.dps = 14
class SingleRelic:
def __init__(self, relic: Dict):
self.raw_relic = relic
self.relic_id = relic['relicId']
self.set_id = relic['SetId']
self.relic_type = relic['Type']
self.relic_level = relic.get('Level', 0)
self.relic_attribute_bonus = {}
async def get_attribute_(self):
# MainAffix
self.relic_attribute_bonus[
self.raw_relic['MainAffix']['Property']
] = mp.mpf(self.raw_relic['MainAffix']['Value'])
# SubAffix
if self.raw_relic.get('SubAffixList'):
for sub_affix in self.raw_relic['SubAffixList']:
sub_affix_property = sub_affix['Property']
value = mp.mpf(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 RelicSet:
HEAD: SingleRelic
HAND: SingleRelic
BODY: SingleRelic
FOOT: SingleRelic
NECK: SingleRelic
OBJECT: SingleRelic
Unknow: SingleRelic
def __init__(self, relic_list: List):
set_id_list = []
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: List = Counter(set_id_list).most_common()
async def get_attribute(self):
for relic in self.__dict__:
await self.__dict__[relic].get_attribute_()

View File

@ -0,0 +1,52 @@
from typing import Dict
from .Avatar import Avatar
from .Weapon import Weapon
from .Relic import RelicSet, SingleRelic
class RoleInstance:
def __init__(self, raw_data: Dict):
self.raw_data = raw_data
self.avatar = Avatar(raw_data['avatar'])
self.weapon = Weapon(raw_data['weapon'])
self.relic_set = RelicSet(raw_data['relic'])
self.base_attr = {}
self.attribute_bonus = {}
async def cal_role_base_attr(self):
await self.avatar.get_attribute()
avatar_attribute = self.avatar.__dict__['avatar_attribute']
for attribute in avatar_attribute:
if attribute in self.base_attr:
self.base_attr[attribute] += avatar_attribute[attribute]
else:
self.base_attr[attribute] = avatar_attribute[attribute]
await self.weapon.get_attribute()
weapon_attribute = self.weapon.__dict__['weapon_attribute']
for attribute in weapon_attribute:
if attribute in self.base_attr:
self.base_attr[attribute] += weapon_attribute[attribute]
else:
self.base_attr[attribute] = weapon_attribute[attribute]
print(self.base_attr)
async def cal_relic_attr_add(self):
await self.relic_set.get_attribute()
for relic_type in self.relic_set.__dict__:
if type(self.relic_set.__dict__[relic_type]) != SingleRelic:
break
relic: SingleRelic = self.relic_set.__dict__[relic_type]
for attribute in relic.relic_attribute_bonus:
if attribute in self.attribute_bonus:
self.attribute_bonus[
attribute
] += relic.relic_attribute_bonus[attribute]
else:
self.attribute_bonus[
attribute
] = relic.relic_attribute_bonus[attribute]
print(self.attribute_bonus)

View File

@ -0,0 +1,96 @@
import json
from typing import Dict
from pathlib import Path
from mpmath import mp
from ..Base.WeaponBase import BaseWeapon
path = Path(__file__).parent
with open(path / 'weapon_effect.json', 'r', encoding='utf-8') as f:
weapon_effect = json.load(f)
mp.dps = 14
class IntheNight(BaseWeapon):
def __init__(self, weapon: Dict):
super().__init__(weapon)
async def check(self):
pass
async def weapon_ability(self, char):
char = await self.weapon_property_ability(char)
char_speed = mp.mpf(char.base_attributes['speed'])
count_ = min(6, int(mp.floor((char_speed - 100) / 10)))
char.a_dmg += (
mp.mpf(weapon_effect['23001']['Param']['a_dmg'][self.weapon_rank])
* count_
)
char.e_dmg += (
mp.mpf(weapon_effect['23001']['Param']['e_dmg'][self.weapon_rank])
* count_
)
char.q_crit_dmg += (
mp.mpf(
weapon_effect['23001']['Param']['q_crit_dmg'][self.weapon_rank]
)
* count_
)
return char
async def weapon_property_ability(self, char):
char.CriticalChanceBase += mp.mpf(
weapon_effect['23001']['AbilityProperty'][self.weapon_rank]
)
return char
class CruisingintheStellarSea(BaseWeapon):
def __init__(self, weapon: Dict):
super().__init__(weapon)
async def check(self):
# 装备者对生命值百分比小于等于50%的敌方目标
# 装备者消灭敌方目标
return True
async def weapon_ability(self, char):
char = await self.weapon_property_ability(char)
if self.check():
char.CriticalChanceBase += mp.mpf(
weapon_effect['24001']['Param']['CriticalChance'][
self.weapon_rank
]
)
char.AttackAddedRatio += mp.mpf(
weapon_effect['24001']['Param']['AttackAddedRatio'][
self.weapon_rank
]
)
return char
async def weapon_property_ability(self, char):
char.CriticalChanceBase += mp.mpf(
weapon_effect['24001']['AbilityProperty'][self.weapon_rank]
)
return char
class HuntWeapon:
def __new__(cls, weapon: Dict):
if weapon['id'] == 24001:
return CruisingintheStellarSea(weapon)
if weapon['id'] == 23001:
return IntheNight(weapon)
async def check_ability(self):
pass
class Weapon:
def __new__(cls, weapon: Dict):
if weapon['id'] == 24001 or weapon['id'] == 23001:
return HuntWeapon(weapon)

View File

@ -0,0 +1,56 @@
from typing import Dict
from abc import abstractmethod
from mpmath import mp
from ....utils.excel.read_excel import EquipmentPromotion
mp.dps = 14
class BaseWeapon:
def __init__(self, weapon: Dict):
self.weapon_id = weapon['id']
self.weapon_level = weapon['level']
self.weapon_rank = weapon['rank']
self.weapon_promotion = weapon['promotion']
self.weapon_attribute = {}
@abstractmethod
async def weapon_ability(self, char):
'''
战斗加成属性, weapon_property_ability() 互斥
'''
...
@abstractmethod
async def weapon_property_ability(self, char):
'''
面板加成属性, weapon_ability() 互斥
'''
...
@abstractmethod
async def check(self):
...
async def get_attribute(self):
promotion = EquipmentPromotion[str(self.weapon_id)][
str(self.weapon_promotion)
]
self.weapon_attribute['hp'] = mp.mpf(
promotion["BaseHP"]['Value']
) + mp.mpf(promotion["BaseHPAdd"]['Value']) * (self.weapon_level - 1)
self.weapon_attribute['attack'] = mp.mpf(
promotion["BaseAttack"]['Value']
) + mp.mpf(promotion["BaseAttackAdd"]['Value']) * (
self.weapon_level - 1
)
self.weapon_attribute['defence'] = mp.mpf(
promotion["BaseDefence"]['Value']
) + mp.mpf(promotion["BaseDefenceAdd"]['Value']) * (
self.weapon_level - 1
)

View File

@ -1,34 +1,36 @@
{
"于夜色中": {
"enable": true,
"trigger": {
"speed": 100
"23001": {
"Param": {
"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
]
},
"step": {
"speed": 10
},
"attrChange": null,
"A_finalDmg": [
0.06,
0.07,
0.08,
0.09,
0.1
],
"E_finalDmg": [
0.06,
0.07,
0.08,
0.09,
0.1
],
"Q_critDmg": [
0.12,
0.14,
0.16,
0.18,
0.2
"AbilityProperty": [
0.18000000016763806,
0.21000000019557774,
0.24000000022351742,
0.2700000002514571,
0.3000000002793968
]
},
"唯有沉默": {
"enable": true,
@ -49,28 +51,30 @@
"如泥酣眠": {
"enable": false
},
"星海巡航": {
"enable": true,
"trigger": {
"charHpLow": 0.5,
"eliminateEnemy": true
},
"attrChange": {
"24001": {
"Param": {
"CriticalChance": [
0.08,
0.1,
0.12,
0.14,
0.16
0.0800000000745058,
0.10000000009313226,
0.12000000011175871,
0.14000000013038516,
0.1600000001490116
],
"AttackAddedRatio": [
0.2,
0.25,
0.3,
0.35,
0.4
0.20000000018626451,
0.25000000023283064,
0.3000000002793968,
0.3500000003259629,
0.40000000037252903
]
}
},
"AbilityProperty": [
0.0800000000745058,
0.10000000009313226,
0.12000000011175871,
0.14000000013038516,
0.1600000001490116
]
},
"春水初生": {
"enable": true,
@ -175,4 +179,4 @@
]
}
}
}
}

View File

@ -0,0 +1,58 @@
{
"details": {
"A普攻伤害": "a",
"E战技伤害": "e",
"Q终结技伤害": "q"
},
"buffs": {
"Talent": {
"id": 110204,
"desc": "希儿天赋:击杀敌人进入增幅状态提高伤害",
"type": "skillDmg",
"value": [
0.4,
0.44,
0.48,
0.52,
0.56,
0.6,
0.65,
0.7,
0.75,
0.8,
0.84,
0.88,
0.92,
0.96,
1.0
]
},
"Skill": {
"desc": "希儿战技释放战技后速度提高25%",
"type": "SpeedAddedRatio",
"value": 0.25
},
"Eidolons": [
{
"cons": 1,
"desc": "对生命小于80%的敌人造成伤害时暴击率提高15%",
"type": "CriticalChance",
"value": 0.15
},
{
"cons": 2,
"desc": "释放战技后2层Buff速度提高50%",
"type": "SpeedAddedRatio",
"value": 0.5
}
],
"SkillTree": [
{
"tree": 2,
"desc": "行迹-割裂量子抗性穿透提高20",
"type": "QuantumAddedRatio",
"value": 0.2
}
]
}
}

View File

@ -0,0 +1,28 @@
{
"108": {
"2": {},
"4": {
"title": "对有量子弱点的目标造成伤害时无视其20%的防御力",
"data": [
{
"type": "def_ignore",
"value": 0.10000000009313226
},
{
"type": "def_ignore",
"value": 0.10000000009313226
}
]
}
},
"306": {
"2": {
"title": "终结技与追加攻击造成的伤害提高15%",
"check": {
"type": "CriticalChanceBase",
"value": 0.5000000004656613
},
"data": 0.1500000001396984
}
}
}