256 lines
9.1 KiB
Rust
256 lines
9.1 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use wicked_waifus_protocol::{ArrayIntInt, RoleInfo};
|
|
|
|
use crate::config;
|
|
use crate::logic::utils::growth_utils::get_role_props_by_level;
|
|
use crate::logic::utils::load_role_info::load_key_value;
|
|
pub use formation::RoleFormation;
|
|
use wicked_waifus_commons::time_util;
|
|
use wicked_waifus_data::{role_info_data, BasePropertyData};
|
|
use wicked_waifus_protocol_internal::{RoleData, RoleStats};
|
|
use crate::logic::player::Element;
|
|
|
|
const MAIN_CHARACTER_MALE_SPECTRO_ID: i32 = 1501;
|
|
const MAIN_CHARACTER_FEMALE_SPECTRO_ID: i32 = 1502;
|
|
const MAIN_CHARACTER_MALE_HAVOC_ID: i32 = 1605;
|
|
const MAIN_CHARACTER_FEMALE_HAVOC_ID: i32 = 1604;
|
|
const MAIN_CHARACTER_MALE_AERO_ID: i32 = 1406;
|
|
const MAIN_CHARACTER_FEMALE_AERO_ID: i32 = 1408;
|
|
|
|
const MAIN_CHARACTER_ARRAY: &[i32] = &[
|
|
MAIN_CHARACTER_MALE_SPECTRO_ID,
|
|
MAIN_CHARACTER_FEMALE_SPECTRO_ID,
|
|
MAIN_CHARACTER_MALE_HAVOC_ID,
|
|
MAIN_CHARACTER_FEMALE_HAVOC_ID,
|
|
MAIN_CHARACTER_MALE_AERO_ID,
|
|
MAIN_CHARACTER_FEMALE_AERO_ID,
|
|
];
|
|
|
|
mod formation;
|
|
pub struct Role {
|
|
pub role_id: i32,
|
|
pub name: String,
|
|
pub level: i32,
|
|
pub exp: i32,
|
|
pub breakthrough: i32,
|
|
pub skill_map: HashMap<i32, i32>,
|
|
pub star: i32,
|
|
pub favor: i32,
|
|
pub create_time: u32,
|
|
pub equip_weapon: i32,
|
|
pub skin_id: i32,
|
|
pub resonant_chain_group_index: i32,
|
|
pub hp: i32,
|
|
pub energy: i32,
|
|
pub special_energy_1: i32,
|
|
pub special_energy_2: i32,
|
|
pub special_energy_3: i32,
|
|
pub special_energy_4: i32,
|
|
pub element_energy: i32,
|
|
pub favor_level: i32,
|
|
pub favor_exp: i32,
|
|
}
|
|
|
|
impl Role {
|
|
#[inline(always)]
|
|
pub fn get_all_roles_except_mc() -> Vec<i32> {
|
|
role_info_data::iter()
|
|
.filter(|role| (role.role_type == 1 && !MAIN_CHARACTER_ARRAY.contains(&role.id)) || role.id == 5101)
|
|
.map(|role| role.id)
|
|
.collect()
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn get_mc_id_based_on_sex(sex: i32, current_element: Element) -> i32 {
|
|
match current_element {
|
|
Element::Glacio => unreachable!(),
|
|
Element::Fusion => unreachable!(),
|
|
Element::Electro => unreachable!(),
|
|
Element::Aero => match sex {
|
|
0 => MAIN_CHARACTER_MALE_AERO_ID,
|
|
1 => MAIN_CHARACTER_FEMALE_AERO_ID,
|
|
_ => unreachable!(),
|
|
}
|
|
Element::Spectro => match sex {
|
|
0 => MAIN_CHARACTER_FEMALE_SPECTRO_ID,
|
|
1 => MAIN_CHARACTER_MALE_SPECTRO_ID,
|
|
_ => unreachable!(),
|
|
}
|
|
Element::Havoc => match sex {
|
|
0 => MAIN_CHARACTER_MALE_HAVOC_ID,
|
|
1 => MAIN_CHARACTER_FEMALE_HAVOC_ID,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn get_mc_based_on_sex(sex: i32, current_element: Element) -> Self {
|
|
Role::new(Self::get_mc_id_based_on_sex(sex, current_element))
|
|
}
|
|
|
|
pub fn get_mc_unlock_variations(unlocked_elements: Vec<Element>) -> Vec<i32> {
|
|
let mut variations: Vec<i32> = Vec::new();
|
|
for element in unlocked_elements {
|
|
match element {
|
|
Element::Glacio => {},
|
|
Element::Fusion => {},
|
|
Element::Electro => {},
|
|
Element::Aero => {
|
|
variations.push(MAIN_CHARACTER_MALE_AERO_ID);
|
|
variations.push(MAIN_CHARACTER_FEMALE_AERO_ID);
|
|
},
|
|
Element::Spectro => {
|
|
variations.push(MAIN_CHARACTER_MALE_SPECTRO_ID);
|
|
variations.push(MAIN_CHARACTER_FEMALE_SPECTRO_ID);
|
|
},
|
|
Element::Havoc => {
|
|
variations.push(MAIN_CHARACTER_MALE_HAVOC_ID);
|
|
variations.push(MAIN_CHARACTER_FEMALE_HAVOC_ID);
|
|
},
|
|
}
|
|
}
|
|
variations
|
|
}
|
|
|
|
pub fn new(role_id: i32) -> Self {
|
|
let data = role_info_data::iter().find(|d| d.id == role_id).unwrap();
|
|
|
|
let default_unlocks = &config::get_config().default_unlocks;
|
|
let (level, breakthrough) = if default_unlocks.unlock_all_roles_max_level {
|
|
(data.max_level, 6)
|
|
} else {
|
|
(1, 0)
|
|
};
|
|
let resonant_chain_group_index = if default_unlocks.unlock_all_roles_all_sequences {
|
|
6
|
|
} else {
|
|
0
|
|
};
|
|
let base_stats = &get_role_props_by_level(role_id, level, breakthrough);
|
|
Self {
|
|
role_id,
|
|
name: String::with_capacity(0),
|
|
level,
|
|
exp: 0, // TODO: Compute based on level??
|
|
breakthrough,
|
|
skill_map: HashMap::new(), // TODO!
|
|
star: 0,
|
|
favor: 0,
|
|
create_time: time_util::unix_timestamp() as u32,
|
|
equip_weapon: data.init_weapon_item_id,
|
|
skin_id: data.skin_id,
|
|
resonant_chain_group_index,
|
|
hp: base_stats.life,
|
|
energy: base_stats.energy,
|
|
special_energy_1: base_stats.special_energy_1,
|
|
special_energy_2: base_stats.special_energy_2,
|
|
special_energy_3: base_stats.special_energy_3,
|
|
special_energy_4: base_stats.special_energy_4,
|
|
element_energy: base_stats.element_energy,
|
|
favor_level: 0,
|
|
favor_exp: 0,
|
|
}
|
|
}
|
|
|
|
pub fn get_base_properties(&self) -> BasePropertyData {
|
|
// Overwrite dynamic attributes with stores values
|
|
let mut base_stats = get_role_props_by_level(self.role_id, self.level, self.breakthrough);
|
|
// TODO: Integrity check, value has to be between 0 and max
|
|
base_stats.life = self.hp;
|
|
base_stats.energy = self.energy;
|
|
base_stats.special_energy_1 = self.special_energy_1;
|
|
base_stats.special_energy_2 = self.special_energy_2;
|
|
base_stats.special_energy_3 = self.special_energy_3;
|
|
base_stats.special_energy_4 = self.special_energy_4;
|
|
base_stats.element_energy = self.element_energy;
|
|
base_stats
|
|
}
|
|
|
|
pub fn to_protobuf(&self) -> RoleInfo {
|
|
let base_prop: HashMap<i32, i32> = load_key_value(&self.get_base_properties());
|
|
RoleInfo {
|
|
role_id: self.role_id,
|
|
name: self.name.clone(),
|
|
level: self.level,
|
|
exp: self.exp,
|
|
breakthrough: self.breakthrough,
|
|
create_time: self.create_time,
|
|
skills: self
|
|
.skill_map
|
|
.iter()
|
|
.map(|(k, v)| ArrayIntInt { key: *k, value: *v })
|
|
.collect(),
|
|
base_prop: base_prop
|
|
.iter()
|
|
.map(|(&k, &v)| ArrayIntInt { key: k, value: v })
|
|
.collect(),
|
|
skin_id: self.skin_id,
|
|
resonant_chain_group_index: self.resonant_chain_group_index,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
pub fn load_from_save(data: RoleData) -> (i32, Self) {
|
|
(
|
|
data.role_id,
|
|
Self {
|
|
role_id: data.role_id,
|
|
name: data.name,
|
|
level: data.level,
|
|
exp: data.exp,
|
|
breakthrough: data.breakthrough,
|
|
skill_map: data.skill_map,
|
|
star: data.star,
|
|
favor: data.favor,
|
|
create_time: data.create_time,
|
|
equip_weapon: data.equip_weapon,
|
|
skin_id: data.skin_id,
|
|
resonant_chain_group_index: data.resonant_chain_group_index,
|
|
hp: data.stats.unwrap().hp,
|
|
energy: data.stats.unwrap().energy,
|
|
special_energy_1: data.stats.unwrap().special_energy_1,
|
|
special_energy_2: data.stats.unwrap().special_energy_2,
|
|
special_energy_3: data.stats.unwrap().special_energy_3,
|
|
special_energy_4: data.stats.unwrap().special_energy_4,
|
|
element_energy: data.stats.unwrap().element_energy,
|
|
favor_level: data.favor_level,
|
|
favor_exp: data.favor_exp,
|
|
},
|
|
)
|
|
}
|
|
|
|
pub fn build_save_data(&self) -> RoleData {
|
|
RoleData {
|
|
role_id: self.role_id,
|
|
name: self.name.clone(),
|
|
level: self.level,
|
|
exp: self.exp,
|
|
breakthrough: self.breakthrough,
|
|
skill_map: self.skill_map.clone(),
|
|
// phantom_map: Default::default(),
|
|
star: self.star,
|
|
favor: self.favor,
|
|
create_time: self.create_time,
|
|
// cur_model: 0,
|
|
// models: vec![],
|
|
// skill_node_state: vec![],
|
|
resonant_chain_group_index: self.resonant_chain_group_index,
|
|
equip_weapon: self.equip_weapon,
|
|
skin_id: self.skin_id,
|
|
stats: Some(RoleStats {
|
|
hp: self.hp,
|
|
energy: self.energy,
|
|
special_energy_1: self.special_energy_1,
|
|
special_energy_2: self.special_energy_2,
|
|
special_energy_3: self.special_energy_3,
|
|
special_energy_4: self.special_energy_4,
|
|
element_energy: self.element_energy,
|
|
}),
|
|
favor_level: self.favor_level,
|
|
favor_exp: self.favor_exp,
|
|
..Default::default()
|
|
}
|
|
}
|
|
}
|