feat: Fix multipath avatar & implement weakness buff id

This commit is contained in:
amizing25 2024-09-18 20:41:34 +07:00
parent f41cc5e47b
commit c4794570d1
8 changed files with 137 additions and 118 deletions

View File

@ -3,7 +3,10 @@ use std::collections::HashMap;
use rand::Rng; use rand::Rng;
use rogue_magic_battle_unit_info::Item; use rogue_magic_battle_unit_info::Item;
use crate::net::tools::{self, BattleType, Monster}; use crate::{
net::tools::{self, BattleType, Monster},
tools::resources::GAME_RES,
};
use super::*; use super::*;
@ -12,7 +15,7 @@ pub async fn on_start_cocoon_stage_cs_req(
body: &StartCocoonStageCsReq, body: &StartCocoonStageCsReq,
res: &mut StartCocoonStageScRsp, res: &mut StartCocoonStageScRsp,
) { ) {
let battle_info = create_battle_info().await; let battle_info = create_battle_info(0, 0).await;
res.prop_entity_id = body.prop_entity_id; res.prop_entity_id = body.prop_entity_id;
res.cocoon_id = body.cocoon_id; res.cocoon_id = body.cocoon_id;
@ -31,13 +34,12 @@ pub async fn on_pve_battle_result_cs_req(
pub async fn on_scene_cast_skill_cs_req( pub async fn on_scene_cast_skill_cs_req(
_session: &mut PlayerSession, _session: &mut PlayerSession,
request: &SceneCastSkillCsReq, req: &SceneCastSkillCsReq,
res: &mut SceneCastSkillScRsp, res: &mut SceneCastSkillScRsp,
) { ) {
res.attacked_group_id = request.attacked_group_id; res.attacked_group_id = req.attacked_group_id;
let battle_info = create_battle_info().await; let targets = req
let targets = request
.hit_target_entity_id_list .hit_target_entity_id_list
.iter() .iter()
.filter(|id| **id > 30_000 || **id < 1_000) .filter(|id| **id > 30_000 || **id < 1_000)
@ -47,10 +49,12 @@ pub async fn on_scene_cast_skill_cs_req(
return; return;
} }
let battle_info = create_battle_info(req.caster_id, req.skill_index).await;
res.battle_info = Some(battle_info); res.battle_info = Some(battle_info);
} }
async fn create_battle_info() -> SceneBattleInfo { async fn create_battle_info(caster_id: u32, skill_index: u32) -> SceneBattleInfo {
let player = tools::FreesrData::load().await; let player = tools::FreesrData::load().await;
let mut battle_info = SceneBattleInfo { let mut battle_info = SceneBattleInfo {
@ -62,10 +66,10 @@ async fn create_battle_info() -> SceneBattleInfo {
}; };
// avatars // avatars
for (i, avatar_id) in player.lineups.iter() { for (avatar_index, avatar_id) in player.lineups.iter() {
if let Some(avatar) = player.avatars.get(avatar_id) { if let Some(avatar) = player.avatars.get(avatar_id) {
let (battle_avatar, techs) = avatar.to_battle_avatar_proto( let (battle_avatar, techs) = avatar.to_battle_avatar_proto(
*i, *avatar_index,
player player
.lightcones .lightcones
.iter() .iter()
@ -79,6 +83,34 @@ async fn create_battle_info() -> SceneBattleInfo {
for tech in techs { for tech in techs {
battle_info.buff_list.push(tech); battle_info.buff_list.push(tech);
} }
if caster_id > 0 && *avatar_index == (caster_id - 1) {
let is_trailblazer = *avatar_id == 8001;
let is_march = *avatar_id == 1001;
let avatar_id = if is_trailblazer {
player.main_character as u32
} else if is_march {
player.march_type as u32
} else {
*avatar_id
};
if let Some(avatar_config) = GAME_RES.avatar_configs.get(&avatar_id) {
battle_info.buff_list.push(BattleBuff {
id: avatar_config.weakness_buff_id,
level: 1,
owner_id: *avatar_index,
wave_flag: 0xffffffff,
dynamic_values: HashMap::from([(
String::from("SkillIndex"),
skill_index as f32,
)]),
..Default::default()
});
}
}
battle_info.battle_avatar_list.push(battle_avatar); battle_info.battle_avatar_list.push(battle_avatar);
// hardcoded march // hardcoded march
@ -87,7 +119,7 @@ async fn create_battle_info() -> SceneBattleInfo {
id: 122401, id: 122401,
level: 3, level: 3,
wave_flag: 0xffffffff, wave_flag: 0xffffffff,
owner_id: *i, owner_id: *avatar_index,
dynamic_values: HashMap::from([ dynamic_values: HashMap::from([
(String::from("#ADF_1"), 3f32), (String::from("#ADF_1"), 3f32),
(String::from("#ADF_2"), 3f32), (String::from("#ADF_2"), 3f32),
@ -224,9 +256,10 @@ async fn create_battle_info() -> SceneBattleInfo {
}) })
} }
// monsters // Monsters
battle_info.monster_wave_list = Monster::to_scene_monster_waves(&player.battle_config.monsters); battle_info.monster_wave_list = Monster::to_scene_monster_waves(&player.battle_config.monsters);
// Rogue Magic
if !player.battle_config.scepters.is_empty() { if !player.battle_config.scepters.is_empty() {
battle_info.rogue_magic_battle_info = Some(RogueMagicBattleInfo { battle_info.rogue_magic_battle_info = Some(RogueMagicBattleInfo {
player_detail_info: Some(RogueMagicBattleUnitInfo { player_detail_info: Some(RogueMagicBattleUnitInfo {

View File

@ -86,8 +86,8 @@ pub async fn on_send_msg_cs_req(
msg_type: body.msg_type, msg_type: body.msg_type,
text: String::from("Inventory Synced"), text: String::from("Inventory Synced"),
emote: body.emote, emote: body.emote,
from_uid: SERVER_UID, // from from_uid: SERVER_UID,
to_uid: 25, // to to_uid: 25,
chat_type: body.chat_type, chat_type: body.chat_type,
}) })
.await .await
@ -117,8 +117,8 @@ pub async fn on_send_msg_cs_req(
msg_type: body.msg_type, msg_type: body.msg_type,
text: format!("Success change mc to {:#?}", mc), text: format!("Success change mc to {:#?}", mc),
emote: body.emote, emote: body.emote,
from_uid: SERVER_UID, // from from_uid: SERVER_UID,
to_uid: 25, // to to_uid: 25,
chat_type: body.chat_type, chat_type: body.chat_type,
}) })
.await .await
@ -148,8 +148,8 @@ pub async fn on_send_msg_cs_req(
msg_type: body.msg_type, msg_type: body.msg_type,
text: format!("Success change march to {:#?}", march_type), text: format!("Success change march to {:#?}", march_type),
emote: body.emote, emote: body.emote,
from_uid: SERVER_UID, // from from_uid: SERVER_UID,
to_uid: 25, // to to_uid: 25,
chat_type: body.chat_type, chat_type: body.chat_type,
}) })
.await .await

View File

@ -48,16 +48,7 @@ pub async fn on_join_lineup_cs_req(
) { ) {
let mut player = tools::FreesrData::load().await; let mut player = tools::FreesrData::load().await;
let lineups = &mut player.lineups; let lineups = &mut player.lineups;
lineups.insert( lineups.insert(body.slot, body.base_avatar_id);
body.slot,
if body.base_avatar_id == 8001 {
player.main_character as u32
} else if body.base_avatar_id == 1001 {
player.march_type as u32
} else {
body.base_avatar_id
},
);
player.save_lineup().await; player.save_lineup().await;
refresh_lineup(session, &player).await; refresh_lineup(session, &player).await;
} }
@ -72,13 +63,7 @@ pub async fn on_replace_lineup_cs_req(
let lineups = &mut player.lineups; let lineups = &mut player.lineups;
for (slot, avatar_id) in &mut *lineups { for (slot, avatar_id) in &mut *lineups {
if let Some(lineup) = req.slots.get(*slot as usize) { if let Some(lineup) = req.slots.get(*slot as usize) {
*avatar_id = if lineup.id == 8001 { *avatar_id = lineup.id;
player.main_character as u32
} else if lineup.id == 1001 {
player.march_type as u32
} else {
lineup.id
};
} else { } else {
*avatar_id = 0; *avatar_id = 0;
} }

View File

@ -45,12 +45,13 @@ use proto::{
CmdMuseumType::*, CmdOfferingType::*, CmdPamMissionType::*, CmdPhoneType::*, CmdMuseumType::*, CmdOfferingType::*, CmdPamMissionType::*, CmdPhoneType::*,
CmdPlayerBoardType::*, CmdPlayerReturnType::*, CmdPlayerSync::*, CmdPlayerType::*, CmdPlayerBoardType::*, CmdPlayerReturnType::*, CmdPlayerSync::*, CmdPlayerType::*,
CmdPlotType::*, CmdPunkLordType::*, CmdQuestType::*, CmdRaidCollectionType::*, CmdRaidType::*, CmdPlotType::*, CmdPunkLordType::*, CmdQuestType::*, CmdRaidCollectionType::*, CmdRaidType::*,
CmdRedDotType::*, CmdReplayType::*, CmdRndOptionType::*, CmdRogueCommonType::*, CmdRecommendType::*, CmdRedDotType::*, CmdReplayType::*, CmdRndOptionType::*,
CmdRogueEndless::*, CmdRogueModifierType::*, CmdRogueTournType::*, CmdRogueType::*, CmdRogueCommonType::*, CmdRogueEndless::*, CmdRogueModifierType::*, CmdRogueTournType::*,
CmdRollShopType::*, CmdSceneType::*, CmdServerPrefsType::*, CmdShopType::*, CmdSpaceZooType::*, CmdRogueType::*, CmdRollShopType::*, CmdSceneType::*, CmdServerPrefsType::*, CmdShopType::*,
CmdStarFightType::*, CmdStoryLineType::*, CmdStrongChallengeActivityType::*, CmdSpaceZooType::*, CmdStarFightType::*, CmdStoryLineType::*,
CmdTalkRewardType::*, CmdTelevisionActivityType::*, CmdTextJoinType::*, CmdTrainVisitorType::*, CmdStrongChallengeActivityType::*, CmdTalkRewardType::*, CmdTelevisionActivityType::*,
CmdTreasureDungeonType::*, CmdTutorialType::*, CmdWaypointType::*, CmdWolfBroType::*, CmdTextJoinType::*, CmdTrainVisitorType::*, CmdTreasureDungeonType::*, CmdTutorialType::*,
CmdWaypointType::*, CmdWolfBroType::*,
}; };
macro_rules! dummy { macro_rules! dummy {
@ -137,5 +138,6 @@ dummy! {
GetPhoneData, GetPhoneData,
// PlayerLoginFinish, // PlayerLoginFinish,
InteractProp, InteractProp,
FinishTalkMission FinishTalkMission,
RelicRecommend
} }

View File

@ -1,6 +1,9 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::{net::tools::FreesrData, util::cur_timestamp_ms}; use crate::{
net::tools::{FreesrData, MultiPathAvatar},
util::cur_timestamp_ms,
};
use super::*; use super::*;
@ -64,50 +67,35 @@ pub async fn on_get_multi_path_avatar_info_cs_req(
(1001, json.march_type.get_type().into()), (1001, json.march_type.get_type().into()),
]); ]);
res.multi_path_avatar_type_info_list = vec![ res.multi_path_avatar_type_info_list = MultiPathAvatar::to_vec()
MultiPathAvatarTypeInfo { .iter()
avatar_id: json.main_character as i32, .filter_map(|mp_type| {
rank: 6, let avatar_info = json.avatars.get(&((*mp_type) as u32))?;
Some(MultiPathAvatarTypeInfo {
avatar_id: *mp_type as i32,
rank: avatar_info.data.rank,
equip_relic_list: json equip_relic_list: json
.relics .relics
.iter() .iter()
.filter(|v| v.equip_avatar == json.main_character as u32) .filter(|relic| relic.equip_avatar == *mp_type as u32)
.map(|v| v.to_equipment_relic_proto()) .map(|relic| relic.to_equipment_relic_proto())
.collect(), .collect(),
skilltree_list: (1..=4) skilltree_list: avatar_info
.map(|v| AvatarSkillTree { .data
level: 1, .skills
point_id: (json.main_character as u32) * 1000 + v, .iter()
.map(|(point_id, level)| AvatarSkillTree {
point_id: *point_id,
level: *level,
}) })
.collect(), .collect(),
path_equipment_id: json path_equipment_id: json
.lightcones .lightcones
.iter() .iter()
.find(|v| v.equip_avatar == json.main_character as u32) .find(|v| v.equip_avatar == *mp_type as u32)
.map(|v| v.internal_uid) .map(|v| v.internal_uid)
.unwrap_or_default(), .unwrap_or_default(),
},
MultiPathAvatarTypeInfo {
avatar_id: json.march_type as i32,
rank: 6,
equip_relic_list: json
.relics
.iter()
.filter(|v| v.equip_avatar == json.march_type as u32)
.map(|v| v.to_equipment_relic_proto())
.collect(),
skilltree_list: (1..=4)
.map(|v| AvatarSkillTree {
level: 1,
point_id: (json.march_type as u32) * 1000 + v,
}) })
.collect(), })
path_equipment_id: json .collect();
.lightcones
.iter()
.find(|v| v.equip_avatar == json.march_type as u32)
.map(|v| v.internal_uid)
.unwrap_or_default(),
},
];
} }

View File

@ -51,6 +51,7 @@ pub async fn on_enter_scene_cs_req(
.is_err() .is_err()
{ {
res.retcode = Nbbhhpnhond::RetSceneEntryIdNotMatch as u32; res.retcode = Nbbhhpnhond::RetSceneEntryIdNotMatch as u32;
return;
}; };
res.alckpiobhlb = req.alckpiobhlb; res.alckpiobhlb = req.alckpiobhlb;
@ -185,7 +186,7 @@ async fn load_scene(
session: &mut PlayerSession, session: &mut PlayerSession,
json: &mut FreesrData, json: &mut FreesrData,
entry_id: u32, entry_id: u32,
save_scene: bool, is_enter_scene: bool,
teleport_id: Option<u32>, teleport_id: Option<u32>,
) -> Result<SceneInfo> { ) -> Result<SceneInfo> {
let (name, scene) = GAME_RES let (name, scene) = GAME_RES
@ -359,13 +360,13 @@ async fn load_scene(
} }
// load player entity // load player entity
let mut player_group = SceneEntityGroupInfo { scene_info.entity_group_list.push(SceneEntityGroupInfo {
state: 0, state: 0,
group_id: 0, group_id: 0,
..Default::default() entity_list: json
}; .lineups
for (slot, avatar_id) in &json.lineups { .iter()
player_group.entity_list.push(SceneEntityInfo { .map(|(slot, avatar_id)| SceneEntityInfo {
inst_id: 0, inst_id: 0,
entity_id: (*slot) + 1, entity_id: (*slot) + 1,
motion: Some(player_pos.clone()), motion: Some(player_pos.clone()),
@ -377,10 +378,10 @@ async fn load_scene(
})), })),
..Default::default() ..Default::default()
}) })
} .collect(),
scene_info.entity_group_list.push(player_group); });
if save_scene { if is_enter_scene {
session session
.send(EnterSceneByServerScNotify { .send(EnterSceneByServerScNotify {
scene: Some(scene_info.clone()), scene: Some(scene_info.clone()),

View File

@ -24,7 +24,7 @@ pub struct AvatarJson {
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AvatarData { pub struct AvatarData {
pub rank: u32, pub rank: u32,
pub skills: BTreeMap<u32, u32>, pub skills: HashMap<u32, u32>,
} }
impl AvatarJson { impl AvatarJson {
@ -506,7 +506,7 @@ impl Position {
pub struct FreesrData { pub struct FreesrData {
pub lightcones: Vec<Lightcone>, pub lightcones: Vec<Lightcone>,
pub relics: Vec<Relic>, pub relics: Vec<Relic>,
pub avatars: BTreeMap<u32, AvatarJson>, pub avatars: HashMap<u32, AvatarJson>,
#[serde(default)] #[serde(default)]
pub battle_config: BattleConfig, pub battle_config: BattleConfig,
@ -554,16 +554,18 @@ impl Default for Persistent {
} }
} }
#[derive(Serialize, Deserialize, Clone, Debug, Copy)] #[derive(Serialize, Deserialize, Clone, Debug, Copy, Default, PartialEq, Eq)]
pub enum MultiPathAvatar { pub enum MultiPathAvatar {
MalePyhsical = 8001, MalePyhsical = 8001,
FemalePhysical = 8002, FemalePhysical = 8002,
MalePreservation = 8003, MalePreservation = 8003,
FemalePreservation = 8004, FemalePreservation = 8004,
MaleHarmony = 8005, MaleHarmony = 8005,
#[default]
FemaleHarmony = 8006, FemaleHarmony = 8006,
MarchHunt = 1224, MarchHunt = 1224,
MarchPreservation = 1001, MarchPreservation = 1001,
Unk = 0,
} }
impl From<u32> for MultiPathAvatar { impl From<u32> for MultiPathAvatar {
@ -577,7 +579,7 @@ impl From<u32> for MultiPathAvatar {
8006 => Self::FemaleHarmony, 8006 => Self::FemaleHarmony,
1224 => Self::MarchHunt, 1224 => Self::MarchHunt,
1001 => Self::MarchPreservation, 1001 => Self::MarchPreservation,
_ => Self::FemaleHarmony, _ => Self::Unk,
} }
} }
} }
@ -603,13 +605,21 @@ impl MultiPathAvatar {
MultiPathAvatar::FemaleHarmony => MultiPathAvatarType::GirlShamanType, MultiPathAvatar::FemaleHarmony => MultiPathAvatarType::GirlShamanType,
MultiPathAvatar::MarchHunt => MultiPathAvatarType::Mar7thRogueType, MultiPathAvatar::MarchHunt => MultiPathAvatarType::Mar7thRogueType,
MultiPathAvatar::MarchPreservation => MultiPathAvatarType::Mar7thKnightType, MultiPathAvatar::MarchPreservation => MultiPathAvatarType::Mar7thKnightType,
MultiPathAvatar::Unk => MultiPathAvatarType::None,
} }
} }
}
impl Default for MultiPathAvatar { pub fn to_vec() -> Vec<MultiPathAvatar> {
fn default() -> Self { vec![
Self::FemaleHarmony Self::MalePyhsical,
Self::FemalePhysical,
Self::MalePreservation,
Self::FemalePreservation,
Self::MaleHarmony,
Self::FemaleHarmony,
Self::MarchHunt,
Self::MarchPreservation,
]
} }
} }

View File

@ -128,7 +128,7 @@ pub struct LevelOutputConfig {
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AvatarConfig { pub struct AvatarConfig {
// pub weakness_buff_id: u32, pub weakness_buff_id: u32,
// pub technique_buff_ids: Vec<u32>, // pub technique_buff_ids: Vec<u32>,
} }
@ -137,7 +137,7 @@ pub struct AvatarConfig {
pub struct JsonConfig { pub struct JsonConfig {
/// `entryid` -> `P[planeId]_F[floorId]` -> `groupId` /// `entryid` -> `P[planeId]_F[floorId]` -> `groupId`
pub level_output_configs: HashMap<u32, HashMap<String, LevelOutputConfig>>, pub level_output_configs: HashMap<u32, HashMap<String, LevelOutputConfig>>,
// pub avatar_configs: HashMap<u32, AvatarConfig>, pub avatar_configs: HashMap<u32, AvatarConfig>,
} }
pub static GAME_RES: LazyLock<JsonConfig> = LazyLock::new(|| { pub static GAME_RES: LazyLock<JsonConfig> = LazyLock::new(|| {