Files
robinsr/gameserver/src/net/handlers/battle.rs
T

391 lines
12 KiB
Rust

use std::collections::HashMap;
use rand::Rng;
use common::{
resources::GAME_RES,
structs::{BattleType, Monster},
};
use super::*;
pub async fn on_start_cocoon_stage_cs_req(
session: &mut PlayerSession,
req: &StartCocoonStageCsReq,
res: &mut StartCocoonStageScRsp,
) {
let battle_info = create_battle_info(session, 0, 0).await;
res.prop_entity_id = req.prop_entity_id;
res.cocoon_id = req.cocoon_id;
res.wave = req.wave;
res.battle_info = Some(battle_info);
}
pub async fn on_quick_start_cocoon_stage_cs_req(
session: &mut PlayerSession,
req: &QuickStartCocoonStageCsReq,
res: &mut QuickStartCocoonStageScRsp,
) {
let mut battle_info = create_battle_info(session, 0, 0).await;
battle_info.world_level = req.world_level;
res.cocoon_id = req.cocoon_id;
res.wave = req.wave;
res.battle_info = Some(battle_info);
}
pub async fn on_scene_enter_stage_cs_req(
session: &mut PlayerSession,
_req: &SceneEnterStageCsReq,
res: &mut SceneEnterStageScRsp,
) {
let battle_info = create_battle_info(session, 0, 0).await;
res.battle_info = Some(battle_info);
}
pub async fn on_pve_battle_result_cs_req(
_session: &mut PlayerSession,
req: &PveBattleResultCsReq,
res: &mut PveBattleResultScRsp,
) {
res.end_status = req.end_status;
res.battle_id = req.battle_id;
}
pub async fn on_scene_cast_skill_cs_req(
session: &mut PlayerSession,
req: &SceneCastSkillCsReq,
res: &mut SceneCastSkillScRsp,
) {
res.cast_entity_id = req.cast_entity_id;
let targets = req
.hit_target_entity_id_list
.iter()
.chain(&req.assist_monster_entity_id_list)
.filter(|id| **id > 30_000 || **id < 1_000)
.collect::<Vec<_>>();
if targets.is_empty() {
tracing::warn!("scene cast skill target is empty!");
return;
}
let battle_info = create_battle_info(session, req.attacked_by_entity_id, req.skill_index).await;
res.cast_entity_id = req.cast_entity_id;
res.battle_info = Some(battle_info);
}
async fn create_battle_info(
session: &mut PlayerSession,
caster_id: u32,
skill_index: u32,
) -> SceneBattleInfo {
let Some(player) = session.json_data.get() else {
tracing::error!("data is not set!");
return SceneBattleInfo::default();
};
let mut battle_info = SceneBattleInfo {
stage_id: player.battle_config.stage_id,
logic_random_seed: rand::rng().random::<u32>(),
battle_id: 1,
rounds_limit: player.battle_config.cycle_count,
world_level: 6,
..Default::default()
};
let mut first_avatar_id = 0;
// avatars
for (avatar_index, avatar_id) in player.lineups.iter() {
if first_avatar_id == 0 {
first_avatar_id = *avatar_id;
}
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) = player.avatars.get(&avatar_id) {
let (battle_avatar, techs) = avatar.to_battle_avatar_proto(
*avatar_index,
player
.lightcones
.iter()
.find(|v| v.equip_avatar == avatar.avatar_id),
player
.relics
.iter()
.filter(|v| v.equip_avatar == avatar.avatar_id)
.collect::<Vec<_>>(),
);
for tech in techs {
battle_info.buff_list.push(tech);
}
if caster_id > 0
&& *avatar_index == (caster_id - 1)
&& let Some(avatar_config) = GAME_RES.avatar_configs.get(&avatar_id)
&& !avatar.techniques.contains(&1000119)
{
battle_info.buff_list.push(BattleBuff {
id: avatar_config.weakness_buff_id,
level: 1,
owner_index: *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);
// hardcoded march
if avatar.avatar_id == 1224 {
let buffs = BattleBuff {
id: 122401,
level: 3,
wave_flag: 0xffffffff,
owner_index: *avatar_index,
dynamic_values: HashMap::from([
(String::from("#ADF_1"), 3f32),
(String::from("#ADF_2"), 3f32),
]),
target_index_list: vec![0],
};
battle_info.buff_list.push(buffs);
}
};
}
// Hardcoded Cerydra & Danheng PT technique
if first_avatar_id != 0 {
for buff in battle_info.buff_list.iter_mut() {
if buff.id == 141202 || buff.id == 141403 {
buff.owner_index = first_avatar_id
}
}
}
// custom stats for avatars
for stat in &player.battle_config.custom_stats {
for avatar in &mut battle_info.battle_avatar_list {
if avatar.relic_list.is_empty() {
avatar.relic_list.push(BattleRelic {
id: 61011,
main_affix_id: 1,
level: 1,
..Default::default()
})
}
if let Some(sub_affix) = avatar.relic_list[0]
.sub_affix_list
.iter_mut()
.find(|v| v.affix_id == stat.sub_affix_id)
{
sub_affix.cnt = stat.count;
} else {
avatar.relic_list[0].sub_affix_list.push(RelicAffix {
affix_id: stat.sub_affix_id,
cnt: stat.count,
step: stat.step,
})
}
}
}
// blessings
for blessing in &player.battle_config.blessings {
let mut buffs = BattleBuff {
id: blessing.id,
level: blessing.level,
wave_flag: 0xffffffff,
owner_index: 0xffffffff,
..Default::default()
};
if let Some(dynamic_value) = &blessing.dynamic_key {
buffs
.dynamic_values
.insert(dynamic_value.key.clone(), dynamic_value.value as f32);
};
for dynamic_value in &blessing.dynamic_values {
if buffs.dynamic_values.contains_key(&dynamic_value.key) {
continue;
};
buffs
.dynamic_values
.insert(dynamic_value.key.clone(), dynamic_value.value as f32);
}
battle_info.buff_list.push(buffs);
}
// pf score object
if player.battle_config.battle_type == BattleType::PF {
if battle_info.stage_id >= 30309011 {
battle_info.battle_target_info.insert(
1,
BattleTargetList {
battle_target_list: vec![BattleTarget {
id: 10003,
progress: 0,
..Default::default()
}],
},
);
} else {
battle_info.battle_target_info.insert(
1,
BattleTargetList {
battle_target_list: vec![BattleTarget {
id: 10002,
progress: 0,
..Default::default()
}],
},
);
}
for i in 2..=4 {
battle_info
.battle_target_info
.insert(i, BattleTargetList::default());
}
battle_info.battle_target_info.insert(
5,
BattleTargetList {
battle_target_list: vec![
BattleTarget {
id: 2001,
progress: 0,
..Default::default()
},
BattleTarget {
id: 2002,
progress: 0,
..Default::default()
},
],
},
);
}
// Apocalyptic Shadow
if player.battle_config.battle_type == BattleType::AS {
battle_info.battle_target_info.insert(
1,
BattleTargetList {
battle_target_list: vec![BattleTarget {
id: 90005,
progress: 0,
..Default::default()
}],
},
);
}
// SU
if player.battle_config.battle_type == BattleType::SU {
battle_info.battle_event.push(BattleEventBattleInfo {
battle_event_id: player.battle_config.path_resonance_id,
status: Some(BattleEventProperty {
sp_bar: Some(SpBarInfo {
cur_sp: 10_000,
max_sp: 10_000,
}),
}),
skill_info: Vec::with_capacity(0),
})
}
// Monsters
battle_info.monster_wave_list = Monster::to_scene_monster_waves(&player.battle_config.monsters);
// Rogue Magic
// TODO: i dont need these shit
if !player.battle_config.scepters.is_empty() {
// battle_info.battle_rogue_magic_info = Some(BattleRogueMagicInfo {
// detail_info: Some(BattleRogueMagicDetailInfo {
// paiigoggofj: Some(Item::BattleRogueMagicData(BattleRogueMagicData {
// round_cnt: Some(BattleRogueMagicRoundCount {
// gpojenhaiba: 3,
// kljklbmlefo: 0,
// }),
// battle_scepter_list: player
// .battle_config
// .scepters
// .iter()
// .map(|scepter| {
// let mut battle_scepter = BattleRogueMagicScepter {
// level: scepter.level,
// scepter_id: scepter.id,
// magic_list: Vec::new(),
// trench_count: HashMap::from([(3, 0), (4, 0), (5, 0)]),
// };
//
// let mut index = [0u32; 3];
//
// for component in &scepter.components {
// let (slot_type, locked) = match component.component_type {
// RogueMagicComponentType::Passive => (3u32, false),
// RogueMagicComponentType::Active => (4, true),
// RogueMagicComponentType::Attach => (5, false),
// };
//
// let slot_index = &mut index[slot_type as usize - 3];
// battle_scepter.magic_list.push(BattleRogueMagicUnit {
// level: component.level,
// unit_id: component.id,
// slot_id: *slot_index,
// locked,
// counter_map: Default::default(),
// });
// *slot_index += 1;
// *battle_scepter.trench_count.get_mut(&slot_type).unwrap() += 1;
// }
//
// battle_scepter
// })
// .collect(),
// })),
// }),
// modifier_content: Some(BattleRogueMagicModifierInfo {
// rogue_magic_battle_const: 5,
// }),
// });
}
// Global Buff
if !battle_info.buff_list.iter().any(|b| b.id == 140703) {
battle_info.buff_list.push(BattleBuff {
id: 140703,
level: 1,
owner_index: u32::MAX,
wave_flag: u32::MAX,
target_index_list: Vec::with_capacity(0),
dynamic_values: HashMap::with_capacity(0),
});
}
battle_info
}