机制代码

录入:EvilP 作者: 翻译:
录入时间:2025-10-26 03:17:06 最后修改时间:2025-11-12 20:50:38
报错页面:传送门

Mirage - 海市蜃楼复制英雄

private static TransferSide GenTransferSideByMirage(WorldHero _hero, Party _party, bool _locatedInAlliedAreas, int _extraStat)
{
	TransferHero transferHero = new TransferHero
	{
		configId = _hero.data.configSid,
		mana = _hero.data.mana,
		manaMax = _hero.currentStats.GetMaxManaPoints(),
		heroMagics = _hero.logic.allMagics,
		heroStat = new HeroStat(),
		heroBonuses = _hero.logic.bonuses,
		level = _hero.data.currentLevel,
		exp = _hero.data.currentExp,
		dataEnergies = _hero.data.dataEnergies,
		expTolevel = _hero.logic.exp.GetMaxGradeForLevel(_hero.data.currentLevel),
		nativeBiome = _hero.logic.data.config.nativeBiome
	};
	transferHero.heroStat.Copy(_hero.currentStats);
	HeroStat heroStat = new HeroStat();
	if (_extraStat == -1)
	{
		_extraStat = _hero.data.currentLevel;
	}
	heroStat.defence += _extraStat;
	heroStat.offence += _extraStat;
	heroStat.spellPower += _extraStat;
	heroStat.intelligence += _extraStat;
	transferHero.heroStat.Plus(heroStat);
	transferHero.manaMax = transferHero.heroStat.GetMaxManaPoints();
	transferHero.mana = transferHero.heroStat.GetMaxManaPoints();
	TransferUnit[] array = new TransferUnit[_hero.data.party.units.Count];
	for (int i = 0; i < array.Length; i++)
	{
		Hex.Session.Data.Unit unit = _party.data.units[i];
		TransferUnit transferUnit = new TransferUnit(unit.sid, unit.stacks, unit.slotPos);
		array[i] = transferUnit;
	}
	TransferSide transferSide = new TransferSide(-1, TransferSide.EType.Type_Hero, TransferSide.EControlType.AI, array, _hero.side.logic.bonuses, -1, -1, _locatedInAlliedAreas, allowMagicInAutobattle: true, null, TransferSideName.GetForMirage());
	transferSide.hero = transferHero;
	transferSide.SortUnitsBySlotPos();
	return transferSide;
}
public void UpdateParty(DataParty _heroParty, ObjMirageConfig _config)
{
	dataParty.units.Clear();
	int num = _config.extraValue / _heroParty.units.Count;
	for (int i = 0; i < _heroParty.units.Count; i++)
	{
		Unit unit = _heroParty.units[i];
		UnitLogicConfig unitLogicConfig = DB.me.unitLogics.Get(unit.sid);
		int num2 = num / unitLogicConfig.squadValue;
		Unit item = new Unit
		{
			sid = unit.sid,
			stacks = (int)((float)(unit.stacks + num2) * (1f + _config.squadMultiply)),
			slotPos = unit.slotPos
		};
		dataParty.units.Add(item);
	}
}

Chimerologist - 嵌合学家转化

public void Convertation(WorldHero _hero)
{
	hero = _hero;
	if (CanConvert())
	{
		int summaValue = GetSummaValue();
		ResNameAndCost[] costResArray = config.costResArray;
		foreach (ResNameAndCost resNameAndCost in costResArray)
		{
			hero.side.res.Subtract(resNameAndCost.name, resNameAndCost.cost);
		}
		UnitLogicConfig unitsWithRandom = UnitsSearchUtility.GetUnitsWithRandom((UnitLogicConfig x) => x.squadValue <= summaValue, (UnitLogicConfig x) => !blockedSids.Contains(x.sid));
		int stacks = summaValue / unitsWithRandom.squadValue;
		Unit unit = new Unit
		{
			sid = unitsWithRandom.sid,
			stacks = stacks
		};
		EventsDispatcher.me.Invoke(EEvent.QuestUnitLose, new EaUnitLose
		{
			units = party.data.units,
			indexSide = _hero.side.index
		});
		party.Clear();
		party.AddInSlot(unit.sid, unit.stacks, 6);
	}
}

Flee or Fight - 野兵战斗还是逃跑

public static void TryStartBattleVsSquad(WorldHero _hero, WorldSquad _squad)
{
	if (UIGlobalMode.isFilmingMode && _hero.side.isMySide)
	{
		StartBattleVsSquad(_hero, _squad);
		return;
	}
	bool flag = (double)((float)_squad.GetSumValue() / (float)_hero.GetSumValue(_battleVsSquad: true)) <= 0.5;
	bool flag2 = DiplomacyUtility.CanApply(_hero, _squad);
	bool flag3 = _hero.side.ai != null;
	bool isMySide = _hero.side.isMySide;
	if (flag3)
	{
		flag2 = false;
	}
	if (!_squad.data.isEscape)
	{
		flag = false;
		flag2 = false;
	}
	if (flag2)
	{
		if (!flag3 && isMySide)
		{
			BhUIs.me.OpenDiplomacy(_squad, _hero);
		}
	}
	else if (flag)
	{
		if (_hero.side.sideMapCheats.cheatWinFight)
		{
			StartBattleVsSquad(_hero, _squad);
		}
		else if (flag3)
		{
			StartBattleVsSquad(_hero, _squad);
		}
		else if (isMySide)
		{
			BhUIs.me.OpenSquadEscapePanel(_squad, _hero);
		}
	}
	else
	{
		StartBattleVsSquad(_hero, _squad);
	}
}

Diplomacy - 外交

{
	"unitCostExtraCharge": 1.0,
	"squadUnitsPoints": [ 25, 50, 75, 125, 225, 425, 1250 ],
	"reactionTypeModifiers": [ 0, 2.0, 1.0, 0.75, 0.5, 0 ],

	"heroUnitsPoints": [ 9, 13, 21, 31, 44, 64, 150 ],
	"fullUnitsMatchBonus": 1.5,
	"partialUnitsMatchBonus": 0.75,
	"heroStatsModifier": 10,
	"heroLevelModifier": 100,

	"valueChancePairs":
	[
		{ "value": 0.00, "chance": -0.40 },
		{ "value": 0.40, "chance": -0.30 },
		{ "value": 0.60, "chance": -0.20 },
		{ "value": 0.80, "chance": -0.10 },
		{ "value": 1.00, "chance": 	0.00 },
		{ "value": 1.20, "chance": 	0.05 },
		{ "value": 1.40, "chance": 	0.10 }
	]
}

===========================

public static bool CanApply(WorldHero _hero, WorldSquad _squad, out string _info)
{
	bool enableDiplomacy = _hero.currentStats.enableDiplomacy;
	if (_squad.data.isCampaignFreeDiplomacy)
	{
		_info = "\nisCampaignFreeDiplomacy";
		return true;
	}
	if (_squad.data.isCampaingDiplomacy)
	{
		_info = "\nisCampaignDiplomacy";
		return true;
	}
	if (_squad.data.reactionType == ESquadReactionType.Docile)
	{
		_info = "\nDocile reaction type";
		return true;
	}
	if (!enableDiplomacy)
	{
		_info = "\nSkill Diplomacy is not learned";
		return false;
	}
	if (_squad.data.reactionType == ESquadReactionType.Aggressive)
	{
		_info = $"\nThis squad is {_squad.data.reactionType}";
		return false;
	}
	_info = $"\nThis squad is {_squad.data.reactionType}";
	DiplomacyInfoConfig diplomacyInfoConfig = DB.me.diplomacyInfoConfig;
	int squadUnitsPoints = GetSquadUnitsPoints(_hero, _squad, diplomacyInfoConfig);
	int heroUnitsPoints = GetHeroUnitsPoints(_hero, _squad, diplomacyInfoConfig);
	bool flag = heroUnitsPoints >= squadUnitsPoints;
	_info = (flag ? "\nYou can take squad units" : "\nYou need more points to take squad units");
	_info += $"\nhero points: {heroUnitsPoints}, squad points: {squadUnitsPoints}";
	return flag;
}

===========================

private static int GetSquadUnitsPoints(WorldHero _hero, WorldSquad _squad, DiplomacyInfoConfig _diplomacyInfoConfig)
{
	float num = CalculateSquadUnitsPoints(_hero, _squad, _diplomacyInfoConfig);
	float modifierForReactionType = _diplomacyInfoConfig.GetModifierForReactionType(_squad.data.reactionType);
	return (int)(num * modifierForReactionType);
}

===========================

private static float CalculateSquadUnitsPoints(WorldHero _hero, WorldSquad _squad, DiplomacyInfoConfig _diplomacyInfoConfig)
{
	float diplomacyFractionPerBonus = _hero.currentStats.diplomacyFractionPerBonus;
	string fraction = _hero.data.config.fraction;
	float num = 0f;
	foreach (DataSquadUnit unit in _squad.data.units)
	{
		float num2 = _diplomacyInfoConfig.GetSquadUnitTierPoint(unit.logicConfig.tier) * unit.amount;
		if (string.Equals(unit.logicConfig.fraction, fraction))
		{
			num2 *= 1f + diplomacyFractionPerBonus;
		}
		num += num2;
	}
	return num;
}

===========================

private static int GetHeroUnitsPoints(WorldHero _hero, WorldSquad _squad, DiplomacyInfoConfig _diplomacyInfoConfig)
{
	float num = CalculateHeroUnitsPoints(_hero, _squad, _diplomacyInfoConfig);
	float num2 = GetSumHeroStats(_hero) * _diplomacyInfoConfig.heroStatsModifier;
	float num3 = (float)_hero.data.currentLevel * _diplomacyInfoConfig.heroLevelModifier;
	float diplomacyEfficiencyPerBonus = _hero.currentStats.diplomacyEfficiencyPerBonus;
	float valueRatio = GetValueRatio(_hero, _squad);
	float chanceForValue = _diplomacyInfoConfig.GetChanceForValue(valueRatio);
	return (int)((num + num2 + num3) * (1f + diplomacyEfficiencyPerBonus) * (1f + chanceForValue));
}

===========================


private static float GetValueRatio(WorldHero _hero, WorldSquad _squad)
{
	int sumValue = _hero.GetSumValue(_battleVsSquad: true);
	int sumValue2 = _squad.GetSumValue();
	return (float)sumValue / (float)sumValue2;
}

===========================

public int GetSumValue(bool _battleVsSquad = false)
{
	int tradeValue = GetTradeValue();
	if (!_battleVsSquad)
	{
		return tradeValue;
	}
	return (int)((float)tradeValue * (1f + currentStats.diplomacySumValuePerBonus));
}

public int GetTradeValue()
{
	return data.GetSumValue() + Mathf.RoundToInt((float)GetItemsValue() * 0.1f);
}

public int GetItemsValue()
{
	int num = 0;
	Items items = Hex.Session.Logic.Logic.me.items;
	foreach (KeyValuePair> item2 in slots.itemsByType)
	{
		foreach (int item3 in item2.Value)
		{
			if (item3 >= 0)
			{
				Item item = items.ById(item3);
				num += item.data.config.goodsValue;
			}
		}
	}
	return num;
}

===========================

private static float CalculateHeroUnitsPoints(WorldHero _hero, WorldSquad _squad, DiplomacyInfoConfig _diplomacyInfoConfig)
{
	List units = _hero.party.data.units;
	HashSet uniqueSquadUnits = GetUniqueSquadUnits(_squad);
	float num = 0f;
	foreach (Unit item in units)
	{
		UnitLogicConfig logicConfig = item.logicConfig;
		int heroUnitTierPoint = _diplomacyInfoConfig.GetHeroUnitTierPoint(logicConfig.tier);
		float unitsMatchModifer = GetUnitsMatchModifer(logicConfig, uniqueSquadUnits, _diplomacyInfoConfig);
		float num2 = (float)(heroUnitTierPoint * item.stacks) * (1f + unitsMatchModifer);
		num += num2;
	}
	return num;
}

===========================

private static float GetUnitsMatchModifer(UnitLogicConfig _unit, HashSet _uniqueSquadUnits, DiplomacyInfoConfig _diplomacyInfoConfig)
{
	float num = 0f;
	if (_uniqueSquadUnits.Contains(_unit.sid))
	{
		num += _diplomacyInfoConfig.fullUnitsMatchBonus;
	}
	if (_unit.version == EUnitVersion.Base)
	{
		UnitLogicConfig upgradeVersion = UnitsVersionUtility.GetUpgradeVersion(_unit);
		if (upgradeVersion == null)
		{
			Logger.Error("No upgrade for unit " + _unit.sid);
			return num;
		}
		UnitLogicConfig oppositeUpgradeVersion = UnitsVersionUtility.GetOppositeUpgradeVersion(upgradeVersion);
		if (_uniqueSquadUnits.Contains(upgradeVersion.sid))
		{
			num += _diplomacyInfoConfig.partialUnitsMatchBonus;
		}
		if (uniqueSquadUnitsSet.Contains(oppositeUpgradeVersion.sid))
		{
			num += _diplomacyInfoConfig.partialUnitsMatchBonus;
		}
	}
	else
	{
		UnitLogicConfig baseVersion = UnitsVersionUtility.GetBaseVersion(_unit);
		UnitLogicConfig oppositeUpgradeVersion2 = UnitsVersionUtility.GetOppositeUpgradeVersion(_unit);
		if (_uniqueSquadUnits.Contains(baseVersion.sid))
		{
			num += _diplomacyInfoConfig.partialUnitsMatchBonus;
		}
		if (oppositeUpgradeVersion2 == null)
		{
			Logger.Error("No alt upgrade for unit " + _unit.sid);
			return num;
		}
		if (uniqueSquadUnitsSet.Contains(oppositeUpgradeVersion2.sid))
		{
			num += _diplomacyInfoConfig.partialUnitsMatchBonus;
		}
	}
	return num;
}

===========================

private static float GetSumHeroStats(WorldHero _hero)
{
	HeroStat currentStats = _hero.currentStats;
	return currentStats.offence + currentStats.defence + currentStats.spellPower + currentStats.intelligence;
}

===========================

private static float GetValueRatio(WorldHero _hero, WorldSquad _squad)
{
	int sumValue = _hero.GetSumValue(_battleVsSquad: true);
	int sumValue2 = _squad.GetSumValue();
	return (float)sumValue / (float)sumValue2;
}

===========================

private static HashSet GetUniqueSquadUnits(WorldSquad _squad)
{
	uniqueSquadUnitsSet.Clear();
	foreach (DataSquadUnit unit in _squad.data.units)
	{
		uniqueSquadUnitsSet.Add(unit.sid);
	}
	return uniqueSquadUnitsSet;
}

Get Stacks - 野怪分组原则

private static int GetStacksByValue(int _heroValue, int _squadValue)
{
	float num = (float)_squadValue / (float)_heroValue;
	if (num >= 1.6f)
	{
		return 7;
	}
	if (num >= 1.4f)
	{
		return 6;
	}
	if (num >= 1.2f)
	{
		return 5;
	}
	if (num >= 1f)
	{
		return 4;
	}
	if (num >= 0.8f)
	{
		return 3;
	}
	if (num >= 0.6f)
	{
		return 2;
	}
	return 1;
}

Summoning Rite - 召唤仪式数量算法

public override int EvaluateForAiUnit(ICaster caster, ICastSource castSource, Unit target, BattleAiParams aiParams, HashSet tempCanReachAlly, HashSet history, Dictionary unitsValues)
{
	if (target == null)
	{
		return 0;
	}
	if (target.fieldData.isSummon)
	{
		return 0;
	}
	if (target.transferUnit == null)
	{
		return 0;
	}
	if (caster is Unit unit)
	{
		int num = (int)((float)target.transferUnit.stacks * percent * (float)target.stats.hp / (float)unit.logicConfig.stats.hp);
		if (!unit.stats.ignoreFinalSummonBonus)
		{
			num = Mathf.RoundToInt((float)num * (1f + unit.stats.finalSummonBonusPercent));
		}
		num = Mathf.Min(num, unit.data.allStacks);
		_ = target.stats.hp;
		string[] mechValues = aiParams.GetMechValues(mechType);
		int num2 = ConfigParserUtility.ParseFromStringArray(mechValues, 0, int.Parse, 0);
		float num3 = ConfigParserUtility.ParseFromStringArray(mechValues, 1, ConfigParserUtility.ParseFloat, 0f);
		return num2 + (int)(num3 * (float)num * (float)target.logicConfig.squadValue);
	}
	return 0;
}

Get Sum By Tags - 非攻防修正增减伤算法(10%下限)

public float GetSumByTags(IEnumerable tags, UnitStat unitStat)
{
	float num = 1f;
	foreach (string tag in tags)
	{
		if (!idToPosSumDict.ContainsKey(tag) && !idToNegSumDict.ContainsKey(tag))
		{
			continue;
		}
		float num2 = 1f;
		if (idToPosSumDict.ContainsKey(tag))
		{
			float num3 = idToPosSumDict[tag];
			float num4 = 0f;
			if (unitStat.outDmgMultipliersSet.positiveSums.ContainsKey(tag))
			{
				num4 = unitStat.outDmgMultipliersSet.positiveSums[tag];
			}
			if (num4 < -1f)
			{
				num4 = -1f;
			}
			num2 += num3 * (1f + num4);
		}
		if (idToNegSumDict.ContainsKey(tag))
		{
			float num5 = idToNegSumDict[tag];
			float num6 = 0f;
			if (unitStat.outDmgMultipliersSet.negativeSums.ContainsKey(tag))
			{
				num6 = unitStat.outDmgMultipliersSet.negativeSums[tag];
			}
			if (num6 < -1f)
			{
				num6 = -1f;
			}
			num2 += num5 * (1f + num6);
		}
		num *= num2;
	}
	if (num < 0.1f)
	{
		num = 0.1f;
	}
	return num;
}

Hero Skills Randomizer - 英雄升级技能生成

public class HeroSkillsRandomizer
{
	private struct SkillRollArgs
	{
		public bool isSkillsCountEqualToMax;

		public bool haveAllSkillsMaxLevel;

		public int nonMasterSkillsCount;

		public SkillsRollChances openedSkillsChances;

		public SkillsRollChances defaultSkillsChances;

		public SkillsRollChances reserveSkillsChances;

		public SkillsRollChances pseudoSkillsChances;

		public SkillsRollChances specialSkillsChances;
	}

	private const int reserveSkillsLevel = -1;

	private const int pseudoSkillsLevel = -2;

	private const int skillSlotsCount = 3;

	private Random random;

	private Hero hero;

	private SkillsRollChancesSet defaultSet;

	private SkillsRollChancesSet specialSet;

	private SkillsRollChancesSet replaceSet;

	public void Init(Hero _hero, Random _random)
	{
		hero = _hero;
		random = _random;
		string skillsRollVariant = hero.data.skillsRollVariant;
		SkillsRollChancesConfig skillsRollChancesConfig = DB.Instance().skillRollChancesConfig.Get(skillsRollVariant);
		defaultSet = new SkillsRollChancesSet(skillsRollChancesConfig.defaultList);
		specialSet = new SkillsRollChancesSet(skillsRollChancesConfig.specialList);
		string configSid = hero.data.configSid;
		if (DB.Instance().replaceSkillRollChancesConfig.TryGet(configSid, out var o))
		{
			replaceSet = new SkillsRollChancesSet(o.defaultList);
		}
	}

	public void SetSkillsToPack(SkillsPack _skillsPack, int _currentLevel, bool _refreshAll, bool _applyReplace)
	{
		SkillsRollChances skillsRollChances = CreateOpenedSkillsRollChances();
		SkillsRollChances skillsRollChances2 = defaultSet[_currentLevel];
		SkillsRollChances skillsRollChances3 = defaultSet[-1];
		SkillsRollChances skillsRollChances4 = defaultSet[-2];
		SkillsRollChances skillsRollChances5 = specialSet[_currentLevel];
		ReplaceSkillsChances(skillsRollChances2, _applyReplace, _currentLevel);
		NullifyChancesForOpenedSkills(skillsRollChances2);
		NullifyChancesForOpenedSkills(skillsRollChances3);
		NullifyChancesForOpenedSkills(skillsRollChances5);
		bool isSkillsCountEqualToMax = IsSkillsCountEqualToMax();
		bool haveAllSkillsMaxLevel = HaveAllSkillsMaxLevel();
		int nonMasterSkillsCount = GetNonMasterSkillsCount();
		string[] array = new string[3];
		bool[] array2 = new bool[3];
		if (_refreshAll || _skillsPack.skillSids == null)
		{
			for (int i = 0; i < 3; i++)
			{
				array[i] = null;
				array2[i] = true;
			}
		}
		else
		{
			for (int j = 0; j < 3; j++)
			{
				string text = _skillsPack.skillSids[j];
				if (!IsSkillValidForSlot(text, j, nonMasterSkillsCount, isSkillsCountEqualToMax, haveAllSkillsMaxLevel))
				{
					array[j] = null;
					array2[j] = true;
					continue;
				}
				array[j] = text;
				array2[j] = false;
				NullifyChanceForSkill(skillsRollChances, text);
				NullifyChanceForSkill(skillsRollChances2, text);
				NullifyChanceForSkill(skillsRollChances3, text);
				NullifyChanceForSkill(skillsRollChances4, text);
				NullifyChanceForSkill(skillsRollChances5, text);
			}
		}
		string _sid = array[0];
		string _sid2 = array[1];
		string _sid3 = array[2];
		bool flag = array2[0];
		bool flag2 = array2[1];
		bool num = array2[2];
		SkillRollArgs _skillRollArgs = new SkillRollArgs
		{
			isSkillsCountEqualToMax = isSkillsCountEqualToMax,
			haveAllSkillsMaxLevel = haveAllSkillsMaxLevel,
			nonMasterSkillsCount = nonMasterSkillsCount,
			openedSkillsChances = skillsRollChances,
			defaultSkillsChances = skillsRollChances2,
			reserveSkillsChances = skillsRollChances3,
			pseudoSkillsChances = skillsRollChances4,
			specialSkillsChances = skillsRollChances5
		};
		if (flag)
		{
			SetSkillForFirstSlot(ref _skillRollArgs, out _sid);
		}
		if (num)
		{
			SetSkillForThirdSlot(ref _skillRollArgs, out _sid3);
		}
		if (flag2)
		{
			SetSkillForSecondSlot(ref _skillRollArgs, out _sid2);
		}
		array[0] = _sid;
		array[1] = _sid2;
		array[2] = _sid3;
		skillsRollChances2.ResetToDefault();
		skillsRollChances3.ResetToDefault();
		skillsRollChances4.ResetToDefault();
		skillsRollChances5?.ResetToDefault();
		_skillsPack.Set(array);
	}

	private SkillsRollChances CreateOpenedSkillsRollChances()
	{
		List currentSkills = hero.skills.currentSkills;
		List list = new List();
		foreach (HeroSkill item2 in currentSkills)
		{
			if (item2.level != item2.config.MaxLevel)
			{
				SkillRollChance item = new SkillRollChance(item2.sid, 100);
				list.Add(item);
			}
		}
		return new SkillsRollChances(list);
	}

	private void NullifyChancesForOpenedSkills(SkillsRollChances _rollChances)
	{
		if (_rollChances != null)
		{
			List currentSkills = hero.skills.currentSkills;
			for (int i = 0; i < currentSkills.Count; i++)
			{
				HeroSkill heroSkill = currentSkills[i];
				_rollChances[heroSkill.sid]?.Set(0);
			}
		}
	}

	private void NullifyChanceForSkill(SkillsRollChances _rollChances, string _sid)
	{
		if (_rollChances != null && !string.IsNullOrEmpty(_sid))
		{
			_rollChances[_sid]?.Set(0);
		}
	}

	private void ResetChanceToDefault(SkillsRollChances _rollChances, string _sid)
	{
		if (_rollChances != null && !string.IsNullOrEmpty(_sid))
		{
			_rollChances[_sid]?.ResetToDefault();
		}
	}

	private void ReplaceSkillsChances(SkillsRollChances _rollChances, bool _applyReplace, int _level)
	{
		if (_rollChances == null || !_applyReplace || replaceSet == null)
		{
			return;
		}
		SkillsRollChances skillsRollChances = replaceSet[_level];
		if (skillsRollChances == null)
		{
			return;
		}
		for (int i = 0; i < _rollChances.Length; i++)
		{
			SkillRollChance skillRollChance = _rollChances[i];
			SkillRollChance skillRollChance2 = skillsRollChances[skillRollChance.Sid];
			if (skillRollChance2 != null)
			{
				skillRollChance.Set(skillRollChance2.Chance);
			}
		}
	}

	private bool IsSkillValidForSlot(string _skillSid, int _slotIndex, int _nonMastersSkillsCount, bool _isSkillsCountEqualToMax, bool _haveAllSkillsMaxLevel)
	{
		HeroSkill heroSkill = hero.skills.BySid(_skillSid);
		SkillConfig skillConfig = DB.me.skills.Get(_skillSid);
		bool isPseudoSkill = skillConfig.isPseudoSkill;
		bool isNewSkill = heroSkill == null;
		int skillLevel = heroSkill?.level ?? (-1);
		int maxLevel = skillConfig.MaxLevel;
		return _slotIndex switch
		{
			0 => IsSkillValidForFirstSlot(isNewSkill, isPseudoSkill, skillLevel, maxLevel, _nonMastersSkillsCount, _isSkillsCountEqualToMax, _haveAllSkillsMaxLevel), 
			1 => IsSkillValidForSecondSlot(isNewSkill, isPseudoSkill, skillLevel, maxLevel, _nonMastersSkillsCount, _isSkillsCountEqualToMax, _haveAllSkillsMaxLevel), 
			2 => IsSkillValidForThirdSlot(isNewSkill, isPseudoSkill, skillLevel, maxLevel, _nonMastersSkillsCount, _isSkillsCountEqualToMax, _haveAllSkillsMaxLevel), 
			_ => false, 
		};
	}

	private bool IsSkillValidForFirstSlot(bool _isNewSkill, bool _isPseudoSkill, int _skillLevel, int _skillMaxLevel, int _nonMastersSkillsCount, bool _isSkillsCountEqualToMax, bool _haveAllSkillsMaxLevel)
	{
		if (!_isSkillsCountEqualToMax)
		{
			return _isNewSkill;
		}
		if (!_haveAllSkillsMaxLevel && _nonMastersSkillsCount >= 3)
		{
			if (!_isNewSkill)
			{
				return _skillLevel < _skillMaxLevel;
			}
			return false;
		}
		return _isPseudoSkill;
	}

	private bool IsSkillValidForSecondSlot(bool _isNewSkill, bool _isPseudoSkill, int _skillLevel, int _skillMaxLevel, int _nonMastersSkillsCount, bool _isSkillsCountEqualToMax, bool _haveAllSkillsMaxLevel)
	{
		if (!_isSkillsCountEqualToMax)
		{
			if (_nonMastersSkillsCount >= 2)
			{
				if (!_isNewSkill)
				{
					return _skillLevel < _skillMaxLevel;
				}
				return true;
			}
			return _isNewSkill;
		}
		if (!_haveAllSkillsMaxLevel && _nonMastersSkillsCount >= 2)
		{
			if (!_isNewSkill)
			{
				return _skillLevel < _skillMaxLevel;
			}
			return false;
		}
		return _isPseudoSkill;
	}

	private bool IsSkillValidForThirdSlot(bool _isNewSkill, bool _isPseudoSkill, int _skillLevel, int _skillMaxLevel, int _nonMastersSkillsCount, bool _isSkillsCountEqualToMax, bool _haveAllSkillsMaxLevel)
	{
		if (!_haveAllSkillsMaxLevel)
		{
			if (!_isNewSkill)
			{
				return _skillLevel < _skillMaxLevel;
			}
			return false;
		}
		if (!_isSkillsCountEqualToMax)
		{
			return _isNewSkill;
		}
		return _isPseudoSkill;
	}

	private void SetSkillForFirstSlot(ref SkillRollArgs _skillRollArgs, out string _sid)
	{
		_sid = string.Empty;
		bool isSkillsCountEqualToMax = _skillRollArgs.isSkillsCountEqualToMax;
		bool haveAllSkillsMaxLevel = _skillRollArgs.haveAllSkillsMaxLevel;
		int nonMasterSkillsCount = _skillRollArgs.nonMasterSkillsCount;
		if (!isSkillsCountEqualToMax)
		{
			_sid = GetNewSkill(_skillRollArgs.defaultSkillsChances, _skillRollArgs.reserveSkillsChances, _skillRollArgs.pseudoSkillsChances);
			NullifyChanceForSkill(_skillRollArgs.defaultSkillsChances, _sid);
			NullifyChanceForSkill(_skillRollArgs.reserveSkillsChances, _sid);
			NullifyChanceForSkill(_skillRollArgs.pseudoSkillsChances, _sid);
			NullifyChanceForSkill(_skillRollArgs.specialSkillsChances, _sid);
		}
		else if (!haveAllSkillsMaxLevel && nonMasterSkillsCount >= 3)
		{
			_sid = GetSkillForLevelUp(_skillRollArgs.openedSkillsChances);
			NullifyChanceForSkill(_skillRollArgs.openedSkillsChances, _sid);
		}
		else
		{
			_sid = GetPseudoSkill(_skillRollArgs.pseudoSkillsChances);
			NullifyChanceForSkill(_skillRollArgs.pseudoSkillsChances, _sid);
		}
	}

	private void SetSkillForSecondSlot(ref SkillRollArgs _skillRollArgs, out string _sid)
	{
		_sid = string.Empty;
		bool isSkillsCountEqualToMax = _skillRollArgs.isSkillsCountEqualToMax;
		bool haveAllSkillsMaxLevel = _skillRollArgs.haveAllSkillsMaxLevel;
		int nonMasterSkillsCount = _skillRollArgs.nonMasterSkillsCount;
		if (!isSkillsCountEqualToMax)
		{
			if (TryGetNewSid(_skillRollArgs.specialSkillsChances, out var _outSid))
			{
				_sid = _outSid;
				return;
			}
			bool flag = true;
			if (nonMasterSkillsCount >= 2 && random.Next(0, 2) == 1)
			{
				flag = false;
			}
			if (flag)
			{
				_sid = GetNewSkill(_skillRollArgs.defaultSkillsChances, _skillRollArgs.reserveSkillsChances, _skillRollArgs.pseudoSkillsChances);
			}
			else
			{
				_sid = GetSkillForLevelUp(_skillRollArgs.openedSkillsChances);
			}
		}
		else if (!haveAllSkillsMaxLevel && nonMasterSkillsCount >= 2)
		{
			_sid = GetSkillForLevelUp(_skillRollArgs.openedSkillsChances);
		}
		else
		{
			_sid = GetPseudoSkill(_skillRollArgs.pseudoSkillsChances);
		}
	}

	private void SetSkillForThirdSlot(ref SkillRollArgs _skillRollArgs, out string _sid)
	{
		_sid = string.Empty;
		bool isSkillsCountEqualToMax = _skillRollArgs.isSkillsCountEqualToMax;
		if (!_skillRollArgs.haveAllSkillsMaxLevel)
		{
			_sid = GetSkillForLevelUp(_skillRollArgs.openedSkillsChances);
			NullifyChanceForSkill(_skillRollArgs.openedSkillsChances, _sid);
		}
		else if (!isSkillsCountEqualToMax)
		{
			_sid = GetNewSkill(_skillRollArgs.defaultSkillsChances, _skillRollArgs.reserveSkillsChances, _skillRollArgs.pseudoSkillsChances);
			NullifyChanceForSkill(_skillRollArgs.defaultSkillsChances, _sid);
			NullifyChanceForSkill(_skillRollArgs.reserveSkillsChances, _sid);
			NullifyChanceForSkill(_skillRollArgs.pseudoSkillsChances, _sid);
			NullifyChanceForSkill(_skillRollArgs.specialSkillsChances, _sid);
		}
		else
		{
			_sid = GetPseudoSkill(_skillRollArgs.pseudoSkillsChances);
			NullifyChanceForSkill(_skillRollArgs.pseudoSkillsChances, _sid);
		}
	}

	private bool IsSkillsCountEqualToMax()
	{
		return hero.skills.currentSkills.Count == 8;
	}

	private bool HaveAllSkillsMaxLevel()
	{
		foreach (HeroSkill currentSkill in hero.skills.currentSkills)
		{
			if (currentSkill.level < currentSkill.config.MaxLevel)
			{
				return false;
			}
		}
		return true;
	}

	private int GetNonMasterSkillsCount()
	{
		int num = 0;
		foreach (HeroSkill currentSkill in hero.skills.currentSkills)
		{
			if (currentSkill.level < currentSkill.config.MaxLevel)
			{
				num++;
			}
		}
		return num;
	}

	private bool TryGetNewSid(SkillsRollChances _rollChances, out string _outSid)
	{
		_outSid = null;
		if (_rollChances == null)
		{
			return false;
		}
		if (!_rollChances.CanRoll())
		{
			_outSid = null;
			return false;
		}
		_outSid = _rollChances.Roll(random);
		return true;
	}

	private string GetNewSkill(SkillsRollChances _defaultRollChances, SkillsRollChances _reserveRollChances, SkillsRollChances _pseudoRollChances)
	{
		if (!TryGetNewSid(_defaultRollChances, out var _outSid) && !TryGetNewSid(_reserveRollChances, out _outSid) && !TryGetNewSid(_pseudoRollChances, out _outSid))
		{
			return null;
		}
		return _outSid;
	}

	private string GetSkillForLevelUp(SkillsRollChances _openedRollChances)
	{
		if (TryGetNewSid(_openedRollChances, out var _outSid))
		{
			return _outSid;
		}
		return null;
	}

	private string GetPseudoSkill(SkillsRollChances _pseudoRollChances)
	{
		if (TryGetNewSid(_pseudoRollChances, out var _outSid))
		{
			return _outSid;
		}
		return null;
	}
}

Skills Roll Chances - 技能权重算法

public class SkillsRollChances
{
	private List list;

	private Dictionary dictBySid;

	public int Length => list.Count;

	public SkillRollChance this[int _index]
	{
		get
		{
			if (_index < 0 || _index >= list.Count)
			{
				return null;
			}
			return list[_index];
		}
	}

	public SkillRollChance this[string _sid]
	{
		get
		{
			if (!dictBySid.TryGetValue(_sid, out var value))
			{
				return null;
			}
			return value;
		}
	}

	public SkillsRollChances(Hex.Configs.SkillRollChance[] _rollChances)
	{
		list = new List();
		dictBySid = new Dictionary();
		foreach (Hex.Configs.SkillRollChance skillRollChance in _rollChances)
		{
			SkillRollChance skillRollChance2 = new SkillRollChance(skillRollChance.sid, skillRollChance.chance);
			list.Add(skillRollChance2);
			dictBySid.Add(skillRollChance2.Sid, skillRollChance2);
		}
	}

	public SkillsRollChances(List _rollChances)
	{
		list = _rollChances;
		dictBySid = new Dictionary();
		foreach (SkillRollChance _rollChance in _rollChances)
		{
			dictBySid.Add(_rollChance.Sid, _rollChance);
		}
	}

	public void ResetToDefault()
	{
		foreach (SkillRollChance item in list)
		{
			item.ResetToDefault();
		}
	}

	public bool CanRoll()
	{
		foreach (SkillRollChance item in list)
		{
			if (item.Chance > 0)
			{
				return true;
			}
		}
		return false;
	}

	public string Roll(Random _random)
	{
		int rollIndex = GetRollIndex(_random);
		return list[rollIndex].Sid;
	}

	private int GetRollIndex(Random _random)
	{
		int num = 0;
		for (int i = 0; i < Length; i++)
		{
			num += list[i].Chance;
		}
		int num2 = _random.Next(0, num);
		for (int num3 = Length - 1; num3 >= 0; num3--)
		{
			num -= list[num3].Chance;
			if (num <= num2)
			{
				return num3;
			}
		}
		return 0;
	}
}