Added properties calculations

This commit is contained in:
traffic95 2025-03-18 23:17:07 +01:00
parent 543727ce4e
commit 911149856e
11 changed files with 4717 additions and 46 deletions

View file

@ -1,7 +1,10 @@
use std::collections::HashMap;
use trigger_protocol::DungeonEquipInfo;
pub struct AvatarUnit {
pub avatar_id: u32,
pub properties: HashMap<u32, i32>,
}
pub struct BuddyUnit {
@ -29,6 +32,7 @@ impl Dungeon {
.iter()
.map(|unit| AvatarUnitInfo {
avatar_id: unit.avatar_id,
properties: unit.properties.clone(),
})
.collect(),
buddy_list: self

View file

@ -1,4 +1,5 @@
mod dungeon;
mod property_util;
pub use dungeon::*;
pub mod scene;
@ -39,7 +40,14 @@ impl GameState {
quest_id: *quest_id,
avatar_list: avatar_id_list
.iter()
.map(|&avatar_id| AvatarUnit { avatar_id })
.map(|&avatar_id| AvatarUnit {
avatar_id,
properties: property_util::calculate_for_avatar(
avatar_id,
filecfg,
dungeon_equip,
),
})
.collect(),
buddy_list: vec![BuddyUnit {
buddy_type: 0,
@ -71,7 +79,14 @@ impl GameState {
quest_id: *quest_id,
avatar_list: avatar_id_list
.iter()
.map(|&avatar_id| AvatarUnit { avatar_id })
.map(|&avatar_id| AvatarUnit {
avatar_id,
properties: property_util::calculate_for_avatar(
avatar_id,
filecfg,
dungeon_equip,
),
})
.collect(),
buddy_list: vec![BuddyUnit {
buddy_type: 0,

View file

@ -0,0 +1,717 @@
use std::collections::HashMap;
use trigger_fileconfig::{
AvatarBattleTemplate, AvatarLevelAdvanceTemplate, AvatarPassiveSkillTemplate, NapFileCfg,
WeaponLevelTemplate, WeaponStarTemplate, WeaponTemplate,
};
use trigger_logic::{battle::EPropertyType, skill::EAvatarSkillType};
use trigger_protocol::{Avatar, DungeonEquipInfo, Equip, Weapon};
struct AvatarFileCfg<'a> {
pub avatar_battle_template: AvatarBattleTemplate<'a>,
pub avatar_passive_skill_templates: Vec<AvatarPassiveSkillTemplate<'a>>,
pub avatar_level_advances: Vec<AvatarLevelAdvanceTemplate<'a>>,
}
struct WeaponFileCfg<'a> {
pub weapon_template: WeaponTemplate<'a>,
pub weapon_level_template: WeaponLevelTemplate<'a>,
pub weapon_star_template: WeaponStarTemplate<'a>,
}
const BEN_AVATAR_ID: u32 = 1121;
const BEN_CORE_PASSIVE_PERCENTAGE: [i32; 7] = [40, 46, 52, 60, 66, 72, 80];
pub fn calculate_for_avatar(
avatar_id: u32,
filecfg: &'static NapFileCfg,
dungeon_equip: &DungeonEquipInfo,
) -> HashMap<u32, i32> {
let mut calculated_properties = HashMap::<_, _>::new();
let Some(player_avatar) = dungeon_equip
.avatar_list
.iter()
.find(|a| (*a).id == avatar_id)
else {
return calculated_properties;
};
let Some(avatar_file_cfg) = get_avatar_filecfg(avatar_id, filecfg) else {
return calculated_properties;
};
insert_avatar_battle_template_properties(&avatar_file_cfg, &mut calculated_properties);
insert_avatar_battle_level_advance_properties(
&avatar_file_cfg,
player_avatar,
&mut calculated_properties,
);
perform_avatar_growth_promotion_calculations(player_avatar, &mut calculated_properties);
add_avatar_passive_skill_properties(
&avatar_file_cfg,
player_avatar,
&mut calculated_properties,
);
let player_weapon = dungeon_equip
.weapon_list
.iter()
.find(|w| w.uid == player_avatar.cur_weapon_uid);
if player_weapon.is_some() {
match get_weapon_filecfg(player_weapon.unwrap(), filecfg) {
Some(weapon_file_cfg) => {
add_weapon_template_properties(&weapon_file_cfg, &mut calculated_properties);
}
None => {}
};
}
let player_dressed_equip_uids: Vec<u32> = player_avatar
.dressed_equip_list
.iter()
.map(|de| de.equip_uid)
.collect();
let player_equips: Vec<&Equip> = dungeon_equip
.equip_list
.iter()
.filter(|e| player_dressed_equip_uids.contains(&e.uid))
.collect();
if player_equips.len() > 0 {
add_player_equip_properties(&player_equips, filecfg, &mut calculated_properties);
add_equipment_suit_properties(&player_equips, filecfg, &mut calculated_properties);
}
calculate_final_properties(&mut calculated_properties);
add_ben_core_passive(avatar_id, player_avatar, &mut calculated_properties);
remove_custom_properties(&mut calculated_properties);
set_battle_properties(&mut calculated_properties);
calculated_properties
}
fn get_avatar_filecfg(
avatar_id: u32,
filecfg: &'static NapFileCfg,
) -> Option<AvatarFileCfg<'static>> {
let Some(avatar_battle_template) = filecfg
.avatar_battle_template_tb()
.data()
.unwrap()
.iter()
.find(|tmpl| tmpl.id() == avatar_id as i32)
else {
return None;
};
let avatar_passive_skill_templates: Vec<AvatarPassiveSkillTemplate> = filecfg
.avatar_passive_skill_template_tb()
.data()
.unwrap()
.iter()
.filter(|tmpl| tmpl.avatar_id() == avatar_id as i32)
.collect();
if avatar_passive_skill_templates.len() == 0 {
return None;
}
let avatar_level_advances: Vec<AvatarLevelAdvanceTemplate> = filecfg
.avatar_level_advance_template_tb()
.data()
.unwrap()
.iter()
.filter(|tmpl| tmpl.avatar_id() == avatar_id as i32)
.collect();
if avatar_level_advances.len() == 0 {
return None;
}
Some(AvatarFileCfg {
avatar_battle_template,
avatar_passive_skill_templates,
avatar_level_advances,
})
}
fn insert_avatar_battle_template_properties(
avatar_file_cfg: &AvatarFileCfg,
properties: &mut HashMap<u32, i32>,
) {
properties.insert(
EPropertyType::HpMaxBase.into(),
avatar_file_cfg.avatar_battle_template.hp_max(),
);
properties.insert(
EPropertyType::HpMaxGrowth.into(),
avatar_file_cfg.avatar_battle_template.health_growth(),
);
properties.insert(
EPropertyType::AtkBase.into(),
avatar_file_cfg.avatar_battle_template.attack(),
);
properties.insert(
EPropertyType::AtkGrowth.into(),
avatar_file_cfg.avatar_battle_template.attack_growth(),
);
properties.insert(
EPropertyType::BreakStunBase.into(),
avatar_file_cfg.avatar_battle_template.break_stun(),
);
properties.insert(
EPropertyType::DefBase.into(),
avatar_file_cfg.avatar_battle_template.defence(),
);
properties.insert(
EPropertyType::DefGrowth.into(),
avatar_file_cfg.avatar_battle_template.defence_growth(),
);
properties.insert(
EPropertyType::CritBase.into(),
avatar_file_cfg.avatar_battle_template.crit(),
);
properties.insert(
EPropertyType::CritDmgBase.into(),
avatar_file_cfg.avatar_battle_template.crit_damage(),
);
properties.insert(
EPropertyType::PenBase.into(),
avatar_file_cfg.avatar_battle_template.pen_rate(),
);
properties.insert(
EPropertyType::PenValueBase.into(),
avatar_file_cfg.avatar_battle_template.pen_delta(),
);
properties.insert(
EPropertyType::SpRecoverBase.into(),
avatar_file_cfg.avatar_battle_template.sp_recover(),
);
properties.insert(
EPropertyType::ElementMysteryBase.into(),
avatar_file_cfg.avatar_battle_template.element_mystery(),
);
properties.insert(
EPropertyType::ElementAbnormalPowerBase.into(),
avatar_file_cfg
.avatar_battle_template
.element_abnormal_power(),
);
}
fn insert_avatar_battle_level_advance_properties(
avatar_file_cfg: &AvatarFileCfg,
player_avatar: &Avatar,
properties: &mut HashMap<u32, i32>,
) {
let Some(avatar_level_advance) = avatar_file_cfg
.avatar_level_advances
.iter()
.find(|tmpl| tmpl.id() == player_avatar.rank as i32)
else {
properties.insert(EPropertyType::HpMaxAdvance.into(), 0);
properties.insert(EPropertyType::AtkAdvance.into(), 0);
properties.insert(EPropertyType::DefAdvance.into(), 0);
return;
};
properties.insert(
EPropertyType::HpMaxAdvance.into(),
avatar_level_advance.hp_max(),
);
properties.insert(
EPropertyType::AtkAdvance.into(),
avatar_level_advance.attack(),
);
properties.insert(
EPropertyType::DefAdvance.into(),
avatar_level_advance.defence(),
);
}
fn perform_avatar_growth_promotion_calculations(
player_avatar: &Avatar,
properties: &mut HashMap<u32, i32>,
) {
properties.insert(
EPropertyType::HpMaxBase.into(),
properties.get(&EPropertyType::HpMaxBase.into()).unwrap()
+ (((player_avatar.level - 1) as f32
* *properties.get(&EPropertyType::HpMaxGrowth.into()).unwrap() as f32)
/ 10000f32) as i32
+ properties.get(&EPropertyType::HpMaxAdvance.into()).unwrap(),
);
properties.insert(
EPropertyType::AtkBase.into(),
properties.get(&EPropertyType::AtkBase.into()).unwrap()
+ (((player_avatar.level - 1) as f32
* *properties.get(&EPropertyType::AtkGrowth.into()).unwrap() as f32)
/ 10000f32) as i32
+ properties.get(&EPropertyType::AtkAdvance.into()).unwrap(),
);
properties.insert(
EPropertyType::DefBase.into(),
properties.get(&EPropertyType::DefBase.into()).unwrap()
+ (((player_avatar.level - 1) as f32
* *properties.get(&EPropertyType::DefGrowth.into()).unwrap() as f32)
/ 10000f32) as i32
+ properties.get(&EPropertyType::DefAdvance.into()).unwrap(),
);
}
fn add_avatar_passive_skill_properties(
avatar_file_cfg: &AvatarFileCfg,
player_avatar: &Avatar,
properties: &mut HashMap<u32, i32>,
) {
let passive_skill_level = player_avatar
.skill_type_level
.iter()
.find(|s| s.skill_type == EAvatarSkillType::CoreSkill as u32)
.unwrap()
.level;
avatar_file_cfg
.avatar_passive_skill_templates
.iter()
.find(|a| a.unlock_passive_skill_level() == passive_skill_level as i32)
.map(|tmpl| tmpl.propertys().unwrap())
.unwrap()
.iter()
.for_each(|p| {
properties.insert(
p.property() as u32,
properties.get(&(p.property() as u32)).unwrap_or(&0) + p.value(),
);
});
}
fn get_weapon_filecfg(
player_weapon: &Weapon,
filecfg: &'static NapFileCfg,
) -> Option<WeaponFileCfg<'static>> {
let Some(weapon_template) = filecfg
.weapon_template_tb()
.data()
.unwrap()
.iter()
.find(|tmpl| tmpl.item_id() == player_weapon.id as i32)
else {
return None;
};
let Some(weapon_level_template) = filecfg
.weapon_level_template_tb()
.data()
.unwrap()
.iter()
.find(|tmpl| tmpl.level() == player_weapon.level as i32)
else {
return None;
};
let Some(weapon_star_template) = filecfg
.weapon_star_template_tb()
.data()
.unwrap()
.iter()
.find(|tmpl| tmpl.star() == player_weapon.star as i32)
else {
return None;
};
Some(WeaponFileCfg {
weapon_template,
weapon_level_template,
weapon_star_template,
})
}
fn add_weapon_template_properties(
weapon_file_cfg: &WeaponFileCfg,
properties: &mut HashMap<u32, i32>,
) {
let base_property = weapon_file_cfg.weapon_template.base_property().unwrap();
let base_property_value = base_property.value()
+ (base_property.value() as f32 * weapon_file_cfg.weapon_level_template.rate() as f32
/ 10000f32) as i32
+ (base_property.value() as f32 * weapon_file_cfg.weapon_star_template.star_rate() as f32
/ 10000f32) as i32;
properties.insert(
base_property.property() as u32,
*properties
.get(&(base_property.property() as u32))
.unwrap_or(&0)
+ base_property_value,
);
let rand_property = weapon_file_cfg.weapon_template.rand_property().unwrap();
let rand_property_value = rand_property.value()
+ (rand_property.value() as f32 * weapon_file_cfg.weapon_star_template.rand_rate() as f32
/ 10000f32) as i32;
properties.insert(
rand_property.property() as u32,
*properties
.get(&(rand_property.property() as u32))
.unwrap_or(&0)
+ rand_property_value,
);
}
fn add_player_equip_properties(
player_equips: &Vec<&Equip>,
filecfg: &'static NapFileCfg,
properties: &mut HashMap<u32, i32>,
) {
player_equips.iter().for_each(|pe| {
let equip_rarity = (pe.id / 10) % 10;
let property_rate = filecfg
.equipment_level_template_tb()
.data()
.unwrap()
.iter()
.find(|tmpl| tmpl.rarity() == equip_rarity as i32 && tmpl.level() == pe.level as i32)
.map(|tmpl| tmpl.property_rate())
.unwrap_or(1);
pe.propertys.iter().for_each(|p| {
properties.insert(
p.key,
properties.get(&p.key).unwrap_or(&0)
+ p.base_value as i32
+ (p.base_value as f32 * property_rate as f32 / 10000f32) as i32,
);
});
pe.sub_propertys.iter().for_each(|p| {
properties.insert(
p.key,
properties.get(&p.key).unwrap_or(&0)
+ (p.base_value as f32 * p.add_value as f32) as i32,
);
});
});
}
fn add_equipment_suit_properties(
player_equips: &Vec<&Equip>,
filecfg: &'static NapFileCfg,
properties: &mut HashMap<u32, i32>,
) {
let mut suit_counts = HashMap::<i32, i32>::new();
player_equips.iter().for_each(|pe| {
let suit_id = pe.id as i32 / 100 * 100;
suit_counts.insert(suit_id, *suit_counts.get(&suit_id).unwrap_or(&0) + 1);
});
suit_counts.iter().for_each(|sc| {
let Some(equipment_suit_template) = filecfg
.equipment_suit_template_tb()
.data()
.unwrap()
.iter()
.find(|tmpl| tmpl.id() == *sc.0)
else {
return;
};
if equipment_suit_template.primary_condition() <= *sc.1 {
equipment_suit_template
.primary_suit_propertys()
.unwrap()
.iter()
.for_each(|p| {
properties.insert(
p.property() as u32,
properties.get(&(p.property() as u32)).unwrap_or(&0) + p.value(),
);
});
}
});
}
fn calculate_final_properties(properties: &mut HashMap<u32, i32>) {
properties.insert(
EPropertyType::HpMax.into(),
properties.get(&EPropertyType::HpMaxBase.into()).unwrap()
+ (*properties.get(&EPropertyType::HpMaxBase.into()).unwrap() as f32
* *properties
.get(&EPropertyType::HpMaxRatio.into())
.unwrap_or(&0) as f32
/ 10000f32)
.ceil() as i32
+ properties
.get(&EPropertyType::HpMaxDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::Atk.into(),
properties.get(&EPropertyType::AtkBase.into()).unwrap()
+ (*properties.get(&EPropertyType::AtkBase.into()).unwrap() as f32
* *properties
.get(&EPropertyType::AtkRatio.into())
.unwrap_or(&0) as f32
/ 10000f32) as i32
+ properties
.get(&EPropertyType::AtkDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::BreakStun.into(),
properties
.get(&EPropertyType::BreakStunBase.into())
.unwrap()
+ (*properties
.get(&EPropertyType::BreakStunBase.into())
.unwrap() as f32
* *properties
.get(&EPropertyType::BreakStunRatio.into())
.unwrap_or(&0) as f32
/ 10000f32) as i32
+ properties
.get(&EPropertyType::BreakStunDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::Def.into(),
properties.get(&EPropertyType::DefBase.into()).unwrap()
+ (*properties.get(&EPropertyType::DefBase.into()).unwrap() as f32
* *properties
.get(&EPropertyType::DefRatio.into())
.unwrap_or(&0) as f32
/ 10000f32) as i32
+ properties
.get(&EPropertyType::DefDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::Crit.into(),
properties.get(&EPropertyType::CritBase.into()).unwrap()
+ properties
.get(&EPropertyType::CritDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::CritDmg.into(),
properties.get(&EPropertyType::CritDmgBase.into()).unwrap()
+ properties
.get(&EPropertyType::CritDmgDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::Pen.into(),
properties.get(&EPropertyType::PenBase.into()).unwrap()
+ properties
.get(&EPropertyType::PenDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::PenValue.into(),
properties.get(&EPropertyType::PenValueBase.into()).unwrap()
+ properties
.get(&EPropertyType::PenValueDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::SpRecover.into(),
properties
.get(&EPropertyType::SpRecoverBase.into())
.unwrap()
+ (*properties
.get(&EPropertyType::SpRecoverBase.into())
.unwrap() as f32
* *properties
.get(&EPropertyType::SpRecoverRatio.into())
.unwrap_or(&0) as f32
/ 10000f32) as i32
+ properties
.get(&EPropertyType::SpRecoverDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::ElementMystery.into(),
properties
.get(&EPropertyType::ElementMysteryBase.into())
.unwrap()
+ properties
.get(&EPropertyType::ElementMysteryDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::ElementAbnormalPower.into(),
properties
.get(&EPropertyType::ElementAbnormalPowerBase.into())
.unwrap()
+ (*properties
.get(&EPropertyType::ElementAbnormalPowerBase.into())
.unwrap() as f32
* *properties
.get(&EPropertyType::ElementAbnormalPowerRatio.into())
.unwrap_or(&0) as f32
/ 10000f32) as i32
+ properties
.get(&EPropertyType::ElementAbnormalPowerDelta.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::AddedDamageRatioPhysics.into(),
properties
.get(&EPropertyType::AddedDamageRatioPhysics1.into())
.unwrap_or(&0)
+ properties
.get(&EPropertyType::AddedDamageRatioPhysics3.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::AddedDamageRatioFire.into(),
properties
.get(&EPropertyType::AddedDamageRatioFire1.into())
.unwrap_or(&0)
+ properties
.get(&EPropertyType::AddedDamageRatioFire3.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::AddedDamageRatioIce.into(),
properties
.get(&EPropertyType::AddedDamageRatioIce1.into())
.unwrap_or(&0)
+ properties
.get(&EPropertyType::AddedDamageRatioIce3.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::AddedDamageRatioElec.into(),
properties
.get(&EPropertyType::AddedDamageRatioElec1.into())
.unwrap_or(&0)
+ properties
.get(&EPropertyType::AddedDamageRatioElec3.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::AddedDamageRatioEther.into(),
properties
.get(&EPropertyType::AddedDamageRatioEther1.into())
.unwrap_or(&0)
+ properties
.get(&EPropertyType::AddedDamageRatioEther3.into())
.unwrap_or(&0),
);
}
fn add_ben_core_passive(
avatar_id: u32,
player_avatar: &Avatar,
properties: &mut HashMap<u32, i32>,
) {
if avatar_id != BEN_AVATAR_ID {
return;
}
let core_level = player_avatar
.skill_type_level
.iter()
.find(|sl| sl.skill_type == EAvatarSkillType::CoreSkill as u32)
.unwrap()
.level as usize;
let def_atk_bonus = match core_level {
1..=7 => {
*properties.get(&EPropertyType::Def.into()).unwrap_or(&0)
* BEN_CORE_PASSIVE_PERCENTAGE[core_level - 1]
/ 100
}
_ => 0,
};
properties.insert(
EPropertyType::Atk.into(),
*properties.get(&EPropertyType::Atk.into()).unwrap_or(&0) + def_atk_bonus,
);
}
fn remove_custom_properties(properties: &mut HashMap<u32, i32>) {
properties.remove(&EPropertyType::HpMaxGrowth.into());
properties.remove(&EPropertyType::AtkGrowth.into());
properties.remove(&EPropertyType::DefGrowth.into());
properties.remove(&EPropertyType::HpMaxAdvance.into());
properties.remove(&EPropertyType::AtkAdvance.into());
properties.remove(&EPropertyType::DefAdvance.into());
}
fn set_battle_properties(properties: &mut HashMap<u32, i32>) {
properties.insert(
EPropertyType::Hp.into(),
*properties.get(&EPropertyType::HpMax.into()).unwrap_or(&0),
);
properties.insert(
EPropertyType::HpMaxBattle.into(),
*properties.get(&EPropertyType::HpMax.into()).unwrap_or(&0),
);
properties.insert(
EPropertyType::AtkBattle.into(),
*properties.get(&EPropertyType::Atk.into()).unwrap_or(&0),
);
properties.insert(
EPropertyType::BreakStunBattle.into(),
*properties
.get(&EPropertyType::BreakStun.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::DefBattle.into(),
*properties.get(&EPropertyType::Def.into()).unwrap_or(&0),
);
properties.insert(
EPropertyType::CritBattle.into(),
*properties.get(&EPropertyType::Crit.into()).unwrap_or(&0),
);
properties.insert(
EPropertyType::CritDmgBattle.into(),
*properties.get(&EPropertyType::CritDmg.into()).unwrap_or(&0),
);
properties.insert(
EPropertyType::PenRatioBattle.into(),
*properties.get(&EPropertyType::Pen.into()).unwrap_or(&0),
);
properties.insert(
EPropertyType::PenDeltaBattle.into(),
*properties
.get(&EPropertyType::PenValue.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::SpRecoverBattle.into(),
*properties
.get(&EPropertyType::SpRecover.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::ElementMysteryBattle.into(),
*properties
.get(&EPropertyType::ElementMystery.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::ElementAbnormalPowerBattle.into(),
*properties
.get(&EPropertyType::ElementAbnormalPower.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::AddedDamageRatioPhysicsBattle.into(),
*properties
.get(&EPropertyType::AddedDamageRatioPhysics.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::AddedDamageRatioFireBattle.into(),
*properties
.get(&EPropertyType::AddedDamageRatioFire.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::AddedDamageRatioIceBattle.into(),
*properties
.get(&EPropertyType::AddedDamageRatioIce.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::AddedDamageRatioElecBattle.into(),
*properties
.get(&EPropertyType::AddedDamageRatioElec.into())
.unwrap_or(&0),
);
properties.insert(
EPropertyType::AddedDamageRatioEtherBattle.into(),
*properties
.get(&EPropertyType::AddedDamageRatioEther.into())
.unwrap_or(&0),
);
}

View file

@ -215,17 +215,32 @@ table EquipmentSuitTemplate {
id: int;
name: string;
primary_condition: int;
primary_suit_propertys: [Property];
unk_3: int;
primary_suit_ability: int;
primary_description: string;
secondary_condition: int;
secondary_suit_propertys: [Property];
unk_7: int;
secondary_suit_ability: int;
secondary_description: string;
suit_item_icon: string;
suit_icon: string;
suit_story: string;
suit_filter_option: string;
suit_icon: string;
suit_item_icon: string;
unk_14: int;
order: int;
unk_16: int;
unk_17: int;
unk_18: int;
unk_19: int;
unk_20: int;
unk_21: int;
primary_suit_propertys: [Property];
unk_23: [int];
unk_24: int;
unk_25: [int];
unk_26: [int];
unk_27: [int];
tag: string;
}
table HollowConfigTemplate {
@ -380,6 +395,160 @@ table ConditionConfigTemplate {
type: int;
}
table AvatarBattleTemplate {
id: int;
unk_1: [int];
unk_2: [int];
unk_3: [int];
unk_4: [int];
unk_5: [int];
unk_6: [int];
unk_7: [int];
unk_8: int;
unk_9: int;
unk_10: int;
avatar_piece_id: int;
unk_12: int;
unk_13: int;
hp_max: int;
health_growth: int;
unk_16: int;
unk_17: int;
unk_18: int;
unk_19: int;
unk_20: int;
attack: int;
attack_growth: int;
defence: int;
defence_growth: int;
crit: int;
crit_damage: int;
crit_res: int;
crit_damage_res: int;
pen_rate: int;
pen_delta: int;
luck: int;
stun: int;
break_stun: int;
element_abnormal_power: int;
sp_bar_point: int;
sp_recover: int;
element_mystery: int;
rbl: int;
rbl_correction_factor: int;
rbl_probability: int;
unk_41: int;
unk_42: int;
unk_43: int;
unk_44: int;
unk_45: int;
unk_46: int;
unk_47: int;
unk_48: int;
unk_49: int;
unk_50: int;
unk_51: int;
unk_52: int;
unk_53: int;
unk_54: int;
unk_55: int;
unk_56: int;
unk_57: int;
unk_58: int;
unk_59: int;
unk_60: int;
unk_61: int;
unk_62: int;
unk_63: int;
unk_64: int;
unk_65: int;
unk_66: int;
tags: [string];
unk_68: [int];
unk_69: [int];
unk_70: int;
unk_71: int;
element: [int];
hit_type: [int];
unk_element_camp: [string];
unk_75: int;
unk_76: short;
}
table AvatarLevelAdvanceTemplate {
avatar_id: int;
id: int;
min_level: int;
max_level: int;
hp_max: int;
unk_5: int;
unk_6: int;
attack: int;
defence: int;
unk_9: int;
unk_10: int;
unk_11: int;
unk_12: int;
unk_13: int;
unk_14: int;
unk_15: int;
unk_16: int;
unk_17: int;
unk_18: [int];
promotion_costs: [RefineCost];
}
table WeaponLevelTemplate {
rarity: int;
level: int;
rate: int;
exp: int;
}
table WeaponStarTemplate {
rarity: int;
star: int;
min_level: int;
max_level: int;
star_rate: int;
rand_rate: int;
unk_6: int;
unk_7: int;
unk_8: int;
unk_9: int;
unk_10: int;
unk_11: int;
unk_12: int;
}
table AvatarPassiveSkillTemplate {
skill_id: int;
avatar_id: int;
min_avatar_level: int;
min_passive_skill_level: int;
unlock_passive_skill_level: int;
unk_5: int;
unk_levelup: string;
unk_7: int;
unk_8: int;
unk_9: int;
unk_10: int;
propertys: [Property];
names: [string];
descriptions: [string];
materials_costs: [RefineCost];
}
table EquipmentLevelTemplate {
rarity: int;
level: int;
property_rate: int;
unk_3: int;
unk_4: int;
unk_5: int;
unk_6: int;
}
table AvatarBaseTemplateTb {
data: [AvatarBaseTemplate];
}
@ -451,3 +620,27 @@ table TeleportConfigTemplateTb {
table ConditionConfigTemplateTb {
data: [ConditionConfigTemplate];
}
table AvatarBattleTemplateTb {
data: [AvatarBattleTemplate];
}
table AvatarLevelAdvanceTemplateTb {
data: [AvatarLevelAdvanceTemplate];
}
table WeaponLevelTemplateTb {
data: [WeaponLevelTemplate];
}
table WeaponStarTemplateTb {
data: [WeaponStarTemplate];
}
table AvatarPassiveSkillTemplateTb {
data: [AvatarPassiveSkillTemplate];
}
table EquipmentLevelTemplateTb {
data: [EquipmentLevelTemplate];
}

File diff suppressed because it is too large Load diff

View file

@ -58,4 +58,10 @@ file_cfg! {
BattleGroupConfigTemplateTb;
MusicPlayerConfigTemplateTb;
TeleportConfigTemplateTb;
AvatarBattleTemplateTb;
AvatarLevelAdvanceTemplateTb;
WeaponLevelTemplateTb;
WeaponStarTemplateTb;
AvatarPassiveSkillTemplateTb;
EquipmentLevelTemplateTb;
}

View file

@ -0,0 +1,91 @@
use num_enum::{IntoPrimitive, TryFromPrimitive};
#[repr(u32)]
#[derive(IntoPrimitive, TryFromPrimitive)]
pub enum EPropertyType {
Hp = 1,
HpMax = 111,
Atk = 121,
BreakStun = 122,
Def = 131,
Crit = 201,
CritDmg = 211,
Pen = 231,
PenValue = 232,
SpRecover = 305,
ElementMystery = 312,
ElementAbnormalPower = 314,
AddedDamageRatioPhysics = 315,
AddedDamageRatioFire = 316,
AddedDamageRatioIce = 317,
AddedDamageRatioElec = 318,
AddedDamageRatioEther = 319,
// battle
HpMaxBattle = 1111,
AtkBattle = 1121,
BreakStunBattle = 1122,
DefBattle = 1131,
CritBattle = 1201,
CritDmgBattle = 1211,
PenRatioBattle = 1231,
PenDeltaBattle = 1232,
SpRecoverBattle = 1305,
ElementMysteryBattle = 1312,
ElementAbnormalPowerBattle = 1314,
AddedDamageRatioPhysicsBattle = 1315,
AddedDamageRatioFireBattle = 1316,
AddedDamageRatioIceBattle = 1317,
AddedDamageRatioElecBattle = 1318,
AddedDamageRatioEtherBattle = 1319,
// base
HpMaxBase = 11101,
AtkBase = 12101,
BreakStunBase = 12201,
DefBase = 13101,
CritBase = 20101,
CritDmgBase = 21101,
PenBase = 23101,
PenValueBase = 23201,
SpRecoverBase = 30501,
ElementMysteryBase = 31201,
ElementAbnormalPowerBase = 31401,
// ratio
HpMaxRatio = 11102,
AtkRatio = 12102,
BreakStunRatio = 12202,
DefRatio = 13102,
SpRecoverRatio = 30502,
ElementAbnormalPowerRatio = 31402,
// delta
HpMaxDelta = 11103,
AtkDelta = 12103,
BreakStunDelta = 12203,
DefDelta = 13103,
CritDelta = 20103,
CritDmgDelta = 21103,
PenDelta = 23103,
PenValueDelta = 23203,
SpRecoverDelta = 30503,
ElementMysteryDelta = 31203,
ElementAbnormalPowerDelta = 31403,
// damage ratios 1/3
AddedDamageRatioPhysics1 = 31501,
AddedDamageRatioPhysics3 = 31503,
AddedDamageRatioFire1 = 31601,
AddedDamageRatioFire3 = 31603,
AddedDamageRatioIce1 = 31701,
AddedDamageRatioIce3 = 31703,
AddedDamageRatioElec1 = 31801,
AddedDamageRatioElec3 = 31803,
AddedDamageRatioEther1 = 31901,
AddedDamageRatioEther3 = 31903,
// --- custom
// growth
HpMaxGrowth = 9999_111_0,
AtkGrowth = 9999_121_0,
DefGrowth = 9999_131_0,
// advance
HpMaxAdvance = 9999_111_1,
AtkAdvance = 9999_121_1,
DefAdvance = 9999_131_1,
}

View file

@ -1,4 +1,5 @@
pub mod action_pb;
pub mod battle;
pub mod item;
pub mod quest;
pub mod scene;

View file

@ -1039,6 +1039,8 @@ pub struct GetResourceDataScRsp {
#[derive(trigger_protobuf_derive::XorFields)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct BuddyUnitInfo {
#[prost(map = "uint32, int32", tag = "15")]
pub properties: ::std::collections::HashMap<u32, i32>,
#[xor(2099)]
#[prost(uint32, tag = "14")]
pub buddy_id: u32,
@ -1710,6 +1712,8 @@ pub struct AvatarUnitInfo {
#[xor(11167)]
#[prost(uint32, tag = "12")]
pub avatar_id: u32,
#[prost(map = "uint32, int32", tag = "2")]
pub properties: ::std::collections::HashMap<u32, i32>,
}
#[derive(trigger_protobuf_derive::CmdID)]
#[cmdid(6984)]

View file

@ -4956,6 +4956,11 @@ impl From<AvatarUnitInfo> for ::trigger_protocol::AvatarUnitInfo {
fn from(value: AvatarUnitInfo) -> Self {
Self {
avatar_id: value.avatar_id.into(),
properties: value
.properties
.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect(),
..Default::default()
}
}
@ -4965,6 +4970,11 @@ impl From<::trigger_protocol::AvatarUnitInfo> for AvatarUnitInfo {
fn from(value: ::trigger_protocol::AvatarUnitInfo) -> Self {
Self {
avatar_id: value.avatar_id.into(),
properties: value
.properties
.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect(),
..Default::default()
}
}

View file

@ -355,6 +355,7 @@ pub struct DungeonEquipInfo {
#[derive(Default, Debug, Clone, Encodeable, Decodeable)]
pub struct AvatarUnitInfo {
pub avatar_id: u32,
pub properties: HashMap<u32, i32>,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable)]