fix: some event will get stuck

This commit is contained in:
Somebody
2025-08-29 16:01:08 +08:00
committed by StopWuyu
parent 86829e1c17
commit aef076e9b6
10 changed files with 308 additions and 36 deletions

View File

@@ -0,0 +1,30 @@
using EggLink.DanhengServer.Enums.TournRogue;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("RogueTournMiracle.json")]
public class RogueTournMiracleExcel : ExcelResource
{
public int MiracleID { get; set; }
public int MiracleDisplayID { get; set; }
public int HandbookMiracleID { get; set; }
public int MiracleEffectDisplayID { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public RogueTournModeEnum TournMode { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public RogueTournMiracleCategoryEnum MiracleCategory { get; set; }
public override int GetId()
{
return MiracleID;
}
public override void Loaded()
{
GameData.RogueTournMiracleData.TryAdd(MiracleID, this);
}
}

View File

@@ -325,6 +325,7 @@ public static class GameData
public static Dictionary<int, RogueTournWorkbenchExcel> RogueTournWorkbenchData { get; private set; } = [];
public static Dictionary<int, RogueTournWorkbenchFuncExcel> RogueTournWorkbenchFuncData { get; private set; } = [];
public static Dictionary<int, RogueTournFormulaExcel> RogueTournFormulaData { get; private set; } = [];
public static Dictionary<int, RogueTournMiracleExcel> RogueTournMiracleData { get; private set; } = [];
public static Dictionary<int, RogueTournTitanTalentExcel> RogueTournTitanTalentData { get; private set; } = [];
public static Dictionary<RogueTitanTypeEnum, RogueTournTitanTypeExcel>

View File

@@ -25,5 +25,8 @@ public enum RogueEventActionTypeEnum
ActionGetBuffInFormula,
ActionEnhanceAllBuff,
ActionGetBuffInFormulaUntilExpandAll,
ActionAddFormulaAndExpand
ActionAddFormulaAndExpand,
ActionDropMiracle,
ActionDropBuff,
ActionAddDialogueEvent
}

View File

@@ -5,5 +5,7 @@ public enum RogueEventConditionTypeEnum
CondNone = 0,
CondCheckMoney,
CondHasAvatar,
CondLineupHasAvatar
CondLineupHasAvatar,
CondHasMiracle,
CondHasBuff
}

View File

@@ -0,0 +1,11 @@
namespace EggLink.DanhengServer.Enums.TournRogue;
public enum RogueTournMiracleCategoryEnum
{
None = 0,
Common,
Rare,
Legendary,
Negative,
Hex
}

View File

@@ -6,7 +6,7 @@
/// <typeparam name="T"></typeparam>
public class RandomList<T>
{
private readonly List<T> _List = [];
private readonly List<T> _list = [];
public RandomList()
{
@@ -14,21 +14,21 @@ public class RandomList<T>
public RandomList(IEnumerable<T> collection)
{
_List.AddRange(collection);
_list.AddRange(collection);
}
public void Add(T item, int weight)
{
for (var i = 0; i < weight; i++) _List.Add(item);
for (var i = 0; i < weight; i++) _list.Add(item);
}
public void Remove(T item)
{
var temp = _List.Clone().ToList();
_List.Clear();
var temp = _list.Clone().ToList();
_list.Clear();
foreach (var i in temp)
if (i?.Equals(item) == false)
_List.Add(i);
_list.Add(i);
}
public void AddRange(IEnumerable<T> collection, IEnumerable<int> weights)
@@ -39,17 +39,17 @@ public class RandomList<T>
public T? GetRandom()
{
if (_List.Count == 0) return default;
return _List[Random.Shared.Next(_List.Count)];
if (_list.Count == 0) return default;
return _list[Random.Shared.Next(_list.Count)];
}
public void Clear()
{
_List.Clear();
_list.Clear();
}
public int GetCount()
{
return _List.Count;
return _list.Count;
}
}

View File

@@ -143,6 +143,23 @@ public abstract class BaseRogueInstance(PlayerInstance player, RogueSubModeEnum
await UpdateMenu();
}
public virtual async ValueTask RemoveBuffList(List<int> buffIds)
{
List<RogueCommonActionResult> resultList = [];
foreach (var buff in buffIds)
{
var res = await RemoveBuff(buff, displayType: RogueCommonActionResultDisplayType.Multi, updateMenu: false,
notify: false);
if (res != null) resultList.Add(res);
}
await Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueSubMode, resultList,
RogueCommonActionResultDisplayType.Multi));
await UpdateMenu();
}
public virtual async ValueTask EnhanceBuff(int buffId,
RogueCommonActionResultSourceType source = RogueCommonActionResultSourceType.Dialogue)
{
@@ -392,19 +409,41 @@ public abstract class BaseRogueInstance(PlayerInstance player, RogueSubModeEnum
new PacketHandleRogueCommonPendingActionScRsp(action.QueuePosition, location, selectMiracle: true));
}
public virtual async ValueTask AddMiracle(int miracleId)
public virtual async ValueTask AddMiracle(int miracleId, RogueCommonActionResultSourceType source = RogueCommonActionResultSourceType.Select)
{
if (RogueMiracles.ContainsKey(miracleId)) return;
GameData.RogueMiracleData.TryGetValue(miracleId, out var excel);
if (excel == null) return;
GameData.RogueTournMiracleData.TryGetValue(miracleId, out var excelT);
if (excel == null && excelT == null) return;
var miracle = new RogueMiracleInstance(this, miracleId);
RogueMiracles.Add(miracleId, miracle);
await Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueSubMode, miracle.ToGetResult(),
await Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueSubMode, miracle.ToGetResult(source),
RogueCommonActionResultDisplayType.Single));
}
public virtual async ValueTask AddMiracleList(List<int> miracleIds, RogueCommonActionResultSourceType source = RogueCommonActionResultSourceType.Select)
{
List<RogueCommonActionResult> res = [];
foreach (var miracleId in miracleIds)
{
if (RogueMiracles.ContainsKey(miracleId)) return;
GameData.RogueMiracleData.TryGetValue(miracleId, out var excel);
GameData.RogueTournMiracleData.TryGetValue(miracleId, out var excelT);
if (excel == null && excelT == null) return;
var miracle = new RogueMiracleInstance(this, miracleId);
RogueMiracles.Add(miracleId, miracle);
res.Add(miracle.ToGetResult(source));
}
await Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueSubMode, res,
RogueCommonActionResultDisplayType.Multi));
}
#endregion
#region Actions
@@ -483,26 +522,48 @@ public abstract class BaseRogueInstance(PlayerInstance player, RogueSubModeEnum
{
RogueDialogueEventConfig? dialogue = null;
RandomList<RogueDialogueEventConfig> randomList = new();
switch (RogueSubMode)
{
case RogueSubModeEnum.CosmosRogue:
case RogueSubModeEnum.CosmosRogueEndless:
dialogue = GameData.CosmosRogueDialogueEventConfig.Values.ToList().RandomElement();
foreach (var e in GameData.CosmosRogueDialogueEventConfig.Values.ToList())
{
randomList.Add(e, e.Weight);
}
break;
case RogueSubModeEnum.TournRogue:
dialogue = GameData.TournRogueDialogueEventConfig.Values.ToList().RandomElement();
foreach (var e in GameData.TournRogueDialogueEventConfig.Values.ToList())
{
randomList.Add(e, e.Weight);
}
break;
case RogueSubModeEnum.ChessRogue:
dialogue = GameData.SwarmRogueDialogueEventConfig.Values.ToList().RandomElement();
foreach (var e in GameData.SwarmRogueDialogueEventConfig.Values.ToList())
{
randomList.Add(e, e.Weight);
}
break;
case RogueSubModeEnum.ChessRogueNous:
dialogue = GameData.NousRogueDialogueEventConfig.Values.ToList().RandomElement();
foreach (var e in GameData.NousRogueDialogueEventConfig.Values.ToList())
{
randomList.Add(e, e.Weight);
}
break;
case RogueSubModeEnum.MagicRogue:
dialogue = GameData.MagicRogueDialogueEventConfig.Values.ToList().RandomElement();
foreach (var e in GameData.MagicRogueDialogueEventConfig.Values.ToList())
{
randomList.Add(e, e.Weight);
}
break;
}
if (randomList.GetCount() > 0) dialogue = randomList.GetRandom();
if (dialogue == null) throw new Exception("No dialogue event config found for rogue mode " + RogueSubMode);
var instance = new RogueEventInstance(dialogue, npc, CurEventUniqueId++);

View File

@@ -6,6 +6,10 @@ using EggLink.DanhengServer.GameServer.Game.RogueTourn;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lineup;
using Newtonsoft.Json.Linq;
using SqlSugar;
using System.Linq;
using EggLink.DanhengServer.Data.Excel;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util;
namespace EggLink.DanhengServer.GameServer.Game.Rogue.Event;
@@ -94,7 +98,15 @@ public static class RogueEventActionExecutor
case RogueEventActionTypeEnum.ActionAddFormulaAndExpand:
await ActionAddFormulaAndExpand(rogue, eventInst, actionData);
break;
case RogueEventActionTypeEnum.ActionNone:
case RogueEventActionTypeEnum.ActionDropMiracle:
await ActionDropMiracle(rogue, eventInst, actionData);
break;
case RogueEventActionTypeEnum.ActionDropBuff:
await ActionDropBuff(rogue, eventInst, actionData);
break;
case RogueEventActionTypeEnum.ActionAddDialogueEvent:
await ActionAddDialogueEvent(rogue, eventInst, actionData);
break;
default:
break;
}
@@ -171,18 +183,24 @@ public static class RogueEventActionExecutor
{
var hpChangeByCurHp = Convert.ToInt32(actionData.Param.GetValueOrDefault("HpChangeByCurHp", 0));
var hpChange = Convert.ToInt32(actionData.Param.GetValueOrDefault("HpChange", 0));
var spChange = Convert.ToInt32(actionData.Param.GetValueOrDefault("SpChange", 0));
var mpChange = Convert.ToInt32(actionData.Param.GetValueOrDefault("MpChange", 0));
foreach (var formalAvatar in rogue.Player.AvatarManager!.AvatarData.FormalAvatars)
{
if (hpChange != 0)
formalAvatar.ExtraLineupHp = hpChange;
if (hpChangeByCurHp != 0)
{
formalAvatar.ExtraLineupHp = (int)Math.Ceiling(formalAvatar.ExtraLineupHp * (-hpChangeByCurHp / 10000d));
}
if (hpChangeByCurHp != 0) formalAvatar.ExtraLineupHp = (int)Math.Ceiling(formalAvatar.ExtraLineupHp * ((10000 + hpChangeByCurHp) / 10000d));
if (spChange != 0)
formalAvatar.ExtraLineupSp = Math.Max(Math.Min(formalAvatar.ExtraLineupSp + spChange, 0), 10000);
}
var curLineup = rogue.Player.LineupManager!.GetCurLineup()!;
if (mpChange != 0)
curLineup.Mp = Math.Max(Math.Min(0, curLineup.Mp + mpChange), rogue.Player.LineupManager!.GetMaxMp());
// sync
await rogue.Player.SendPacket(new PacketSyncLineupNotify(rogue.Player.LineupManager!.GetCurLineup()!));
}
@@ -190,7 +208,21 @@ public static class RogueEventActionExecutor
private static async ValueTask ActionRemoveBuff(BaseRogueInstance rogue, RogueEventInstance eventInst,
RogueDialogueEventActionData actionData)
{
// TODO select buff to remove
var count = Convert.ToInt32(actionData.Param.GetValueOrDefault("Count", 1));
var groupId = Convert.ToInt32(actionData.Param.GetValueOrDefault("GroupId", 0));
if (count <= 0) return;
var group = GameData.RogueBuffGroupData.GetValueOrDefault(groupId)?.BuffList.Select(x => x.MazeBuffID).ToList();
if (group == null && groupId != 0) return;
var ownedBuffs = groupId == 0 || group == null
? rogue.RogueBuffs.ToList()
: rogue.RogueBuffs.Where(x => group.Contains(x.BuffId)).ToList();
if (ownedBuffs.Count == 0) return;
var selectedBuffs = ownedBuffs.OrderBy(_ => Guid.NewGuid()).Take(Math.Min(count, ownedBuffs.Count)).ToList(); // avoid ownedBuffs.Count < count
await rogue.RemoveBuffList(selectedBuffs.Select(x => x.BuffId).ToList());
}
private static async ValueTask ActionInvalidateOption(BaseRogueInstance rogue, RogueEventInstance eventInst,
@@ -213,7 +245,7 @@ public static class RogueEventActionExecutor
var miracleId = Convert.ToInt32(actionData.Param.GetValueOrDefault("MiracleId", 0));
if (miracleId == 0) return;
await rogue.AddMiracle(miracleId);
await rogue.AddMiracle(miracleId, RogueCommonActionResultSourceType.Dialogue);
}
private static async ValueTask ActionGetBuffInGroup(BaseRogueInstance rogue, RogueEventInstance eventInst,
@@ -237,7 +269,7 @@ public static class RogueEventActionExecutor
{
var stageId = Convert.ToInt32(actionData.Param.GetValueOrDefault("StageId", 0));
var winActions = (JArray?)actionData.Param.GetValueOrDefault("WinActions"); // TODO
if (!GameData.PlaneEventData.ContainsKey(stageId)) return;
if (!GameData.PlaneEventData.ContainsKey(stageId * 10 + rogue.Player.Data.WorldLevel)) return;
var optionInst = eventInst.Options.Find(x => x.OptionId == eventInst.SelectedOptionId);
if (optionInst == null) return;
@@ -358,7 +390,7 @@ public static class RogueEventActionExecutor
var notOwned = group.Where(x => !owned.Contains(x.MazeBuffID)).ToList();
if (notOwned.Count == 0) return;
await rogue.AddBuffList(notOwned.Take(Math.Min(count, notOwned.Count)).ToList());
await rogue.AddBuffList(notOwned.OrderBy(_ => Guid.NewGuid()).Take(Math.Min(count, notOwned.Count)).ToList());
}
private static async ValueTask ActionGetBuff(BaseRogueInstance rogue, RogueEventInstance eventInst,
@@ -375,14 +407,32 @@ public static class RogueEventActionExecutor
var notOwned = group.Where(x => !owned.Contains(x.MazeBuffID)).ToList();
if (notOwned.Count == 0) return;
await rogue.AddBuffList(notOwned.Take(Math.Min(count, notOwned.Count)).ToList());
await rogue.AddBuffList(notOwned.OrderBy(_ => Guid.NewGuid()).Take(Math.Min(count, notOwned.Count)).ToList());
}
private static async ValueTask ActionGetMiracleByCategory(BaseRogueInstance rogue, RogueEventInstance eventInst,
RogueDialogueEventActionData actionData)
{
// TODO
await ValueTask.CompletedTask;
var categories = (JArray?)actionData.Param.GetValueOrDefault("Categories");
var count = Convert.ToInt32(actionData.Param.GetValueOrDefault("Count", 1));
if (categories == null || categories.Count == 0 || count == 0) return;
List<RogueTournMiracleCategoryEnum> categoryEnums = [];
foreach (var cat in categories)
{
if (Enum.TryParse(cat.ToString(), out RogueTournMiracleCategoryEnum categoryEnum))
categoryEnums.Add(categoryEnum);
}
if (categoryEnums.Count == 0) return;
var possibleMiracles = GameData.RogueTournMiracleData.Values
.Where(x => categoryEnums.Contains(x.MiracleCategory) && !rogue.RogueMiracles.ContainsKey(x.MiracleID) &&
x.TournMode == RogueTournModeEnum.Tourn2)
.ToList();
if (possibleMiracles.Count == 0) return;
var selectedMiracles = possibleMiracles.OrderBy(_ => Guid.NewGuid()).Take(Math.Min(count, possibleMiracles.Count)).ToList(); // avoid possibleMiracles.Count < count
await rogue.AddMiracleList(selectedMiracles.Select(x => x.MiracleID).ToList(), RogueCommonActionResultSourceType.Dialogue);
}
private static async ValueTask ActionDropFormula(BaseRogueInstance rogue, RogueEventInstance eventInst,
@@ -416,10 +466,34 @@ public static class RogueEventActionExecutor
var count = Convert.ToInt32(actionData.Param.GetValueOrDefault("Count", 1));
if (count <= 0) return;
if (rogue is RogueTournInstance inst)
if (rogue is not RogueTournInstance inst) return;
Dictionary<int, int> typeNumDict = [];
foreach (var excel in inst.RogueFormulas)
{
// TODO
typeNumDict.TryAdd(excel.MainBuffTypeID, 0);
typeNumDict.TryAdd(excel.SubBuffTypeID, 0);
typeNumDict[excel.MainBuffTypeID] = Math.Max(typeNumDict[excel.MainBuffTypeID], excel.MainBuffNum);
typeNumDict[excel.SubBuffTypeID] = Math.Max(typeNumDict[excel.SubBuffTypeID], excel.SubBuffNum);
}
List<int> availableTypes = [];
foreach (var (typeId, num) in typeNumDict)
{
var ownedNum = inst.RogueBuffs.Count(x => x.BuffExcel.RogueBuffType == typeId);
if (ownedNum < num)
availableTypes.Add(typeId);
}
if (availableTypes.Count == 0) return;
var owned = rogue.RogueBuffs.Select(x => x.BuffId).ToList();
var notOwned = GameData.RogueBuffData.Values.Where(x => x is RogueTournBuffExcel)
.Where(x => !owned.Contains(x.MazeBuffID) && availableTypes.Contains(x.RogueBuffType) && x.MazeBuffLevel == 1).ToList();
if (notOwned.Count == 0) return;
await rogue.AddBuffList(notOwned.OrderBy(_ => Guid.NewGuid()).Take(Math.Min(count, notOwned.Count)).ToList()); // avoid notOwned.Count < count
}
private static async ValueTask ActionEnhanceAllBuff(BaseRogueInstance rogue, RogueEventInstance eventInst,
@@ -433,6 +507,41 @@ public static class RogueEventActionExecutor
private static async ValueTask ActionGetBuffInFormulaUntilExpandAll(BaseRogueInstance rogue,
RogueEventInstance eventInst, RogueDialogueEventActionData actionData)
{
if (rogue is not RogueTournInstance inst) return;
Dictionary<int, int> typeNumDict = [];
foreach (var excel in inst.RogueFormulas)
{
typeNumDict.TryAdd(excel.MainBuffTypeID, 0);
typeNumDict.TryAdd(excel.SubBuffTypeID, 0);
typeNumDict[excel.MainBuffTypeID] = Math.Max(typeNumDict[excel.MainBuffTypeID], excel.MainBuffNum);
typeNumDict[excel.SubBuffTypeID] = Math.Max(typeNumDict[excel.SubBuffTypeID], excel.SubBuffNum);
}
List<int> availableTypes = [];
foreach (var (typeId, num) in typeNumDict)
{
var ownedNum = inst.RogueBuffs.Count(x => x.BuffExcel.RogueBuffType == typeId);
if (ownedNum < num)
availableTypes.Add(typeId);
}
if (availableTypes.Count == 0) return;
var owned = rogue.RogueBuffs.Select(x => x.BuffId).ToList();
var notOwned = GameData.RogueBuffData.Values.Where(x => x is RogueTournBuffExcel)
.Where(x => !owned.Contains(x.MazeBuffID) && availableTypes.Contains(x.RogueBuffType) && x.MazeBuffLevel == 1).ToList();
if (notOwned.Count == 0) return;
while (inst.ExpandedFormulaIdList.Count < inst.RogueFormulas.Count)
{
var add = notOwned.RandomElement();
await inst.AddBuff(add.MazeBuffID);
notOwned.Remove(add);
if (notOwned.Count == 0) break;
}
}
private static async ValueTask ActionAddFormulaAndExpand(BaseRogueInstance rogue, RogueEventInstance eventInst,
@@ -454,4 +563,27 @@ public static class RogueEventActionExecutor
// TODO expand it
}
private static async ValueTask ActionDropMiracle(BaseRogueInstance rogue, RogueEventInstance eventInst,
RogueDialogueEventActionData actionData)
{
await ValueTask.CompletedTask;
}
private static async ValueTask ActionDropBuff(BaseRogueInstance rogue, RogueEventInstance eventInst,
RogueDialogueEventActionData actionData)
{
// TODO select buff to remove
await ValueTask.CompletedTask;
}
private static async ValueTask ActionAddDialogueEvent(BaseRogueInstance rogue, RogueEventInstance eventInst,
RogueDialogueEventActionData actionData)
{
var eventId = Convert.ToInt32(actionData.Param.GetValueOrDefault("EventId", 0));
if (eventId == 0) return;
eventInst.EffectEventId.Add(eventId);
await ValueTask.CompletedTask;
}
}

View File

@@ -1,7 +1,9 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Enums.Rogue;
using EggLink.DanhengServer.Enums.TournRogue;
using EggLink.DanhengServer.GameServer.Game.Player;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.RogueCommon;
using Newtonsoft.Json.Linq;
namespace EggLink.DanhengServer.GameServer.Game.Rogue.Event;
@@ -51,6 +53,34 @@ public class RogueEventManager(PlayerInstance player, BaseRogueInstance rogueIns
x.BaseAvatarId != Convert.ToInt32(condition.Param["AvatarId"])) == true)
optionInst.IsValid = false;
break;
case RogueEventConditionTypeEnum.CondHasMiracle:
var categories = (JArray?)condition.Param["Categories"];
if (categories == null || categories.Count == 0) break;
List<RogueTournMiracleCategoryEnum> categoryEnums = [];
foreach (var cat in categories)
{
if (Enum.TryParse(cat.ToString(), out RogueTournMiracleCategoryEnum categoryEnum))
categoryEnums.Add(categoryEnum);
}
if (Rogue.RogueMiracles.Keys.All(x =>
!categoryEnums.Contains(
GameData.RogueTournMiracleData.GetValueOrDefault(x)?.MiracleCategory ??
RogueTournMiracleCategoryEnum.None)))
optionInst.IsValid = false;
break;
case RogueEventConditionTypeEnum.CondHasBuff:
var groupId = Convert.ToInt32(condition.Param["GroupId"]);
var group = GameData.RogueBuffGroupData.GetValueOrDefault(groupId);
if (group == null) break;
var buffInGroup = group.BuffList.Select(x => x.MazeBuffID).ToHashSet();
if (Rogue.RogueBuffs.All(x => !buffInGroup.Contains(x.BuffId))) optionInst.IsValid = false;
break;
}
}
@@ -118,5 +148,7 @@ public class RogueEventManager(PlayerInstance player, BaseRogueInstance rogueIns
await Player.SendPacket(new PacketSyncRogueCommonDialogueOptionFinishScNotify(eventInstance));
option.IsSelected = true;
await Player.SendPacket(new PacketSelectRogueCommonDialogueOptionScRsp(eventInstance));
eventInstance.EffectEventId.Clear();
}
}

View File

@@ -144,11 +144,11 @@ public class RogueMiracleInstance
};
}
public RogueCommonActionResult ToGetResult()
public RogueCommonActionResult ToGetResult(RogueCommonActionResultSourceType source = RogueCommonActionResultSourceType.Select)
{
return new RogueCommonActionResult
{
Source = RogueCommonActionResultSourceType.Select,
Source = source,
RogueAction = new RogueCommonActionResultData
{
GetMiracleList = new RogueCommonMiracle