Implement avatar trace effect change (Echo)

This commit is contained in:
xeon 2024-11-04 01:04:18 +03:00
parent 4fb5d000fd
commit 8dde0c8705
17 changed files with 352 additions and 45 deletions

View file

@ -0,0 +1 @@
Ù<7F> ƒ­âÙ<> ,Eff_Avatar_Lady_Sword_Qin_CharMaster_00_Blow-Eff_Avatar_Lady_Sword_Qin_CharMaster_00_WorldøœÖÞîøœÅÚ<7F> £­âÚ<> -Eff_Avatar_Loli_Sword_Qiqi_CharMaster_00_Blow.Eff_Avatar_Loli_Sword_Qiqi_CharMaster_00_World€Îȹ<>ò™ Û<7F> ›­âÛ<> 5Eff_Avatar_Lady_Catalyst_Ningguang_CharMaster_00_Blow6Eff_Avatar_Lady_Catalyst_Ningguang_CharMaster_00_World˜Ä™«ÖÞͶ Ü<7F> ½­âÜ<> /Eff_Avatar_Girl_Sword_Momoka_CharMaster_00_Blow0Eff_Avatar_Girl_Sword_Momoka_CharMaster_00_WorldÐÚ¹·ŽøƒÄÝ<7F> <0A>­âÝ<> 1Eff_Avatar_Male_Claymore_Diluc_CharMaster_00_Blow2Eff_Avatar_Male_Claymore_Diluc_CharMaster_00_WorldÐÆÈÆ Þè²ÔÞ<7F> ž­âÞ<> /Eff_Avatar_Male_Pole_Zhongli_CharMaster_00_Blow0Eff_Avatar_Male_Pole_Zhongli_CharMaster_00_World¨åø¼öèÎË ß<7F> ª­âß<> /Eff_Avatar_Girl_Sword_Keqing_CharMaster_00_Blow0Eff_Avatar_Girl_Sword_Keqing_CharMaster_00_Worldˆ´Ã…¦ÚÑó

View file

@ -117,6 +117,8 @@ pub fn sync_avatar_data(players: Res<Players>, out: Res<MessageOutput>) {
as u32, as u32,
avatar_type: 1, // TODO! avatar_type: 1, // TODO!
wearing_flycloak_id: a.wearing_flycloak_id, wearing_flycloak_id: a.wearing_flycloak_id,
costume_id: a.costume_id,
trace_effect_id: a.trace_effect_id,
fetter_info: Some(AvatarFetterInfo::default()), fetter_info: Some(AvatarFetterInfo::default()),
skill_level_map: a.skill_level_map.clone(), skill_level_map: a.skill_level_map.clone(),
inherent_proud_skill_list: a.inherent_proud_skill_list.clone(), inherent_proud_skill_list: a.inherent_proud_skill_list.clone(),
@ -167,6 +169,12 @@ pub fn sync_avatar_data(players: Res<Players>, out: Res<MessageOutput>) {
.iter() .iter()
.copied() .copied()
.collect(), .collect(),
owned_trace_effect_list: player_info
.avatar_module
.owned_trace_effect_set
.iter()
.copied()
.collect(),
..Default::default() ..Default::default()
}, },
); );

View file

@ -4,7 +4,8 @@ use common::time_util;
use sakura_data::excel::{ use sakura_data::excel::{
avatar_costume_excel_config_collection, avatar_excel_config_collection, avatar_costume_excel_config_collection, avatar_excel_config_collection,
avatar_flycloak_excel_config_collection, avatar_skill_depot_excel_config_collection, avatar_flycloak_excel_config_collection, avatar_skill_depot_excel_config_collection,
weapon_excel_config_collection, AvatarExcelConfig, AvatarUseType, avatar_trace_effect_excel_config_collection, weapon_excel_config_collection, AvatarExcelConfig,
AvatarUseType,
}; };
use sakura_persistence::player_information::*; use sakura_persistence::player_information::*;
@ -32,6 +33,9 @@ pub fn create_default_player_information(uid: u32, nick_name: String) -> PlayerI
.filter(|c| !c.is_default) .filter(|c| !c.is_default)
.map(|c| c.skin_id) .map(|c| c.skin_id)
.collect(), .collect(),
owned_trace_effect_set: avatar_trace_effect_excel_config_collection::iter()
.map(|c| c.trace_effect_id)
.collect(),
}, },
item_map: HashMap::new(), item_map: HashMap::new(),
world_position: PlayerPositionInformation { world_position: PlayerPositionInformation {
@ -134,6 +138,7 @@ fn add_avatar_and_weapon(player: &mut PlayerInformation, avatar: &AvatarExcelCon
inherent_proud_skill_list, inherent_proud_skill_list,
wearing_flycloak_id: DEFAULT_FLYCLOAK_ID, wearing_flycloak_id: DEFAULT_FLYCLOAK_ID,
costume_id: 0, costume_id: 0,
trace_effect_id: 0,
}, },
); );

View file

@ -1,11 +1,14 @@
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use sakura_data::excel::avatar_costume_excel_config_collection; use sakura_data::excel::{
use sakura_entity::avatar::AvatarCostumeChangeEvent; avatar_costume_excel_config_collection, avatar_trace_effect_excel_config_collection,
};
use sakura_entity::avatar::{AvatarAppearanceChange, AvatarAppearanceChangeEvent};
use sakura_message::{event::ClientMessageEvent, output::MessageOutput}; use sakura_message::{event::ClientMessageEvent, output::MessageOutput};
use sakura_persistence::{player_information::PlayerInformation, Players}; use sakura_persistence::{player_information::PlayerInformation, Players};
use sakura_proto::{ use sakura_proto::{
AvatarChangeCostumeReq, AvatarChangeCostumeRsp, AvatarFlycloakChangeNotify, AvatarChangeCostumeReq, AvatarChangeCostumeRsp, AvatarChangeTraceEffectReq,
AvatarWearFlycloakReq, AvatarWearFlycloakRsp, Retcode, AvatarChangeTraceEffectRsp, AvatarFlycloakChangeNotify, AvatarWearFlycloakReq,
AvatarWearFlycloakRsp, Retcode,
}; };
use tracing::{debug, instrument}; use tracing::{debug, instrument};
@ -14,7 +17,7 @@ pub fn handle_appearance_change_request(
mut events: EventReader<ClientMessageEvent>, mut events: EventReader<ClientMessageEvent>,
mut players: ResMut<Players>, mut players: ResMut<Players>,
message_output: Res<MessageOutput>, message_output: Res<MessageOutput>,
mut costume_change_events: EventWriter<AvatarCostumeChangeEvent>, mut change_events: EventWriter<AvatarAppearanceChangeEvent>,
) { ) {
for message in events.read() { for message in events.read() {
if let Some(request) = message.decode::<AvatarWearFlycloakReq>() { if let Some(request) = message.decode::<AvatarWearFlycloakReq>() {
@ -31,7 +34,16 @@ pub fn handle_appearance_change_request(
let mut rsp = AvatarChangeCostumeRsp::default(); let mut rsp = AvatarChangeCostumeRsp::default();
if let Some(change_event) = change_costume(player, request, &mut rsp) { if let Some(change_event) = change_costume(player, request, &mut rsp) {
costume_change_events.send(change_event); change_events.send(change_event);
}
message_output.send(message.sender_uid(), rsp);
} else if let Some(request) = message.decode::<AvatarChangeTraceEffectReq>() {
let player = players.get_mut(message.sender_uid());
let mut rsp = AvatarChangeTraceEffectRsp::default();
if let Some(change_event) = change_trace_effect(player, request, &mut rsp) {
change_events.send(change_event);
} }
message_output.send(message.sender_uid(), rsp); message_output.send(message.sender_uid(), rsp);
@ -85,7 +97,7 @@ fn change_costume(
player: &mut PlayerInformation, player: &mut PlayerInformation,
request: AvatarChangeCostumeReq, request: AvatarChangeCostumeReq,
response: &mut AvatarChangeCostumeRsp, response: &mut AvatarChangeCostumeRsp,
) -> Option<AvatarCostumeChangeEvent> { ) -> Option<AvatarAppearanceChangeEvent> {
response.retcode = Retcode::RetFail.into(); response.retcode = Retcode::RetFail.into();
let config = (request.costume_id != 0) let config = (request.costume_id != 0)
@ -140,9 +152,83 @@ fn change_costume(
avatar.avatar_id, request.costume_id avatar.avatar_id, request.costume_id
); );
Some(AvatarCostumeChangeEvent( Some(AvatarAppearanceChangeEvent {
player.uid, player_uid: player.uid,
request.avatar_guid, avatar_guid: request.avatar_guid,
request.costume_id, change: AvatarAppearanceChange::Costume(request.costume_id),
)) })
}
#[instrument(skip(player, response))]
fn change_trace_effect(
player: &mut PlayerInformation,
request: AvatarChangeTraceEffectReq,
response: &mut AvatarChangeTraceEffectRsp,
) -> Option<AvatarAppearanceChangeEvent> {
response.retcode = Retcode::RetFail.into();
let config = (request.trace_effect_id != 0)
.then(|| {
avatar_trace_effect_excel_config_collection::iter()
.find(|c| c.trace_effect_id == request.trace_effect_id)
})
.flatten();
if request.trace_effect_id != 0 && config.is_none() {
debug!(
"trace_effect_id {} config doesn't exist",
request.trace_effect_id
);
return None;
};
if !player
.avatar_module
.owned_trace_effect_set
.contains(&request.trace_effect_id)
&& config.is_some()
{
debug!(
"trace effect is not unlocked, id: {}",
request.trace_effect_id
);
response.retcode = Retcode::RetNotHasTraceEffect.into();
return None;
}
let Some(avatar) = player
.avatar_module
.avatar_map
.get_mut(&request.avatar_guid)
else {
debug!("avatar guid {} doesn't exist", request.avatar_guid);
return None;
};
if let Some(config) = config {
if config.avatar_id != avatar.avatar_id {
debug!(
"avatar trace effect mismatch, config: {}, requested: {}",
config.avatar_id, avatar.avatar_id
);
response.retcode = Retcode::RetTraceEffectAvatarError.into();
return None;
}
}
response.avatar_guid = request.avatar_guid;
response.trace_effect_id = request.trace_effect_id;
response.retcode = Retcode::RetSucc.into();
avatar.trace_effect_id = request.trace_effect_id;
debug!(
"change trace effect for avatar {} to {}",
avatar.avatar_id, request.trace_effect_id
);
Some(AvatarAppearanceChangeEvent {
player_uid: player.uid,
avatar_guid: request.avatar_guid,
change: AvatarAppearanceChange::TraceEffect(request.trace_effect_id),
})
} }

View file

@ -0,0 +1,12 @@
use sakura_data_derive::FromBinary;
#[derive(Debug, FromBinary)]
pub struct AvatarTraceEffectExcelConfig {
pub trace_effect_id: u32,
pub avatar_id: u32,
pub item_id: u32,
pub unk_1: String,
pub unk_2: Vec<String>,
pub name_text_map_hash: u32,
pub desc_text_map_hash: u32,
}

View file

@ -4,6 +4,7 @@ mod avatar_excel_config;
mod avatar_flycloak_excel_config; mod avatar_flycloak_excel_config;
mod avatar_promote_excel_config; mod avatar_promote_excel_config;
mod avatar_skill_depot_excel_config; mod avatar_skill_depot_excel_config;
mod avatar_trace_effect_excel_config;
mod map_area_config; mod map_area_config;
mod monster_curve_excel_config; mod monster_curve_excel_config;
mod monster_excel_config; mod monster_excel_config;
@ -18,6 +19,7 @@ pub use avatar_excel_config::*;
pub use avatar_flycloak_excel_config::*; pub use avatar_flycloak_excel_config::*;
pub use avatar_promote_excel_config::*; pub use avatar_promote_excel_config::*;
pub use avatar_skill_depot_excel_config::*; pub use avatar_skill_depot_excel_config::*;
pub use avatar_trace_effect_excel_config::*;
pub use map_area_config::*; pub use map_area_config::*;
pub use monster_curve_excel_config::*; pub use monster_curve_excel_config::*;
pub use monster_excel_config::*; pub use monster_excel_config::*;
@ -68,6 +70,7 @@ macro_rules! excel_loader {
excel_loader! { excel_loader! {
AvatarExcelConfig; AvatarExcelConfig;
AvatarCostumeExcelConfig; AvatarCostumeExcelConfig;
AvatarTraceEffectExcelConfig;
AvatarFlycloakExcelConfig; AvatarFlycloakExcelConfig;
AvatarSkillDepotExcelConfig; AvatarSkillDepotExcelConfig;
AvatarCurveExcelConfig; AvatarCurveExcelConfig;

View file

@ -79,6 +79,7 @@ mod tests {
excel_test!( excel_test!(
AvatarExcelConfig, AvatarExcelConfig,
AvatarTraceEffectExcelConfig,
AvatarCostumeExcelConfig, AvatarCostumeExcelConfig,
AvatarFlycloakExcelConfig, AvatarFlycloakExcelConfig,
AvatarSkillDepotExcelConfig, AvatarSkillDepotExcelConfig,

View file

@ -6,7 +6,7 @@ use sakura_persistence::{
player_information::{AvatarInformation, ItemInformation}, player_information::{AvatarInformation, ItemInformation},
Players, Players,
}; };
use sakura_proto::{AvatarChangeCostumeNotify, SceneEntityInfo}; use sakura_proto::{AvatarChangeCostumeNotify, AvatarChangeTraceEffectNotify, SceneEntityInfo};
use crate::{ use crate::{
int_prop_pair, int_prop_pair,
@ -25,6 +25,7 @@ pub struct Equipment {
pub struct AvatarAppearance { pub struct AvatarAppearance {
pub flycloak_id: u32, pub flycloak_id: u32,
pub costume_id: u32, pub costume_id: u32,
pub trace_effect_id: u32,
} }
#[derive(Event)] #[derive(Event)]
@ -34,8 +35,17 @@ pub struct AvatarEquipChangeEvent {
pub weapon_guid: u64, pub weapon_guid: u64,
} }
pub enum AvatarAppearanceChange {
Costume(u32),
TraceEffect(u32),
}
#[derive(Event)] #[derive(Event)]
pub struct AvatarCostumeChangeEvent(pub u32, pub u64, pub u32); pub struct AvatarAppearanceChangeEvent {
pub player_uid: u32,
pub avatar_guid: u64,
pub change: AvatarAppearanceChange,
}
#[derive(Component)] #[derive(Component)]
pub struct AvatarID(pub u32); pub struct AvatarID(pub u32);
@ -106,47 +116,71 @@ pub struct AvatarQueryReadOnly {
} }
pub fn update_avatar_appearance( pub fn update_avatar_appearance(
mut events: EventReader<AvatarCostumeChangeEvent>, mut events: EventReader<AvatarAppearanceChangeEvent>,
mut avatars: Query<(&Guid, &mut AvatarAppearance)>, mut avatars: Query<(&Guid, &mut AvatarAppearance)>,
) { ) {
for AvatarCostumeChangeEvent(_, guid, costume_id) in events.read() { for event in events.read() {
if let Some((_, mut appearance)) = avatars.iter_mut().find(|(g, _)| g.0 == *guid) { if let Some((_, mut appearance)) =
appearance.costume_id = *costume_id; avatars.iter_mut().find(|(g, _)| g.0 == event.avatar_guid)
{
match event.change {
AvatarAppearanceChange::Costume(costume_id) => {
appearance.costume_id = costume_id;
}
AvatarAppearanceChange::TraceEffect(trace_effect_id) => {
appearance.trace_effect_id = trace_effect_id;
}
}
} }
} }
} }
pub fn notify_avatar_costume_change( pub fn notify_avatar_appearance_change(
mut events: EventReader<AvatarCostumeChangeEvent>, mut events: EventReader<AvatarAppearanceChangeEvent>,
avatars: Query<AvatarQueryReadOnly>, avatars: Query<AvatarQueryReadOnly>,
weapons: Query<WeaponQueryReadOnly>, weapons: Query<WeaponQueryReadOnly>,
message_output: Res<MessageOutput>, message_output: Res<MessageOutput>,
players: Res<Players>, players: Res<Players>,
) { ) {
for AvatarCostumeChangeEvent(player_uid, guid, _) in events.read() { for event in events.read() {
if let Some(avatar_data) = avatars if let Some(avatar_data) = avatars
.iter() .iter()
.find(|avatar_data| avatar_data.guid.0 == *guid) .find(|avatar_data| avatar_data.guid.0 == event.avatar_guid)
{ {
let weapon_data = weapons.get(avatar_data.equipment.weapon).unwrap(); let weapon_data = weapons.get(avatar_data.equipment.weapon).unwrap();
message_output.send_to_all(AvatarChangeCostumeNotify { let entity_info = Some(build_avatar_entity_info(&avatar_data, &weapon_data));
entity_info: Some(build_avatar_entity_info(&avatar_data, &weapon_data)),
}); match event.change {
AvatarAppearanceChange::Costume(_) => {
message_output.send_to_all(AvatarChangeCostumeNotify { entity_info })
}
AvatarAppearanceChange::TraceEffect(_) => {
message_output.send_to_all(AvatarChangeTraceEffectNotify { entity_info })
}
}
} }
// that's disgusting, this packet required even if avatar is not on scene // that's disgusting, notify required even if avatar is not on scene
// even though it contains SceneEntityInfo // even though it contains SceneEntityInfo
else { else {
let player = players.get(*player_uid); let player = players.get(event.player_uid);
let avatar = player.avatar_module.avatar_map.get(guid).unwrap(); let avatar = player
.avatar_module
.avatar_map
.get(&event.avatar_guid)
.unwrap();
let weapon = player.item_map.get(&avatar.weapon_guid).unwrap(); let weapon = player.item_map.get(&avatar.weapon_guid).unwrap();
message_output.send( let entity_info = Some(build_fake_avatar_entity_info(avatar, weapon));
*player_uid, match event.change {
AvatarChangeCostumeNotify { AvatarAppearanceChange::Costume(_) => {
entity_info: Some(build_fake_avatar_entity_info(avatar, weapon)), message_output.send(event.player_uid, AvatarChangeCostumeNotify { entity_info })
}, }
); AvatarAppearanceChange::TraceEffect(_) => message_output.send(
event.player_uid,
AvatarChangeTraceEffectNotify { entity_info },
),
}
} }
} }
} }
@ -219,6 +253,7 @@ fn build_fake_avatar_entity_info(
wearing_flycloak_id: avatar.wearing_flycloak_id, wearing_flycloak_id: avatar.wearing_flycloak_id,
born_time: avatar.born_time, born_time: avatar.born_time,
costume_id: avatar.costume_id, costume_id: avatar.costume_id,
trace_effect_id: avatar.trace_effect_id,
cur_vehicle_info: None, cur_vehicle_info: None,
excel_info: Some(AvatarExcelInfo::default()), excel_info: Some(AvatarExcelInfo::default()),
anim_hash: 0, anim_hash: 0,
@ -305,6 +340,7 @@ fn build_avatar_entity_info(
wearing_flycloak_id: avatar_data.appearance.flycloak_id, wearing_flycloak_id: avatar_data.appearance.flycloak_id,
born_time: avatar_data.born_time.0, born_time: avatar_data.born_time.0,
costume_id: avatar_data.appearance.costume_id, costume_id: avatar_data.appearance.costume_id,
trace_effect_id: avatar_data.appearance.trace_effect_id,
cur_vehicle_info: None, cur_vehicle_info: None,
excel_info: Some(AvatarExcelInfo::default()), excel_info: Some(AvatarExcelInfo::default()),
anim_hash: 0, anim_hash: 0,

View file

@ -1,4 +1,4 @@
use avatar::{AvatarCostumeChangeEvent, AvatarEquipChangeEvent}; use avatar::{AvatarAppearanceChangeEvent, AvatarEquipChangeEvent};
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use common::{EntityCounter, FightProperties, LifeState, ProtocolEntityID, ToBeRemovedMarker}; use common::{EntityCounter, FightProperties, LifeState, ProtocolEntityID, ToBeRemovedMarker};
@ -25,7 +25,7 @@ impl Plugin for EntityPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.insert_resource(EntityCounter::default()) app.insert_resource(EntityCounter::default())
.add_event::<AvatarEquipChangeEvent>() .add_event::<AvatarEquipChangeEvent>()
.add_event::<AvatarCostumeChangeEvent>() .add_event::<AvatarAppearanceChangeEvent>()
.add_event::<EntityDisappearEvent>() .add_event::<EntityDisappearEvent>()
.add_systems(Update, avatar::update_avatar_appearance) .add_systems(Update, avatar::update_avatar_appearance)
.add_systems( .add_systems(
@ -35,7 +35,7 @@ impl Plugin for EntityPlugin {
notify_life_state_change, notify_life_state_change,
notify_disappear_entities, notify_disappear_entities,
remove_marked_entities, remove_marked_entities,
avatar::notify_avatar_costume_change, avatar::notify_avatar_appearance_change,
avatar::notify_appear_avatar_entities avatar::notify_appear_avatar_entities
.run_if(avatar::run_if_avatar_entities_appeared), .run_if(avatar::run_if_avatar_entities_appeared),
monster::notify_appear_monster_entities monster::notify_appear_monster_entities

View file

@ -35,6 +35,7 @@ pub struct AvatarModuleInformation {
pub team_map: HashMap<u32, AvatarTeamInformation>, pub team_map: HashMap<u32, AvatarTeamInformation>,
pub owned_flycloak_set: HashSet<u32>, pub owned_flycloak_set: HashSet<u32>,
pub owned_costume_set: HashSet<u32>, pub owned_costume_set: HashSet<u32>,
pub owned_trace_effect_set: HashSet<u32>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -57,6 +58,7 @@ pub struct AvatarInformation {
pub inherent_proud_skill_list: Vec<u32>, pub inherent_proud_skill_list: Vec<u32>,
pub wearing_flycloak_id: u32, pub wearing_flycloak_id: u32,
pub costume_id: u32, pub costume_id: u32,
pub trace_effect_id: u32,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]

View file

@ -9248,11 +9248,11 @@ pub struct Mkbmdcgmieo {
#[derive(sakura_proto_derive::CmdID)] #[derive(sakura_proto_derive::CmdID)]
#[cmdid(689)] #[cmdid(689)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)] #[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct Nolndpmeomc { pub struct AvatarChangeTraceEffectReq {
#[prost(uint64, tag = "9")] #[prost(uint64, tag = "9")]
pub avatar_guid: u64, pub avatar_guid: u64,
#[prost(uint32, tag = "5")] #[prost(uint32, tag = "5")]
pub dpmaabplgdp: u32, pub trace_effect_id: u32,
} }
#[derive(sakura_proto_derive::CmdID)] #[derive(sakura_proto_derive::CmdID)]
#[cmdid(2773)] #[cmdid(2773)]
@ -18167,7 +18167,7 @@ pub struct AvatarInfo {
#[prost(uint32, tag = "30")] #[prost(uint32, tag = "30")]
pub mfmiphlgdfl: u32, pub mfmiphlgdfl: u32,
#[prost(uint32, tag = "31")] #[prost(uint32, tag = "31")]
pub dpmaabplgdp: u32, pub trace_effect_id: u32,
} }
#[derive(sakura_proto_derive::CmdID)] #[derive(sakura_proto_derive::CmdID)]
#[cmdid(26048)] #[cmdid(26048)]
@ -18559,9 +18559,9 @@ pub struct Cgoihcdffej {
#[derive(sakura_proto_derive::CmdID)] #[derive(sakura_proto_derive::CmdID)]
#[cmdid(25986)] #[cmdid(25986)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)] #[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct Opcpmjolife { pub struct AvatarChangeTraceEffectRsp {
#[prost(uint32, tag = "1")] #[prost(uint32, tag = "1")]
pub dpmaabplgdp: u32, pub trace_effect_id: u32,
#[prost(int32, tag = "12")] #[prost(int32, tag = "12")]
pub retcode: i32, pub retcode: i32,
#[prost(uint64, tag = "15")] #[prost(uint64, tag = "15")]
@ -20049,7 +20049,7 @@ pub struct Lmfbfgjedkn {
#[derive(Clone, Copy, PartialEq, ::prost::Message)] #[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct Glinbnfejlc { pub struct Glinbnfejlc {
#[prost(uint32, tag = "15")] #[prost(uint32, tag = "15")]
pub dpmaabplgdp: u32, pub trace_effect_id: u32,
} }
#[derive(sakura_proto_derive::CmdID)] #[derive(sakura_proto_derive::CmdID)]
#[cmdid(9144)] #[cmdid(9144)]
@ -37400,7 +37400,7 @@ pub struct SceneAvatarInfo {
#[prost(uint32, tag = "22")] #[prost(uint32, tag = "22")]
pub anim_hash: u32, pub anim_hash: u32,
#[prost(uint32, tag = "23")] #[prost(uint32, tag = "23")]
pub dpmaabplgdp: u32, pub trace_effect_id: u32,
} }
#[derive(sakura_proto_derive::CmdID)] #[derive(sakura_proto_derive::CmdID)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]

View file

@ -436,6 +436,11 @@ impl From<crate::client::AvatarDataNotify> for AvatarDataNotify {
.map(|v| v.into()) .map(|v| v.into())
.collect(), .collect(),
choose_avatar_guid: value.choose_avatar_guid.into(), choose_avatar_guid: value.choose_avatar_guid.into(),
owned_trace_effect_list: value
.owned_trace_effect_list
.into_iter()
.map(|v| v.into())
.collect(),
avatar_team_map: value avatar_team_map: value
.avatar_team_map .avatar_team_map
.into_iter() .into_iter()
@ -579,6 +584,15 @@ for query_curr_region_http_rsp::Detail {
} }
} }
} }
impl From<crate::client::AvatarChangeTraceEffectReq> for AvatarChangeTraceEffectReq {
fn from(value: crate::client::AvatarChangeTraceEffectReq) -> Self {
Self {
avatar_guid: value.avatar_guid.into(),
trace_effect_id: value.trace_effect_id.into(),
..Default::default()
}
}
}
impl From<crate::client::QueryPathReq> for QueryPathReq { impl From<crate::client::QueryPathReq> for QueryPathReq {
fn from(value: crate::client::QueryPathReq) -> Self { fn from(value: crate::client::QueryPathReq) -> Self {
Self { Self {
@ -1085,6 +1099,7 @@ impl From<crate::client::AvatarInfo> for AvatarInfo {
excel_info: value.excel_info.map(|v| v.into()), excel_info: value.excel_info.map(|v| v.into()),
anim_hash: value.anim_hash.into(), anim_hash: value.anim_hash.into(),
mirror_avatar_info: value.mirror_avatar_info.map(|v| v.into()), mirror_avatar_info: value.mirror_avatar_info.map(|v| v.into()),
trace_effect_id: value.trace_effect_id.into(),
..Default::default() ..Default::default()
} }
} }
@ -1141,6 +1156,16 @@ impl From<crate::client::scene_entity_info::Entity> for scene_entity_info::Entit
} }
} }
} }
impl From<crate::client::AvatarChangeTraceEffectRsp> for AvatarChangeTraceEffectRsp {
fn from(value: crate::client::AvatarChangeTraceEffectRsp) -> Self {
Self {
trace_effect_id: value.trace_effect_id.into(),
retcode: value.retcode.into(),
avatar_guid: value.avatar_guid.into(),
..Default::default()
}
}
}
impl From<crate::client::EnterScenePeerNotify> for EnterScenePeerNotify { impl From<crate::client::EnterScenePeerNotify> for EnterScenePeerNotify {
fn from(value: crate::client::EnterScenePeerNotify) -> Self { fn from(value: crate::client::EnterScenePeerNotify) -> Self {
Self { Self {
@ -1733,6 +1758,15 @@ impl From<crate::client::UnlockTransPointReq> for UnlockTransPointReq {
} }
} }
} }
impl From<crate::client::AvatarChangeTraceEffectNotify>
for AvatarChangeTraceEffectNotify {
fn from(value: crate::client::AvatarChangeTraceEffectNotify) -> Self {
Self {
entity_info: value.entity_info.map(|v| v.into()),
..Default::default()
}
}
}
impl From<crate::client::AvatarFightPropUpdateNotify> for AvatarFightPropUpdateNotify { impl From<crate::client::AvatarFightPropUpdateNotify> for AvatarFightPropUpdateNotify {
fn from(value: crate::client::AvatarFightPropUpdateNotify) -> Self { fn from(value: crate::client::AvatarFightPropUpdateNotify) -> Self {
Self { Self {
@ -2273,6 +2307,7 @@ impl From<crate::client::SceneAvatarInfo> for SceneAvatarInfo {
cur_vehicle_info: value.cur_vehicle_info.map(|v| v.into()), cur_vehicle_info: value.cur_vehicle_info.map(|v| v.into()),
excel_info: value.excel_info.map(|v| v.into()), excel_info: value.excel_info.map(|v| v.into()),
anim_hash: value.anim_hash.into(), anim_hash: value.anim_hash.into(),
trace_effect_id: value.trace_effect_id.into(),
..Default::default() ..Default::default()
} }
} }

View file

@ -185,6 +185,14 @@ pub fn client_to_normal(
proto.encode_to_vec().into_boxed_slice(), proto.encode_to_vec().into_boxed_slice(),
)) ))
} }
crate::client::AvatarChangeTraceEffectReq::CMD_ID => {
let proto = crate::client::AvatarChangeTraceEffectReq::decode(body)?;
let proto: crate::normal::AvatarChangeTraceEffectReq = proto.into();
Ok((
crate::normal::AvatarChangeTraceEffectReq::CMD_ID,
proto.encode_to_vec().into_boxed_slice(),
))
}
crate::client::QueryPathReq::CMD_ID => { crate::client::QueryPathReq::CMD_ID => {
let proto = crate::client::QueryPathReq::decode(body)?; let proto = crate::client::QueryPathReq::decode(body)?;
let proto: crate::normal::QueryPathReq = proto.into(); let proto: crate::normal::QueryPathReq = proto.into();
@ -289,6 +297,14 @@ pub fn client_to_normal(
proto.encode_to_vec().into_boxed_slice(), proto.encode_to_vec().into_boxed_slice(),
)) ))
} }
crate::client::AvatarChangeTraceEffectRsp::CMD_ID => {
let proto = crate::client::AvatarChangeTraceEffectRsp::decode(body)?;
let proto: crate::normal::AvatarChangeTraceEffectRsp = proto.into();
Ok((
crate::normal::AvatarChangeTraceEffectRsp::CMD_ID,
proto.encode_to_vec().into_boxed_slice(),
))
}
crate::client::EnterScenePeerNotify::CMD_ID => { crate::client::EnterScenePeerNotify::CMD_ID => {
let proto = crate::client::EnterScenePeerNotify::decode(body)?; let proto = crate::client::EnterScenePeerNotify::decode(body)?;
let proto: crate::normal::EnterScenePeerNotify = proto.into(); let proto: crate::normal::EnterScenePeerNotify = proto.into();
@ -417,6 +433,14 @@ pub fn client_to_normal(
proto.encode_to_vec().into_boxed_slice(), proto.encode_to_vec().into_boxed_slice(),
)) ))
} }
crate::client::AvatarChangeTraceEffectNotify::CMD_ID => {
let proto = crate::client::AvatarChangeTraceEffectNotify::decode(body)?;
let proto: crate::normal::AvatarChangeTraceEffectNotify = proto.into();
Ok((
crate::normal::AvatarChangeTraceEffectNotify::CMD_ID,
proto.encode_to_vec().into_boxed_slice(),
))
}
crate::client::AvatarFightPropUpdateNotify::CMD_ID => { crate::client::AvatarFightPropUpdateNotify::CMD_ID => {
let proto = crate::client::AvatarFightPropUpdateNotify::decode(body)?; let proto = crate::client::AvatarFightPropUpdateNotify::decode(body)?;
let proto: crate::normal::AvatarFightPropUpdateNotify = proto.into(); let proto: crate::normal::AvatarFightPropUpdateNotify = proto.into();
@ -799,6 +823,14 @@ pub fn normal_to_client(
proto.encode_to_vec().into_boxed_slice(), proto.encode_to_vec().into_boxed_slice(),
)) ))
} }
crate::normal::AvatarChangeTraceEffectReq::CMD_ID => {
let proto = crate::normal::AvatarChangeTraceEffectReq::decode(body)?;
let proto: crate::client::AvatarChangeTraceEffectReq = proto.into();
Ok((
crate::client::AvatarChangeTraceEffectReq::CMD_ID,
proto.encode_to_vec().into_boxed_slice(),
))
}
crate::normal::QueryPathReq::CMD_ID => { crate::normal::QueryPathReq::CMD_ID => {
let proto = crate::normal::QueryPathReq::decode(body)?; let proto = crate::normal::QueryPathReq::decode(body)?;
let proto: crate::client::QueryPathReq = proto.into(); let proto: crate::client::QueryPathReq = proto.into();
@ -903,6 +935,14 @@ pub fn normal_to_client(
proto.encode_to_vec().into_boxed_slice(), proto.encode_to_vec().into_boxed_slice(),
)) ))
} }
crate::normal::AvatarChangeTraceEffectRsp::CMD_ID => {
let proto = crate::normal::AvatarChangeTraceEffectRsp::decode(body)?;
let proto: crate::client::AvatarChangeTraceEffectRsp = proto.into();
Ok((
crate::client::AvatarChangeTraceEffectRsp::CMD_ID,
proto.encode_to_vec().into_boxed_slice(),
))
}
crate::normal::EnterScenePeerNotify::CMD_ID => { crate::normal::EnterScenePeerNotify::CMD_ID => {
let proto = crate::normal::EnterScenePeerNotify::decode(body)?; let proto = crate::normal::EnterScenePeerNotify::decode(body)?;
let proto: crate::client::EnterScenePeerNotify = proto.into(); let proto: crate::client::EnterScenePeerNotify = proto.into();
@ -1031,6 +1071,14 @@ pub fn normal_to_client(
proto.encode_to_vec().into_boxed_slice(), proto.encode_to_vec().into_boxed_slice(),
)) ))
} }
crate::normal::AvatarChangeTraceEffectNotify::CMD_ID => {
let proto = crate::normal::AvatarChangeTraceEffectNotify::decode(body)?;
let proto: crate::client::AvatarChangeTraceEffectNotify = proto.into();
Ok((
crate::client::AvatarChangeTraceEffectNotify::CMD_ID,
proto.encode_to_vec().into_boxed_slice(),
))
}
crate::normal::AvatarFightPropUpdateNotify::CMD_ID => { crate::normal::AvatarFightPropUpdateNotify::CMD_ID => {
let proto = crate::normal::AvatarFightPropUpdateNotify::decode(body)?; let proto = crate::normal::AvatarFightPropUpdateNotify::decode(body)?;
let proto: crate::client::AvatarFightPropUpdateNotify = proto.into(); let proto: crate::client::AvatarFightPropUpdateNotify = proto.into();

View file

@ -11367,6 +11367,8 @@ pub struct AvatarDataNotify {
pub cur_avatar_team_id: u32, pub cur_avatar_team_id: u32,
#[prost(uint64, tag = "9")] #[prost(uint64, tag = "9")]
pub choose_avatar_guid: u64, pub choose_avatar_guid: u64,
#[prost(uint32, repeated, tag = "10")]
pub owned_trace_effect_list: ::prost::alloc::vec::Vec<u32>,
} }
#[derive(sakura_proto_derive::CmdID)] #[derive(sakura_proto_derive::CmdID)]
#[cmdid(1608)] #[cmdid(1608)]
@ -11936,6 +11938,33 @@ pub struct MirrorAvatarDataUpdateNotify {
pub avatar_list: ::prost::alloc::vec::Vec<AvatarInfo>, pub avatar_list: ::prost::alloc::vec::Vec<AvatarInfo>,
} }
#[derive(sakura_proto_derive::CmdID)] #[derive(sakura_proto_derive::CmdID)]
#[cmdid(1733)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AvatarChangeTraceEffectNotify {
#[prost(message, optional, tag = "1")]
pub entity_info: ::core::option::Option<SceneEntityInfo>,
}
#[derive(sakura_proto_derive::CmdID)]
#[cmdid(1734)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct AvatarChangeTraceEffectReq {
#[prost(uint64, tag = "1")]
pub avatar_guid: u64,
#[prost(uint32, tag = "2")]
pub trace_effect_id: u32,
}
#[derive(sakura_proto_derive::CmdID)]
#[cmdid(1735)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct AvatarChangeTraceEffectRsp {
#[prost(int32, tag = "1")]
pub retcode: i32,
#[prost(uint64, tag = "2")]
pub avatar_guid: u64,
#[prost(uint32, tag = "3")]
pub trace_effect_id: u32,
}
#[derive(sakura_proto_derive::CmdID)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)] #[derive(Clone, Copy, PartialEq, ::prost::Message)]
pub struct BattlePassCycle { pub struct BattlePassCycle {
#[prost(uint32, tag = "1")] #[prost(uint32, tag = "1")]
@ -35809,6 +35838,8 @@ pub struct SceneAvatarInfo {
pub excel_info: ::core::option::Option<AvatarExcelInfo>, pub excel_info: ::core::option::Option<AvatarExcelInfo>,
#[prost(uint32, tag = "21")] #[prost(uint32, tag = "21")]
pub anim_hash: u32, pub anim_hash: u32,
#[prost(uint32, tag = "22")]
pub trace_effect_id: u32,
} }
#[derive(sakura_proto_derive::CmdID)] #[derive(sakura_proto_derive::CmdID)]
#[derive(Clone, Copy, PartialEq, ::prost::Message)] #[derive(Clone, Copy, PartialEq, ::prost::Message)]
@ -36784,6 +36815,8 @@ pub struct AvatarInfo {
pub anim_hash: u32, pub anim_hash: u32,
#[prost(message, optional, tag = "27")] #[prost(message, optional, tag = "27")]
pub mirror_avatar_info: ::core::option::Option<MirrorAvatarInfo>, pub mirror_avatar_info: ::core::option::Option<MirrorAvatarInfo>,
#[prost(uint32, tag = "31")]
pub trace_effect_id: u32,
} }
#[derive(sakura_proto_derive::CmdID)] #[derive(sakura_proto_derive::CmdID)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]

View file

@ -436,6 +436,11 @@ impl From<crate::normal::AvatarDataNotify> for AvatarDataNotify {
.map(|v| v.into()) .map(|v| v.into())
.collect(), .collect(),
choose_avatar_guid: value.choose_avatar_guid.into(), choose_avatar_guid: value.choose_avatar_guid.into(),
owned_trace_effect_list: value
.owned_trace_effect_list
.into_iter()
.map(|v| v.into())
.collect(),
avatar_team_map: value avatar_team_map: value
.avatar_team_map .avatar_team_map
.into_iter() .into_iter()
@ -579,6 +584,15 @@ for query_curr_region_http_rsp::Detail {
} }
} }
} }
impl From<crate::normal::AvatarChangeTraceEffectReq> for AvatarChangeTraceEffectReq {
fn from(value: crate::normal::AvatarChangeTraceEffectReq) -> Self {
Self {
avatar_guid: value.avatar_guid.into(),
trace_effect_id: value.trace_effect_id.into(),
..Default::default()
}
}
}
impl From<crate::normal::QueryPathReq> for QueryPathReq { impl From<crate::normal::QueryPathReq> for QueryPathReq {
fn from(value: crate::normal::QueryPathReq) -> Self { fn from(value: crate::normal::QueryPathReq) -> Self {
Self { Self {
@ -1085,6 +1099,7 @@ impl From<crate::normal::AvatarInfo> for AvatarInfo {
excel_info: value.excel_info.map(|v| v.into()), excel_info: value.excel_info.map(|v| v.into()),
anim_hash: value.anim_hash.into(), anim_hash: value.anim_hash.into(),
mirror_avatar_info: value.mirror_avatar_info.map(|v| v.into()), mirror_avatar_info: value.mirror_avatar_info.map(|v| v.into()),
trace_effect_id: value.trace_effect_id.into(),
..Default::default() ..Default::default()
} }
} }
@ -1141,6 +1156,16 @@ impl From<crate::normal::scene_entity_info::Entity> for scene_entity_info::Entit
} }
} }
} }
impl From<crate::normal::AvatarChangeTraceEffectRsp> for AvatarChangeTraceEffectRsp {
fn from(value: crate::normal::AvatarChangeTraceEffectRsp) -> Self {
Self {
trace_effect_id: value.trace_effect_id.into(),
retcode: value.retcode.into(),
avatar_guid: value.avatar_guid.into(),
..Default::default()
}
}
}
impl From<crate::normal::EnterScenePeerNotify> for EnterScenePeerNotify { impl From<crate::normal::EnterScenePeerNotify> for EnterScenePeerNotify {
fn from(value: crate::normal::EnterScenePeerNotify) -> Self { fn from(value: crate::normal::EnterScenePeerNotify) -> Self {
Self { Self {
@ -1733,6 +1758,15 @@ impl From<crate::normal::UnlockTransPointReq> for UnlockTransPointReq {
} }
} }
} }
impl From<crate::normal::AvatarChangeTraceEffectNotify>
for AvatarChangeTraceEffectNotify {
fn from(value: crate::normal::AvatarChangeTraceEffectNotify) -> Self {
Self {
entity_info: value.entity_info.map(|v| v.into()),
..Default::default()
}
}
}
impl From<crate::normal::AvatarFightPropUpdateNotify> for AvatarFightPropUpdateNotify { impl From<crate::normal::AvatarFightPropUpdateNotify> for AvatarFightPropUpdateNotify {
fn from(value: crate::normal::AvatarFightPropUpdateNotify) -> Self { fn from(value: crate::normal::AvatarFightPropUpdateNotify) -> Self {
Self { Self {
@ -2273,6 +2307,7 @@ impl From<crate::normal::SceneAvatarInfo> for SceneAvatarInfo {
cur_vehicle_info: value.cur_vehicle_info.map(|v| v.into()), cur_vehicle_info: value.cur_vehicle_info.map(|v| v.into()),
excel_info: value.excel_info.map(|v| v.into()), excel_info: value.excel_info.map(|v| v.into()),
anim_hash: value.anim_hash.into(), anim_hash: value.anim_hash.into(),
trace_effect_id: value.trace_effect_id.into(),
..Default::default() ..Default::default()
} }
} }

View file

@ -95,6 +95,7 @@ pub fn player_join_team(
appearance: AvatarAppearance { appearance: AvatarAppearance {
flycloak_id: to_spawn.wearing_flycloak_id, flycloak_id: to_spawn.wearing_flycloak_id,
costume_id: to_spawn.costume_id, costume_id: to_spawn.costume_id,
trace_effect_id: to_spawn.trace_effect_id,
}, },
transform: Transform { transform: Transform {
position: player_info.world_position.position.into(), position: player_info.world_position.position.into(),

View file

@ -134,6 +134,7 @@ pub fn notify_scene_team_update(
wearing_flycloak_id: avatar_data.appearance.flycloak_id, wearing_flycloak_id: avatar_data.appearance.flycloak_id,
born_time: avatar_data.born_time.0, born_time: avatar_data.born_time.0,
costume_id: avatar_data.appearance.costume_id, costume_id: avatar_data.appearance.costume_id,
trace_effect_id: avatar_data.appearance.trace_effect_id,
cur_vehicle_info: None, cur_vehicle_info: None,
excel_info: Some(AvatarExcelInfo::default()), excel_info: Some(AvatarExcelInfo::default()),
anim_hash: 0, anim_hash: 0,