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.
 
 
 
 
 
 

610 lines
26 KiB

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
{
/// <summary>
/// 计算rewarid可与获得的reward,apply为true表示给于
/// </summary>
/// <param name="player"></param>
/// <param name="rewardId"></param>
/// <returns></returns>
public static List<RewardItemRW> Reward(PlayerOnGame player, string rewardId, bool apply = true, bool sendGetMsg = false)
{
try
{
var config = RewardDescMgr.Instance.GetConfig(rewardId);
if (config != null)
{
List<RewardItemRW> list = new List<RewardItemRW>();
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<KV>( );
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<RewardWeightItem> weightList = new List<RewardWeightItem>();
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<RewardItem>();
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<RewardItem>();
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<RewardItemRW>();
}catch(Exception e)
{
TraceLog.Error("Reward {0} error {1}, player = {2}", rewardId, e.Message, player.UserID);
GameServerUtils.GetApp().Alerter.AlertException(e);
return new List<RewardItemRW>();
}
}
private static List<RewardItemRW> 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<RewardItemRW> RewardTimesResetByMaxValue2(PlayerOnGame player, RewardDesc config, ref RewardTimesItem it)
{
int count = ++it.Times ;
int max = 0;
List<RewardItemRW> resList = new List<RewardItemRW>();
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<RewardItemRW> RewardOnce(PlayerOnGame player, RewardDesc config)
{
List<RewardItemRW> resList = new List<RewardItemRW>();
int allWeight = 0;
var weightList = new List<RewardWeightItem>();
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<RewardItemRW> 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<RewardWeightItem>();
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<RewardItemRW> 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<RewardWeightItem>();
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<RewardItemRW> RewardArray2(PlayerOnGame player, ref RewardArrayItem item)
{
int ri = GameServerUtils.GetGameServerData().m_app.Rand.Next(item.Count - item.NowIdx);
List <RewardItemRW> resList = new List<RewardItemRW>();
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<RewardItemRW> RewardGroupArray2(PlayerOnGame player, ref RewardArrayItem item)
{
List<RewardItemRW> resList = new List<RewardItemRW>();
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<RewardItemRW> ParseReward(PlayerOnGame player, RewardItem item)
{
List <RewardItemRW> list = new List <RewardItemRW>();
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<RewardItemRW> MergeReward(List<RewardItemRW> list)
{
//相同type和code的合并
List<RewardItemRW> res = new List<RewardItemRW>();
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<RewardItemRW> ApplyGiveReward(PlayerOnGame player, List<RewardItemRW> list, bool sendGetMsg = false,
string reason = "")
{
if(reason == "")
{
reason = BillChangeItemReason.Reward;
}
List<RewardItemRW> res = new List<RewardItemRW> ();
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;
}
}