XilonenImpact/gameserver/src/player/avatar/avatar.rs
2024-08-30 01:48:02 +03:00

439 lines
13 KiB
Rust

use std::{
cell::RefCell,
rc::{Rc, Weak},
};
use data::{math_def::Vector3, prop_type::PROP_LEVEL, FightPropType};
use proto::{
avatar_bin::{self, Detail},
AbilitySyncStateInfo, AnimatorParameterValueInfoPair, AvatarBin, AvatarExcelInfo, Cjnoehnhdgl,
EntityAuthorityInfo, EntityClientData, FightPropPair, Jgkjmgmfmpo, MotionInfo, PropPair,
PropValue, ProtEntityType, SceneAvatarInfo, SceneEntityInfo,
};
use crate::{
ability::AbilityComp,
creature::{property::PropValueMap, Creature, FightPropComp, LifeState},
entity::Entity,
item::EquipComp,
player::{item::Item, Player},
};
use super::{FormalAvatar, MirrorAvatar, TrialAvatar};
pub enum Avatar {
Formal(FormalAvatar),
Trial(TrialAvatar),
Mirror(MirrorAvatar),
}
impl Avatar {
pub fn base_avatar(&self) -> &BaseAvatar {
match self {
Self::Formal(a) => &a.base,
Self::Trial(a) => &a.base,
Self::Mirror(a) => &a.base,
}
}
pub fn base_avatar_mut(&mut self) -> &mut BaseAvatar {
match self {
Self::Formal(a) => &mut a.base,
Self::Trial(a) => &mut a.base,
Self::Mirror(a) => &mut a.base,
}
}
pub fn on_add_to_scene_team(&mut self) {
self.base_avatar_mut().on_add_to_scene_team();
}
pub fn on_remove_from_scene_team(&mut self) {
self.base_avatar_mut().on_remove_from_scene_team();
}
pub fn init(&mut self) {
let base = self.base_avatar_mut();
base.skill_depot_id = data::iter_avatar_data()
.find(|a| a.id == base.avatar_id)
.unwrap()
.skill_depot_id;
let player = self.base_avatar().player().unwrap();
let item_comp = player.player_item_comp.borrow();
let equip_item_vec = self
.base_avatar()
.equip_comp
.equip_guid_vec
.iter()
.map(|guid| item_comp.pack_store.items.get(guid).unwrap())
.collect::<Vec<_>>();
let mut equip_vec = Vec::new();
for item in equip_item_vec.iter() {
match item {
// TODO: Item::Equip -> Weapon, Relic
Item::Weapon(weapon) => equip_vec.push(weapon),
}
}
self.base_avatar_mut().equip_comp.init(equip_vec);
}
pub fn set_last_valid_position(&mut self, pos: Vector3) {
self.base_avatar_mut().last_valid_pos = pos;
}
pub fn set_last_valid_rotation(&mut self, rot: Vector3) {
self.base_avatar_mut().last_valid_rot = rot;
}
pub fn to_client(&self) -> proto::AvatarInfo {
let mut info = match self {
Self::Formal(avatar) => avatar.to_client(),
Self::Trial(avatar) => avatar.to_client(),
Self::Mirror(avatar) => avatar.to_client(),
};
info.avatar_type = self.get_avatar_type();
info
}
pub fn to_client_scene_entity(&self, scene_entity_info: &mut SceneEntityInfo) {
Entity::to_client(self, scene_entity_info);
}
pub fn to_client_avatar_entity(&self, scene_avatar_info: &mut SceneAvatarInfo) {
let player = self.get_owner_player().unwrap();
scene_avatar_info.uid = player.uid;
scene_avatar_info.peer_id = player.peer_id.get();
scene_avatar_info.avatar_id = self.base_avatar().avatar_id;
scene_avatar_info.guid = self.base_avatar().guid;
scene_avatar_info.equip_id_list = {
let item_comp = player.player_item_comp.borrow();
self.base_avatar()
.equip_comp
.equip_guid_vec
.iter()
.map(|guid| {
item_comp
.pack_store
.items
.get(guid)
.map(|item| item.item_id())
})
.flatten()
.collect()
};
scene_avatar_info.skill_depot_id = self.base_avatar().skill_depot_id;
scene_avatar_info.born_time = self.base_avatar().born_time;
scene_avatar_info.team_resonance_list = vec![10301]; // TODO!
scene_avatar_info.wearing_flycloak_id = self.base_avatar().flycloak_id;
scene_avatar_info.costume_id = 0; // TODO!
scene_avatar_info.excel_info = Some(AvatarExcelInfo::default());
scene_avatar_info.weapon = self
.base_avatar()
.equip_comp
.weapon_gadget
.as_ref()
.map(|gadget| gadget.borrow().to_client());
}
pub fn from_bin(bin: AvatarBin) -> Self {
let level = bin.level;
let cur_hp = bin.cur_hp;
let mut avatar = match bin.detail.clone().unwrap() {
Detail::FormalAvatar(detail) => Self::Formal(FormalAvatar::from_bin(bin, detail)),
Detail::TrialAvatar(detail) => Self::Trial(TrialAvatar::from_bin(bin, detail)),
Detail::MirrorAvatar(detail) => Self::Mirror(MirrorAvatar::from_bin(bin, detail)),
};
avatar.set_level(level);
avatar.set_cur_hp(cur_hp);
// TODO: cur_elem_energy
avatar
}
pub fn to_bin(&self) -> AvatarBin {
match self {
Self::Formal(a) => a.to_bin(),
Self::Trial(a) => a.to_bin(),
Self::Mirror(a) => a.to_bin(),
}
}
pub fn get_avatar_type(&self) -> u32 {
match self {
Self::Formal(_) => 1,
Self::Trial(_) => 2,
Self::Mirror(_) => 3,
}
}
}
#[derive(Default)]
pub struct BaseAvatar {
player: Weak<Player>,
pub avatar_id: u32,
pub guid: u64,
pub level: u32,
pub life_state: LifeState,
pub promote_level: u32,
pub skill_depot_id: u32,
// skill_map, buff_map, depot_map
pub satiation_val: f32,
pub satiation_penalty_time: f32,
pub flycloak_id: u32,
pub born_time: u32,
// Components
pub fight_prop_comp: FightPropComp,
pub equip_comp: EquipComp,
pub ability_comp: Rc<RefCell<AbilityComp>>,
// Entity
pub entity_id: u32,
pub pos: Vector3,
pub rot: Vector3,
pub last_valid_pos: Vector3,
pub last_valid_rot: Vector3,
}
impl BaseAvatar {
pub fn to_client(&self, prop_map: PropValueMap) -> proto::AvatarInfo {
let mut info = proto::AvatarInfo {
avatar_id: self.avatar_id,
guid: self.guid,
prop_map,
life_state: self.life_state as u32,
skill_depot_id: self.skill_depot_id,
wearing_flycloak_id: self.flycloak_id,
born_time: self.born_time,
fetter_info: Some(proto::AvatarFetterInfo {
exp_level: 1,
..Default::default()
}),
fight_prop_map: self.fight_prop_comp.get_fight_prop_value_map(),
..Default::default()
};
self.equip_comp.to_client(&mut info);
info
}
pub fn from_bin(bin: AvatarBin) -> Self {
let mut fight_prop_comp = FightPropComp::default();
fight_prop_comp.set_cur_hp(bin.cur_hp);
let equip_comp = EquipComp::from_bin(&bin);
Self {
player: Weak::new(),
avatar_id: bin.avatar_id,
guid: bin.guid,
level: bin.level,
life_state: bin.life_state.into(),
promote_level: bin.promote_level,
skill_depot_id: bin.skill_depot_id,
satiation_val: bin.satiation_val,
satiation_penalty_time: bin.satiation_penalty_time,
flycloak_id: bin.flycloak_id,
born_time: bin.born_time,
fight_prop_comp,
equip_comp,
..Default::default()
}
}
pub fn to_bin(&self, detail: avatar_bin::Detail) -> AvatarBin {
let mut bin = AvatarBin {
detail: Some(detail),
avatar_id: self.avatar_id,
guid: self.guid,
level: self.level,
life_state: self.life_state as u32,
cur_hp: self.fight_prop_comp.get_prop_value(FightPropType::CurHp),
cur_elem_energy: 0.0, // todo
promote_level: self.promote_level,
skill_depot_id: self.skill_depot_id,
satiation_val: self.satiation_val,
satiation_penalty_time: self.satiation_penalty_time,
flycloak_id: self.flycloak_id,
born_time: self.born_time,
..Default::default()
};
self.equip_comp.to_bin(&mut bin);
bin
}
pub fn on_add_to_scene_team(&mut self) {
// TODO
}
pub fn on_remove_from_scene_team(&mut self) {
// TODO
}
pub fn set_player(&mut self, player: Rc<Player>) {
self.player = Rc::downgrade(&player)
}
fn player(&self) -> Option<Rc<Player>> {
self.player.upgrade()
}
}
impl Creature for Avatar {
fn set_level(&mut self, level: u32) {
self.base_avatar_mut().level = level;
self.assign_prop();
}
fn assign_prop(&mut self) {
// TODO: level-based calculation
let id = self.base_avatar().avatar_id;
let config = data::iter_avatar_data().find(|a| a.id == id).unwrap();
let base = self.base_avatar_mut();
let fpc = &mut base.fight_prop_comp;
fpc.fight_cal_prop_map
.insert(FightPropType::BaseHp, config.hp_base);
fpc.fight_cal_prop_map
.insert(FightPropType::MaxHp, config.hp_base);
fpc.fight_cal_prop_map
.insert(FightPropType::BaseAttack, config.defense_base);
fpc.fight_cal_prop_map
.insert(FightPropType::BaseDefense, config.defense_base);
}
fn set_cur_hp_full(&mut self) {
let base = self.base_avatar_mut();
let fpc = &mut base.fight_prop_comp;
fpc.set_cur_hp(fpc.get_prop_value(FightPropType::MaxHp));
}
fn get_life_state(&self) -> LifeState {
self.base_avatar().life_state
}
fn set_life_state(&mut self, state: LifeState) {
self.base_avatar_mut().life_state = state;
}
fn get_cur_hp(&self) -> f32 {
let base = self.base_avatar();
base.fight_prop_comp.get_prop_value(FightPropType::CurHp)
}
fn set_cur_hp(&mut self, hp: f32) {
let base = self.base_avatar_mut();
let fpc = &mut base.fight_prop_comp;
fpc.set_cur_hp(hp);
}
}
impl Entity for Avatar {
fn get_entity_type(&self) -> ProtEntityType {
ProtEntityType::ProtEntityAvatar
}
fn get_group_id(&self) -> u32 {
0
}
fn entity_id(&self) -> u32 {
self.base_avatar().entity_id
}
fn set_entity_id(&mut self, id: u32) {
self.base_avatar_mut().entity_id = id
}
fn position(&self) -> &data::math_def::Vector3 {
&self.base_avatar().pos
}
fn rotation(&self) -> &data::math_def::Vector3 {
&self.base_avatar().rot
}
fn get_owner_player(&self) -> Option<Rc<Player>> {
self.base_avatar().player()
}
fn is_on_scene(&self) -> bool {
self.entity_id() != 0
}
fn set_position(&mut self, pos: data::math_def::Vector3) {
self.base_avatar_mut().pos = pos;
}
fn set_rotation(&mut self, rot: data::math_def::Vector3) {
self.base_avatar_mut().rot = rot;
}
fn to_client(&self, scene_entity_info: &mut SceneEntityInfo) {
scene_entity_info.entity_id = self.entity_id();
scene_entity_info.entity_type = self.get_entity_type().into();
scene_entity_info.life_state = self.get_life_state() as u32;
scene_entity_info.motion_info = Some(MotionInfo {
pos: Some(self.position().to_client()),
rot: Some(self.rotation().to_client()),
speed: Some(proto::Vector::default()),
..Default::default()
});
// TODO: macro for this stuff
scene_entity_info.prop_list = vec![PropPair {
r#type: PROP_LEVEL,
prop_value: Some(PropValue {
r#type: PROP_LEVEL,
val: self.base_avatar().level as i64,
value: Some(proto::prop_value::Value::Ival(
self.base_avatar().level as i64,
)),
}),
}];
scene_entity_info.fight_prop_list = self
.base_avatar()
.fight_prop_comp
.get_fight_prop_value_map()
.iter()
.map(|(ty, val)| FightPropPair {
prop_type: *ty,
prop_value: *val,
})
.collect();
let mut scene_avatar_info = SceneAvatarInfo::default();
self.to_client_avatar_entity(&mut scene_avatar_info);
scene_entity_info.entity =
Some(proto::scene_entity_info::Entity::Avatar(scene_avatar_info));
scene_entity_info.animator_para_list = vec![AnimatorParameterValueInfoPair {
animator_para: Some(Cjnoehnhdgl::default()),
name_id: 0,
}];
scene_entity_info.entity_client_data = Some(EntityClientData::default());
scene_entity_info.entity_authority_info = Some(EntityAuthorityInfo {
ability_info: Some(AbilitySyncStateInfo::default()),
born_pos: Some(proto::Vector::default()),
client_extra_info: Some(Jgkjmgmfmpo {
hekhfgcpgja: Some(proto::Vector::default()),
}),
..Default::default()
});
}
}