This commit is contained in:
traffic95 2025-03-18 20:42:30 +01:00
commit 94af165a63
20 changed files with 716 additions and 24 deletions

1
Cargo.lock generated
View file

@ -3751,6 +3751,7 @@ version = "0.0.1"
dependencies = [
"num_enum",
"prost",
"trigger-fileconfig",
]
[[package]]

View file

@ -1,10 +1,3 @@
pub const MALE_AVATAR_ID: u32 = 2011;
pub const FEMALE_AVATAR_ID: u32 = 2021;
pub fn is_player_avatar(id: u32) -> bool {
id == MALE_AVATAR_ID || id == FEMALE_AVATAR_ID
}
pub fn is_valid_talent_switch(v: &[bool]) -> bool {
v.len() == 6
&& v[0..3]

View file

@ -4,6 +4,7 @@ pub mod dungeon_util;
pub mod equip_util;
pub mod gm_util;
mod player;
pub mod scene;
pub mod scene_util;
pub use player::NapPlayer;

View file

@ -8,7 +8,7 @@ use role::RoleModel;
use scene::SceneModel;
use trigger_database::{entity::*, prelude::*, DatabaseConnection};
use trigger_fileconfig::NapFileCfg;
use trigger_logic::scene::ESceneType;
use trigger_logic::{scene::ESceneType, template_ext::TemplateExt};
use trigger_protocol::PlayerInfo;
use trigger_sv::message::GameStateData;
use yorozuya::YorozuyaModel;
@ -62,11 +62,8 @@ impl NapPlayer {
player_uid,
};
let Some((player_basic_info, is_new_player)) =
player_util::load_player_basic_info(database, player_uid, create_if_not_exists).await
else {
return None;
};
let (player_basic_info, is_new_player) =
player_util::load_player_basic_info(database, player_uid, create_if_not_exists).await?;
let role_model = RoleModel::init(context.clone()).await;
let item_model = ItemModel::init(context.clone()).await;
@ -95,6 +92,28 @@ impl NapPlayer {
})
}
pub fn beginner_procedure_id(&self) -> Option<i32> {
(self.player_basic_info.beginner_procedure_id != -1)
.then_some(self.player_basic_info.beginner_procedure_id)
}
pub async fn advance_beginner_procedure(&mut self, id: i32) {
let active_model = player_basic_info::ActiveModel {
beginner_procedure_id: Set(self
.context
.filecfg
.is_last_procedure(id)
.then_some(-1)
.unwrap_or(id)),
..self.player_basic_info.clone().into()
};
self.player_basic_info = active_model
.update(self.context.database)
.await
.expect("player_basic_info::update failed");
}
pub fn build_state_reentrant_data(&self, scene: &scene_info::Model) -> Option<GameStateData> {
match ESceneType::try_from(scene.scene_type).unwrap() {
ESceneType::Hall => Some(GameStateData::Hall {
@ -106,6 +125,31 @@ impl NapPlayer {
}
}
pub async fn select_role(&mut self, avatar_id: u32) {
let mut active_model: player_basic_info::ActiveModel =
self.player_basic_info.clone().into();
active_model.set(
player_basic_info::Column::AvatarId,
(avatar_id as i32).into(),
);
active_model.set(
player_basic_info::Column::PlayerAvatarId,
(avatar_id as i32).into(),
);
active_model.set(
player_basic_info::Column::ControlAvatarId,
(avatar_id as i32).into(),
);
self.player_basic_info = active_model
.update(self.context.database)
.await
.expect("player_basic_info::update failed");
}
pub async fn set_control_avatars(&mut self, player_avatar_id: u32, control_avatar_id: u32) {
let mut active_model: player_basic_info::ActiveModel =
self.player_basic_info.clone().into();

View file

@ -32,9 +32,10 @@ fn create_default_player_basic_info(player_uid: i32) -> player_basic_info::Activ
nick_name: String::from("ReversedRooms"),
level: 60,
exp: 0,
avatar_id: 2021,
player_avatar_id: 2021,
control_avatar_id: 1361,
avatar_id: 0,
player_avatar_id: 0,
control_avatar_id: 0,
beginner_procedure_id: 0,
}
.into()
}

View file

@ -0,0 +1,22 @@
use trigger_logic::scene::ESceneType;
#[derive(Debug)]
pub enum ServerlessStateData {
FreshScene { procedure_id: i32 },
}
impl ServerlessStateData {
pub fn protocol_scene_data(&self) -> trigger_protocol::SceneData {
use trigger_protocol::*;
match self {
Self::FreshScene { procedure_id } => SceneData {
scene_type: ESceneType::Fresh.into(),
fresh_scene_info: Some(FreshSceneInfo {
last_procedure_id: *procedure_id as u32,
}),
..Default::default()
},
}
}
}

View file

@ -4,10 +4,9 @@ use trigger_codegen::handlers;
#[handlers]
mod player_module {
use tracing::debug;
use trigger_logic::template_ext::TemplateExt;
use trigger_sv::{net::ServerType, time_util};
use crate::logic::avatar_util;
pub async fn on_get_player_info(
context: &mut MessageContext<'_, '_>,
_request: GetPlayerInfoCsReq,
@ -39,6 +38,34 @@ mod player_module {
}
}
pub async fn on_select_role(
context: &mut MessageContext<'_, '_>,
request: SelectRoleCsReq,
) -> SelectRoleScRsp {
if let Some(procedure_id) = context.player.beginner_procedure_id() {
if context
.state
.filecfg
.procedure_allows_select_role(procedure_id + 1)
&& context
.state
.filecfg
.is_player_avatar(request.avatar_id as i32)
{
context.player.select_role(request.avatar_id).await;
context.add_notify(PlayerSyncScNotify {
player_info: Some(context.player.get_protocol_player_info()),
..Default::default()
});
return SelectRoleScRsp { retcode: 0 };
}
}
SelectRoleScRsp { retcode: 1 }
}
pub async fn on_get_authkey(
context: &mut MessageContext<'_, '_>,
request: GetAuthkeyCsReq,
@ -69,8 +96,14 @@ mod player_module {
context: &mut MessageContext<'_, '_>,
request: SwitchRoleCsReq,
) -> SwitchRoleScRsp {
if avatar_util::is_player_avatar(request.player_avatar_id)
&& (avatar_util::is_player_avatar(request.control_avatar_id)
if context
.state
.filecfg
.is_player_avatar(request.player_avatar_id as i32)
&& (context
.state
.filecfg
.is_player_avatar(request.control_avatar_id as i32)
|| context
.player
.role_model

View file

@ -5,11 +5,28 @@ use trigger_codegen::handlers;
mod scene_module {
use tracing::debug;
use trigger_logic::scene::{ELocalPlayType, ESceneType};
use trigger_sv::message::GameStateData;
use trigger_sv::{
message::{AvailableServerProtocolMessage, GameStateData},
net::ServerType,
};
use crate::logic::{dungeon_util, scene_util};
use crate::logic::{dungeon_util, scene::ServerlessStateData, scene_util};
pub async fn on_enter_world(context: &mut MessageContext<'_, '_>, _request: EnterWorldCsReq) {
if let Some(procedure_id) = context.player.beginner_procedure_id() {
debug!("entering beginner procedure, id: {procedure_id}");
context
.session
.load_serverless_state(
ServerlessStateData::FreshScene { procedure_id },
context.request_id,
EnterWorldScRsp::default(),
)
.await;
return;
}
let scene_model = &mut context.player.scene_model;
let scene_to_enter = match scene_model.get_current_scene().await {
@ -24,7 +41,6 @@ mod scene_module {
};
let scene_to_enter = if scene_to_enter.is_none() {
// TODO: first scene to be created should be the 'Fresh' scene (beginner procedure)
debug!(
"player with uid {} has no scene to enter, default hall scene will be created",
context.session.player_uid
@ -149,6 +165,104 @@ mod scene_module {
.await;
}
pub async fn on_advance_beginner_procedure(
context: &mut MessageContext<'_, '_>,
request: AdvanceBeginnerProcedureCsReq,
) {
let rsp = if let Some(procedure_id) = context.player.beginner_procedure_id() {
if request.procedure_id == procedure_id + 1 {
context
.player
.advance_beginner_procedure(request.procedure_id)
.await;
let rsp = AdvanceBeginnerProcedureScRsp {
retcode: 0,
next_procedure_id: request.procedure_id,
};
if context.player.beginner_procedure_id().is_none() {
// Beginner procedure finished, enter the hall scene now
let scene_model = &mut context.player.scene_model;
let scene = scene_model.create_scene_info(ESceneType::Hall).await;
scene_model.set_default_scene(&scene).await;
context
.session
.change_game_state(
context.request_id,
rsp,
context.player.build_state_reentrant_data(&scene).unwrap(),
&scene,
context.player,
false,
)
.await;
None
} else {
Some(rsp)
}
} else {
debug!(
"invalid procedure transition (from: {}, to: {})",
procedure_id, request.procedure_id
);
Some(AdvanceBeginnerProcedureScRsp {
retcode: 1,
..Default::default()
})
}
} else {
Some(AdvanceBeginnerProcedureScRsp {
retcode: 1,
..Default::default()
})
};
if let Some(rsp) = rsp {
context
.session
.network_mgr
.send_to(
ServerType::GateServer,
0,
AvailableServerProtocolMessage {
session_id: context.session.id,
ack_request_id: context.request_id,
notifies: Vec::new(),
response: Some(rsp.into()),
},
)
.await;
}
}
pub async fn on_beginnerbattle_begin(
_context: &mut MessageContext<'_, '_>,
request: BeginnerbattleBeginCsReq,
) -> BeginnerbattleBeginScRsp {
BeginnerbattleBeginScRsp {
retcode: 0,
battle_uid: request.battle_id as i64,
}
}
pub async fn on_beginnerbattle_rebegin(
_context: &mut MessageContext<'_, '_>,
_request: BeginnerbattleRebeginCsReq,
) -> BeginnerbattleRebeginScRsp {
BeginnerbattleRebeginScRsp { retcode: 0 }
}
pub async fn on_beginnerbattle_end(
_context: &mut MessageContext<'_, '_>,
_request: BeginnerbattleEndCsReq,
) -> BeginnerbattleEndScRsp {
BeginnerbattleEndScRsp { retcode: 0 }
}
pub async fn on_active_hollow_check_point(
_context: &mut MessageContext<'_, '_>,
request: ActiveHollowCheckPointCsReq,

View file

@ -185,6 +185,18 @@ mod client_systems_module {
}
}
pub async fn on_end_newbie(
_context: &mut MessageContext<'_, '_>,
request: EndNewbieCsReq,
) -> EndNewbieScRsp {
debug!("EndNewbie({})", request.group_id);
EndNewbieScRsp {
retcode: 0,
group_id: 0,
}
}
pub async fn on_get_trashbin_hermit_data(
_context: &mut MessageContext<'_, '_>,
_request: GetTrashbinHermitDataCsReq,

View file

@ -35,4 +35,11 @@ mod workbench_module {
abyss_reward_data: Some(AbyssRewardData::default()),
}
}
pub async fn on_unlock_clue_item(
_context: &mut MessageContext<'_, '_>,
_request: UnlockClueItemCsReq,
) -> UnlockClueItemScRsp {
UnlockClueItemScRsp { retcode: 0 }
}
}

View file

@ -15,7 +15,7 @@ use trigger_sv::{
net::{ServerNetworkManager, ServerType},
};
use crate::logic::{scene_util, NapPlayer};
use crate::logic::{scene::ServerlessStateData, scene_util, NapPlayer};
pub mod message;
@ -50,6 +50,31 @@ impl GameSession {
}
}
pub async fn load_serverless_state(
&self,
state_data: ServerlessStateData,
ack_request_id: u32,
response: impl Into<ProtocolUnit>,
) {
let enter_scene_notify = trigger_protocol::EnterSceneScNotify {
scene: Some(state_data.protocol_scene_data()),
dungeon: None,
};
self.network_mgr
.send_to(
ServerType::GateServer,
0,
AvailableServerProtocolMessage {
session_id: self.id,
ack_request_id,
notifies: vec![enter_scene_notify.into()],
response: Some(response.into()),
},
)
.await;
}
pub async fn change_game_state(
&self,
ack_request_id: u32,

View file

@ -11,6 +11,7 @@ pub struct Model {
pub avatar_id: i32,
pub player_avatar_id: i32,
pub control_avatar_id: i32,
pub beginner_procedure_id: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]

View file

@ -395,6 +395,15 @@ table ConditionConfigTemplate {
type: int;
}
table ProcedureConfigTemplate {
procedure_id: int;
procedure_type: int;
content_id: string;
jump_tos: [int];
procedure_banks: [string];
procedure_event: string;
}
table AvatarBattleTemplate {
id: int;
unk_1: [int];
@ -621,6 +630,10 @@ table ConditionConfigTemplateTb {
data: [ConditionConfigTemplate];
}
table ProcedureConfigTemplateTb {
data: [ProcedureConfigTemplate];
}
table AvatarBattleTemplateTb {
data: [AvatarBattleTemplate];
}

View file

@ -7366,6 +7366,188 @@ impl core::fmt::Debug for ConditionConfigTemplate<'_> {
ds.finish()
}
}
pub enum ProcedureConfigTemplateOffset {}
#[derive(Copy, Clone, PartialEq)]
pub struct ProcedureConfigTemplate<'a> {
pub _tab: flatbuffers::Table<'a>,
}
impl<'a> flatbuffers::Follow<'a> for ProcedureConfigTemplate<'a> {
type Inner = ProcedureConfigTemplate<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: flatbuffers::Table::new(buf, loc) }
}
}
impl<'a> ProcedureConfigTemplate<'a> {
pub const VT_PROCEDURE_ID: flatbuffers::VOffsetT = 4;
pub const VT_PROCEDURE_TYPE: flatbuffers::VOffsetT = 6;
pub const VT_CONTENT_ID: flatbuffers::VOffsetT = 8;
pub const VT_JUMP_TOS: flatbuffers::VOffsetT = 10;
pub const VT_PROCEDURE_BANKS: flatbuffers::VOffsetT = 12;
pub const VT_PROCEDURE_EVENT: flatbuffers::VOffsetT = 14;
#[inline]
pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
ProcedureConfigTemplate { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>(
_fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>,
args: &'args ProcedureConfigTemplateArgs<'args>
) -> flatbuffers::WIPOffset<ProcedureConfigTemplate<'bldr>> {
let mut builder = ProcedureConfigTemplateBuilder::new(_fbb);
if let Some(x) = args.procedure_event { builder.add_procedure_event(x); }
if let Some(x) = args.procedure_banks { builder.add_procedure_banks(x); }
if let Some(x) = args.jump_tos { builder.add_jump_tos(x); }
if let Some(x) = args.content_id { builder.add_content_id(x); }
builder.add_procedure_type(args.procedure_type);
builder.add_procedure_id(args.procedure_id);
builder.finish()
}
#[inline]
pub fn procedure_id(&self) -> i32 {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<i32>(ProcedureConfigTemplate::VT_PROCEDURE_ID, Some(0)).unwrap()}
}
#[inline]
pub fn procedure_type(&self) -> i32 {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<i32>(ProcedureConfigTemplate::VT_PROCEDURE_TYPE, Some(0)).unwrap()}
}
#[inline]
pub fn content_id(&self) -> Option<&'a str> {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(ProcedureConfigTemplate::VT_CONTENT_ID, None)}
}
#[inline]
pub fn jump_tos(&self) -> Option<flatbuffers::Vector<'a, i32>> {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, i32>>>(ProcedureConfigTemplate::VT_JUMP_TOS, None)}
}
#[inline]
pub fn procedure_banks(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>> {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>>>(ProcedureConfigTemplate::VT_PROCEDURE_BANKS, None)}
}
#[inline]
pub fn procedure_event(&self) -> Option<&'a str> {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(ProcedureConfigTemplate::VT_PROCEDURE_EVENT, None)}
}
}
impl flatbuffers::Verifiable for ProcedureConfigTemplate<'_> {
#[inline]
fn run_verifier(
v: &mut flatbuffers::Verifier, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<i32>("procedure_id", Self::VT_PROCEDURE_ID, false)?
.visit_field::<i32>("procedure_type", Self::VT_PROCEDURE_TYPE, false)?
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("content_id", Self::VT_CONTENT_ID, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, i32>>>("jump_tos", Self::VT_JUMP_TOS, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<&'_ str>>>>("procedure_banks", Self::VT_PROCEDURE_BANKS, false)?
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("procedure_event", Self::VT_PROCEDURE_EVENT, false)?
.finish();
Ok(())
}
}
pub struct ProcedureConfigTemplateArgs<'a> {
pub procedure_id: i32,
pub procedure_type: i32,
pub content_id: Option<flatbuffers::WIPOffset<&'a str>>,
pub jump_tos: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, i32>>>,
pub procedure_banks: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>>>,
pub procedure_event: Option<flatbuffers::WIPOffset<&'a str>>,
}
impl<'a> Default for ProcedureConfigTemplateArgs<'a> {
#[inline]
fn default() -> Self {
ProcedureConfigTemplateArgs {
procedure_id: 0,
procedure_type: 0,
content_id: None,
jump_tos: None,
procedure_banks: None,
procedure_event: None,
}
}
}
pub struct ProcedureConfigTemplateBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> {
fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>,
start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> ProcedureConfigTemplateBuilder<'a, 'b, A> {
#[inline]
pub fn add_procedure_id(&mut self, procedure_id: i32) {
self.fbb_.push_slot::<i32>(ProcedureConfigTemplate::VT_PROCEDURE_ID, procedure_id, 0);
}
#[inline]
pub fn add_procedure_type(&mut self, procedure_type: i32) {
self.fbb_.push_slot::<i32>(ProcedureConfigTemplate::VT_PROCEDURE_TYPE, procedure_type, 0);
}
#[inline]
pub fn add_content_id(&mut self, content_id: flatbuffers::WIPOffset<&'b str>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(ProcedureConfigTemplate::VT_CONTENT_ID, content_id);
}
#[inline]
pub fn add_jump_tos(&mut self, jump_tos: flatbuffers::WIPOffset<flatbuffers::Vector<'b , i32>>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(ProcedureConfigTemplate::VT_JUMP_TOS, jump_tos);
}
#[inline]
pub fn add_procedure_banks(&mut self, procedure_banks: flatbuffers::WIPOffset<flatbuffers::Vector<'b , flatbuffers::ForwardsUOffset<&'b str>>>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(ProcedureConfigTemplate::VT_PROCEDURE_BANKS, procedure_banks);
}
#[inline]
pub fn add_procedure_event(&mut self, procedure_event: flatbuffers::WIPOffset<&'b str>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(ProcedureConfigTemplate::VT_PROCEDURE_EVENT, procedure_event);
}
#[inline]
pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> ProcedureConfigTemplateBuilder<'a, 'b, A> {
let start = _fbb.start_table();
ProcedureConfigTemplateBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline]
pub fn finish(self) -> flatbuffers::WIPOffset<ProcedureConfigTemplate<'a>> {
let o = self.fbb_.end_table(self.start_);
flatbuffers::WIPOffset::new(o.value())
}
}
impl core::fmt::Debug for ProcedureConfigTemplate<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut ds = f.debug_struct("ProcedureConfigTemplate");
ds.field("procedure_id", &self.procedure_id());
ds.field("procedure_type", &self.procedure_type());
ds.field("content_id", &self.content_id());
ds.field("jump_tos", &self.jump_tos());
ds.field("procedure_banks", &self.procedure_banks());
ds.field("procedure_event", &self.procedure_event());
ds.finish()
}
}
pub enum AvatarBattleTemplateOffset {}
#[derive(Copy, Clone, PartialEq)]
@ -11904,6 +12086,103 @@ impl core::fmt::Debug for ConditionConfigTemplateTb<'_> {
ds.finish()
}
}
pub enum ProcedureConfigTemplateTbOffset {}
#[derive(Copy, Clone, PartialEq)]
pub struct ProcedureConfigTemplateTb<'a> {
pub _tab: flatbuffers::Table<'a>,
}
impl<'a> flatbuffers::Follow<'a> for ProcedureConfigTemplateTb<'a> {
type Inner = ProcedureConfigTemplateTb<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: flatbuffers::Table::new(buf, loc) }
}
}
impl<'a> ProcedureConfigTemplateTb<'a> {
pub const VT_DATA: flatbuffers::VOffsetT = 4;
#[inline]
pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
ProcedureConfigTemplateTb { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>(
_fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>,
args: &'args ProcedureConfigTemplateTbArgs<'args>
) -> flatbuffers::WIPOffset<ProcedureConfigTemplateTb<'bldr>> {
let mut builder = ProcedureConfigTemplateTbBuilder::new(_fbb);
if let Some(x) = args.data { builder.add_data(x); }
builder.finish()
}
#[inline]
pub fn data(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<ProcedureConfigTemplate<'a>>>> {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<ProcedureConfigTemplate>>>>(ProcedureConfigTemplateTb::VT_DATA, None)}
}
}
impl flatbuffers::Verifiable for ProcedureConfigTemplateTb<'_> {
#[inline]
fn run_verifier(
v: &mut flatbuffers::Verifier, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<ProcedureConfigTemplate>>>>("data", Self::VT_DATA, false)?
.finish();
Ok(())
}
}
pub struct ProcedureConfigTemplateTbArgs<'a> {
pub data: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<ProcedureConfigTemplate<'a>>>>>,
}
impl<'a> Default for ProcedureConfigTemplateTbArgs<'a> {
#[inline]
fn default() -> Self {
ProcedureConfigTemplateTbArgs {
data: None,
}
}
}
pub struct ProcedureConfigTemplateTbBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> {
fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>,
start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> ProcedureConfigTemplateTbBuilder<'a, 'b, A> {
#[inline]
pub fn add_data(&mut self, data: flatbuffers::WIPOffset<flatbuffers::Vector<'b , flatbuffers::ForwardsUOffset<ProcedureConfigTemplate<'b >>>>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(ProcedureConfigTemplateTb::VT_DATA, data);
}
#[inline]
pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> ProcedureConfigTemplateTbBuilder<'a, 'b, A> {
let start = _fbb.start_table();
ProcedureConfigTemplateTbBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline]
pub fn finish(self) -> flatbuffers::WIPOffset<ProcedureConfigTemplateTb<'a>> {
let o = self.fbb_.end_table(self.start_);
flatbuffers::WIPOffset::new(o.value())
}
}
impl core::fmt::Debug for ProcedureConfigTemplateTb<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut ds = f.debug_struct("ProcedureConfigTemplateTb");
ds.field("data", &self.data());
ds.finish()
}
}
pub enum AvatarBattleTemplateTbOffset {}
#[derive(Copy, Clone, PartialEq)]

View file

@ -45,6 +45,7 @@ file_cfg! {
WeaponTemplateTb;
EquipmentTemplateTb;
EquipmentSuitTemplateTb;
ProcedureConfigTemplateTb;
UnlockConfigTemplateTb;
PostGirlConfigTemplateTb;
ArchiveFileQuestTemplateTb;

View file

@ -6,3 +6,5 @@ version.workspace = true
[dependencies]
num_enum.workspace = true
prost.workspace = true
trigger-fileconfig.workspace = true

View file

@ -3,3 +3,4 @@ pub mod item;
pub mod quest;
pub mod scene;
pub mod skill;
pub mod template_ext;

View file

@ -107,3 +107,9 @@ impl From<Vec<f64>> for Vector3f {
}
}
}
impl From<ESceneType> for u32 {
fn from(value: ESceneType) -> Self {
i16::from(value) as u32
}
}

View file

@ -0,0 +1,42 @@
use trigger_fileconfig::NapFileCfg;
pub trait TemplateExt {
fn is_player_avatar(&self, avatar_id: i32) -> bool;
fn procedure_allows_select_role(&self, procedure_id: i32) -> bool;
fn is_last_procedure(&self, procedure_id: i32) -> bool;
}
impl TemplateExt for NapFileCfg {
fn is_player_avatar(&self, avatar_id: i32) -> bool {
self.avatar_base_template_tb()
.data()
.unwrap()
.iter()
.find_map(|tmpl| (tmpl.id() == avatar_id && tmpl.camp() == 0).then_some(true))
.unwrap_or(false)
}
fn procedure_allows_select_role(&self, procedure_id: i32) -> bool {
self.procedure_config_template_tb()
.data()
.unwrap()
.iter()
.find_map(|tmpl| {
(tmpl.procedure_id() == procedure_id && tmpl.procedure_type() == 4).then_some(true)
})
.unwrap_or(false)
}
fn is_last_procedure(&self, procedure_id: i32) -> bool {
// faggots nuked JumpTos from client data btw!
self.procedure_config_template_tb()
.data()
.unwrap()
.iter()
.max_by_key(|tmpl| tmpl.procedure_id())
.unwrap()
.procedure_id()
== procedure_id
}
}

View file

@ -85,6 +85,18 @@ pub struct PlayerLogoutScRsp {
pub retcode: i32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(9)]
pub struct SelectRoleCsReq {
pub avatar_id: u32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(10)]
pub struct SelectRoleScRsp {
pub retcode: i32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(80)]
pub struct SwitchRoleCsReq {
@ -269,6 +281,7 @@ pub struct SceneData {
pub local_play_type: u32,
pub hall_scene_info: Option<HallSceneInfo>,
pub fight_scene_info: Option<FightSceneInfo>,
pub fresh_scene_info: Option<FreshSceneInfo>,
pub rally_scene_info: Option<RallySceneInfo>,
}
@ -322,6 +335,11 @@ pub struct FightSceneInfo {
pub level_reward_info: Option<LevelRewardInfo>,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable)]
pub struct FreshSceneInfo {
pub last_procedure_id: u32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable)]
pub struct PublicVariable {
pub r#type: u32,
@ -561,6 +579,59 @@ pub struct ActiveHollowCheckPointScRsp {
pub retcode: i32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(477)]
pub struct AdvanceBeginnerProcedureCsReq {
pub procedure_id: i32,
pub params: i32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(478)]
pub struct AdvanceBeginnerProcedureScRsp {
pub retcode: i32,
pub next_procedure_id: i32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(479)]
pub struct BeginnerbattleBeginCsReq {
pub battle_id: i32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(480)]
pub struct BeginnerbattleBeginScRsp {
pub retcode: i32,
pub battle_uid: i64,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(481)]
pub struct BeginnerbattleRebeginCsReq {
pub battle_id: i32,
pub battle_uid: i64,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(482)]
pub struct BeginnerbattleRebeginScRsp {
pub retcode: i32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(483)]
pub struct BeginnerbattleEndCsReq {
pub battle_id: i32,
pub battle_uid: i64,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(484)]
pub struct BeginnerbattleEndScRsp {
pub retcode: i32,
}
// Quest
#[derive(Default, Debug, Clone, Encodeable, Decodeable)]
@ -1273,6 +1344,19 @@ pub struct GetNewsStandDataScRsp {
pub news_stand_data: Option<NewsStandData>,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(1323)]
pub struct EndNewbieCsReq {
pub group_id: u32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(1324)]
pub struct EndNewbieScRsp {
pub retcode: i32,
pub group_id: u32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(1340)]
pub struct GetTrashbinHermitDataCsReq {}
@ -1490,6 +1574,16 @@ pub struct GetWorkbenchDataScRsp {
pub workbench_data: Option<WorkbenchData>,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(2002)]
pub struct UnlockClueItemCsReq {}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(2003)]
pub struct UnlockClueItemScRsp {
pub retcode: i32,
}
#[derive(Default, Debug, Clone, Encodeable, Decodeable, ClientCmdID)]
#[id(2010)]
pub struct GetPartnerDataCsReq {}