using System.Collections.Generic; using System.Linq; using ProtoCSStruct; using Sog; namespace Game { /// ///主线章节系统 /// public static class ChapterSvc { //进入游戏 检测上次战斗数据 public static void OnEnter(PlayerOnGame player) { OnBattleEnd(player); player.RoleData.ChapterData.CanJoinBattle = true; player.MakeDirty(); } //下线清理数据 public static void OnOffline(PlayerOnGame player) { // OnBattleEnd(player);//客户端战斗过程中长时间且后台运行,会导致战斗结束,这里不清理 player.MakeDirty(); } //重连得话需要同步数据 public static void OnReEnter(PlayerOnGame player) { player.RoleData.ChapterData.CanJoinBattle = true; if (!player.RoleData.IsInBattle) { return; } //player.RoleData.IsInBattle = false; OffsetBattleTime(ref player.RoleData.BattleRecord); SyncChapterInfo(player); } public static void OnPlayerBorn(PlayerOnGame player) { ref var chapterData = ref player.RoleData.ChapterData; var chapterId = CommParamDescMgr.Instance.MainLandFirstId.int_val; var desc = ChapterDescMgr.Instance.GetConfig(chapterId); if (desc == null) { TraceLog.Error("ChapterSvc.OnPlayerBorn init chapter id desc not found id= {0}", chapterId); } else { chapterData.ChapterId = desc.chapterId; } chapterData.CanJoinBattle = true; chapterData.BattleId = 0; InitRecords(ref chapterData.EffectiveStage); InitRecords(ref chapterData.PerfectIds); InitRecords(ref chapterData.EffectiveRewardRecord); InitRecords(ref chapterData.PerfectRewardRecord); player.MakeDirty(); SyncChapterInfo(player); } private static void InitRecords(ref RepeatedRecord data) { for (var i = 0; i < data.Records.GetMaxCount(); i++) { var one = new RepeatedRecordOne(); for (var j = 0; j < one.Record.GetMaxCount(); j++) { one.Record.Add(0); } data.Records.Add(one); } } public static void OnBattleBegin(PlayerOnGame player, StructPacket packet) { ref var req = ref packet.GetMessage(); //Thread.Sleep(2000); var isGm = req.IsGm; isGm = false; ref var res = ref OnBattleBeginRes.Parser.GetMessageClear(); var resCmd = (int)CSGameMsgID.BattleBeginRes; var chapterId = req.ChapterId; var battleId = req.BattleId; if (!player.RoleData.ChapterData.CanJoinBattle) { res.Ret = (int)CSErrCode.CanJoinBattleFail; player.SendToClient(resCmd, ref res); return; } if (player.RoleData.IsInBattle) { //结算上一场战斗 OnBattleEnd(player); TraceLog.Error("ChapterSvc.OnBattleBegin player is in battle,uid={0},chapterId={1},battleId={2}", player.UserID, chapterId, battleId); // res.Ret = (int)CSErrCode.Fail; // player.SendToClient(resCmd, ref res); // return; } var battleDesc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if (battleDesc == null) { res.Ret = (int)CSErrCode.DescNotFound; player.SendToClient(resCmd, ref res); return; } switch (battleDesc.chapterBattleType) { case ChapterBattleType.RewardBattle: BeginRewardBattle(player, isGm, battleId); break; case ChapterBattleType.MainBattle: BeginMainBattle(player, isGm, chapterId, battleId); break; case ChapterBattleType.GuideBattle: BeginGuideBattle(player, isGm, battleId); break; default: TraceLog.Error("ChapterSvc.OnBattleBegin battle type not found"); break; } } private static void BeginGuideBattle(PlayerOnGame player, bool isGm, int battleId) { ref var res = ref OnBattleBeginRes.Parser.GetMessageClear(); var resCmd = (int)CSGameMsgID.BattleBeginRes; var battleDesc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if (battleDesc == null) { res.Ret = (int)CSErrCode.DescNotFound; player.SendToClient(resCmd, ref res); return; } var now = GameServerUtils.GetTimeSecond(); ref var record = ref player.RoleData.BattleRecord; record.Clear(); record.BattleBeginTime = now; record.BeginTime = now; record.BattleData.BattleId = battleId; record.BattleData.BattleStatus = BattleStatus.NONE; InitBuildMonsterInfo(player, battleId); player.RoleData.IsInBattle = true; player.MakeDirty(); res.Ret = (int)CSErrCode.None; res.BattleData.CopyFrom(ref record.BattleData); player.SendToClient(resCmd, ref res); //SyncChapterInfo(player); } private static void BeginRewardBattle(PlayerOnGame player, bool isGm, int battleId) { ref var res = ref OnBattleBeginRes.Parser.GetMessageClear(); ref var chapter = ref player.RoleData.ChapterData; var resCmd = (int)CSGameMsgID.BattleBeginRes; var battleDesc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if (battleDesc == null) { res.Ret = (int)CSErrCode.DescNotFound; player.SendToClient(resCmd, ref res); return; } var now = GameServerUtils.GetTimeSecond(); if (chapter.RewardBattleData.BattleId == 0 || chapter.RewardBattleData.BattleId != battleId) { res.Ret = (int)CSErrCode.DescNotFound; player.SendToClient(resCmd, ref res); return; } if (chapter.RewardBattleData.LoseTime < now) { res.Ret = (int)CSErrCode.DescNotFound; player.SendToClient(resCmd, ref res); return; } var power = PlayerDataSvc.ClcPower(player); if (power < battleDesc.chapterBattleCost && !isGm) { //体力不够呀 res.Ret = (int)CSErrCode.TargetNotExist; player.SendToClient(resCmd, ref res); PlayerDataSvc.SyncPower(player); //主动同步一下体力,防止客户端显示不对 return; } ref var record = ref player.RoleData.BattleRecord; player.RoleData.ChapterData.CanJoinBattle = false; record.Clear(); record.BattleBeginTime = now; record.BeginTime = now; record.BattleData.BattleId = battleId; record.BattleData.BattleStatus = BattleStatus.NONE; InitBuildMonsterInfo(player, battleId); player.RoleData.IsInBattle = true; player.MakeDirty(); res.Ret = (int)CSErrCode.None; res.BattleData.CopyFrom(ref record.BattleData); player.SendToClient(resCmd, ref res); SyncChapterInfo(player); } private static void BeginMainBattle(PlayerOnGame player, bool isGm, int chapterId, int battleId) { ref var res = ref OnBattleBeginRes.Parser.GetMessageClear(); ref var chapter = ref player.RoleData.ChapterData; var resCmd = (int)CSGameMsgID.BattleBeginRes; var battleDesc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if (battleDesc == null) { res.Ret = (int)CSErrCode.DescNotFound; player.SendToClient(resCmd, ref res); return; } var desc = ChapterDescMgr.Instance.GetConfig(chapterId); if (desc == null) { res.Ret = (int)CSErrCode.DescNotFound; player.SendToClient(resCmd, ref res); return; } if (!desc.battleList.Contains(battleId)) { //是这个章节关卡么 res.Ret = (int)CSErrCode.Fail; player.SendToClient(resCmd, ref res); return; } var power = PlayerDataSvc.ClcPower(player); if (power < battleDesc.chapterBattleCost && !isGm) { //体力不够呀 res.Ret = (int)CSErrCode.PayConsumeItemLimit; player.SendToClient(resCmd, ref res); PlayerDataSvc.SyncPower(player); //主动同步一下体力,防止客户端显示不对 return; } if(chapter.BattleId != 0 && chapter.ChapterId == chapterId && chapter.BattleId + 1 < battleId) { res.Ret = (int)CSErrCode.Fail; player.SendToClient(resCmd, ref res); TraceLog.Error("ChapterSvc.BeginMainBattle BattleId not +1,uid={0},chapterId={1},battleId={2}, databattleid={3}", player.UserID, chapterId, battleId, chapter.BattleId); return; } if (chapter.ChapterId != 0 && chapter.ChapterId < chapterId) //新的一章 { if (chapter.BattleId != 0) //上一章没有打完,不可以打下一章的 { var nowc = chapter.BattleId / 1000;//1010->1 if (nowc + 1 != chapterId % 1000)//1005->5 { res.Ret = (int)CSErrCode.Fail; player.SendToClient(resCmd, ref res); TraceLog.Error("ChapterSvc.BeginMainBattle chapterId not match,uid={0},chapterId={1},battleId={2}, databattleid={3}", player.UserID, chapterId, battleId, chapter.BattleId); return; } var winBattleDesc = ChapterBattleDescMgr.Instance.GetConfig(chapter.BattleId); if (winBattleDesc == null) { res.Ret = (int)CSErrCode.DescNotFound; player.Error("not found battle desc id={0}", chapter.BattleId); player.SendToClient(resCmd, ref res); return; } if (winBattleDesc.nextChapterBattleId != 0) { res.Ret = (int)CSErrCode.Fail; player.SendToClient(resCmd, ref res); TraceLog.Error("ChapterSvc.BeginMainBattle2 chapterId not match,uid={0},chapterId={1},battleId={2}, databattleid={3}", player.UserID, chapterId, battleId, chapter.BattleId); return; } } } player.RoleData.ChapterData.CanJoinBattle = false; ref var record = ref player.RoleData.BattleRecord; record.Clear(); var now = GameServerUtils.GetTimeSecond(); record.BattleBeginTime = now; record.BeginTime = now; record.BattleData.BattleId = battleId; record.BattleData.BattleStatus = BattleStatus.NONE; chapter.LastBattleId = battleId; chapter.LastChapterId = chapterId; InitBuildMonsterInfo(player, battleId); player.RoleData.IsInBattle = true; player.MakeDirty(); res.Ret = (int)CSErrCode.None; res.BattleData.CopyFrom(ref record.BattleData); player.SendToClient(resCmd, ref res); SyncChapterInfo(player); } public static void InitBuildMonsterInfo(PlayerOnGame player, int battleId, int initStageId = 0) { ref var record = ref player.RoleData.BattleRecord; var battleDesc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if(initStageId == 0) { initStageId = battleDesc.firstChapterBattleStageId; } var battleStageDesc = ChapterBattleStageDescMgr.Instance.GetConfig(initStageId); if (battleStageDesc == null) { TraceLog.Error("ChapterSvc.InitBuildMonsterInfo not found stage desc id={0}", initStageId); return; } ref var stageInfo = ref record.StageInfo; var nextStageId = battleStageDesc.stageId; while (nextStageId != 0) { var desc = ChapterBattleStageDescMgr.Instance.GetConfig(nextStageId); var stage = new MonsterStage() { StageId = nextStageId, }; var monster = desc.monster; var list = new List(); foreach (var mon in monster) { for (var i = 0; i < mon.List.Length; i++) { GenericUtils.Merge(list, mon.List[i], mon.Num[i]); } } foreach (var idv in list) { stage.AllNum += idv.Value; stage.MonsterInfo.Add(idv); } stageInfo.Add(stage); nextStageId = desc.nextStageId; } } public static void OnBattleOption(PlayerOnGame player, StructPacket packet, bool isAdv = false) { ref var req = ref packet.GetMessage(); ref var res = ref OnBattleOptionRes.Parser.GetMessageClear(); switch (req.Option) { case ChapterOption.ActiveMonster: OnActiveNextStage(player); break; case ChapterOption.SuspendBattle: OnSuspendBattle(player); break; case ChapterOption.ContinueBattle: OnContinueBattle(player); break; case ChapterOption.ResurrectionBattle: OnResurrectionBattle(player, isAdv); break; case ChapterOption.DefeatBattle: res.Ret = (int)OnBattleDefeat(player); break; case ChapterOption.EndBattle: OnBattleEnd(player); SyncChapterInfo(player); break; case ChapterOption.None: default: TraceLog.Error("ChapterSvc.OnBattleOption command not supported,uid={0}", player.UserID); break; } player.MakeDirty(); res.Option = req.Option; res.BattleData.CopyFrom(ref player.RoleData.BattleRecord.BattleData); player.SendToClient((int)CSGameMsgID.BattleOptionRes, ref res); } //激活波次 private static void OnActiveNextStage(PlayerOnGame player) { if (!player.RoleData.IsInBattle) { return; } ref var chapterBattleData = ref player.RoleData.BattleRecord; var stageId = chapterBattleData.MonsterStageId; int nextStageId; if (stageId == 0) { var desc = ChapterBattleDescMgr.Instance.GetConfig(chapterBattleData.BattleData.BattleId); stageId = desc.firstChapterBattleStageId; nextStageId = stageId; } else { var stageDesc = ChapterBattleStageDescMgr.Instance.GetConfig(stageId); nextStageId = stageDesc.nextStageId; } if (nextStageId == 0) { return; } var nextStageDesc = ChapterBattleStageDescMgr.Instance.GetConfig(nextStageId); if (nextStageDesc == null) { return; } var now = GameServerUtils.GetTimeSecond(); chapterBattleData.MonsterStageId = nextStageId; chapterBattleData.MonsterBeginTime = now; chapterBattleData.MonsterActiveTime = now; chapterBattleData.MonsterTimeDuration = 0; } // 由客户端触发产出一批怪,祭坛 public static void OnTickBattleEntity(PlayerOnGame player, StructPacket packet) { ref var req = ref packet.GetMessage(); var type = req.Type; ref var res = ref OnTickBattleEntityRes.Parser.GetMessageClear(); res.Seq = req.Seq; res.MsgSeq = req.MsgSeq; const int cmd = (int)CSGameMsgID.OntickBattleEntityRes; switch (type) { case 0: // { // ref var chapter = ref player.RoleData.BattleRecord; // // ref var stageInfo = ref chapter.StageInfo; // var index = -1; // for (int i = 0; i < stageInfo.Count; i++) // { // if (stageInfo[i].StageId == req.StageId) // { // index = i; // break; // } // } // // ref var stage = ref stageInfo[index]; // var stageDesc = ChapterBattleStageDescMgr.Instance.GetConfig(stage.StageId); // // var maxNum = 0; // foreach (var m in stageDesc.monster) // { // for (int i = 0; i < m.List.Length; i++) // { // if (m.List[i] == req.EntityId) // { // maxNum = m.Num[i]; // } // } // } // // if (req.EntityNum > maxNum) // { // res.Ret = (int)CSErrCode.SendLimit; // player.SendToClient(cmd, ref res); // return; // } // // ref var monster = ref stage.MonsterInfo; // index = -1; // for (var i = 0; i < monster.Count; i++) // { // if (monster[i].Id == req.EntityId) // { // index = i; // break; // } // } // // if (index == -1) // { // monster.Add(new IDValue32() { Id = req.EntityId, Value = req.EntityNum }); // } // else // { // var num = monster[index].Value + req.EntityNum; // if (num > maxNum) // { // //超过数量 // res.Ret = (int)CSErrCode.SendLimit; // player.SendToClient(cmd, ref res); // return; // } // // monster[index].Value += req.EntityNum; // } // } break; case 1: //刷一个祭坛出来 { ref var record = ref player.RoleData.BattleRecord; var index = -1; for (int i = 0; i < record.AltarInfo.Count; i++) { if (record.AltarInfo[i].Id == req.EntityId) { index = i; break; } } if (index < 0) { var battleDesc = ChapterBattleDescMgr.Instance.GetConfig(record.BattleData.BattleId); var alterIds = battleDesc.altarId; var entityId = req.EntityId; var exist = alterIds.Any(alterId => alterId == entityId); if (exist) { record.AltarInfo.Add(new IDValue32() { Id = req.EntityId, Value = 1 }); player.MakeDirty(); } } } break; } player.SendToClient(cmd, ref res); } //拾取击杀怪物发送奖励 public static void OnKilledMonsterReq(PlayerOnGame player, StructPacket packet) { ref var req = ref packet.GetMessage(); var monsterId = req.MonsterId; var stageId = req.StageId; var monsterPropDesc = MonsterPropDescMgr.Instance.GetConfig(monsterId); var cmd = (int)CSGameMsgID.KilledMonsterRes; ref var res = ref OnKilledMonsterRes.Parser.GetMessageClear(); res.DropInfo.Seq = req.Seq; res.MsgSeq = req.MsgSeq; if (monsterPropDesc == null) { player.SendToClient(cmd, ref res); return; } if (!player.RoleData.IsInBattle) { player.SendToClient(cmd, ref res); return; } var stageDesc = ChapterBattleStageDescMgr.Instance.GetConfig(stageId); if (stageDesc == null) { player.SendToClient(cmd, ref res); return; } if (string.IsNullOrEmpty(monsterPropDesc.dropConfig)) { OnBattleWin(player, stageDesc.stageType); player.SendToClient(cmd, ref res); return; } ref var record = ref player.RoleData.BattleRecord; var stageInfo = record.StageInfo; var maxNum = 0; //当前波次这儿怪的最大数量 for (var i = 0; i < stageInfo.Count; i++) { if (stageInfo[i].StageId == stageId) { for (int j = 0; j < stageInfo[i].MonsterInfo.Count; j++) { var id = stageInfo[i].MonsterInfo[j].Id; if (id == monsterId) { maxNum = stageInfo[i].MonsterInfo[j].Value; break; } } break; } } if (maxNum == 0) //召唤怪 { OnBattleWin(player, stageDesc.stageType); player.SendToClient(cmd, ref res); return; } ref var killedMonsters = ref record.KilledMonsters; var killNum = 0; var indexi = -1; var indexj = -1; for (var i = 0; i < killedMonsters.Count; i++) { if (killedMonsters[i].StageId == stageId) { for (var j = 0; j < killedMonsters[i].MonsterInfo.Count; j++) { if (killedMonsters[i].MonsterInfo[j].Id == monsterId) { killNum = killedMonsters[i].MonsterInfo[j].Value; //当前波次这个怪的击杀数量 indexj = j; break; } } indexi = i; break; } } if (maxNum > 0 && killNum > 0 && maxNum <= killNum) { OnBattleWin(player, stageDesc.stageType); player.SendToClient(cmd, ref res); //击杀到最大值 return; } var dropRewardId = monsterPropDesc.dropConfig; if (string.IsNullOrEmpty(dropRewardId)) { OnBattleWin(player, stageDesc.stageType); player.SendToClient(cmd, ref res); //没有奖励的怪物不计入 return; } var dropInfo = new MonsterDrop { Seq = req.Seq }; var dropReward = new List(); BuildDropReward(player, dropRewardId, dropReward, ref dropInfo); res.DropInfo.CopyFrom(ref dropInfo); if (indexi > -1) { if (indexj > -1) { killedMonsters[indexi].MonsterInfo[indexj].Value += 1; } else { killedMonsters[indexi].MonsterInfo.Add(new IDValue32() { Id = monsterId, Value = 1 }); } } else { var killInfo = new KillMonsterInfo(); killInfo.MonsterInfo.Add(new IDValue32() { Id = monsterId, Value = 1 }); killInfo.StageId = stageId; killedMonsters.Add(killInfo); indexi = killedMonsters.Count - 1; } var quickPassed = IsCanSendQuickPassReward(player, ref record, stageId); //是否速通 if (quickPassed) { killedMonsters[indexi].Effective = true; var stageRewardId = stageDesc.stageReward; var list = ChapterHelper.ConvRewardInternal(player, stageRewardId); if (list.Count > 0) { ref var sync = ref SyncExtDropRewardData.Parser.GetMessageClear(); foreach (var v in list) { sync.Rewards.Add(v); } TaskEXEvent.TriggerGetStageRwdN(player); player.SendToClient((int)CSGameMsgID.OnSyncExtDropRewardData, ref sync); } else { TraceLog.Trace( "Chapter.OnKilledMonsterReq not found quick kill monster reward stage={0} ,rewardCfg={1}", stageId, stageRewardId); } dropReward.AddRange(list); //添加到记录里面 AppendChapterDataEffectiveStage(player, stageId); if (player.RoleData.ChapterData.BattleId >= record.BattleData.BattleId) { IsPerfectPass(player, ref record); } } AppendDropReward(ref record, dropReward); var exp = monsterPropDesc.exp; LevelUtils.AddExp(player, exp, "Chapter"); OnBattleWin(player, stageDesc.stageType); player.MakeDirty(); player.SendToClient(cmd, ref res); } private static void OnBattleWin(PlayerOnGame player, ChapterBattleStageType stageType) { if (stageType != ChapterBattleStageType.Boss) { return; } ref var res = ref OnChapterBattleWinSync.Parser.GetMessageClear(); ref var record = ref player.RoleData.BattleRecord; ref var chapterData = ref player.RoleData.ChapterData; var battleDesc = ChapterBattleDescMgr.Instance.GetConfig(record.BattleData.BattleId); if (battleDesc == null) { player.SendToClient((int)CSGameMsgID.OnSyncChapterBattleWin, ref res); return; } if (battleDesc.chapterBattleType == ChapterBattleType.ContinueBattle) { //player.SendToClient((int)CSGameMsgID.OnSyncChapterBattleWin, ref res); return; } if (record.BattleData.BattleStatus == BattleStatus.DEFEAT) { return; } if(record.BattleData.BattleStatus == BattleStatus.WIN) { player.SendToClient((int)CSGameMsgID.OnSyncChapterBattleWin, ref res); return; } var upBattle = false; var cost = battleDesc.chapterBattleCost; PlayerDataSvc.CostPower(player, cost, true); //扣体力 switch (battleDesc.chapterBattleType) { case ChapterBattleType.MainBattle: IsPerfectPass(player, ref record); record.BattleData.BattleStatus = BattleStatus.WIN; if (chapterData.LastChapterId > chapterData.ChapterId) { chapterData.ChapterId = chapterData.LastChapterId; } if (chapterData.LastBattleId > chapterData.BattleId) { ClcBattleTime(ref record, true); chapterData.BattleId = chapterData.LastBattleId; upBattle = true; //新关卡,重置 var nextChapterBattleId = battleDesc.nextChapterBattleId; var nextChapterId = chapterData.ChapterId; if (nextChapterBattleId == 0) { var chapterDesc = ChapterDescMgr.Instance.GetConfig(chapterData.ChapterId); nextChapterId = chapterDesc.nextChapterId; var nextChapterDesc = ChapterDescMgr.Instance.GetConfig(nextChapterId); nextChapterBattleId = nextChapterDesc.firstChapterBattleId; } if (nextChapterBattleId != 0) { chapterData.LastChapterId = nextChapterId; chapterData.LastBattleId = nextChapterBattleId; } } RandomRewardBattleChapter(player, battleDesc); TaskEXEvent.TriggerChapterBattle(player, record.BattleData.BattleId); TaskEXEvent.PassChapterBattle(player); break; case ChapterBattleType.RewardBattle: player.RoleData.ChapterData.RewardBattleData.Clear(); record.BattleData.BattleStatus = BattleStatus.WIN; break; case ChapterBattleType.GuideBattle: record.BattleData.BattleStatus = BattleStatus.WIN; break; case ChapterBattleType.ContinueBattle: record.BattleData.BattleStatus = BattleStatus.WIN; break; } SyncChapterInfo(player); SystemUnlockEvent.OnLevelChange(player); player.SendToClient((int)CSGameMsgID.OnSyncChapterBattleWin, ref res); if (upBattle) { RankSvc.UpdateRankScore(player, 1, chapterData.BattleId, record.BattleTimeDuration); } PopPackageSvc.TriggerPopPackage(player,PackPopType.LevelStage); } public static void OnGainStageReward(PlayerOnGame player, StructPacket packet) { ref var req = ref packet.GetMessage(); var res = OnGainBattleRewardRes.Parser.GetMessageClear(); res.StageId = req.StageId; var stageId = req.StageId; var cmd = (int)CSGameMsgID.OnGainBattleRewardRes; if (stageId == 0) { res.Ret = CSErrCode.Fail; player.SendToClient(cmd, ref res); return; } var desc = ChapterBattleStageDescMgr.Instance.GetConfig(stageId); if (desc == null) { res.Ret = CSErrCode.DescNotFound; player.SendToClient(cmd, ref res); return; } var effect = ChapterHelper.IsEffectiveStage(player, desc.stageIndex); if (!effect) { res.Ret = CSErrCode.RecvLimit; player.SendToClient(cmd, ref res); return; } var isGain = ChapterHelper.IsGainEffectiveReward(player, desc.stageIndex); if (isGain) { res.Ret = CSErrCode.RecvLimit; player.SendToClient(cmd, ref res); return; } var rewardId = desc.stageManualReward; if (string.IsNullOrEmpty(rewardId)) { res.Ret = CSErrCode.DescNotFound; player.SendToClient(cmd, ref res); return; } RewardSvc.Reward(player, rewardId, true, true); ChapterHelper.SetGainEffectiveReward(player, desc.stageIndex); SyncChapterInfo(player); player.MakeDirty(); player.SendToClient(cmd, ref res); } //领取当前关卡得所有波次奖励 public static void OnGainAllStageReward(PlayerOnGame player, StructPacket packet) { ref var req = ref packet.GetMessage(); var chapterDesc = ChapterDescMgr.Instance.GetConfig(req.ChapterId); ref var res = ref OnGainAllBattleRewardRes.Parser.GetMessageClear(); var cmd = (int)CSGameMsgID.OnGainAllBattleRewardRes; if (chapterDesc == null) { res.Ret = CSErrCode.DescNotFound; player.SendToClient(cmd, ref res); return; } var battleId = chapterDesc.firstChapterBattleId; var rewardList = new List(); while (battleId != 0) { var desc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if (desc == null) { break; } battleId = desc.nextChapterBattleId; var stageId = desc.firstChapterBattleStageId; while (stageId != 0) { var stageDesc = ChapterBattleStageDescMgr.Instance.GetConfig(stageId); if (stageDesc == null) { break; } stageId = stageDesc.nextStageId; if (!ChapterHelper.IsEffectiveStage(player, stageDesc.stageIndex)) { continue; } if (ChapterHelper.IsGainEffectiveReward(player, stageDesc.stageIndex)) { continue; } var rewardId = stageDesc.stageManualReward; if (string.IsNullOrEmpty(rewardId)) { continue; } var list = RewardSvc.Reward(player, rewardId, false, false); foreach (var item in list) { var reward = new TypeIDValueString { Type = item.type, Value = (int)item.amount }; reward.Id.SetString(item.code); GenericUtils.Merge(rewardList, reward); } ChapterHelper.SetGainEffectiveReward(player, stageDesc.stageIndex); } if (ChapterHelper.IsPerfectPass(player, desc.chapterIndex) && !ChapterHelper.IsGainPerfectPassReward(player, desc.chapterIndex)) { var rewardId = desc.manualReward; if (string.IsNullOrEmpty(rewardId)) { continue; } ChapterHelper.SetGainPerfectPassReward(player,desc.chapterIndex); var list = RewardSvc.Reward(player, rewardId, false, false); foreach (var item in list) { var reward = new TypeIDValueString { Type = item.type, Value = (int)item.amount }; reward.Id.SetString(item.code); GenericUtils.Merge(rewardList, reward); } } } var unifyOp = new UnifyOp(player, BillChangeItemReason.CHAPTER); foreach (var reward in rewardList) { unifyOp.AddGoods(reward.Type, reward.Id.GetString(), reward.Value); } unifyOp.DoOp(sendGetItemMsg: true); SyncChapterInfo(player); player.MakeDirty(); player.SendToClient(cmd, ref res); } private static void RandomRewardBattleChapter(PlayerOnGame player, ChapterBattleDesc currentBattleDesc) { if (!SystemUnlockSvc.IsUnlockSys(player, SystemUnlockId.RwdChapter)) { return; } if (currentBattleDesc.chapterBattleType != ChapterBattleType.MainBattle) { return; } var rewardId = CommParamDescMgr.Instance.RwdChapterRwd.str_val; if (MonthlyCardSvc.IsActive(player, (int)MonthlyCardId.VIP_CARD_PLUS)) { var vipDesc = MonthlyCardDescMgr.Instance.GetConfig((int)MonthlyCardId.VIP_CARD_PLUS); if (vipDesc != null && !string.IsNullOrEmpty(vipDesc.rwdBattleCondUp)) { rewardId = vipDesc.rwdBattleCondUp; } } var reward = RewardSvc.Reward(player, rewardId, false); if (reward == null || reward.Count == 0) { return; } var rd = reward[0]; var type = rd.type; if (type != (int)GoodsType.BattleReward) //type=6 is character battle id; { return; } int.TryParse(rd.code, out var battleId); if (battleId == 0) { return; } var duration = CommParamDescMgr.Instance.RwdChapterTime.int_val; player.RoleData.ChapterData.RewardBattleData.LoseTime = GameServerUtils.GetTimeSecond() + duration; player.RoleData.ChapterData.RewardBattleData.BattleId = battleId; player.RoleData.ChapterData.RewardBattleData.Level = player.GetLevel(); } private static void BuildDropReward(PlayerOnGame player, string rewardId, List collect, ref MonsterDrop dropInfo) { var list = ChapterHelper.ConvRewardInternal(player, rewardId); foreach (var reward in list) { collect.Add(reward); dropInfo.Rewards.Add(reward); } } public static bool IsCanSendQuickPassReward(PlayerOnGame player, ref ChapterDataRecord record, int stageId) { var desc = ChapterBattleDescMgr.Instance.GetConfig(record.BattleData.BattleId); var isPerfect = ChapterHelper.IsPerfectPass(player, desc.chapterIndex); if (isPerfect) //已经完美通关那必定已经发过完美通关奖励了 { return false; } var battleId = record.BattleData.BattleId; var battleDesc = ChapterBattleDescMgr.Instance.GetConfig(battleId); //奖励关卡不速通 if (battleDesc.chapterBattleType == ChapterBattleType.RewardBattle) { return false; } var stageDesc = ChapterBattleStageDescMgr.Instance.GetConfig(stageId); var isEffectiveStage = ChapterHelper.IsEffectiveStage(player, stageDesc.stageIndex); if (isEffectiveStage) { return false; //以发过了 } var timeLimit = stageDesc.stageRewardLimitTime; if (record.MonsterStageId != stageId) { return false; } if (!IsKillOneStage(ref record, stageId)) { return false; } ClcBattleTime(ref record, true); return record.MonsterTimeDuration < timeLimit; } private static void AppendChapterDataEffectiveStage(PlayerOnGame player, int stageId) { var stageDesc = ChapterBattleStageDescMgr.Instance.GetConfig(stageId); var effectiveStage = ChapterHelper.IsEffectiveStage(player, stageDesc.stageIndex); if (effectiveStage) { return; } ChapterHelper.SetEffectiveStage(player, stageDesc.stageIndex); } //完美通关判定 private static void IsPerfectPass(PlayerOnGame player, ref ChapterDataRecord record) { var battleId = record.BattleData.BattleId; if (battleId == 0) { return; } var desc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if (desc == null || desc.chapterBattleType == ChapterBattleType.RewardBattle) { return; } if (ChapterHelper.IsPerfectPass(player, desc.chapterIndex)) { return; } var stageId = desc.firstChapterBattleStageId; var perfectPass = true; while (stageId != 0) { var stageDesc = ChapterBattleStageDescMgr.Instance.GetConfig(stageId); stageId = stageDesc.nextStageId; if (stageDesc.stageType == ChapterBattleStageType.Boss) { continue; } perfectPass &= ChapterHelper.IsEffectiveStage(player, stageDesc.stageIndex); } if (perfectPass) { //完美通关 ChapterHelper.SetPerfectPass(player, desc.chapterIndex); } SyncChapterInfo(player); } //当前波怪物是否杀完 private static bool IsKillOneStage(ref ChapterDataRecord record, int stageId) { var index = -1; for (int i = 0; i < record.KilledMonsters.Count; i++) { if (record.KilledMonsters[i].StageId == stageId) { index = i; break; } } if (index < 0) { return false; } var killNum = 0; var monsterInfo = record.KilledMonsters[index].MonsterInfo; for (int i = 0; i < monsterInfo.Count; i++) { killNum += monsterInfo[i].Value; } for (var i = 0; i < record.StageInfo.Count; i++) { if (record.StageInfo[i].StageId != stageId) continue; if (killNum >= record.StageInfo[i].AllNum) { return true; } } return false; } public static void AppendDropReward(ref ChapterDataRecord record, List reward) { if (reward.Count == 0) { return; } var dropReward = record.DropReward; for (var i = 0; i < dropReward.Count; i++) { reward.Add(dropReward[i]); } var rw = GenericUtils.MergedDuplicates(reward); record.DropReward.Clear(); foreach (var t in rw) { record.DropReward.Add(t); } } public static void OnPickupMonsterReward(PlayerOnGame player, StructPacket packet) { ref var req = ref packet.GetMessage(); ref var record = ref player.RoleData.BattleRecord; ref var res = ref OnPickupMonsterRewardRes.Parser.GetMessageClear(); var battleDesc = ChapterBattleDescMgr.Instance.GetConfig(record.BattleData.BattleId); if (battleDesc == null || battleDesc.chapterBattleType == ChapterBattleType.ContinueBattle) {//boss连战单独处理 return; } ref var reward = ref record.DropReward; var index = -1; for (int i = 0; i < reward.Count; i++) { if (reward[i].Id == req.Id && reward[i].Type == req.Type) { index = i; } } if (index < 0) { player.SendToClient((int)CSGameMsgID.OnPickupMonsterRewardRes, ref res); return; } var id = reward[index].Id; var type = reward[index].Type; var value = reward[index].Value; reward.RemoveAt(index); if (value <= 0) { return; } var unifyOp = new UnifyOp(player, BillChangeItemReason.CHAPTER); unifyOp.AddGoods(type, id, value); unifyOp.DoOp(); player.MakeDirty(); player.SendToClient((int)CSGameMsgID.OnPickupMonsterRewardRes, ref res); } //暂停(失败也会) private static void OnSuspendBattle(PlayerOnGame player) { if (!player.RoleData.IsInBattle) { return; } ref var chapterBattleData = ref player.RoleData.BattleRecord; if (chapterBattleData.BattleData.BattleId == 0) { return; } if (chapterBattleData.BattleData.BattleStatus != BattleStatus.NONE) { return; } ClcBattleTime(ref chapterBattleData, true); chapterBattleData.BattleData.BattleStatus = BattleStatus.SUSPEND; //暂停 } //继续 private static void OnContinueBattle(PlayerOnGame player) { if (!player.RoleData.IsInBattle) { return; } ref var chapterBattleData = ref player.RoleData.BattleRecord; if (chapterBattleData.BattleData.BattleId == 0) { return; } if (chapterBattleData.BattleData.BattleStatus == (int)BattleStatus.NONE) { return; } if (IsBattleWin(ref chapterBattleData)) { return; } ClcBattleTime(ref chapterBattleData); chapterBattleData.BattleData.BattleStatus = (int)BattleStatus.NONE; } //复活 private static void OnResurrectionBattle(PlayerOnGame player, bool isAdv = false) { if (!player.RoleData.IsInBattle) { return; } ref var chapterBattleData = ref player.RoleData.BattleRecord; if (chapterBattleData.BattleData.BattleId == 0) { return; } var desc = ChapterBattleDescMgr.Instance.GetConfig(chapterBattleData.BattleData.BattleId); if (desc.isRevive == ReviveType.FALSE) { return; } var status = chapterBattleData.BattleData.BattleStatus; if (status is BattleStatus.NONE or BattleStatus.WIN) { return; } if (IsBattleWin(ref chapterBattleData)) { return; } if (isAdv) { chapterBattleData.BattleData.ReviveNum++; } ClcBattleTime(ref chapterBattleData); chapterBattleData.BattleData.BattleStatus = (int)BattleStatus.NONE; } private static bool IsBattleWin(ref ChapterDataRecord chapterDataRecord) { return chapterDataRecord.BattleData.BattleStatus == BattleStatus.WIN; } //激活祭坛 public static void OnActiveAltar(PlayerOnGame player, StructPacket packet) { // ref var req = ref packet.GetMessage(); // var altarId = req.AltarId; // var res = new OnActiveAltarRes(); // var cmd = (int)CSGameMsgID.BattleActiveAltarRes; // // ref var chapterData = ref player.RoleData.ChapterData; // if (!chapterData.IsInBattle) // { // res.Ret = (int)CSErrCode.Fail; // player.SendToClient(cmd, ref res); // return; // } // // ref var chapterBattleData = ref player.RoleData.ChapterBattleData; // if (chapterBattleData.BattleId == 0) // { // res.Ret = (int)CSErrCode.DescNotFound; // player.SendToClient(cmd, ref res); // return; // } // // ref var lateAltarInfo = ref chapterBattleData.AltarInfo; // var index = -1; // for (int i = 0; i < lateAltarInfo.Count; i++) // { // if (lateAltarInfo[i].AlterId == altarId) // { // index = i; // break; // } // } // // if (index == -1) // { // res.Ret = (int)CSErrCode.DescNotFound; // player.SendToClient(cmd, ref res); // return; // } // // ref var info = ref lateAltarInfo[index]; // if (info.IsUse) // { // res.Ret = (int)CSErrCode.Fail; // player.SendToClient(cmd, ref res); // return; // } // // info.IsUse = true; // var desc = AltarDescMgr.Instance.GetConfig(info.AlterId); // var altarEffect = desc.altarEffect; // if (altarEffect != 0) // { // //刷新buff // } // // player.MakeDirty(); // res.Ret = (int)CSErrCode.None; // player.SendToClient(cmd, ref res); } public static void OnBattleDefeat(PlayerOnGame player, StructPacket packet) { ref var req = ref packet.GetMessage(); var ret = OnBattleDefeat(player); ref var res = ref OnBattleDefeatRes.Parser.GetMessageClear(); res.Ret = ret; res.DefType = req.DefType; res.BattleId = req.BattleId; player.SendToClient((int)CSGameMsgID.OnBattleDefeatRes, ref res); } //失败等待复活 private static CSErrCode OnBattleDefeat(PlayerOnGame player) { if (!player.RoleData.IsInBattle) { return CSErrCode.None; } ref var chapterBattleData = ref player.RoleData.BattleRecord; if (chapterBattleData.BattleData.BattleId == 0) { ref var res = ref OnChapterBattleWinSync.Parser.GetMessageClear(); player.SendToClient((int)CSGameMsgID.OnSyncChapterBattleWin, ref res); return CSErrCode.BattleDefeatFail; } if (IsBattleWin(ref chapterBattleData)) { ref var res = ref OnChapterBattleWinSync.Parser.GetMessageClear(); player.SendToClient((int)CSGameMsgID.OnSyncChapterBattleWin, ref res); return CSErrCode.BattleDefeatFail; } if (chapterBattleData.BattleData.BattleStatus == BattleStatus.DEFEAT) { return CSErrCode.None; } OnSuspendBattle(player); chapterBattleData.BattleData.BattleStatus = BattleStatus.DEFEAT; //失败等待复活 return CSErrCode.None; } //战斗结束 private static void OnBattleEnd(PlayerOnGame player) { if (!player.RoleData.IsInBattle) { return; } player.RoleData.ChapterData.CanJoinBattle = true; player.RoleData.IsInBattle = false; ref var chapterBattleData = ref player.RoleData.BattleRecord; if (chapterBattleData.BattleData.BattleId == 0) { return; } if (player.RoleData.BattleRecord.BattleData.BattleStatus != BattleStatus.WIN) //并没有击杀boss中途退出 { var battleId = player.RoleData.BattleRecord.BattleData.BattleId; var battleStageDesc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if (battleStageDesc != null) { if (chapterBattleData.MonsterStageId != 0) //==0 没有进入战斗场景,不扣体力 { var cost = battleStageDesc.chapterBattleCost - battleStageDesc.chapterBattleFailReturn; PlayerDataSvc.CostPower(player, cost, true); } if (battleStageDesc.chapterBattleType == ChapterBattleType.RewardBattle) { player.RoleData.ChapterData.RewardBattleData.Clear(); } } else { player.Error("Chapter.OnBattleEnd not found battle stage desc id={0}", battleId); } } var battleData = player.RoleData.BattleRecord.BattleData; GameTALogUtils.ChapterBattleEnd(player, player.RoleData.ChapterData.LastChapterId, battleData.BattleId, battleData.BattleStatus == BattleStatus.WIN ? 1 : 0, player.RoleData.BattleRecord.BattleTimeDuration, chapterBattleData.MonsterStageId, player.RoleData.BattleRecord.PropVal); SendAllBattleReward(player); player.RoleData.BattleRecord.Clear(); player.RoleData.IsInBattle = false; } private static void SendAllBattleReward(PlayerOnGame player) { ref var dropReward = ref player.RoleData.BattleRecord.DropReward; if (dropReward.Count == 0) { return; } var op = new UnifyOp(player, BillChangeItemReason.CHAPTER); for (var i = 0; i < dropReward.Count; i++) { var rd = dropReward[i]; op.AddGoods(rd.Type, rd.Id, rd.Value); } op.DoOp(); dropReward.Clear(); } //是否战斗超时 private static bool IsBattleTimeout(ref ChapterDataRecord chapterBattleData) { var battleId = chapterBattleData.BattleData.BattleId; var desc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if (desc == null) { return true; } ClcBattleTime(ref chapterBattleData, true); return chapterBattleData.BattleTimeDuration > desc.chapterBattleLimitedTime; } //统计结算战斗耗时 private static void ClcBattleTime(ref ChapterDataRecord chapterDataRecord, bool calculate = false) { var now = GameServerUtils.GetTimeSecond(); if (calculate) { var duration = now - chapterDataRecord.BattleBeginTime; chapterDataRecord.BattleTimeDuration += (int)duration; duration = now - chapterDataRecord.MonsterBeginTime; chapterDataRecord.MonsterTimeDuration += (int)duration; //计算真正耗时 } chapterDataRecord.BattleBeginTime = now; chapterDataRecord.MonsterBeginTime = now; } private static void OffsetBattleTime(ref ChapterDataRecord chapterDataRecord) { var now = GameServerUtils.GetTimeSecond(); chapterDataRecord.BattleBeginTime = now; chapterDataRecord.MonsterBeginTime = now; } //同步客户端信息 public static void SyncChapterInfo(PlayerOnGame player) { ref var sync = ref SyncChapterData.Parser.GetMessageClear(); sync.ChapterData.CopyFrom(ref player.RoleData.ChapterData); sync.ChapterBattleData.CopyFrom(ref player.RoleData.BattleRecord.BattleData); player.SendToClient((int)CSGameMsgID.BattleSyncData, ref sync); } //扫荡 public static void OnMopUp(PlayerOnGame player, bool isAdv = false) { var cmd = (int)CSGameMsgID.MopUpRes; ref var res = ref MopUpRes.Parser.GetMessageClear(); var canMopUpNum = GetMopUpNum(player); if (!isAdv && canMopUpNum <= 0) { res.Ret = (int)CSErrCode.Fail; player.SendToClient(cmd, ref res); return; } var battleId = player.RoleData.ChapterData.BattleId; if (battleId == 0) { res.Ret = (int)CSErrCode.Fail; player.SendToClient(cmd, ref res); return; } var desc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if (desc == null) { res.Ret = (int)CSErrCode.Fail; player.SendToClient(cmd, ref res); return; } var costPower = desc.chapterBattleCost; var ret = PlayerDataSvc.CostPower(player, costPower); if (!ret) { res.Ret = (int)CSErrCode.Fail; player.SendToClient(cmd, ref res); return; } if (!isAdv) { player.RoleData.PowerPointData.MopTimes++; } PlayerDataSvc.SyncPower(player); //扫荡时设置当前关卡为最大关卡 player.RoleData.ChapterData.LastBattleId = player.RoleData.ChapterData.BattleId; var rewards = RewardSvc.Reward(player, desc.sweepReward, false, false); var unifyOp = new UnifyOp(player, BillChangeItemReason.Mop, "" + desc.chapterBattleId); foreach (var reward in rewards) { unifyOp.AddGoods(reward.type, reward.code, reward.amount); } var list = new List(); unifyOp.DoOp(retList: list); foreach (var info in list) { if (info.ChgCount <= 0) { continue; } res.Rewards.Add(info); } player.SendToClient(cmd, ref res); player.MakeDirty(); } //战斗中是否可以改变天赋或者切换武器 public static bool CanChangeTalentOrEquip(PlayerOnGame player) { if (player.RoleData.ChapterData.CanJoinBattle) { return true; } var battleId = player.RoleData.BattleRecord.BattleData.BattleId; var desc = ChapterBattleDescMgr.Instance.GetConfig(battleId); if (desc == null) { return true; } return desc.isChange == Bool.TRUE; } private static int GetMopUpNum(PlayerOnGame player) { var data = player.RoleData.PowerPointData; var baseNum = CommParamDescMgr.Instance.SweepTimes.int_val; baseNum += player.RoleData.PowerPointData.ExtMopTimes; return baseNum - data.MopTimes; } public static void PushProp(PlayerOnGame player, StructPacket packet) { ref var req = ref packet.GetMessage(); player.RoleData.BattleRecord.PropVal.CopyFrom(ref req.PropVal); var res = new OnBattlePushClientPropRes(); player.SendToClient((int)CSGameMsgID.OnBattlePushPropDataRes, ref res); } } }