Compare commits
17 commits
master
...
automatic+
Author | SHA1 | Date | |
---|---|---|---|
|
5e68a19066 | ||
|
f372bc9914 | ||
|
1480baae70 | ||
|
3adf8cdc19 | ||
|
e5211c759a | ||
|
af681c8f15 | ||
|
ce265b89ca | ||
|
b3c5e03786 | ||
|
5f4cac9da9 | ||
|
e9ea58bf75 | ||
4d9035b663 | |||
8af090bcac | |||
8bda4f0d01 | |||
8ec70fa371 | |||
b93485bee1 | |||
ffeda38057 | |||
|
5d3c0e90fc |
28 changed files with 1229 additions and 662 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
wicked-waifus-data/src/buff.rs
Normal file
12
wicked-waifus-data/src/buff.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct BuffData {
|
||||
pub id: i64,
|
||||
pub ge_desc: String,
|
||||
pub duration_policy: i32,
|
||||
pub extra_effect_parameters: Option<Vec<String>>,
|
||||
pub game_attribute_i_d: i32
|
||||
}
|
|
@ -138,6 +138,7 @@ json_data! {
|
|||
LevelPlayNodeData;
|
||||
LivenessTask;
|
||||
LordGym;
|
||||
ModelConfigPreload;
|
||||
MonsterDetection;
|
||||
MonsterPropertyGrowth;
|
||||
Motion;
|
||||
|
@ -168,8 +169,9 @@ json_hash_table_data! {
|
|||
DragonPool, id, i32;
|
||||
DropPackage, id, i32;
|
||||
TemplateConfig, blueprint_type, String;
|
||||
SummonCfg, blueprint_type, String;
|
||||
Buff, id, i64;
|
||||
}
|
||||
|
||||
mod level_entity_config;
|
||||
|
||||
pub mod level_entity_config_data {
|
||||
|
@ -184,7 +186,10 @@ pub mod level_entity_config_data {
|
|||
}
|
||||
|
||||
pub fn get(map_id: i32, entity_id: i64) -> Option<&'static Data> {
|
||||
TABLE.get().unwrap().get(&create_key_internal(map_id, entity_id))
|
||||
TABLE
|
||||
.get()
|
||||
.unwrap()
|
||||
.get(&create_key_internal(map_id, entity_id))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -207,10 +212,9 @@ fn load_json_entity_level_config_data(base_path: &str) -> Result<(), LoadDataErr
|
|||
serde_json::from_reader::<BufReader<File>, Vec<level_entity_config_data::Data>>(reader)?
|
||||
.into_iter()
|
||||
.map(|element| (level_entity_config_data::create_key(&element), element))
|
||||
.collect::<std::collections::HashMap<_, _>>()
|
||||
.collect::<std::collections::HashMap<_, _>>(),
|
||||
);
|
||||
tracing::info!("Loading data finished: {path}");
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
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>,
|
||||
|
||||
}
|
|
@ -15,6 +15,7 @@ pub mod reward;
|
|||
pub mod teleport;
|
||||
pub mod timer;
|
||||
pub mod var;
|
||||
pub mod model;
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
|
@ -28,6 +29,7 @@ pub struct ComponentsData {
|
|||
pub interact_component: Option<interact::InteractComponent>,
|
||||
pub entity_state_component: Option<entity_state::EntityStateComponent>,
|
||||
pub reward_component: Option<reward::RewardComponent>,
|
||||
pub model_component: Option<model::ModelComponent>,
|
||||
// TODO: Implement this ones
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub scene_actor_ref_component: Option<serde_json::Value>,
|
||||
|
@ -70,8 +72,6 @@ pub struct ComponentsData {
|
|||
#[cfg(feature = "strict_json_fields")]
|
||||
pub photo_target_component: Option<serde_json::Value>,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub model_component: Option<serde_json::Value>,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub entity_group_component: Option<serde_json::Value>,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub scene_item_life_cycle_component: Option<serde_json::Value>,
|
||||
|
@ -230,6 +230,7 @@ impl ComponentsData {
|
|||
interact_component: self.interact_component.as_ref().or(template.interact_component.as_ref()).cloned(),
|
||||
entity_state_component: self.entity_state_component.as_ref().or(template.entity_state_component.as_ref()).cloned(),
|
||||
reward_component: self.reward_component.as_ref().or(template.reward_component.as_ref()).cloned(),
|
||||
model_component: self.model_component.as_ref().or(template.model_component.as_ref()).cloned(),
|
||||
}
|
||||
}
|
||||
}
|
18
wicked-waifus-data/src/pb_components/model.rs
Normal file
18
wicked-waifus-data/src/pb_components/model.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct ModelType {
|
||||
pub r#type: Option<String>,
|
||||
pub model_id: Option<i32>
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct ModelComponent {
|
||||
pub half_height: Option<i32>,
|
||||
pub disabled: Option<bool>,
|
||||
pub model_type: Option<ModelType>
|
||||
}
|
|
@ -100,7 +100,6 @@ pub struct RoleInfoData {
|
|||
pub role_guide: i32,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub red_dot_disable_rule: i32,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub skin_damage: Vec<String>,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub hide_hu_lu: bool,
|
||||
|
|
12
wicked-waifus-data/src/summon_cfg.rs
Normal file
12
wicked-waifus-data/src/summon_cfg.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[cfg_attr(feature = "strict_json_fields", serde(deny_unknown_fields))]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct SummonCfgData {
|
||||
pub id: i32,
|
||||
pub blueprint_type: String,
|
||||
#[cfg(feature = "strict_json_fields")]
|
||||
pub name: String,
|
||||
pub born_buff_id: Vec<i64>,
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
require('../Module/WaterMask/WaterMaskController').WaterMaskView.EOo();
|
41
wicked-waifus-game-server/scripts/watermask-edit.js
Normal file
41
wicked-waifus-game-server/scripts/watermask-edit.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
const UE = require("ue"),
|
||||
Info_1 = require("../../../Core/Common/Info"),
|
||||
MathUtils_1 = require("../../../Core/Utils/MathUtils"),
|
||||
EventDefine_1 = require("../../Common/Event/EventDefine"),
|
||||
EventSystem_1 = require("../../Common/Event/EventSystem"),
|
||||
UiControllerBase_1 = require("../../Ui/Base/UiControllerBase"),
|
||||
UiLayerType_1 = require("../../Ui/Define/UiLayerType"),
|
||||
UiLayer_1 = require("../../Ui/UiLayer");
|
||||
|
||||
var _a = require('../Module/WaterMask/WaterMaskController').WaterMaskView;
|
||||
_a.LOo = 0.18;
|
||||
_a.yOo = 700;
|
||||
_a.IOo = 700;
|
||||
_a.vOo = function () {
|
||||
void 0 !== _a.SOo && _a.EOo();
|
||||
var e = UiLayer_1.UiLayer.GetLayerRootUiItem(UiLayerType_1.ELayerType.WaterMask),
|
||||
t = (_a.SOo = UE.KuroActorManager.SpawnActor(Info_1.Info.World, UE.UIContainerActor.StaticClass(),
|
||||
MathUtils_1.MathUtils.DefaultTransform, void 0), _a.SOo.RootComponent),
|
||||
e = (t.SetDisplayName("WaterMaskContainer"), UE.KuroStaticLibrary.SetActorPermanent(_a.SOo, !0, !0), _a.SOo
|
||||
.K2_AttachRootComponentTo(e), t.GetRootCanvas().GetOwner().RootComponent),
|
||||
i = e.widget.width % _a.yOo / 2,
|
||||
r = e.widget.height % _a.IOo / 2,
|
||||
n = e.widget.width / 2,
|
||||
_ = e.widget.height / 2,
|
||||
s = Math.ceil(e.widget.width / _a.yOo),
|
||||
o = Math.ceil(e.widget.height / _a.IOo),
|
||||
v = " "; // EDIT ME!
|
||||
for (let a = 0; a < s; a++)
|
||||
for (let e = 0; e < o; e++) {
|
||||
var E = UE.KuroActorManager.SpawnActor(Info_1.Info.World, UE.UITextActor.StaticClass(), MathUtils_1
|
||||
.MathUtils.DefaultTransform, void 0),
|
||||
U = E.RootComponent,
|
||||
U = (E.K2_AttachRootComponentTo(t), U.SetDisplayName("WaterMaskText"), E.GetComponentByClass(UE
|
||||
.UIText.StaticClass()));
|
||||
U.SetFontSize(_a.vFt), U.SetOverflowType(0), U.SetAlpha(_a.LOo), U.SetFont(UE.LGUIFontData
|
||||
.GetDefaultFont()), U.SetText(v), U.SetUIRelativeLocation(new UE.Vector(a * _a.yOo - n + i, e *
|
||||
_a.IOo - _ + r, 0)), U.SetUIRelativeRotation(new UE.Rotator(0, _a.TOo, 0)), UE.KuroStaticLibrary
|
||||
.SetActorPermanent(E, !0, !0)
|
||||
}
|
||||
};
|
||||
_a.vOo();
|
|
@ -8,17 +8,34 @@ pub struct BufManager {
|
|||
recycled_handles: HashMap<i32, VecDeque<i32>>,
|
||||
}
|
||||
|
||||
impl BufManager {
|
||||
const PERMANENT_ROLE_BUFFS: &'static [i64] = &[
|
||||
3003, // Remove wall run prohibition
|
||||
3004, // Remove gliding prohibition
|
||||
1213, // Reduce stamina while flying
|
||||
1214, // Reduce stamina while flying in sprint
|
||||
1215, // Reduce stamina while flying up in sprint
|
||||
1216, // Reduce stamina while flying down in sprint
|
||||
640012051, // Allow flying -> tag: 1151923109
|
||||
];
|
||||
const OVERRIDE_BUFFS: &[i64] = &[
|
||||
3003, // Remove wall run prohibition
|
||||
3004, // Remove gliding prohibition
|
||||
1213, // Reduce stamina while flying
|
||||
1214, // Reduce stamina while flying in sprint
|
||||
1215, // Reduce stamina while flying up in sprint
|
||||
1216, // Reduce stamina while flying down in sprint
|
||||
640012051, // Allow flying -> tag: 1151923109
|
||||
];
|
||||
|
||||
const ROLE_OVERRIDES: &[(i32, &[i64])] = &[
|
||||
(1407, &[
|
||||
// ciaconna's forte buffs are completely fucked to get from an algorithm and i hate kuro!
|
||||
1407900003,
|
||||
1407500040,
|
||||
]),
|
||||
];
|
||||
|
||||
fn get_role_buff_overrides(role_id: i32) -> Option<&'static [i64]> {
|
||||
for &(role, buff) in ROLE_OVERRIDES {
|
||||
if role == role_id {
|
||||
return Some(buff);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
impl BufManager {
|
||||
pub fn create(&mut self, buf: &mut FightBuffInformation) {
|
||||
let handle = self
|
||||
.recycled_handles
|
||||
|
@ -35,7 +52,9 @@ impl BufManager {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn remove_entity_buffs(&mut self, entity_id: i64) {
|
||||
let handles = self.active_buf_set.iter()
|
||||
let handles = self
|
||||
.active_buf_set
|
||||
.iter()
|
||||
.filter(|(_, buff)| buff.entity_id == entity_id)
|
||||
.map(|(&handle, _)| handle)
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -57,13 +76,33 @@ impl BufManager {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_permanent_buffs(&mut self, origin_id: i64) -> Vec<FightBuffInformation> {
|
||||
Self::PERMANENT_ROLE_BUFFS
|
||||
pub fn create_permanent_buffs(&mut self, origin_id: i64, role_id: i32) -> Vec<FightBuffInformation> {
|
||||
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().contains("666")// KURO IS EVIL
|
||||
&&
|
||||
buf.duration_policy == 1
|
||||
&&
|
||||
!buf.ge_desc.contains("【废弃】") // remove "deprecated" buffs
|
||||
})
|
||||
.map(|x| *x.0)
|
||||
.collect::<Vec<i64>>();
|
||||
|
||||
tracing::debug!("adding roleid {:#?}", buffs);
|
||||
|
||||
buffs.extend(OVERRIDE_BUFFS.iter().copied());
|
||||
if let Some(role_buff_overrides) = get_role_buff_overrides(role_id) {
|
||||
buffs.extend(role_buff_overrides.iter().copied());
|
||||
}
|
||||
buffs.dedup();
|
||||
|
||||
buffs
|
||||
.iter()
|
||||
.map(|&id| {
|
||||
.map(|id| {
|
||||
let mut buff = FightBuffInformation {
|
||||
handle_id: 0,
|
||||
buff_id: id,
|
||||
buff_id: *id,
|
||||
level: 1,
|
||||
stack_count: 1,
|
||||
instigator_id: origin_id,
|
||||
|
@ -81,6 +120,26 @@ impl BufManager {
|
|||
})
|
||||
.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 {
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::collections::hash_map::{Keys, Values};
|
|||
use std::collections::HashMap;
|
||||
use wicked_waifus_protocol::FightBuffInformation;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WorldEntity {
|
||||
components: HashMap<i32, Vec<RefCell<ComponentContainer>>>,
|
||||
entity_manager: EntityManager,
|
||||
|
@ -107,21 +108,15 @@ impl WorldEntity {
|
|||
self.components.remove(&entity_id).is_some() && self.entity_manager.remove(entity_id)
|
||||
}
|
||||
|
||||
pub fn active_entity_empty(&self) -> bool {
|
||||
self.entity_manager.active_entity_empty()
|
||||
pub fn get_all_entity_ids(&mut self) -> Vec<i32> {
|
||||
self.entity_manager.get_all_entity_id()
|
||||
}
|
||||
|
||||
pub fn generate_role_permanent_buffs(&mut self, entity_id: i64) -> Vec<FightBuffInformation> {
|
||||
self.buff_manager.create_permanent_buffs(entity_id)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for WorldEntity {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
components: HashMap::new(),
|
||||
entity_manager: EntityManager::default(),
|
||||
buff_manager: BufManager::default(),
|
||||
}
|
||||
pub fn create_buff(&mut self, entity_id: i32, buff_id: i64) -> FightBuffInformation {
|
||||
self.buff_manager.create_buff(entity_id as i64, buff_id)
|
||||
}
|
||||
}
|
||||
|
|
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()
|
||||
};
|
||||
}
|
||||
}
|
|
@ -160,38 +160,38 @@ fn handle_damage_execute_request(
|
|||
..Default::default()
|
||||
}),
|
||||
));
|
||||
if let Some((value, _)) = query_components!(world, request.target_entity_id, Attribute)
|
||||
.0
|
||||
.unwrap()
|
||||
.attr_map
|
||||
.get(&EAttributeType::Life)
|
||||
{
|
||||
let updated_value = match value - damage >= 0 {
|
||||
true => value - damage,
|
||||
false => 0,
|
||||
};
|
||||
receive_pack.data.push(create_combat_notify(
|
||||
CombatCommon {
|
||||
entity_id: request.target_entity_id,
|
||||
..Default::default()
|
||||
},
|
||||
combat_notify_data::Message::AttributeChangedNotify(AttributeChangedNotify {
|
||||
id: request.target_entity_id,
|
||||
attributes: vec![GameplayAttributeData {
|
||||
current_value: updated_value,
|
||||
value_increment: updated_value,
|
||||
attribute_type: EAttributeType::Life.into(),
|
||||
}],
|
||||
}),
|
||||
));
|
||||
if updated_value == 0 {
|
||||
world_util::remove_entity(
|
||||
player,
|
||||
request.target_entity_id,
|
||||
ERemoveEntityType::HpIsZero,
|
||||
);
|
||||
}
|
||||
}
|
||||
// if let Some((value, _)) = query_components!(world, request.target_entity_id, Attribute)
|
||||
// .0
|
||||
// .unwrap()
|
||||
// .attr_map
|
||||
// .get(&EAttributeType::Life)
|
||||
// {
|
||||
// let updated_value = match value - damage >= 0 {
|
||||
// true => value - damage,
|
||||
// false => 0,
|
||||
// };
|
||||
// receive_pack.data.push(create_combat_notify(
|
||||
// CombatCommon {
|
||||
// entity_id: request.target_entity_id,
|
||||
// ..Default::default()
|
||||
// },
|
||||
// combat_notify_data::Message::AttributeChangedNotify(AttributeChangedNotify {
|
||||
// id: request.target_entity_id,
|
||||
// attributes: vec![GameplayAttributeData {
|
||||
// current_value: updated_value,
|
||||
// value_increment: updated_value,
|
||||
// attribute_type: EAttributeType::Life.into(),
|
||||
// }],
|
||||
// }),
|
||||
// ));
|
||||
// if updated_value == 0 {
|
||||
// world_util::remove_entity(
|
||||
// player,
|
||||
// request.target_entity_id,
|
||||
// ERemoveEntityType::HpIsZero,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
response.error_code = ErrorCode::Success.into();
|
||||
}
|
||||
|
|
|
@ -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 crate::logic::handler::handle_action;
|
||||
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;
|
||||
|
||||
pub fn on_entity_active_request(
|
||||
|
@ -190,7 +190,7 @@ pub fn on_entity_interact_request(
|
|||
match option_type {
|
||||
OptionType::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(_) => {
|
||||
|
@ -234,6 +234,52 @@ pub fn on_get_reward_treasure_box_request(
|
|||
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 {
|
||||
let world_ref = player.world.borrow();
|
||||
let world = world_ref.get_world_entity();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
pub use action::*;
|
||||
pub use attribute::*;
|
||||
pub use advice::*;
|
||||
pub use animal::*;
|
||||
pub use chat::*;
|
||||
|
@ -20,6 +22,8 @@ pub use skill::*;
|
|||
pub use teleport::*;
|
||||
pub use tutorial::*;
|
||||
|
||||
mod action;
|
||||
mod attribute;
|
||||
mod advice;
|
||||
mod animal;
|
||||
mod chat;
|
||||
|
@ -55,7 +59,7 @@ macro_rules! handle_request {
|
|||
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();
|
||||
[<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! {
|
||||
// Advice
|
||||
Advice;
|
||||
|
@ -120,6 +158,10 @@ handle_request! {
|
|||
AnimalDrop;
|
||||
AnimalDestroy;
|
||||
|
||||
// Attribute
|
||||
AttributeChanged;
|
||||
FormationAttr;
|
||||
|
||||
// Chat (TODO: Review TODOs)
|
||||
PrivateChat;
|
||||
PrivateChatData;
|
||||
|
@ -141,6 +183,10 @@ handle_request! {
|
|||
EntityInteract;
|
||||
EntityFollowTrack;
|
||||
GetRewardTreasureBox;
|
||||
OrderApplyBuff;
|
||||
OrderRemoveBuff;
|
||||
ApplyGameplayEffect;
|
||||
RemoveGameplayEffect;
|
||||
|
||||
// Friend (TODO: Implement them)
|
||||
FriendAll;
|
||||
|
@ -198,7 +244,6 @@ handle_request! {
|
|||
RoleShowListUpdate;
|
||||
ClientCurrentRoleReport;
|
||||
RoleFavorList;
|
||||
FormationAttr;
|
||||
UpdateFormation;
|
||||
|
||||
// Scene (TODO: Review this on_..., port some from go)
|
||||
|
@ -280,10 +325,200 @@ handle_push! {
|
|||
// Entity
|
||||
MovePackage;
|
||||
|
||||
ApplyGameplayEffect;
|
||||
RemoveGameplayEffect;
|
||||
|
||||
// Misc
|
||||
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) {
|
||||
match msg {
|
||||
Message::Request { .. } => handle_request(player, msg),
|
||||
|
@ -296,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,
|
||||
};
|
||||
|
||||
use crate::logic::ecs::world;
|
||||
use crate::logic::player::Player;
|
||||
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(
|
||||
player: &mut Player,
|
||||
|
@ -44,14 +48,6 @@ pub fn on_role_favor_list_request(
|
|||
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(
|
||||
player: &mut Player,
|
||||
request: UpdateFormationRequest,
|
||||
|
@ -65,6 +61,22 @@ pub fn on_update_formation_request(
|
|||
let cur_role = formation.cur_role;
|
||||
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 {
|
||||
// update player current formation id
|
||||
player.cur_formation_id = formation_id;
|
||||
|
@ -81,30 +93,26 @@ pub fn on_update_formation_request(
|
|||
}
|
||||
|
||||
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();
|
||||
for id in removed_entities.clone() {
|
||||
if let (Some(concomitant),) = query_components!(world, id, Concomitant) {
|
||||
removed_entities.extend(concomitant.custom_entity_ids.clone());
|
||||
};
|
||||
}
|
||||
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,
|
||||
ERemoveEntityType::RemoveTypeForce,
|
||||
));
|
||||
}
|
||||
|
||||
let added_roles: Vec<Role> = formation
|
||||
.role_ids
|
||||
.iter()
|
||||
.map(|&role_id| Role::new(role_id))
|
||||
.collect();
|
||||
|
||||
if !added_roles.is_empty() {
|
||||
// add new roles
|
||||
player.notify(player.build_player_entity_add_notify(added_roles));
|
||||
}
|
||||
player.build_player_entity_add_notify(world);
|
||||
|
||||
// send update group formation notify
|
||||
player.notify(player.build_update_group_formation_notify(
|
||||
|
@ -119,22 +127,6 @@ pub fn on_update_formation_request(
|
|||
|
||||
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());
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use wicked_waifus_protocol::{ErrorCode, SceneLoadingFinishRequest, SceneLoadingFinishResponse, SceneTraceRequest, SceneTraceResponse, UpdateSceneDateRequest, UpdateSceneDateResponse, AccessPathTimeServerConfigRequest, AccessPathTimeServerConfigResponse, PlayerHeadDataRequest, PlayerHeadDataResponse, UnlockRoleSkinListRequest, UnlockRoleSkinListResponse, JsPatchNotify};
|
||||
|
||||
const WATER_MASK: &str = include_str!("../../../scripts/watermask-disable.js");
|
||||
//const WATER_MASK: &str = include_str!("../../../scripts/watermask-disable.js");
|
||||
const WATER_MASK: &str = include_str!("../../../scripts/watermask-edit.js");
|
||||
const UID_FIX: &str = include_str!("../../../scripts/uidfix.js");
|
||||
const CENSORSHIP_FIX: &str = include_str!("../../../scripts/censorshipfix.js");
|
||||
const DEBUG_DISABLE: &str = include_str!("../../../scripts/debug_disable.js");
|
||||
|
|
|
@ -12,6 +12,10 @@ pub struct ExploreTools {
|
|||
pub roulette: Roulette,
|
||||
}
|
||||
|
||||
const ADDITIONAL_ROULETTE: &[i32] = &[
|
||||
1015 // flight
|
||||
];
|
||||
|
||||
impl ExploreTools {
|
||||
pub fn build_save_data(&self) -> PlayerExploreToolsData {
|
||||
PlayerExploreToolsData {
|
||||
|
@ -63,6 +67,16 @@ impl ExploreTools {
|
|||
.enumerate()
|
||||
.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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@ use wicked_waifus_protocol::message::Message;
|
|||
use wicked_waifus_protocol::player_attr::Value;
|
||||
use wicked_waifus_protocol::{
|
||||
AdventreTask, AdventureManualData, AdventureUpdateNotify, AdviceSettingNotify, BuffItemNotify,
|
||||
ControlInfoNotify, EEntityType, ERemoveEntityType, EnergyInfo, EnergyUpdateNotify,
|
||||
EntityAddNotify, EntityConfigType, EntityPb, EntityRemoveInfo, EntityRemoveNotify, EntityState,
|
||||
ControlInfoNotify, ERemoveEntityType, EnergyInfo, EnergyUpdateNotify,
|
||||
EntityRemoveInfo, EntityRemoveNotify,
|
||||
FavorItem, FightFormationNotifyInfo, FightRoleInfo, FightRoleInfos, FormationRoleInfo,
|
||||
GroupFormation, HostTeleportUnlockNotify, InstDataNotify, ItemPkgOpenNotify,
|
||||
LevelPlayInfoNotify, LivingStatus, MailInfosNotify, MapUnlockFieldNotify,
|
||||
LevelPlayInfoNotify, LivingStatus, MailInfosNotify,
|
||||
MonthCardDailyRewardNotify, MoonChasingTargetGetCountNotify,
|
||||
MoonChasingTrackMoonHandbookRewardNotify, NormalItemUpdateNotify, PassiveSkillNotify,
|
||||
PbGetRoleListNotify, PlayerAttr, PlayerAttrKey, PlayerAttrNotify, PlayerAttrType,
|
||||
|
@ -24,11 +24,12 @@ use wicked_waifus_protocol::{
|
|||
};
|
||||
use wicked_waifus_protocol_internal::{PlayerBasicData, PlayerRoleData, PlayerSaveData};
|
||||
|
||||
use super::ecs::component::ComponentContainer;
|
||||
use super::utils::world_util::add_player_entities;
|
||||
use super::{
|
||||
ecs::world::World,
|
||||
role::{Role, RoleFormation},
|
||||
};
|
||||
use crate::logic::components::RoleSkin;
|
||||
use crate::logic::ecs::world::WorldEntity;
|
||||
use crate::logic::player::basic_info::PlayerBasicInfo;
|
||||
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_teleports::{PlayerTeleport, PlayerTeleports};
|
||||
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::{config, create_player_entity_pb, query_components};
|
||||
use crate::{config, query_components};
|
||||
use crate::logic::player::Element::Spectro;
|
||||
|
||||
mod basic_info;
|
||||
|
@ -263,7 +257,7 @@ impl Player {
|
|||
}
|
||||
|
||||
if !rf.role_ids.contains(&rf.cur_role) {
|
||||
rf.cur_role = *rf.role_ids.iter().nth(0).unwrap();
|
||||
rf.cur_role = *rf.role_ids.first().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,9 +298,7 @@ impl Player {
|
|||
pub fn build_role_favor_list_notify(&self) -> RoleFavorListNotify {
|
||||
RoleFavorListNotify {
|
||||
favor_list: self
|
||||
.role_list
|
||||
.iter()
|
||||
.map(|(_, role)| RoleFavor {
|
||||
.role_list.values().map(|role| RoleFavor {
|
||||
role_id: role.role_id,
|
||||
level: role.favor_level,
|
||||
exp: role.favor_exp,
|
||||
|
@ -341,9 +333,7 @@ impl Player {
|
|||
pub fn build_motion_list_notify(&self) -> RoleMotionListNotify {
|
||||
RoleMotionListNotify {
|
||||
motion_list: self
|
||||
.role_list
|
||||
.iter()
|
||||
.map(|(_, role)| {
|
||||
.role_list.values().map(|role| {
|
||||
RoleMotion {
|
||||
role_id: role.role_id,
|
||||
motion_ids: motion_data::iter()
|
||||
|
@ -362,15 +352,8 @@ impl Player {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn build_player_entity_add_notify(&self, role_list: Vec<Role>) -> EntityAddNotify {
|
||||
create_player_entity_pb!(
|
||||
role_list,
|
||||
self.basic_info.cur_map_id,
|
||||
self,
|
||||
self.basic_info.id,
|
||||
self.location.position.clone(),
|
||||
self.explore_tools
|
||||
)
|
||||
pub fn build_player_entity_add_notify(&self, world: &mut WorldEntity) {
|
||||
add_player_entities(self, self.formation_list.get(&self.cur_formation_id).unwrap(), Some(world))
|
||||
}
|
||||
|
||||
pub fn build_player_entity_remove_notify(
|
||||
|
@ -406,8 +389,7 @@ impl Player {
|
|||
.iter()
|
||||
.map(|&role_id| {
|
||||
let entity_id = world.get_entity_id(role_id);
|
||||
let role_skin =
|
||||
query_components!(world, entity_id, RoleSkin).0.unwrap();
|
||||
let _role_skin = query_components!(world, entity_id, RoleSkin).0.unwrap();
|
||||
FightRoleInfo {
|
||||
role_id,
|
||||
entity_id: world.get_entity_id(role_id),
|
||||
|
@ -449,13 +431,13 @@ impl Player {
|
|||
tracing::warn!("Role {} not found in use role list", role_id);
|
||||
return Default::default();
|
||||
}
|
||||
let role = *role_map.get(&role_id).unwrap();
|
||||
let role = *role_map.get(role_id).unwrap();
|
||||
FormationRoleInfo {
|
||||
role_id: role.role_id,
|
||||
max_hp: 0,
|
||||
cur_hp: 0,
|
||||
level: role.level,
|
||||
role_skin_id: role.skin_id,
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
|
@ -607,9 +589,7 @@ impl Player {
|
|||
basic_data: Some(self.basic_info.build_save_data()),
|
||||
role_data: Some(PlayerRoleData {
|
||||
role_list: self
|
||||
.role_list
|
||||
.iter()
|
||||
.map(|(_, role)| role.build_save_data())
|
||||
.role_list.values().map(|role| role.build_save_data())
|
||||
.collect(),
|
||||
role_formation_list: self
|
||||
.formation_list
|
||||
|
@ -642,9 +622,7 @@ impl Player {
|
|||
// TODO: There is a bug we are investigating with several resonators, this is a workaround
|
||||
PbGetRoleListNotify {
|
||||
role_list: self
|
||||
.role_list
|
||||
.iter()
|
||||
.map(|(_, role)| role.to_protobuf())
|
||||
.role_list.values().map(|role| role.to_protobuf())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ pub struct RoleFormation {
|
|||
|
||||
// Will be updated every version
|
||||
// const DEFAULT_FORMATION: &[i32] = &[5101, 1407, 1507];
|
||||
const DEFAULT_FORMATION: &[i32] = &[1205, 1207, 1409];
|
||||
const DEFAULT_FORMATION: &[i32] = &[1506, 1207, 1409];
|
||||
|
||||
impl RoleFormation {
|
||||
pub fn default_roles() -> &'static [i32] {
|
||||
|
@ -29,7 +29,7 @@ impl RoleFormation {
|
|||
RoleFormationData {
|
||||
formation_id: self.id,
|
||||
cur_role: self.cur_role,
|
||||
role_id_list: self.role_ids.iter().map(|&role_id| role_id).collect(),
|
||||
role_id_list: self.role_ids.to_vec(),
|
||||
is_current: self.is_current,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,13 +158,13 @@ impl Role {
|
|||
// Overwrite dynamic attributes with stores values
|
||||
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
|
||||
base_stats.life = self.hp;
|
||||
base_stats.energy = self.energy;
|
||||
base_stats.life = base_stats.life_max;
|
||||
base_stats.energy = base_stats.energy_max;
|
||||
base_stats.special_energy_1 = self.special_energy_1;
|
||||
base_stats.special_energy_2 = self.special_energy_2;
|
||||
base_stats.special_energy_3 = self.special_energy_3;
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
use wicked_waifus_commons::time_util;
|
||||
use wicked_waifus_protocol_internal::PlayerSaveData;
|
||||
use wicked_waifus_protocol::{message::Message, AfterJoinSceneNotify, EnterGameResponse, JoinSceneNotify, SilenceNpcNotify, TransitionOptionPb};
|
||||
use super::{ecs::world::World, player::Player, utils::world_util};
|
||||
use crate::logic::ecs::world::WorldEntity;
|
||||
use crate::{
|
||||
logic,
|
||||
player_save_task::{self, PlayerSaveReason},
|
||||
session::Session,
|
||||
};
|
||||
use std::collections::hash_map::Entry::Vacant;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
|
@ -13,16 +17,20 @@ use std::{
|
|||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
use super::{ecs::world::World, player::Player, utils::world_util};
|
||||
use crate::logic::ecs::world::WorldEntity;
|
||||
use crate::{logic, player_save_task::{self, PlayerSaveReason}, session::Session};
|
||||
use wicked_waifus_commons::time_util;
|
||||
use wicked_waifus_protocol::{
|
||||
message::Message, AfterJoinSceneNotify, EnterGameResponse, JoinSceneNotify, SilenceNpcNotify,
|
||||
TransitionOptionPb,
|
||||
};
|
||||
use wicked_waifus_protocol::{FormationAttr, FormationAttrNotify};
|
||||
use wicked_waifus_protocol_internal::PlayerSaveData;
|
||||
|
||||
pub enum LogicInput {
|
||||
AddPlayer {
|
||||
player_id: i32,
|
||||
enter_rpc_id: u16,
|
||||
session: Arc<Session>,
|
||||
player_save_data: PlayerSaveData,
|
||||
player_save_data: Box<PlayerSaveData>,
|
||||
},
|
||||
RemovePlayer {
|
||||
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) {
|
||||
(
|
||||
e.insert(RefCell::new(Player::load_from_save(player_save_data))),
|
||||
e.insert(RefCell::new(Player::load_from_save(*player_save_data))),
|
||||
true,
|
||||
)
|
||||
} else if let Some(player) = state.players.get_mut(&player_id) {
|
||||
(player, false)
|
||||
} else {
|
||||
if let Some(player) = state.players.get_mut(&player_id) {
|
||||
(player, false)
|
||||
} else {
|
||||
tracing::warn!("logic_thread: get player requested, but player {player_id} with data doesn't exist");
|
||||
return;
|
||||
}
|
||||
tracing::warn!("logic_thread: get player requested, but player {player_id} with data doesn't exist");
|
||||
return;
|
||||
};
|
||||
|
||||
let mut player = player.borrow_mut();
|
||||
|
@ -163,8 +169,7 @@ fn handle_logic_input(state: &mut LogicState, input: LogicInput) {
|
|||
.world
|
||||
.borrow_mut()
|
||||
.set_in_world_player_data(player.build_in_world_player());
|
||||
|
||||
world_util::add_player_entities(&player);
|
||||
world_util::add_player_entities(&player, player.formation_list.get(&player.cur_formation_id).unwrap(), None);
|
||||
let scene_info = world_util::build_scene_information(&player);
|
||||
|
||||
player.notify(SilenceNpcNotify::default());
|
||||
|
@ -175,6 +180,26 @@ fn handle_logic_input(state: &mut LogicState, input: LogicInput) {
|
|||
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(player.build_update_formation_notify());
|
||||
|
||||
|
@ -211,10 +236,14 @@ fn handle_logic_input(state: &mut LogicState, input: LogicInput) {
|
|||
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: Remove all entities
|
||||
|
||||
player_save_task::push(
|
||||
player_id,
|
||||
player.borrow().build_save_data(),
|
||||
|
|
|
@ -1,315 +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::StopCameraLookAt(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 },
|
||||
Action::BvbPlayDialog(action) => unimplemented_action! { action },
|
||||
Action::BvbSendSystemEvent(action) => unimplemented_action! { action },
|
||||
Action::BvbSendAiEvent(action) => unimplemented_action! { action },
|
||||
Action::BvbPlayerOperationConstraint(action) => unimplemented_action! { action },
|
||||
Action::ExecClientBattleAction(action) => unimplemented_action! { action },
|
||||
Action::TriggerSpecificScanEffect(action) => unimplemented_action! { action },
|
||||
Action::SetActorVar(action) => unimplemented_action! { action },
|
||||
Action::RunActorCustomEvent(action) => unimplemented_action! { action },
|
||||
Action::StopUiScreenEffect(action) => unimplemented_action! { action },
|
||||
Action::StopNewMoveWithSpline(action) => unimplemented_action! { action },
|
||||
Action::RequestSystemFunction(action) => unimplemented_action! { action },
|
||||
}
|
||||
}
|
||||
|
||||
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??
|
||||
});
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
pub mod action_utils;
|
||||
pub mod condition_utils;
|
||||
pub mod entity_serializer;
|
||||
pub mod load_role_info;
|
||||
pub mod world_util;
|
||||
pub mod quadrant_util;
|
||||
pub mod growth_utils;
|
||||
pub mod tag_utils;
|
||||
pub mod tag_utils;
|
|
@ -1,198 +1,258 @@
|
|||
use wicked_waifus_protocol::summon::ESummonType;
|
||||
use wicked_waifus_protocol::{
|
||||
EEntityType, ERemoveEntityType, EntityAddNotify, EntityConfigType, EntityPb, EntityRemoveInfo,
|
||||
EntityRemoveNotify, EntityState, FightRoleInfo, FightRoleInfos, LivingStatus, SceneInformation,
|
||||
SceneMode, ScenePlayerInformation, SceneTimeInfo,
|
||||
EEntityType, ERemoveEntityType, EntityAddNotify, EntityConfigType, EntityPb, EntityRemoveInfo, EntityRemoveNotify, EntityState, FightBuffInformation, FightRoleInfo, FightRoleInfos, LivingStatus, SceneInformation, SceneMode, ScenePlayerInformation, SceneTimeInfo
|
||||
};
|
||||
|
||||
use wicked_waifus_data::pb_components::ComponentsData;
|
||||
use wicked_waifus_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::ecs::entity::EntityBuilder;
|
||||
use crate::logic::ecs::world::World;
|
||||
use crate::logic::ecs::entity::{Entity, EntityBuilder};
|
||||
use crate::logic::ecs::world::{World, WorldEntity};
|
||||
use crate::logic::math::Transform;
|
||||
use crate::logic::player::Player;
|
||||
use crate::logic::utils::{entity_serializer, tag_utils};
|
||||
use crate::logic::role::RoleFormation;
|
||||
use crate::logic::utils::growth_utils::get_monster_props_by_level;
|
||||
use crate::logic::utils::{entity_serializer, tag_utils};
|
||||
use crate::logic::{
|
||||
components::{
|
||||
Attribute, EntityConfig, Equip, FightBuff, Movement, OwnerPlayer, PlayerOwnedEntityMarker,
|
||||
Position, RoleSkin, Visibility, VisionSkill,
|
||||
Attribute, Concomitant, EntityConfig, Equip, FightBuff, Movement, OwnerPlayer,
|
||||
PlayerOwnedEntityMarker, Position, RoleSkin, Summoner, Visibility, VisionSkill,
|
||||
},
|
||||
ecs::component::ComponentContainer,
|
||||
};
|
||||
//use crate::resonator_data::{ResonatorData, Concomitant, SummonerComponent};
|
||||
|
||||
use crate::query_with;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! create_player_entity_pb {
|
||||
($role_list:expr, $cur_map_id:expr, $player:expr, $player_id:expr, $position:expr, $explore_tools:expr) => {{
|
||||
let mut world_ref = $player.world.borrow_mut();
|
||||
let world = world_ref.get_mut_world_entity();
|
||||
pub fn summon_concomitant(player: &Player, world: &mut WorldEntity, template_cfg: &wicked_waifus_data::TemplateConfigData, cur_summon_id: i32) -> (Entity, Vec<i64>) {
|
||||
let mut concomitant_buffs: Vec<FightBuffInformation> = Vec::new();
|
||||
|
||||
let current_formation = $player.formation_list.get(&$player.cur_formation_id).unwrap();
|
||||
let cur_role_id = current_formation.cur_role;
|
||||
let summon_cfg = summon_cfg_data::get(&template_cfg.blueprint_type).unwrap();
|
||||
let concomitant_config_id = template_cfg.id;
|
||||
|
||||
let mut pbs = Vec::new();
|
||||
let con_entity = world.create_entity(
|
||||
cur_summon_id,
|
||||
EEntityType::Monster.into(),
|
||||
player.basic_info.cur_map_id,
|
||||
);
|
||||
|
||||
for role in $role_list {
|
||||
let entity = world.create_entity(
|
||||
role.role_id,
|
||||
EEntityType::Player.into(),
|
||||
$cur_map_id,
|
||||
);
|
||||
// Once per character buffs are implemented, add a mut on role_buffs
|
||||
let fight_buff_infos = world.generate_role_permanent_buffs(entity.entity_id as i64);
|
||||
let buf_manager = FightBuff {
|
||||
fight_buff_infos,
|
||||
list_buff_effect_cd: vec![],
|
||||
};
|
||||
for buff_id in &summon_cfg.born_buff_id {
|
||||
concomitant_buffs.push(world.create_buff(cur_summon_id, *buff_id));
|
||||
}
|
||||
|
||||
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,
|
||||
}))
|
||||
// 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: 90, // TODO: store this too
|
||||
}))
|
||||
.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(buf_manager))
|
||||
.build();
|
||||
tracing::info!("Adding Concomitant with id: {} and buffs {:#?}", concomitant_config_id, concomitant_buffs);
|
||||
|
||||
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,
|
||||
}
|
||||
}};
|
||||
(world
|
||||
.create_builder(con_entity)
|
||||
.with(ComponentContainer::PlayerOwnedEntityMarker(PlayerOwnedEntityMarker {
|
||||
entity_type: EEntityType::Monster,
|
||||
}))
|
||||
.with(ComponentContainer::EntityConfig(EntityConfig {
|
||||
camp: 0,
|
||||
config_id: concomitant_config_id,
|
||||
config_type: EntityConfigType::Template,
|
||||
entity_type: EEntityType::Monster,
|
||||
entity_state: EntityState::Born,
|
||||
}))
|
||||
.with(ComponentContainer::OwnerPlayer(OwnerPlayer(
|
||||
player.basic_info.id,
|
||||
)))
|
||||
.with(ComponentContainer::Position(Position(
|
||||
player.location.position.clone(),
|
||||
)))
|
||||
.with(ComponentContainer::Visibility(Visibility {
|
||||
is_visible: false,
|
||||
is_actor_visible: true,
|
||||
}))
|
||||
.with(ComponentContainer::Attribute(Attribute::from_data(
|
||||
base_property_data::iter()
|
||||
.find(|d| d.id == template_cfg.components_data.attribute_component.clone().unwrap().property_id.unwrap())
|
||||
.unwrap(),
|
||||
None,
|
||||
None,
|
||||
)))
|
||||
.with(ComponentContainer::FightBuff(FightBuff { fight_buff_infos: concomitant_buffs, ..Default::default() }))
|
||||
.with(ComponentContainer::Summoner(Summoner {
|
||||
summon_cfg_id: summon_cfg.id,
|
||||
summon_skill_id: 0,
|
||||
summon_type: ESummonType::ESummonTypeConcomitantCustom.into()
|
||||
}))
|
||||
.with(ComponentContainer::Autonomous(Autonomous { autonomous_id: 3 }))
|
||||
.build(), summon_cfg.born_buff_id.clone())
|
||||
}
|
||||
|
||||
pub fn add_player_entities(player: &Player) {
|
||||
let mut world_ref = player.world.borrow_mut();
|
||||
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
|
||||
fn add_player_entity(player: &Player, formation: &RoleFormation, world: &mut WorldEntity) {
|
||||
let role_vec = formation
|
||||
.role_ids
|
||||
.iter()
|
||||
.map(|role_id| player.role_list.get(&role_id).unwrap())
|
||||
.map(|role_id| player.role_list.get(role_id).unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
let cur_role_id = current_formation.cur_role;
|
||||
|
||||
if world.active_entity_empty() {
|
||||
for role in role_vec {
|
||||
let entity = world.create_entity(
|
||||
role.role_id,
|
||||
EEntityType::Player.into(),
|
||||
player.basic_info.cur_map_id,
|
||||
);
|
||||
// Once per character buffs are implemented, add a mut on role_buffs
|
||||
let fight_buff_infos = world.generate_role_permanent_buffs(entity.entity_id as i64);
|
||||
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.into(),
|
||||
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))
|
||||
.build();
|
||||
tracing::info!("adding player entity for formation {:#?}", formation.role_ids);
|
||||
let cur_role_id = formation.cur_role;
|
||||
|
||||
tracing::debug!(
|
||||
"created player entity, id: {}, role_id: {}",
|
||||
entity.entity_id,
|
||||
role.role_id
|
||||
);
|
||||
let mut pbs = Vec::new();
|
||||
|
||||
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 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());
|
||||
}
|
||||
|
||||
player.notify(EntityAddNotify {
|
||||
entity_pbs: concom_pbs,
|
||||
remove_tag_ids: true,
|
||||
});
|
||||
}
|
||||
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 {
|
||||
|
@ -264,7 +324,7 @@ fn build_player_info_list(world: &World) -> Vec<ScenePlayerInformation> {
|
|||
cur_role: cur_role_id,
|
||||
// is_retain: true,
|
||||
fight_role_infos: active_characters
|
||||
.map(|(id, _, _, conf, role_skin)| FightRoleInfo {
|
||||
.map(|(id, _, _, conf, _role_skin)| FightRoleInfo {
|
||||
entity_id: id.into(),
|
||||
role_id: conf.config_id,
|
||||
on_stage_without_control: false,
|
||||
|
@ -430,7 +490,13 @@ pub fn add_entities(player: &Player, entities: &[&LevelEntityConfigData], extern
|
|||
|
||||
build_autonomous_component(&mut builder, player.basic_info.id, entity_logic);
|
||||
build_interact_component(&mut builder, &components);
|
||||
build_tags_components(&mut builder, &components, player, blueprint_config.unwrap().entity_type, config_id as i64);
|
||||
build_tags_components(
|
||||
&mut builder,
|
||||
&components,
|
||||
player,
|
||||
blueprint_config.unwrap().entity_type,
|
||||
config_id as i64,
|
||||
);
|
||||
build_attribute_component(&mut builder, &components, player.location.instance_id);
|
||||
build_ai_components(&mut builder, &components);
|
||||
added_entities.push(builder.build());
|
||||
|
@ -496,7 +562,10 @@ fn build_tags_components(
|
|||
if let Some(entity_state_component) = &components.entity_state_component {
|
||||
let state = match entity_type {
|
||||
EntityType::Teleporter | EntityType::TemporaryTeleporter => {
|
||||
let result = player.teleports.teleports_data.iter()
|
||||
let result = player
|
||||
.teleports
|
||||
.teleports_data
|
||||
.iter()
|
||||
.find(|teleporter| teleporter.entity_config_id == config_id);
|
||||
match result.is_some() {
|
||||
true => tag_utils::get_tag_id_by_name("关卡.Common.状态.激活"),
|
||||
|
|
|
@ -51,12 +51,12 @@ async fn handler_loop(
|
|||
return;
|
||||
};
|
||||
|
||||
tracing::debug!(
|
||||
"received message from service: {}, rpc_id: {} message_id: {}",
|
||||
message.src_service_id,
|
||||
message.rpc_id,
|
||||
message.message_id
|
||||
);
|
||||
// tracing::debug!(
|
||||
// "received message from service: {}, rpc_id: {} message_id: {}",
|
||||
// message.src_service_id,
|
||||
// message.rpc_id,
|
||||
// message.message_id
|
||||
// );
|
||||
|
||||
match message.message_id {
|
||||
CreatePlayerDataRequest::MESSAGE_ID => {
|
||||
|
@ -141,7 +141,7 @@ async fn on_start_player_session_request(
|
|||
player_id: player_data.player_id,
|
||||
enter_rpc_id: message.rpc_id,
|
||||
session: session.clone(),
|
||||
player_save_data,
|
||||
player_save_data: Box::new(player_save_data),
|
||||
});
|
||||
|
||||
session_mgr.add(session.clone());
|
||||
|
|
Loading…
Reference in a new issue