using RPG.GameCore.Excel; using RPG.Network.Proto; using RPG.Services.Gameserver.Game.Entity; using RPG.Services.Gameserver.Game.Maze; using RPG.Services.Gameserver.Game.Team; using RPG.Services.Gameserver.Modules.Attributes; using RPG.Services.Gameserver.Session; using System.Security.Cryptography; namespace RPG.Services.Gameserver.Modules; internal class BattleModule : BaseModule { public SceneBattleInfo? Battle { get; private set; } private uint _battleMonsterEntityId; private IEnumerable? _battleMonsterAssists; private readonly MazeManager _mazeManager; private readonly ExcelTables _excelTables; public BattleModule(ModuleManager moduleManager, MazeManager mazeManager, ExcelTables excelTables) : base(moduleManager) { _mazeManager = mazeManager; _excelTables = excelTables; } [OnCommand(CmdType.CmdPVEBattleResultCsReq)] public Task OnCmdPVEBattleResultCsReq(PlayerSession session, ReadOnlyMemory body) { PVEBattleResultCsReq req = PVEBattleResultCsReq.Parser.ParseFrom(body.Span); AdventureModule adventureModule = ModuleManager.Get(); switch (req.EndStatus) { case BattleEndStatus.BattleEndWin: adventureModule.OnBattleWin(_battleMonsterEntityId, _battleMonsterAssists!); break; case BattleEndStatus.BattleEndLose: adventureModule.OnBattleLost(); break; } Send(session, CmdType.CmdPVEBattleResultScRsp, new PVEBattleResultScRsp { Retcode = 0, StageId = req.StageId, EndStatus = req.EndStatus }); return Task.CompletedTask; } public void OnBeingHitByMonster(uint monsterEntityId, IEnumerable assists) { // TODO: debuffs StartBattle(monsterEntityId, assists); } public void OnSuccessfulAttack(uint monsterEntityId, IEnumerable assists) { // TODO: buffs StartBattle(monsterEntityId, assists); } private void StartBattle(uint monsterEntityId, IEnumerable assists) { _battleMonsterEntityId = monsterEntityId; _battleMonsterAssists = assists; List battleEvents = []; if (_mazeManager.EntityManager.GetEntityById(monsterEntityId) is NpcMonsterEntity monster) { battleEvents.Add(monster.EventId); } foreach (uint assistEntityId in assists) { if (_mazeManager.EntityManager.GetEntityById(assistEntityId) is NpcMonsterEntity assistMonster) { battleEvents.Add(assistMonster.EventId); } } Battle = CreateBattleWithEvents(battleEvents); } private SceneBattleInfo CreateBattleWithEvents(List battleEvents) { SceneBattleInfo battle = new() { LogicRandomSeed = (uint)RandomNumberGenerator.GetInt32(int.MaxValue), StageId = battleEvents[0] * 10, }; foreach (uint eventId in battleEvents) { StageRow stage = _excelTables.GetExcelRow(ExcelType.Stage, eventId * 10)!; foreach (StageMonsterWave stageWave in stage.MonsterList) { SceneMonsterWave wave = new(); // wtf mihoyo.. if (stageWave.Monster0 != 0) wave.MonsterIdList.Add(stageWave.Monster0); if (stageWave.Monster1 != 0) wave.MonsterIdList.Add(stageWave.Monster1); if (stageWave.Monster2 != 0) wave.MonsterIdList.Add(stageWave.Monster2); if (stageWave.Monster3 != 0) wave.MonsterIdList.Add(stageWave.Monster3); if (stageWave.Monster4 != 0) wave.MonsterIdList.Add(stageWave.Monster4); battle.MonsterWaveList.Add(wave); } } foreach (TeamMember? member in ModuleManager.Get().Team.Members) { if (member == null) continue; battle.BattleAvatarList.Add(new BattleAvatar { Id = member.AvatarId, Hp = member.Hp, Sp = member.Sp, Level = 8, Promotion = 0, Rank = 0, AvatarType = member.AvatarType, Index = (uint)battle.BattleAvatarList.Count }); } return battle; } }