forked from wickedwaifus/wicked-waifus-rs
parent
ccf8aca5fd
commit
3552b7a431
34 changed files with 783 additions and 1950 deletions
464
Cargo.lock
generated
464
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
[workspace]
|
||||
members = ["wicked-waifus-asset-updater", "wicked-waifus-commons", "wicked-waifus-config-server", "wicked-waifus-hotpatch-server", "wicked-waifus-login-server", "wicked-waifus-gateway-server", "wicked-waifus-gateway-server/kcp", "wicked-waifus-database", "wicked-waifus-http", "wicked-waifus-protokey", "wicked-waifus-protocol-internal", "wicked-waifus-game-server", "wicked-waifus-network", "wicked-waifus-data"]
|
||||
members = ["wicked-waifus-asset-updater", "wicked-waifus-commons", "wicked-waifus-config-server", "wicked-waifus-hotpatch-server", "wicked-waifus-login-server", "wicked-waifus-gateway-server", "wicked-waifus-database", "wicked-waifus-http", "wicked-waifus-protokey", "wicked-waifus-protocol-internal", "wicked-waifus-game-server", "wicked-waifus-network", "wicked-waifus-data"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
|
@ -46,7 +46,6 @@ tracing = "0.1.40"
|
|||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
|
||||
# Internal
|
||||
kcp = { path = "wicked-waifus-gateway-server/kcp" }
|
||||
wicked-waifus-asset-updater = { path = "wicked-waifus-asset-updater" }
|
||||
wicked-waifus-commons = { path = "wicked-waifus-commons" }
|
||||
wicked-waifus-http = { path = "wicked-waifus-http" }
|
||||
|
|
|
@ -11,5 +11,5 @@ serve_dir_path = "data/assets/config-server"
|
|||
|
||||
[asset_config]
|
||||
repository_url = "https://git.xeondev.com/wickedwaifus/wicked-waifus-config-server-files.git"
|
||||
reference = "8f109f2724"
|
||||
reference = "f088e91db3"
|
||||
discard_local_changes = true
|
|
@ -47,21 +47,6 @@ pub struct BasePropertyData {
|
|||
pub damage_reduce_element4: i32,
|
||||
pub damage_reduce_element5: i32,
|
||||
pub damage_reduce_element6: i32,
|
||||
pub reaction_change1: i32,
|
||||
pub reaction_change2: i32,
|
||||
pub reaction_change3: i32,
|
||||
pub reaction_change4: i32,
|
||||
pub reaction_change5: i32,
|
||||
pub reaction_change6: i32,
|
||||
pub reaction_change7: i32,
|
||||
pub reaction_change8: i32,
|
||||
pub reaction_change9: i32,
|
||||
pub reaction_change10: i32,
|
||||
pub reaction_change11: i32,
|
||||
pub reaction_change12: i32,
|
||||
pub reaction_change13: i32,
|
||||
pub reaction_change14: i32,
|
||||
pub reaction_change15: i32,
|
||||
pub energy_max: i32,
|
||||
pub energy: i32,
|
||||
pub special_energy_1_max: i32,
|
||||
|
|
|
@ -149,6 +149,7 @@ json_data! {
|
|||
RoleInfo;
|
||||
RoleLevelConsume;
|
||||
RolePropertyGrowth;
|
||||
RoleSkin;
|
||||
SilentAreaDetection;
|
||||
SynthesisFormula;
|
||||
Teleporter;
|
||||
|
|
|
@ -68,6 +68,8 @@ pub enum GachaViewTypeInfoId {
|
|||
StandardResonatorConvene = 4,
|
||||
StandardWeaponConvene = 5,
|
||||
BeginnersChoiceConvene = 6,
|
||||
MultipleChoiceResonatorConvene = 7,
|
||||
MultipleChoiceWeaponConvene = 8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
|
@ -120,6 +122,7 @@ pub enum EntityType {
|
|||
ControlConnector,
|
||||
ConveyorBelt,
|
||||
CookTool,
|
||||
CurveControlDestructible,
|
||||
CustomAoiEditor,
|
||||
Destructible,
|
||||
DestructibleControl,
|
||||
|
@ -132,6 +135,7 @@ pub enum EntityType {
|
|||
DynamicPortalCreater,
|
||||
EffectArea,
|
||||
EnrichmentArea,
|
||||
EntityBatchRefresh,
|
||||
EntityBundle,
|
||||
EntityList,
|
||||
EntityPackage,
|
||||
|
@ -163,6 +167,7 @@ pub enum EntityType {
|
|||
LevelPlay,
|
||||
LevelPlayReward,
|
||||
LevelQteTrigger,
|
||||
LevelSeqTrigger,
|
||||
LevitateMagnet,
|
||||
LifePointCenter,
|
||||
Lift,
|
||||
|
@ -202,16 +207,19 @@ pub enum EntityType {
|
|||
SimpleInteract,
|
||||
SimpleNPc,
|
||||
SkyboxTrigger,
|
||||
SlideRail,
|
||||
SoundBox,
|
||||
SpawnMonster,
|
||||
SpawnPasserbyNpc,
|
||||
Spline,
|
||||
SplineRange,
|
||||
SummonGongduolaPoint,
|
||||
StateSceneItem,
|
||||
StateTrigger,
|
||||
StatueFoundation,
|
||||
SuiGuangHook,
|
||||
TargetGear,
|
||||
TargetGear2,
|
||||
TargetGearGroup,
|
||||
TargetGearGroup2,
|
||||
TargetGearPro,
|
||||
|
@ -220,6 +228,7 @@ pub enum EntityType {
|
|||
TeleControl3,
|
||||
TeleControlGroup,
|
||||
Teleporter,
|
||||
TemplateEntitySpawner,
|
||||
TemporaryTeleporter,
|
||||
TimedStrikeDevice,
|
||||
TimelineTrackController,
|
||||
|
|
|
@ -217,6 +217,15 @@ pub struct NodeDataDetailAction {
|
|||
pub actions: Vec<Action>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct NodeDataDetailActionWithResult {
|
||||
#[serde(flatten)]
|
||||
pub common: NodeDataDetailCommon,
|
||||
pub action: Action,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
|
@ -258,6 +267,7 @@ pub enum NodeDataDetail {
|
|||
Repeater(NodeDataDetailRepeater),
|
||||
Condition(NodeDataDetailCondition),
|
||||
Action(NodeDataDetailAction),
|
||||
ActionWithResult(NodeDataDetailActionWithResult),
|
||||
QuestSucceed(NodeDataDetailQuestSucceed),
|
||||
QuestFailed(NodeDataDetailQuestFailed),
|
||||
AlwaysFalse(NodeDataDetailAlways),
|
||||
|
|
|
@ -196,7 +196,8 @@ pub enum LeisureInteractOption {
|
|||
FailurePose,
|
||||
GameplayPose1,
|
||||
GameplayPose2,
|
||||
GameplayPose3
|
||||
GameplayPose3,
|
||||
FaithJump
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
|
@ -508,6 +509,11 @@ pub struct CameraLookAt {
|
|||
pub camera_pos: Option<Point>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct StopCameraLookAt {}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
|
@ -2257,6 +2263,94 @@ pub struct ActiveAntiGravitySafePoint {
|
|||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct BvbPlayDialog {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct BvbSendSystemEvent {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct BvbSendAiEvent {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct BvbPlayerOperationConstraint {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct ExecClientBattleAction {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct TriggerSpecificScanEffect {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct SetActorVar {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct RunActorCustomEvent {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct StopUiScreenEffect {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct StopNewMoveWithSpline {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct RequestSystemFunction {
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "Name")]
|
||||
pub enum Action {
|
||||
|
@ -2279,6 +2373,7 @@ pub enum Action {
|
|||
TeleportDungeon(ActionFields<TeleportDungeon>),
|
||||
DestroySelf(ActionFields<DestroySelf>),
|
||||
CameraLookAt(ActionFields<CameraLookAt>),
|
||||
StopCameraLookAt(ActionFields<StopCameraLookAt>),
|
||||
EnterOrbitalCamera(ActionFields<EnterOrbitalCamera>),
|
||||
ExitOrbitalCamera(ActionFields<ExitOrbitalCamera>),
|
||||
SendAiEvent(ActionFields<SendAiEvent>),
|
||||
|
@ -2432,6 +2527,17 @@ pub enum Action {
|
|||
GetRewardByInteract(ActionFields<GetRewardByInteract>),
|
||||
OpenQte(ActionFields<OpenQte>),
|
||||
ActiveAntiGravitySafePoint(ActionFields<ActiveAntiGravitySafePoint>),
|
||||
BvbPlayDialog(ActionFields<BvbPlayDialog>),
|
||||
BvbSendSystemEvent(ActionFields<BvbSendSystemEvent>),
|
||||
BvbSendAiEvent(ActionFields<BvbSendAiEvent>),
|
||||
BvbPlayerOperationConstraint(ActionFields<BvbPlayerOperationConstraint>),
|
||||
ExecClientBattleAction(ActionFields<ExecClientBattleAction>),
|
||||
TriggerSpecificScanEffect(ActionFields<TriggerSpecificScanEffect>),
|
||||
SetActorVar(ActionFields<SetActorVar>),
|
||||
RunActorCustomEvent(ActionFields<RunActorCustomEvent>),
|
||||
StopUiScreenEffect(ActionFields<StopUiScreenEffect>),
|
||||
StopNewMoveWithSpline(ActionFields<StopNewMoveWithSpline>),
|
||||
RequestSystemFunction(ActionFields<RequestSystemFunction>),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
|
|
|
@ -335,6 +335,7 @@ pub struct UsingVehicle {
|
|||
pub enum VehicleType {
|
||||
FishingBoat,
|
||||
Gongduola,
|
||||
SceneItemAutoMoveVehicle,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
|
@ -757,6 +758,13 @@ pub struct AddFlowInteractOption {
|
|||
pub config: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct MonsterMergedHpBarSettings {
|
||||
pub display_buff_ids: Vec<i64>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
|
||||
|
@ -765,6 +773,7 @@ pub struct MonsterCreator {
|
|||
pub prefab_var: Option<Var>,
|
||||
pub show_monster_merged_hp_bar: Option<bool>,
|
||||
pub tid_monster_group_name: Option<String>,
|
||||
pub monster_merged_hp_bar_settings: Option<MonsterMergedHpBarSettings>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
|
@ -1135,6 +1144,60 @@ pub struct CheckEntityReward {
|
|||
pub UiType: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct CheckIsGramophonePlayingMusic {
|
||||
// TODO:
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub UiType: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct CheckBVBEvent {
|
||||
// TODO:
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub UiType: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct FinishBvbChallenge {
|
||||
// TODO:
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub UiType: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct CompareActorVarElement {
|
||||
// TODO: ActorRef > PathName(String)
|
||||
// pub var1: Var,
|
||||
// pub compare: CompareType,
|
||||
// pub var2: Var,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct CompareActorVar {
|
||||
pub conditions: Vec<CompareActorVarElement>,
|
||||
pub count: i32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct CheckDangoCultivationProgress {
|
||||
// TODO:
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub UiType: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "Type")]
|
||||
pub enum Condition {
|
||||
|
@ -1237,6 +1300,11 @@ pub enum Condition {
|
|||
CheckEntityGravityDirection(CheckEntityGravityDirection),
|
||||
CheckTeleControlState(CheckTeleControlState),
|
||||
CheckEntityReward(CheckEntityReward),
|
||||
CheckIsGramophonePlayingMusic(CheckIsGramophonePlayingMusic),
|
||||
CheckBVBEvent(CheckBVBEvent),
|
||||
FinishBvbChallenge(FinishBvbChallenge),
|
||||
CompareActorVar(CompareActorVar),
|
||||
CheckDangoCultivationProgress(CheckDangoCultivationProgress),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
|
|
|
@ -91,6 +91,13 @@ pub struct SelfVar {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct System {
|
||||
pub r#type: VarType,
|
||||
// TODO: Add Var substruct
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "Source")]
|
||||
|
@ -100,4 +107,5 @@ pub enum Var {
|
|||
Global(Global),
|
||||
#[serde(rename = "Self")]
|
||||
SelfVar(SelfVar),
|
||||
System(System),
|
||||
}
|
101
wicked-waifus-data/src/role_skin.rs
Normal file
101
wicked-waifus-data/src/role_skin.rs
Normal file
|
@ -0,0 +1,101 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct RoleSkinData {
|
||||
pub id: i32,
|
||||
pub role_id: i32,
|
||||
pub suit_weapon_skin_id: i32,
|
||||
pub head_id: i32,
|
||||
pub quality_id: i32,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub name: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub title_name: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub sub_dec_name: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub type_description: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub attributes_description: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub bg_description: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub icon_middle: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub icon_small: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub item_access: Vec<i32>,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub sort_index: i32,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub red_dot_disable_rule: i32,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub show_in_bag: bool,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub obtained_show_description: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub icon: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub function_desc: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub first_obtain_desc: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub quality: u8,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub tag: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub role_head_icon_circle: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub role_head_icon_large: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub role_head_icon_big: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub card: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub role_head_icon: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub preview_role_card: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub buy_shop_preview_role_card: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub formation_role_card: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub role_stand: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub suit_weapon_skin_color: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub role_obtain_color1: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub role_obtain_color2: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub role_portrait: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub mesh_id: i32,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub ui_mesh_id: i32,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub role_body: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
#[serde(rename = "UiScenePerformanceABP")]
|
||||
pub ui_scene_performance_abp: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub foot_step_state: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub pay_shop_preview_role_texture_path: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub pay_shop_preview_role_texture_bg_path: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub pay_shop_preview_weapon_texture_path: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub pay_shop_preview_buy_role_texture_path: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub pay_shop_preview_buy_role_suit_weapon_texture_path: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub share_texture_path: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub spine_skeleton_data: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub small_spine_atlas: String,
|
||||
}
|
|
@ -14,7 +14,7 @@ serde.workspace = true
|
|||
indexmap = "2.7.1"
|
||||
uuid = { version = "1.11.0", features = ["v4"] }
|
||||
rand = "0.9.0-alpha.2"
|
||||
unreal-niggery-rs = { git = "https://git.xeondev.com/xavo95/unreal-niggery-rs.git" }
|
||||
unreal-niggery-rs = { git = "https://git.xeondev.com/ReversedRoomsMisc/unreal-niggery-rs.git" }
|
||||
widestring = "1.1.0"
|
||||
# Used for debug
|
||||
#serde_json = "1.0.135"
|
||||
|
|
|
@ -19,7 +19,7 @@ load_textmaps = true
|
|||
quadrant_size = 1000000
|
||||
|
||||
[asset_config]
|
||||
asset_url = "https://git.xeondev.com/wickedwaifus/wicked-waifus-data/releases/download/pioneer_2.3.1/bundle.zip"
|
||||
asset_url = "https://git.xeondev.com/wickedwaifus/wicked-waifus-data/releases/download/pioneer_2.4.1/bundle.zip"
|
||||
buffer_size = 268435456
|
||||
|
||||
[default_unlocks]
|
||||
|
|
|
@ -2,12 +2,10 @@ use rand::prelude::IndexedRandom;
|
|||
use rand::Rng;
|
||||
use wicked_waifus_protocol::{ErrorCode, GachaResult, GachaReward};
|
||||
|
||||
use wicked_waifus_data::GachaViewTypeInfoId::{BeginnersChoiceConvene,
|
||||
FeaturedResonatorConvene,
|
||||
FeaturedWeaponConvene,
|
||||
NoviceConvene,
|
||||
StandardResonatorConvene,
|
||||
StandardWeaponConvene,
|
||||
use wicked_waifus_data::GachaViewTypeInfoId::{
|
||||
BeginnersChoiceConvene, FeaturedResonatorConvene, FeaturedWeaponConvene,
|
||||
MultipleChoiceResonatorConvene, MultipleChoiceWeaponConvene, NoviceConvene,
|
||||
StandardResonatorConvene, StandardWeaponConvene,
|
||||
};
|
||||
|
||||
use crate::logic::gacha::pool_info::PoolInfo;
|
||||
|
@ -53,16 +51,23 @@ impl GachaPool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pull<T: Rng>(&mut self,
|
||||
rng: &mut T,
|
||||
player: &mut Player) -> Result<GachaResult, ErrorCode> {
|
||||
pub fn pull<T: Rng>(
|
||||
&mut self,
|
||||
rng: &mut T,
|
||||
player: &mut Player,
|
||||
) -> Result<GachaResult, ErrorCode> {
|
||||
self.check_limits()?;
|
||||
|
||||
let result = if (self.info.pool_type == BeginnersChoiceConvene)
|
||||
&& (self.info.pool_id > 50) && (self.info.pool_id < 60) {
|
||||
&& (self.info.pool_id > 50)
|
||||
&& (self.info.pool_id < 60)
|
||||
{
|
||||
let item_id = self.info.guaranteed_character_id.unwrap();
|
||||
GachaResult {
|
||||
gacha_reward: Some(GachaReward { item_id, item_count: 1 }),
|
||||
gacha_reward: Some(GachaReward {
|
||||
item_id,
|
||||
item_count: 1,
|
||||
}),
|
||||
extra_rewards: self.calculate_extra_rewards(2),
|
||||
transform_rewards: Self::get_transform_rewards(player, item_id),
|
||||
bottom: None,
|
||||
|
@ -84,13 +89,14 @@ impl GachaPool {
|
|||
};
|
||||
item_id
|
||||
}
|
||||
_ => {
|
||||
self.get_random_item(rarity, rng)
|
||||
}
|
||||
_ => self.get_random_item(rarity, rng),
|
||||
};
|
||||
self.update_pity(rarity);
|
||||
GachaResult {
|
||||
gacha_reward: Some(GachaReward { item_id, item_count: 1 }),
|
||||
gacha_reward: Some(GachaReward {
|
||||
item_id,
|
||||
item_count: 1,
|
||||
}),
|
||||
extra_rewards: self.calculate_extra_rewards(rarity),
|
||||
transform_rewards: Self::get_transform_rewards(player, item_id),
|
||||
bottom: None,
|
||||
|
@ -123,15 +129,29 @@ impl GachaPool {
|
|||
|
||||
fn get_random_item(&self, rarity: usize, rng: &mut impl Rng) -> i32 {
|
||||
let items: &[i32] = match rarity {
|
||||
0 => &[21010013, 21020013, 21030013, 21040013, 21050013, 21010023, 21020023, 21030023, 21040023, 21050023, 21010043, 21020043, 21030043, 21040043, 21050043],
|
||||
0 => &[
|
||||
21010013, 21020013, 21030013, 21040013, 21050013, 21010023, 21020023, 21030023,
|
||||
21040023, 21050023, 21010043, 21020043, 21030043, 21040043, 21050043,
|
||||
],
|
||||
1 => match self.info.pool_type {
|
||||
StandardWeaponConvene => &[21010024, 21020024, 21030024, 21040024, 21050024, 21010044, 21020044, 21030044, 21040044, 21050044, 21010064, 21020064, 21030064, 21040064, 21050064],
|
||||
FeaturedResonatorConvene | FeaturedWeaponConvene => &self.info.rate_up_four_star[..],
|
||||
StandardWeaponConvene => &[
|
||||
21010024, 21020024, 21030024, 21040024, 21050024, 21010044, 21020044, 21030044,
|
||||
21040044, 21050044, 21010064, 21020064, 21030064, 21040064, 21050064,
|
||||
],
|
||||
FeaturedResonatorConvene | FeaturedWeaponConvene => {
|
||||
&self.info.rate_up_four_star[..]
|
||||
}
|
||||
_ => &[1303, 1602, 1102, 1204, 1403, 1103, 1402, 1202, 1601],
|
||||
},
|
||||
2 => match self.info.pool_type {
|
||||
NoviceConvene | StandardResonatorConvene => &[1405, 1301, 1503, 1104, 1203],
|
||||
FeaturedResonatorConvene | FeaturedWeaponConvene | StandardWeaponConvene | BeginnersChoiceConvene => &self.info.rate_up_five_star[..],
|
||||
// TODO: Review MultipleChoiceConvene
|
||||
FeaturedResonatorConvene
|
||||
| FeaturedWeaponConvene
|
||||
| StandardWeaponConvene
|
||||
| BeginnersChoiceConvene
|
||||
| MultipleChoiceResonatorConvene
|
||||
| MultipleChoiceWeaponConvene => &self.info.rate_up_five_star[..],
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -154,15 +174,23 @@ impl GachaPool {
|
|||
}
|
||||
|
||||
fn calculate_probabilities(&self) -> [f32; 3] {
|
||||
let mut prob = [self.rates.three_star, self.rates.four_star, self.rates.five_star];
|
||||
let mut prob = [
|
||||
self.rates.three_star,
|
||||
self.rates.four_star,
|
||||
self.rates.five_star,
|
||||
];
|
||||
|
||||
if self.pull_count >= self.info.pity_system.soft_pity_start {
|
||||
let extra_prob = 0.8 + 8.0 * (self.pull_count - self.info.pity_system.soft_pity_start - 1) as f32;
|
||||
let extra_prob =
|
||||
0.8 + 8.0 * (self.pull_count - self.info.pity_system.soft_pity_start - 1) as f32;
|
||||
prob[0] -= extra_prob;
|
||||
prob[2] = extra_prob;
|
||||
}
|
||||
|
||||
match (self.pity_four + 1 >= self.info.pity_system.hard_pity_four, self.pull_count + 1 >= self.info.pity_system.hard_pity_five) {
|
||||
match (
|
||||
self.pity_four + 1 >= self.info.pity_system.hard_pity_four,
|
||||
self.pull_count + 1 >= self.info.pity_system.hard_pity_five,
|
||||
) {
|
||||
(true, _) => [0.0, 100.0, 0.0],
|
||||
(_, true) => [0.0, 0.0, 100.0],
|
||||
_ => prob,
|
||||
|
@ -172,9 +200,9 @@ impl GachaPool {
|
|||
fn determine_rarity(&self, prob: &[f32; 3], rng: &mut impl Rng) -> usize {
|
||||
let roll: f32 = rng.random_range(0.0..100.0);
|
||||
match (roll < prob[2], roll < prob[2] + prob[1]) {
|
||||
(true, _) => 2, // 5-star
|
||||
(_, true) => 1, // 4-star
|
||||
_ => 0, // 3-star
|
||||
(true, _) => 2, // 5-star
|
||||
(_, true) => 1, // 4-star
|
||||
_ => 0, // 3-star
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,18 +234,18 @@ impl GachaPool {
|
|||
}
|
||||
|
||||
/*
|
||||
TODO: update rewards for duplicates
|
||||
TODO: update rewards for duplicates
|
||||
|
||||
4-star duplicate:
|
||||
1st to 6th duplicate: 3 afterglow corals and 1 waveband of that char
|
||||
7th duplicate onwards: 8 afterglow corals
|
||||
will not receive any afterglow corals when you pull a 4-star that you do not already own for the first time.
|
||||
4-star duplicate:
|
||||
1st to 6th duplicate: 3 afterglow corals and 1 waveband of that char
|
||||
7th duplicate onwards: 8 afterglow corals
|
||||
will not receive any afterglow corals when you pull a 4-star that you do not already own for the first time.
|
||||
|
||||
5-star duplicate:
|
||||
1st to 6th duplicate: 15 afterglow corals and 1 waveband of that char
|
||||
7th duplicate onwards: 40 afterglow corals
|
||||
will not receive any afterglow corals when you pull a 5-star that you do not already own for the first time.
|
||||
*/
|
||||
5-star duplicate:
|
||||
1st to 6th duplicate: 15 afterglow corals and 1 waveband of that char
|
||||
7th duplicate onwards: 40 afterglow corals
|
||||
will not receive any afterglow corals when you pull a 5-star that you do not already own for the first time.
|
||||
*/
|
||||
match rarity {
|
||||
2 => rewards.push(GachaReward {
|
||||
item_id: 50004, // afterglow corals
|
||||
|
@ -236,4 +264,4 @@ TODO: update rewards for duplicates
|
|||
pub fn is_active(&self) -> bool {
|
||||
self.info.is_active()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
use std::time::SystemTime;
|
||||
|
||||
use wicked_waifus_data::GachaViewTypeInfoId;
|
||||
use wicked_waifus_data::GachaViewTypeInfoId::{BeginnersChoiceConvene,
|
||||
FeaturedResonatorConvene,
|
||||
FeaturedWeaponConvene,
|
||||
NoviceConvene,
|
||||
StandardResonatorConvene,
|
||||
StandardWeaponConvene,
|
||||
use wicked_waifus_data::GachaViewTypeInfoId::{
|
||||
BeginnersChoiceConvene, FeaturedResonatorConvene, FeaturedWeaponConvene,
|
||||
MultipleChoiceResonatorConvene, MultipleChoiceWeaponConvene, NoviceConvene,
|
||||
StandardResonatorConvene, StandardWeaponConvene,
|
||||
};
|
||||
|
||||
use crate::logic::gacha::category::PoolCategory;
|
||||
|
@ -58,30 +56,37 @@ impl PoolInfo {
|
|||
const NOVICE_GACHA_POOL_RESOURCE: &'static str = "UiItem_NewPlayerGachaPool";
|
||||
const BASE_GACHA_POOL_RESOURCE: &'static str = "UiItem_BaseGachaPool";
|
||||
|
||||
pub(crate) fn new(pool_id: i32,
|
||||
pool_type: GachaViewTypeInfoId,
|
||||
category: PoolCategory,
|
||||
rate_up_five_star: &[i32],
|
||||
rate_up_four_star: &[i32],
|
||||
guaranteed_character_id: Option<i32>) -> Self {
|
||||
pub(crate) fn new(
|
||||
pool_id: i32,
|
||||
pool_type: GachaViewTypeInfoId,
|
||||
category: PoolCategory,
|
||||
rate_up_five_star: &[i32],
|
||||
rate_up_four_star: &[i32],
|
||||
guaranteed_character_id: Option<i32>,
|
||||
) -> Self {
|
||||
let start_time = SystemTime::now();
|
||||
let end_time = match category {
|
||||
PoolCategory::Permanent => None,
|
||||
PoolCategory::Event(duration) | PoolCategory::Special(duration) => Some(start_time + duration),
|
||||
PoolCategory::Event(duration) | PoolCategory::Special(duration) => {
|
||||
Some(start_time + duration)
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Make objects const 50001, 50002, 50005, 50006 or check if gacha consumes exist
|
||||
let (item_id, daily_limit, total_limit, pity_system) = match pool_type {
|
||||
NoviceConvene => (50001, 0, 50, PitySystem::novice()),
|
||||
StandardResonatorConvene | StandardWeaponConvene => (50001, 0, 80, PitySystem::default()),
|
||||
FeaturedResonatorConvene => (50002, 0, 0, PitySystem::default()),
|
||||
FeaturedWeaponConvene => (50005, 0, 0, PitySystem::default()),
|
||||
BeginnersChoiceConvene => {
|
||||
match pool_id {
|
||||
51..56 => (50006, 0, 1, PitySystem::default()),
|
||||
_ => (50001, 0, 80, PitySystem::default()),
|
||||
}
|
||||
StandardResonatorConvene | StandardWeaponConvene => {
|
||||
(50001, 0, 80, PitySystem::default())
|
||||
}
|
||||
// TODO: Review MultipleChoiceConvene
|
||||
FeaturedResonatorConvene
|
||||
| MultipleChoiceResonatorConvene
|
||||
| MultipleChoiceWeaponConvene => (50002, 0, 0, PitySystem::default()),
|
||||
FeaturedWeaponConvene => (50005, 0, 0, PitySystem::default()),
|
||||
BeginnersChoiceConvene => match pool_id {
|
||||
51..56 => (50006, 0, 1, PitySystem::default()),
|
||||
_ => (50001, 0, 80, PitySystem::default()),
|
||||
},
|
||||
};
|
||||
|
||||
Self {
|
||||
|
|
|
@ -5,12 +5,10 @@ use rand::prelude::StdRng;
|
|||
use rand::SeedableRng;
|
||||
|
||||
use wicked_waifus_data::gacha_view_info_data;
|
||||
use wicked_waifus_data::GachaViewTypeInfoId::{BeginnersChoiceConvene,
|
||||
FeaturedResonatorConvene,
|
||||
FeaturedWeaponConvene,
|
||||
NoviceConvene,
|
||||
StandardResonatorConvene,
|
||||
StandardWeaponConvene,
|
||||
use wicked_waifus_data::GachaViewTypeInfoId::{
|
||||
BeginnersChoiceConvene, FeaturedResonatorConvene, FeaturedWeaponConvene,
|
||||
MultipleChoiceResonatorConvene, MultipleChoiceWeaponConvene, NoviceConvene,
|
||||
StandardResonatorConvene, StandardWeaponConvene,
|
||||
};
|
||||
use wicked_waifus_protocol::{ErrorCode, GachaResult};
|
||||
|
||||
|
@ -40,29 +38,48 @@ impl GachaService {
|
|||
|
||||
for element in gacha_view_info_data::iter() {
|
||||
let duration = match element.r#type {
|
||||
NoviceConvene | StandardResonatorConvene | StandardWeaponConvene => PoolCategory::Permanent,
|
||||
FeaturedResonatorConvene | FeaturedWeaponConvene => PoolCategory::Event(Self::THREE_WEEKS),
|
||||
NoviceConvene | StandardResonatorConvene | StandardWeaponConvene => {
|
||||
PoolCategory::Permanent
|
||||
}
|
||||
// TODO: Review MultipleChoiceConvene
|
||||
FeaturedResonatorConvene
|
||||
| FeaturedWeaponConvene
|
||||
| MultipleChoiceResonatorConvene
|
||||
| MultipleChoiceWeaponConvene => PoolCategory::Event(Self::THREE_WEEKS),
|
||||
BeginnersChoiceConvene => match element.id {
|
||||
51..56 => PoolCategory::Special(Self::ONE_WEEK),
|
||||
_ => PoolCategory::Permanent,
|
||||
},
|
||||
};
|
||||
let guaranteed = if (element.show_id_list.len() > 0) && (element.r#type == FeaturedResonatorConvene) {
|
||||
let guaranteed = if (element.show_id_list.len() > 0)
|
||||
&& (element.r#type == FeaturedResonatorConvene)
|
||||
{
|
||||
Some(element.show_id_list[0])
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let info = PoolInfo::new(element.id, element.r#type, duration, &element.up_list[..], &element.show_id_list[..], guaranteed);
|
||||
let info = PoolInfo::new(
|
||||
element.id,
|
||||
element.r#type,
|
||||
duration,
|
||||
&element.up_list[..],
|
||||
&element.show_id_list[..],
|
||||
guaranteed,
|
||||
);
|
||||
pools.insert(element.id, GachaPool::new(info));
|
||||
}
|
||||
pools
|
||||
}
|
||||
|
||||
pub fn pull(&mut self,
|
||||
player: &mut Player,
|
||||
pool_id: i32,
|
||||
times: i32) -> Result<Vec<GachaResult>, ErrorCode> {
|
||||
let pool = self.pools.get_mut(&pool_id)
|
||||
pub fn pull(
|
||||
&mut self,
|
||||
player: &mut Player,
|
||||
pool_id: i32,
|
||||
times: i32,
|
||||
) -> Result<Vec<GachaResult>, ErrorCode> {
|
||||
let pool = self
|
||||
.pools
|
||||
.get_mut(&pool_id)
|
||||
.ok_or(ErrorCode::ErrGachaPoolConfigNotFound)?;
|
||||
|
||||
if !pool.is_active() {
|
||||
|
@ -83,7 +100,8 @@ impl GachaService {
|
|||
}
|
||||
|
||||
pub fn get_active_pools(&self) -> Vec<(i32, &GachaPool)> {
|
||||
self.pools.iter()
|
||||
self.pools
|
||||
.iter()
|
||||
.filter(|(_, pool)| pool.is_active())
|
||||
.map(|(id, pool)| (*id, pool))
|
||||
.collect()
|
||||
|
@ -91,8 +109,9 @@ impl GachaService {
|
|||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_all_pools(&self) -> Vec<(i32, &PoolInfo)> {
|
||||
self.pools.iter()
|
||||
self.pools
|
||||
.iter()
|
||||
.map(|(id, pool)| (*id, &pool.info))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,12 @@ use wicked_waifus_protocol::combat_message::{
|
|||
combat_send_data, CombatNotifyData, CombatReceiveData, CombatRequestData, CombatResponseData,
|
||||
CombatSendPackRequest, CombatSendPackResponse,
|
||||
};
|
||||
use wicked_waifus_protocol::{AttributeChangedNotify, CombatCommon, DamageExecuteRequest, DamageExecuteResponse, EAttributeType, ERemoveEntityType, EntityRemoveNotify, ErrorCode, GameplayAttributeData, SwitchRoleRequest, SwitchRoleResponse};
|
||||
use wicked_waifus_protocol::{
|
||||
AttributeChangedNotify, CombatCommon, DErrorResult, DamageExecuteRequest,
|
||||
DamageExecuteResponse, EAttributeType, ERemoveEntityType, ErrorCode,
|
||||
FsmConditionPassRequest, FsmConditionPassResponse, GameplayAttributeData,
|
||||
PlayerBattleStateChangeNotify, SwitchRoleRequest, SwitchRoleResponse,
|
||||
};
|
||||
|
||||
use wicked_waifus_data::damage_data;
|
||||
|
||||
|
@ -55,6 +60,9 @@ pub fn on_combat_message_combat_send_pack_request(
|
|||
combat_request_data::Message::SwitchRoleRequest(ref request) => {
|
||||
handle_switch_role_request(player, request_data, request, response);
|
||||
}
|
||||
combat_request_data::Message::FsmConditionPassRequest(ref request) => {
|
||||
handle_fsm_condition_request(player, request_data, request, response);
|
||||
}
|
||||
combat_request_data::Message::DamageExecuteRequest(ref request) => {
|
||||
handle_damage_execute_request(player, request_data, request, response);
|
||||
}
|
||||
|
@ -117,16 +125,20 @@ fn handle_damage_execute_request(
|
|||
.unwrap();
|
||||
if let Ok(related_attribute) = EAttributeType::try_from(damage_data.related_property) {
|
||||
if let Some((value, _)) = attribute.attr_map.get(&related_attribute) {
|
||||
if let Some(&rate_lv) = damage_data.rate_lv.iter().find(|&lvl| *lvl == request.skill_level) {
|
||||
if let Some(&rate_lv) = damage_data
|
||||
.rate_lv
|
||||
.iter()
|
||||
.find(|&lvl| *lvl == request.skill_level)
|
||||
{
|
||||
let hardness_lv = damage_data.hardness_lv[0];
|
||||
tracing::info!(
|
||||
"atk: {}, damage_id: {}, role_id: {}, rate_lv: {}, hardness_lv: {}",
|
||||
value,
|
||||
request.damage_id,
|
||||
config_id,
|
||||
rate_lv,
|
||||
hardness_lv
|
||||
);
|
||||
"atk: {}, damage_id: {}, role_id: {}, rate_lv: {}, hardness_lv: {}",
|
||||
value,
|
||||
request.damage_id,
|
||||
config_id,
|
||||
rate_lv,
|
||||
hardness_lv
|
||||
);
|
||||
damage = if hardness_lv == 0 || rate_lv <= 0 {
|
||||
1
|
||||
} else {
|
||||
|
@ -173,9 +185,58 @@ fn handle_damage_execute_request(
|
|||
}),
|
||||
));
|
||||
if updated_value == 0 {
|
||||
world_util::remove_entity(player, request.target_entity_id, ERemoveEntityType::HpIsZero);
|
||||
world_util::remove_entity(
|
||||
player,
|
||||
request.target_entity_id,
|
||||
ERemoveEntityType::HpIsZero,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
response.error_code = ErrorCode::Success.into();
|
||||
}
|
||||
|
||||
fn handle_battle(
|
||||
player: &mut Player,
|
||||
combat_request: &CombatRequestData,
|
||||
response: &mut CombatSendPackResponse,
|
||||
condition: bool,
|
||||
) {
|
||||
let receive_pack = response
|
||||
.receive_pack_notify
|
||||
.get_or_insert_with(Default::default);
|
||||
|
||||
receive_pack.data.push(create_combat_notify(
|
||||
combat_request.combat_common.unwrap(),
|
||||
combat_notify_data::Message::PlayerBattleStateChangeNotify(PlayerBattleStateChangeNotify {
|
||||
player_id: player.basic_info.id,
|
||||
|
||||
in_battle: condition,
|
||||
}),
|
||||
));
|
||||
}
|
||||
|
||||
fn handle_fsm_condition_request(
|
||||
player: &mut Player,
|
||||
combat_request: &CombatRequestData,
|
||||
request: &FsmConditionPassRequest,
|
||||
response: &mut CombatSendPackResponse,
|
||||
) {
|
||||
let receive_pack = response
|
||||
.receive_pack_notify
|
||||
.get_or_insert_with(Default::default);
|
||||
|
||||
receive_pack.data.push(create_combat_response(
|
||||
combat_request,
|
||||
combat_response_data::Message::FsmConditionPassResponse(FsmConditionPassResponse {
|
||||
fsm_id: request.fsm_id,
|
||||
|
||||
error: Some(DErrorResult {
|
||||
error_code: ErrorCode::Success.into(),
|
||||
|
||||
error_params: Vec::new(),
|
||||
}),
|
||||
}),
|
||||
));
|
||||
handle_battle(player, combat_request, response, true);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ dummy_handler! {
|
|||
TowerSeasonUpdate;
|
||||
ValidTimeItem;
|
||||
PayShopInfo;
|
||||
PayInfo;
|
||||
InitRange;
|
||||
Activity;
|
||||
BattlePass;
|
||||
|
|
|
@ -216,6 +216,7 @@ handle_request! {
|
|||
PayShopInfo;
|
||||
// PayShopUpdate;
|
||||
// MonthCard;
|
||||
PayInfo;
|
||||
|
||||
// Skill (TODO: Review this on_..., port some from go)
|
||||
VisionExploreSkillSet;
|
||||
|
|
|
@ -72,5 +72,7 @@ pub fn on_unlock_role_skin_list_request(
|
|||
response: &mut UnlockRoleSkinListResponse,
|
||||
) {
|
||||
// TODO: port this from golang
|
||||
response.phantom_skin_list = vec![];
|
||||
response.role_skin_list = wicked_waifus_data::role_skin_data::iter()
|
||||
.map(|data| data.id)
|
||||
.collect::<Vec<_>>();
|
||||
}
|
|
@ -8,7 +8,8 @@ pub struct RoleFormation {
|
|||
}
|
||||
|
||||
// Will be updated every version
|
||||
const DEFAULT_FORMATION: &[i32] = &[5101, 1407, 1507];
|
||||
// const DEFAULT_FORMATION: &[i32] = &[5101, 1407, 1507];
|
||||
const DEFAULT_FORMATION: &[i32] = &[1205, 1207, 1409];
|
||||
|
||||
impl RoleFormation {
|
||||
pub fn default_roles() -> &'static [i32] {
|
||||
|
|
|
@ -43,6 +43,7 @@ pub fn perform_action(player: &mut Player,
|
|||
Action::TeleportDungeon(action) => unimplemented_action! { action },
|
||||
Action::DestroySelf(action) => unimplemented_action! { action },
|
||||
Action::CameraLookAt(action) => unimplemented_action! { action },
|
||||
Action::StopCameraLookAt(action) => unimplemented_action! { action },
|
||||
Action::EnterOrbitalCamera(action) => unimplemented_action! { action },
|
||||
Action::ExitOrbitalCamera(action) => unimplemented_action! { action },
|
||||
Action::SendAiEvent(action) => unimplemented_action! { action },
|
||||
|
@ -196,6 +197,17 @@ pub fn perform_action(player: &mut Player,
|
|||
Action::GetRewardByInteract(action) => unimplemented_action! { action },
|
||||
Action::OpenQte(action) => unimplemented_action! { action },
|
||||
Action::ActiveAntiGravitySafePoint(action) => unimplemented_action! { action },
|
||||
Action::BvbPlayDialog(action) => unimplemented_action! { action },
|
||||
Action::BvbSendSystemEvent(action) => unimplemented_action! { action },
|
||||
Action::BvbSendAiEvent(action) => unimplemented_action! { action },
|
||||
Action::BvbPlayerOperationConstraint(action) => unimplemented_action! { action },
|
||||
Action::ExecClientBattleAction(action) => unimplemented_action! { action },
|
||||
Action::TriggerSpecificScanEffect(action) => unimplemented_action! { action },
|
||||
Action::SetActorVar(action) => unimplemented_action! { action },
|
||||
Action::RunActorCustomEvent(action) => unimplemented_action! { action },
|
||||
Action::StopUiScreenEffect(action) => unimplemented_action! { action },
|
||||
Action::StopNewMoveWithSpline(action) => unimplemented_action! { action },
|
||||
Action::RequestSystemFunction(action) => unimplemented_action! { action },
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,11 @@ pub fn check_condition(player: &Player,
|
|||
Condition::CheckEntityGravityDirection(condition) => unimplemented_condition! { condition },
|
||||
Condition::CheckTeleControlState(condition) => unimplemented_condition! { condition },
|
||||
Condition::CheckEntityReward(condition) => unimplemented_condition! { condition },
|
||||
Condition::CheckIsGramophonePlayingMusic(condition) => unimplemented_condition! { condition },
|
||||
Condition::CheckBVBEvent(condition) => unimplemented_condition! { condition },
|
||||
Condition::FinishBvbChallenge(condition) => unimplemented_condition! { condition },
|
||||
Condition::CompareActorVar(condition) => unimplemented_condition! { condition },
|
||||
Condition::CheckDangoCultivationProgress(condition) => unimplemented_condition! { condition },
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,21 +62,6 @@ impl_base_prop!(
|
|||
damage_reduce_element4,
|
||||
damage_reduce_element5,
|
||||
damage_reduce_element6,
|
||||
reaction_change1,
|
||||
reaction_change2,
|
||||
reaction_change3,
|
||||
reaction_change4,
|
||||
reaction_change5,
|
||||
reaction_change6,
|
||||
reaction_change7,
|
||||
reaction_change8,
|
||||
reaction_change9,
|
||||
reaction_change10,
|
||||
reaction_change11,
|
||||
reaction_change12,
|
||||
reaction_change13,
|
||||
reaction_change14,
|
||||
reaction_change15,
|
||||
energy_max,
|
||||
energy,
|
||||
special_energy_1_max,
|
||||
|
|
|
@ -4,14 +4,19 @@ edition = "2021"
|
|||
version.workspace = true
|
||||
|
||||
[features]
|
||||
# If supporting clients < 2.0 please use "--no-default-features"
|
||||
# (additonally you could add "-F ack-cmd-conv" but it's currently a NO-OP)
|
||||
default = ["ack-cmd-conv"]
|
||||
debug-msg = []
|
||||
ack-cmd-conv = []
|
||||
ack-cmd-conv-crc-mtu = []
|
||||
|
||||
[dependencies]
|
||||
# Framework
|
||||
tokio.workspace = true
|
||||
|
||||
# Networking
|
||||
kcp = { workspace = true, features = ["tokio"] }
|
||||
kcp = { git = "https://git.xeondev.com/ReversedRoomsMisc/kcp-rs.git", features = ["wuthering-waves-old", "tokio"] }
|
||||
|
||||
# Serialization
|
||||
serde.workspace = true
|
||||
|
|
|
@ -2,6 +2,7 @@ service_id = 1
|
|||
|
||||
[network]
|
||||
kcp_port = 7777
|
||||
kcp_crc = false
|
||||
|
||||
[protokey]
|
||||
builtin_encryption_msg_id = [111, 112]
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
[package]
|
||||
name = "kcp"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[features]
|
||||
fastack-conserve = []
|
||||
tokio = ["dep:tokio"]
|
||||
|
||||
[dependencies]
|
||||
bytes = "1.6.0"
|
||||
log = "0.4.21"
|
||||
thiserror = "1.0.58"
|
||||
tokio = { version = "1.37.0", optional = true, features = ["io-util"] }
|
||||
|
||||
[dev-dependencies]
|
||||
time = "0.3.34"
|
||||
rand = "0.8.5"
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
use std::{
|
||||
error::Error as StdError,
|
||||
io::{self, ErrorKind},
|
||||
};
|
||||
|
||||
/// KCP protocol errors
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("conv inconsistent, expected {0}, found {1}")]
|
||||
ConvInconsistent(u32, u32),
|
||||
#[error("invalid mtu {0}")]
|
||||
InvalidMtu(usize),
|
||||
#[error("invalid segment size {0}")]
|
||||
InvalidSegmentSize(usize),
|
||||
#[error("invalid segment data size, expected {0}, found {1}")]
|
||||
InvalidSegmentDataSize(usize, usize),
|
||||
#[error("{0}")]
|
||||
IoError(
|
||||
#[from]
|
||||
#[source]
|
||||
io::Error,
|
||||
),
|
||||
#[error("need to call update() once")]
|
||||
NeedUpdate,
|
||||
#[error("recv queue is empty")]
|
||||
RecvQueueEmpty,
|
||||
#[error("expecting fragment")]
|
||||
ExpectingFragment,
|
||||
#[error("command {0} is not supported")]
|
||||
UnsupportedCmd(u8),
|
||||
#[error("user's send buffer is too big")]
|
||||
UserBufTooBig,
|
||||
#[error("user's recv buffer is too small")]
|
||||
UserBufTooSmall,
|
||||
}
|
||||
|
||||
fn make_io_error<T>(kind: ErrorKind, msg: T) -> io::Error
|
||||
where
|
||||
T: Into<Box<dyn StdError + Send + Sync>>,
|
||||
{
|
||||
io::Error::new(kind, msg)
|
||||
}
|
||||
|
||||
impl From<Error> for io::Error {
|
||||
fn from(err: Error) -> Self {
|
||||
let kind = match err {
|
||||
Error::IoError(err) => return err,
|
||||
Error::RecvQueueEmpty | Error::ExpectingFragment => ErrorKind::WouldBlock,
|
||||
_ => ErrorKind::Other,
|
||||
};
|
||||
|
||||
make_io_error(kind, err)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,17 +0,0 @@
|
|||
extern crate bytes;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
mod error;
|
||||
mod kcp;
|
||||
|
||||
/// The `KCP` prelude
|
||||
pub mod prelude {
|
||||
pub use super::{get_conv, Kcp, KCP_OVERHEAD};
|
||||
}
|
||||
|
||||
pub use error::Error;
|
||||
pub use kcp::{get_conv, get_sn, set_conv, Kcp, KCP_OVERHEAD};
|
||||
|
||||
/// KCP result
|
||||
pub type KcpResult<T> = Result<T, Error>;
|
|
@ -17,6 +17,7 @@ pub struct ServerConfig {
|
|||
#[derive(Deserialize)]
|
||||
pub struct NetworkSettings {
|
||||
pub kcp_port: u16,
|
||||
pub kcp_crc: Option<bool>
|
||||
}
|
||||
|
||||
impl TomlConfig for ServerConfig {
|
||||
|
|
|
@ -38,6 +38,7 @@ async fn main() -> Result<()> {
|
|||
let server = UdpServer::new(
|
||||
&CONFIG.network,
|
||||
PROTOKEY_HELPER.get_or_init(|| protokey_helper),
|
||||
CONFIG.network.kcp_crc.unwrap_or(false),
|
||||
&SESSION_MGR,
|
||||
Arc::new(database),
|
||||
)
|
||||
|
|
|
@ -41,6 +41,7 @@ impl Session {
|
|||
addr: SocketAddr,
|
||||
socket: Arc<UdpSocket>,
|
||||
helper: &'static ServerProtoKeyHelper,
|
||||
use_crc: bool,
|
||||
database: Arc<PgPool>,
|
||||
) -> Self {
|
||||
let output = SessionOutput {
|
||||
|
@ -51,7 +52,7 @@ impl Session {
|
|||
let cur_time_ms = time_util::unix_timestamp_ms();
|
||||
Self {
|
||||
protokey_helper: helper,
|
||||
kcp: Kcp::new(conv_id, true, output),
|
||||
kcp: Kcp::new(conv_id, 0, use_crc, 0, true, output),
|
||||
decoder: LengthFieldBasedDecoder::new(),
|
||||
start_time_ms: cur_time_ms,
|
||||
last_heartbeat_time_ms: cur_time_ms,
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::{config::NetworkSettings, session::Session, session::SessionManager};
|
|||
pub struct UdpServer {
|
||||
socket: Arc<UdpSocket>,
|
||||
protokey_helper: &'static ServerProtoKeyHelper,
|
||||
kcp_use_crc: bool,
|
||||
session_mgr: &'static SessionManager,
|
||||
db: Arc<PgPool>,
|
||||
}
|
||||
|
@ -21,6 +22,7 @@ impl UdpServer {
|
|||
pub async fn new(
|
||||
network_settings: &'static NetworkSettings,
|
||||
protokey_helper: &'static ServerProtoKeyHelper,
|
||||
kcp_use_crc: bool,
|
||||
session_mgr: &'static SessionManager,
|
||||
db: Arc<PgPool>,
|
||||
) -> Result<Self, tokio::io::Error> {
|
||||
|
@ -29,6 +31,7 @@ impl UdpServer {
|
|||
Ok(Self {
|
||||
socket: Arc::new(socket),
|
||||
protokey_helper,
|
||||
kcp_use_crc,
|
||||
session_mgr,
|
||||
db,
|
||||
})
|
||||
|
@ -65,6 +68,7 @@ impl UdpServer {
|
|||
addr,
|
||||
self.socket.clone(),
|
||||
self.protokey_helper,
|
||||
self.kcp_use_crc,
|
||||
self.db.clone(),
|
||||
);
|
||||
self.session_mgr.add(conv_id, session);
|
||||
|
@ -72,6 +76,11 @@ impl UdpServer {
|
|||
let mut ack = Vec::with_capacity(5);
|
||||
ack.push(Self::CMD_ACK);
|
||||
ack.extend(conv_id.to_le_bytes());
|
||||
#[cfg(feature = "ack-cmd-conv-crc-mtu")]
|
||||
{
|
||||
ack.extend((self.kcp_use_crc as u32).to_le_bytes());
|
||||
ack.extend(Self::MTU.to_le_bytes());
|
||||
}
|
||||
let _ = self.socket.send_to(&ack, addr).await;
|
||||
|
||||
tracing::debug!("new connection from {addr}, conv_id: {conv_id}");
|
||||
|
|
Loading…
Reference in a new issue