private void RandomizeATBCosts(Dictionary <Ability, int> plando) { if (Flags.AbilityFlags.ATBCost) { int variance = Flags.AbilityFlags.ATBCost.Range.Value; Flags.AbilityFlags.ATBCost.SetRand(); RandoCrystarium crystarium = randomizers.Get <RandoCrystarium>("Crystarium"); List <string> startingAbilityNodes = crystarium.crystariums.Values.SelectMany(c => c.DataList).Where(node => node.CPCost == 0 && node.Type == CrystariumType.Ability).Select(node => node.AbilityName).ToList(); Abilities.abilities.Where(a => a.Role != Role.None).ForEach(aID => { if (abilities.IdList.IndexOf(aID.GetIDs()[0]) > -1) { int max = aID.GetIDs().Where(id => startingAbilityNodes.Contains(id)).Count() > 0 ? 3 : 6; if (aID == Abilities.Attack || aID == Abilities.HandGrenade) { max = 2; } int cost = plando.ContainsKey(aID) ? (plando[aID] * 10) : abilities[aID.GetIDs()[0]].ATBCost; if (cost > 0 && cost < 0xFFFF) { if (!plando.ContainsKey(aID)) { cost = RandomNum.RandInt(Math.Max(1, cost / 10 - variance), Math.Min(max, cost / 10 + variance)) * 10; } if (cost == 60) { cost = 0xFFFF; } aID.GetIDs().ForEach(id => { if (abilities.IdList.IndexOf(id) > -1) { abilities[id].ATBCost = (ushort)cost; } }); } } }); RandomNum.ClearRand(); } }
private void RandomizeDebuffs(DataStoreEnemy enemy, Enemy enemyID, int modifier, Dictionary <Enemy, Dictionary <Debuff, int> > plandoDebuffResists) { RandoCrystarium crystarium = randomizers.Get <RandoCrystarium>("Crystarium"); float leaderBias = 0.75f, aiBias = 0.90f; Dictionary <Debuff, int[]> bounds = ((Debuff[])Enum.GetValues(typeof(Debuff))).ToDictionary(d => d, d => new int[] { 0, 100 }); int immunities = (int)(((Debuff[])Enum.GetValues(typeof(Debuff))).Where(d => enemy[d] >= 100).Count() + Math.Sign(modifier - 100) * RandomNum.RandInt(0, (int)Math.Round(Math.Sqrt(1.2 * Math.Abs(modifier - 100))))); if (enemyID.Type == EnemyType.Eidolon) { bounds[Debuff.Poison] = new int[] { 100, 100 }; immunities--; } if (plandoDebuffResists.ContainsKey(enemyID)) { plandoDebuffResists[enemyID].ForEach(pair => { bounds[pair.Key] = new int[] { pair.Value, pair.Value }; if (pair.Value == 100) { immunities--; } }); } immunities = Math.Max(0, Math.Min(11 - bounds.Values.Where(a => a[0] == 100 && a[1] == 100).Count(), immunities)); for (int i = 0; i < immunities; i++) { Debuff d; do { d = (Debuff)RandomNum.RandInt(0, 10); } while (bounds[d][0] == 100 && bounds[d][1] == 100); bounds[d] = new int[] { 100, 100 }; } List <Party> partiesUsed = enemyID.Parties.Select(p => GetParty(p)).ToList(); if (enemyID.ParentData != null && enemyID.ParentData.Parties.Length > 0) { partiesUsed.AddRange(enemyID.ParentData.Parties); } Dictionary <Debuff, int> weights = Enumerable.Range((int)Debuff.Deprotect, 11).ToDictionary(i => (Debuff)i, i => 10000); foreach (Party p in partiesUsed) { Dictionary <Member, List <Ability> > partyAbilities = new Dictionary <Member, List <Ability> >(); for (int i = 0; i < p.Members.Length; i++) { List <Ability> abilities = p.Members[i].GetAbilitiesAvailable(p.MaxStage, crystarium.crystariums[p.Members[i].Character.ToString().ToLower()], i == 0 || p.LeaderSwap, enemyID.ElementProperty == ElementProperty.Skytank).Where(a => a.Elements.Length > 0).ToList(); partyAbilities.Add(p.Members[i], abilities); } int randomRequiredVulnerable = RandomNum.RandInt(0, p.Members.Length); for (int i = 0; i < p.Members.Length; i++) { float bias = (i == 0 ? leaderBias : aiBias) / (float)partiesUsed.Count; Ability ability; int debuffCount = partyAbilities[p.Members[i]].SelectMany(a => a.Debuffs).Distinct().Count(); if (debuffCount == 0) { ability = partyAbilities[p.Members[i]][RandomNum.RandInt(0, partyAbilities[p.Members[i]].Count - 1)]; } else { List <Debuff> validDebuffs; do { ability = partyAbilities[p.Members[i]][RandomNum.RandInt(0, partyAbilities[p.Members[i]].Count - 1)]; validDebuffs = ability.Debuffs.ToList(); } while (validDebuffs.Count == 0); weights.Keys.Where(e => validDebuffs.Contains(e)).ForEach(e => { if (RandomNum.RandInt(0, 99) < 40) { weights[e] = (int)(weights[e] / bias); } else { weights[e] = (int)(weights[e] * bias); } if (i == randomRequiredVulnerable && bounds[e][1] > 99) { bounds[e][1] = 99; } }); } } } if (enemyID.Type == EnemyType.Eidolon) { bounds[Debuff.Poison] = new int[] { 100, 100 }; } if (plandoDebuffResists.ContainsKey(enemyID)) { plandoDebuffResists[enemyID].ForEach(pair => bounds[pair.Key] = new int[] { pair.Value, pair.Value }); } StatValuesWeighted debuffs = new StatValuesWeighted(weights.Values.ToArray()); Tuple <int, int>[] debuffBounds = weights.Keys.Select(d => new Tuple <int, int>(bounds[d][0], bounds[d][1])).ToArray(); debuffs.Randomize(debuffBounds, (int)(debuffs.GetTotalPoints(debuffBounds) * modifier / 100f)); weights.Keys.ToList().ForEach(d => enemy[d] = (byte)Math.Min(100, debuffs[weights.Keys.ToList().IndexOf(d)])); }
private void RandomizeElements(DataStoreEnemy enemy, Enemy enemyID, int modifier, Dictionary <Enemy, Dictionary <Element, ElementalRes> > plandoElementResists) { RandoCrystarium crystarium = randomizers.Get <RandoCrystarium>("Crystarium"); float leaderBias = 0.75f, aiBias = 0.90f; Dictionary <Element, ElementalRes[]> bounds = new Dictionary <Element, ElementalRes[]>(); bounds.Add(Element.Fire, new ElementalRes[] { ElementalRes.Weakness, ElementalRes.Absorb }); bounds.Add(Element.Ice, new ElementalRes[] { ElementalRes.Weakness, ElementalRes.Absorb }); bounds.Add(Element.Thunder, new ElementalRes[] { ElementalRes.Weakness, ElementalRes.Absorb }); bounds.Add(Element.Water, new ElementalRes[] { ElementalRes.Weakness, ElementalRes.Absorb }); bounds.Add(Element.Wind, new ElementalRes[] { ElementalRes.Weakness, ElementalRes.Absorb }); bounds.Add(Element.Earth, new ElementalRes[] { ElementalRes.Weakness, ElementalRes.Absorb }); bounds.Add(Element.Physical, new ElementalRes[] { ElementalRes.Weakness, ElementalRes.Immune }); bounds.Add(Element.Magical, new ElementalRes[] { ElementalRes.Weakness, ElementalRes.Immune }); if (enemyID.ElementProperty == ElementProperty.Bomb) { ((Element[])Enum.GetValues(typeof(Element))).Where(e => enemy[e] == ElementalRes.Absorb).ForEach(e => bounds[e] = new ElementalRes[] { ElementalRes.Absorb, ElementalRes.Absorb }); } if (plandoElementResists.ContainsKey(enemyID)) { plandoElementResists[enemyID].ForEach(pair => bounds[pair.Key] = new ElementalRes[] { pair.Value, pair.Value }); } bool isArmored = enemy.PhysicalRes >= ElementalRes.Resistant && enemy.MagicRes >= ElementalRes.Resistant; ElementalRes possibleMax = isArmored ? ElementalRes.Resistant : ElementalRes.Halved; List <Party> partiesUsed = enemyID.Parties.Select(p => GetParty(p)).ToList(); if (enemyID.ParentData != null && enemyID.ParentData.Parties.Length > 0) { partiesUsed.AddRange(enemyID.ParentData.Parties.Select(p => GetParty(p)).ToList()); } Dictionary <Element, int> typeWeights = Enumerable.Range((int)Element.Physical, 2).ToDictionary(i => (Element)i, i => 10000); Dictionary <Element, int> elementWeights = Enumerable.Range((int)Element.Fire, 6).ToDictionary(i => (Element)i, i => 10000); foreach (Party p in partiesUsed) { Dictionary <Member, List <Ability> > partyAbilities = new Dictionary <Member, List <Ability> >(); for (int i = 0; i < p.Members.Length; i++) { List <Ability> abilities = p.Members[i].GetAbilitiesAvailable(p.MaxStage, crystarium.crystariums[p.Members[i].Character.ToString().ToLower()], i == 0 || p.LeaderSwap, enemyID.ElementProperty == ElementProperty.Skytank).Where(a => a.Elements.Length > 0).SkipWhile(a => (enemyID.ElementProperty == ElementProperty.Bomb ? (a.Elements.Where(e => bounds[e][0] == ElementalRes.Absorb && bounds[e][1] == ElementalRes.Absorb).Count() > 0) : false)).ToList(); partyAbilities.Add(p.Members[i], abilities); } if (enemyID.ElementProperty == ElementProperty.Bomb && partyAbilities.Values.SelectMany(l => l).Count() == 0) { ((Element[])Enum.GetValues(typeof(Element))).Where(e => enemy[e] == ElementalRes.Absorb).ForEach(e => bounds[e] = new ElementalRes[] { ElementalRes.Halved, ElementalRes.Halved }); } List <Ability> physical, magic; physical = partyAbilities.Values.SelectMany(l => l).Where(a => a.Elements.Contains(Element.Physical)).ToList(); magic = partyAbilities.Values.SelectMany(l => l).Where(a => a.Elements.Contains(Element.Magical)).ToList(); if (physical.Count > 0 && magic.Count == 0 && bounds[Element.Physical][1] > possibleMax) { bounds[Element.Physical][1] = possibleMax; } else if (physical.Count == 0 && magic.Count > 0 && bounds[Element.Magical][1] > possibleMax) { bounds[Element.Magical][1] = possibleMax; } int randomRequiredVulnerable = RandomNum.RandInt(0, p.Members.Length); for (int i = 0; i < p.Members.Length; i++) { if (partyAbilities[p.Members[i]].Count == 0) { continue; } float bias = (i == 0 ? leaderBias : aiBias) / (float)partiesUsed.Count; Ability ability; int elementCount = partyAbilities[p.Members[i]].SelectMany(a => GetElementsOnAbility(a, partyAbilities.Values.SelectMany(l => l).ToList())).Distinct().Count(); if (elementCount == 0) { ability = partyAbilities[p.Members[i]][RandomNum.RandInt(0, partyAbilities[p.Members[i]].Count - 1)]; } else { List <Element> validElements; do { ability = partyAbilities[p.Members[i]][RandomNum.RandInt(0, partyAbilities[p.Members[i]].Count - 1)]; validElements = GetElementsOnAbility(ability, partyAbilities.Values.SelectMany(l => l).ToList()).ToList(); } while (validElements.Count == 0); elementWeights.Keys.Where(e => validElements.Contains(e)).ForEach(e => { if (RandomNum.RandInt(0, 99) < 40) { elementWeights[e] = (int)(elementWeights[e] / bias); } else { elementWeights[e] = (int)(elementWeights[e] * bias); } if (i == randomRequiredVulnerable && bounds[e][1] > possibleMax) { bounds[e][1] = possibleMax; } }); } typeWeights.Keys.Where(e => ability.Elements.Contains(e)).ForEach(e => { float typeBias = bias * (e == Element.Physical ? 0.45f : 1); if (RandomNum.RandInt(0, 99) < 40) { typeWeights[e] = (int)(typeWeights[e] / Math.Pow(typeBias, 0.1)); } else { typeWeights[e] = (int)(typeWeights[e] * Math.Pow(typeBias, 0.1)); } if (i == randomRequiredVulnerable && bounds[e][1] > possibleMax) { bounds[e][1] = possibleMax; } }); } } if (plandoElementResists.ContainsKey(enemyID)) { plandoElementResists[enemyID].ForEach(pair => bounds[pair.Key] = new ElementalRes[] { pair.Value, pair.Value }); } StatValuesWeighted types = new StatValuesWeighted(typeWeights.Values.ToArray()); StatValuesWeighted elements = new StatValuesWeighted(elementWeights.Values.ToArray()); Tuple <int, int>[] typeBounds = typeWeights.Keys.Select(e => GetElemBounds(bounds[e])).ToArray(); types.Randomize(typeBounds, (int)(types.GetTotalPoints(typeBounds) * modifier / 100f)); Tuple <int, int>[] elementBounds = elementWeights.Keys.Select(e => GetElemBounds(bounds[e])).ToArray(); elements.Randomize(elementBounds, (int)(elements.GetTotalPoints(elementBounds) * modifier / 100f)); typeWeights.Keys.ToList().ForEach(e => enemy[e] = GetBoundRes(types[typeWeights.Keys.ToList().IndexOf(e)])); elementWeights.Keys.ToList().ForEach(e => enemy[e] = GetBoundRes(elements[elementWeights.Keys.ToList().IndexOf(e)])); }