diff --git a/Common/Data/Config/Scene/FloorInfo.cs b/Common/Data/Config/Scene/FloorInfo.cs index c2165291..58b81734 100644 --- a/Common/Data/Config/Scene/FloorInfo.cs +++ b/Common/Data/Config/Scene/FloorInfo.cs @@ -33,6 +33,8 @@ public class FloorInfo return group.AnchorList.Find(info => info.ID == anchorId); } + [JsonIgnore] public List FloorSavedValue { get; set; } = []; + public void OnLoad() { if (Loaded) return; @@ -41,37 +43,48 @@ public class FloorInfo foreach (var dimension in DimensionList) dimension.OnLoad(this); + FloorSavedValue.AddRange(SavedValues); // Cache anchors foreach (var group in Groups.Values) - foreach (var prop in group.PropList) - // Check if prop can be teleported to - if (prop.AnchorID > 0) - { - // Put inside cached teleport list to send to client when they request map info - CachedTeleports.TryAdd(prop.MappingInfoID, prop); - UnlockedCheckpoints.Add(prop); - - // Force prop to be in the unlocked state - prop.State = PropStateEnum.CheckPointEnable; - } - else if (!string.IsNullOrEmpty(prop.InitLevelGraph)) - { - var json = prop.InitLevelGraph; - - // Hacky way to setup prop triggers - if (json.Contains("Maze_GroupProp_OpenTreasure_WhenMonsterDie")) + { + foreach (var condition in group.SavedValueCondition.Conditions) + FloorSavedValue.Add(new FloorSavedValueInfo { - //prop.Trigger = new TriggerOpenTreasureWhenMonsterDie(group.Id); - } - else if (json.Contains("Common_Console")) - { - prop.CommonConsole = true; - } + DefaultValue = 0, + ID = -1, + Name = condition.SavedValueName + }); - // Clear for garbage collection - prop.ValueSource = null; - prop.InitLevelGraph = null; - } + foreach (var prop in group.PropList) + // Check if prop can be teleported to + if (prop.AnchorID > 0) + { + // Put inside cached teleport list to send to client when they request map info + CachedTeleports.TryAdd(prop.MappingInfoID, prop); + UnlockedCheckpoints.Add(prop); + + // Force prop to be in the unlocked state + prop.State = PropStateEnum.CheckPointEnable; + } + else if (!string.IsNullOrEmpty(prop.InitLevelGraph)) + { + var json = prop.InitLevelGraph; + + // Hacky way to setup prop triggers + if (json.Contains("Maze_GroupProp_OpenTreasure_WhenMonsterDie")) + { + //prop.Trigger = new TriggerOpenTreasureWhenMonsterDie(group.Id); + } + else if (json.Contains("Common_Console")) + { + prop.CommonConsole = true; + } + + // Clear for garbage collection + prop.ValueSource = null; + prop.InitLevelGraph = null; + } + } Loaded = true; } diff --git a/Common/Data/Config/Scene/GroupInfo.cs b/Common/Data/Config/Scene/GroupInfo.cs index 310b6fd4..a2500b59 100644 --- a/Common/Data/Config/Scene/GroupInfo.cs +++ b/Common/Data/Config/Scene/GroupInfo.cs @@ -1,7 +1,9 @@ -using EggLink.DanhengServer.Database.Quests; +using EggLink.DanhengServer.Data.Excel; +using EggLink.DanhengServer.Database.Quests; using EggLink.DanhengServer.Enums; using EggLink.DanhengServer.Enums.Mission; using EggLink.DanhengServer.Enums.Scene; +using EggLink.DanhengServer.Enums.Task; using EggLink.DanhengServer.Util; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -22,6 +24,7 @@ public class GroupInfo public string LevelGraph { get; set; } = ""; public bool LoadOnInitial { get; set; } public string GroupName { get; set; } = ""; + public SavedValueLoadCondition SavedValueCondition { get; set; } = new(); public LoadCondition LoadCondition { get; set; } = new(); public LoadCondition UnloadCondition { get; set; } = new(); public LoadCondition ForceUnloadCondition { get; set; } = new(); @@ -114,6 +117,56 @@ public class LoadCondition } } +public class SavedValueLoadCondition +{ + public List Conditions { get; set; } = []; + + [JsonConverter(typeof(StringEnumConverter))] + public OperationEnum Operation { get; set; } = OperationEnum.And; + + public bool IsTrue(Dictionary savedValue, bool defaultResult = true) + { + if (Conditions.Count == 0) return defaultResult; + var canLoad = Operation == OperationEnum.And; + // check load condition + foreach (var condition in Conditions) + { + // saved value + var status = savedValue.GetValueOrDefault(condition.SavedValueName, 0); + var b = condition.Operation switch + { + CompareTypeEnum.Equal => status != condition.Value, + CompareTypeEnum.Greater => status <= condition.Value, + CompareTypeEnum.GreaterEqual => status > condition.Value, + CompareTypeEnum.Less => status >= condition.Value, + CompareTypeEnum.LessEqual => status < condition.Value, + CompareTypeEnum.NotEqual => status == condition.Value, + CompareTypeEnum.Unknow => true, + _ => false + }; + + if (b) + { + if (Operation == OperationEnum.And) + { + canLoad = false; + break; + } + } + else + { + if (Operation == OperationEnum.Or) + { + canLoad = true; + break; + } + } + } + + return canLoad; + } +} + public class Condition { [JsonConverter(typeof(StringEnumConverter))] @@ -125,6 +178,16 @@ public class Condition public MissionPhaseEnum Phase { get; set; } = MissionPhaseEnum.Accept; } +public class SavedValueCondition +{ + public string SavedValueName { get; set; } = ""; + + public int Value { get; set; } + + [JsonConverter(typeof(StringEnumConverter))] + public CompareTypeEnum Operation { get; set; } = CompareTypeEnum.Unknow; +} + public class LevelGroupSystemUnlockCondition { public List Conditions { get; set; } = []; diff --git a/DanhengKcpSharp/BasePacket.cs b/DanhengKcpSharp/BasePacket.cs index 2371a93f..cb8dbdbb 100644 --- a/DanhengKcpSharp/BasePacket.cs +++ b/DanhengKcpSharp/BasePacket.cs @@ -21,6 +21,11 @@ public class BasePacket(ushort cmdId) Data = message.ToByteArray(); } + public void SetData(string base64) + { + SetData(Convert.FromBase64String(base64)); + } + public byte[] BuildPacket() { using MemoryStream? ms = new(); diff --git a/GameServer/Game/Player/PlayerInstance.cs b/GameServer/Game/Player/PlayerInstance.cs index f08ac702..95884f61 100644 --- a/GameServer/Game/Player/PlayerInstance.cs +++ b/GameServer/Game/Player/PlayerInstance.cs @@ -497,7 +497,7 @@ public class PlayerInstance(PlayerData data) $"JG_ML_{splits[3]}_Puzzle{(config.TargetState == PropStateEnum.Open ? "Started" : "Complete")}"; } - if (SceneInstance?.FloorInfo?.SavedValues.Find(x => x.Name == key) != null) + if (SceneInstance?.FloorInfo?.FloorSavedValue.Find(x => x.Name == key) != null) { // should save var plane = SceneInstance.PlaneId; diff --git a/GameServer/Game/Scene/SceneEntityLoader.cs b/GameServer/Game/Scene/SceneEntityLoader.cs index d741e0b5..3b51f6ff 100644 --- a/GameServer/Game/Scene/SceneEntityLoader.cs +++ b/GameServer/Game/Scene/SceneEntityLoader.cs @@ -1,5 +1,6 @@ using EggLink.DanhengServer.Data; using EggLink.DanhengServer.Data.Config.Scene; +using EggLink.DanhengServer.Database.Scene; using EggLink.DanhengServer.Enums; using EggLink.DanhengServer.Enums.Mission; using EggLink.DanhengServer.Enums.Scene; @@ -135,6 +136,10 @@ public class SceneEntityLoader(SceneInstance scene) if ((!info.LoadCondition.IsTrue(missionData) || info.UnloadCondition.IsTrue(missionData, false) || info.ForceUnloadCondition.IsTrue(missionData, false)) && !forceLoad) return null; + if (!info.SavedValueCondition.IsTrue( + Scene.Player.SceneData!.FloorSavedData.GetValueOrDefault(Scene.FloorId, [])) && !forceLoad) + return null; + if (Scene.Entities.Values.ToList().FindIndex(x => x.GroupID == info.Id) != -1) // check if group is already loaded return null; diff --git a/GameServer/Game/Scene/SceneInstance.cs b/GameServer/Game/Scene/SceneInstance.cs index ba79824a..f097ca2e 100644 --- a/GameServer/Game/Scene/SceneInstance.cs +++ b/GameServer/Game/Scene/SceneInstance.cs @@ -115,7 +115,7 @@ public class SceneInstance Player.SceneData!.FloorSavedData.TryGetValue(FloorId, out var floorData); - foreach (var value in FloorInfo?.SavedValues ?? []) + foreach (var value in FloorInfo?.FloorSavedValue ?? []) if (floorData != null && floorData.TryGetValue(value.Name, out var v)) sceneInfo.FloorSavedData[value.Name] = v; else diff --git a/GameServer/Game/TrainParty/TrainPartyManager.cs b/GameServer/Game/TrainParty/TrainPartyManager.cs index 2ccc7b3e..49db310f 100644 --- a/GameServer/Game/TrainParty/TrainPartyManager.cs +++ b/GameServer/Game/TrainParty/TrainPartyManager.cs @@ -31,7 +31,8 @@ public class TrainPartyManager : BasePlayerManager var proto = new TrainPartyData { TrainPartyInfo = ToPartyInfo(), - PassengerInfo = ToPassengerInfo() + PassengerInfo = ToPassengerInfo(), + LFLMKPGJADO = new MJKBNJAKOJH() }; return proto;