mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-13 15:34:36 +01:00
implement interception rewards, random item boxes
This commit is contained in:
@@ -178,6 +178,10 @@ namespace EpinelPS.Data
|
|||||||
|
|
||||||
[LoadRecord("ConditionRewardTable.json", "id", typeof(ConditionRewardTable))]
|
[LoadRecord("ConditionRewardTable.json", "id", typeof(ConditionRewardTable))]
|
||||||
public readonly Dictionary<int, ConditionRewardRecord> ConditionRewards = [];
|
public readonly Dictionary<int, ConditionRewardRecord> ConditionRewards = [];
|
||||||
|
[LoadRecord("ItemConsumeTable.json", "id", typeof(ItemConsumeTable))]
|
||||||
|
public readonly Dictionary<int, ItemConsumeRecord> ConsumableItems = [];
|
||||||
|
[LoadRecord("ItemRandomTable.json", "id", typeof(RandomItemTable))]
|
||||||
|
public readonly Dictionary<int, RandomItemRecord> RandomItem = [];
|
||||||
static async Task<GameData> BuildAsync()
|
static async Task<GameData> BuildAsync()
|
||||||
{
|
{
|
||||||
await Load();
|
await Load();
|
||||||
|
|||||||
@@ -794,5 +794,41 @@
|
|||||||
{
|
{
|
||||||
public List<ConditionRewardRecord> records = [];
|
public List<ConditionRewardRecord> records = [];
|
||||||
}
|
}
|
||||||
|
public enum ItemSubType
|
||||||
|
{
|
||||||
|
BundleBox,
|
||||||
|
ItemRandomBoxList,
|
||||||
|
ItemRandomBoxNormal,
|
||||||
|
TimeReward,
|
||||||
|
Box,
|
||||||
|
ProfileRandomBox,
|
||||||
|
ArcadeItem,
|
||||||
|
EquipCombination
|
||||||
|
}
|
||||||
|
public class ItemConsumeRecord
|
||||||
|
{
|
||||||
|
public int id;
|
||||||
|
public string use_type = "";
|
||||||
|
public string item_type = "";
|
||||||
|
public ItemSubType item_sub_type;
|
||||||
|
public int use_id;
|
||||||
|
}
|
||||||
|
public class ItemConsumeTable
|
||||||
|
{
|
||||||
|
public List<ItemConsumeRecord> records = [];
|
||||||
|
}
|
||||||
|
public class RandomItemRecord
|
||||||
|
{
|
||||||
|
public int id;
|
||||||
|
public int group_id;
|
||||||
|
public string reward_type = "";
|
||||||
|
public int reward_id;
|
||||||
|
public int reward_value_min;
|
||||||
|
public int reward_value_max;
|
||||||
|
public int ratio;
|
||||||
|
}
|
||||||
|
public class RandomItemTable
|
||||||
|
{
|
||||||
|
public List<RandomItemRecord> records = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
EpinelPS/LobbyServer/Inventory/UseRandomBox.cs
Normal file
32
EpinelPS/LobbyServer/Inventory/UseRandomBox.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using EpinelPS.Database;
|
||||||
|
using EpinelPS.Utils;
|
||||||
|
|
||||||
|
namespace EpinelPS.LobbyServer.Inventory
|
||||||
|
{
|
||||||
|
[PacketPath("/inventory/userandombox")]
|
||||||
|
public class UseRandomBox : LobbyMsgHandler
|
||||||
|
{
|
||||||
|
protected override async Task HandleAsync()
|
||||||
|
{
|
||||||
|
var req = await ReadData<ReqUseRandomBox>();
|
||||||
|
var user = GetUser();
|
||||||
|
|
||||||
|
var response = new ResUseRandomBox();
|
||||||
|
|
||||||
|
var box = user.Items.Where(x => x.Isn == req.Isn).FirstOrDefault() ?? throw new InvalidDataException("cannot find box with isn " + req.Isn);
|
||||||
|
if (req.Count > box.Count) throw new Exception("count mismatch");
|
||||||
|
|
||||||
|
box.Count -= req.Count;
|
||||||
|
if (box.Count == 0) user.Items.Remove(box);
|
||||||
|
|
||||||
|
response.Reward = NetUtils.UseLootBox(user, box.ItemType, req.Count);
|
||||||
|
|
||||||
|
// update client side box count
|
||||||
|
response.Reward.UserItems.Add(NetUtils.UserItemDataToNet(box));
|
||||||
|
|
||||||
|
JsonDb.Save();
|
||||||
|
|
||||||
|
await WriteDataAsync(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
using EpinelPS.Database;
|
using System.Collections;
|
||||||
using EpinelPS.Data;
|
|
||||||
using Google.Protobuf.WellKnownTypes;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using EpinelPS.Data;
|
||||||
|
using EpinelPS.Database;
|
||||||
|
using Google.Protobuf.WellKnownTypes;
|
||||||
using static Google.Rpc.Context.AttributeContext.Types;
|
using static Google.Rpc.Context.AttributeContext.Types;
|
||||||
|
|
||||||
namespace EpinelPS.Utils
|
namespace EpinelPS.Utils
|
||||||
@@ -43,6 +44,22 @@ namespace EpinelPS.Utils
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static NetUserItemData UserItemDataToNet(ItemData item)
|
||||||
|
{
|
||||||
|
return new NetUserItemData()
|
||||||
|
{
|
||||||
|
Count = item.Count,
|
||||||
|
Tid = item.ItemType,
|
||||||
|
Csn = item.Csn,
|
||||||
|
Lv = item.Level,
|
||||||
|
Exp = item.Exp,
|
||||||
|
Corporation = item.Corp,
|
||||||
|
Isn = item.Isn,
|
||||||
|
Position = item.Position
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<NetUserItemData> GetUserItems(User user)
|
public static List<NetUserItemData> GetUserItems(User user)
|
||||||
{
|
{
|
||||||
List<NetUserItemData> ret = new();
|
List<NetUserItemData> ret = new();
|
||||||
@@ -58,33 +75,12 @@ namespace EpinelPS.Utils
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
itemDictionary[item.ItemType] = new NetUserItemData()
|
itemDictionary[item.ItemType] = UserItemDataToNet(item);
|
||||||
{
|
|
||||||
Count = item.Count,
|
|
||||||
Tid = item.ItemType,
|
|
||||||
Csn = item.Csn,
|
|
||||||
Lv = item.Level,
|
|
||||||
Exp = item.Exp,
|
|
||||||
Corporation = item.Corp,
|
|
||||||
Isn = item.Isn,
|
|
||||||
Position = item.Position
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var newItem = new NetUserItemData()
|
itemDictionary[item.ItemType] = UserItemDataToNet(item);
|
||||||
{
|
|
||||||
Count = item.Count,
|
|
||||||
Tid = item.ItemType,
|
|
||||||
Csn = item.Csn,
|
|
||||||
Lv = item.Level,
|
|
||||||
Exp = item.Exp,
|
|
||||||
Corporation = item.Corp,
|
|
||||||
Isn = item.Isn,
|
|
||||||
Position = item.Position
|
|
||||||
};
|
|
||||||
itemDictionary[item.ItemType] = newItem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,5 +371,33 @@ namespace EpinelPS.Utils
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static NetRewardData UseLootBox(User user, int boxId, int count)
|
||||||
|
{
|
||||||
|
ItemConsumeRecord? cItem = GameData.Instance.ConsumableItems.Where(x => x.Value.id == boxId).FirstOrDefault().Value ?? throw new Exception("cannot find box id " + boxId);
|
||||||
|
|
||||||
|
if (cItem.use_type != "ItemRandomBox") throw new Exception("expected random box");
|
||||||
|
|
||||||
|
// find matching probability entries
|
||||||
|
var probabilityEntries = GameData.Instance.RandomItem.Values.Where(x => x.group_id == cItem.use_id).ToArray();
|
||||||
|
if (!probabilityEntries.Any()) throw new Exception($"cannot find any probability entries with ID {cItem.use_id}, box ID: {cItem.id}");
|
||||||
|
|
||||||
|
// run probability as many times as needed
|
||||||
|
NetRewardData ret = new() { PassPoint = new() };
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var winningRecord = Rng.PickWeightedItem(probabilityEntries);
|
||||||
|
|
||||||
|
if (winningRecord.reward_value_min != winningRecord.reward_value_max)
|
||||||
|
{
|
||||||
|
Logging.WriteLine("TODO: reward_value_max", LogType.Warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
RewardUtils.AddSingleObject(user, ref ret, winningRecord.reward_id, winningRecord.reward_type, winningRecord.reward_value_min);
|
||||||
|
}
|
||||||
|
JsonDb.Save();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using EpinelPS.Database;
|
|
||||||
using EpinelPS.Data;
|
using EpinelPS.Data;
|
||||||
|
using EpinelPS.Database;
|
||||||
|
using Org.BouncyCastle.Ocsp;
|
||||||
|
|
||||||
namespace EpinelPS.Utils
|
namespace EpinelPS.Utils
|
||||||
{
|
{
|
||||||
@@ -56,12 +57,12 @@ namespace EpinelPS.Utils
|
|||||||
BeforeExp = user.userPointData.ExperiencePoint,
|
BeforeExp = user.userPointData.ExperiencePoint,
|
||||||
BeforeLv = user.userPointData.UserLevel,
|
BeforeLv = user.userPointData.UserLevel,
|
||||||
|
|
||||||
// IncreaseExp = rewardData.user_exp,
|
// IncreaseExp = rewardData.user_exp,
|
||||||
CurrentExp = newXp,
|
CurrentExp = newXp,
|
||||||
CurrentLv = newLevel,
|
CurrentLv = newLevel,
|
||||||
|
|
||||||
GainExp = rewardData.user_exp,
|
GainExp = rewardData.user_exp,
|
||||||
|
|
||||||
};
|
};
|
||||||
user.userPointData.ExperiencePoint = newXp;
|
user.userPointData.ExperiencePoint = newXp;
|
||||||
|
|
||||||
@@ -70,126 +71,167 @@ namespace EpinelPS.Utils
|
|||||||
|
|
||||||
foreach (var item in rewardData.rewards)
|
foreach (var item in rewardData.rewards)
|
||||||
{
|
{
|
||||||
if (item.reward_id != 0 || !string.IsNullOrEmpty(item.reward_type))
|
if (item.reward_percent != 1000000)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(item.reward_type) || string.IsNullOrWhiteSpace(item.reward_type)) { }
|
Logging.WriteLine("WARNING: ignoring percent: " + item.reward_percent / 10000 + ", item will be added anyways", LogType.Warning);
|
||||||
else if (item.reward_type == "Currency")
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
foreach (var currentReward in user.Currency)
|
|
||||||
{
|
|
||||||
if (currentReward.Key == (CurrencyType)item.reward_id)
|
|
||||||
{
|
|
||||||
user.Currency[currentReward.Key] += item.reward_value;
|
|
||||||
|
|
||||||
ret.Currency.Add(new NetCurrencyData()
|
|
||||||
{
|
|
||||||
FinalValue = user.Currency[currentReward.Key],
|
|
||||||
Value = item.reward_value,
|
|
||||||
Type = item.reward_id
|
|
||||||
});
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
user.Currency.Add((CurrencyType)item.reward_id, item.reward_value);
|
|
||||||
ret.Currency.Add(new NetCurrencyData()
|
|
||||||
{
|
|
||||||
FinalValue = item.reward_value,
|
|
||||||
Value = item.reward_value,
|
|
||||||
Type = item.reward_id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (item.reward_type == "Item")
|
|
||||||
{
|
|
||||||
// Check if user already has said item. If it is level 1, increase item count.
|
|
||||||
// If user does not have item, generate a new item ID
|
|
||||||
if (user.Items.Where(x => x.ItemType == item.reward_id && x.Level == 1).Any())
|
|
||||||
{
|
|
||||||
ItemData? newItem = user.Items.Where(x => x.ItemType == item.reward_id && x.Level == 1).FirstOrDefault();
|
|
||||||
if (newItem != null)
|
|
||||||
{
|
|
||||||
newItem.Count += item.reward_value;
|
|
||||||
|
|
||||||
// Tell the client the reward and its amount
|
|
||||||
ret.Item.Add(new NetItemData()
|
|
||||||
{
|
|
||||||
Count = item.reward_value,
|
|
||||||
Tid = item.reward_id,
|
|
||||||
//Isn = newItem.Isn
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tell the client the new amount of this item
|
|
||||||
ret.UserItems.Add(new NetUserItemData()
|
|
||||||
{
|
|
||||||
Isn = newItem.Isn,
|
|
||||||
Tid = newItem.ItemType,
|
|
||||||
Count = newItem.Count
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("should not occur");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
var id = user.GenerateUniqueItemId();
|
|
||||||
user.Items.Add(new ItemData() { ItemType = item.reward_id, Isn = id, Level = 1, Exp = 0, Count = item.reward_value });
|
|
||||||
ret.Item.Add(new NetItemData()
|
|
||||||
{
|
|
||||||
Count = item.reward_value,
|
|
||||||
Tid = item.reward_id,
|
|
||||||
//Isn = id
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tell the client the new amount of this item (which is the same as user did not have item previously)
|
|
||||||
ret.UserItems.Add(new NetUserItemData()
|
|
||||||
{
|
|
||||||
Isn = id,
|
|
||||||
Tid = item.reward_id,
|
|
||||||
Count = item.reward_value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (item.reward_type == "Memorial")
|
|
||||||
{
|
|
||||||
if (!user.Memorial.Contains(item.reward_id))
|
|
||||||
{
|
|
||||||
ret.Memorial.Add(item.reward_id);
|
|
||||||
user.Memorial.Add(item.reward_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (item.reward_type == "Bgm")
|
|
||||||
{
|
|
||||||
if (!user.JukeboxBgm.Contains(item.reward_id))
|
|
||||||
{
|
|
||||||
ret.JukeboxBgm.Add(item.reward_id);
|
|
||||||
user.JukeboxBgm.Add(item.reward_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (item.reward_type == "InfraCoreExp")
|
|
||||||
{
|
|
||||||
ret.InfraCoreExp = new NetIncreaseExpData()
|
|
||||||
{
|
|
||||||
BeforeLv = user.InfraCoreLvl,
|
|
||||||
BeforeExp = user.InfraCoreExp,
|
|
||||||
// TODO
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine("TODO: Reward type " + item.reward_type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddSingleObject(user, ref ret, item.reward_id, item.reward_type, item.reward_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a single item to users inventory, and also adds it to ret parameter.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
/// <param name="ret"></param>
|
||||||
|
/// <param name="rewardId"></param>
|
||||||
|
/// <param name="rewardType"></param>
|
||||||
|
/// <param name="rewardCount"></param>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public static void AddSingleObject(User user, ref NetRewardData ret, int rewardId, string rewardType, int rewardCount)
|
||||||
|
{
|
||||||
|
if (rewardId != 0 || !string.IsNullOrEmpty(rewardType))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(rewardType) || string.IsNullOrWhiteSpace(rewardType)) { }
|
||||||
|
else if (rewardType == "Currency")
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
foreach (var currentReward in user.Currency)
|
||||||
|
{
|
||||||
|
if (currentReward.Key == (CurrencyType)rewardId)
|
||||||
|
{
|
||||||
|
user.Currency[currentReward.Key] += rewardCount;
|
||||||
|
|
||||||
|
ret.Currency.Add(new NetCurrencyData()
|
||||||
|
{
|
||||||
|
FinalValue = user.Currency[currentReward.Key],
|
||||||
|
Value = rewardCount,
|
||||||
|
Type = rewardId
|
||||||
|
});
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
user.Currency.Add((CurrencyType)rewardId, rewardCount);
|
||||||
|
ret.Currency.Add(new NetCurrencyData()
|
||||||
|
{
|
||||||
|
FinalValue = rewardCount,
|
||||||
|
Value = rewardCount,
|
||||||
|
Type = rewardId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rewardType == "Item")
|
||||||
|
{
|
||||||
|
// Check if user already has said item. If it is level 1, increase item count.
|
||||||
|
// If user does not have item, generate a new item ID
|
||||||
|
if (user.Items.Where(x => x.ItemType == rewardId && x.Level == 1).Any())
|
||||||
|
{
|
||||||
|
ItemData? newItem = user.Items.Where(x => x.ItemType == rewardId && x.Level == 1).FirstOrDefault();
|
||||||
|
if (newItem != null)
|
||||||
|
{
|
||||||
|
newItem.Count += rewardCount;
|
||||||
|
|
||||||
|
// Tell the client the reward and its amount
|
||||||
|
ret.Item.Add(new NetItemData()
|
||||||
|
{
|
||||||
|
Count = rewardCount,
|
||||||
|
Tid = rewardId,
|
||||||
|
//Isn = newItem.Isn
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tell the client the new amount of this item
|
||||||
|
ret.UserItems.Add(new NetUserItemData()
|
||||||
|
{
|
||||||
|
Isn = newItem.Isn,
|
||||||
|
Tid = newItem.ItemType,
|
||||||
|
Count = newItem.Count
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("should not occur");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
var id = user.GenerateUniqueItemId();
|
||||||
|
user.Items.Add(new ItemData() { ItemType = rewardId, Isn = id, Level = 1, Exp = 0, Count = rewardCount });
|
||||||
|
ret.Item.Add(new NetItemData()
|
||||||
|
{
|
||||||
|
Count = rewardCount,
|
||||||
|
Tid = rewardId,
|
||||||
|
//Isn = id
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tell the client the new amount of this item (which is the same as user did not have item previously)
|
||||||
|
ret.UserItems.Add(new NetUserItemData()
|
||||||
|
{
|
||||||
|
Isn = id,
|
||||||
|
Tid = rewardId,
|
||||||
|
Count = rewardCount
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rewardType == "Memorial")
|
||||||
|
{
|
||||||
|
if (!user.Memorial.Contains(rewardId))
|
||||||
|
{
|
||||||
|
ret.Memorial.Add(rewardId);
|
||||||
|
user.Memorial.Add(rewardId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rewardType == "Bgm")
|
||||||
|
{
|
||||||
|
if (!user.JukeboxBgm.Contains(rewardId))
|
||||||
|
{
|
||||||
|
ret.JukeboxBgm.Add(rewardId);
|
||||||
|
user.JukeboxBgm.Add(rewardId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rewardType == "InfraCoreExp")
|
||||||
|
{
|
||||||
|
ret.InfraCoreExp = new NetIncreaseExpData()
|
||||||
|
{
|
||||||
|
BeforeLv = user.InfraCoreLvl,
|
||||||
|
BeforeExp = user.InfraCoreExp,
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (rewardType == "ItemRandomBox")
|
||||||
|
{
|
||||||
|
ItemConsumeRecord? cItem = GameData.Instance.ConsumableItems.Where(x => x.Value.id == rewardId).FirstOrDefault().Value;
|
||||||
|
|
||||||
|
if (cItem.item_sub_type == ItemSubType.ItemRandomBoxList)
|
||||||
|
{
|
||||||
|
NetRewardData reward = NetUtils.UseLootBox(user, rewardId, rewardCount);
|
||||||
|
|
||||||
|
NetUtils.RegisterRewardsForUser(user, reward);
|
||||||
|
ret = NetUtils.MergeRewards([ret, reward], user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var itm = new NetItemData()
|
||||||
|
{
|
||||||
|
Count = rewardCount,
|
||||||
|
Tid = cItem.id,
|
||||||
|
Isn = user.GenerateUniqueItemId()
|
||||||
|
};
|
||||||
|
ret.Item.Add(itm);
|
||||||
|
user.Items.Add(new ItemData() { Count = rewardCount, Isn = itm.Isn, ItemType = itm.Tid });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logging.WriteLine("TODO: Reward type " + rewardType, LogType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace EpinelPS.Utils
|
using EpinelPS.Data;
|
||||||
|
|
||||||
|
namespace EpinelPS.Utils
|
||||||
{
|
{
|
||||||
public class Rng
|
public class Rng
|
||||||
{
|
{
|
||||||
@@ -14,6 +16,30 @@
|
|||||||
public static int RandomId()
|
public static int RandomId()
|
||||||
{
|
{
|
||||||
return random.Next();
|
return random.Next();
|
||||||
|
} /// <summary>
|
||||||
|
/// Picks a random item. weights is a list of numbers which represents probability, table ids represent ID for weight
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="weights"></param>
|
||||||
|
/// <param name="tableIds"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public static RandomItemRecord PickWeightedItem(RandomItemRecord[] records)
|
||||||
|
{
|
||||||
|
int totalWeight = 0;
|
||||||
|
foreach (var item in records)
|
||||||
|
totalWeight += item.ratio;
|
||||||
|
|
||||||
|
int randomNumber = random.Next(0, totalWeight);
|
||||||
|
|
||||||
|
int runningSum = 0;
|
||||||
|
for (int i = 0; i < records.Length; i++)
|
||||||
|
{
|
||||||
|
runningSum += records[i].ratio;
|
||||||
|
if (randomNumber < runningSum)
|
||||||
|
return records[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Weight distribution error.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user