Add split file encounter dumping, weather groups

Diferent weather allows for different Mark values (ribbon), and only
Symbol encounters can wander into adjacent maps
Need to have separate exports with appropriate metadata

add nest dumper I forgot to push before working on slot dump v2
This commit is contained in:
Kurt
2019-11-27 22:29:13 -08:00
parent 5a00bc4802
commit 1ef510bcf0
2 changed files with 155 additions and 0 deletions

View File

@@ -1,11 +1,138 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace pkNX.Structures
{
public static class EncounterTable8Util
{
public static byte[][] GetBytes(IReadOnlyDictionary<ulong, byte> zone_loc, EncounterArchive8 t)
{
var result = new byte[t.EncounterTables.Length][];
for (int i = 0; i < result.Length; i++)
{
var zone = t.EncounterTables[i];
result[i] = GetZoneBytes(zone, zone_loc);
}
return result;
}
private static byte[] GetZoneBytes(EncounterTable8 zone, IReadOnlyDictionary<ulong, byte> zoneLoc)
{
byte locID = zoneLoc[zone.ZoneID];
var list = new List<Slot8>();
for (int i = 0; i < zone.SubTables.Length; i++)
{
var weather = (SWSHEncounterType)(1 << i);
var table = zone.SubTables[i];
var min = table.LevelMin;
var max = table.LevelMax;
foreach (var s in table.Slots)
{
var s8 = new Slot8(s.Species, s.Form, min, max) {EncounterType = weather};
var match = list.Find(z => z.Equals(s8));
if (match == null)
list.Add(s8);
else
match.EncounterType |= weather;
}
}
return SerializeSlot8(locID, list);
}
private static byte[] SerializeSlot8(byte locID, IEnumerable<Slot8> list)
{
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
int ctr = 0;
bw.Write(locID);
bw.Write((byte) 0); // count tmp
var groups = list.GroupBy(z => (int) z.EncounterType | (z.Min << 16) | (z.Max << 24));
foreach (var g in groups)
{
var slots = g.ToArray();
var type = g.Key & 0xFFFF;
var min = (g.Key >> 16) & 0xFF;
var max = g.Key >> 24;
bw.Write((ushort) type);
bw.Write((byte) min);
bw.Write((byte) max);
bw.Write((byte) slots.Length);
bw.Write((byte) 0);
foreach (var slot in slots)
bw.Write((ushort)(slot.Species | (slot.Form << 11)));
ctr += slots.Length;
}
bw.BaseStream.Seek(1, SeekOrigin.Begin);
bw.Write((byte) ctr);
return ms.ToArray();
}
[Flags]
private enum SWSHEncounterType
{
None,
Normal = 1,
Overcast = 1 << 1,
Raining = 1 << 2,
Thunderstorm = 1 << 3,
Intense_Sun = 1 << 4,
Snowing = 1 << 5,
Snowstorm = 1 << 6,
Sandstorm = 1 << 7,
Heavy_Fog = 1 << 8,
Shaking_Trees = 1 << 9,
Fishing = 1 << 10,
};
private class Slot8 : IEquatable<Slot8>
{
public readonly int Species;
public readonly int Form;
public readonly int Min;
public readonly int Max;
public SWSHEncounterType EncounterType;
public Slot8(int s, int f, int n, int x)
{
Species = s;
Form = f;
Min = n;
Max = x;
}
public bool Equals(Slot8 other)
{
if (other is null) return false;
if (ReferenceEquals(this, other)) return true;
return Species == other.Species && Form == other.Form && Min == other.Min && Max == other.Max;
}
public override bool Equals(object obj)
{
if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == GetType() && Equals((Slot8) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = Species;
hashCode = (hashCode * 397) ^ Form;
hashCode = (hashCode * 397) ^ Min;
hashCode = (hashCode * 397) ^ Max;
return hashCode;
}
}
}
public static IEnumerable<string> GetLines(EncounterArchive8 t, IReadOnlyDictionary<ulong, string> zone_names, string[] subtable_names, string[] species)
{
for (var i = 0; i < t.EncounterTables.Length; i++)

View File

@@ -297,6 +297,11 @@ public void DumpWilds()
File.WriteAllLines(GetPath("Encounters_Symbol_Sword.txt"), EncounterTable8Util.GetLines(encount_symbol_sw, zones, subtables, species));
File.WriteAllLines(GetPath("Encounters_Shield.txt"), EncounterTable8Util.GetLines(encount_sh, zones, subtables, species));
File.WriteAllLines(GetPath("Encounters_Symbol_Shield.txt"), EncounterTable8Util.GetLines(encount_symbol_sh, zones, subtables, species));
File.WriteAllBytes(GetPath("encounter_sw_hidden.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, encount_sw), "sw"));
File.WriteAllBytes(GetPath("encounter_sh_hidden.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, encount_sh), "sh"));
File.WriteAllBytes(GetPath("encounter_sw_symbol.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, encount_symbol_sw), "sw"));
File.WriteAllBytes(GetPath("encounter_sh_symbol.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, encount_symbol_sh), "sh"));
}
public void DumpNestEntries()
@@ -457,6 +462,29 @@ public void DumpDistributionNestEntries(string path)
var dist_sh = TableUtil.GetTable(dist_encounts.Tables.Where(z => z.GameVersion == 2).SelectMany(z => z.Entries));
File.WriteAllText(GetPath("nestDist_sw.txt"), dist_sw);
File.WriteAllText(GetPath("nestDist_sh.txt"), dist_sh);
string[][] nestHex = new string[2][];
foreach (var game in new[] { 1, 2 })
{
var tables = dist_encounts.Tables.Where(z => z.GameVersion == game).ToList();
var encounters = tables.SelectMany((z, x) => z.GetSummary(speciesNames, x)).ToArray();
var path1 = GetPath($"nestHex{game}.txt");
File.WriteAllLines(path1, encounters);
nestHex[game - 1] = encounters;
var result = tables.Select(z => z.GetSummarySimple());
var path2 = GetPath($"nestDistFormat_{game}.txt");
File.WriteAllLines(path2, result);
}
var common = nestHex[0].Intersect(nestHex[1]).Where(z => z.StartsWith(" ")).Distinct();
var sword = nestHex[0].Where(z => !nestHex[1].Contains(z)).Distinct();
var shield = nestHex[1].Where(z => !nestHex[0].Contains(z)).Distinct();
File.WriteAllLines(GetPath("hex_nestDistCommon.txt"), common);
File.WriteAllLines(GetPath("hex_nestDistSword.txt"), sword);
File.WriteAllLines(GetPath("hex_nestDistShield.txt"), shield);
}
private static readonly int[] LanguageIndexes = { 0, 2, 3, 4, 5, 6, 7, 8, 9 };