mirror of
https://github.com/haven1433/HexManiacAdvance.git
synced 2026-06-01 04:53:29 -05:00
add the concept of 'comment segments' for tables
This can allow the table to insert comments when writing the content as a string. Also, update the formatting for wild pokemon summary
This commit is contained in:
parent
a397cf1c71
commit
2ac3f88541
|
|
@ -7,6 +7,7 @@ using System.Collections.ObjectModel;
|
|||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.HexManiac.Core {
|
||||
|
|
@ -182,6 +183,21 @@ namespace HavenSoft.HexManiac.Core {
|
|||
return input.Substring(0, index) + replacement + input.Substring(index + search.Length);
|
||||
}
|
||||
|
||||
public static StringBuilder TrimEnd(this StringBuilder sb) {
|
||||
if (sb == null || sb.Length == 0) return sb;
|
||||
|
||||
int i = sb.Length - 1;
|
||||
|
||||
for (; i >= 0; i--)
|
||||
if (!char.IsWhiteSpace(sb[i]))
|
||||
break;
|
||||
|
||||
if (i < sb.Length - 1)
|
||||
sb.Length = i + 1;
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static bool IsAny<T>(this T self, params T[] options) {
|
||||
Debug.Assert(self is IEquatable<T> || self is Enum);
|
||||
return options.Contains(self);
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ data.trainers.rematches, , , , , ,
|
|||
data.trainers.rematches, 082C00, 082C00, 082C20, 082C20, , , , , , [base:data.trainers.stats rematch1:data.trainers.stats rematch2:data.trainers.stats rematch3:data.trainers.stats rematch4:data.trainers.stats mapBank: mapNum: unused:]56
|
||||
data.trainers.multibattle.steven.team, , , , , , , , , 165534, [species:data.pokemon.names iv. level. nature.data.pokemon.natures.names hpEV. atkEV. defEV. speedEV. spAtkEV. spDefEV. unused. [move:data.pokemon.moves.names]4]3
|
||||
data.decorations.stats, 0B3AC8, 0B3AC8, 0B3AE8, 0B3AE8, 00014C, 00014C, 00014C, 00014C, 00014C, [id. name""16 permission.decorpermissions shape.decorshape category.decorcategory price: unused: description<""> graphics<>]
|
||||
data.pokemon.wild, 084D9C, 084D9C, 084DBC, 084DBC, 082990, 082964, 0829A4, 082978, 0B4D48, [bank. map. unused: grass<[rate:: list<[lowLevel. highLevel. species:data.pokemon.names]12>]1> surf<[rate:: list<[lowLevel. highLevel. species:data.pokemon.names]5>]1> tree<[rate:: list<[lowLevel. highLevel. species:data.pokemon.names]5>]1> fish<[rate:: list<[lowLevel. highLevel. species:data.pokemon.names]10>]1>]!FFFF
|
||||
data.pokemon.wild, 084D9C, 084D9C, 084DBC, 084DBC, 082990, 082964, 0829A4, 082978, 0B4D48, [bank. map. unused: grass<[rate:: list<[lowLevel. highLevel. species:data.pokemon.names]12>]1> surf<[rate:: list<[lowLevel. highLevel. species:data.pokemon.names]5>]1> tree<[rate:: list<[lowLevel. highLevel. species:data.pokemon.names]5>]1> fish<[rate:: list<[old|comment=0|old_rod: good|comment=2|good_rod: super|comment=5|super_rod: lowLevel. highLevel. species:data.pokemon.names]10>]1>]!FFFF
|
||||
data.pokemon.trades, 04D8D4, 04D8D4, 04D8F4, 04D8F4, , , , , , [nickname""12 receive:data.pokemon.names hp. attack. defense. speed. spatk. spdef. abilitynum:: trainerid:: cool. tough. beauty. smart. cute. unused. unused: personality:: helditem:data.items.stats mailnum. trainername""11 trainergender.trainergender sheen. give::data.pokemon.names]3
|
||||
data.pokemon.trades, , , , , 053AD4, 053AD4, 053AE8, 053AE8, , [nickname""12 receive:data.pokemon.names hp. attack. defense. speed. spatk. spdef. abilitynum:: trainerid:: cool. tough. beauty. smart. cute. unused. unused: personality:: helditem:data.items.stats mailnum. trainername""11 trainergender.trainergender sheen. give::data.pokemon.names]9
|
||||
data.pokemon.trades, , , , , , , , , 07E774, [nickname""12 receive:data.pokemon.names hp. attack. defense. speed. spatk. spdef. abilitynum:: trainerid:: cool. tough. beauty. smart. cute. unused. unused: personality:: helditem:data.items.stats mailnum. trainername""11 trainergender.trainergender sheen. give::data.pokemon.names]4
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
}
|
||||
|
||||
public static bool IsUnused(this ArrayRunElementSegment segment) {
|
||||
return segment.Name.StartsWith("unused") || segment.Name.StartsWith("padding");
|
||||
return segment is ArrayRunCommentSegment || segment.Name.StartsWith("unused") || segment.Name.StartsWith("padding");
|
||||
}
|
||||
|
||||
public static IDataFormat CreateSegmentDataFormat(this ITableRun self, IDataModel data, int index) {
|
||||
|
|
@ -128,7 +128,20 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
var names = self.ElementNames;
|
||||
var offsets = self.ConvertByteOffsetToArrayOffset(start);
|
||||
length += offsets.SegmentOffset;
|
||||
var comments = new Dictionary<int, string>();
|
||||
foreach (var seg in self.ElementContent) {
|
||||
if (seg is not ArrayRunCommentSegment comment) continue;
|
||||
if (comments.ContainsKey(comment.Index)) {
|
||||
comments[comment.Index] += Environment.NewLine + comment.RenderCommentLine();
|
||||
} else {
|
||||
comments[comment.Index] = comment.RenderCommentLine();
|
||||
}
|
||||
}
|
||||
for (int i = offsets.ElementIndex; i < self.ElementCount && length > 0; i++) {
|
||||
if (comments.TryGetValue(i, out var comment)) {
|
||||
if (i != 0) text.AppendLine();
|
||||
text.AppendLine(comment);
|
||||
}
|
||||
var offset = offsets.SegmentStart;
|
||||
var couldBeExtension = offsets.ElementIndex > 0 || self is TableStreamRun streamRun && streamRun.AllowsZeroElements;
|
||||
if (offsets.SegmentIndex == 0 && couldBeExtension) text.Append(ArrayRun.ExtendArray);
|
||||
|
|
@ -492,6 +505,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
public const string ColorFormatString = "|c";
|
||||
public const string CalculatedFormatString = "|=";
|
||||
public const string RenderFormatString = "|render=";
|
||||
public const string CommentFormatString = "|comment=";
|
||||
public const string SplitterFormatString = "|";
|
||||
|
||||
private const int JunkLimit = 80;
|
||||
|
|
@ -1338,6 +1352,12 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
var tupleContract = segments.Slice(TupleFormatString.Length, endOfToken - TupleFormatString.Length);
|
||||
segments = segments.Slice(endOfToken).Trim();
|
||||
list.Add(new ArrayRunTupleSegment(name, tupleContract.ToString(), segmentLength));
|
||||
} else if (segments.StartsWith(CommentFormatString)) {
|
||||
var endOfToken = segments.IndexOf(' ');
|
||||
if (endOfToken == -1) endOfToken = segments.Length;
|
||||
var contract = segments.Slice(CommentFormatString.Length, endOfToken - CommentFormatString.Length);
|
||||
segments = segments.Slice(endOfToken).Trim();
|
||||
list.Add(new ArrayRunCommentSegment(name, contract.ToString()));
|
||||
} else if (segments.StartsWith(ColorFormatString)) {
|
||||
var endOfToken = segments.IndexOf(' ');
|
||||
if (endOfToken == -1) endOfToken = segments.Length;
|
||||
|
|
@ -1414,6 +1434,8 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
return (ElementContentType.Integer, 0, 0);
|
||||
} else if (segments.StartsWith(RenderFormatString)) {
|
||||
return (ElementContentType.Integer, 0, 0);
|
||||
} else if (segments.StartsWith(CommentFormatString)) {
|
||||
return (ElementContentType.Integer, 0, 0);
|
||||
} else if (segments.StartsWith(DoubleByteIntegerFormat + string.Empty + DoubleByteIntegerFormat)) {
|
||||
return (ElementContentType.Integer, 2, 4);
|
||||
} else if (segments.StartsWith(DoubleByteIntegerFormat + string.Empty + SingleByteIntegerFormat) || segments.StartsWith(".:")) {
|
||||
|
|
@ -1581,6 +1603,18 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
}
|
||||
}
|
||||
|
||||
public class ArrayRunCommentSegment : ArrayRunElementSegment {
|
||||
public int Index { get; private set; }
|
||||
public string Comment { get; private set; }
|
||||
public override string SerializeFormat => $"{Name}|comment={Index}|{Comment}";
|
||||
public ArrayRunCommentSegment(string name, string contract) : base(name, ElementContentType.Integer, 0) {
|
||||
var parts = contract.Split('|', 2);
|
||||
if (parts[0].TryParseInt(out var index)) Index = index;
|
||||
Comment = parts[1];
|
||||
}
|
||||
public string RenderCommentLine() => $"# {Comment.Replace('_', ' ')}";
|
||||
}
|
||||
|
||||
public class ArrayRunParseException : Exception {
|
||||
public ArrayRunParseException(string message) : base(message) { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
var self = this;
|
||||
if (lengthOverride != ElementCount) self = new TableStreamRun(model, Start, PointerSources, FormatString, ElementContent, endStream, lengthOverride);
|
||||
var changedAddresses = new List<int>();
|
||||
var lines = content.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var lines = content.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).Where(line => !line.Trim().StartsWith("#")).ToArray();
|
||||
if (lines.Length == 0 && !AllowsZeroElements) lines = content.Split(Environment.NewLine);
|
||||
var newRun = self;
|
||||
var appendCount = Math.Max(lines.Length, 1) - lengthOverride;
|
||||
|
|
@ -271,6 +271,8 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
if (pointerValue == Pointer.NULL) value = "<null>";
|
||||
} else if (segment.Type == ElementContentType.PCS) {
|
||||
value = model.TextConverter.Convert(model, offset, segment.Length);
|
||||
} else if (segment.Length == 0) {
|
||||
continue;
|
||||
}
|
||||
var extraWhitespace = new string(' ', longestLabel - segment.Name.Length);
|
||||
result.Append($"{segment.Name}:{extraWhitespace} {value}");
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Input;
|
||||
|
|
@ -53,6 +54,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
|
||||
// extend wild table
|
||||
var wildTable = model.GetTable(HardcodeTablesModel.WildTableName);
|
||||
if (wildTable == null) return;
|
||||
var originalStart = wildTable.Start;
|
||||
wildTable = model.RelocateForExpansion(token, wildTable, wildTable.Length + wildTable.ElementLength);
|
||||
wildTable = wildTable.Append(token, 1);
|
||||
|
|
@ -83,30 +85,46 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
// grass<[rate:: list<>]1> surf<[rate:: list<>]1> tree<[rate:: list<>]1> fish<[rate:: list<>]1>
|
||||
var text = new StringBuilder();
|
||||
if (wildDataIndex < 0) return text.ToString();
|
||||
BuildWildTooltip(text, wild[wildDataIndex], "grass");
|
||||
text.AppendLine();
|
||||
BuildWildTooltip(text, wild[wildDataIndex], "surf");
|
||||
text.AppendLine();
|
||||
BuildWildTooltip(text, wild[wildDataIndex], "tree");
|
||||
text.AppendLine();
|
||||
if (BuildWildTooltip(text, wild[wildDataIndex], "grass")) text.AppendLine();
|
||||
if (BuildWildTooltip(text, wild[wildDataIndex], "surf")) text.AppendLine();
|
||||
if (BuildWildTooltip(text, wild[wildDataIndex], "tree")) text.AppendLine();
|
||||
BuildWildTooltip(text, wild[wildDataIndex], "fish");
|
||||
wildText = text.ToString();
|
||||
wildText = text.TrimEnd().ToString();
|
||||
if (string.IsNullOrWhiteSpace(wildText)) wildText = "No Wild Pokemon (yet!)";
|
||||
return wildText;
|
||||
}
|
||||
}
|
||||
private static void BuildWildTooltip(StringBuilder text, ModelArrayElement wild, string type) {
|
||||
private static bool BuildWildTooltip(StringBuilder text, ModelArrayElement wild, string type) {
|
||||
// list<[low. high. species:]n>
|
||||
var terrain = wild.GetSubTable(type);
|
||||
if (terrain == null) return;
|
||||
if (terrain == null) return false;
|
||||
var list = terrain[0].GetSubTable("list");
|
||||
if (list == null) return;
|
||||
if (list == null) return false;
|
||||
text.Append(type);
|
||||
text.Append(": ");
|
||||
var content = list.Select(element => element.GetEnumValue("species")).ToHistogram();
|
||||
text.AppendJoin(", ", content.Keys.Select(pokemon => {
|
||||
if (content[pokemon] == 1) return pokemon;
|
||||
return $"{pokemon} x{content[pokemon]}";
|
||||
text.AppendLine(":");
|
||||
|
||||
if (type == "fish") {
|
||||
text.Append($"old rod: ");
|
||||
AppendHistogram(text, list.Take(2), "species");
|
||||
text.AppendLine();
|
||||
text.Append($"good rod: ");
|
||||
AppendHistogram(text, list.Skip(2).Take(3), "species");
|
||||
text.AppendLine();
|
||||
text.Append($"super rod: ");
|
||||
AppendHistogram(text, list.Skip(5), "species");
|
||||
} else {
|
||||
AppendHistogram(text, list, "species");
|
||||
}
|
||||
text.AppendLine();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void AppendHistogram(StringBuilder text, IEnumerable<ModelArrayElement> elements, string fieldName) {
|
||||
var histogram = elements.Select(element => element.GetEnumValue(fieldName)).ToHistogram();
|
||||
text.AppendJoin(", ", histogram.Keys.Select(key => {
|
||||
if (histogram[key] == 1) return key;
|
||||
return $"{key} x{histogram[key]}";
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user