forked from wickedwaifus/wicked-waifus-rs
Compare commits
11 commits
4d9035b663
...
5e68a19066
Author | SHA1 | Date | |
---|---|---|---|
|
5e68a19066 | ||
|
f372bc9914 | ||
|
1480baae70 | ||
|
3adf8cdc19 | ||
|
e5211c759a | ||
|
af681c8f15 | ||
|
ce265b89ca | ||
|
b3c5e03786 | ||
|
5f4cac9da9 | ||
|
e9ea58bf75 | ||
3552b7a431 |
50 changed files with 1801 additions and 2613 deletions
30
.zed/settings.json
Normal file
30
.zed/settings.json
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Folder-specific settings
|
||||||
|
//
|
||||||
|
// For a full list of overridable settings, and general information on folder-specific settings,
|
||||||
|
// see the documentation: https://zed.dev/docs/configuring-zed#settings-files
|
||||||
|
{
|
||||||
|
"lsp": {
|
||||||
|
"rust-analyzer": {
|
||||||
|
"initialization_options": {
|
||||||
|
// get more cargo-less diagnostics from rust-analyzer,
|
||||||
|
// which might include false-positives (those can be turned off by their names)
|
||||||
|
"diagnostics": {
|
||||||
|
"experimental": {
|
||||||
|
"enable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// To disable the checking entirely
|
||||||
|
// (ignores all cargo and check settings below)
|
||||||
|
"checkOnSave": false,
|
||||||
|
// To check the `lib` target only.
|
||||||
|
"cargo": {
|
||||||
|
"allTargets": false
|
||||||
|
},
|
||||||
|
// Use `-p` instead of `--workspace` for cargo check
|
||||||
|
"check": {
|
||||||
|
"workspace": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
461
Cargo.lock
generated
461
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
[workspace]
|
[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"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
|
@ -46,7 +46,6 @@ tracing = "0.1.40"
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
|
|
||||||
# Internal
|
# Internal
|
||||||
kcp = { path = "wicked-waifus-gateway-server/kcp" }
|
|
||||||
wicked-waifus-asset-updater = { path = "wicked-waifus-asset-updater" }
|
wicked-waifus-asset-updater = { path = "wicked-waifus-asset-updater" }
|
||||||
wicked-waifus-commons = { path = "wicked-waifus-commons" }
|
wicked-waifus-commons = { path = "wicked-waifus-commons" }
|
||||||
wicked-waifus-http = { path = "wicked-waifus-http" }
|
wicked-waifus-http = { path = "wicked-waifus-http" }
|
||||||
|
|
|
@ -11,5 +11,5 @@ serve_dir_path = "data/assets/config-server"
|
||||||
|
|
||||||
[asset_config]
|
[asset_config]
|
||||||
repository_url = "https://git.xeondev.com/wickedwaifus/wicked-waifus-config-server-files.git"
|
repository_url = "https://git.xeondev.com/wickedwaifus/wicked-waifus-config-server-files.git"
|
||||||
reference = "8f109f2724"
|
reference = "f088e91db3"
|
||||||
discard_local_changes = true
|
discard_local_changes = true
|
|
@ -47,21 +47,6 @@ pub struct BasePropertyData {
|
||||||
pub damage_reduce_element4: i32,
|
pub damage_reduce_element4: i32,
|
||||||
pub damage_reduce_element5: i32,
|
pub damage_reduce_element5: i32,
|
||||||
pub damage_reduce_element6: 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_max: i32,
|
||||||
pub energy: i32,
|
pub energy: i32,
|
||||||
pub special_energy_1_max: i32,
|
pub special_energy_1_max: i32,
|
||||||
|
|
|
@ -138,6 +138,7 @@ json_data! {
|
||||||
LevelPlayNodeData;
|
LevelPlayNodeData;
|
||||||
LivenessTask;
|
LivenessTask;
|
||||||
LordGym;
|
LordGym;
|
||||||
|
ModelConfigPreload;
|
||||||
MonsterDetection;
|
MonsterDetection;
|
||||||
MonsterPropertyGrowth;
|
MonsterPropertyGrowth;
|
||||||
Motion;
|
Motion;
|
||||||
|
@ -149,6 +150,7 @@ json_data! {
|
||||||
RoleInfo;
|
RoleInfo;
|
||||||
RoleLevelConsume;
|
RoleLevelConsume;
|
||||||
RolePropertyGrowth;
|
RolePropertyGrowth;
|
||||||
|
RoleSkin;
|
||||||
SilentAreaDetection;
|
SilentAreaDetection;
|
||||||
SynthesisFormula;
|
SynthesisFormula;
|
||||||
Teleporter;
|
Teleporter;
|
||||||
|
|
|
@ -68,6 +68,8 @@ pub enum GachaViewTypeInfoId {
|
||||||
StandardResonatorConvene = 4,
|
StandardResonatorConvene = 4,
|
||||||
StandardWeaponConvene = 5,
|
StandardWeaponConvene = 5,
|
||||||
BeginnersChoiceConvene = 6,
|
BeginnersChoiceConvene = 6,
|
||||||
|
MultipleChoiceResonatorConvene = 7,
|
||||||
|
MultipleChoiceWeaponConvene = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
@ -120,6 +122,7 @@ pub enum EntityType {
|
||||||
ControlConnector,
|
ControlConnector,
|
||||||
ConveyorBelt,
|
ConveyorBelt,
|
||||||
CookTool,
|
CookTool,
|
||||||
|
CurveControlDestructible,
|
||||||
CustomAoiEditor,
|
CustomAoiEditor,
|
||||||
Destructible,
|
Destructible,
|
||||||
DestructibleControl,
|
DestructibleControl,
|
||||||
|
@ -132,6 +135,7 @@ pub enum EntityType {
|
||||||
DynamicPortalCreater,
|
DynamicPortalCreater,
|
||||||
EffectArea,
|
EffectArea,
|
||||||
EnrichmentArea,
|
EnrichmentArea,
|
||||||
|
EntityBatchRefresh,
|
||||||
EntityBundle,
|
EntityBundle,
|
||||||
EntityList,
|
EntityList,
|
||||||
EntityPackage,
|
EntityPackage,
|
||||||
|
@ -163,6 +167,7 @@ pub enum EntityType {
|
||||||
LevelPlay,
|
LevelPlay,
|
||||||
LevelPlayReward,
|
LevelPlayReward,
|
||||||
LevelQteTrigger,
|
LevelQteTrigger,
|
||||||
|
LevelSeqTrigger,
|
||||||
LevitateMagnet,
|
LevitateMagnet,
|
||||||
LifePointCenter,
|
LifePointCenter,
|
||||||
Lift,
|
Lift,
|
||||||
|
@ -202,16 +207,19 @@ pub enum EntityType {
|
||||||
SimpleInteract,
|
SimpleInteract,
|
||||||
SimpleNPc,
|
SimpleNPc,
|
||||||
SkyboxTrigger,
|
SkyboxTrigger,
|
||||||
|
SlideRail,
|
||||||
SoundBox,
|
SoundBox,
|
||||||
SpawnMonster,
|
SpawnMonster,
|
||||||
SpawnPasserbyNpc,
|
SpawnPasserbyNpc,
|
||||||
Spline,
|
Spline,
|
||||||
|
SplineRange,
|
||||||
SummonGongduolaPoint,
|
SummonGongduolaPoint,
|
||||||
StateSceneItem,
|
StateSceneItem,
|
||||||
StateTrigger,
|
StateTrigger,
|
||||||
StatueFoundation,
|
StatueFoundation,
|
||||||
SuiGuangHook,
|
SuiGuangHook,
|
||||||
TargetGear,
|
TargetGear,
|
||||||
|
TargetGear2,
|
||||||
TargetGearGroup,
|
TargetGearGroup,
|
||||||
TargetGearGroup2,
|
TargetGearGroup2,
|
||||||
TargetGearPro,
|
TargetGearPro,
|
||||||
|
@ -220,6 +228,7 @@ pub enum EntityType {
|
||||||
TeleControl3,
|
TeleControl3,
|
||||||
TeleControlGroup,
|
TeleControlGroup,
|
||||||
Teleporter,
|
Teleporter,
|
||||||
|
TemplateEntitySpawner,
|
||||||
TemporaryTeleporter,
|
TemporaryTeleporter,
|
||||||
TimedStrikeDevice,
|
TimedStrikeDevice,
|
||||||
TimelineTrackController,
|
TimelineTrackController,
|
||||||
|
|
26
wicked-waifus-data/src/model_config_preload.rs
Normal file
26
wicked-waifus-data/src/model_config_preload.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
pub struct ModelConfigPreloadData {
|
||||||
|
pub id: i32,
|
||||||
|
pub actor_class_path: String,
|
||||||
|
#[cfg(feature = "strict_json_fields")]
|
||||||
|
pub actor_class: Vec<String>,
|
||||||
|
#[cfg(feature = "strict_json_fields")]
|
||||||
|
pub animations: Vec<String>,
|
||||||
|
#[cfg(feature = "strict_json_fields")]
|
||||||
|
pub effects: Vec<String>,
|
||||||
|
#[cfg(feature = "strict_json_fields")]
|
||||||
|
pub audios: Vec<String>,
|
||||||
|
#[cfg(feature = "strict_json_fields")]
|
||||||
|
pub meshes: Vec<String>,
|
||||||
|
#[cfg(feature = "strict_json_fields")]
|
||||||
|
pub materials: Vec<String>,
|
||||||
|
#[cfg(feature = "strict_json_fields")]
|
||||||
|
pub animation_blueprints: Vec<String>,
|
||||||
|
#[cfg(feature = "strict_json_fields")]
|
||||||
|
pub others: Vec<String>,
|
||||||
|
|
||||||
|
}
|
|
@ -217,6 +217,15 @@ pub struct NodeDataDetailAction {
|
||||||
pub actions: Vec<Action>,
|
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)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||||
#[serde(rename_all = "PascalCase")]
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
@ -258,6 +267,7 @@ pub enum NodeDataDetail {
|
||||||
Repeater(NodeDataDetailRepeater),
|
Repeater(NodeDataDetailRepeater),
|
||||||
Condition(NodeDataDetailCondition),
|
Condition(NodeDataDetailCondition),
|
||||||
Action(NodeDataDetailAction),
|
Action(NodeDataDetailAction),
|
||||||
|
ActionWithResult(NodeDataDetailActionWithResult),
|
||||||
QuestSucceed(NodeDataDetailQuestSucceed),
|
QuestSucceed(NodeDataDetailQuestSucceed),
|
||||||
QuestFailed(NodeDataDetailQuestFailed),
|
QuestFailed(NodeDataDetailQuestFailed),
|
||||||
AlwaysFalse(NodeDataDetailAlways),
|
AlwaysFalse(NodeDataDetailAlways),
|
||||||
|
|
|
@ -196,7 +196,8 @@ pub enum LeisureInteractOption {
|
||||||
FailurePose,
|
FailurePose,
|
||||||
GameplayPose1,
|
GameplayPose1,
|
||||||
GameplayPose2,
|
GameplayPose2,
|
||||||
GameplayPose3
|
GameplayPose3,
|
||||||
|
FaithJump
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
@ -508,6 +509,11 @@ pub struct CameraLookAt {
|
||||||
pub camera_pos: Option<Point>,
|
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)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||||
#[serde(rename_all = "PascalCase")]
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
@ -2257,6 +2263,94 @@ pub struct ActiveAntiGravitySafePoint {
|
||||||
pub config: serde_json::Value,
|
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)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
#[serde(tag = "Name")]
|
#[serde(tag = "Name")]
|
||||||
pub enum Action {
|
pub enum Action {
|
||||||
|
@ -2279,6 +2373,7 @@ pub enum Action {
|
||||||
TeleportDungeon(ActionFields<TeleportDungeon>),
|
TeleportDungeon(ActionFields<TeleportDungeon>),
|
||||||
DestroySelf(ActionFields<DestroySelf>),
|
DestroySelf(ActionFields<DestroySelf>),
|
||||||
CameraLookAt(ActionFields<CameraLookAt>),
|
CameraLookAt(ActionFields<CameraLookAt>),
|
||||||
|
StopCameraLookAt(ActionFields<StopCameraLookAt>),
|
||||||
EnterOrbitalCamera(ActionFields<EnterOrbitalCamera>),
|
EnterOrbitalCamera(ActionFields<EnterOrbitalCamera>),
|
||||||
ExitOrbitalCamera(ActionFields<ExitOrbitalCamera>),
|
ExitOrbitalCamera(ActionFields<ExitOrbitalCamera>),
|
||||||
SendAiEvent(ActionFields<SendAiEvent>),
|
SendAiEvent(ActionFields<SendAiEvent>),
|
||||||
|
@ -2432,6 +2527,17 @@ pub enum Action {
|
||||||
GetRewardByInteract(ActionFields<GetRewardByInteract>),
|
GetRewardByInteract(ActionFields<GetRewardByInteract>),
|
||||||
OpenQte(ActionFields<OpenQte>),
|
OpenQte(ActionFields<OpenQte>),
|
||||||
ActiveAntiGravitySafePoint(ActionFields<ActiveAntiGravitySafePoint>),
|
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)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
|
|
@ -335,6 +335,7 @@ pub struct UsingVehicle {
|
||||||
pub enum VehicleType {
|
pub enum VehicleType {
|
||||||
FishingBoat,
|
FishingBoat,
|
||||||
Gongduola,
|
Gongduola,
|
||||||
|
SceneItemAutoMoveVehicle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
@ -757,6 +758,13 @@ pub struct AddFlowInteractOption {
|
||||||
pub config: serde_json::Value,
|
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)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||||
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
|
#[serde(rename_all = "PascalCase", deny_unknown_fields)]
|
||||||
|
@ -765,6 +773,7 @@ pub struct MonsterCreator {
|
||||||
pub prefab_var: Option<Var>,
|
pub prefab_var: Option<Var>,
|
||||||
pub show_monster_merged_hp_bar: Option<bool>,
|
pub show_monster_merged_hp_bar: Option<bool>,
|
||||||
pub tid_monster_group_name: Option<String>,
|
pub tid_monster_group_name: Option<String>,
|
||||||
|
pub monster_merged_hp_bar_settings: Option<MonsterMergedHpBarSettings>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
@ -1135,6 +1144,60 @@ pub struct CheckEntityReward {
|
||||||
pub UiType: serde_json::Value,
|
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)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
#[serde(tag = "Type")]
|
#[serde(tag = "Type")]
|
||||||
pub enum Condition {
|
pub enum Condition {
|
||||||
|
@ -1237,6 +1300,11 @@ pub enum Condition {
|
||||||
CheckEntityGravityDirection(CheckEntityGravityDirection),
|
CheckEntityGravityDirection(CheckEntityGravityDirection),
|
||||||
CheckTeleControlState(CheckTeleControlState),
|
CheckTeleControlState(CheckTeleControlState),
|
||||||
CheckEntityReward(CheckEntityReward),
|
CheckEntityReward(CheckEntityReward),
|
||||||
|
CheckIsGramophonePlayingMusic(CheckIsGramophonePlayingMusic),
|
||||||
|
CheckBVBEvent(CheckBVBEvent),
|
||||||
|
FinishBvbChallenge(FinishBvbChallenge),
|
||||||
|
CompareActorVar(CompareActorVar),
|
||||||
|
CheckDangoCultivationProgress(CheckDangoCultivationProgress),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
|
|
@ -4,8 +4,8 @@ use serde::Deserialize;
|
||||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||||
#[serde(rename_all = "PascalCase")]
|
#[serde(rename_all = "PascalCase")]
|
||||||
pub struct ModelType {
|
pub struct ModelType {
|
||||||
r#type: Option<String>,
|
pub r#type: Option<String>,
|
||||||
model_id: Option<i32>
|
pub model_id: Option<i32>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
|
|
@ -91,6 +91,13 @@ pub struct SelfVar {
|
||||||
pub name: String,
|
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)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
#[serde(tag = "Source")]
|
#[serde(tag = "Source")]
|
||||||
|
@ -100,4 +107,5 @@ pub enum Var {
|
||||||
Global(Global),
|
Global(Global),
|
||||||
#[serde(rename = "Self")]
|
#[serde(rename = "Self")]
|
||||||
SelfVar(SelfVar),
|
SelfVar(SelfVar),
|
||||||
|
System(System),
|
||||||
}
|
}
|
|
@ -100,7 +100,6 @@ pub struct RoleInfoData {
|
||||||
pub role_guide: i32,
|
pub role_guide: i32,
|
||||||
#[cfg(feature = "strict_json_fields")]
|
#[cfg(feature = "strict_json_fields")]
|
||||||
pub red_dot_disable_rule: i32,
|
pub red_dot_disable_rule: i32,
|
||||||
#[cfg(feature = "strict_json_fields")]
|
|
||||||
pub skin_damage: Vec<String>,
|
pub skin_damage: Vec<String>,
|
||||||
#[cfg(feature = "strict_json_fields")]
|
#[cfg(feature = "strict_json_fields")]
|
||||||
pub hide_hu_lu: bool,
|
pub hide_hu_lu: bool,
|
||||||
|
|
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,
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ load_textmaps = true
|
||||||
quadrant_size = 1000000
|
quadrant_size = 1000000
|
||||||
|
|
||||||
[asset_config]
|
[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
|
buffer_size = 268435456
|
||||||
|
|
||||||
[default_unlocks]
|
[default_unlocks]
|
||||||
|
|
|
@ -80,17 +80,17 @@ impl BufManager {
|
||||||
let mut buffs = wicked_waifus_data::buff_data::iter().filter(|(id, buf)| {
|
let mut buffs = wicked_waifus_data::buff_data::iter().filter(|(id, buf)| {
|
||||||
id.to_string().starts_with(&role_id.to_string()) // must be part of char kit :)
|
id.to_string().starts_with(&role_id.to_string()) // must be part of char kit :)
|
||||||
&&
|
&&
|
||||||
(
|
!id.to_string().contains("666")// KURO IS EVIL
|
||||||
!id.to_string().contains("666")// KURO IS EVIL
|
&&
|
||||||
&&
|
buf.duration_policy == 1
|
||||||
buf.duration_policy == 1
|
&&
|
||||||
)
|
!buf.ge_desc.contains("【废弃】") // remove "deprecated" buffs
|
||||||
// &&
|
|
||||||
// !buf.ge_desc.contains("【废弃】") // remove "deprecated" buffs
|
|
||||||
})
|
})
|
||||||
.map(|x| *x.0)
|
.map(|x| *x.0)
|
||||||
.collect::<Vec<i64>>();
|
.collect::<Vec<i64>>();
|
||||||
|
|
||||||
|
tracing::debug!("adding roleid {:#?}", buffs);
|
||||||
|
|
||||||
buffs.extend(OVERRIDE_BUFFS.iter().copied());
|
buffs.extend(OVERRIDE_BUFFS.iter().copied());
|
||||||
if let Some(role_buff_overrides) = get_role_buff_overrides(role_id) {
|
if let Some(role_buff_overrides) = get_role_buff_overrides(role_id) {
|
||||||
buffs.extend(role_buff_overrides.iter().copied());
|
buffs.extend(role_buff_overrides.iter().copied());
|
||||||
|
@ -120,6 +120,26 @@ impl BufManager {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_buff(&mut self, origin_id: i64, buff_id: i64) -> FightBuffInformation {
|
||||||
|
let mut buff = FightBuffInformation {
|
||||||
|
handle_id: 0,
|
||||||
|
buff_id,
|
||||||
|
level: 1,
|
||||||
|
stack_count: 1,
|
||||||
|
instigator_id: origin_id,
|
||||||
|
entity_id: origin_id,
|
||||||
|
apply_type: 0,
|
||||||
|
duration: -1f32,
|
||||||
|
left_duration: -1f32,
|
||||||
|
context: vec![],
|
||||||
|
is_active: true,
|
||||||
|
server_id: 0,
|
||||||
|
message_id: 0,
|
||||||
|
};
|
||||||
|
self.create(&mut buff);
|
||||||
|
buff
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BufManager {
|
impl Default for BufManager {
|
||||||
|
|
|
@ -108,11 +108,15 @@ impl WorldEntity {
|
||||||
self.components.remove(&entity_id).is_some() && self.entity_manager.remove(entity_id)
|
self.components.remove(&entity_id).is_some() && self.entity_manager.remove(entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn active_entity_empty(&self) -> bool {
|
pub fn get_all_entity_ids(&mut self) -> Vec<i32> {
|
||||||
self.entity_manager.active_entity_empty()
|
self.entity_manager.get_all_entity_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_role_permanent_buffs(&mut self, entity_id: i32, role_id: i32) -> Vec<FightBuffInformation> {
|
pub fn generate_role_permanent_buffs(&mut self, entity_id: i32, role_id: i32) -> Vec<FightBuffInformation> {
|
||||||
self.buff_manager.create_permanent_buffs(entity_id as i64, role_id)
|
self.buff_manager.create_permanent_buffs(entity_id as i64, role_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_buff(&mut self, entity_id: i32, buff_id: i64) -> FightBuffInformation {
|
||||||
|
self.buff_manager.create_buff(entity_id as i64, buff_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,10 @@ use rand::prelude::IndexedRandom;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use wicked_waifus_protocol::{ErrorCode, GachaResult, GachaReward};
|
use wicked_waifus_protocol::{ErrorCode, GachaResult, GachaReward};
|
||||||
|
|
||||||
use wicked_waifus_data::GachaViewTypeInfoId::{BeginnersChoiceConvene,
|
use wicked_waifus_data::GachaViewTypeInfoId::{
|
||||||
FeaturedResonatorConvene,
|
BeginnersChoiceConvene, FeaturedResonatorConvene, FeaturedWeaponConvene,
|
||||||
FeaturedWeaponConvene,
|
MultipleChoiceResonatorConvene, MultipleChoiceWeaponConvene, NoviceConvene,
|
||||||
NoviceConvene,
|
StandardResonatorConvene, StandardWeaponConvene,
|
||||||
StandardResonatorConvene,
|
|
||||||
StandardWeaponConvene,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::logic::gacha::pool_info::PoolInfo;
|
use crate::logic::gacha::pool_info::PoolInfo;
|
||||||
|
@ -53,16 +51,23 @@ impl GachaPool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pull<T: Rng>(&mut self,
|
pub fn pull<T: Rng>(
|
||||||
rng: &mut T,
|
&mut self,
|
||||||
player: &mut Player) -> Result<GachaResult, ErrorCode> {
|
rng: &mut T,
|
||||||
|
player: &mut Player,
|
||||||
|
) -> Result<GachaResult, ErrorCode> {
|
||||||
self.check_limits()?;
|
self.check_limits()?;
|
||||||
|
|
||||||
let result = if (self.info.pool_type == BeginnersChoiceConvene)
|
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();
|
let item_id = self.info.guaranteed_character_id.unwrap();
|
||||||
GachaResult {
|
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),
|
extra_rewards: self.calculate_extra_rewards(2),
|
||||||
transform_rewards: Self::get_transform_rewards(player, item_id),
|
transform_rewards: Self::get_transform_rewards(player, item_id),
|
||||||
bottom: None,
|
bottom: None,
|
||||||
|
@ -84,13 +89,14 @@ impl GachaPool {
|
||||||
};
|
};
|
||||||
item_id
|
item_id
|
||||||
}
|
}
|
||||||
_ => {
|
_ => self.get_random_item(rarity, rng),
|
||||||
self.get_random_item(rarity, rng)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
self.update_pity(rarity);
|
self.update_pity(rarity);
|
||||||
GachaResult {
|
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),
|
extra_rewards: self.calculate_extra_rewards(rarity),
|
||||||
transform_rewards: Self::get_transform_rewards(player, item_id),
|
transform_rewards: Self::get_transform_rewards(player, item_id),
|
||||||
bottom: None,
|
bottom: None,
|
||||||
|
@ -123,15 +129,29 @@ impl GachaPool {
|
||||||
|
|
||||||
fn get_random_item(&self, rarity: usize, rng: &mut impl Rng) -> i32 {
|
fn get_random_item(&self, rarity: usize, rng: &mut impl Rng) -> i32 {
|
||||||
let items: &[i32] = match rarity {
|
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 {
|
1 => match self.info.pool_type {
|
||||||
StandardWeaponConvene => &[21010024, 21020024, 21030024, 21040024, 21050024, 21010044, 21020044, 21030044, 21040044, 21050044, 21010064, 21020064, 21030064, 21040064, 21050064],
|
StandardWeaponConvene => &[
|
||||||
FeaturedResonatorConvene | FeaturedWeaponConvene => &self.info.rate_up_four_star[..],
|
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],
|
_ => &[1303, 1602, 1102, 1204, 1403, 1103, 1402, 1202, 1601],
|
||||||
},
|
},
|
||||||
2 => match self.info.pool_type {
|
2 => match self.info.pool_type {
|
||||||
NoviceConvene | StandardResonatorConvene => &[1405, 1301, 1503, 1104, 1203],
|
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!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -154,15 +174,23 @@ impl GachaPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_probabilities(&self) -> [f32; 3] {
|
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 {
|
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[0] -= extra_prob;
|
||||||
prob[2] = 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, 100.0, 0.0],
|
||||||
(_, true) => [0.0, 0.0, 100.0],
|
(_, true) => [0.0, 0.0, 100.0],
|
||||||
_ => prob,
|
_ => prob,
|
||||||
|
@ -172,9 +200,9 @@ impl GachaPool {
|
||||||
fn determine_rarity(&self, prob: &[f32; 3], rng: &mut impl Rng) -> usize {
|
fn determine_rarity(&self, prob: &[f32; 3], rng: &mut impl Rng) -> usize {
|
||||||
let roll: f32 = rng.random_range(0.0..100.0);
|
let roll: f32 = rng.random_range(0.0..100.0);
|
||||||
match (roll < prob[2], roll < prob[2] + prob[1]) {
|
match (roll < prob[2], roll < prob[2] + prob[1]) {
|
||||||
(true, _) => 2, // 5-star
|
(true, _) => 2, // 5-star
|
||||||
(_, true) => 1, // 4-star
|
(_, true) => 1, // 4-star
|
||||||
_ => 0, // 3-star
|
_ => 0, // 3-star
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,18 +234,18 @@ impl GachaPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: update rewards for duplicates
|
TODO: update rewards for duplicates
|
||||||
|
|
||||||
4-star duplicate:
|
4-star duplicate:
|
||||||
1st to 6th duplicate: 3 afterglow corals and 1 waveband of that char
|
1st to 6th duplicate: 3 afterglow corals and 1 waveband of that char
|
||||||
7th duplicate onwards: 8 afterglow corals
|
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.
|
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:
|
5-star duplicate:
|
||||||
1st to 6th duplicate: 15 afterglow corals and 1 waveband of that char
|
1st to 6th duplicate: 15 afterglow corals and 1 waveband of that char
|
||||||
7th duplicate onwards: 40 afterglow corals
|
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.
|
will not receive any afterglow corals when you pull a 5-star that you do not already own for the first time.
|
||||||
*/
|
*/
|
||||||
match rarity {
|
match rarity {
|
||||||
2 => rewards.push(GachaReward {
|
2 => rewards.push(GachaReward {
|
||||||
item_id: 50004, // afterglow corals
|
item_id: 50004, // afterglow corals
|
||||||
|
@ -236,4 +264,4 @@ TODO: update rewards for duplicates
|
||||||
pub fn is_active(&self) -> bool {
|
pub fn is_active(&self) -> bool {
|
||||||
self.info.is_active()
|
self.info.is_active()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use wicked_waifus_data::GachaViewTypeInfoId;
|
use wicked_waifus_data::GachaViewTypeInfoId;
|
||||||
use wicked_waifus_data::GachaViewTypeInfoId::{BeginnersChoiceConvene,
|
use wicked_waifus_data::GachaViewTypeInfoId::{
|
||||||
FeaturedResonatorConvene,
|
BeginnersChoiceConvene, FeaturedResonatorConvene, FeaturedWeaponConvene,
|
||||||
FeaturedWeaponConvene,
|
MultipleChoiceResonatorConvene, MultipleChoiceWeaponConvene, NoviceConvene,
|
||||||
NoviceConvene,
|
StandardResonatorConvene, StandardWeaponConvene,
|
||||||
StandardResonatorConvene,
|
|
||||||
StandardWeaponConvene,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::logic::gacha::category::PoolCategory;
|
use crate::logic::gacha::category::PoolCategory;
|
||||||
|
@ -58,30 +56,37 @@ impl PoolInfo {
|
||||||
const NOVICE_GACHA_POOL_RESOURCE: &'static str = "UiItem_NewPlayerGachaPool";
|
const NOVICE_GACHA_POOL_RESOURCE: &'static str = "UiItem_NewPlayerGachaPool";
|
||||||
const BASE_GACHA_POOL_RESOURCE: &'static str = "UiItem_BaseGachaPool";
|
const BASE_GACHA_POOL_RESOURCE: &'static str = "UiItem_BaseGachaPool";
|
||||||
|
|
||||||
pub(crate) fn new(pool_id: i32,
|
pub(crate) fn new(
|
||||||
pool_type: GachaViewTypeInfoId,
|
pool_id: i32,
|
||||||
category: PoolCategory,
|
pool_type: GachaViewTypeInfoId,
|
||||||
rate_up_five_star: &[i32],
|
category: PoolCategory,
|
||||||
rate_up_four_star: &[i32],
|
rate_up_five_star: &[i32],
|
||||||
guaranteed_character_id: Option<i32>) -> Self {
|
rate_up_four_star: &[i32],
|
||||||
|
guaranteed_character_id: Option<i32>,
|
||||||
|
) -> Self {
|
||||||
let start_time = SystemTime::now();
|
let start_time = SystemTime::now();
|
||||||
let end_time = match category {
|
let end_time = match category {
|
||||||
PoolCategory::Permanent => None,
|
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
|
// 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 {
|
let (item_id, daily_limit, total_limit, pity_system) = match pool_type {
|
||||||
NoviceConvene => (50001, 0, 50, PitySystem::novice()),
|
NoviceConvene => (50001, 0, 50, PitySystem::novice()),
|
||||||
StandardResonatorConvene | StandardWeaponConvene => (50001, 0, 80, PitySystem::default()),
|
StandardResonatorConvene | StandardWeaponConvene => {
|
||||||
FeaturedResonatorConvene => (50002, 0, 0, PitySystem::default()),
|
(50001, 0, 80, PitySystem::default())
|
||||||
FeaturedWeaponConvene => (50005, 0, 0, PitySystem::default()),
|
|
||||||
BeginnersChoiceConvene => {
|
|
||||||
match pool_id {
|
|
||||||
51..56 => (50006, 0, 1, PitySystem::default()),
|
|
||||||
_ => (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 {
|
Self {
|
||||||
|
|
|
@ -5,12 +5,10 @@ use rand::prelude::StdRng;
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
|
|
||||||
use wicked_waifus_data::gacha_view_info_data;
|
use wicked_waifus_data::gacha_view_info_data;
|
||||||
use wicked_waifus_data::GachaViewTypeInfoId::{BeginnersChoiceConvene,
|
use wicked_waifus_data::GachaViewTypeInfoId::{
|
||||||
FeaturedResonatorConvene,
|
BeginnersChoiceConvene, FeaturedResonatorConvene, FeaturedWeaponConvene,
|
||||||
FeaturedWeaponConvene,
|
MultipleChoiceResonatorConvene, MultipleChoiceWeaponConvene, NoviceConvene,
|
||||||
NoviceConvene,
|
StandardResonatorConvene, StandardWeaponConvene,
|
||||||
StandardResonatorConvene,
|
|
||||||
StandardWeaponConvene,
|
|
||||||
};
|
};
|
||||||
use wicked_waifus_protocol::{ErrorCode, GachaResult};
|
use wicked_waifus_protocol::{ErrorCode, GachaResult};
|
||||||
|
|
||||||
|
@ -40,29 +38,48 @@ impl GachaService {
|
||||||
|
|
||||||
for element in gacha_view_info_data::iter() {
|
for element in gacha_view_info_data::iter() {
|
||||||
let duration = match element.r#type {
|
let duration = match element.r#type {
|
||||||
NoviceConvene | StandardResonatorConvene | StandardWeaponConvene => PoolCategory::Permanent,
|
NoviceConvene | StandardResonatorConvene | StandardWeaponConvene => {
|
||||||
FeaturedResonatorConvene | FeaturedWeaponConvene => PoolCategory::Event(Self::THREE_WEEKS),
|
PoolCategory::Permanent
|
||||||
|
}
|
||||||
|
// TODO: Review MultipleChoiceConvene
|
||||||
|
FeaturedResonatorConvene
|
||||||
|
| FeaturedWeaponConvene
|
||||||
|
| MultipleChoiceResonatorConvene
|
||||||
|
| MultipleChoiceWeaponConvene => PoolCategory::Event(Self::THREE_WEEKS),
|
||||||
BeginnersChoiceConvene => match element.id {
|
BeginnersChoiceConvene => match element.id {
|
||||||
51..56 => PoolCategory::Special(Self::ONE_WEEK),
|
51..56 => PoolCategory::Special(Self::ONE_WEEK),
|
||||||
_ => PoolCategory::Permanent,
|
_ => 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])
|
Some(element.show_id_list[0])
|
||||||
} else {
|
} else {
|
||||||
None
|
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.insert(element.id, GachaPool::new(info));
|
||||||
}
|
}
|
||||||
pools
|
pools
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pull(&mut self,
|
pub fn pull(
|
||||||
player: &mut Player,
|
&mut self,
|
||||||
pool_id: i32,
|
player: &mut Player,
|
||||||
times: i32) -> Result<Vec<GachaResult>, ErrorCode> {
|
pool_id: i32,
|
||||||
let pool = self.pools.get_mut(&pool_id)
|
times: i32,
|
||||||
|
) -> Result<Vec<GachaResult>, ErrorCode> {
|
||||||
|
let pool = self
|
||||||
|
.pools
|
||||||
|
.get_mut(&pool_id)
|
||||||
.ok_or(ErrorCode::ErrGachaPoolConfigNotFound)?;
|
.ok_or(ErrorCode::ErrGachaPoolConfigNotFound)?;
|
||||||
|
|
||||||
if !pool.is_active() {
|
if !pool.is_active() {
|
||||||
|
@ -83,7 +100,8 @@ impl GachaService {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_active_pools(&self) -> Vec<(i32, &GachaPool)> {
|
pub fn get_active_pools(&self) -> Vec<(i32, &GachaPool)> {
|
||||||
self.pools.iter()
|
self.pools
|
||||||
|
.iter()
|
||||||
.filter(|(_, pool)| pool.is_active())
|
.filter(|(_, pool)| pool.is_active())
|
||||||
.map(|(id, pool)| (*id, pool))
|
.map(|(id, pool)| (*id, pool))
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -91,8 +109,9 @@ impl GachaService {
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn get_all_pools(&self) -> Vec<(i32, &PoolInfo)> {
|
pub fn get_all_pools(&self) -> Vec<(i32, &PoolInfo)> {
|
||||||
self.pools.iter()
|
self.pools
|
||||||
|
.iter()
|
||||||
.map(|(id, pool)| (*id, &pool.info))
|
.map(|(id, pool)| (*id, &pool.info))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
255
wicked-waifus-game-server/src/logic/handler/action.rs
Normal file
255
wicked-waifus-game-server/src/logic/handler/action.rs
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use wicked_waifus_protocol::{
|
||||||
|
CommonTagData, EntityCommonTagNotify, EntityStateReadyNotify, FightBuffInformation, ItemRewardNotify, NormalItemUpdateNotify, RewardItemInfo, WR
|
||||||
|
};
|
||||||
|
|
||||||
|
use wicked_waifus_data::pb_components::action::{
|
||||||
|
AddBuffToEntity, AddBuffToPlayer, ChangeSelfEntityState, CollectParams, RemoveBuffFromEntity, RemoveBuffFromPlayer, UnlockTeleportTrigger
|
||||||
|
};
|
||||||
|
use wicked_waifus_data::pb_components::entity_state::EntityStateComponent;
|
||||||
|
|
||||||
|
use crate::logic::ecs::component::ComponentContainer;
|
||||||
|
use crate::logic::ecs::world::WorldEntity;
|
||||||
|
use crate::logic::handler::handle_action;
|
||||||
|
use crate::logic::player::{ItemUsage, Player};
|
||||||
|
use crate::logic::utils::tag_utils;
|
||||||
|
use crate::query_components;
|
||||||
|
|
||||||
|
pub fn collect_action(
|
||||||
|
player: &mut Player,
|
||||||
|
_entity_id: i64,
|
||||||
|
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
||||||
|
template_config: &wicked_waifus_data::TemplateConfigData,
|
||||||
|
_: CollectParams
|
||||||
|
) {
|
||||||
|
if let Some(reward_component) = level_entity_data
|
||||||
|
.components_data
|
||||||
|
.reward_component
|
||||||
|
.as_ref()
|
||||||
|
.or(template_config.components_data.reward_component.as_ref())
|
||||||
|
{
|
||||||
|
if reward_component.disabled.unwrap_or(false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: check the use of reward_type and drop_on_event
|
||||||
|
// Seems type 0 is reward from preview, while 1 and 2 is unknown
|
||||||
|
if let Some(reward_id) = reward_component.reward_id {
|
||||||
|
let drop = wicked_waifus_data::drop_package_data::get(&reward_id).unwrap();
|
||||||
|
let usages = drop
|
||||||
|
.drop_preview
|
||||||
|
.iter()
|
||||||
|
.map(|(&id, &quantity)| ItemUsage { id, quantity })
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let updated_items = player.inventory.add_items(&usages);
|
||||||
|
let normal_item_list = player
|
||||||
|
.inventory
|
||||||
|
.to_normal_item_list_filtered(updated_items.keys().cloned().collect::<Vec<i32>>());
|
||||||
|
player.notify(NormalItemUpdateNotify {
|
||||||
|
normal_item_list,
|
||||||
|
no_tips: false,
|
||||||
|
});
|
||||||
|
// UpdateHandBookActiveStateMapNotify
|
||||||
|
let mut rewards: HashMap<i32, WR> = HashMap::new();
|
||||||
|
rewards.insert(
|
||||||
|
0,
|
||||||
|
WR {
|
||||||
|
item_list: drop
|
||||||
|
.drop_preview
|
||||||
|
.iter()
|
||||||
|
.map(|(&id, &quantity)| RewardItemInfo {
|
||||||
|
show_plan_id: 0, // TODO: Check how to get this
|
||||||
|
item_id: id,
|
||||||
|
count: quantity,
|
||||||
|
incr_id: 0,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
player.notify(ItemRewardNotify {
|
||||||
|
drop_id: reward_id,
|
||||||
|
reason: 15000,
|
||||||
|
magnification: 1,
|
||||||
|
reward_items: rewards,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// TODO: Should we remove entity?? get pcap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn unlock_teleport_trigger_action(
|
||||||
|
player: &mut Player,
|
||||||
|
_entity_id: i64,
|
||||||
|
_level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
||||||
|
_template_config: &wicked_waifus_data::TemplateConfigData,
|
||||||
|
action: UnlockTeleportTrigger
|
||||||
|
) {
|
||||||
|
player.unlock_teleport(action.teleport_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn change_self_entity_state_action(
|
||||||
|
player: &mut Player,
|
||||||
|
entity_id: i64,
|
||||||
|
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
||||||
|
template_config: &wicked_waifus_data::TemplateConfigData,
|
||||||
|
action: ChangeSelfEntityState,
|
||||||
|
) {
|
||||||
|
let state = tag_utils::get_tag_id_by_name(action.entity_state.as_str());
|
||||||
|
|
||||||
|
// TODO: update Tag::CommonEntityTags too??
|
||||||
|
let old_state = {
|
||||||
|
let world_ref = player.world.borrow();
|
||||||
|
let world = world_ref.get_world_entity();
|
||||||
|
let mut state_tag = query_components!(world, entity_id, StateTag).0.unwrap();
|
||||||
|
let old_state = state_tag.state_tag_id;
|
||||||
|
tracing::debug!("ChangeSelfEntityState: old state {old_state} -> new state: {state}");
|
||||||
|
state_tag.state_tag_id = state;
|
||||||
|
old_state
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(entity_state_component) = level_entity_data
|
||||||
|
.components_data
|
||||||
|
.entity_state_component
|
||||||
|
.as_ref()
|
||||||
|
.or(template_config
|
||||||
|
.components_data
|
||||||
|
.entity_state_component
|
||||||
|
.as_ref())
|
||||||
|
.cloned()
|
||||||
|
{
|
||||||
|
let entity_state_component: EntityStateComponent = entity_state_component; // TODO: Remove this line, used for casting only
|
||||||
|
|
||||||
|
// TODO: implement rest of cases
|
||||||
|
if let Some(state_change_behaviors) = entity_state_component.state_change_behaviors {
|
||||||
|
for state_change_behavior in state_change_behaviors {
|
||||||
|
// TODO: implement rest of cases
|
||||||
|
let expected = tag_utils::get_tag_id_by_name(state_change_behavior.state.as_str());
|
||||||
|
|
||||||
|
if expected == state {
|
||||||
|
if let Some(actions) = state_change_behavior.action {
|
||||||
|
for sub in actions {
|
||||||
|
handle_action(
|
||||||
|
player,
|
||||||
|
entity_id,
|
||||||
|
level_entity_data,
|
||||||
|
template_config,
|
||||||
|
sub,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player.notify(EntityCommonTagNotify {
|
||||||
|
id: entity_id,
|
||||||
|
tags: vec![
|
||||||
|
CommonTagData {
|
||||||
|
tag_id: old_state,
|
||||||
|
remove_tag_ids: false,
|
||||||
|
}, // Remove
|
||||||
|
CommonTagData {
|
||||||
|
tag_id: state,
|
||||||
|
remove_tag_ids: true,
|
||||||
|
}, // Add
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
player.notify(EntityStateReadyNotify {
|
||||||
|
entity_id,
|
||||||
|
tag_id: state,
|
||||||
|
ready: true, // TODO: Always true? or shall we compare it to something??
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_buff_to_entity(
|
||||||
|
world: &mut WorldEntity,
|
||||||
|
entity_ids: Vec<i64>,
|
||||||
|
buff_ids: Vec<i64>,
|
||||||
|
) {
|
||||||
|
for entity_id in entity_ids {
|
||||||
|
let (Some(mut buff_component),) = query_components!(world, entity_id, FightBuff) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
for buff_id in &buff_ids {
|
||||||
|
buff_component.fight_buff_infos.push(FightBuffInformation {
|
||||||
|
handle_id: 1,
|
||||||
|
buff_id: *buff_id,
|
||||||
|
level: 1,
|
||||||
|
stack_count: 1,
|
||||||
|
instigator_id: 0,
|
||||||
|
entity_id: 0,
|
||||||
|
apply_type: 0,
|
||||||
|
duration: -1.0,
|
||||||
|
left_duration: -1.0,
|
||||||
|
context: vec![],
|
||||||
|
is_active: true,
|
||||||
|
server_id: 1,
|
||||||
|
message_id: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_buff_to_entity_action(
|
||||||
|
player: &mut Player,
|
||||||
|
entity_id: i64,
|
||||||
|
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
||||||
|
template_config: &wicked_waifus_data::TemplateConfigData,
|
||||||
|
params: AddBuffToEntity
|
||||||
|
) {
|
||||||
|
tracing::info!("entity buff request received with the following details: {:#?}.", params);
|
||||||
|
let mut world_ref = player.world.borrow_mut();
|
||||||
|
let world = world_ref.get_mut_world_entity();
|
||||||
|
|
||||||
|
match params {
|
||||||
|
AddBuffToEntity::SingleEntityBuffs(single_entity_buffs) => {
|
||||||
|
add_buff_to_entity(world, vec![single_entity_buffs.entity_id], single_entity_buffs.buff_ids)
|
||||||
|
},
|
||||||
|
AddBuffToEntity::MultipleEntitiesBuff(multiple_entities_buff) => {
|
||||||
|
add_buff_to_entity(world, multiple_entities_buff.entity_ids, multiple_entities_buff.buff_ids)
|
||||||
|
},
|
||||||
|
AddBuffToEntity::SelfEntityBuff(self_entity_buff) => {
|
||||||
|
add_buff_to_entity(world, vec![entity_id], self_entity_buff.buff_ids)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_buff_from_entity_action(
|
||||||
|
player: &mut Player,
|
||||||
|
entity_id: i64,
|
||||||
|
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
||||||
|
template_config: &wicked_waifus_data::TemplateConfigData,
|
||||||
|
params: RemoveBuffFromEntity
|
||||||
|
) {
|
||||||
|
tracing::info!("entity buff request received with the following details: {:#?}.", params);
|
||||||
|
let mut world_ref = player.world.borrow_mut();
|
||||||
|
let world = world_ref.get_mut_world_entity();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_buff_to_player_action(
|
||||||
|
player: &mut Player,
|
||||||
|
entity_id: i64,
|
||||||
|
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
||||||
|
template_config: &wicked_waifus_data::TemplateConfigData,
|
||||||
|
params: AddBuffToPlayer
|
||||||
|
) {
|
||||||
|
tracing::info!("entity buff request received with the following details: {:#?}.", params);
|
||||||
|
let mut world_ref = player.world.borrow_mut();
|
||||||
|
let world = world_ref.get_mut_world_entity();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_buff_from_player_action(
|
||||||
|
player: &mut Player,
|
||||||
|
entity_id: i64,
|
||||||
|
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
||||||
|
template_config: &wicked_waifus_data::TemplateConfigData,
|
||||||
|
params: RemoveBuffFromPlayer
|
||||||
|
) {
|
||||||
|
tracing::info!("entity buff request received with the following details: {:#?}.", params);
|
||||||
|
let mut world_ref = player.world.borrow_mut();
|
||||||
|
let world = world_ref.get_mut_world_entity();
|
||||||
|
}
|
58
wicked-waifus-game-server/src/logic/handler/attribute.rs
Normal file
58
wicked-waifus-game-server/src/logic/handler/attribute.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use wicked_waifus_protocol::{AttributeChangedRequest, AttributeChangedResponse, EAttributeType, ErrorCode, FormationAttrRequest, FormationAttrResponse};
|
||||||
|
|
||||||
|
use crate::{logic::{ecs::component::ComponentContainer, player::Player}, query_components};
|
||||||
|
|
||||||
|
pub fn on_attribute_changed_request(
|
||||||
|
player: &mut Player,
|
||||||
|
request: AttributeChangedRequest,
|
||||||
|
response: &mut AttributeChangedResponse,
|
||||||
|
) {
|
||||||
|
let mut world_ref = player.world.borrow_mut();
|
||||||
|
let world = world_ref.get_mut_world_entity();
|
||||||
|
|
||||||
|
let id = request.id;
|
||||||
|
|
||||||
|
if let (Some(mut component),) = query_components!(world, id, Attribute) {
|
||||||
|
for needs_editing in request.attributes {
|
||||||
|
if let Ok(attr_type) = EAttributeType::try_from(needs_editing.attribute_type) {
|
||||||
|
component.attr_map.get_mut(&attr_type).unwrap().0 = needs_editing.current_value;
|
||||||
|
component.attr_map.get_mut(&attr_type).unwrap().1 = needs_editing.value_increment;
|
||||||
|
} else {
|
||||||
|
tracing::warn!("Attribute skipped!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.error_code = ErrorCode::Success.into()
|
||||||
|
} else {
|
||||||
|
response.error_code = ErrorCode::ErrEntityNotFound.into()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_formation_attr_request(
|
||||||
|
player: &mut Player,
|
||||||
|
request: FormationAttrRequest,
|
||||||
|
response: &mut FormationAttrResponse,
|
||||||
|
) {
|
||||||
|
let mut world_ref = player.world.borrow_mut();
|
||||||
|
let world = world_ref.get_mut_world_entity();
|
||||||
|
|
||||||
|
let formation = &player.formation_list[&player.cur_formation_id];
|
||||||
|
|
||||||
|
for role_id in formation.role_ids.clone() {
|
||||||
|
if let (Some(mut component),) = query_components!(world, role_id as i64, Attribute) {
|
||||||
|
for needs_editing in &request.formation_attrs {
|
||||||
|
if let Ok(attr_type) = EAttributeType::try_from(needs_editing.attr_id) {
|
||||||
|
component.attr_map.get_mut(&attr_type).unwrap().0 = needs_editing.current_value;
|
||||||
|
component.attr_map.get_mut(&attr_type).unwrap().1 = needs_editing.max_value;
|
||||||
|
} else {
|
||||||
|
tracing::warn!("Attribute skipped!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.error_code = ErrorCode::Success.into()
|
||||||
|
} else {
|
||||||
|
response.error_code = ErrorCode::ErrEntityNotFound.into()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,12 @@ use wicked_waifus_protocol::combat_message::{
|
||||||
combat_send_data, CombatNotifyData, CombatReceiveData, CombatRequestData, CombatResponseData,
|
combat_send_data, CombatNotifyData, CombatReceiveData, CombatRequestData, CombatResponseData,
|
||||||
CombatSendPackRequest, CombatSendPackResponse,
|
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;
|
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) => {
|
combat_request_data::Message::SwitchRoleRequest(ref request) => {
|
||||||
handle_switch_role_request(player, request_data, request, response);
|
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) => {
|
combat_request_data::Message::DamageExecuteRequest(ref request) => {
|
||||||
handle_damage_execute_request(player, request_data, request, response);
|
handle_damage_execute_request(player, request_data, request, response);
|
||||||
}
|
}
|
||||||
|
@ -117,16 +125,20 @@ fn handle_damage_execute_request(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if let Ok(related_attribute) = EAttributeType::try_from(damage_data.related_property) {
|
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((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];
|
let hardness_lv = damage_data.hardness_lv[0];
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"atk: {}, damage_id: {}, role_id: {}, rate_lv: {}, hardness_lv: {}",
|
"atk: {}, damage_id: {}, role_id: {}, rate_lv: {}, hardness_lv: {}",
|
||||||
value,
|
value,
|
||||||
request.damage_id,
|
request.damage_id,
|
||||||
config_id,
|
config_id,
|
||||||
rate_lv,
|
rate_lv,
|
||||||
hardness_lv
|
hardness_lv
|
||||||
);
|
);
|
||||||
damage = if hardness_lv == 0 || rate_lv <= 0 {
|
damage = if hardness_lv == 0 || rate_lv <= 0 {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,34 +160,83 @@ fn handle_damage_execute_request(
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
if let Some((value, _)) = query_components!(world, request.target_entity_id, Attribute)
|
// if let Some((value, _)) = query_components!(world, request.target_entity_id, Attribute)
|
||||||
.0
|
// .0
|
||||||
.unwrap()
|
// .unwrap()
|
||||||
.attr_map
|
// .attr_map
|
||||||
.get(&EAttributeType::Life)
|
// .get(&EAttributeType::Life)
|
||||||
{
|
// {
|
||||||
let updated_value = match value - damage >= 0 {
|
// let updated_value = match value - damage >= 0 {
|
||||||
true => value - damage,
|
// true => value - damage,
|
||||||
false => 0,
|
// false => 0,
|
||||||
};
|
// };
|
||||||
receive_pack.data.push(create_combat_notify(
|
// receive_pack.data.push(create_combat_notify(
|
||||||
CombatCommon {
|
// CombatCommon {
|
||||||
entity_id: request.target_entity_id,
|
// entity_id: request.target_entity_id,
|
||||||
..Default::default()
|
// ..Default::default()
|
||||||
},
|
// },
|
||||||
combat_notify_data::Message::AttributeChangedNotify(AttributeChangedNotify {
|
// combat_notify_data::Message::AttributeChangedNotify(AttributeChangedNotify {
|
||||||
id: request.target_entity_id,
|
// id: request.target_entity_id,
|
||||||
attributes: vec![GameplayAttributeData {
|
// attributes: vec![GameplayAttributeData {
|
||||||
current_value: updated_value,
|
// current_value: updated_value,
|
||||||
value_increment: updated_value,
|
// value_increment: updated_value,
|
||||||
attribute_type: EAttributeType::Life.into(),
|
// attribute_type: EAttributeType::Life.into(),
|
||||||
}],
|
// }],
|
||||||
}),
|
// }),
|
||||||
));
|
// ));
|
||||||
if updated_value == 0 {
|
// 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();
|
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;
|
TowerSeasonUpdate;
|
||||||
ValidTimeItem;
|
ValidTimeItem;
|
||||||
PayShopInfo;
|
PayShopInfo;
|
||||||
|
PayInfo;
|
||||||
InitRange;
|
InitRange;
|
||||||
Activity;
|
Activity;
|
||||||
BattlePass;
|
BattlePass;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use wicked_waifus_protocol::{EntityAccessInfo, EntityAccessRangeRequest, EntityAccessRangeResponse, EntityActiveRequest, EntityActiveResponse, EntityFollowTrackRequest, EntityFollowTrackResponse, EntityInteractRequest, EntityInteractResponse, EntityOnLandedRequest, EntityOnLandedResponse, EntityPb, EntityPositionRequest, EntityPositionResponse, ErrorCode, GetRewardTreasureBoxRequest, GetRewardTreasureBoxResponse, MovePackagePush};
|
use wicked_waifus_protocol::{ApplyGameplayEffectPush, ApplyGameplayEffectRequest, ApplyGameplayEffectResponse, EntityAccessInfo, EntityAccessRangeRequest, EntityAccessRangeResponse, EntityActiveRequest, EntityActiveResponse, EntityFollowTrackRequest, EntityFollowTrackResponse, EntityInteractRequest, EntityInteractResponse, EntityOnLandedRequest, EntityOnLandedResponse, EntityPb, EntityPositionRequest, EntityPositionResponse, ErrorCode, GetRewardTreasureBoxRequest, GetRewardTreasureBoxResponse, MovePackagePush, OrderApplyBuffRequest, OrderApplyBuffResponse, OrderRemoveBuffRequest, OrderRemoveBuffResponse, RemoveGameplayEffectPush, RemoveGameplayEffectRequest, RemoveGameplayEffectResponse};
|
||||||
|
|
||||||
use wicked_waifus_data::pb_components::option::OptionType;
|
use wicked_waifus_data::pb_components::option::OptionType;
|
||||||
|
|
||||||
|
use crate::logic::handler::handle_action;
|
||||||
use crate::{logic, logic::ecs::component::ComponentContainer, logic::player::Player, query_components};
|
use crate::{logic, logic::ecs::component::ComponentContainer, logic::player::Player, query_components};
|
||||||
use crate::logic::utils::action_utils::perform_action;
|
|
||||||
use crate::logic::utils::condition_utils::check_condition;
|
use crate::logic::utils::condition_utils::check_condition;
|
||||||
|
|
||||||
pub fn on_entity_active_request(
|
pub fn on_entity_active_request(
|
||||||
|
@ -190,7 +190,7 @@ pub fn on_entity_interact_request(
|
||||||
match option_type {
|
match option_type {
|
||||||
OptionType::Actions(actions) => {
|
OptionType::Actions(actions) => {
|
||||||
for action in actions.actions {
|
for action in actions.actions {
|
||||||
perform_action(player, request.entity_id, &entity, template_config, action);
|
handle_action(player, request.entity_id, &entity, template_config, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OptionType::Flow(_) => {
|
OptionType::Flow(_) => {
|
||||||
|
@ -234,6 +234,52 @@ pub fn on_get_reward_treasure_box_request(
|
||||||
tracing::debug!("GetRewardTreasureBoxRequest with ID: {} and ConfigID {config_id}", request.entity_id);
|
tracing::debug!("GetRewardTreasureBoxRequest with ID: {} and ConfigID {config_id}", request.entity_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_order_apply_buff_request(
|
||||||
|
player: &Player,
|
||||||
|
request: OrderApplyBuffRequest,
|
||||||
|
_response: &mut OrderApplyBuffResponse,
|
||||||
|
) {
|
||||||
|
tracing::info!("OrderApplyBuffRequest receuived");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_order_remove_buff_request(
|
||||||
|
player: &Player,
|
||||||
|
request: OrderRemoveBuffRequest,
|
||||||
|
_response: &mut OrderRemoveBuffResponse,
|
||||||
|
) {
|
||||||
|
tracing::info!("OrderRemoveBuffRequest receuived");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_apply_gameplay_effect_request(
|
||||||
|
player: &Player,
|
||||||
|
request: ApplyGameplayEffectRequest,
|
||||||
|
response: &mut ApplyGameplayEffectResponse
|
||||||
|
) {
|
||||||
|
tracing::info!("applygameplayeffect receuived");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_apply_gameplay_effect_push(
|
||||||
|
player: &Player,
|
||||||
|
push: ApplyGameplayEffectPush
|
||||||
|
) {
|
||||||
|
tracing::info!("applygameplayeffect receuived");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_remove_gameplay_effect_request(
|
||||||
|
player: &Player,
|
||||||
|
request: RemoveGameplayEffectRequest,
|
||||||
|
response: &mut RemoveGameplayEffectResponse
|
||||||
|
) {
|
||||||
|
tracing::info!("applygameplayeffect receuived");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_remove_gameplay_effect_push(
|
||||||
|
player: &Player,
|
||||||
|
push: RemoveGameplayEffectPush
|
||||||
|
) {
|
||||||
|
tracing::info!("applygameplayeffect receuived");
|
||||||
|
}
|
||||||
|
|
||||||
fn get_config_id_from_entity_id(player: &Player, entity_id: i64) -> i64 {
|
fn get_config_id_from_entity_id(player: &Player, entity_id: i64) -> i64 {
|
||||||
let world_ref = player.world.borrow();
|
let world_ref = player.world.borrow();
|
||||||
let world = world_ref.get_world_entity();
|
let world = world_ref.get_world_entity();
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
pub use action::*;
|
||||||
|
pub use attribute::*;
|
||||||
pub use advice::*;
|
pub use advice::*;
|
||||||
pub use animal::*;
|
pub use animal::*;
|
||||||
pub use chat::*;
|
pub use chat::*;
|
||||||
|
@ -20,6 +22,8 @@ pub use skill::*;
|
||||||
pub use teleport::*;
|
pub use teleport::*;
|
||||||
pub use tutorial::*;
|
pub use tutorial::*;
|
||||||
|
|
||||||
|
mod action;
|
||||||
|
mod attribute;
|
||||||
mod advice;
|
mod advice;
|
||||||
mod animal;
|
mod animal;
|
||||||
mod chat;
|
mod chat;
|
||||||
|
@ -55,7 +59,7 @@ macro_rules! handle_request {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
tracing::debug!("logic: processing request {}", stringify!($($inner_package::)?[<$name Request>]));
|
// tracing::debug!("logic: processing request {}", stringify!($($inner_package::)?[<$name Request>]));
|
||||||
|
|
||||||
let mut response = ::wicked_waifus_protocol::$($inner_package::)?[<$name Response>]::default();
|
let mut response = ::wicked_waifus_protocol::$($inner_package::)?[<$name Response>]::default();
|
||||||
[<on_ $($inner_package:snake _)? $name:snake _request>](player, request, &mut response);
|
[<on_ $($inner_package:snake _)? $name:snake _request>](player, request, &mut response);
|
||||||
|
@ -110,6 +114,40 @@ macro_rules! handle_push {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! handle_action {
|
||||||
|
($($variant:ident),* $(,)?) => {
|
||||||
|
use wicked_waifus_data::pb_components::action::Action;
|
||||||
|
use crate::logic::player::Player;
|
||||||
|
|
||||||
|
fn perform_action(
|
||||||
|
player: &mut Player,
|
||||||
|
entity_id: i64,
|
||||||
|
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
||||||
|
template_config: &wicked_waifus_data::TemplateConfigData,
|
||||||
|
action: Action
|
||||||
|
) {
|
||||||
|
::paste::paste! {
|
||||||
|
match action {
|
||||||
|
$(
|
||||||
|
Action::$variant(inner) => {
|
||||||
|
[<$variant:snake _action>](
|
||||||
|
player,
|
||||||
|
entity_id,
|
||||||
|
level_entity_data,
|
||||||
|
template_config,
|
||||||
|
inner.params
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)*
|
||||||
|
_ => {
|
||||||
|
::tracing::warn!("Action not implemented for: {:?}", action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
handle_request! {
|
handle_request! {
|
||||||
// Advice
|
// Advice
|
||||||
Advice;
|
Advice;
|
||||||
|
@ -120,6 +158,10 @@ handle_request! {
|
||||||
AnimalDrop;
|
AnimalDrop;
|
||||||
AnimalDestroy;
|
AnimalDestroy;
|
||||||
|
|
||||||
|
// Attribute
|
||||||
|
AttributeChanged;
|
||||||
|
FormationAttr;
|
||||||
|
|
||||||
// Chat (TODO: Review TODOs)
|
// Chat (TODO: Review TODOs)
|
||||||
PrivateChat;
|
PrivateChat;
|
||||||
PrivateChatData;
|
PrivateChatData;
|
||||||
|
@ -141,6 +183,10 @@ handle_request! {
|
||||||
EntityInteract;
|
EntityInteract;
|
||||||
EntityFollowTrack;
|
EntityFollowTrack;
|
||||||
GetRewardTreasureBox;
|
GetRewardTreasureBox;
|
||||||
|
OrderApplyBuff;
|
||||||
|
OrderRemoveBuff;
|
||||||
|
ApplyGameplayEffect;
|
||||||
|
RemoveGameplayEffect;
|
||||||
|
|
||||||
// Friend (TODO: Implement them)
|
// Friend (TODO: Implement them)
|
||||||
FriendAll;
|
FriendAll;
|
||||||
|
@ -198,7 +244,6 @@ handle_request! {
|
||||||
RoleShowListUpdate;
|
RoleShowListUpdate;
|
||||||
ClientCurrentRoleReport;
|
ClientCurrentRoleReport;
|
||||||
RoleFavorList;
|
RoleFavorList;
|
||||||
FormationAttr;
|
|
||||||
UpdateFormation;
|
UpdateFormation;
|
||||||
|
|
||||||
// Scene (TODO: Review this on_..., port some from go)
|
// Scene (TODO: Review this on_..., port some from go)
|
||||||
|
@ -216,6 +261,7 @@ handle_request! {
|
||||||
PayShopInfo;
|
PayShopInfo;
|
||||||
// PayShopUpdate;
|
// PayShopUpdate;
|
||||||
// MonthCard;
|
// MonthCard;
|
||||||
|
PayInfo;
|
||||||
|
|
||||||
// Skill (TODO: Review this on_..., port some from go)
|
// Skill (TODO: Review this on_..., port some from go)
|
||||||
VisionExploreSkillSet;
|
VisionExploreSkillSet;
|
||||||
|
@ -279,10 +325,200 @@ handle_push! {
|
||||||
// Entity
|
// Entity
|
||||||
MovePackage;
|
MovePackage;
|
||||||
|
|
||||||
|
ApplyGameplayEffect;
|
||||||
|
RemoveGameplayEffect;
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
VersionInfo;
|
VersionInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle_action! {
|
||||||
|
// ExecBattleAction,
|
||||||
|
// WaitBattleCondition,
|
||||||
|
// SetBattleState,
|
||||||
|
// PlayFlow,
|
||||||
|
Collect,
|
||||||
|
// LeisureInteract,
|
||||||
|
UnlockTeleportTrigger,
|
||||||
|
// EnableTemporaryTeleport,
|
||||||
|
// OpenSystemBoard,
|
||||||
|
// OpenSystemFunction,
|
||||||
|
ChangeSelfEntityState,
|
||||||
|
// SetPlayerOperationRestriction,
|
||||||
|
// Wait,
|
||||||
|
// ChangeEntityState,
|
||||||
|
// Log,
|
||||||
|
// EnableNearbyTracking,
|
||||||
|
// TeleportDungeon,
|
||||||
|
// DestroySelf,
|
||||||
|
// CameraLookAt,
|
||||||
|
// StopCameraLookAt,
|
||||||
|
// EnterOrbitalCamera,
|
||||||
|
// ExitOrbitalCamera,
|
||||||
|
// SendAiEvent,
|
||||||
|
// SetInteractionLockState,
|
||||||
|
// AwakeEntity,
|
||||||
|
// ChangeLiftTarget,
|
||||||
|
// CalculateVar,
|
||||||
|
AddBuffToPlayer,
|
||||||
|
RemoveBuffFromPlayer,
|
||||||
|
AddBuffToEntity,
|
||||||
|
RemoveBuffFromEntity,
|
||||||
|
// Prompt,
|
||||||
|
// SetEntityVisible,
|
||||||
|
// DestroyEntity,
|
||||||
|
// GuideTrigger,
|
||||||
|
// TriggerCameraShake,
|
||||||
|
// SetVar,
|
||||||
|
// VehicleEnter,
|
||||||
|
// VehicleExitPlayer,
|
||||||
|
// LockEntity,
|
||||||
|
// UnlockEntity,
|
||||||
|
// CommonTip,
|
||||||
|
// CommonTip2,
|
||||||
|
// PostAkEvent,
|
||||||
|
// VehicleEnterNpc,
|
||||||
|
// VehicleExitNpc,
|
||||||
|
// PlayerLookAt,
|
||||||
|
// PlayBubble,
|
||||||
|
// AddPlayBubble,
|
||||||
|
// ClearPlayBubble,
|
||||||
|
// ExecRiskHarvestEffect,
|
||||||
|
// EnableLevelPlay,
|
||||||
|
// ClaimLevelPlayReward,
|
||||||
|
// SettlementDungeon,
|
||||||
|
// ExitDungeon,
|
||||||
|
// FinishDungeon,
|
||||||
|
// RecordDungeonEvent,
|
||||||
|
// RecoverDurability,
|
||||||
|
// FadeInScreen,
|
||||||
|
// FadeOutScreen,
|
||||||
|
// ChangeNpcPerformState,
|
||||||
|
// EntityTurnTo,
|
||||||
|
// EntityLookAt,
|
||||||
|
// ToggleMapMarkState,
|
||||||
|
// RandomVar,
|
||||||
|
// ModifySceneItemAttributeTag,
|
||||||
|
// VehicleWaterfallClimbing,
|
||||||
|
// VehicleTeleport,
|
||||||
|
// RogueGotoNextFloor,
|
||||||
|
// RogueReceiveReward,
|
||||||
|
// RogueSelectRoom,
|
||||||
|
// RogueActivatePortal,
|
||||||
|
// MowingTowerGotoNextFloor,
|
||||||
|
// SlashAndTowerGotoNextFloor,
|
||||||
|
// PlayMontage,
|
||||||
|
// OpenSystemBoardWithReturn,
|
||||||
|
// UnlockSystemItem,
|
||||||
|
// SetSportsState,
|
||||||
|
// OpenSimpleGameplay,
|
||||||
|
// PlayEffect,
|
||||||
|
// PlayEffect2,
|
||||||
|
// RestorePlayerCameraAdjustment,
|
||||||
|
// AdjustPlayerCamera,
|
||||||
|
// SetPlayerPos,
|
||||||
|
// MoveWithSpline,
|
||||||
|
// EnableSplineMoveModel,
|
||||||
|
// ToggleScanSplineEffect,
|
||||||
|
// MoveSceneItem,
|
||||||
|
// StopSceneItemMove,
|
||||||
|
// FireBullet,
|
||||||
|
// ClearFishingCabinInSaleItems,
|
||||||
|
// AcceptFishingEntrust,
|
||||||
|
// DestroyFishingBoat,
|
||||||
|
// SetJigsawItem,
|
||||||
|
// SetJigsawFoundation,
|
||||||
|
// SetTeleControl,
|
||||||
|
// SetEntityClientVisible,
|
||||||
|
// ToggleHighlightExploreUi,
|
||||||
|
// ExecAlertSystemAction,
|
||||||
|
// AddFlowInteractOption,
|
||||||
|
// RemoveFlowInteractOption,
|
||||||
|
// EnableHostility,
|
||||||
|
// ChangePhantomFormation,
|
||||||
|
// RestorePhantomFormation,
|
||||||
|
// ChangeTimer,
|
||||||
|
// ToggleTimerPauseState,
|
||||||
|
// ChangeFightTeam,
|
||||||
|
// AddTrialFollowShooter,
|
||||||
|
// RemoveTrialFollowShooter,
|
||||||
|
// AddTrialCharacter,
|
||||||
|
// RemoveTrialCharacter,
|
||||||
|
// SetAreaState,
|
||||||
|
// SwitchSubLevels,
|
||||||
|
// ChangeTeamPosition,
|
||||||
|
// GetItem,
|
||||||
|
// CreatePrefab,
|
||||||
|
// DestroyPrefab,
|
||||||
|
// CompleteGuide,
|
||||||
|
// PlayDynamicSettlement,
|
||||||
|
// UsePhantomSkill,
|
||||||
|
// HideTargetRange,
|
||||||
|
// ChangeOtherState,
|
||||||
|
// SetRegionConfig,
|
||||||
|
// SetReviveRegion,
|
||||||
|
// ExecResurrection,
|
||||||
|
// ShowTargetRange,
|
||||||
|
// SetTime,
|
||||||
|
// SetTimeLockState,
|
||||||
|
// EnableSystem,
|
||||||
|
// EnableAoiNotify,
|
||||||
|
// SetForceLock,
|
||||||
|
// PlayRegisteredMontage,
|
||||||
|
// SetAudioState,
|
||||||
|
// HideGroup,
|
||||||
|
// ShowHidedGroup,
|
||||||
|
// HideSpecificEntities,
|
||||||
|
// ShowSpecificEntities,
|
||||||
|
// RemovePreloadResource,
|
||||||
|
// Preload,
|
||||||
|
// EnableAI,
|
||||||
|
// SwitchDataLayers,
|
||||||
|
// DestroyQuest,
|
||||||
|
// DestroyQuestItem,
|
||||||
|
// PromptQuestChapterUI,
|
||||||
|
// TakePlotPhoto,
|
||||||
|
// SetWuYinQuState,
|
||||||
|
// RunActions,
|
||||||
|
// ManualOccupations,
|
||||||
|
// SetWeather,
|
||||||
|
// SendNpcMail,
|
||||||
|
// EnableFunction,
|
||||||
|
// FocusOnMapMark,
|
||||||
|
// CharacterLookAt,
|
||||||
|
// AddGuestCharacter,
|
||||||
|
// RemoveGuestCharacter,
|
||||||
|
// TeleportToAndEnterVehicle,
|
||||||
|
// SetAreaTimeState,
|
||||||
|
// ResetPlayerCameraFocus,
|
||||||
|
// ResetLevelPlay,
|
||||||
|
// VehicleSprint,
|
||||||
|
// VehicleMoveWithPathLine,
|
||||||
|
// ClientPreEnableSubLevels,
|
||||||
|
// GuestOperateUiAnimation,
|
||||||
|
// ChangeEntityCamp,
|
||||||
|
// NewMoveWithSpline,
|
||||||
|
// DangoAbyssActivatePortal,
|
||||||
|
// DangoAbyssCreateRewardTreasureBox,
|
||||||
|
// DangoAbyssGotoNextFloor,
|
||||||
|
// DangoAbyssReceiveReward,
|
||||||
|
// SummonEntity,
|
||||||
|
// GetRewardByInteract,
|
||||||
|
// OpenQte,
|
||||||
|
// ActiveAntiGravitySafePoint,
|
||||||
|
// BvbPlayDialog,
|
||||||
|
// BvbSendSystemEvent,
|
||||||
|
// BvbSendAiEvent,
|
||||||
|
// BvbPlayerOperationConstraint,
|
||||||
|
// ExecClientBattleAction,
|
||||||
|
// TriggerSpecificScanEffect,
|
||||||
|
// SetActorVar,
|
||||||
|
// RunActorCustomEvent,
|
||||||
|
// StopUiScreenEffect,
|
||||||
|
// StopNewMoveWithSpline,
|
||||||
|
// RequestSystemFunction
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_logic_message(player: &mut super::player::Player, msg: Message) {
|
pub fn handle_logic_message(player: &mut super::player::Player, msg: Message) {
|
||||||
match msg {
|
match msg {
|
||||||
Message::Request { .. } => handle_request(player, msg),
|
Message::Request { .. } => handle_request(player, msg),
|
||||||
|
@ -295,3 +531,13 @@ pub fn handle_logic_message(player: &mut super::player::Player, msg: Message) {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_action(
|
||||||
|
player: &mut Player,
|
||||||
|
entity_id: i64,
|
||||||
|
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
||||||
|
template_config: &wicked_waifus_data::TemplateConfigData,
|
||||||
|
element: Action
|
||||||
|
) {
|
||||||
|
perform_action(player, entity_id, level_entity_data, template_config, element)
|
||||||
|
}
|
|
@ -7,8 +7,12 @@ use wicked_waifus_protocol::{
|
||||||
RoleShowListUpdateResponse, UpdateFormationRequest, UpdateFormationResponse,
|
RoleShowListUpdateResponse, UpdateFormationRequest, UpdateFormationResponse,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::logic::ecs::world;
|
||||||
use crate::logic::player::Player;
|
use crate::logic::player::Player;
|
||||||
use crate::logic::role::{Role, RoleFormation};
|
use crate::logic::role::{Role, RoleFormation};
|
||||||
|
use crate::logic::utils::world_util::{add_player_entities, summon_concomitant};
|
||||||
|
use crate::query_components;
|
||||||
|
use crate::logic::ecs::component::ComponentContainer;
|
||||||
|
|
||||||
pub fn on_role_show_list_update_request(
|
pub fn on_role_show_list_update_request(
|
||||||
player: &mut Player,
|
player: &mut Player,
|
||||||
|
@ -44,14 +48,6 @@ pub fn on_role_favor_list_request(
|
||||||
response.error_code = ErrorCode::Success.into();
|
response.error_code = ErrorCode::Success.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_formation_attr_request(
|
|
||||||
_player: &Player,
|
|
||||||
_request: FormationAttrRequest,
|
|
||||||
response: &mut FormationAttrResponse,
|
|
||||||
) {
|
|
||||||
response.error_code = ErrorCode::Success.into();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_update_formation_request(
|
pub fn on_update_formation_request(
|
||||||
player: &mut Player,
|
player: &mut Player,
|
||||||
request: UpdateFormationRequest,
|
request: UpdateFormationRequest,
|
||||||
|
@ -65,6 +61,22 @@ pub fn on_update_formation_request(
|
||||||
let cur_role = formation.cur_role;
|
let cur_role = formation.cur_role;
|
||||||
let is_current = formation.is_current;
|
let is_current = formation.is_current;
|
||||||
|
|
||||||
|
// update all formation and check formation_list
|
||||||
|
player
|
||||||
|
.formation_list
|
||||||
|
.entry(formation_id)
|
||||||
|
.and_modify(|r| {
|
||||||
|
r.cur_role = formation.cur_role;
|
||||||
|
r.role_ids = formation.role_ids.clone();
|
||||||
|
r.is_current = is_current;
|
||||||
|
})
|
||||||
|
.or_insert(RoleFormation {
|
||||||
|
id: formation_id,
|
||||||
|
cur_role: formation.cur_role,
|
||||||
|
role_ids: formation.role_ids.clone(),
|
||||||
|
is_current,
|
||||||
|
});
|
||||||
|
|
||||||
if is_current {
|
if is_current {
|
||||||
// update player current formation id
|
// update player current formation id
|
||||||
player.cur_formation_id = formation_id;
|
player.cur_formation_id = formation_id;
|
||||||
|
@ -81,60 +93,40 @@ pub fn on_update_formation_request(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(old_formation) = player.formation_list.get(&real_formation_id) {
|
if let Some(old_formation) = player.formation_list.get(&real_formation_id) {
|
||||||
let removed_entities: Vec<i64> = old_formation
|
let mut removed_entities: Vec<i64> = old_formation
|
||||||
.role_ids
|
|
||||||
.iter()
|
|
||||||
.map(|&role_id| world.get_entity_id(role_id))
|
|
||||||
.collect();
|
|
||||||
removed_entities.iter().for_each(|&entity_id| {
|
|
||||||
world.remove_entity(entity_id as i32);
|
|
||||||
});
|
|
||||||
player.notify(player.build_player_entity_remove_notify(
|
|
||||||
removed_entities,
|
|
||||||
ERemoveEntityType::RemoveTypeNormal,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let added_roles: Vec<Role> = formation
|
|
||||||
.role_ids
|
.role_ids
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&role_id| Role::new(role_id))
|
.map(|&role_id| world.get_entity_id(role_id))
|
||||||
.collect();
|
.collect();
|
||||||
|
for id in removed_entities.clone() {
|
||||||
if !added_roles.is_empty() {
|
if let (Some(concomitant),) = query_components!(world, id, Concomitant) {
|
||||||
// add new roles
|
removed_entities.extend(concomitant.custom_entity_ids.clone());
|
||||||
player.notify(player.build_player_entity_add_notify(added_roles, world));
|
};
|
||||||
}
|
}
|
||||||
|
removed_entities.iter().for_each(|&entity_id| {
|
||||||
// send update group formation notify
|
world.remove_entity(entity_id as i32);
|
||||||
player.notify(player.build_update_group_formation_notify(
|
});
|
||||||
RoleFormation {
|
player.notify(player.build_player_entity_remove_notify(
|
||||||
id: formation_id,
|
removed_entities,
|
||||||
cur_role,
|
ERemoveEntityType::RemoveTypeForce,
|
||||||
role_ids: formation.role_ids.clone(),
|
|
||||||
is_current,
|
|
||||||
},
|
|
||||||
world,
|
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
player.build_player_entity_add_notify(world);
|
||||||
|
|
||||||
|
// send update group formation notify
|
||||||
|
player.notify(player.build_update_group_formation_notify(
|
||||||
|
RoleFormation {
|
||||||
|
id: formation_id,
|
||||||
|
cur_role,
|
||||||
|
role_ids: formation.role_ids.clone(),
|
||||||
|
is_current,
|
||||||
|
},
|
||||||
|
world,
|
||||||
|
));
|
||||||
|
|
||||||
response.formation = Some(formation.clone());
|
response.formation = Some(formation.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// update all formation and check formation_list
|
|
||||||
player
|
|
||||||
.formation_list
|
|
||||||
.entry(formation_id)
|
|
||||||
.and_modify(|r| {
|
|
||||||
r.cur_role = formation.cur_role;
|
|
||||||
r.role_ids = formation.role_ids.clone();
|
|
||||||
r.is_current = is_current;
|
|
||||||
})
|
|
||||||
.or_insert(RoleFormation {
|
|
||||||
id: formation_id,
|
|
||||||
cur_role: formation.cur_role,
|
|
||||||
role_ids: formation.role_ids,
|
|
||||||
is_current,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
player.notify(player.build_update_formation_notify());
|
player.notify(player.build_update_formation_notify());
|
||||||
|
|
|
@ -73,5 +73,7 @@ pub fn on_unlock_role_skin_list_request(
|
||||||
response: &mut UnlockRoleSkinListResponse,
|
response: &mut UnlockRoleSkinListResponse,
|
||||||
) {
|
) {
|
||||||
// TODO: port this from golang
|
// 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<_>>();
|
||||||
}
|
}
|
|
@ -12,6 +12,10 @@ pub struct ExploreTools {
|
||||||
pub roulette: Roulette,
|
pub roulette: Roulette,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ADDITIONAL_ROULETTE: &[i32] = &[
|
||||||
|
1015 // flight
|
||||||
|
];
|
||||||
|
|
||||||
impl ExploreTools {
|
impl ExploreTools {
|
||||||
pub fn build_save_data(&self) -> PlayerExploreToolsData {
|
pub fn build_save_data(&self) -> PlayerExploreToolsData {
|
||||||
PlayerExploreToolsData {
|
PlayerExploreToolsData {
|
||||||
|
@ -63,6 +67,16 @@ impl ExploreTools {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.for_each(|(i, e)| roulette[i] = e.phantom_skill_id);
|
.for_each(|(i, e)| roulette[i] = e.phantom_skill_id);
|
||||||
|
|
||||||
|
let mut count = 2;
|
||||||
|
|
||||||
|
explore_tools_data::iter()
|
||||||
|
.for_each(|e| {
|
||||||
|
if ADDITIONAL_ROULETTE.contains(&e.phantom_skill_id) {
|
||||||
|
count += 1;
|
||||||
|
roulette[count] = e.phantom_skill_id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
roulette
|
roulette
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,11 @@ use wicked_waifus_protocol::message::Message;
|
||||||
use wicked_waifus_protocol::player_attr::Value;
|
use wicked_waifus_protocol::player_attr::Value;
|
||||||
use wicked_waifus_protocol::{
|
use wicked_waifus_protocol::{
|
||||||
AdventreTask, AdventureManualData, AdventureUpdateNotify, AdviceSettingNotify, BuffItemNotify,
|
AdventreTask, AdventureManualData, AdventureUpdateNotify, AdviceSettingNotify, BuffItemNotify,
|
||||||
ControlInfoNotify, EEntityType, ERemoveEntityType, EnergyInfo, EnergyUpdateNotify,
|
ControlInfoNotify, ERemoveEntityType, EnergyInfo, EnergyUpdateNotify,
|
||||||
EntityAddNotify, EntityConfigType, EntityPb, EntityRemoveInfo, EntityRemoveNotify, EntityState,
|
EntityRemoveInfo, EntityRemoveNotify,
|
||||||
FavorItem, FightFormationNotifyInfo, FightRoleInfo, FightRoleInfos, FormationRoleInfo,
|
FavorItem, FightFormationNotifyInfo, FightRoleInfo, FightRoleInfos, FormationRoleInfo,
|
||||||
GroupFormation, HostTeleportUnlockNotify, InstDataNotify, ItemPkgOpenNotify,
|
GroupFormation, HostTeleportUnlockNotify, InstDataNotify, ItemPkgOpenNotify,
|
||||||
LevelPlayInfoNotify, LivingStatus, MailInfosNotify, MapUnlockFieldNotify,
|
LevelPlayInfoNotify, LivingStatus, MailInfosNotify,
|
||||||
MonthCardDailyRewardNotify, MoonChasingTargetGetCountNotify,
|
MonthCardDailyRewardNotify, MoonChasingTargetGetCountNotify,
|
||||||
MoonChasingTrackMoonHandbookRewardNotify, NormalItemUpdateNotify, PassiveSkillNotify,
|
MoonChasingTrackMoonHandbookRewardNotify, NormalItemUpdateNotify, PassiveSkillNotify,
|
||||||
PbGetRoleListNotify, PlayerAttr, PlayerAttrKey, PlayerAttrNotify, PlayerAttrType,
|
PbGetRoleListNotify, PlayerAttr, PlayerAttrKey, PlayerAttrNotify, PlayerAttrType,
|
||||||
|
@ -24,11 +24,12 @@ use wicked_waifus_protocol::{
|
||||||
};
|
};
|
||||||
use wicked_waifus_protocol_internal::{PlayerBasicData, PlayerRoleData, PlayerSaveData};
|
use wicked_waifus_protocol_internal::{PlayerBasicData, PlayerRoleData, PlayerSaveData};
|
||||||
|
|
||||||
|
use super::ecs::component::ComponentContainer;
|
||||||
|
use super::utils::world_util::add_player_entities;
|
||||||
use super::{
|
use super::{
|
||||||
ecs::world::World,
|
ecs::world::World,
|
||||||
role::{Role, RoleFormation},
|
role::{Role, RoleFormation},
|
||||||
};
|
};
|
||||||
use crate::logic::components::RoleSkin;
|
|
||||||
use crate::logic::ecs::world::WorldEntity;
|
use crate::logic::ecs::world::WorldEntity;
|
||||||
use crate::logic::player::basic_info::PlayerBasicInfo;
|
use crate::logic::player::basic_info::PlayerBasicInfo;
|
||||||
use crate::logic::player::explore_tools::ExploreTools;
|
use crate::logic::player::explore_tools::ExploreTools;
|
||||||
|
@ -46,15 +47,8 @@ use crate::logic::player::player_mc_element::PlayerMcElement;
|
||||||
use crate::logic::player::player_month_card::PlayerMonthCard;
|
use crate::logic::player::player_month_card::PlayerMonthCard;
|
||||||
use crate::logic::player::player_teleports::{PlayerTeleport, PlayerTeleports};
|
use crate::logic::player::player_teleports::{PlayerTeleport, PlayerTeleports};
|
||||||
use crate::logic::player::player_tutorials::{PlayerTutorial, PlayerTutorials};
|
use crate::logic::player::player_tutorials::{PlayerTutorial, PlayerTutorials};
|
||||||
use crate::logic::{
|
|
||||||
components::{
|
|
||||||
Attribute, EntityConfig, Equip, FightBuff, Movement, OwnerPlayer, PlayerOwnedEntityMarker,
|
|
||||||
Position, Visibility, VisionSkill, SoarWingSkin
|
|
||||||
},
|
|
||||||
ecs::component::ComponentContainer,
|
|
||||||
};
|
|
||||||
use crate::session::Session;
|
use crate::session::Session;
|
||||||
use crate::{config, create_player_entity_pb, query_components};
|
use crate::{config, query_components};
|
||||||
use crate::logic::player::Element::Spectro;
|
use crate::logic::player::Element::Spectro;
|
||||||
|
|
||||||
mod basic_info;
|
mod basic_info;
|
||||||
|
@ -358,16 +352,8 @@ impl Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_player_entity_add_notify(&self, role_list: Vec<Role>, world: &mut WorldEntity) -> EntityAddNotify {
|
pub fn build_player_entity_add_notify(&self, world: &mut WorldEntity) {
|
||||||
create_player_entity_pb!(
|
add_player_entities(self, self.formation_list.get(&self.cur_formation_id).unwrap(), Some(world))
|
||||||
role_list,
|
|
||||||
self.basic_info.cur_map_id,
|
|
||||||
self,
|
|
||||||
self.basic_info.id,
|
|
||||||
self.location.position.clone(),
|
|
||||||
self.explore_tools,
|
|
||||||
world
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_player_entity_remove_notify(
|
pub fn build_player_entity_remove_notify(
|
||||||
|
@ -403,8 +389,7 @@ impl Player {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&role_id| {
|
.map(|&role_id| {
|
||||||
let entity_id = world.get_entity_id(role_id);
|
let entity_id = world.get_entity_id(role_id);
|
||||||
let role_skin =
|
let _role_skin = query_components!(world, entity_id, RoleSkin).0.unwrap();
|
||||||
query_components!(world, entity_id, RoleSkin).0.unwrap();
|
|
||||||
FightRoleInfo {
|
FightRoleInfo {
|
||||||
role_id,
|
role_id,
|
||||||
entity_id: world.get_entity_id(role_id),
|
entity_id: world.get_entity_id(role_id),
|
||||||
|
|
|
@ -8,7 +8,8 @@ pub struct RoleFormation {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Will be updated every version
|
// Will be updated every version
|
||||||
const DEFAULT_FORMATION: &[i32] = &[1506, 1407, 1507];//5101, 1407, 1507]; // 5022 MChibi 5023 FChibi //5023, 5025, 5026 //1607
|
// const DEFAULT_FORMATION: &[i32] = &[5101, 1407, 1507];
|
||||||
|
const DEFAULT_FORMATION: &[i32] = &[1506, 1207, 1409];
|
||||||
|
|
||||||
impl RoleFormation {
|
impl RoleFormation {
|
||||||
pub fn default_roles() -> &'static [i32] {
|
pub fn default_roles() -> &'static [i32] {
|
||||||
|
|
|
@ -158,13 +158,13 @@ impl Role {
|
||||||
// Overwrite dynamic attributes with stores values
|
// Overwrite dynamic attributes with stores values
|
||||||
let mut base_stats = get_role_props_by_level(self.role_id, self.level, self.breakthrough);
|
let mut base_stats = get_role_props_by_level(self.role_id, self.level, self.breakthrough);
|
||||||
// TODO: Integrity check, value has to be between 0 and max
|
// TODO: Integrity check, value has to be between 0 and max
|
||||||
base_stats.life = self.hp;
|
base_stats.life = base_stats.life_max;
|
||||||
base_stats.energy = self.energy;
|
base_stats.energy = base_stats.energy_max;
|
||||||
base_stats.special_energy_1 = self.special_energy_1;
|
base_stats.special_energy_1 = self.special_energy_1;
|
||||||
base_stats.special_energy_2 = self.special_energy_2;
|
base_stats.special_energy_2 = self.special_energy_2;
|
||||||
base_stats.special_energy_3 = self.special_energy_3;
|
base_stats.special_energy_3 = self.special_energy_3;
|
||||||
base_stats.special_energy_4 = self.special_energy_4;
|
base_stats.special_energy_4 = self.special_energy_4;
|
||||||
base_stats.element_energy = self.element_energy;
|
base_stats.element_energy = base_stats.element_energy_max;
|
||||||
base_stats
|
base_stats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
use wicked_waifus_commons::time_util;
|
use super::{ecs::world::World, player::Player, utils::world_util};
|
||||||
use wicked_waifus_protocol_internal::PlayerSaveData;
|
use crate::logic::ecs::world::WorldEntity;
|
||||||
use wicked_waifus_protocol::{message::Message, AfterJoinSceneNotify, EnterGameResponse, JoinSceneNotify, SilenceNpcNotify, TransitionOptionPb};
|
use crate::{
|
||||||
|
logic,
|
||||||
|
player_save_task::{self, PlayerSaveReason},
|
||||||
|
session::Session,
|
||||||
|
};
|
||||||
use std::collections::hash_map::Entry::Vacant;
|
use std::collections::hash_map::Entry::Vacant;
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
@ -13,16 +17,20 @@ use std::{
|
||||||
thread,
|
thread,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
use super::{ecs::world::World, player::Player, utils::world_util};
|
use wicked_waifus_commons::time_util;
|
||||||
use crate::logic::ecs::world::WorldEntity;
|
use wicked_waifus_protocol::{
|
||||||
use crate::{logic, player_save_task::{self, PlayerSaveReason}, session::Session};
|
message::Message, AfterJoinSceneNotify, EnterGameResponse, JoinSceneNotify, SilenceNpcNotify,
|
||||||
|
TransitionOptionPb,
|
||||||
|
};
|
||||||
|
use wicked_waifus_protocol::{FormationAttr, FormationAttrNotify};
|
||||||
|
use wicked_waifus_protocol_internal::PlayerSaveData;
|
||||||
|
|
||||||
pub enum LogicInput {
|
pub enum LogicInput {
|
||||||
AddPlayer {
|
AddPlayer {
|
||||||
player_id: i32,
|
player_id: i32,
|
||||||
enter_rpc_id: u16,
|
enter_rpc_id: u16,
|
||||||
session: Arc<Session>,
|
session: Arc<Session>,
|
||||||
player_save_data: PlayerSaveData,
|
player_save_data: Box<PlayerSaveData>,
|
||||||
},
|
},
|
||||||
RemovePlayer {
|
RemovePlayer {
|
||||||
player_id: i32,
|
player_id: i32,
|
||||||
|
@ -132,16 +140,14 @@ fn handle_logic_input(state: &mut LogicState, input: LogicInput) {
|
||||||
} => {
|
} => {
|
||||||
let (player, is_player) = if let Vacant(e) = state.players.entry(player_id) {
|
let (player, is_player) = if let Vacant(e) = state.players.entry(player_id) {
|
||||||
(
|
(
|
||||||
e.insert(RefCell::new(Player::load_from_save(player_save_data))),
|
e.insert(RefCell::new(Player::load_from_save(*player_save_data))),
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
} else if let Some(player) = state.players.get_mut(&player_id) {
|
||||||
|
(player, false)
|
||||||
} else {
|
} else {
|
||||||
if let Some(player) = state.players.get_mut(&player_id) {
|
tracing::warn!("logic_thread: get player requested, but player {player_id} with data doesn't exist");
|
||||||
(player, false)
|
return;
|
||||||
} else {
|
|
||||||
tracing::warn!("logic_thread: get player requested, but player {player_id} with data doesn't exist");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut player = player.borrow_mut();
|
let mut player = player.borrow_mut();
|
||||||
|
@ -163,8 +169,7 @@ fn handle_logic_input(state: &mut LogicState, input: LogicInput) {
|
||||||
.world
|
.world
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_in_world_player_data(player.build_in_world_player());
|
.set_in_world_player_data(player.build_in_world_player());
|
||||||
|
world_util::add_player_entities(&player, player.formation_list.get(&player.cur_formation_id).unwrap(), None);
|
||||||
world_util::add_player_entities(&player);
|
|
||||||
let scene_info = world_util::build_scene_information(&player);
|
let scene_info = world_util::build_scene_information(&player);
|
||||||
|
|
||||||
player.notify(SilenceNpcNotify::default());
|
player.notify(SilenceNpcNotify::default());
|
||||||
|
@ -175,6 +180,26 @@ fn handle_logic_input(state: &mut LogicState, input: LogicInput) {
|
||||||
transition_option: Some(TransitionOptionPb::default()),
|
transition_option: Some(TransitionOptionPb::default()),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
player.notify(FormationAttrNotify {
|
||||||
|
duration: 1534854458,
|
||||||
|
formation_attrs: vec![
|
||||||
|
FormationAttr {
|
||||||
|
attr_id: 1,
|
||||||
|
ratio: 2400,
|
||||||
|
base_max_value: 24000,
|
||||||
|
max_value: 24000,
|
||||||
|
current_value: 24000,
|
||||||
|
},
|
||||||
|
FormationAttr {
|
||||||
|
attr_id: 10,
|
||||||
|
ratio: 2400,
|
||||||
|
base_max_value: 15000,
|
||||||
|
max_value: 15000,
|
||||||
|
current_value: 15000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
player.notify(AfterJoinSceneNotify::default());
|
player.notify(AfterJoinSceneNotify::default());
|
||||||
player.notify(player.build_update_formation_notify());
|
player.notify(player.build_update_formation_notify());
|
||||||
|
|
||||||
|
@ -211,10 +236,14 @@ fn handle_logic_input(state: &mut LogicState, input: LogicInput) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = state.worlds.remove(&player_id);
|
let removed_world = state.worlds.remove(&player_id).unwrap();
|
||||||
|
let mut removed_world_ref = removed_world.borrow_mut();
|
||||||
|
let world = removed_world_ref.get_mut_world_entity();
|
||||||
|
for entity_id in world.get_all_entity_ids() {
|
||||||
|
world.remove_entity(entity_id);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: kick co-op players from removed world
|
// TODO: kick co-op players from removed world
|
||||||
// TODO: Remove all entities
|
|
||||||
|
|
||||||
player_save_task::push(
|
player_save_task::push(
|
||||||
player_id,
|
player_id,
|
||||||
player.borrow().build_save_data(),
|
player.borrow().build_save_data(),
|
||||||
|
|
|
@ -1,303 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use wicked_waifus_protocol::{CommonTagData, EntityCommonTagNotify, EntityStateReadyNotify, ItemRewardNotify, NormalItemUpdateNotify, RewardItemInfo, WR};
|
|
||||||
|
|
||||||
use wicked_waifus_data::pb_components::action::{Action, ChangeSelfEntityState, UnlockTeleportTrigger};
|
|
||||||
use wicked_waifus_data::pb_components::entity_state::EntityStateComponent;
|
|
||||||
|
|
||||||
use crate::logic::ecs::component::ComponentContainer;
|
|
||||||
use crate::logic::player::{ItemUsage, Player};
|
|
||||||
use crate::logic::utils::tag_utils;
|
|
||||||
use crate::query_components;
|
|
||||||
|
|
||||||
macro_rules! unimplemented_action {
|
|
||||||
($action:ident) => {
|
|
||||||
{
|
|
||||||
tracing::warn!("Action not implemented for: {:?}", $action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn perform_action(player: &mut Player,
|
|
||||||
entity_id: i64,
|
|
||||||
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
|
||||||
template_config: &wicked_waifus_data::TemplateConfigData,
|
|
||||||
element: Action) {
|
|
||||||
match element {
|
|
||||||
Action::SetBattleState(action) => unimplemented_action! { action },
|
|
||||||
Action::ExecBattleAction(action) => unimplemented_action! { action },
|
|
||||||
Action::WaitBattleCondition(action) => unimplemented_action! { action },
|
|
||||||
Action::PlayFlow(action) => unimplemented_action! { action },
|
|
||||||
Action::Collect(_) => collect_action(player, level_entity_data, template_config),
|
|
||||||
Action::LeisureInteract(action) => unimplemented_action! { action },
|
|
||||||
Action::UnlockTeleportTrigger(action) => unlock_teleport_trigger(player, action.params),
|
|
||||||
Action::EnableTemporaryTeleport(action) => unimplemented_action! { action },
|
|
||||||
Action::OpenSystemBoard(action) => unimplemented_action! { action },
|
|
||||||
Action::OpenSystemFunction(action) => unimplemented_action! { action },
|
|
||||||
Action::ChangeSelfEntityState(action) => change_self_entity_state(player, entity_id, level_entity_data, template_config, action.params),
|
|
||||||
Action::SetPlayerOperationRestriction(action) => unimplemented_action! { action },
|
|
||||||
Action::Wait(action) => unimplemented_action! { action },
|
|
||||||
Action::ChangeEntityState(action) => unimplemented_action! { action },
|
|
||||||
Action::Log(action) => unimplemented_action! { action },
|
|
||||||
Action::EnableNearbyTracking(action) => unimplemented_action! { action },
|
|
||||||
Action::TeleportDungeon(action) => unimplemented_action! { action },
|
|
||||||
Action::DestroySelf(action) => unimplemented_action! { action },
|
|
||||||
Action::CameraLookAt(action) => unimplemented_action! { action },
|
|
||||||
Action::EnterOrbitalCamera(action) => unimplemented_action! { action },
|
|
||||||
Action::ExitOrbitalCamera(action) => unimplemented_action! { action },
|
|
||||||
Action::SendAiEvent(action) => unimplemented_action! { action },
|
|
||||||
Action::SetInteractionLockState(action) => unimplemented_action! { action },
|
|
||||||
Action::AwakeEntity(action) => unimplemented_action! { action },
|
|
||||||
Action::ChangeLiftTarget(action) => unimplemented_action! { action },
|
|
||||||
Action::CalculateVar(action) => unimplemented_action! { action },
|
|
||||||
Action::AddBuffToPlayer(action) => unimplemented_action! { action },
|
|
||||||
Action::RemoveBuffFromPlayer(action) => unimplemented_action! { action },
|
|
||||||
Action::AddBuffToEntity(action) => unimplemented_action! { action },
|
|
||||||
Action::RemoveBuffFromEntity(action) => unimplemented_action! { action },
|
|
||||||
Action::Prompt(action) => unimplemented_action! { action },
|
|
||||||
Action::SetEntityVisible(action) => unimplemented_action! { action },
|
|
||||||
Action::DestroyEntity(action) => unimplemented_action! { action },
|
|
||||||
Action::GuideTrigger(action) => unimplemented_action! { action },
|
|
||||||
Action::TriggerCameraShake(action) => unimplemented_action! { action },
|
|
||||||
Action::SetVar(action) => unimplemented_action! { action },
|
|
||||||
Action::VehicleEnter(action) => unimplemented_action! { action },
|
|
||||||
Action::VehicleExitPlayer(action) => unimplemented_action! { action },
|
|
||||||
Action::LockEntity(action) => unimplemented_action! { action },
|
|
||||||
Action::UnlockEntity(action) => unimplemented_action! { action },
|
|
||||||
Action::CommonTip(action) => unimplemented_action! { action },
|
|
||||||
Action::CommonTip2(action) => unimplemented_action! { action },
|
|
||||||
Action::PostAkEvent(action) => unimplemented_action! { action },
|
|
||||||
Action::VehicleEnterNpc(action) => unimplemented_action! { action },
|
|
||||||
Action::VehicleExitNpc(action) => unimplemented_action! { action },
|
|
||||||
Action::PlayerLookAt(action) => unimplemented_action! { action },
|
|
||||||
Action::PlayBubble(action) => unimplemented_action! { action },
|
|
||||||
Action::AddPlayBubble(action) => unimplemented_action! { action },
|
|
||||||
Action::ClearPlayBubble(action) => unimplemented_action! { action },
|
|
||||||
Action::ExecRiskHarvestEffect(action) => unimplemented_action! { action },
|
|
||||||
Action::EnableLevelPlay(action) => unimplemented_action! { action },
|
|
||||||
Action::ClaimLevelPlayReward(action) => unimplemented_action! { action },
|
|
||||||
Action::SettlementDungeon(action) => unimplemented_action! { action },
|
|
||||||
Action::ExitDungeon(action) => unimplemented_action! { action },
|
|
||||||
Action::FinishDungeon(action) => unimplemented_action! { action },
|
|
||||||
Action::RecordDungeonEvent(action) => unimplemented_action! { action },
|
|
||||||
Action::RecoverDurability(action) => unimplemented_action! { action },
|
|
||||||
Action::FadeInScreen(action) => unimplemented_action! { action },
|
|
||||||
Action::FadeOutScreen(action) => unimplemented_action! { action },
|
|
||||||
Action::ChangeNpcPerformState(action) => unimplemented_action! { action },
|
|
||||||
Action::EntityTurnTo(action) => unimplemented_action! { action },
|
|
||||||
Action::EntityLookAt(action) => unimplemented_action! { action },
|
|
||||||
Action::ToggleMapMarkState(action) => unimplemented_action! { action },
|
|
||||||
Action::RandomVar(action) => unimplemented_action! { action },
|
|
||||||
Action::ModifySceneItemAttributeTag(action) => unimplemented_action! { action },
|
|
||||||
Action::VehicleWaterfallClimbing(action) => unimplemented_action! { action },
|
|
||||||
Action::VehicleTeleport(action) => unimplemented_action! { action },
|
|
||||||
Action::RogueGotoNextFloor(action) => unimplemented_action! { action },
|
|
||||||
Action::RogueReceiveReward(action) => unimplemented_action! { action },
|
|
||||||
Action::RogueSelectRoom(action) => unimplemented_action! { action },
|
|
||||||
Action::RogueActivatePortal(action) => unimplemented_action! { action },
|
|
||||||
Action::MowingTowerGotoNextFloor(action) => unimplemented_action! { action },
|
|
||||||
Action::SlashAndTowerGotoNextFloor(action) => unimplemented_action! { action },
|
|
||||||
Action::PlayMontage(action) => unimplemented_action! { action },
|
|
||||||
Action::OpenSystemBoardWithReturn(action) => unimplemented_action! { action },
|
|
||||||
Action::UnlockSystemItem(action) => unimplemented_action! { action },
|
|
||||||
Action::SetSportsState(action) => unimplemented_action! { action },
|
|
||||||
Action::OpenSimpleGameplay(action) => unimplemented_action! { action },
|
|
||||||
Action::PlayEffect(action) => unimplemented_action! { action },
|
|
||||||
Action::PlayEffect2(action) => unimplemented_action! { action },
|
|
||||||
Action::RestorePlayerCameraAdjustment(action) => unimplemented_action! { action },
|
|
||||||
Action::AdjustPlayerCamera(action) => unimplemented_action! { action },
|
|
||||||
Action::SetPlayerPos(action) => unimplemented_action! { action },
|
|
||||||
Action::MoveWithSpline(action) => unimplemented_action! { action },
|
|
||||||
Action::EnableSplineMoveModel(action) => unimplemented_action! { action },
|
|
||||||
Action::ToggleScanSplineEffect(action) => unimplemented_action! { action },
|
|
||||||
Action::MoveSceneItem(action) => unimplemented_action! { action },
|
|
||||||
Action::StopSceneItemMove(action) => unimplemented_action! { action },
|
|
||||||
Action::FireBullet(action) => unimplemented_action! { action },
|
|
||||||
Action::ClearFishingCabinInSaleItems(action) => unimplemented_action! { action },
|
|
||||||
Action::AcceptFishingEntrust(action) => unimplemented_action! { action },
|
|
||||||
Action::DestroyFishingBoat(action) => unimplemented_action! { action },
|
|
||||||
Action::SetJigsawItem(action) => unimplemented_action! { action },
|
|
||||||
Action::SetJigsawFoundation(action) => unimplemented_action! { action },
|
|
||||||
Action::SetTeleControl(action) => unimplemented_action! { action },
|
|
||||||
Action::SetEntityClientVisible(action) => unimplemented_action! { action },
|
|
||||||
Action::ToggleHighlightExploreUi(action) => unimplemented_action! { action },
|
|
||||||
Action::ExecAlertSystemAction(action) => unimplemented_action! { action },
|
|
||||||
Action::AddFlowInteractOption(action) => unimplemented_action! { action },
|
|
||||||
Action::RemoveFlowInteractOption(action) => unimplemented_action! { action },
|
|
||||||
Action::EnableHostility(action) => unimplemented_action! { action },
|
|
||||||
Action::ChangePhantomFormation(action) => unimplemented_action! { action },
|
|
||||||
Action::RestorePhantomFormation(action) => unimplemented_action! { action },
|
|
||||||
Action::ChangeTimer(action) => unimplemented_action! { action },
|
|
||||||
Action::ToggleTimerPauseState(action) => unimplemented_action! { action },
|
|
||||||
Action::ChangeFightTeam(action) => unimplemented_action! { action },
|
|
||||||
Action::AddTrialFollowShooter(action) => unimplemented_action! { action },
|
|
||||||
Action::RemoveTrialFollowShooter(action) => unimplemented_action! { action },
|
|
||||||
Action::AddTrialCharacter(action) => unimplemented_action! { action },
|
|
||||||
Action::RemoveTrialCharacter(action) => unimplemented_action! { action },
|
|
||||||
Action::SetAreaState(action) => unimplemented_action! { action },
|
|
||||||
Action::SwitchSubLevels(action) => unimplemented_action! { action },
|
|
||||||
Action::ChangeTeamPosition(action) => unimplemented_action! { action },
|
|
||||||
Action::GetItem(action) => unimplemented_action! { action },
|
|
||||||
Action::CreatePrefab(action) => unimplemented_action! { action },
|
|
||||||
Action::DestroyPrefab(action) => unimplemented_action! { action },
|
|
||||||
Action::CompleteGuide(action) => unimplemented_action! { action },
|
|
||||||
Action::PlayDynamicSettlement(action) => unimplemented_action! { action },
|
|
||||||
Action::UsePhantomSkill(action) => unimplemented_action! { action },
|
|
||||||
Action::HideTargetRange(action) => unimplemented_action! { action },
|
|
||||||
Action::ChangeOtherState(action) => unimplemented_action! { action },
|
|
||||||
Action::SetRegionConfig(action) => unimplemented_action! { action },
|
|
||||||
Action::SetReviveRegion(action) => unimplemented_action! { action },
|
|
||||||
Action::ExecResurrection(action) => unimplemented_action! { action },
|
|
||||||
Action::ShowTargetRange(action) => unimplemented_action! { action },
|
|
||||||
Action::SetTime(action) => unimplemented_action! { action },
|
|
||||||
Action::SetTimeLockState(action) => unimplemented_action! { action },
|
|
||||||
Action::EnableSystem(action) => unimplemented_action! { action },
|
|
||||||
Action::EnableAoiNotify(action) => unimplemented_action! { action },
|
|
||||||
Action::SetForceLock(action) => unimplemented_action! { action },
|
|
||||||
Action::PlayRegisteredMontage(action) => unimplemented_action! { action },
|
|
||||||
Action::SetAudioState(action) => unimplemented_action! { action },
|
|
||||||
Action::HideGroup(action) => unimplemented_action! { action },
|
|
||||||
Action::ShowHidedGroup(action) => unimplemented_action! { action },
|
|
||||||
Action::HideSpecificEntities(action) => unimplemented_action! { action },
|
|
||||||
Action::ShowSpecificEntities(action) => unimplemented_action! { action },
|
|
||||||
Action::RemovePreloadResource(action) => unimplemented_action! { action },
|
|
||||||
Action::Preload(action) => unimplemented_action! { action },
|
|
||||||
Action::EnableAI(action) => unimplemented_action! { action },
|
|
||||||
Action::SwitchDataLayers(action) => unimplemented_action! { action },
|
|
||||||
Action::DestroyQuest(action) => unimplemented_action! { action },
|
|
||||||
Action::DestroyQuestItem(action) => unimplemented_action! { action },
|
|
||||||
Action::PromptQuestChapterUI(action) => unimplemented_action! { action },
|
|
||||||
Action::TakePlotPhoto(action) => unimplemented_action! { action },
|
|
||||||
Action::SetWuYinQuState(action) => unimplemented_action! { action },
|
|
||||||
Action::RunActions(action) => unimplemented_action! { action },
|
|
||||||
Action::ManualOccupations(action) => unimplemented_action! { action },
|
|
||||||
Action::SetWeather(action) => unimplemented_action! { action },
|
|
||||||
Action::SendNpcMail(action) => unimplemented_action! { action },
|
|
||||||
Action::EnableFunction(action) => unimplemented_action! { action },
|
|
||||||
Action::FocusOnMapMark(action) => unimplemented_action! { action },
|
|
||||||
Action::CharacterLookAt(action) => unimplemented_action! { action },
|
|
||||||
Action::AddGuestCharacter(action) => unimplemented_action! { action },
|
|
||||||
Action::RemoveGuestCharacter(action) => unimplemented_action! { action },
|
|
||||||
Action::TeleportToAndEnterVehicle(action) => unimplemented_action! { action },
|
|
||||||
Action::SetAreaTimeState(action) => unimplemented_action! { action },
|
|
||||||
Action::ResetPlayerCameraFocus(action) => unimplemented_action! { action },
|
|
||||||
Action::ResetLevelPlay(action) => unimplemented_action! { action },
|
|
||||||
Action::VehicleSprint(action) => unimplemented_action! { action },
|
|
||||||
Action::VehicleMoveWithPathLine(action) => unimplemented_action! { action },
|
|
||||||
Action::ClientPreEnableSubLevels(action) => unimplemented_action! { action },
|
|
||||||
Action::GuestOperateUiAnimation(action) => unimplemented_action! { action },
|
|
||||||
Action::ChangeEntityCamp(action) => unimplemented_action! { action },
|
|
||||||
Action::NewMoveWithSpline(action) => unimplemented_action! { action },
|
|
||||||
Action::DangoAbyssActivatePortal(action) => unimplemented_action! { action },
|
|
||||||
Action::DangoAbyssCreateRewardTreasureBox(action) => unimplemented_action! { action },
|
|
||||||
Action::DangoAbyssGotoNextFloor(action) => unimplemented_action! { action },
|
|
||||||
Action::DangoAbyssReceiveReward(action) => unimplemented_action! { action },
|
|
||||||
Action::SummonEntity(action) => unimplemented_action! { action },
|
|
||||||
Action::GetRewardByInteract(action) => unimplemented_action! { action },
|
|
||||||
Action::OpenQte(action) => unimplemented_action! { action },
|
|
||||||
Action::ActiveAntiGravitySafePoint(action) => unimplemented_action! { action },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn collect_action(player: &mut Player,
|
|
||||||
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
|
||||||
template_config: &wicked_waifus_data::TemplateConfigData) {
|
|
||||||
if let Some(reward_component) = level_entity_data.components_data.reward_component
|
|
||||||
.as_ref()
|
|
||||||
.or(template_config.components_data.reward_component.as_ref()) {
|
|
||||||
if reward_component.disabled.unwrap_or(false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: check the use of reward_type and drop_on_event
|
|
||||||
// Seems type 0 is reward from preview, while 1 and 2 is unknown
|
|
||||||
if let Some(reward_id) = reward_component.reward_id {
|
|
||||||
let drop = wicked_waifus_data::drop_package_data::get(&reward_id).unwrap();
|
|
||||||
let usages = drop.drop_preview.iter()
|
|
||||||
.map(|(&id, &quantity)| ItemUsage { id, quantity })
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let updated_items = player.inventory.add_items(&usages);
|
|
||||||
let normal_item_list = player.inventory.to_normal_item_list_filtered(
|
|
||||||
updated_items.keys().cloned().collect::<Vec<i32>>()
|
|
||||||
);
|
|
||||||
player.notify(NormalItemUpdateNotify { normal_item_list, no_tips: false });
|
|
||||||
// UpdateHandBookActiveStateMapNotify
|
|
||||||
let mut rewards: HashMap<i32, WR> = HashMap::new();
|
|
||||||
rewards.insert(0, WR {
|
|
||||||
item_list: drop.drop_preview.iter()
|
|
||||||
.map(|(&id, &quantity)| RewardItemInfo {
|
|
||||||
show_plan_id: 0, // TODO: Check how to get this
|
|
||||||
item_id: id,
|
|
||||||
count: quantity,
|
|
||||||
incr_id: 0,
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
});
|
|
||||||
player.notify(ItemRewardNotify {
|
|
||||||
drop_id: reward_id,
|
|
||||||
reason: 15000,
|
|
||||||
magnification: 1,
|
|
||||||
reward_items: rewards,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// TODO: Should we remove entity?? get pcap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn unlock_teleport_trigger(player: &mut Player, action: UnlockTeleportTrigger) {
|
|
||||||
player.unlock_teleport(action.teleport_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn change_self_entity_state(player: &mut Player,
|
|
||||||
entity_id: i64,
|
|
||||||
level_entity_data: &wicked_waifus_data::LevelEntityConfigData,
|
|
||||||
template_config: &wicked_waifus_data::TemplateConfigData,
|
|
||||||
action: ChangeSelfEntityState) {
|
|
||||||
let state = tag_utils::get_tag_id_by_name(action.entity_state.as_str());
|
|
||||||
|
|
||||||
// TODO: update Tag::CommonEntityTags too??
|
|
||||||
let old_state = {
|
|
||||||
let world_ref = player.world.borrow();
|
|
||||||
let world = world_ref.get_world_entity();
|
|
||||||
let mut state_tag = query_components!(world, entity_id, StateTag).0.unwrap();
|
|
||||||
let old_state = state_tag.state_tag_id;
|
|
||||||
tracing::debug!("ChangeSelfEntityState: old state {old_state} -> new state: {state}");
|
|
||||||
state_tag.state_tag_id = state;
|
|
||||||
old_state
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(entity_state_component) = level_entity_data.components_data.entity_state_component.as_ref()
|
|
||||||
.or(template_config.components_data.entity_state_component.as_ref()).cloned() {
|
|
||||||
let entity_state_component: EntityStateComponent = entity_state_component; // TODO: Remove this line, used for casting only
|
|
||||||
|
|
||||||
// TODO: implement rest of cases
|
|
||||||
if let Some(state_change_behaviors) = entity_state_component.state_change_behaviors {
|
|
||||||
for state_change_behavior in state_change_behaviors {
|
|
||||||
// TODO: implement rest of cases
|
|
||||||
let expected = tag_utils::get_tag_id_by_name(state_change_behavior.state.as_str());
|
|
||||||
|
|
||||||
if expected == state {
|
|
||||||
if let Some(actions) = state_change_behavior.action {
|
|
||||||
for sub in actions {
|
|
||||||
perform_action(player, entity_id, level_entity_data, template_config, sub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
player.notify(EntityCommonTagNotify {
|
|
||||||
id: entity_id,
|
|
||||||
tags: vec![
|
|
||||||
CommonTagData { tag_id: old_state, remove_tag_ids: false }, // Remove
|
|
||||||
CommonTagData { tag_id: state, remove_tag_ids: true }, // Add
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
player.notify(EntityStateReadyNotify {
|
|
||||||
entity_id,
|
|
||||||
tag_id: state,
|
|
||||||
ready: true, // TODO: Always true? or shall we compare it to something??
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -119,6 +119,11 @@ pub fn check_condition(player: &Player,
|
||||||
Condition::CheckEntityGravityDirection(condition) => unimplemented_condition! { condition },
|
Condition::CheckEntityGravityDirection(condition) => unimplemented_condition! { condition },
|
||||||
Condition::CheckTeleControlState(condition) => unimplemented_condition! { condition },
|
Condition::CheckTeleControlState(condition) => unimplemented_condition! { condition },
|
||||||
Condition::CheckEntityReward(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_element4,
|
||||||
damage_reduce_element5,
|
damage_reduce_element5,
|
||||||
damage_reduce_element6,
|
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_max,
|
||||||
energy,
|
energy,
|
||||||
special_energy_1_max,
|
special_energy_1_max,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
pub mod action_utils;
|
|
||||||
pub mod condition_utils;
|
pub mod condition_utils;
|
||||||
pub mod entity_serializer;
|
pub mod entity_serializer;
|
||||||
pub mod load_role_info;
|
pub mod load_role_info;
|
||||||
|
|
|
@ -5,7 +5,7 @@ use wicked_waifus_protocol::{
|
||||||
|
|
||||||
use wicked_waifus_data::pb_components::ComponentsData;
|
use wicked_waifus_data::pb_components::ComponentsData;
|
||||||
use wicked_waifus_data::{
|
use wicked_waifus_data::{
|
||||||
base_property_data, blueprint_config_data, template_config_data, EntityLogic, EntityType, LevelEntityConfigData
|
base_property_data, blueprint_config_data, summon_cfg_data, template_config_data, EntityLogic, EntityType, LevelEntityConfigData
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::logic::components::{Autonomous, Fsm, Interact, MonsterAi, SoarWingSkin, StateTag, Tag};
|
use crate::logic::components::{Autonomous, Fsm, Interact, MonsterAi, SoarWingSkin, StateTag, Tag};
|
||||||
|
@ -13,6 +13,7 @@ use crate::logic::ecs::entity::{Entity, EntityBuilder};
|
||||||
use crate::logic::ecs::world::{World, WorldEntity};
|
use crate::logic::ecs::world::{World, WorldEntity};
|
||||||
use crate::logic::math::Transform;
|
use crate::logic::math::Transform;
|
||||||
use crate::logic::player::Player;
|
use crate::logic::player::Player;
|
||||||
|
use crate::logic::role::RoleFormation;
|
||||||
use crate::logic::utils::growth_utils::get_monster_props_by_level;
|
use crate::logic::utils::growth_utils::get_monster_props_by_level;
|
||||||
use crate::logic::utils::{entity_serializer, tag_utils};
|
use crate::logic::utils::{entity_serializer, tag_utils};
|
||||||
use crate::logic::{
|
use crate::logic::{
|
||||||
|
@ -26,133 +27,35 @@ use crate::logic::{
|
||||||
|
|
||||||
use crate::query_with;
|
use crate::query_with;
|
||||||
|
|
||||||
#[macro_export]
|
pub fn summon_concomitant(player: &Player, world: &mut WorldEntity, template_cfg: &wicked_waifus_data::TemplateConfigData, cur_summon_id: i32) -> (Entity, Vec<i64>) {
|
||||||
macro_rules! create_player_entity_pb {
|
|
||||||
($role_list:expr, $cur_map_id:expr, $player:expr, $player_id:expr, $position:expr, $explore_tools:expr, $world:expr) => {{
|
|
||||||
let current_formation = $player
|
|
||||||
.formation_list
|
|
||||||
.get(&$player.cur_formation_id)
|
|
||||||
.unwrap();
|
|
||||||
let cur_role_id = current_formation.cur_role;
|
|
||||||
|
|
||||||
let mut pbs = Vec::new();
|
|
||||||
|
|
||||||
for role in $role_list {
|
|
||||||
let role_id: i32 = role.role_id;
|
|
||||||
let entity =
|
|
||||||
$world.create_entity(role.role_id, EEntityType::Player.into(), $cur_map_id);
|
|
||||||
let fight_buff_infos = $world.generate_role_permanent_buffs(entity.entity_id, role_id);
|
|
||||||
|
|
||||||
let buffs = FightBuff {
|
|
||||||
fight_buff_infos,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let entity = $world
|
|
||||||
.create_builder(entity)
|
|
||||||
.with(ComponentContainer::PlayerOwnedEntityMarker(
|
|
||||||
PlayerOwnedEntityMarker {
|
|
||||||
entity_type: EEntityType::Player,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
.with(ComponentContainer::EntityConfig(EntityConfig {
|
|
||||||
camp: 0,
|
|
||||||
config_id: role.role_id,
|
|
||||||
config_type: EntityConfigType::Character,
|
|
||||||
entity_type: EEntityType::Player.into(),
|
|
||||||
entity_state: EntityState::Default,
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::OwnerPlayer(OwnerPlayer($player_id)))
|
|
||||||
.with(ComponentContainer::Position(Position($position)))
|
|
||||||
.with(ComponentContainer::Visibility(Visibility {
|
|
||||||
is_visible: role.role_id == cur_role_id,
|
|
||||||
is_actor_visible: true,
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::Attribute(Attribute::from_data(
|
|
||||||
&role.get_base_properties(),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
)))
|
|
||||||
.with(ComponentContainer::Movement(Movement::default()))
|
|
||||||
.with(ComponentContainer::Equip(Equip {
|
|
||||||
weapon_id: role.equip_weapon,
|
|
||||||
weapon_breach_level: 90,
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::VisionSkill(VisionSkill {
|
|
||||||
skill_id: $explore_tools.active_explore_skill,
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::RoleSkin(RoleSkin {
|
|
||||||
skin_id: role.skin_id,
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::SoarWingSkin(SoarWingSkin {
|
|
||||||
skin_id: 84000001,
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::FightBuff(buffs))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let mut pb = EntityPb {
|
|
||||||
id: entity.entity_id as i64,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
$world
|
|
||||||
.get_entity_components(entity.entity_id)
|
|
||||||
.into_iter()
|
|
||||||
.for_each(|comp| comp.set_pb_data(&mut pb));
|
|
||||||
pbs.push(pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityAddNotify {
|
|
||||||
entity_pbs: pbs,
|
|
||||||
remove_tag_ids: true,
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn summon_concomitant(player: &Player, world: &mut WorldEntity, summon_cfg: &wicked_waifus_data::SummonCfgData) -> Entity {
|
|
||||||
let mut concomitant_buffs: Vec<FightBuffInformation> = Vec::new();
|
let mut concomitant_buffs: Vec<FightBuffInformation> = Vec::new();
|
||||||
|
|
||||||
for buff_id in &summon_cfg.born_buff_id {
|
let summon_cfg = summon_cfg_data::get(&template_cfg.blueprint_type).unwrap();
|
||||||
concomitant_buffs
|
let concomitant_config_id = template_cfg.id;
|
||||||
.push(FightBuffInformation {
|
|
||||||
handle_id: 1,
|
|
||||||
buff_id: *buff_id,
|
|
||||||
level: 1,
|
|
||||||
stack_count: 1,
|
|
||||||
instigator_id: 0,
|
|
||||||
entity_id: 0,
|
|
||||||
apply_type: 0,
|
|
||||||
duration: -1.0,
|
|
||||||
left_duration: -1.0,
|
|
||||||
context: vec![],
|
|
||||||
is_active: true,
|
|
||||||
server_id: 1,
|
|
||||||
message_id: 1,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let concomitant_id = template_config_data::get(&summon_cfg.blueprint_type).unwrap().id;
|
|
||||||
tracing::info!("Adding Concomitant with id: {}", concomitant_id);
|
|
||||||
let con_buffs = concomitant_buffs.clone();
|
|
||||||
|
|
||||||
let con_entity = world.create_entity(
|
let con_entity = world.create_entity(
|
||||||
concomitant_id,
|
cur_summon_id,
|
||||||
EEntityType::Monster.into(),
|
EEntityType::Monster.into(),
|
||||||
player.basic_info.cur_map_id,
|
player.basic_info.cur_map_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
world
|
for buff_id in &summon_cfg.born_buff_id {
|
||||||
|
concomitant_buffs.push(world.create_buff(cur_summon_id, *buff_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
tracing::info!("Adding Concomitant with id: {} and buffs {:#?}", concomitant_config_id, concomitant_buffs);
|
||||||
|
|
||||||
|
(world
|
||||||
.create_builder(con_entity)
|
.create_builder(con_entity)
|
||||||
.with(ComponentContainer::PlayerOwnedEntityMarker(PlayerOwnedEntityMarker {
|
.with(ComponentContainer::PlayerOwnedEntityMarker(PlayerOwnedEntityMarker {
|
||||||
entity_type: EEntityType::Monster,
|
entity_type: EEntityType::Monster,
|
||||||
}))
|
}))
|
||||||
.with(ComponentContainer::EntityConfig(EntityConfig {
|
.with(ComponentContainer::EntityConfig(EntityConfig {
|
||||||
camp: 0,
|
camp: 0,
|
||||||
config_id: concomitant_id,
|
config_id: concomitant_config_id,
|
||||||
config_type: EntityConfigType::Template,
|
config_type: EntityConfigType::Template,
|
||||||
entity_type: EEntityType::Monster,
|
entity_type: EEntityType::Monster,
|
||||||
entity_state: EntityState::Sleep,
|
entity_state: EntityState::Born,
|
||||||
}))
|
}))
|
||||||
.with(ComponentContainer::OwnerPlayer(OwnerPlayer(
|
.with(ComponentContainer::OwnerPlayer(OwnerPlayer(
|
||||||
player.basic_info.id,
|
player.basic_info.id,
|
||||||
|
@ -162,129 +65,194 @@ fn summon_concomitant(player: &Player, world: &mut WorldEntity, summon_cfg: &wic
|
||||||
)))
|
)))
|
||||||
.with(ComponentContainer::Visibility(Visibility {
|
.with(ComponentContainer::Visibility(Visibility {
|
||||||
is_visible: false,
|
is_visible: false,
|
||||||
is_actor_visible: false,
|
is_actor_visible: true,
|
||||||
}))
|
}))
|
||||||
.with(ComponentContainer::Attribute(Attribute::from_data(
|
.with(ComponentContainer::Attribute(Attribute::from_data(
|
||||||
base_property_data::iter()
|
base_property_data::iter()
|
||||||
.find(|d| d.id == concomitant_id as i32)
|
.find(|d| d.id == template_cfg.components_data.attribute_component.clone().unwrap().property_id.unwrap())
|
||||||
.unwrap_or_else(|| {
|
.unwrap(),
|
||||||
base_property_data::iter()
|
|
||||||
.find(|d| d.id == 390070051)
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
tracing::error!("Default base property concomitant not found!");
|
|
||||||
panic!("Critical config missing: base property concomitant")
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
)))
|
)))
|
||||||
.with(ComponentContainer::Movement(Movement::default()))
|
.with(ComponentContainer::FightBuff(FightBuff { fight_buff_infos: concomitant_buffs, ..Default::default() }))
|
||||||
.with(ComponentContainer::FightBuff(FightBuff { fight_buff_infos: con_buffs, ..Default::default() }))
|
|
||||||
.with(ComponentContainer::Summoner(Summoner {
|
.with(ComponentContainer::Summoner(Summoner {
|
||||||
summon_cfg_id: summon_cfg.id,
|
summon_cfg_id: summon_cfg.id,
|
||||||
summon_skill_id: 0,
|
summon_skill_id: 0,
|
||||||
summon_type: ESummonType::ESummonTypeConcomitantCustom.into()
|
summon_type: ESummonType::ESummonTypeConcomitantCustom.into()
|
||||||
}))
|
}))
|
||||||
.build()
|
.with(ComponentContainer::Autonomous(Autonomous { autonomous_id: 3 }))
|
||||||
|
.build(), summon_cfg.born_buff_id.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_player_entities(player: &Player) {
|
fn add_player_entity(player: &Player, formation: &RoleFormation, world: &mut WorldEntity) {
|
||||||
let mut world_ref = player.world.borrow_mut();
|
let role_vec = formation
|
||||||
let world = world_ref.get_mut_world_entity();
|
|
||||||
|
|
||||||
let current_formation = player.formation_list.get(&player.cur_formation_id).unwrap();
|
|
||||||
|
|
||||||
let role_vec = current_formation
|
|
||||||
.role_ids
|
.role_ids
|
||||||
.iter()
|
.iter()
|
||||||
.map(|role_id| player.role_list.get(role_id).unwrap())
|
.map(|role_id| player.role_list.get(role_id).unwrap())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let cur_role_id = current_formation.cur_role;
|
|
||||||
|
|
||||||
if world.active_entity_empty() {
|
tracing::info!("adding player entity for formation {:#?}", formation.role_ids);
|
||||||
for role in role_vec {
|
let cur_role_id = formation.cur_role;
|
||||||
let mut concomitants: Vec<i64> = vec![];
|
|
||||||
|
|
||||||
for (_, summon_cfg) in wicked_waifus_data::summon_cfg_data::iter().filter(|(_, cfg)| {
|
let mut pbs = Vec::new();
|
||||||
cfg.blueprint_type.starts_with("Player0") && cfg.born_buff_id.iter().any(|x| {
|
|
||||||
x.to_string().starts_with(&role.role_id.to_string())
|
for role in role_vec {
|
||||||
})
|
let entity = world.create_entity(
|
||||||
|
role.role_id,
|
||||||
|
EEntityType::Player.into(),
|
||||||
|
player.basic_info.cur_map_id,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut fight_buff_infos = world.generate_role_permanent_buffs(entity.entity_id, role.role_id);
|
||||||
|
|
||||||
|
// TODO: add actual weapon switching and remove this! - rabby
|
||||||
|
let equip_weapon = match role.role_id {
|
||||||
|
1409 => 21020056, // cartethyia
|
||||||
|
1207 => 21010036, // lupa
|
||||||
|
1301 => 21010036,
|
||||||
|
_ => role.equip_weapon,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut concomitants: Vec<i64> = vec![];
|
||||||
|
let mut concom_pbs = Vec::new();
|
||||||
|
|
||||||
|
let role_data = wicked_waifus_data::role_info_data::iter().find(|r| r.id == role.role_id).unwrap();
|
||||||
|
if let Some(skin_damage_first) = role_data.skin_damage.first() {
|
||||||
|
let role_name = skin_damage_first.as_str()
|
||||||
|
.split('/').next_back()
|
||||||
|
.and_then(|s| s.strip_prefix("DA_"))
|
||||||
|
.and_then(|s| s.split('_').next()).unwrap();
|
||||||
|
|
||||||
|
let mut summon_id = 1000;
|
||||||
|
for model_config in wicked_waifus_data::model_config_preload_data::iter().filter(|cfg| {
|
||||||
|
cfg.actor_class_path.starts_with("/Game/Aki/Character/Monster/Summon/") && cfg.actor_class_path.contains(role_name)
|
||||||
}) {
|
}) {
|
||||||
let concomitant = summon_concomitant(player, world, summon_cfg);
|
let template_cfg = wicked_waifus_data::template_config_data::iter().find(|cfg| {
|
||||||
|
let template_model_component = cfg.1.components_data.model_component.clone();
|
||||||
|
template_model_component.is_some()
|
||||||
|
&&
|
||||||
|
template_model_component.clone().unwrap().model_type.unwrap().model_id.is_some()
|
||||||
|
&&
|
||||||
|
template_model_component.unwrap().model_type.unwrap().model_id.unwrap() == model_config.id
|
||||||
|
}).unwrap().1;
|
||||||
|
|
||||||
|
let (concomitant, buffs) = summon_concomitant(player, world, template_cfg, summon_id);
|
||||||
|
let mut pb = EntityPb {
|
||||||
|
id: summon_id as i64,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
for buff_id in buffs {
|
||||||
|
fight_buff_infos.push(world.create_buff(entity.entity_id, buff_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
world
|
||||||
|
.get_entity_components(summon_id)
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|comp| comp.set_pb_data(&mut pb));
|
||||||
|
concom_pbs.push(pb);
|
||||||
|
summon_id += 1;
|
||||||
concomitants.push(concomitant.entity_id.into());
|
concomitants.push(concomitant.entity_id.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let entity = world.create_entity(
|
player.notify(EntityAddNotify {
|
||||||
role.role_id,
|
entity_pbs: concom_pbs,
|
||||||
EEntityType::Player.into(),
|
remove_tag_ids: true,
|
||||||
player.basic_info.cur_map_id,
|
});
|
||||||
);
|
|
||||||
let fight_buff_infos = world.generate_role_permanent_buffs(entity.entity_id, role.role_id);
|
|
||||||
let buf_manager = FightBuff {
|
|
||||||
fight_buff_infos,
|
|
||||||
list_buff_effect_cd: vec![]
|
|
||||||
};
|
|
||||||
let entity = world
|
|
||||||
.create_builder(entity)
|
|
||||||
.with(ComponentContainer::PlayerOwnedEntityMarker(
|
|
||||||
PlayerOwnedEntityMarker {
|
|
||||||
entity_type: EEntityType::Player,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
.with(ComponentContainer::EntityConfig(EntityConfig {
|
|
||||||
camp: 0,
|
|
||||||
config_id: role.role_id,
|
|
||||||
config_type: EntityConfigType::Character,
|
|
||||||
entity_type: EEntityType::Player,
|
|
||||||
entity_state: EntityState::Default,
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::OwnerPlayer(OwnerPlayer(
|
|
||||||
player.basic_info.id,
|
|
||||||
)))
|
|
||||||
.with(ComponentContainer::Position(Position(
|
|
||||||
player.location.position.clone(),
|
|
||||||
)))
|
|
||||||
.with(ComponentContainer::Visibility(Visibility {
|
|
||||||
is_visible: role.role_id == cur_role_id,
|
|
||||||
is_actor_visible: true,
|
|
||||||
}))
|
|
||||||
// TODO: from role
|
|
||||||
// TODO: Check if role has hardness or rage_mode
|
|
||||||
// TODO: Support AddProp from Equipment(Echo, weapon, buffs??), weapon base state goes to base_prop too.
|
|
||||||
.with(ComponentContainer::Attribute(Attribute::from_data(
|
|
||||||
&role.get_base_properties(),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
)))
|
|
||||||
.with(ComponentContainer::Movement(Movement::default()))
|
|
||||||
.with(ComponentContainer::Equip(Equip {
|
|
||||||
weapon_id: role.equip_weapon,
|
|
||||||
weapon_breach_level: 0, // TODO: store this too
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::VisionSkill(VisionSkill {
|
|
||||||
skill_id: player.explore_tools.active_explore_skill,
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::RoleSkin(RoleSkin {
|
|
||||||
skin_id: role.skin_id,
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::SoarWingSkin(SoarWingSkin {
|
|
||||||
skin_id: 84000001,
|
|
||||||
}))
|
|
||||||
.with(ComponentContainer::FightBuff(buf_manager))
|
|
||||||
.with(ComponentContainer::Concomitant(Concomitant {
|
|
||||||
vision_entity_id: 0,
|
|
||||||
custom_entity_ids: concomitants,
|
|
||||||
phantom_role_id: 0,
|
|
||||||
}))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
tracing::debug!(
|
|
||||||
"created player entity, id: {}, role_id: {}",
|
|
||||||
entity.entity_id,
|
|
||||||
role.role_id
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
fight_buff_infos.dedup_by(|x, z| x.buff_id == z.buff_id);
|
||||||
|
|
||||||
|
let buf_manager = FightBuff {
|
||||||
|
fight_buff_infos,
|
||||||
|
list_buff_effect_cd: vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
let entity = world
|
||||||
|
.create_builder(entity)
|
||||||
|
.with(ComponentContainer::PlayerOwnedEntityMarker(
|
||||||
|
PlayerOwnedEntityMarker {
|
||||||
|
entity_type: EEntityType::Player,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.with(ComponentContainer::EntityConfig(EntityConfig {
|
||||||
|
camp: 0,
|
||||||
|
config_id: role.role_id,
|
||||||
|
config_type: EntityConfigType::Character,
|
||||||
|
entity_type: EEntityType::Player,
|
||||||
|
entity_state: EntityState::Default,
|
||||||
|
}))
|
||||||
|
.with(ComponentContainer::OwnerPlayer(OwnerPlayer(
|
||||||
|
player.basic_info.id,
|
||||||
|
)))
|
||||||
|
.with(ComponentContainer::Position(Position(
|
||||||
|
player.location.position.clone(),
|
||||||
|
)))
|
||||||
|
.with(ComponentContainer::Visibility(Visibility {
|
||||||
|
is_visible: role.role_id == cur_role_id,
|
||||||
|
is_actor_visible: true,
|
||||||
|
}))
|
||||||
|
// TODO: from role
|
||||||
|
// TODO: Check if role has hardness or rage_mode
|
||||||
|
// TODO: Support AddProp from Equipment(Echo, weapon, buffs??), weapon base state goes to base_prop too.
|
||||||
|
.with(ComponentContainer::Attribute(Attribute::from_data(
|
||||||
|
&role.get_base_properties(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)))
|
||||||
|
.with(ComponentContainer::Movement(Movement::default()))
|
||||||
|
.with(ComponentContainer::Equip(Equip {
|
||||||
|
weapon_id: equip_weapon,
|
||||||
|
weapon_breach_level: 0, // TODO: store this too
|
||||||
|
}))
|
||||||
|
.with(ComponentContainer::VisionSkill(VisionSkill {
|
||||||
|
skill_id: player.explore_tools.active_explore_skill,
|
||||||
|
}))
|
||||||
|
.with(ComponentContainer::RoleSkin(RoleSkin {
|
||||||
|
skin_id: role.skin_id,
|
||||||
|
}))
|
||||||
|
.with(ComponentContainer::SoarWingSkin(SoarWingSkin {
|
||||||
|
skin_id: 84000001,
|
||||||
|
}))
|
||||||
|
.with(ComponentContainer::FightBuff(buf_manager))
|
||||||
|
.with(ComponentContainer::Concomitant(Concomitant {
|
||||||
|
vision_entity_id: 0,
|
||||||
|
custom_entity_ids: concomitants,
|
||||||
|
phantom_role_id: 0
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let mut pb = EntityPb {
|
||||||
|
id: entity.entity_id as i64,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
world
|
||||||
|
.get_entity_components(entity.entity_id)
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|comp| comp.set_pb_data(&mut pb));
|
||||||
|
pbs.push(pb);
|
||||||
|
|
||||||
|
tracing::debug!(
|
||||||
|
"created player entity, id: {}, role_id: {}",
|
||||||
|
entity.entity_id,
|
||||||
|
role.role_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
player.notify(EntityAddNotify {
|
||||||
|
entity_pbs: pbs,
|
||||||
|
remove_tag_ids: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_player_entities(player: &Player, formation: &RoleFormation, possible_world: Option<&mut WorldEntity>) {
|
||||||
|
match possible_world {
|
||||||
|
Some(world) => add_player_entity(player, formation, world),
|
||||||
|
None => {
|
||||||
|
let mut world_ref = player.world.borrow_mut();
|
||||||
|
add_player_entity(player, formation, world_ref.get_mut_world_entity())
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_scene_information(player: &Player) -> SceneInformation {
|
pub fn build_scene_information(player: &Player) -> SceneInformation {
|
||||||
|
|
|
@ -51,12 +51,12 @@ async fn handler_loop(
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
tracing::debug!(
|
// tracing::debug!(
|
||||||
"received message from service: {}, rpc_id: {} message_id: {}",
|
// "received message from service: {}, rpc_id: {} message_id: {}",
|
||||||
message.src_service_id,
|
// message.src_service_id,
|
||||||
message.rpc_id,
|
// message.rpc_id,
|
||||||
message.message_id
|
// message.message_id
|
||||||
);
|
// );
|
||||||
|
|
||||||
match message.message_id {
|
match message.message_id {
|
||||||
CreatePlayerDataRequest::MESSAGE_ID => {
|
CreatePlayerDataRequest::MESSAGE_ID => {
|
||||||
|
@ -141,7 +141,7 @@ async fn on_start_player_session_request(
|
||||||
player_id: player_data.player_id,
|
player_id: player_data.player_id,
|
||||||
enter_rpc_id: message.rpc_id,
|
enter_rpc_id: message.rpc_id,
|
||||||
session: session.clone(),
|
session: session.clone(),
|
||||||
player_save_data,
|
player_save_data: Box::new(player_save_data),
|
||||||
});
|
});
|
||||||
|
|
||||||
session_mgr.add(session.clone());
|
session_mgr.add(session.clone());
|
||||||
|
|
|
@ -4,14 +4,19 @@ edition = "2021"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
|
||||||
[features]
|
[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 = []
|
debug-msg = []
|
||||||
|
ack-cmd-conv = []
|
||||||
|
ack-cmd-conv-crc-mtu = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Framework
|
# Framework
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
|
|
||||||
# Networking
|
# Networking
|
||||||
kcp = { workspace = true, features = ["tokio"] }
|
kcp = { git = "https://git.xeondev.com/ReversedRoomsMisc/kcp-rs.git", features = ["wuthering-waves-old", "tokio"] }
|
||||||
|
|
||||||
# Serialization
|
# Serialization
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
|
|
@ -2,6 +2,7 @@ service_id = 1
|
||||||
|
|
||||||
[network]
|
[network]
|
||||||
kcp_port = 7777
|
kcp_port = 7777
|
||||||
|
kcp_crc = false
|
||||||
|
|
||||||
[protokey]
|
[protokey]
|
||||||
builtin_encryption_msg_id = [111, 112]
|
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)]
|
#[derive(Deserialize)]
|
||||||
pub struct NetworkSettings {
|
pub struct NetworkSettings {
|
||||||
pub kcp_port: u16,
|
pub kcp_port: u16,
|
||||||
|
pub kcp_crc: Option<bool>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TomlConfig for ServerConfig {
|
impl TomlConfig for ServerConfig {
|
||||||
|
|
|
@ -38,6 +38,7 @@ async fn main() -> Result<()> {
|
||||||
let server = UdpServer::new(
|
let server = UdpServer::new(
|
||||||
&CONFIG.network,
|
&CONFIG.network,
|
||||||
PROTOKEY_HELPER.get_or_init(|| protokey_helper),
|
PROTOKEY_HELPER.get_or_init(|| protokey_helper),
|
||||||
|
CONFIG.network.kcp_crc.unwrap_or(false),
|
||||||
&SESSION_MGR,
|
&SESSION_MGR,
|
||||||
Arc::new(database),
|
Arc::new(database),
|
||||||
)
|
)
|
||||||
|
|
|
@ -41,6 +41,7 @@ impl Session {
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
socket: Arc<UdpSocket>,
|
socket: Arc<UdpSocket>,
|
||||||
helper: &'static ServerProtoKeyHelper,
|
helper: &'static ServerProtoKeyHelper,
|
||||||
|
use_crc: bool,
|
||||||
database: Arc<PgPool>,
|
database: Arc<PgPool>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let output = SessionOutput {
|
let output = SessionOutput {
|
||||||
|
@ -51,7 +52,7 @@ impl Session {
|
||||||
let cur_time_ms = time_util::unix_timestamp_ms();
|
let cur_time_ms = time_util::unix_timestamp_ms();
|
||||||
Self {
|
Self {
|
||||||
protokey_helper: helper,
|
protokey_helper: helper,
|
||||||
kcp: Kcp::new(conv_id, true, output),
|
kcp: Kcp::new(conv_id, 0, use_crc, 0, true, output),
|
||||||
decoder: LengthFieldBasedDecoder::new(),
|
decoder: LengthFieldBasedDecoder::new(),
|
||||||
start_time_ms: cur_time_ms,
|
start_time_ms: cur_time_ms,
|
||||||
last_heartbeat_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 {
|
pub struct UdpServer {
|
||||||
socket: Arc<UdpSocket>,
|
socket: Arc<UdpSocket>,
|
||||||
protokey_helper: &'static ServerProtoKeyHelper,
|
protokey_helper: &'static ServerProtoKeyHelper,
|
||||||
|
kcp_use_crc: bool,
|
||||||
session_mgr: &'static SessionManager,
|
session_mgr: &'static SessionManager,
|
||||||
db: Arc<PgPool>,
|
db: Arc<PgPool>,
|
||||||
}
|
}
|
||||||
|
@ -21,6 +22,7 @@ impl UdpServer {
|
||||||
pub async fn new(
|
pub async fn new(
|
||||||
network_settings: &'static NetworkSettings,
|
network_settings: &'static NetworkSettings,
|
||||||
protokey_helper: &'static ServerProtoKeyHelper,
|
protokey_helper: &'static ServerProtoKeyHelper,
|
||||||
|
kcp_use_crc: bool,
|
||||||
session_mgr: &'static SessionManager,
|
session_mgr: &'static SessionManager,
|
||||||
db: Arc<PgPool>,
|
db: Arc<PgPool>,
|
||||||
) -> Result<Self, tokio::io::Error> {
|
) -> Result<Self, tokio::io::Error> {
|
||||||
|
@ -29,6 +31,7 @@ impl UdpServer {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
socket: Arc::new(socket),
|
socket: Arc::new(socket),
|
||||||
protokey_helper,
|
protokey_helper,
|
||||||
|
kcp_use_crc,
|
||||||
session_mgr,
|
session_mgr,
|
||||||
db,
|
db,
|
||||||
})
|
})
|
||||||
|
@ -65,6 +68,7 @@ impl UdpServer {
|
||||||
addr,
|
addr,
|
||||||
self.socket.clone(),
|
self.socket.clone(),
|
||||||
self.protokey_helper,
|
self.protokey_helper,
|
||||||
|
self.kcp_use_crc,
|
||||||
self.db.clone(),
|
self.db.clone(),
|
||||||
);
|
);
|
||||||
self.session_mgr.add(conv_id, session);
|
self.session_mgr.add(conv_id, session);
|
||||||
|
@ -72,6 +76,11 @@ impl UdpServer {
|
||||||
let mut ack = Vec::with_capacity(5);
|
let mut ack = Vec::with_capacity(5);
|
||||||
ack.push(Self::CMD_ACK);
|
ack.push(Self::CMD_ACK);
|
||||||
ack.extend(conv_id.to_le_bytes());
|
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;
|
let _ = self.socket.send_to(&ack, addr).await;
|
||||||
|
|
||||||
tracing::debug!("new connection from {addr}, conv_id: {conv_id}");
|
tracing::debug!("new connection from {addr}, conv_id: {conv_id}");
|
||||||
|
|
Loading…
Reference in a new issue