mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-04-22 23:41:36 -05:00
Lift stat amp reinterpret to nature adjust
Allows retaining a stat parse amplification tracking result in visual order, unless requested in stored order. Results in slightly less logic being done on un-kept parses/IV parses. Adds xmldoc Extract Ability/Nature parse lines to add parse fail indicators on conflicting values. ``` Piplup [Torrent] @ Oran Berry Ability: Defiant ``` Will now flag the conflicting ability
This commit is contained in:
parent
2514e66331
commit
a7420cb3de
|
|
@ -219,7 +219,6 @@ public StatParseResult TryParseStats(ReadOnlySpan<char> message, Span<int> bestR
|
|||
{
|
||||
var result = ParseInternal(message, bestResult);
|
||||
ReorderSpeedNotLast(bestResult);
|
||||
result.TreatAmpsAsSpeedNotLast();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -263,8 +263,8 @@ private void ParseLineAbilityBracket(ReadOnlySpan<char> line, GameStrings locali
|
|||
|
||||
private bool ParseEntry(BattleTemplateToken token, ReadOnlySpan<char> value, BattleTemplateLocalization localization) => token switch
|
||||
{
|
||||
BattleTemplateToken.Ability => (Ability = StringUtil.FindIndexIgnoreCase(localization.Strings.abilitylist, value)) >= 0,
|
||||
BattleTemplateToken.Nature => (Nature = (Nature)StringUtil.FindIndexIgnoreCase(localization.Strings.natures, value)).IsFixed(),
|
||||
BattleTemplateToken.Ability => ParseLineAbility(value, localization.Strings.abilitylist),
|
||||
BattleTemplateToken.Nature => ParseLineNature(value, localization.Strings.natures),
|
||||
BattleTemplateToken.Shiny => Shiny = true,
|
||||
BattleTemplateToken.Gigantamax => CanGigantamax = true,
|
||||
BattleTemplateToken.HeldItem => ParseItemName(value, localization.Strings),
|
||||
|
|
@ -279,6 +279,46 @@ private void ParseLineAbilityBracket(ReadOnlySpan<char> line, GameStrings locali
|
|||
_ => false,
|
||||
};
|
||||
|
||||
private bool ParseLineAbility(ReadOnlySpan<char> value, ReadOnlySpan<string> abilityNames)
|
||||
{
|
||||
var index = StringUtil.FindIndexIgnoreCase(abilityNames, value);
|
||||
if (index < 0)
|
||||
{
|
||||
InvalidLines.Add($"Unknown Ability: {value}");
|
||||
return false;
|
||||
}
|
||||
if (Ability != -1 && Ability != index)
|
||||
{
|
||||
InvalidLines.Add($"Different ability already specified: {value}");
|
||||
return false;
|
||||
}
|
||||
|
||||
Ability = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ParseLineNature(ReadOnlySpan<char> value, ReadOnlySpan<string> natureNames)
|
||||
{
|
||||
var index = StringUtil.FindIndexIgnoreCase(natureNames, value);
|
||||
if (index < 0)
|
||||
return false;
|
||||
|
||||
var nature = (Nature)index;
|
||||
if (!nature.IsFixed())
|
||||
{
|
||||
InvalidLines.Add($"Invalid Nature: {value}");
|
||||
return false;
|
||||
}
|
||||
if (Nature != Nature.Random && Nature != nature)
|
||||
{
|
||||
InvalidLines.Add($"Different nature already specified: {value}");
|
||||
return false;
|
||||
}
|
||||
|
||||
Nature = nature;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ParseNickname(ReadOnlySpan<char> value)
|
||||
{
|
||||
if (value.Length == 0)
|
||||
|
|
@ -1002,7 +1042,7 @@ private bool ParseLineEVs(ReadOnlySpan<char> line, BattleTemplateLocalization lo
|
|||
return false; // invalid line
|
||||
}
|
||||
|
||||
if (Nature != Nature.Random)
|
||||
if (Nature != Nature.Random) // specified in a separate Nature line
|
||||
InvalidLines.Add($"EV nature ignored, specified previously: {natureName}");
|
||||
else
|
||||
Nature = (Nature)natureIndex;
|
||||
|
|
@ -1012,18 +1052,20 @@ private bool ParseLineEVs(ReadOnlySpan<char> line, BattleTemplateLocalization lo
|
|||
|
||||
var result = localization.Config.TryParseStats(line, EVs);
|
||||
var success = result.IsParsedAllStats;
|
||||
if (!result.IsParseClean)
|
||||
InvalidLines.Add($"Invalid EVs: {line}");
|
||||
|
||||
if (result is { HasAmps: false })
|
||||
return success;
|
||||
if (Nature != Nature.Random)
|
||||
{
|
||||
InvalidLines.Add($"EV nature +/- ignored, specified previously: {line}");
|
||||
return false;
|
||||
}
|
||||
|
||||
success &= AdjustNature(result.Plus, result.Minus);
|
||||
// Use the amp nature ONLY if nature was not specified.
|
||||
// Only indicate invalid if it differs from the current nature.
|
||||
var currentNature = Nature;
|
||||
result.TreatAmpsAsSpeedNotLast();
|
||||
var ampNature = AdjustNature(result.Plus, result.Minus);
|
||||
success &= ampNature;
|
||||
if (ampNature && currentNature != Nature.Random && currentNature != Nature)
|
||||
{
|
||||
InvalidLines.Add($"EV +/- nature does not match specified nature: {currentNature}");
|
||||
Nature = currentNature; // revert to original
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -1031,17 +1073,14 @@ private bool ParseLineIVs(ReadOnlySpan<char> line, BattleTemplateConfig config)
|
|||
{
|
||||
// Parse stats, with unspecified name representation (try all).
|
||||
var result = config.TryParseStats(line, IVs);
|
||||
var success = result.IsParsedAllStats;
|
||||
if (!result.IsParseClean)
|
||||
InvalidLines.Add($"Invalid IVs: {line}");
|
||||
return success;
|
||||
return result.IsParsedAllStats;
|
||||
}
|
||||
|
||||
private bool AdjustNature(int plus, int minus)
|
||||
private bool AdjustNature(sbyte plus, sbyte minus)
|
||||
{
|
||||
if (plus == -1)
|
||||
if (plus == StatParseResult.NoStatAmp)
|
||||
InvalidLines.Add("Invalid Nature adjustment, missing plus stat.");
|
||||
if (minus == -1)
|
||||
if (minus == StatParseResult.NoStatAmp)
|
||||
InvalidLines.Add("Invalid Nature adjustment, missing minus stat.");
|
||||
else
|
||||
Nature = NatureAmp.CreateNatureFromAmps(plus, minus);
|
||||
|
|
|
|||
|
|
@ -284,9 +284,17 @@ public static StatParseResult TryParseRaw(ReadOnlySpan<char> message, Span<int>
|
|||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
var index = message.IndexOf(separator);
|
||||
|
||||
var value = index != -1 ? message[..index].Trim() : message.Trim();
|
||||
message = message[(index+1)..].TrimStart();
|
||||
ReadOnlySpan<char> value;
|
||||
if (index != -1)
|
||||
{
|
||||
value = message[..index].TrimEnd();
|
||||
message = message[(index + 1)..].TrimStart();
|
||||
}
|
||||
else // no further iterations to be done
|
||||
{
|
||||
value = message;
|
||||
message = default;
|
||||
}
|
||||
|
||||
if (value.Length == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace PKHeX.Core;
|
|||
public record struct StatParseResult()
|
||||
{
|
||||
private const uint MaxStatCount = 6; // Number of stats in the game
|
||||
private const sbyte NoStatAmp = -1;
|
||||
public const sbyte NoStatAmp = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Count of parsed stats.
|
||||
|
|
@ -16,17 +16,17 @@ public record struct StatParseResult()
|
|||
public byte CountParsed { get; private set; } = 0; // could potentially make this a computed value (popcnt), but it's not worth it
|
||||
|
||||
/// <summary>
|
||||
/// Indexes of parsed stats.
|
||||
/// Bitflag indexes of parsed stats, indexed in visual order.
|
||||
/// </summary>
|
||||
public byte IndexesParsed { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Stat index of increased stat.
|
||||
/// Stat index of increased stat, indexed in visual order.
|
||||
/// </summary>
|
||||
public sbyte Plus { get; set; } = NoStatAmp;
|
||||
|
||||
/// <summary>
|
||||
/// Stat index of decreased stat.
|
||||
/// Stat index of decreased stat, indexed in visual order.
|
||||
/// </summary>
|
||||
public sbyte Minus { get; set; } = NoStatAmp;
|
||||
|
||||
|
|
@ -114,15 +114,19 @@ public void TreatAmpsAsSpeedNotLast()
|
|||
Minus = GetSpeedMiddleIndex(Minus);
|
||||
}
|
||||
|
||||
// Move speed from index 5 to index 3, and the other stats down to account for HP not being boosted.
|
||||
/// <summary>
|
||||
/// Adjusts stat indexes from visual to stored, and ignoring HP's index.
|
||||
/// </summary>
|
||||
/// <param name="amp">Visual index of the stat to get the adjusted value for.</param>
|
||||
/// <returns>Stored index of the stat.</returns>
|
||||
private static sbyte GetSpeedMiddleIndex(sbyte amp) => amp switch
|
||||
{
|
||||
0 => -1,
|
||||
// 0 => NoStatAmp -- handle via default case
|
||||
1 => 0, // Atk
|
||||
2 => 1, // Def
|
||||
3 => 3, // SpA
|
||||
4 => 4, // SpD
|
||||
5 => 2, // Spe
|
||||
_ => amp,
|
||||
_ => NoStatAmp,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user