You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1701 lines
61 KiB

using System.Collections.Generic;
using System.Linq;
using ProtoCSStruct;
using Sog;
namespace Game
{
/// <summary>
///主线章节系统
///</summary>
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<OnBattleBeginReq>();
//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<IDValue32>();
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<OnBattleOptionReq>();
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<OnTickBattleEntityReq>();
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<OnKilledMonsterReq>();
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<TypeIDValue32>();
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<OnGainBattleRewardReq>();
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<OnGainAllBattleRewardReq>();
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<TypeIDValueString>();
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<TypeIDValue32> 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<TypeIDValue32> 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<OnPickupMonsterRewardReq>();
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<OnActiveAltarReq>();
// 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<OnBattleDefeatReq>();
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<CSItemChgInfo>();
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<OnBattlePushClientPropReq>();
player.RoleData.BattleRecord.PropVal.CopyFrom(ref req.PropVal);
var res = new OnBattlePushClientPropRes();
player.SendToClient((int)CSGameMsgID.OnBattlePushPropDataRes, ref res);
}
}
}