feat: grid fight pending action

This commit is contained in:
StopWuyu
2025-11-01 18:00:30 +08:00
parent 15e91b1dc6
commit 81d5b7d563
340 changed files with 2376 additions and 1867 deletions

View File

@@ -22,10 +22,11 @@ public class BattleGridFightOptions(GridFightGameSectionInfo curSection, GridFig
public void HandleProto(SceneBattleInfo proto, BattleInstance battle)
{
var avatars = AvatarComponent.GetForegroundAvatarInfos(4 + BasicComponent.GetFieldCount());
var backAvatars = AvatarComponent.GetBackgroundAvatarInfos(4 + BasicComponent.GetFieldCount());
var tempLineup = new LineupInfo
{
BaseAvatars = avatars.Select(y => new LineupAvatarInfo
BaseAvatars = avatars.Concat(backAvatars).Select(y => new LineupAvatarInfo
{
BaseAvatarId = y.BaseAvatarId
}).ToList()
@@ -35,6 +36,11 @@ public class BattleGridFightOptions(GridFightGameSectionInfo curSection, GridFig
x.ToBattleProto(
new PlayerDataCollection(Player.Data, Player.InventoryManager!.Data, tempLineup), AvatarType.AvatarGridFightType)).ToList();
var backFormatted = backAvatars.Select(x =>
x.ToBattleProto(
new PlayerDataCollection(Player.Data, Player.InventoryManager!.Data, tempLineup),
AvatarType.AvatarGridFightType)).ToList();
proto.BattleAvatarList.Add(formatted.Take(4));
foreach (var wave in Encounter.MonsterWaves)
@@ -59,10 +65,22 @@ public class BattleGridFightOptions(GridFightGameSectionInfo curSection, GridFig
foreach (var role in AvatarComponent.Data.Roles)
{
if (!GameData.GridFightRoleStarData.TryGetValue(role.RoleId << 2 | role.Tier, out var roleConf)) continue;
if (!GameData.GridFightRoleStarData.TryGetValue(role.RoleId << 4 | role.Tier, out var roleConf)) continue;
battle.BattleEvents.TryAdd((int)roleConf.BEID, new BattleEventInstance((int)roleConf.BEID, 5000));
}
battle.Buffs.Add(new MazeBuff(35100001, 1, -1)
{
WaveFlag = -1
});
var even = battle.Stages.First().StageConfigData.FirstOrDefault(x => x.Key == "_CreateBattleEvent");
if (even?.Value != null)
{
var id = int.Parse(even.Value);
battle.BattleEvents.TryAdd(id, new BattleEventInstance(id, 5000));
}
proto.BattleGridFightInfo = new BattleGridFightInfo
{
GridGameAvatarList =
@@ -72,7 +90,7 @@ public class BattleGridFightOptions(GridFightGameSectionInfo curSection, GridFig
BattleWaveId = 1,
GridFightCurLevel = BasicComponent.Data.CurLevel,
GridFightLineupHp = BasicComponent.Data.CurHp,
GridFightAvatarList = { formatted },
GridFightAvatarList = { formatted, backFormatted },
GridFightStageInfo = new BattleGridFightStageInfo
{
ChapterId = CurSection.ChapterId,
@@ -80,7 +98,8 @@ public class BattleGridFightOptions(GridFightGameSectionInfo curSection, GridFig
SectionId = CurSection.SectionId
},
IsOverlock = Inst.IsOverLock,
Season = Inst.Season
Season = Inst.Season,
DFNBKALPGPH = 1,
};
}
}

View File

@@ -1,4 +1,5 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction;
using EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.GridFight;
using EggLink.DanhengServer.Proto;
@@ -8,6 +9,8 @@ namespace EggLink.DanhengServer.GameServer.Game.GridFight.Component;
public class GridFightBasicComponent(GridFightInstance inst) : BaseGridFightComponent(inst)
{
#region Fields & Properties
public const uint MaxHp = 100;
public GridFightBasicInfoPb Data { get; set; } = new()
@@ -19,6 +22,10 @@ public class GridFightBasicComponent(GridFightInstance inst) : BaseGridFightComp
CurGold = 5
};
#endregion
#region Data Management
public async ValueTask<Retcode> UpdateGoldNum(int changeNum, bool sendPacket = true, GridFightSrc src = GridFightSrc.KGridFightSrcManualRefreshGoods)
{
if (changeNum < 0 && -changeNum > Data.CurGold)
@@ -131,11 +138,19 @@ public class GridFightBasicComponent(GridFightInstance inst) : BaseGridFightComp
return Retcode.RetSucc;
}
#endregion
#region Information
public uint GetFieldCount()
{
return 4 + 6;
}
#endregion
#region Serialization
public override GridFightGameInfo ToProto()
{
return new GridFightGameInfo
@@ -162,4 +177,6 @@ public class GridFightBasicComponent(GridFightInstance inst) : BaseGridFightComp
}
};
}
#endregion
}

View File

@@ -10,17 +10,23 @@ namespace EggLink.DanhengServer.GameServer.Game.GridFight.Component;
public class GridFightLevelComponent : BaseGridFightComponent
{
#region Properties & Fields // TODO : to proto field
private uint _curChapterId = 1;
private uint _curSectionId = 1;
public Dictionary<uint, List<GridFightGameSectionInfo>> Sections { get; } = [];
public GridFightGameSectionInfo CurrentSection => Sections[_curChapterId][(int)(_curSectionId - 1)];
public List<GridFightRoleDamageSttInfo> RoleDamageSttInfos { get; } = [];
#endregion
#region Constructors
public GridFightLevelComponent(GridFightInstance inst) : base(inst)
{
// TODO: randomly select a base route id
List<uint> chapterIds = [1100];
List<GridFightCampExcel> campPool = GameData.GridFightCampData.Values.ToList();
List<GridFightCampExcel> campPool = GameData.GridFightCampData.Values.Where(x => x.BossBattleArea != 0).ToList();
foreach (var chapterId in Enumerable.Range(1, 3))
{
var chapters = chapterIds.Count >= chapterId
@@ -34,11 +40,16 @@ public class GridFightLevelComponent : BaseGridFightComponent
var camp = campPool.RandomElement(); // cannot the same
campPool.Remove(camp);
// create section infos
Sections[(uint)chapterId] = [..select.Values.Select(x => new GridFightGameSectionInfo(x, camp))];
Sections[(uint)chapterId] = [.. select.Values.Select(x => new GridFightGameSectionInfo(x, camp))];
}
}
#endregion
#region Stt
public async ValueTask<(Retcode, GridFightRoleDamageSttInfo?)> AddRoleDamageStt(uint roleId, double damage, bool sendPacket = true)
{
var roleComp = Inst.GetComponent<GridFightRoleComponent>();
@@ -84,6 +95,10 @@ public class GridFightLevelComponent : BaseGridFightComponent
return (Retcode.RetSucc, res);
}
#endregion
#region Actions
public async ValueTask<List<BaseGridFightSyncData>> EnterNextSection(bool sendPacket = true)
{
// if last section of chapter
@@ -104,6 +119,8 @@ public class GridFightLevelComponent : BaseGridFightComponent
}
List<BaseGridFightSyncData> syncs = [new GridFightLevelSyncData(GridFightSrc.KGridFightSrcBattleEnd, this)];
//await Inst.RollPortalBuff();
if (sendPacket)
{
await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(syncs));
@@ -112,6 +129,10 @@ public class GridFightLevelComponent : BaseGridFightComponent
return syncs;
}
#endregion
#region Information
public List<GridFightMonsterInfo> GetBossMonsters()
{
// get every chapter last section camp
@@ -135,6 +156,10 @@ public class GridFightLevelComponent : BaseGridFightComponent
return bosses;
}
#endregion
#region Serialization
public override GridFightGameInfo ToProto()
{
return new GridFightGameInfo
@@ -182,6 +207,8 @@ public class GridFightLevelComponent : BaseGridFightComponent
RoleDamageSttList = { RoleDamageSttInfos.Select(x => x.ToProto()) }
};
}
#endregion
}
public class GridFightRoleDamageSttInfo
@@ -252,18 +279,54 @@ public class GridFightGameEncounterInfo
EncounterDifficulty = difficulty;
ParentSection = section;
if (ParentSection.Excel.NodeType != GridFightNodeTypeEnum.Monster) return;
if (ParentSection.Excel.NodeType is not GridFightNodeTypeEnum.Monster and not GridFightNodeTypeEnum.CampMonster
and not GridFightNodeTypeEnum.Boss and not GridFightNodeTypeEnum.EliteBranch) return;
var monsterPool = ParentSection.MonsterCamp.Monsters.Where(x => x.MonsterTier <= 3).OrderBy(_ => Guid.NewGuid()).ToList();
List<GridFightMonsterExcel> monsters = [];
foreach (var _ in Enumerable.Range(0, Random.Shared.Next(1, 5)))
var waveNum = ParentSection.Excel.NodeType switch
{
monsters.Add(monsterPool.RandomElement());
}
GridFightNodeTypeEnum.Boss => 2,
GridFightNodeTypeEnum.EliteBranch => 2,
_ => 1
};
MonsterWaves.Add(new GridFightGameMonsterWaveInfo(1, monsters, ParentSection.MonsterCamp.ID));
List<int> monsterNum = ParentSection.Excel.NodeType switch
{
GridFightNodeTypeEnum.Boss => [Random.Shared.Next(3, 5), 1],
GridFightNodeTypeEnum.EliteBranch => [Random.Shared.Next(3, 5), 3],
GridFightNodeTypeEnum.CampMonster => [3],
_ => [Random.Shared.Next(3, 5)]
};
var monsterPool = ParentSection.MonsterCamp.Monsters.Where(x => x.MonsterTier <= 2).OrderBy(_ => Guid.NewGuid()).ToList();
var monster4Pool = ParentSection.MonsterCamp.Monsters.Where(x => x.MonsterTier is 4 or 3).OrderBy(_ => Guid.NewGuid()).ToList();
var monster5Pool = ParentSection.MonsterCamp.Monsters.Where(x => x.MonsterTier == 5).OrderBy(_ => Guid.NewGuid()).ToList();
for (var i = 0; i < waveNum; i++)
{
if (i < waveNum - 1 || ParentSection.Excel.NodeType is GridFightNodeTypeEnum.Monster)
{
// no elite
var res = monsterPool.OrderBy(_ => Guid.NewGuid()).Take(monsterNum[i]).ToList();
MonsterWaves.Add(new GridFightGameMonsterWaveInfo((uint)(i + 1), res, ParentSection.MonsterCamp.ID));
}
else
{
var elite = ParentSection.Excel.NodeType switch
{
GridFightNodeTypeEnum.Boss => monster5Pool.RandomElement(),
_ => monster4Pool.RandomElement(),
};
List<GridFightMonsterExcel> monsters = [elite];
var remain = monsterNum[i] - 1;
if (remain > 0)
{
monsters.AddRange(monsterPool.OrderBy(_ => Guid.NewGuid()).Take(remain).ToList());
}
MonsterWaves.Add(new GridFightGameMonsterWaveInfo((uint)(i + 1), monsters, ParentSection.MonsterCamp.ID));
}
}
}
public uint EncounterIndex { get; set; }

View File

@@ -11,7 +11,8 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo
{
public GridFightAvatarInfoPb Data { get; set; } = new();
public async ValueTask<List<BaseGridFightSyncData>> AddAvatar(uint roleId, uint tier = 1, bool sendPacket = true)
public async ValueTask<List<BaseGridFightSyncData>> AddAvatar(uint roleId, uint tier = 1, bool sendPacket = true,
bool checkMerge = true, GridFightSrc src = GridFightSrc.KGridFightSrcBuyGoods)
{
var pos = 1u;
// get first empty pos
@@ -25,7 +26,7 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo
var info = new GridFightRoleInfoPb
{
RoleId = roleId,
RoleId = roleId,
UniqueId = ++Data.CurUniqueId,
Tier = tier,
Pos = pos
@@ -33,7 +34,14 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo
Data.Roles.Add(info);
List<BaseGridFightSyncData> syncs = [new GridFightRoleAddSyncData(GridFightSrc.KGridFightSrcBuyGoods, info)];
List<BaseGridFightSyncData> syncs = [new GridFightRoleAddSyncData(src, info)];
if (checkMerge)
{
var mergeSyncs = await CheckIfMergeRole();
syncs.AddRange(mergeSyncs);
}
if (sendPacket)
{
await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(syncs));
@@ -42,6 +50,58 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo
return syncs;
}
public async ValueTask<List<BaseGridFightSyncData>> CheckIfMergeRole(bool sendPacket = false)
{
List<BaseGridFightSyncData> syncs = [];
bool hasMerged;
do
{
hasMerged = false;
// group roles by RoleId and Tier, then filter groups with 3 or more roles
var mergeCandidates = Data.Roles
.GroupBy(r => new { r.RoleId, r.Tier })
.Where(g => g.Count() >= 3)
.Where(g =>
{
// check if next tier exists
var nextTierKey = g.Key.RoleId << 4 | (g.Key.Tier + 1);
return GameData.GridFightRoleStarData.ContainsKey(nextTierKey);
})
.OrderBy(g => g.Key.RoleId)
.ThenBy(g => g.Key.Tier)
.FirstOrDefault(); // process one group at a time to handle continuous merging
if (mergeCandidates != null)
{
var roleId = mergeCandidates.Key.RoleId;
var currentTier = mergeCandidates.Key.Tier;
var toMerge = mergeCandidates.Take(3).ToList();
// remove merged roles
foreach (var role in toMerge)
{
Data.Roles.Remove(role);
syncs.Add(new GridFightRoleRemoveSyncData(GridFightSrc.KGridFightSrcMergeRole, role));
}
// add new merged role with tier + 1
var addSyncs = await AddAvatar(roleId, currentTier + 1, false, false, GridFightSrc.KGridFightSrcMergeRole);
syncs.AddRange(addSyncs);
hasMerged = true;
}
} while (hasMerged); // continue until no more merges are possible
if (sendPacket && syncs.Count > 0)
{
await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(syncs));
}
return syncs;
}
public async ValueTask<List<BaseGridFightSyncData>> SellAvatar(uint uniqueId, bool sendPacket = true)
{
var role = Data.Roles.FirstOrDefault(x => x.UniqueId == uniqueId);
@@ -77,7 +137,34 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo
public List<BaseAvatarInfo> GetForegroundAvatarInfos(uint maxAvatarNum)
{
var foreground = Data.Roles.Where(x => x.Pos <= maxAvatarNum).OrderBy(x => x.Pos).ToList();
var foreground = Data.Roles.Where(x => x.Pos <= 4).OrderBy(x => x.Pos).ToList();
List<BaseAvatarInfo> res = [];
foreach (var role in foreground)
{
var excel = GameData.GridFightRoleBasicInfoData[role.RoleId];
// get formal or special
var formal = Inst.Player.AvatarManager!.GetFormalAvatar((int)excel.AvatarID);
if (formal != null)
{
res.Add(formal);
}
else
{
var special = Inst.Player.AvatarManager.GetTrialAvatar((int)excel.SpecialAvatarID);
if (special != null)
{
res.Add(special);
}
}
}
return res;
}
public List<BaseAvatarInfo> GetBackgroundAvatarInfos(uint maxAvatarNum)
{
var foreground = Data.Roles.Where(x => x.Pos <= maxAvatarNum && x.Pos > 4).OrderBy(x => x.Pos).ToList();
List<BaseAvatarInfo> res = [];
foreach (var role in foreground)

View File

@@ -1,5 +1,6 @@
using EggLink.DanhengServer.GameServer.Game.Battle;
using EggLink.DanhengServer.GameServer.Game.GridFight.Component;
using EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction;
using EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
using EggLink.DanhengServer.GameServer.Game.Player;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.GridFight;
@@ -18,7 +19,9 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
public BattleInstance? StartBattle()
{
return Player.BattleManager!.StartGridFightBattle(this);
var battle = Player.BattleManager!.StartGridFightBattle(this);
return battle;
}
public async ValueTask EndBattle(BattleInstance battle, PVEBattleResultCsReq req)
@@ -32,7 +35,7 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
var prevData = basicComp.Data.Clone();
var expNum = 5u;
var baseCoin = 3u;
var baseCoin = levelComp.CurrentSection.Excel.BasicGoldRewardNum;
var interestCoin = basicComp.Data.CurGold / 10;
if (battle.BattleEndStatus == BattleEndStatus.BattleEndWin)
@@ -89,8 +92,10 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
Components.Add(new GridFightLevelComponent(this));
Components.Add(new GridFightRoleComponent(this));
_ = GetComponent<GridFightRoleComponent>().AddAvatar(1414, 3, false); // TODO test
_ = GetComponent<GridFightRoleComponent>().AddAvatar(1414, 3, false);
_ = GetComponent<GridFightShopComponent>().RefreshShop(true, false);
// _ = CreatePendingAction<GridFightAugmentPendingAction>(); // TODO wait for release official server
}
public T GetComponent<T>() where T : BaseGridFightComponent
@@ -106,7 +111,7 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
Season = Season,
IsOverlock = IsOverLock,
UniqueId = UniqueId,
PendingAction = new GridFightPendingAction(),
PendingAction = GetCurAction().ToProto(),
GridFightGameData = ToGameDataInfo(),
RogueCurrentGameInfo = { ToGameInfos() }
};
@@ -121,4 +126,89 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
{
return new GridFightGameData();
}
#region Pending Action
public SortedDictionary<uint, BaseGridFightPendingAction> PendingActions { get; set; } = new();
private uint _curQueuePos = 1;
public BaseGridFightPendingAction GetCurAction()
{
if (PendingActions.Count > 0)
{
return PendingActions.First().Value;
}
return new GridFightEmptyPendingAction(this);
}
public uint AddPendingAction(BaseGridFightPendingAction action)
{
var pos = _curQueuePos++;
action.QueuePosition = pos;
PendingActions[pos] = action;
return pos;
}
public async ValueTask CreatePendingAction<T>(GridFightSrc src = GridFightSrc.KGridFightSrcEnterNode, bool sendPacket = true) where T: BaseGridFightPendingAction
{
var action = (T)Activator.CreateInstance(typeof(T), this)!;
AddPendingAction(action);
if (sendPacket)
await Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(
new GridFightPendingActionSyncData(src, action)));
}
public async ValueTask HandleResultRequest(GridFightHandlePendingActionCsReq req)
{
var curAction = GetCurAction();
switch (req.GridFightActionTypeCase)
{
case GridFightHandlePendingActionCsReq.GridFightActionTypeOneofCase.PortalBuffAction:
break;
case GridFightHandlePendingActionCsReq.GridFightActionTypeOneofCase.PortalBuffRerollAction:
if (curAction is GridFightPortalBuffPendingAction portalBuffAction)
{
await portalBuffAction.RerollBuff();
}
break;
case GridFightHandlePendingActionCsReq.GridFightActionTypeOneofCase.AugmentAction:
break;
case GridFightHandlePendingActionCsReq.GridFightActionTypeOneofCase.RerollAugmentAction:
if (curAction is GridFightAugmentPendingAction augmentAction)
{
await augmentAction.RerollAugment(req.RerollAugmentAction.AugmentId);
}
break;
case GridFightHandlePendingActionCsReq.GridFightActionTypeOneofCase.EliteAction:
break;
case GridFightHandlePendingActionCsReq.GridFightActionTypeOneofCase.SupplyAction:
break;
}
// end
PendingActions.Remove(curAction.QueuePosition);
await Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(
new GridFightPendingActionSyncData(GridFightSrc.KGridFightSrcNone, GetCurAction())));
}
#endregion
#region Portal Buff
public async ValueTask AddPortalBuff(uint portalBuffId)
{
}
#endregion
}

View File

@@ -0,0 +1,10 @@
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction;
public abstract class BaseGridFightPendingAction(GridFightInstance inst)
{
public GridFightInstance Inst { get; set; } = inst;
public uint QueuePosition { get; set; }
public abstract GridFightPendingAction ToProto();
}

View File

@@ -0,0 +1,72 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.GridFight;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction;
public class GridFightAugmentPendingAction : BaseGridFightPendingAction
{
public List<GridFightAugmentSelectUnit> Augments { get; set; } = [];
public override GridFightPendingAction ToProto()
{
return new GridFightPendingAction
{
QueuePosition = QueuePosition,
AugmentAction = new GridFightAugmentActionInfo
{
PendingAugmentInfoList = { Augments.Select(x => x.ToProto()) }
}
};
}
public GridFightAugmentPendingAction(GridFightInstance inst) : base(inst)
{
for (var i = 0; i < 3; i++)
{
var augmentId = GameData.GridFightAugmentData.Keys.Where(x => Augments.All(c => c.AugmentId != x)).ToList()
.RandomElement();
Augments.Add(new GridFightAugmentSelectUnit
{
AugmentId = augmentId
});
}
}
public async ValueTask RerollAugment(uint augmentId)
{
var augment = Augments.FirstOrDefault(x => x.AugmentId == augmentId);
if (augment == null) return;
if (augment.CurRerollNum >= augment.MaxRerollNum)
return;
var newAugmentId = GameData.GridFightAugmentData.Keys.Where(x => Augments.All(c => c.AugmentId != x)).ToList();
augment.AugmentId = newAugmentId.RandomElement();
augment.CurRerollNum++;
// sync
await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(
new GridFightPendingActionSyncData(GridFightSrc.KGridFightSrcNone, this)));
}
}
public class GridFightAugmentSelectUnit
{
public uint AugmentId { get; set; }
public uint MaxRerollNum { get; set; } = 2;
public uint CurRerollNum { get; set; }
public GridFightPendingAugmentInfo ToProto()
{
return new GridFightPendingAugmentInfo
{
AugmentId = AugmentId,
AugmentCurRerollCount = CurRerollNum,
AugmentMaxRerollCount = MaxRerollNum
};
}
}

View File

@@ -0,0 +1,14 @@
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction;
public class GridFightEliteBranchPendingAction(GridFightInstance inst) : BaseGridFightPendingAction(inst)
{
public override GridFightPendingAction ToProto()
{
return new GridFightPendingAction
{
EliteBranchAction = new GridFightEliteBranchActionInfo()
};
}
}

View File

@@ -0,0 +1,14 @@
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction;
public class GridFightElitePendingAction(GridFightInstance inst) : BaseGridFightPendingAction(inst)
{
public override GridFightPendingAction ToProto()
{
return new GridFightPendingAction
{
EliteAction = new GridFightEliteActionInfo()
};
}
}

View File

@@ -0,0 +1,11 @@
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction;
public class GridFightEmptyPendingAction(GridFightInstance inst) : BaseGridFightPendingAction(inst)
{
public override GridFightPendingAction ToProto()
{
return new GridFightPendingAction();
}
}

View File

@@ -0,0 +1,41 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.GridFight;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction;
public class GridFightPortalBuffPendingAction(GridFightInstance inst) : BaseGridFightPendingAction(inst)
{
public uint MaxRerollCount { get; set; } = 2;
public uint CurRerollCount { get; set; }
public async ValueTask RerollBuff()
{
if (MaxRerollCount <= CurRerollCount )
return;
CurRerollCount++;
PortalBuffList = GameData.GridFightPortalBuffData.Keys.OrderBy(_ => Guid.NewGuid()).Take(3).ToList();
// sync
await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(
new GridFightPendingActionSyncData(GridFightSrc.KGridFightSrcNone, this)));
}
public List<uint> PortalBuffList { get; set; } = GameData.GridFightPortalBuffData.Keys.OrderBy(_ => Guid.NewGuid()).Take(3).ToList();
public override GridFightPendingAction ToProto()
{
return new GridFightPendingAction
{
PortalBuffAction = new GridFightPortalBuffActionInfo
{
GridFightPortalBuffList = { PortalBuffList },
MaxRerollCount = MaxRerollCount,
CurRollCount = CurRerollCount
},
QueuePosition = QueuePosition
};
}
}

View File

@@ -0,0 +1,15 @@
using EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
public class GridFightPendingActionSyncData(GridFightSrc src, BaseGridFightPendingAction action) : BaseGridFightSyncData(src)
{
public override GridFightSyncData ToProto()
{
return new GridFightSyncData
{
PendingAction = action.ToProto()
};
}
}

View File

@@ -0,0 +1,20 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.GridFight;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.GridFight;
[Opcode(CmdIds.GridFightHandlePendingActionCsReq)]
public class HandlerGridFightHandlePendingActionCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var req = GridFightHandlePendingActionCsReq.Parser.ParseFrom(data);
var inst = connection.Player!.GridFightManager!.GridFightInstance;
if (inst != null)
await inst.HandleResultRequest(req);
await connection.SendPacket(new PacketGridFightHandlePendingActionScRsp(req.QueuePosition));
}
}

View File

@@ -0,0 +1,17 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.GridFight;
public class PacketGridFightHandlePendingActionScRsp : BasePacket
{
public PacketGridFightHandlePendingActionScRsp(uint pos) : base(CmdIds.GridFightHandlePendingActionScRsp)
{
var proto = new GridFightHandlePendingActionScRsp
{
QueuePosition = pos
};
SetData(proto);
}
}