feat: complete game flow

This commit is contained in:
Somebody
2025-11-09 12:11:08 +08:00
parent 4be76f5ff7
commit 4b0f689188
34 changed files with 2452 additions and 140 deletions

View File

@@ -3,6 +3,7 @@ using EggLink.DanhengServer.Enums.Mission;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Player;
using EggLink.DanhengServer.Internationalization;
using EggLink.DanhengServer.Proto;
using Google.Protobuf.WellKnownTypes;
namespace EggLink.DanhengServer.Command.Command.Cmd;
@@ -144,4 +145,32 @@ public class CommandUnlockAll : ICommand
await arg.SendMsg(I18NManager.Translate("Game.Command.UnlockAll.UnlockedAll",
I18NManager.Translate("Word.TypesOfChallenge")));
}
[CommandMethod("0 grid")]
public async ValueTask UnlockAllGrid(CommandArg arg)
{
if (arg.Target == null)
{
await arg.SendMsg(I18NManager.Translate("Game.Command.Notice.PlayerNotFound"));
return;
}
var player = arg.Target!.Player!;
List<int> gridList = [2100162, 2100163, 7300022, 7300038, 6071325];
List<int> allList = [.. gridList];
foreach (var id in allList)
{
// finish mission
await player.QuestManager!.AcceptQuest(id);
await player.QuestManager!.FinishQuest(id);
}
if (player.SceneInstance!.FloorId == 20322001)
await player.SceneInstance.UpdateFloorSavedValue("FSV_370GridFight", 1);
await arg.SendMsg(I18NManager.Translate("Game.Command.UnlockAll.UnlockedAll",
I18NManager.Translate("Word.TypesOfGridFight")));
}
}

View File

@@ -9,6 +9,7 @@ public class GridFightAugmentExcel : ExcelResource
{
public uint ID { get; set; }
public uint CategoryID { get; set; }
public List<string> AugmentSavedValueList { get; set; } = [];
[JsonConverter(typeof(StringEnumConverter))] public GridFightAugmentQualityEnum Quality { get; set; }
public override int GetId()

View File

@@ -0,0 +1,24 @@
using EggLink.DanhengServer.Enums.GridFight;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("GridFightAugmentMonster.json")]
public class GridFightAugmentMonsterExcel : ExcelResource
{
public uint DivisionLevel { get; set; }
public uint EnemyDiffLvAdd { get; set; }
[JsonConverter(typeof(StringEnumConverter))] public GridFightAugmentQualityEnum Quality { get; set; }
public override int GetId()
{
return (int)DivisionLevel;
}
public override void Loaded()
{
GameData.GridFightAugmentMonsterData.TryAdd(DivisionLevel, []);
GameData.GridFightAugmentMonsterData[DivisionLevel][Quality] = this;
}
}

View File

@@ -0,0 +1,20 @@
namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("GridFightDivisionStage.json")]
public class GridFightDivisionStageExcel : ExcelResource
{
public uint DivisionID { get; set; }
public uint EnemyDifficultyLevel { get; set; }
public uint ExpModify { get; set; }
public uint SeasonID { get; set; }
public override int GetId()
{
return (int)DivisionID;
}
public override void Loaded()
{
GameData.GridFightDivisionStageData.TryAdd(DivisionID, this);
}
}

View File

@@ -0,0 +1,20 @@
namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("GridFightNodeTemplate.json")]
public class GridFightNodeTemplateExcel : ExcelResource
{
public uint NodeTemplateID { get; set; }
public uint PenaltyBonusRuleID { get; set; }
public uint IsAugment { get; set; }
public uint BasicGoldRewardNum { get; set; }
public override int GetId()
{
return (int)NodeTemplateID;
}
public override void Loaded()
{
GameData.GridFightNodeTemplateData.TryAdd(NodeTemplateID, this);
}
}

View File

@@ -14,6 +14,7 @@ public class GridFightStageRouteExcel : ExcelResource
public uint IsAugment { get; set; }
public uint NodeTemplateID { get; set; }
public uint BasicGoldRewardNum { get; set; }
public List<uint> PenaltyBonusRuleIDList { get; set; } = [];
[JsonConverter(typeof(StringEnumConverter))]
public GridFightNodeTypeEnum NodeType { get; set; }

View File

@@ -7,8 +7,8 @@ namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("RogueBuffGroup.json")]
public class RogueBuffGroupExcel : BaseRogueBuffGroupExcel
{
[JsonProperty("GroupID")] public int GroupID { get; set; }
[JsonProperty("BuffTagList")] public List<int> BuffTagList { get; set; } = [];
[JsonProperty("IDLBMIHBAPB")] public int GroupID { get; set; }
[JsonProperty("GNGDPDOMDFH")] public List<int> BuffTagList { get; set; } = [];
public override int GetId()
{

View File

@@ -1,14 +1,15 @@
using System.Collections.Concurrent;
using EggLink.DanhengServer.Data.Config;
using EggLink.DanhengServer.Data.Config;
using EggLink.DanhengServer.Data.Config.AdventureAbility;
using EggLink.DanhengServer.Data.Config.Character;
using EggLink.DanhengServer.Data.Config.Scene;
using EggLink.DanhengServer.Data.Custom;
using EggLink.DanhengServer.Data.Excel;
using EggLink.DanhengServer.Enums.GridFight;
using EggLink.DanhengServer.Enums.Rogue;
using EggLink.DanhengServer.Enums.TournRogue;
using EggLink.DanhengServer.Util;
using Newtonsoft.Json;
using System.Collections.Concurrent;
namespace EggLink.DanhengServer.Data;
@@ -107,6 +108,7 @@ public static class GameData
public static Dictionary<uint, GridFightRoleBasicInfoExcel> GridFightRoleBasicInfoData { get; private set; } = [];
public static Dictionary<uint, GridFightRoleStarExcel> GridFightRoleStarData { get; private set; } = [];
public static Dictionary<uint, GridFightDivisionInfoExcel> GridFightDivisionInfoData { get; private set; } = [];
public static Dictionary<uint, GridFightDivisionStageExcel> GridFightDivisionStageData { get; private set; } = [];
public static Dictionary<uint, GridFightEquipmentExcel> GridFightEquipmentData { get; private set; } = [];
public static Dictionary<uint, GridFightConsumablesExcel> GridFightConsumablesData { get; private set; } = [];
public static Dictionary<uint, GridFightCampExcel> GridFightCampData { get; private set; } = [];
@@ -114,11 +116,13 @@ public static class GameData
public static Dictionary<uint, GridFightPlayerLevelExcel> GridFightPlayerLevelData { get; private set; } = [];
public static Dictionary<uint, GridFightMonsterExcel> GridFightMonsterData { get; private set; } = [];
public static Dictionary<uint, GridFightAugmentExcel> GridFightAugmentData { get; private set; } = [];
public static Dictionary<uint, Dictionary<GridFightAugmentQualityEnum, GridFightAugmentMonsterExcel>> GridFightAugmentMonsterData { get; private set; } = [];
public static Dictionary<uint, GridFightPortalBuffExcel> GridFightPortalBuffData { get; private set; } = [];
public static Dictionary<uint, GridFightItemsExcel> GridFightItemsData { get; private set; } = [];
public static Dictionary<uint, GridFightTalentExcel> GridFightTalentData { get; private set; } = [];
public static Dictionary<uint, GridFightSeasonTalentExcel> GridFightSeasonTalentData { get; private set; } = [];
public static Dictionary<uint, Dictionary<uint, GridFightStageRouteExcel>> GridFightStageRouteData { get; private set; } = [];
public static Dictionary<uint, GridFightNodeTemplateExcel> GridFightNodeTemplateData { get; private set; } = [];
#endregion

View File

@@ -2,7 +2,7 @@
public static class GameConstants
{
public const string GAME_VERSION = "3.6.51";
public const string GAME_VERSION = "3.7.0";
public const string AvatarDbVersion = "20250430";
public const int GameVersionInt = 3200;
public const int MAX_STAMINA = 300;

View File

@@ -15,14 +15,16 @@ public class BattleGridFightOptions(GridFightGameSectionInfo curSection, GridFig
public GridFightGameEncounterInfo Encounter { get; set; } = curSection.Encounters.RandomElement();
public GridFightInstance Inst { get; set; } = inst;
public GridFightRoleComponent AvatarComponent { get; set; } = inst.GetComponent<GridFightRoleComponent>();
public GridFightLevelComponent LevelComponent { get; set; } = inst.GetComponent<GridFightLevelComponent>();
public GridFightBasicComponent BasicComponent { get; set; } = inst.GetComponent<GridFightBasicComponent>();
public GridFightAugmentComponent AugmentComponent { get; set; } = inst.GetComponent<GridFightAugmentComponent>();
public GridFightGameSectionInfo CurSection { get; set; } = curSection;
public PlayerInstance Player { get; set; } = player;
public void HandleProto(SceneBattleInfo proto, BattleInstance battle)
{
var avatars = AvatarComponent.GetForegroundAvatarInfos(4 + BasicComponent.GetFieldCount());
var backAvatars = AvatarComponent.GetBackgroundAvatarInfos(4 + BasicComponent.GetFieldCount());
var avatars = AvatarComponent.GetForegroundAvatarInfos(0);
var backAvatars = AvatarComponent.GetBackgroundAvatarInfos(BasicComponent.GetFieldCount());
var tempLineup = new LineupInfo
{
@@ -34,12 +36,13 @@ public class BattleGridFightOptions(GridFightGameSectionInfo curSection, GridFig
var formatted = avatars.Select(x =>
x.ToBattleProto(
new PlayerDataCollection(Player.Data, Player.InventoryManager!.Data, tempLineup), AvatarType.AvatarGridFightType)).ToList();
new PlayerDataCollection(Player.Data, Player.InventoryManager!.Data, tempLineup),
x is SpecialAvatarInfo ? AvatarType.AvatarTrialType : AvatarType.AvatarGridFightType)).ToList();
var backFormatted = backAvatars.Select(x =>
x.ToBattleProto(
new PlayerDataCollection(Player.Data, Player.InventoryManager!.Data, tempLineup),
AvatarType.AvatarGridFightType)).ToList();
x is SpecialAvatarInfo ? AvatarType.AvatarTrialType : AvatarType.AvatarGridFightType)).ToList();
proto.BattleAvatarList.Add(formatted.Take(4));
@@ -51,13 +54,20 @@ public class BattleGridFightOptions(GridFightGameSectionInfo curSection, GridFig
BattleWaveId = wave.Wave,
MonsterParam = new SceneMonsterWaveParam
{
Level = 89
Level = 90
},
MonsterList =
{
wave.Monsters.Select(x => new SceneMonster
{
MonsterId = x.MonsterID
MonsterId = x.MonsterID,
ExtraInfo = new SceneMonsterExtraInfo
{
BattleGridFightInfo = new SceneMonsterGridFightInfo
{
Tier = Math.Max(1, x.MonsterTier)
}
}
})
}
});
@@ -69,21 +79,21 @@ public class BattleGridFightOptions(GridFightGameSectionInfo curSection, GridFig
battle.BattleEvents.TryAdd((int)roleConf.BEID, new BattleEventInstance((int)roleConf.BEID, 5000));
}
battle.Buffs.Add(new MazeBuff(35100001, 1, -1)
var ruleId = CurSection.Excel.PenaltyBonusRuleIDList.FirstOrDefault(0u);
if (ruleId == 0)
{
WaveFlag = -1
});
if (GameData.GridFightNodeTemplateData.TryGetValue(CurSection.Excel.NodeTemplateID, out var node)) ruleId = node.PenaltyBonusRuleID;
}
proto.BattleGridFightInfo = new BattleGridFightInfo
{
GridGameAvatarList =
{
AvatarComponent.Data.Roles.Where(x => x.Pos <= 4 + BasicComponent.GetFieldCount()).Select(x => x.ToBattleInfo())
AvatarComponent.Data.Roles.Where(x => x.Pos <= BasicComponent.GetFieldCount()).OrderBy(x => x.Pos).Select(x => x.ToBattleInfo())
},
BattleWaveId = 1,
GridFightCurLevel = BasicComponent.Data.CurLevel,
GridFightLineupHp = BasicComponent.Data.CurHp,
GridFightAvatarList = { formatted, backFormatted },
GridFightAvatarList = { backFormatted },
GridFightStageInfo = new BattleGridFightStageInfo
{
ChapterId = CurSection.ChapterId,
@@ -92,7 +102,11 @@ public class BattleGridFightOptions(GridFightGameSectionInfo curSection, GridFig
},
IsOverlock = Inst.IsOverLock,
Season = Inst.Season,
DFNBKALPGPH = 1,
BattleDifficulty = AugmentComponent.GetAugmentDifficulty() + Inst.GetDivisionDifficulty() + Encounter.EncounterDifficulty - 1,
GameDivisionId = Inst.DivisionId,
PenaltyBonusRuleId = ruleId,
GridFightAugmentInfo = { AugmentComponent.Data.Augments.Select(x => x.ToBattleInfo()) },
GridFightPortalBuffList = { LevelComponent.PortalBuffs.Select(x => x.ToBattleInfo()) },
};
}
}

View File

@@ -0,0 +1,87 @@
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.Proto.ServerSide;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.Component;
public class GridFightAugmentComponent(GridFightInstance inst) : BaseGridFightComponent(inst)
{
public GridFightAugmentInfoPb Data { get; set; } = new();
public async ValueTask<List<BaseGridFightSyncData>> AddAugment(uint augmentId, bool sendPacket = true, GridFightSrc src = GridFightSrc.KGridFightSrcSelectAugment, uint syncGroup = 0)
{
if (!GameData.GridFightAugmentData.TryGetValue(augmentId, out var excel)) return [];
var info = new GridFightGameAugmentPb
{
AugmentId = augmentId
};
foreach (var saved in excel.AugmentSavedValueList)
{
info.SavedValues.Add(saved, 0);
}
Data.Augments.Add(info);
var syncData = new GridFightAddAugmentSyncData(src, info, syncGroup);
if (sendPacket)
{
await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(syncData));
}
return [syncData];
}
public uint GetAugmentDifficulty()
{
if (!GameData.GridFightDivisionInfoData.TryGetValue(Inst.DivisionId, out var excel)) return 0;
var difficulty = 0u;
foreach (var augment in Data.Augments)
{
if (!GameData.GridFightAugmentData.TryGetValue(augment.AugmentId, out var augmentExcel)) continue;
var diff = GameData.GridFightAugmentMonsterData.GetValueOrDefault(excel.DivisionLevel, [])
.GetValueOrDefault(augmentExcel.Quality)?.EnemyDiffLvAdd ?? 0;
difficulty += diff;
}
return difficulty;
}
public override GridFightGameInfo ToProto()
{
return new GridFightGameInfo
{
GridAugmentInfo = new GridFightGameAugmentInfo
{
GridFightAugmentInfo = { Data.Augments.Select(x => x.ToProto()) }
}
};
}
}
public static class GridFightAugmentExtensions
{
public static GridGameAugmentInfo ToProto(this GridFightGameAugmentPb info)
{
return new GridGameAugmentInfo
{
AugmentId = info.AugmentId,
GameSavedValueMap = { info.SavedValues }
};
}
public static BattleGridFightAugmentInfo ToBattleInfo(this GridFightGameAugmentPb info)
{
return new BattleGridFightAugmentInfo
{
AugmentId = info.AugmentId,
GameSavedValueMap = { info.SavedValues }
};
}
}

View File

@@ -1,5 +1,4 @@
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;
@@ -17,9 +16,9 @@ public class GridFightBasicComponent(GridFightInstance inst) : BaseGridFightComp
{
CurHp = 100,
CurLevel = 1,
CurOnGroundAvatarCount = 1,
MaxAvatarNum = 1,
BuyLevelCost = 1,
CurGold = 5
CurGold = 0
};
#endregion
@@ -64,7 +63,7 @@ public class GridFightBasicComponent(GridFightInstance inst) : BaseGridFightComp
if (await UpdateGoldNum((int)-Data.BuyLevelCost, false) != Retcode.RetSucc)
return Retcode.RetGridFightCoinNotEnough;
return await AddLevelExp(1, sendPacket);
return await AddLevelExp(4, sendPacket);
}
public async ValueTask<Retcode> AddLevelExp(uint exp, bool sendPacket = true)
@@ -86,6 +85,8 @@ public class GridFightBasicComponent(GridFightInstance inst) : BaseGridFightComp
if (level.LevelUpExp + costExp > Data.LevelExp)
break;
if (level.LevelUpExp == 0) continue; // max level
costExp += (int)level.LevelUpExp;
targetLevel = level.PlayerLevel + 1;
}
@@ -124,7 +125,7 @@ public class GridFightBasicComponent(GridFightInstance inst) : BaseGridFightComp
Data.CurLevel += level;
Data.BuyLevelCost = (uint)Math.Ceiling(Data.CurLevel / 2f);
Data.CurOnGroundAvatarCount = levelConf.AvatarMaxNumber;
Data.MaxAvatarNum = levelConf.AvatarMaxNumber;
if (sendPacket)
{
@@ -160,9 +161,9 @@ public class GridFightBasicComponent(GridFightInstance inst) : BaseGridFightComp
GridFightCurLevel = Data.CurLevel,
GridFightCurLevelExp = Data.LevelExp,
GridFightLevelCost = Data.BuyLevelCost,
GridFightMaxAvatarCount = Data.CurOnGroundAvatarCount,
GridFightMaxAvatarCount = 9,
GridFightOffFieldMaxCount = 6,
GridFightMaxFieldCount = 8,
GridFightMaxFieldCount = Data.MaxAvatarNum,
GridFightLineupHp = Data.CurHp,
GridFightCurGold = Data.CurGold,
GridFightMaxGold = 2000,
@@ -171,8 +172,10 @@ public class GridFightBasicComponent(GridFightInstance inst) : BaseGridFightComp
{
IJDIAOMINLB = new BHJALAPDBLH()
},
CALCJMHAKPF = new OLEIDBLBILD
GameLockInfo = new GridFightLockInfo
{
LockReason = (GridFightLockReason)Data.LockReason,
LockType = (GridFightLockType)Data.LockType
}
}
};

View File

@@ -18,6 +18,7 @@ public class GridFightLevelComponent : BaseGridFightComponent
public Dictionary<uint, List<GridFightGameSectionInfo>> Sections { get; } = [];
public GridFightGameSectionInfo CurrentSection => Sections[_curChapterId][(int)(_curSectionId - 1)];
public List<GridFightRoleDamageSttInfo> RoleDamageSttInfos { get; } = [];
public List<GridFightPortalBuffInfo> PortalBuffs { get; } = [];
#endregion
@@ -125,13 +126,23 @@ public class GridFightLevelComponent : BaseGridFightComponent
if (CurrentSection.Excel.IsAugment == 1)
{
// create augment action
syncs.Add(await Inst.CreatePendingAction<GridFightAugmentPendingAction>(sendPacket: false));
syncs.AddRange(await Inst.CreatePendingAction<GridFightAugmentPendingAction>(sendPacket: false));
}
if (CurrentSection.Excel.NodeType == GridFightNodeTypeEnum.Supply)
{
// create supply action
syncs.Add(await Inst.CreatePendingAction<GridFightSupplyPendingAction>(sendPacket: false));
syncs.AddRange(await Inst.CreatePendingAction<GridFightSupplyPendingAction>(sendPacket: false));
}
else
{
syncs.AddRange(await Inst.CreatePendingAction<GridFightElitePendingAction>(sendPacket: false));
if (CurrentSection.Excel.NodeType is not GridFightNodeTypeEnum.Boss
and not GridFightNodeTypeEnum.EliteBranch)
{
syncs.AddRange(await Inst.CreatePendingAction<GridFightPreparePendingAction>(sendPacket: false));
}
}
if (sendPacket)
@@ -142,6 +153,24 @@ public class GridFightLevelComponent : BaseGridFightComponent
return syncs;
}
public async ValueTask<List<BaseGridFightSyncData>> AddPortalBuff(uint portalBuffId, bool sendPacket = true, GridFightSrc src = GridFightSrc.KGridFightSrcSelectPortalBuff)
{
var info = new GridFightPortalBuffInfo
{
PortalBuffId = portalBuffId
};
PortalBuffs.Add(info);
var syncData = new GridFightAddPortalBuffSyncData(src, info);
if (sendPacket)
{
await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(syncData));
}
return [syncData];
}
#endregion
#region Information
@@ -209,7 +238,8 @@ public class GridFightLevelComponent : BaseGridFightComponent
LevelSttInfo = new GridFightLevelSttInfo
{
GridFightDamageSttInfo = ToDamageSttInfo()
}
},
GridFightPortalBuffList = { PortalBuffs.Select(x => x.ToProto()) }
}
};
}
@@ -246,6 +276,39 @@ public class GridFightRoleDamageSttInfo
}
}
public class GridFightPortalBuffInfo
{
public uint PortalBuffId { get; set; }
public Dictionary<string, uint> SavedValue { get; set; } = [];
public GridFightGamePortalBuffInfo ToProto()
{
return new GridFightGamePortalBuffInfo
{
PortalBuffId = PortalBuffId,
GameSavedValueMap = { SavedValue }
};
}
public BattleGridFightPortalBuffInfo ToBattleInfo()
{
return new BattleGridFightPortalBuffInfo
{
PortalBuffId = PortalBuffId,
GameSavedValueMap = { SavedValue }
};
}
public GridFightPortalBuffSyncInfo ToSyncInfo()
{
return new GridFightPortalBuffSyncInfo
{
PortalBuffId = PortalBuffId,
GameSavedValueMap = { SavedValue }
};
}
}
public class GridFightGameSectionInfo
{
public GridFightStageRouteExcel Excel { get; }
@@ -263,7 +326,7 @@ public class GridFightGameSectionInfo
MonsterCamp = camp;
if (Excel.NodeType is not GridFightNodeTypeEnum.Monster and not GridFightNodeTypeEnum.CampMonster
and not GridFightNodeTypeEnum.Boss and not GridFightNodeTypeEnum.EliteBranch || Excel.IsAugment == 1) return;
and not GridFightNodeTypeEnum.Boss and not GridFightNodeTypeEnum.EliteBranch) return;
Encounters.Add(new GridFightGameEncounterInfo(1, 1, this));
}
@@ -324,13 +387,13 @@ public class GridFightGameEncounterInfo
}
else
{
var elite = ParentSection.Excel.NodeType switch
List<GridFightMonsterExcel> elites = ParentSection.Excel.NodeType switch
{
GridFightNodeTypeEnum.Boss => monster5Pool.RandomElement(),
_ => monster4Pool.RandomElement(),
GridFightNodeTypeEnum.Boss => [..monster5Pool],
_ => [monster4Pool.RandomElement()],
};
List<GridFightMonsterExcel> monsters = [elite];
List<GridFightMonsterExcel> monsters = [..elites];
var remain = monsterNum[i] - 1;
if (remain > 0)

View File

@@ -9,21 +9,37 @@ namespace EggLink.DanhengServer.GameServer.Game.GridFight.Component;
public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightComponent(inst)
{
public const uint PrepareAreaPos = 13;
public GridFightAvatarInfoPb Data { get; set; } = new();
public async ValueTask<List<BaseGridFightSyncData>> AddAvatar(uint roleId, uint tier = 1, bool sendPacket = true,
bool checkMerge = true, GridFightSrc src = GridFightSrc.KGridFightSrcBuyGoods)
public bool HasAnyEmptyPos()
{
var pos = 1u;
return Data.Roles.Where(x => x.Pos > PrepareAreaPos).ToList().Count < 9;
}
public async ValueTask<List<BaseGridFightSyncData>> AddAvatar(uint roleId, uint tier = 1, bool sendPacket = true,
bool checkMerge = true, GridFightSrc src = GridFightSrc.KGridFightSrcBuyGoods, uint syncGroup = 0, uint targetPos = 0)
{
if (!GameData.GridFightRoleBasicInfoData.TryGetValue(roleId, out var excel)) return [];
var pos = 0u;
var initialPos = targetPos > 0 ? targetPos : PrepareAreaPos + 1;
// get first empty pos
var usedPos = Data.Roles.Select(x => x.Pos).ToHashSet();
for (var i = 1u; i <= 20u; i++)
for (var i = initialPos; i <= PrepareAreaPos + 9; i++)
{
if (usedPos.Contains(i)) continue;
pos = i;
break;
}
// check if any empty
if (pos == 0)
{
return [];
}
var info = new GridFightRoleInfoPb
{
RoleId = roleId,
@@ -32,9 +48,14 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo
Pos = pos
};
foreach (var saved in excel.RoleSavedValueList)
{
info.SavedValues.Add(saved, 0);
}
Data.Roles.Add(info);
List<BaseGridFightSyncData> syncs = [new GridFightRoleAddSyncData(src, info)];
List<BaseGridFightSyncData> syncs = [new GridFightRoleAddSyncData(src, info, syncGroup)];
if (checkMerge)
{
@@ -54,6 +75,7 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo
{
List<BaseGridFightSyncData> syncs = [];
bool hasMerged;
uint groupId = 0;
do
{
@@ -83,13 +105,14 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo
foreach (var role in toMerge)
{
Data.Roles.Remove(role);
syncs.Add(new GridFightRoleRemoveSyncData(GridFightSrc.KGridFightSrcMergeRole, role));
syncs.Add(new GridFightRoleRemoveSyncData(GridFightSrc.KGridFightSrcMergeRole, role, groupId));
}
// add new merged role with tier + 1
var addSyncs = await AddAvatar(roleId, currentTier + 1, false, false, GridFightSrc.KGridFightSrcMergeRole);
var addSyncs = await AddAvatar(roleId, currentTier + 1, false, false, GridFightSrc.KGridFightSrcMergeRole, groupId, toMerge.First().Pos);
syncs.AddRange(addSyncs);
groupId++;
hasMerged = true;
}
} while (hasMerged); // continue until no more merges are possible
@@ -189,8 +212,17 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo
return res;
}
public async ValueTask UpdatePos(List<GridFightPosInfo> posList)
public async ValueTask<Retcode> UpdatePos(List<GridFightPosInfo> posList)
{
foreach (var pos in posList.Where(x => x.Pos <= PrepareAreaPos))
{
var role = Data.Roles.FirstOrDefault(x => x.UniqueId == pos.UniqueId);
if (role == null) continue;
if (Data.Roles.Where(x => x.UniqueId != pos.UniqueId && x.Pos <= PrepareAreaPos).Any(x => x.RoleId == role.RoleId))
return Retcode.RetGridFightSameRoleInBattle;
}
List<BaseGridFightSyncData> syncs = [];
foreach (var pos in posList)
{
@@ -206,6 +238,8 @@ public class GridFightRoleComponent(GridFightInstance inst) : BaseGridFightCompo
{
await Inst.Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(syncs));
}
return Retcode.RetSucc;
}
public override GridFightGameInfo ToProto()
@@ -229,7 +263,9 @@ public static class GridFightRoleInfoPbExtensions
Id = info.RoleId,
UniqueId = info.UniqueId,
Tier = info.Tier,
Pos = info.Pos
Pos = info.Pos,
GameSavedValueMap = { info.SavedValues },
EquipUniqueIdList = { info.EquipmentIds }
};
}
@@ -241,7 +277,9 @@ public static class GridFightRoleInfoPbExtensions
UniqueId = info.UniqueId,
Tier = info.Tier,
Pos = info.Pos,
AvatarId = GameData.GridFightRoleBasicInfoData[info.RoleId].AvatarID
AvatarId = GameData.GridFightRoleBasicInfoData[info.RoleId].AvatarID,
RoleEquipmentList = { },
GameSavedValueMap = { info.SavedValues }
};
}
}

View File

@@ -11,7 +11,7 @@ public class GridFightShopComponent(GridFightInstance inst) : BaseGridFightCompo
{
public GridFightShopInfoPb Data { get; set; } = new()
{
RefreshCost = 3,
RefreshCost = 2,
FreeRefreshCount = 1
};
@@ -34,6 +34,11 @@ public class GridFightShopComponent(GridFightInstance inst) : BaseGridFightCompo
public async ValueTask<Retcode> BuyGoods(List<uint> indexes, bool sendPacket = true)
{
var avatarComp = Inst.GetComponent<GridFightRoleComponent>();
// check pos
if (!avatarComp.HasAnyEmptyPos()) return Retcode.RetGridFightNoEmptyPos;
var curLevel = Inst.GetComponent<GridFightBasicComponent>().Data.CurLevel;
var targetGoods = indexes
@@ -52,7 +57,6 @@ public class GridFightShopComponent(GridFightInstance inst) : BaseGridFightCompo
// GIVE ITEMS
List<BaseGridFightSyncData> syncs = [];
var avatarComp = Inst.GetComponent<GridFightRoleComponent>();
foreach (var item in targetGoods)
{
if (item.ItemTypeCase == GridFightShopItemPb.ItemTypeOneofCase.RoleItem)
@@ -68,10 +72,7 @@ public class GridFightShopComponent(GridFightInstance inst) : BaseGridFightCompo
// REMOVE ITEMS FROM SHOP
foreach (var index in indexes)
{
Data.ShopItems.RemoveAt((int)index);
// add new item
AddGoods(1, curLevel);
Data.ShopItems[(int)index].SoldOut = true;
}
if (sendPacket)
@@ -141,12 +142,12 @@ public class GridFightShopComponent(GridFightInstance inst) : BaseGridFightCompo
return code;
}
Data.RefreshCost += 2;
Data.RefreshCost = 2;
}
}
else
{
Data.RefreshCost = 3;
Data.RefreshCost = 2;
Data.FreeRefreshCount++;
if (Data.ShopLocked)
{
@@ -201,7 +202,10 @@ public static class GridFightShopInfoPbExtensions
{
public static GridFightShopGoodsInfo ToProto(this GridFightShopItemPb info)
{
var proto = new GridFightShopGoodsInfo();
var proto = new GridFightShopGoodsInfo
{
IsSoldOut = info.SoldOut
};
if (info.ItemTypeCase == GridFightShopItemPb.ItemTypeOneofCase.RoleItem)
{

View File

@@ -1,3 +1,4 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.GameServer.Game.Battle;
using EggLink.DanhengServer.GameServer.Game.GridFight.Component;
using EggLink.DanhengServer.GameServer.Game.GridFight.PendingAction;
@@ -91,11 +92,13 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
Components.Add(new GridFightShopComponent(this));
Components.Add(new GridFightLevelComponent(this));
Components.Add(new GridFightRoleComponent(this));
Components.Add(new GridFightAugmentComponent(this));
_ = GetComponent<GridFightRoleComponent>().AddAvatar(1414, 3, false);
_ = GetComponent<GridFightShopComponent>().RefreshShop(true, false);
_ = CreatePendingAction<GridFightPortalBuffPendingAction>(); // TODO wait for release official server
_ = CreatePendingAction<GridFightPortalBuffPendingAction>(sendPacket:false);
_ = CreatePendingAction<GridFightElitePendingAction>(sendPacket: false);
}
public T GetComponent<T>() where T : BaseGridFightComponent
@@ -103,6 +106,13 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
return (T)Components.First(c => c is T);
}
public uint GetDivisionDifficulty()
{
return GameData.GridFightDivisionStageData.TryGetValue(DivisionId, out var excel)
? excel.EnemyDifficultyLevel
: 0;
}
public GridFightCurrentInfo ToProto()
{
return new GridFightCurrentInfo
@@ -124,7 +134,14 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
public GridFightGameData ToGameDataInfo()
{
return new GridFightGameData();
return new GridFightGameData
{
GameItemInfoList = { new GridFightGameItemInfo
{
UniqueId = 18,
JCDHFKOCDOL = new()
} }
};
}
#region Pending Action
@@ -152,47 +169,63 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
return pos;
}
public async ValueTask<BaseGridFightSyncData> CreatePendingAction<T>(GridFightSrc src = GridFightSrc.KGridFightSrcEnterNode, bool sendPacket = true) where T: BaseGridFightPendingAction
public async ValueTask<List<BaseGridFightSyncData>> CreatePendingAction<T>(GridFightSrc src = GridFightSrc.KGridFightSrcEnterNode, bool sendPacket = true) where T: BaseGridFightPendingAction
{
var action = (T)Activator.CreateInstance(typeof(T), this)!;
var basicComp = GetComponent<GridFightBasicComponent>();
AddPendingAction(action);
basicComp.Data.LockReason = (uint)GridFightLockReason.KGridFightLockReasonPendingAction;
basicComp.Data.LockType = (uint)GridFightLockType.KGridFightLockTypeAll;
var res = new GridFightPendingActionSyncData(src, action);
if (sendPacket)
await Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(res));
return res;
return [res, new GridFightLockInfoSyncData(src, basicComp.Data.Clone())];
}
public async ValueTask HandleResultRequest(GridFightHandlePendingActionCsReq req)
{
var basicComp = GetComponent<GridFightBasicComponent>();
var curAction = GetCurAction();
// end
PendingActions.Remove(curAction.QueuePosition);
var src = GridFightSrc.KGridFightSrcNone;
var isFinish = true;
GridFightSrc src;
List<BaseGridFightSyncData> syncs = [];
switch (req.GridFightActionTypeCase)
{
case GridFightHandlePendingActionCsReq.GridFightActionTypeOneofCase.PortalBuffAction:
src = GridFightSrc.KGridFightSrcSelectPortalBuff;
syncs.AddRange(await GetComponent<GridFightLevelComponent>().AddPortalBuff(req.PortalBuffAction.SelectPortalBuffId, false, src));
// initial supply
await basicComp.UpdateGoldNum(5, false, GridFightSrc.KGridFightSrcInitialSupplySelect);
syncs.Add(new GridFightGoldSyncData(GridFightSrc.KGridFightSrcInitialSupplySelect, basicComp.Data));
break;
case GridFightHandlePendingActionCsReq.GridFightActionTypeOneofCase.PortalBuffRerollAction:
if (curAction is GridFightPortalBuffPendingAction portalBuffAction)
{
isFinish = false;
await portalBuffAction.RerollBuff();
}
break;
case GridFightHandlePendingActionCsReq.GridFightActionTypeOneofCase.AugmentAction:
src = GridFightSrc.KGridFightSrcSelectAugment;
await CheckCurNodeFinish(src);
syncs.AddRange(await GetComponent<GridFightAugmentComponent>().AddAugment(req.AugmentAction.AugmentId, false, src));
break;
case GridFightHandlePendingActionCsReq.GridFightActionTypeOneofCase.RerollAugmentAction:
if (curAction is GridFightAugmentPendingAction augmentAction)
{
isFinish = false;
await augmentAction.RerollAugment(req.RerollAugmentAction.AugmentId);
}
@@ -205,9 +238,31 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
break;
}
if (isFinish)
{
PendingActions.Remove(curAction.QueuePosition);
syncs.Add(new GridFightFinishPendingActionSyncData(GridFightSrc.KGridFightSrcNone, curAction.QueuePosition));
await Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(
new GridFightPendingActionSyncData(src, GetCurAction())));
// unlock
basicComp.Data.LockReason = (uint)GridFightLockReason.KGridFightLockReasonUnknown;
basicComp.Data.LockType = (uint)GridFightLockType.KGridFightLockTypeNone;
syncs.Add(new GridFightLockInfoSyncData(GridFightSrc.KGridFightSrcNone, basicComp.Data.Clone()));
// sync level
syncs.Add(new GridFightLevelSyncData(GridFightSrc.KGridFightSrcNone, GetComponent<GridFightLevelComponent>()));
}
if (PendingActions.Count > 0)
{
basicComp.Data.LockReason = (uint)GridFightLockReason.KGridFightLockReasonPendingAction;
basicComp.Data.LockType = (uint)GridFightLockType.KGridFightLockTypeAll;
syncs.Add(new GridFightPendingActionSyncData(GridFightSrc.KGridFightSrcNone, GetCurAction(), 1));
syncs.Add(new GridFightLockInfoSyncData(GridFightSrc.KGridFightSrcNone, basicComp.Data.Clone(), 1));
}
await Player.SendPacket(new PacketGridFightSyncUpdateResultScNotify(syncs));
}
public async ValueTask CheckCurNodeFinish(GridFightSrc src)
@@ -220,16 +275,7 @@ public class GridFightInstance(PlayerInstance player, uint season, uint division
if (PendingActions.Count != 0) return;
// next
await levelComp.EnterNextSection(src:src);
}
#endregion
#region Portal Buff
public async ValueTask AddPortalBuff(uint portalBuffId)
{
await levelComp.EnterNextSection(src:GridFightSrc.KGridFightSrcNone);
}
#endregion

View File

@@ -8,7 +8,8 @@ public class GridFightEliteBranchPendingAction(GridFightInstance inst) : BaseGri
{
return new GridFightPendingAction
{
EliteBranchAction = new GridFightEliteBranchActionInfo()
EliteBranchAction = new GridFightEliteBranchActionInfo(),
QueuePosition = QueuePosition
};
}
}

View File

@@ -8,7 +8,8 @@ public class GridFightElitePendingAction(GridFightInstance inst) : BaseGridFight
{
return new GridFightPendingAction
{
EliteAction = new GridFightEliteActionInfo()
EliteAction = new GridFightEliteActionInfo(),
QueuePosition = QueuePosition
};
}
}

View File

@@ -6,6 +6,9 @@ public class GridFightEmptyPendingAction(GridFightInstance inst) : BaseGridFight
{
public override GridFightPendingAction ToProto()
{
return new GridFightPendingAction();
return new GridFightPendingAction
{
QueuePosition = QueuePosition
};
}
}

View File

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

View File

@@ -47,7 +47,7 @@ public class GridFightSupplyPendingAction : BaseGridFightPendingAction
{
MaxRerollCount = MaxRerollNum,
CurRollCount = CurRerollNum,
MEKEFPNMNLE = 3,
MaxSelectCount = 1,
JLHIKCHIEDJ = 2,
SupplyRoleInfoList = { RoleList.Select(x => x.ToProto()) }
}

View File

@@ -2,8 +2,9 @@ using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
public abstract class BaseGridFightSyncData(GridFightSrc src)
public abstract class BaseGridFightSyncData(GridFightSrc src, uint groupId = 0)
{
public GridFightSrc Src { get; set; } = src;
public uint GroupId { get; set; } = groupId;
public abstract GridFightSyncData ToProto();
}

View File

@@ -0,0 +1,19 @@
using EggLink.DanhengServer.GameServer.Game.GridFight.Component;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Proto.ServerSide;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
public class GridFightAddAugmentSyncData(GridFightSrc src, GridFightGameAugmentPb augment, uint groupId = 0) : BaseGridFightSyncData(src, groupId)
{
public override GridFightSyncData ToProto()
{
return new GridFightSyncData
{
AugmentSyncInfo = new GridFightAugmentSyncInfo
{
SyncAugmentInfo = augment.ToProto()
}
};
}
}

View File

@@ -0,0 +1,15 @@
using EggLink.DanhengServer.Proto;
using GridFightPortalBuffInfo = EggLink.DanhengServer.GameServer.Game.GridFight.Component.GridFightPortalBuffInfo;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
public class GridFightAddPortalBuffSyncData(GridFightSrc src, GridFightPortalBuffInfo info, uint groupId = 0) : BaseGridFightSyncData(src, groupId)
{
public override GridFightSyncData ToProto()
{
return new GridFightSyncData
{
PortalBuffSyncInfo = info.ToSyncInfo()
};
}
}

View File

@@ -8,6 +8,7 @@ public class GridFightFinishPendingActionSyncData(GridFightSrc src, uint queuePo
{
return new GridFightSyncData
{
FinishPendingActionPos = queuePosition
};
}
}

View File

@@ -0,0 +1,19 @@
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Proto.ServerSide;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
public class GridFightLockInfoSyncData(GridFightSrc src, GridFightBasicInfoPb info, uint groupId = 0) : BaseGridFightSyncData(src, groupId)
{
public override GridFightSyncData ToProto()
{
return new GridFightSyncData
{
SyncLockInfo = new GridFightLockInfo
{
LockType = (GridFightLockType)info.LockType,
LockReason = (GridFightLockReason)info.LockReason
}
};
}
}

View File

@@ -9,7 +9,7 @@ public class GridFightMaxAvatarNumSyncData(GridFightSrc src, GridFightBasicInfoP
{
return new GridFightSyncData
{
GridFightMaxAvatarCount = info.CurOnGroundAvatarCount
MaxBattleRoleNum = info.MaxAvatarNum
};
}
}

View File

@@ -3,7 +3,7 @@ using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
public class GridFightPendingActionSyncData(GridFightSrc src, BaseGridFightPendingAction action) : BaseGridFightSyncData(src)
public class GridFightPendingActionSyncData(GridFightSrc src, BaseGridFightPendingAction action, uint groupId = 0) : BaseGridFightSyncData(src, groupId)
{
public override GridFightSyncData ToProto()
{

View File

@@ -4,7 +4,7 @@ using EggLink.DanhengServer.Proto.ServerSide;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
public class GridFightRoleAddSyncData(GridFightSrc src, GridFightRoleInfoPb role) : BaseGridFightSyncData(src)
public class GridFightRoleAddSyncData(GridFightSrc src, GridFightRoleInfoPb role, uint groupId = 0) : BaseGridFightSyncData(src, groupId)
{
public override GridFightSyncData ToProto()
{

View File

@@ -3,7 +3,7 @@ using EggLink.DanhengServer.Proto.ServerSide;
namespace EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
public class GridFightRoleRemoveSyncData(GridFightSrc src, GridFightRoleInfoPb role) : BaseGridFightSyncData(src)
public class GridFightRoleRemoveSyncData(GridFightSrc src, GridFightRoleInfoPb role, uint groupId = 0) : BaseGridFightSyncData(src, groupId)
{
public override GridFightSyncData ToProto()
{

View File

@@ -20,9 +20,9 @@ public class HandlerGridFightUpdatePosCsReq : Handler
}
var gridFight = connection.Player.GridFightManager.GridFightInstance;
await gridFight.GetComponent<GridFightRoleComponent>().UpdatePos(req.GridFightPosInfoList.ToList());
var ret = await gridFight.GetComponent<GridFightRoleComponent>().UpdatePos(req.GridFightPosInfoList.ToList());
await connection.SendPacket(
new PacketGridFightUpdatePosScRsp(Retcode.RetSucc, req.GridFightPosInfoList));
new PacketGridFightUpdatePosScRsp(ret, req.GridFightPosInfoList));
}
}

View File

@@ -1,7 +1,6 @@
using EggLink.DanhengServer.GameServer.Game.GridFight.Sync;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
using System.Linq;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.GridFight;
@@ -9,23 +8,17 @@ public class PacketGridFightSyncUpdateResultScNotify : BasePacket
{
public PacketGridFightSyncUpdateResultScNotify(List<BaseGridFightSyncData> data) : base(CmdIds.GridFightSyncUpdateResultScNotify)
{
Dictionary<GridFightSrc, List<BaseGridFightSyncData>> srcDict = [];
foreach (var syncData in data)
{
srcDict.TryAdd(syncData.Src, []);
srcDict[syncData.Src].Add(syncData);
}
var group = data.GroupBy(x => new { x.GroupId, x.Src });
var proto = new GridFightSyncUpdateResultScNotify
{
SyncResultDataList =
{
srcDict.Select(x => new GridFightSyncResultData
group.Select(x => new GridFightSyncResultData
{
GridUpdateSrc = x.Key,
UpdateDynamicList = { x.Value.Select(j => j.ToProto()) },
ONMDGNHMABO = { (uint)x.Value.Count }
GridUpdateSrc = x.Key.Src,
UpdateDynamicList = { x.Select(j => j.ToProto()) },
ONMDGNHMABO = { 0 }
})
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -12,6 +12,7 @@ message GridFightShopItemPb {
GridFightShopRoleItemPb RoleItem = 1;
}
uint32 Rarity = 2;
bool SoldOut = 3;
}
message GridFightShopInfoPb {
@@ -35,8 +36,10 @@ message GridFightBasicInfoPb {
uint32 LevelExp = 3;
uint32 BuyLevelCost = 4;
uint32 CurHp = 5;
uint32 CurOnGroundAvatarCount = 6;
uint32 MaxAvatarNum = 6;
uint32 ComboNum = 7;
uint32 LockType = 8;
uint32 LockReason = 9;
}
message GridFightRoleInfoPb {
@@ -44,6 +47,8 @@ message GridFightRoleInfoPb {
uint32 Tier = 2;
uint32 Pos = 3;
uint32 UniqueId = 4;
map<string, uint32> SavedValues = 5;
repeated uint32 EquipmentIds = 6;
}
message GridFightAvatarInfoPb {
@@ -51,10 +56,47 @@ message GridFightAvatarInfoPb {
uint32 CurUniqueId = 2;
}
message GridFightGameOrbPb {
uint32 OrbItemId = 1;
uint32 UniqueId = 2;
}
message GridFightOrbInfoPb {
repeated GridFightGameOrbPb Orbs = 1;
}
message GridFightGameAugmentPb {
uint32 AugmentId = 1;
map<string, uint32> SavedValues = 2;
}
message GridFightAugmentInfoPb {
repeated GridFightGameAugmentPb Augments = 1;
}
message GridFightGameTraitEffectPb {
uint32 TraitId = 1;
uint32 EffectId = 2;
uint32 Param = 3;
}
message GridFightGameTraitPb {
uint32 TraitId = 1;
repeated GridFightGameTraitEffectPb Effects = 2;
uint32 ExtraRoleNum = 3;
}
message GridFightTraitInfoPb {
repeated GridFightGameTraitPb Traits = 1;
}
message GridFightComponentPb {
oneof ComponentType {
GridFightShopInfoPb ShopInfo = 1;
GridFightBasicInfoPb BasicInfo = 2;
GridFightAvatarInfoPb AvatarInfo = 3;
GridFightOrbInfoPb OrbInfo = 4;
GridFightAugmentInfoPb AugmentInfo = 5;
GridFightTraitInfoPb TraitInfo = 6;
}
}