using ProtoCSStruct; using Sog; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using TencentCloud.Npp.V20190823.Models; namespace Game { public class RewardSvc { /// /// 计算rewarid可与获得的reward,apply为true表示给于 /// /// /// /// public static List Reward(PlayerOnGame player, string rewardId, bool apply = true, bool sendGetMsg = false) { try { var config = RewardDescMgr.Instance.GetConfig(rewardId); if (config != null) { List list = new List(); switch (config.randomType) { case RewardRandomType.Fixed: { foreach (var item in config.list) { list.AddRange(ParseReward(player, item)); } break; } case RewardRandomType.Once: { list.AddRange(RewardOnce(player, config)); break; } case RewardRandomType.Level: { int lv = player.RoleBase.Level; for (int i = 0; i < config.rangeList.Count; i++) { var item = config.rangeList[i]; if (lv >= item.rangeMin && lv < item.rangeMax) { foreach (var item1 in item.list) { list.AddRange(ParseReward(player, item1)); } break; } } break; } case RewardRandomType.ContinueBattle: { int lv = player.RoleData.Cbdata.NowLayer ; for (int i = 0; i < config.rangeList.Count; i++) { var item = config.rangeList[i]; if (lv >= item.rangeMin && lv < item.rangeMax) { foreach (var item1 in item.list) { list.AddRange(ParseReward(player, item1)); } break; } } break; } case RewardRandomType.TimesResetByMaxValue: { list.AddRange(RewardTimesResetByMaxValue(player, config)); break; } case RewardRandomType.Arrays: { list.AddRange(RewardArray(player, config)); break; } case RewardRandomType.GroupArrays: { list.AddRange(RewardGroupArray(player, config)); break; } case RewardRandomType.Zone: { int bid = player.RoleData.ChapterData.BattleId; var desc = ChapterBattleDescMgr.Instance.GetConfig(bid); if (desc == null) { break; } var lv = desc.chapterIndex; for (int i = 0; i < config.rangeList.Count; i++) { var item = config.rangeList[i]; if (lv >= item.rangeMin && lv < item.rangeMax) { foreach (var item1 in item.list) { list.AddRange(ParseReward(player, item1)); } break; } } break; } case RewardRandomType.Appoint: {//当玩家主线进度为30,玩家挑战序号为15的关卡,则发放15对应的奖励 //若当前关卡序号在配置中不存在,则无事发生 int bid = player.RoleData.ChapterData.LastBattleId; var desc = ChapterBattleDescMgr.Instance.GetConfig(bid); if (desc == null) { break; } var lv = desc.chapterIndex; for (int i = 0; i < config.rangeList.Count; i++) { var item = config.rangeList[i]; if (lv == item.rangeMin) { foreach (var item1 in item.list) { list.AddRange(ParseReward(player, item1)); } break; } } break; } case RewardRandomType.Talent: { ref var titems = ref player.RoleData.Talent.TalentPage.Items; var talentTypeCount = new List( ); for (int i = 0; i < titems.Count; i++) { ref var item = ref titems.Get(i); var talent = TalentDescMgr.Instance.GetConfig(item.Id); if (talent == null) { continue; } if (!CommParamDescMgr.Instance.TalentInclude.int_list.Contains(item.Id)) { continue; } var count = 0; for(int j = 0; j < talentTypeCount.Count;j++) { if (talentTypeCount[j].key == talent.talentType) { talentTypeCount[j].value += 1; count = 1; break; } } if(count == 0) { talentTypeCount.Add(new KV { key = talent.talentType, value = 1 }); } } talentTypeCount.Sort((a, b) => b.value - a.value); var maxType = talentTypeCount[0].key; List weightList = new List(); var t = config.talentList[0]; if(t.typeList.TryGetValue(maxType, out var typeList)) { RewardWeightItem rw = new RewardWeightItem(); rw.key = maxType; rw.weight = t.max; rw.list = new List(); rw.list.AddRange(typeList); weightList.Add(rw); } foreach (var item in t.typeList) { var otherType = item.Key; if (otherType == maxType) { continue; } RewardWeightItem rw = new RewardWeightItem(); rw.key = otherType; rw.weight = t.other; rw.list = new List(); rw.list.AddRange(item.Value); weightList.Add(rw); } int allWeight = 0; for(int i = 0; i < weightList.Count; i++) { allWeight += weightList[i].weight; } int r = GameServerUtils.GetGameServerData().m_app.Rand.Next(allWeight); allWeight = 0; for (int i = 0; i < weightList.Count; i++) { allWeight += weightList[i].weight; if (r < allWeight) { foreach (var item1 in weightList[i].list) { list.AddRange(ParseReward(player, item1)); } break; } } break; } } list = MergeReward(list); if (apply) { list = ApplyGiveReward(player, list, sendGetMsg); } return list; } return new List(); }catch(Exception e) { TraceLog.Error("Reward {0} error {1}, player = {2}", rewardId, e.Message, player.UserID); GameServerUtils.GetApp().Alerter.AlertException(e); return new List(); } } private static List RewardTimesResetByMaxValue(PlayerOnGame player, RewardDesc config) { ref var rdata = ref player.DropRateData.RewardData; for(int i = 0;i < rdata.TimesItems.Count; i++) { if (rdata.TimesItems.Get(i).Code.Equals(config.id)) { ref var it =ref rdata.TimesItems[i]; return RewardTimesResetByMaxValue2(player, config, ref it); } } RewardTimesItem item = new RewardTimesItem(); item.Code.SetString(config.id); item.Times = 0; rdata.TimesItems.Add(ref item); TraceLog.Trace("reward {0} add", item.Times); return RewardTimesResetByMaxValue(player, config); } private static List RewardTimesResetByMaxValue2(PlayerOnGame player, RewardDesc config, ref RewardTimesItem it) { int count = ++it.Times ; int max = 0; List resList = new List(); for (int i = 0; i < config.rangeList.Count; i++) { var item = config.rangeList[i]; max = Math.Max(max, item.rangeMax); if (count >= item.rangeMin && count < item.rangeMax) { foreach (var item1 in item.list) { resList.AddRange(ParseReward(player, item1)); } //TraceLog.Trace("reward {0} {1} drop {2}", count, it.Times, resList.Count); break; } } if (count >= max) { it.Times = 0;//再来一次 return RewardTimesResetByMaxValue2(player, config, ref it); } return resList; } private static List RewardOnce(PlayerOnGame player, RewardDesc config) { List resList = new List(); int allWeight = 0; var weightList = new List(); foreach (var item in config.weightList) { RewardWeightItem rli = new RewardWeightItem(); rli.key = item.key; rli.list = item.list; if (item.key.Contains("+X")) {//TODO 取得身上某个属性的值 var lucky = player.knight.props.GetPropFinal(PropertyDef.Luck) / 10_000; var add = lucky *1.0F/(lucky + CommParamDescMgr.Instance.LuckRwdInc.int_list[0] / 10_000) * CommParamDescMgr.Instance.LuckRwdInc.int_list[1] / 10_000; rli.weight = (int)(int.Parse(item.key.Replace("+X", "")) + add); } else { rli.weight = int.Parse(item.key); } weightList.Add(rli); allWeight += rli.weight; } int rand = GameServerUtils.GetGameServerData().m_app.Rand.Next(allWeight); int tr = 0; for (int i = 0; i < weightList.Count; i++) { var it = weightList[i]; tr += it.weight; if (rand < tr) { foreach (var item in it.list) { resList.AddRange(ParseReward(player, item)); } break; } } return resList; } private static List RewardArray(PlayerOnGame player, RewardDesc config) { ref DBRoleRewardData rewardData = ref player.DropRateData.RewardData; for (int i = 0; i < rewardData.ArrayItems.Count; i++) { if (rewardData.ArrayItems[i].Code.Equals(config.id)) { ref var arrayItem_ = ref rewardData.ArrayItems[i]; if (arrayItem_.NowIdx < arrayItem_.Count) { return RewardArray2(player, ref arrayItem_); } rewardData.ArrayItems.RemoveAt(i); break; } } int allWeight = 0; var weightList = new List(); foreach (var item in config.weightList) { RewardWeightItem rli = new RewardWeightItem(); rli.key = item.key; rli.list = item.list; if (item.key.Contains("+X")) {//TODO 取得身上某个属性的值 var lucky = player.knight.props.GetPropFinal(PropertyDef.Luck) / 10_000; var add = lucky * 1.0F / (lucky + CommParamDescMgr.Instance.LuckRwdInc.int_list[0] / 10_000) * CommParamDescMgr.Instance.LuckRwdInc.int_list[1] / 10_000; rli.weight = (int)(int.Parse(item.key.Replace("+X", "")) + add); } else { rli.weight = int.Parse(item.key); } weightList.Add(rli); allWeight += rli.weight; } GenericUtils.Shuffle(GameServerUtils.GetGameServerData().m_app.Rand, weightList); RewardArrayItem arrayItem = new RewardArrayItem(); arrayItem.Code.SetString(config.id); arrayItem.NowIdx = 0; for (int i = 0; i < weightList.Count; i++) { RewardWeightItem rli = weightList[i]; ProtoCSStruct.RewardWeightItem rli2 = new ProtoCSStruct.RewardWeightItem(); rli2.Weight = rli.weight; arrayItem.Count += rli.weight; for (int j = 0; j < rli.list.Count; j++) { var item = rli.list[j]; ProtoCSStruct.RewardItem item1 = new ProtoCSStruct.RewardItem(); item1.Type = item.type; item1.Code.SetString(item.code); item1.Amount = item.amount; item1.Repeat = item.repeat; rli2.List.Add(ref item1); } arrayItem.Items.Add(ref rli2); } rewardData.ArrayItems.Add(ref arrayItem); return RewardArray(player, config); } private static List RewardGroupArray(PlayerOnGame player, RewardDesc config) { ref DBRoleRewardData rewardData = ref player.DropRateData.RewardData; for (int i = 0; i < rewardData.GroupArrayItems.Count; i++) { if (rewardData.GroupArrayItems[i].Code.Equals(config.id)) { ref var arrayItem_ = ref rewardData.GroupArrayItems[i]; if (arrayItem_.NowIdx < arrayItem_.Count) { return RewardGroupArray2(player, ref arrayItem_); } rewardData.GroupArrayItems.RemoveAt(i); break; } } int allWeight = 0; var weightList = new List(); foreach (var item in config.weightList) { RewardWeightItem rli = new RewardWeightItem(); rli.key = item.key; rli.list = item.list; if (item.key.Contains("+X")) {//TODO 取得身上某个属性的值 var lucky = player.knight.props.GetPropFinal(PropertyDef.Luck) / 10_000; var add = lucky * 1.0F / (lucky + CommParamDescMgr.Instance.LuckRwdInc.int_list[0] / 10_000) * CommParamDescMgr.Instance.LuckRwdInc.int_list[1] / 10_000; rli.weight = (int)(int.Parse(item.key.Replace("+X", "")) + add); } else { rli.weight = int.Parse(item.key); } weightList.Add(rli); allWeight += rli.weight; } GenericUtils.Shuffle(GameServerUtils.GetGameServerData().m_app.Rand, weightList); RewardArrayItem arrayItem = new RewardArrayItem(); arrayItem.Code.SetString(config.id); arrayItem.NowIdx = 0; for (int i = 0; i < weightList.Count; i++) { RewardWeightItem rli = weightList[i]; ProtoCSStruct.RewardWeightItem rli2 = new ProtoCSStruct.RewardWeightItem(); rli2.Weight = rli.weight; arrayItem.Count += rli2.Weight; for (int j = 0; j < rli.list.Count; j++) { var item = rli.list[j]; ProtoCSStruct.RewardItem item1 = new ProtoCSStruct.RewardItem(); item1.Type = item.type; item1.Code.SetString(item.code); item1.Amount = item.amount; item1.Repeat = item.repeat; rli2.List.Add(ref item1); } arrayItem.Items.Add(ref rli2); } rewardData.GroupArrayItems.Add(ref arrayItem); return RewardGroupArray(player, config); } private static List RewardArray2(PlayerOnGame player, ref RewardArrayItem item) { int ri = GameServerUtils.GetGameServerData().m_app.Rand.Next(item.Count - item.NowIdx); List resList = new List(); int c = 0; for (int i = 0; i < item.Items.Count; i++) { ref var it = ref item.Items[i]; if(it.Weight == 0) { continue; } c += it.Weight; if(ri < c) { item.NowIdx++; it.Weight--; for(int j = 0; j < it.List.Count; j++) { var item1 = it.List[j]; resList.AddRange(ParseReward(player, new RewardItem(item1.Type, item1.Code.GetString(), item1.Amount, item1.Repeat))); } break; } } return resList; } private static List RewardGroupArray2(PlayerOnGame player, ref RewardArrayItem item) { List resList = new List(); int c = 0; for (int i = 0; i < item.Items.Count; i++) { ref var it = ref item.Items[i]; c += it.Weight; if (item.NowIdx < c) { item.NowIdx++; for (int j = 0; j < it.List.Count; j++) { var item1 = it.List[j]; resList.AddRange(ParseReward(player, new RewardItem(item1.Type, item1.Code.GetString(), item1.Amount, item1.Repeat))); } break; } } return resList; } private static List ParseReward(PlayerOnGame player, RewardItem item) { List list = new List (); switch (item.type) { case 9://link { if (String.IsNullOrEmpty(item.code))//为空,不处理 { break; } if (item.amount > 0) {//发两个RewardA,只走一次RewardA的发奖逻辑,但是奖励*2 var l = Reward(player, item.code, false); foreach (var item1 in l) { item1.amount *= item.amount; list.Add(item1); } }else if(item.repeat > 0) {//发2个RewardA,走2次RewardA的发奖逻辑 for (int j = 0; j < item.repeat; j++) { var l = Reward(player, item.code, false); list.AddRange(l); } } break; } default: { list.Add(new RewardItemRW(item)); break; } } return list; } public static List MergeReward(List list) { //相同type和code的合并 List res = new List(); foreach (var item in list) { bool find = false; foreach (var item1 in res) { if (item1.type == item.type && item1.code.Equals(item.code)) { item1.amount += item.amount; find = true; break; } } if (!find && item.IsValid()) { res.Add(item); } }; return res; } public static List ApplyGiveReward(PlayerOnGame player, List list, bool sendGetMsg = false, string reason = "") { if(reason == "") { reason = BillChangeItemReason.Reward; } List res = new List (); UnifyOp op = new UnifyOp(player, reason); int c = 0; foreach (var item in list) { var gd = (GoodsType)item.type; if( gd != GoodsType.None && gd != GoodsType.Size && gd != GoodsType.Props) { op.AddGoods(item.type, item.code, item.amount); res.Add(item); c++; if(c % 60 == 0) { op.DoOp(true, true, sendGetMsg); c = 0; } } } if(c > 0) { op.DoOp(true, true, sendGetMsg); } return res; } } public class KV { public string key; public int value; } }