You've already forked taptap2024_GJ_chidouren
init
This commit is contained in:
13
Assets/Scripts/System/RandomPool/CardQuality.cs
Normal file
13
Assets/Scripts/System/RandomPool/CardQuality.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace System.RandomPool
|
||||
{
|
||||
[Serializable]
|
||||
public enum CardQuality
|
||||
{
|
||||
N = 0,
|
||||
R,
|
||||
SR,
|
||||
SSR,
|
||||
UR,
|
||||
SP
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/System/RandomPool/CardQuality.cs.meta
Normal file
3
Assets/Scripts/System/RandomPool/CardQuality.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a00056319b674b658ff5612096aa3820
|
||||
timeCreated: 1694858873
|
||||
19
Assets/Scripts/System/RandomPool/CommonNoneObject.cs
Normal file
19
Assets/Scripts/System/RandomPool/CommonNoneObject.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace Game.Data.CustomGroup
|
||||
{
|
||||
[Serializable]
|
||||
public class CommonNoneObject
|
||||
{
|
||||
public object Value;
|
||||
|
||||
public CommonNoneObject(object value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public CommonNoneObject()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31f1a9057c244d5b96c568142385aecf
|
||||
timeCreated: 1649521283
|
||||
88
Assets/Scripts/System/RandomPool/CommonPoolConfig.cs
Normal file
88
Assets/Scripts/System/RandomPool/CommonPoolConfig.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
using System.RandomPool;
|
||||
using FJson.Core;
|
||||
using UnityEngine;
|
||||
using Views;
|
||||
|
||||
namespace Game.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// 基于此配置表扩展该通用随机池
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class CommonPoolConfig<T> where T : class
|
||||
{
|
||||
internal Dictionary<int, List<RandomNode<T>>> poolContents;
|
||||
internal Dictionary<int, int> poolLevelWeight;
|
||||
|
||||
public CommonPoolConfig ()
|
||||
{
|
||||
this.poolContents = new Dictionary<int, List<RandomNode<T>>> ();
|
||||
this.poolLevelWeight = new Dictionary<int, int> ();
|
||||
}
|
||||
|
||||
public CommonPoolConfig (Dictionary<int, List<RandomNode<T>>> poolContents, Dictionary<int, int> poolLevelWeight)
|
||||
{
|
||||
this.poolContents = poolContents;
|
||||
this.poolLevelWeight = poolLevelWeight;
|
||||
}
|
||||
|
||||
public void PutPools (int level, RandomNode<T> node)
|
||||
{
|
||||
if (this.poolContents.ContainsKey (level))
|
||||
{
|
||||
this.poolContents[level].Add (node);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.poolContents[level] = new List<RandomNode<T>> () { node };
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual CommonRandomGroup<T> CreateGroup (int poolId)
|
||||
{
|
||||
return new CommonRandomGroup<T> (poolId);
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// 用于创建怪物池对应配置表
|
||||
// /// </summary>
|
||||
// /// <param name="poolRow"></param>
|
||||
// /// <returns></returns>
|
||||
// public static CommonPoolConfig<RofEnemyRow> CreateEnemyPoolConfig(RofEnemyPoolRow poolRow)
|
||||
// {
|
||||
// var poolConfig = new CommonPoolConfig<RofEnemyRow>();
|
||||
// var poolValue = KeywordUtils.DecodeRangeNum(poolRow.EnemyIDs);
|
||||
// if (!string.IsNullOrWhiteSpace(poolValue))
|
||||
// {
|
||||
// poolValue = poolValue.Replace(" ", "");
|
||||
// var enemyIds = poolValue.Split(',');
|
||||
//
|
||||
// foreach (var enemyId in enemyIds)
|
||||
// {
|
||||
// if (int.TryParse(enemyId, out var id))
|
||||
// {
|
||||
// var rofEnemyRow = EnemyManager.Instance.GetEnemy(id);
|
||||
// var level = (ItemQuality) rofEnemyRow.quality;
|
||||
// RandomNode<RofEnemyRow> node = new RandomNode<RofEnemyRow>(rofEnemyRow.ID, rofEnemyRow,
|
||||
// -1, rofEnemyRow.weight, rofEnemyRow.exploreCondition);
|
||||
// poolConfig.PutPools(level, node);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (poolConfig.poolContents.ContainsKey(ItemQuality.Normal))
|
||||
// poolConfig.poolLevelWeight[ItemQuality.Normal] = poolRow.NormalWeight;
|
||||
// if (poolConfig.poolContents.ContainsKey(ItemQuality.Rare))
|
||||
// poolConfig.poolLevelWeight[ItemQuality.Rare] = poolRow.RareWeight;
|
||||
// if (poolConfig.poolContents.ContainsKey(ItemQuality.Epic))
|
||||
// poolConfig.poolLevelWeight[ItemQuality.Epic] = poolRow.EpicWeight;
|
||||
// if (poolConfig.poolContents.ContainsKey(ItemQuality.Legend))
|
||||
// poolConfig.poolLevelWeight[ItemQuality.Legend] = poolRow.LegendWeight;
|
||||
// if (poolConfig.poolContents.ContainsKey(ItemQuality.Hide))
|
||||
// poolConfig.poolLevelWeight[ItemQuality.Hide] = poolRow.HideWeight;
|
||||
// return poolConfig;
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05fdcfdaf9544e0d8908119713e89d46
|
||||
timeCreated: 1633771120
|
||||
227
Assets/Scripts/System/RandomPool/CommonRandomGroup.cs
Normal file
227
Assets/Scripts/System/RandomPool/CommonRandomGroup.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.RandomPool;
|
||||
|
||||
namespace Game.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// 通用随机池单元组,用于最终产生随机节点
|
||||
/// </summary>
|
||||
public class CommonRandomGroup<T> where T : class
|
||||
{
|
||||
private int _poolId;
|
||||
private int _weightMax;
|
||||
private readonly List<RandomNode<T>> _item;
|
||||
private int _curWeightSum; //当前的总权重
|
||||
private int _curConditionMask; //当前条件阈值 ,必须大于此值
|
||||
public int ValidRofCount { get; private set; }
|
||||
|
||||
public CommonRandomGroup(int poolId)
|
||||
{
|
||||
this._poolId = poolId;
|
||||
this._item = new List<RandomNode<T>>();
|
||||
this._weightMax = 0;
|
||||
this._curWeightSum = 0;
|
||||
this._curConditionMask = -1;
|
||||
this.ValidRofCount = -2;
|
||||
}
|
||||
|
||||
public bool SetMask(int exploreCount, IList<int> disableKeys = null , object customMask = null)
|
||||
{
|
||||
this.ValidRofCount = 0;
|
||||
this._curWeightSum = 0;
|
||||
var isSet = false;
|
||||
|
||||
for (int i = 0; i < this._item.Count; i++)
|
||||
{
|
||||
var node = this._item[i];
|
||||
|
||||
if (disableKeys != null && disableKeys.Contains(node.key))
|
||||
{
|
||||
node.curWeight = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
var isBound = this.IsBound(node, exploreCount);
|
||||
if (!isBound)
|
||||
{
|
||||
node.curWeight = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.OnCustomMask(node , customMask))
|
||||
{
|
||||
node.curWeight = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
isSet = true;
|
||||
this._curWeightSum += node.weight;
|
||||
node.curWeight = this._curWeightSum;
|
||||
this.ValidRofCount += 1;
|
||||
}
|
||||
|
||||
this._curConditionMask = exploreCount;
|
||||
return isSet;
|
||||
}
|
||||
|
||||
protected virtual bool OnCustomMask(RandomNode<T> node, object customMask)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsBound(RandomNode<T> node, int maskCount)
|
||||
{
|
||||
if (!node.IsValid(RandomLogController.GetPoolLog(this._poolId, node.key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (maskCount == -1)
|
||||
return true;
|
||||
if (node.weight <= 0)
|
||||
return false;
|
||||
if (node.maxRange == -1 && node.minRange == -1)
|
||||
return true;
|
||||
|
||||
if (node.minRange == -1)
|
||||
{
|
||||
return maskCount <= node.maxRange;
|
||||
}
|
||||
|
||||
if (node.maxRange == -1)
|
||||
{
|
||||
return maskCount >= node.minRange;
|
||||
}
|
||||
|
||||
return maskCount >= node.minRange && maskCount <= node.maxRange;
|
||||
}
|
||||
|
||||
public void PutItem(RandomNode<T> node)
|
||||
{
|
||||
//此处后续可增加数量限制判断
|
||||
this._weightMax += node.weight;
|
||||
this._item.Add(node);
|
||||
}
|
||||
|
||||
public void PullItem(int node)
|
||||
{
|
||||
for (int i = 0; i < _item.Count; i++)
|
||||
{
|
||||
var randomNode = _item[i];
|
||||
if (randomNode.key == node)
|
||||
{
|
||||
RandomLogController.PoolPullLog (this._poolId , node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveItem(int node)
|
||||
{
|
||||
for (int i = 0; i < _item.Count; i++)
|
||||
{
|
||||
var randomNode = _item[i];
|
||||
if (randomNode.key == node)
|
||||
{
|
||||
_item.RemoveAt(i);
|
||||
_weightMax -= randomNode.weight;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal RandomNode<T> GetItem(int id)
|
||||
{
|
||||
for (int i = 0; i < this._item.Count; i++)
|
||||
{
|
||||
var node = this._item[i];
|
||||
if (id == node.key)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public float GetItemRate(int id)
|
||||
{
|
||||
var f = 0f;
|
||||
var item = this.GetItem(id);
|
||||
if (item != null)
|
||||
{
|
||||
if (item.curWeight != -1)
|
||||
{
|
||||
f = item.weight / (this._weightMax * 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public T RandomItem(int poolId, int seedId)
|
||||
{
|
||||
if (this._item.Count == 0 || ValidRofCount == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
RandomNode<T> item = null;
|
||||
var p = RandomUtils.RandomFloat () * this._curWeightSum;
|
||||
for (int i = 0; i < this._item.Count; i++)
|
||||
{
|
||||
var randomNode = this._item[i];
|
||||
if (p <= randomNode.curWeight)
|
||||
{
|
||||
item = randomNode;
|
||||
RandomLogController.PoolPushLog(poolId, item.key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return item?.value;
|
||||
}
|
||||
|
||||
public RandomNode<T> RandomNode(int poolId, int seedId)
|
||||
{
|
||||
if (this._item.Count == 0 || ValidRofCount == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
RandomNode<T> item = null;
|
||||
var p = RandomUtils.RandomFloat () * this._curWeightSum;
|
||||
for (int i = 0; i < this._item.Count; i++)
|
||||
{
|
||||
var randomNode = this._item[i];
|
||||
if (p <= randomNode.curWeight)
|
||||
{
|
||||
item = randomNode;
|
||||
RandomLogController.PoolPushLog(poolId, item.key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static bool IsPush(int poolId, int id, int maskCount)
|
||||
{
|
||||
return RandomLogController.IsPush(poolId, id, maskCount);
|
||||
}
|
||||
|
||||
public void ResetItemWeight(int id, int weight)
|
||||
{
|
||||
for (int i = 0; i < this._item.Count; i++)
|
||||
{
|
||||
var randomNode = this._item[i];
|
||||
if (randomNode.key == id)
|
||||
{
|
||||
this._weightMax -= randomNode.weight;
|
||||
randomNode.weight = weight;
|
||||
this._weightMax += randomNode.weight;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d946aa8658147658a1b2eca11f78117
|
||||
timeCreated: 1633769414
|
||||
409
Assets/Scripts/System/RandomPool/CommonRandomPool.cs
Normal file
409
Assets/Scripts/System/RandomPool/CommonRandomPool.cs
Normal file
@@ -0,0 +1,409 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.RandomPool;
|
||||
using Game;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// 通用随机池,基于权重随机
|
||||
/// </summary>
|
||||
public class CommonRandomPool<T> where T : class
|
||||
{
|
||||
protected Dictionary<int, CommonRandomGroup<T>> _randomGroups;
|
||||
protected LevelRandom _levelRandom;
|
||||
protected int _poolId;
|
||||
protected int _seedId;
|
||||
public LevelRandom LevelRandom => this._levelRandom;
|
||||
|
||||
public int ValidRofCount
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var randomGroupsValue in _randomGroups.Values)
|
||||
{
|
||||
count += randomGroupsValue.ValidRofCount;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public CommonRandomPool(CommonPoolConfig<T> config, int poolId, int seedId)
|
||||
{
|
||||
this._poolId = poolId;
|
||||
this._seedId = seedId;
|
||||
this._randomGroups = new Dictionary<int, CommonRandomGroup<T>>();
|
||||
foreach (var contentsKey in config.poolContents.Keys)
|
||||
{
|
||||
var nodes = config.poolContents[contentsKey];
|
||||
CommonRandomGroup<T> randomGroup = config.CreateGroup(this._poolId);
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
randomGroup.PutItem(node);
|
||||
}
|
||||
this._randomGroups[contentsKey] = randomGroup;
|
||||
}
|
||||
|
||||
foreach (var groupsValue in this._randomGroups.Values)
|
||||
{
|
||||
groupsValue?.SetMask(-1);
|
||||
}
|
||||
this._levelRandom = new LevelRandom(config.poolLevelWeight , new List<int>(this._randomGroups.Keys));
|
||||
}
|
||||
|
||||
public void PutNode(RandomNode<T> node , int quality)
|
||||
{
|
||||
if (_randomGroups.ContainsKey(quality))
|
||||
{
|
||||
var commonRandomGroup = _randomGroups[quality];
|
||||
commonRandomGroup.PutItem(node);
|
||||
commonRandomGroup.SetMask(-1);
|
||||
}
|
||||
}
|
||||
|
||||
public RandomNode<T> GetNode(int key , int quality)
|
||||
{
|
||||
if (_randomGroups.ContainsKey(quality))
|
||||
{
|
||||
var commonRandomGroup = _randomGroups[quality];
|
||||
return commonRandomGroup.GetItem(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ResetNodeWeight(int quality ,int key , int weight)
|
||||
{
|
||||
if (this._randomGroups.TryGetValue (quality, out var commonRandomGroup))
|
||||
{
|
||||
commonRandomGroup.ResetItemWeight (key , weight);
|
||||
commonRandomGroup.SetMask (-1);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetQualityWeight(int quality , int weight)
|
||||
{
|
||||
this._levelRandom.SetWeight (quality , weight);
|
||||
}
|
||||
|
||||
public void PutNodes(List<RandomNode<T>> nodes , int quality)
|
||||
{
|
||||
if (this._randomGroups.TryGetValue (quality, out var commonRandomGroup))
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
commonRandomGroup.PutItem(node);
|
||||
}
|
||||
commonRandomGroup.SetMask(-1);
|
||||
}
|
||||
}
|
||||
|
||||
//回收随机节点
|
||||
public void PullNode(int key , int quality)
|
||||
{
|
||||
if (_randomGroups.ContainsKey(quality))
|
||||
{
|
||||
var commonRandomGroup = _randomGroups[quality];
|
||||
commonRandomGroup.PullItem(key);
|
||||
commonRandomGroup.SetMask(-1);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveNode(int key , int quality)
|
||||
{
|
||||
if (_randomGroups.ContainsKey(quality))
|
||||
{
|
||||
var commonRandomGroup = _randomGroups[quality];
|
||||
commonRandomGroup.RemoveItem(key);
|
||||
commonRandomGroup.SetMask(-1);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveNode(int key)
|
||||
{
|
||||
foreach (int itemQuality in Enum.GetValues(typeof(int)))
|
||||
{
|
||||
RemoveNode(key , itemQuality);
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> RandomItems(int maskCount, int count, bool isSign = false , object customMask = null )
|
||||
{
|
||||
List<T> nodes = new List<T>();
|
||||
List<int> disableList = new List<int>();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = this.RandomNode(maskCount, disableList , customMask);
|
||||
if (node != null)
|
||||
{
|
||||
nodes.Add(node.value);
|
||||
if (isSign)
|
||||
{
|
||||
disableList.Add(node.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public List<T> RandomItems(int maskCount, int count, bool isSign, IList<int> qualities, IList<int> disableKeys , object customMask = null)
|
||||
{
|
||||
List<T> nodes = new List<T>();
|
||||
List<int> disableList = new List<int>();
|
||||
if (disableKeys != null)
|
||||
{
|
||||
disableList.AddRange(disableKeys);
|
||||
}
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
RandomNode<T> node = null;
|
||||
|
||||
if (qualities?.Count > i)
|
||||
{
|
||||
node = this.RandomNode(maskCount, qualities[i], disableList , customMask);
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
node = this.RandomNode(maskCount, disableList , customMask);
|
||||
}
|
||||
|
||||
if (node != null)
|
||||
{
|
||||
nodes.Add(node.value);
|
||||
if (isSign)
|
||||
{
|
||||
disableList.Add(node.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定稀有度安全随机一个物品,如果指定稀有度没有满足条件,则递减一个稀有度重新随机,直到正确数据出一个物品,也可能会出现所有稀有度都无法满足条件,返回空
|
||||
/// </summary>
|
||||
/// <param name="maskCount"></param>
|
||||
/// <param name="quality"></param>
|
||||
/// <param name="disableKeys"></param>
|
||||
/// <param name="customMask"></param>
|
||||
/// <returns></returns>
|
||||
public T RandomItem(int maskCount, int quality, IList<int> disableKeys = null, object customMask = null)
|
||||
{
|
||||
var maxCount = 10;
|
||||
var levelMasks = new List<int>();
|
||||
foreach (var groupsKey in this._randomGroups.Keys)
|
||||
{
|
||||
if (!this._randomGroups[groupsKey].SetMask(maskCount, disableKeys , customMask))
|
||||
{
|
||||
levelMasks.Add(groupsKey);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = (int)quality; i >= 0; i--)
|
||||
{
|
||||
var level = (int)i;
|
||||
if (!levelMasks.Contains(level) && this._randomGroups.ContainsKey(level) && this._randomGroups[level].ValidRofCount > 0)
|
||||
{
|
||||
while (maxCount-- > 0)
|
||||
{
|
||||
var node = this._randomGroups[level].RandomItem(this._poolId, this._seedId);
|
||||
if (node == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogError($"随机条件不满足 ,poolId:{this._poolId} maskID: {maskCount}");
|
||||
return null;
|
||||
}
|
||||
|
||||
public T RandomItem(int maskCount, IList<int> disableKeys = null, object customMask = null)
|
||||
{
|
||||
var maxCount = 10;
|
||||
var levelMasks = new List<int>();
|
||||
foreach (var groupsKey in this._randomGroups.Keys)
|
||||
{
|
||||
if (!this._randomGroups[groupsKey].SetMask(maskCount, disableKeys , customMask))
|
||||
{
|
||||
levelMasks.Add(groupsKey);
|
||||
}
|
||||
}
|
||||
|
||||
var level = this._levelRandom.RandomItemLevel(this._seedId, levelMasks);
|
||||
if (this._randomGroups.ContainsKey(level) && this._randomGroups[level].ValidRofCount > 0)
|
||||
{
|
||||
while (maxCount-- > 0)
|
||||
{
|
||||
var node = this._randomGroups[level].RandomItem(this._poolId, this._seedId);
|
||||
if (node == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogError($"随机条件不满足 ,poolId:{this._poolId} maskID: {maskCount}");
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 随机一组有效的稀有度数据,用于后续随机
|
||||
/// </summary>
|
||||
/// <param name="count">数据长度</param>
|
||||
/// <param name="maxQuality">最大稀有度限制</param>
|
||||
/// <param name="qualities">期望能出现的稀有度</param>
|
||||
/// <param name="randomGroup"></param>
|
||||
/// <returns></returns>
|
||||
public List<int> CustomRandomQuality(int count,
|
||||
int maxQuality,
|
||||
IList<int> qualities = null , int randomGroup = 0)
|
||||
{
|
||||
List<int> finalQualities = new List<int>();
|
||||
if (qualities != null)
|
||||
{
|
||||
finalQualities.AddRange(qualities);
|
||||
}
|
||||
|
||||
List<int> levelMasks = new List<int>();
|
||||
bool isTr = false;
|
||||
foreach (int value in Enum.GetValues(typeof(int)))
|
||||
{
|
||||
if (isTr)
|
||||
levelMasks.Add(value);
|
||||
else
|
||||
isTr = value == maxQuality;
|
||||
}
|
||||
|
||||
for (int i = finalQualities.Count; i < count; i++)
|
||||
{
|
||||
finalQualities.Add(this.LevelRandom.RandomItemLevel((int) randomGroup, levelMasks));
|
||||
}
|
||||
|
||||
return finalQualities;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 随机一个指定稀有度的节点
|
||||
/// </summary>
|
||||
/// <param name="maskCount"></param>
|
||||
/// <param name="quality"></param>
|
||||
/// <param name="disableKeys"></param>
|
||||
/// <param name="customMask"></param>
|
||||
/// <returns></returns>
|
||||
public RandomNode<T> RandomNode(int maskCount, int quality, IList<int> disableKeys = null , object customMask = null)
|
||||
{
|
||||
if (this._randomGroups.ContainsKey(quality))
|
||||
{
|
||||
if (this._randomGroups[quality].SetMask(maskCount, disableKeys , customMask))
|
||||
{
|
||||
return this._randomGroups[quality].RandomNode(this._poolId, this._seedId);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public RandomNode<T> RandomNode(int maskCount, List<int> qualities, IList<int> disableKeys = null , object customMask = null)
|
||||
{
|
||||
var levelMasks = new List<int>();
|
||||
foreach (var groupsKey in this._randomGroups.Keys)
|
||||
{
|
||||
if (!qualities.Contains(groupsKey) || !this._randomGroups[groupsKey].SetMask(maskCount, disableKeys , customMask))
|
||||
{
|
||||
levelMasks.Add(groupsKey);
|
||||
}
|
||||
}
|
||||
|
||||
var level = this._levelRandom.RandomItemLevel(this._seedId, levelMasks);
|
||||
if (this._randomGroups.ContainsKey(level) && this._randomGroups[level].ValidRofCount > 0)
|
||||
{
|
||||
return this._randomGroups[level].RandomNode(this._poolId, this._seedId);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public RandomNode<T> RandomNode(int maskCount, IList<int> disableKeys = null, object customMask = null)
|
||||
{
|
||||
var maxCount = 10;
|
||||
var levelMasks = new List<int>();
|
||||
foreach (var groupsKey in this._randomGroups.Keys)
|
||||
{
|
||||
if (!this._randomGroups[groupsKey].SetMask(maskCount, disableKeys , customMask))
|
||||
{
|
||||
levelMasks.Add(groupsKey);
|
||||
}
|
||||
}
|
||||
|
||||
var level = this._levelRandom.RandomItemLevel(this._seedId, levelMasks);
|
||||
if (this._randomGroups.ContainsKey(level) && this._randomGroups[level].ValidRofCount > 0)
|
||||
{
|
||||
while (maxCount-- > 0)
|
||||
{
|
||||
var node = this._randomGroups[level].RandomNode(this._poolId, this._seedId);
|
||||
if (node == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogError($"随机条件不满足 ,poolId:{this._poolId} maskID: {maskCount}");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取该随机池中当前指定稀有度下的有效数
|
||||
/// </summary>
|
||||
/// <param name="quality"></param>
|
||||
/// <param name="maskCount"></param>
|
||||
/// <param name="disableKeys"></param>
|
||||
/// <param name="customMask"></param>
|
||||
/// <returns></returns>
|
||||
public int GetPoolValidCount(int quality, int maskCount , IList<int> disableKeys = null, object customMask = null)
|
||||
{
|
||||
if (this._randomGroups.ContainsKey(quality))
|
||||
{
|
||||
if (this._randomGroups[quality].SetMask(maskCount , disableKeys , customMask))
|
||||
{
|
||||
return this._randomGroups[quality].ValidRofCount;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取该随机池中当前总共的有效数
|
||||
/// </summary>
|
||||
/// <param name="maskCount"></param>
|
||||
/// <param name="disableKeys"></param>
|
||||
/// <param name="customMask"></param>
|
||||
/// <returns></returns>
|
||||
public int GetPoolValidCount(int maskCount , IList<int> disableKeys = null, object customMask = null)
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var groupsKey in this._randomGroups.Keys)
|
||||
{
|
||||
var randomGroup = this._randomGroups[groupsKey];
|
||||
if (!randomGroup.SetMask(maskCount, disableKeys , customMask))
|
||||
{
|
||||
count += randomGroup.ValidRofCount;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f4a3f041f964ea298df7f86be3f6380
|
||||
timeCreated: 1633768881
|
||||
111
Assets/Scripts/System/RandomPool/LevelRandom.cs
Normal file
111
Assets/Scripts/System/RandomPool/LevelRandom.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.RandomPool;
|
||||
using FJson;
|
||||
using Framework.Save;
|
||||
// using Framework.Save;
|
||||
using Game.Data;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
/// <summary>
|
||||
/// 稀有度随机
|
||||
/// </summary>
|
||||
public class LevelRandom
|
||||
{
|
||||
private LiteDictionary<int, int> _levelDic;
|
||||
private Dictionary<int, int> _weightDic;
|
||||
private int _weightSum;
|
||||
|
||||
public LevelRandom (Dictionary<int, int> levelDic, IList<int> commonRandomGroups)
|
||||
{
|
||||
this._weightDic = new Dictionary<int, int>();
|
||||
this._levelDic = new LiteDictionary<int, int>();
|
||||
|
||||
foreach (var randomGroup in commonRandomGroups)
|
||||
{
|
||||
if (levelDic.TryGetValue (randomGroup , out var value))
|
||||
{
|
||||
this._levelDic[randomGroup] = value;
|
||||
}
|
||||
}
|
||||
|
||||
this.RefreshWeight();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新总权重
|
||||
/// </summary>
|
||||
private void RefreshWeight()
|
||||
{
|
||||
this._weightDic.Clear();
|
||||
this._weightSum = 0;
|
||||
foreach (var dicKey in this._levelDic.Keys)
|
||||
{
|
||||
this._weightSum += this._levelDic[dicKey];
|
||||
this._weightDic[dicKey] = this._weightSum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置指定等级的中奖比重
|
||||
/// </summary>
|
||||
/// <param name="quality"></param>
|
||||
/// <param name="weight"></param>
|
||||
public void SetWeight(int quality, int weight)
|
||||
{
|
||||
this._levelDic[quality] = weight;
|
||||
this.RefreshWeight();
|
||||
}
|
||||
|
||||
public int RandomItemLevel(int seedId)
|
||||
{
|
||||
var d = RandomUtils.RandomFloat ();
|
||||
var level = 0;
|
||||
foreach (var dicKey in this._weightDic.Keys)
|
||||
{
|
||||
var value = this._weightDic[dicKey];
|
||||
if (d <= value * 1f / this._weightSum)
|
||||
{
|
||||
level = dicKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
public int RandomItemLevel(int seedId , List<int> maskLevel)
|
||||
{
|
||||
var level = 0;
|
||||
if (maskLevel == null || maskLevel.Count == 0)
|
||||
return this.RandomItemLevel(seedId);
|
||||
Dictionary<int, int> tempWeightList = new Dictionary<int, int>();
|
||||
int tempWeightSum = 0;
|
||||
foreach (var itemLevel in this._levelDic.Keys)
|
||||
{
|
||||
if (maskLevel.Contains(itemLevel))
|
||||
continue;
|
||||
tempWeightSum += this._levelDic[itemLevel];
|
||||
tempWeightList[itemLevel] = tempWeightSum;
|
||||
}
|
||||
|
||||
if (tempWeightSum != 0)
|
||||
{
|
||||
var d = RandomUtils.RandomFloat () * tempWeightSum;
|
||||
foreach (var dicKey in tempWeightList.Keys)
|
||||
{
|
||||
var value = tempWeightList[dicKey];
|
||||
if (d <= value)
|
||||
{
|
||||
level = dicKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/System/RandomPool/LevelRandom.cs.meta
Normal file
11
Assets/Scripts/System/RandomPool/LevelRandom.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dabd2f28c18cee74a9b251727db1c0a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/Scripts/System/RandomPool/PoolLogger.meta
Normal file
3
Assets/Scripts/System/RandomPool/PoolLogger.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9ae61360ae242f68446a6dac657ee3a
|
||||
timeCreated: 1717494667
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace System.RandomPool.PoolLogger
|
||||
{
|
||||
public interface IRandomLog
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fe4ac1ddd934f9ba2f4d26557ff865d
|
||||
timeCreated: 1717494684
|
||||
113
Assets/Scripts/System/RandomPool/RandomLogController.cs
Normal file
113
Assets/Scripts/System/RandomPool/RandomLogController.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using FJson;
|
||||
using Framework.Save;
|
||||
using UnityEngine;
|
||||
|
||||
namespace System.RandomPool
|
||||
{
|
||||
internal class RandomLogController
|
||||
{
|
||||
internal class RandomLogData : SinglePersistentData<RandomLogData>
|
||||
{
|
||||
/// <summary>
|
||||
/// 随机池抽取记录
|
||||
/// </summary>
|
||||
public LiteDictionary<int, LiteDictionary<int, int>> LocalPoolLog =
|
||||
new LiteDictionary<int, LiteDictionary<int, int>> ();
|
||||
|
||||
}
|
||||
|
||||
private static RandomLogData _data;
|
||||
|
||||
internal static RandomLogData Data
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_data == null)
|
||||
{
|
||||
_data = new RandomLogData();
|
||||
if (!_data.Load ())
|
||||
{
|
||||
_data.LocalPoolLog = new LiteDictionary<int, LiteDictionary<int, int>> ();
|
||||
}
|
||||
}
|
||||
return _data;
|
||||
}
|
||||
}
|
||||
|
||||
internal static LiteDictionary<int, LiteDictionary<int, int>> LocalPoolLog => Data.LocalPoolLog;
|
||||
|
||||
/// <summary>
|
||||
/// 从随机池中取出
|
||||
/// </summary>
|
||||
/// <param name="poolId"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
internal static int PoolPushLog (int poolId, int id)
|
||||
{
|
||||
if (!LocalPoolLog.ContainsKey (poolId))
|
||||
{
|
||||
LocalPoolLog[poolId] = new LiteDictionary<int, int> ();
|
||||
}
|
||||
|
||||
if (LocalPoolLog[poolId].ContainsKey (id))
|
||||
{
|
||||
LocalPoolLog[poolId][id] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LocalPoolLog[poolId][id] = 1;
|
||||
}
|
||||
Data.Save ();
|
||||
Debug.Log ($"随机池记录增加 : 池id: {poolId} 物品ID: {id}, 数量: {LocalPoolLog[poolId][id]}");
|
||||
return LocalPoolLog[poolId][id];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收到随机池中
|
||||
/// </summary>
|
||||
/// <param name="poolId"></param>
|
||||
/// <param name="id"></param>
|
||||
internal static void PoolPullLog (int poolId, int id)
|
||||
{
|
||||
if (LocalPoolLog.ContainsKey (poolId) && LocalPoolLog[poolId].ContainsKey (id))
|
||||
{
|
||||
LocalPoolLog[poolId][id] -= 1;
|
||||
Debug.Log ($"随机池记录减少 : 池id: {poolId} 物品ID: {id} , 数量: {LocalPoolLog[poolId][id]}");
|
||||
}
|
||||
}
|
||||
|
||||
internal static int GetPoolLog (int poolId, int id)
|
||||
{
|
||||
if (!LocalPoolLog.ContainsKey (poolId))
|
||||
{
|
||||
LocalPoolLog[poolId] = new LiteDictionary<int, int> ();
|
||||
}
|
||||
|
||||
if (!LocalPoolLog[poolId].ContainsKey (id))
|
||||
{
|
||||
LocalPoolLog[poolId][id] = 0;
|
||||
}
|
||||
|
||||
return LocalPoolLog[poolId][id];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于判断是否还可以继续取出指定id
|
||||
/// </summary>
|
||||
/// <param name="poolId"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="maskCount"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsPush (int poolId, int id, int maskCount)
|
||||
{
|
||||
if (maskCount == -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var i = GetPoolLog (poolId, id);
|
||||
return i != -1 && i < maskCount;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0efde2709a1b42aca02954a2ed20f688
|
||||
timeCreated: 1717142563
|
||||
54
Assets/Scripts/System/RandomPool/RandomNode.cs
Normal file
54
Assets/Scripts/System/RandomPool/RandomNode.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// 通用随机单元
|
||||
/// </summary>
|
||||
public class RandomNode<T> where T : class
|
||||
{
|
||||
public int key; // 承载key
|
||||
public T value; // 承载内容
|
||||
public int count; // 最大数量
|
||||
public int weight; // 随机权重
|
||||
public int minRange; //至少抽取次数阈值
|
||||
public int maxRange; //至多抽取次数阈值
|
||||
|
||||
public int curWeight; //当前的权重值,用于权重随机中的值比较。
|
||||
|
||||
public RandomNode(int key, T value, int count, int weight, int minRange, int maxRange)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.count = count;
|
||||
this.weight = weight;
|
||||
this.minRange = minRange;
|
||||
this.maxRange = maxRange;
|
||||
}
|
||||
|
||||
public RandomNode(int key, T value, int count, int weight, string range)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.count = count;
|
||||
this.weight = weight;
|
||||
if (range.Equals("-1", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
this.minRange = -1;
|
||||
this.maxRange = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
var rs = range.Split(',');
|
||||
this.minRange = int.Parse(rs[0]);
|
||||
this.maxRange = int.Parse(rs.Length == 2 ? rs[1] : rs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid(int nowCount)
|
||||
{
|
||||
return this.count == -1 || nowCount < this.count;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/System/RandomPool/RandomNode.cs.meta
Normal file
3
Assets/Scripts/System/RandomPool/RandomNode.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec18fb4e926e4fbebdee8dd4df47c86a
|
||||
timeCreated: 1633768902
|
||||
47
Assets/Scripts/System/RandomPool/RandomUtils.cs
Normal file
47
Assets/Scripts/System/RandomPool/RandomUtils.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace System.RandomPool
|
||||
{
|
||||
public static class RandomUtils
|
||||
{
|
||||
public static float RandomFloat ()
|
||||
{
|
||||
return 1 - UnityEngine.Random.Range (0 , 1f);
|
||||
}
|
||||
|
||||
public static bool HasRandom (float rota)
|
||||
{
|
||||
if (rota <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rota >= 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return RandomFloat () <= rota;
|
||||
}
|
||||
|
||||
public static int RandomInt (int min, int max)
|
||||
{
|
||||
return UnityEngine.Random.Range (min, max);
|
||||
}
|
||||
|
||||
public static float RandomFloat (float min, float max)
|
||||
{
|
||||
return UnityEngine.Random.Range (min, max);
|
||||
}
|
||||
|
||||
public static int Range (int randomCountX, int randomCountY)
|
||||
{
|
||||
return RandomInt (randomCountX, randomCountY);
|
||||
}
|
||||
|
||||
public static float RandomFormVector (Vector2 range)
|
||||
{
|
||||
return RandomFloat (range.x, range.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/System/RandomPool/RandomUtils.cs.meta
Normal file
3
Assets/Scripts/System/RandomPool/RandomUtils.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02c4973fa8f146b7a465eb2966fdfb00
|
||||
timeCreated: 1690191117
|
||||
76
Assets/Scripts/System/RandomPool/WeightRandomPool.cs
Normal file
76
Assets/Scripts/System/RandomPool/WeightRandomPool.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic;
|
||||
using Game;
|
||||
using Game.Data;
|
||||
|
||||
namespace System.RandomPool
|
||||
{
|
||||
public class WeightRandomPool
|
||||
{
|
||||
private class WeightCommonRandomPool : CommonRandomPool<WeightNode>
|
||||
{
|
||||
public WeightCommonRandomPool (CommonPoolConfig<WeightNode> config, int poolId, int seedId) : base (config, poolId, seedId)
|
||||
{
|
||||
config.poolContents = new Dictionary<int, List<RandomNode<WeightNode>>> ();
|
||||
config.poolContents[0] = new List<RandomNode<WeightNode>> ();
|
||||
config.poolLevelWeight = new Dictionary<int, int> ();
|
||||
config.poolLevelWeight[0] = 100;
|
||||
|
||||
this._poolId = poolId;
|
||||
this._seedId = seedId;
|
||||
this._randomGroups = new Dictionary<int, CommonRandomGroup<WeightNode>>();
|
||||
CommonRandomGroup<WeightNode> randomGroup = new CommonRandomGroup<WeightNode> (poolId);
|
||||
this._randomGroups[0] = randomGroup;
|
||||
this._randomGroups[0].SetMask(-1);
|
||||
|
||||
this._levelRandom = new LevelRandom(config.poolLevelWeight , new List<int>(this._randomGroups.Keys));
|
||||
}
|
||||
}
|
||||
|
||||
public class WeightNode
|
||||
{
|
||||
public int Id;
|
||||
public int Weight;
|
||||
}
|
||||
|
||||
private WeightCommonRandomPool _weightCommonRandomPool;
|
||||
|
||||
public int ValidRofCount => this._weightCommonRandomPool.ValidRofCount;
|
||||
|
||||
public WeightRandomPool ()
|
||||
{
|
||||
CommonPoolConfig<WeightNode> config = new CommonPoolConfig<WeightNode> ();
|
||||
config.poolLevelWeight = new Dictionary<int, int> ();
|
||||
this._weightCommonRandomPool = new WeightCommonRandomPool (config , 0 , 0);
|
||||
}
|
||||
|
||||
public void PutNode (int id , int weight , int minRange = -1, int maxRange = -1)
|
||||
{
|
||||
this._weightCommonRandomPool.PutNode (new RandomNode<WeightNode> (id , new WeightNode () { Id = id, Weight = weight } , -1 , weight ,
|
||||
minRange , maxRange) , 0);
|
||||
}
|
||||
|
||||
public void ResetNode (int id , int weight)
|
||||
{
|
||||
this._weightCommonRandomPool.ResetNodeWeight (0 ,id , weight);
|
||||
}
|
||||
|
||||
|
||||
public int RandomNode (IList<int> disableKeys = null)
|
||||
{
|
||||
return this._weightCommonRandomPool.RandomItem (-1 , 0 , disableKeys)?.Id ?? -1;
|
||||
}
|
||||
|
||||
public List<int> RandomNodes (int count , IList<int> disableKeys = null , bool isSin = false , int mask = -1)
|
||||
{
|
||||
List<int> ids = new List<int> ();
|
||||
var randomItems = this._weightCommonRandomPool.RandomItems (mask , count, isSin , null , disableKeys);
|
||||
for (var index = 0; index < randomItems.Count; index++)
|
||||
{
|
||||
var randomItem = randomItems[index];
|
||||
ids.Add (randomItem.Id);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 808899a02f2a49edb7f421d962788633
|
||||
timeCreated: 1701151822
|
||||
Reference in New Issue
Block a user