pkNX/pkNX.WinForms/Subforms/PaldeaMap.cs
Kurt ec9c6d88a8
SV Teal Mask Support (#348)
Closes #347 
Closes #341 

Co-authored-by: Michael Scire <SciresM@gmail.com>
Co-authored-by: sora10pls <17801814+sora10pls@users.noreply.github.com>
Co-authored-by: Lusamine <30205550+Lusamine@users.noreply.github.com>
2023-10-05 18:57:41 -07:00

133 lines
6.4 KiB
C#

using System;
using System.Collections.Generic;
using pkNX.Game;
using pkNX.Structures;
using pkNX.Structures.FlatBuffers;
using pkNX.Structures.FlatBuffers.SV;
using pkNX.Structures.FlatBuffers.SV.Trinity;
namespace pkNX.WinForms.Subforms
{
public class PaldeaMap
{
public readonly List<string>[] AreaNames = { new(), new() };
private readonly Dictionary<string, AreaDef9>[] Areas = { new(), new() };
public readonly Dictionary<string, HavokCollision.AABBTree>[] AreaCollisionTrees = { new(), new() };
public readonly Dictionary<string, BoxCollision9>[] AreaCollisionBoxes = { new(), new() };
private readonly IList<FieldMainArea>[] MainAreas = new IList<FieldMainArea>[2];
private readonly IList<FieldSubArea>[] SubAreas = new IList<FieldSubArea>[2];
private readonly IList<FieldInsideArea>[] InsideAreas = new IList<FieldInsideArea>[2];
private readonly IList<FieldDungeonArea>[] DungeonAreas = new IList<FieldDungeonArea>[2];
private readonly IList<FieldLocation>[] FieldLocations = new IList<FieldLocation>[2];
public PaldeaMap(GameManagerSV ROM)
{
MainAreas[0] = FlatBufferConverter.DeserializeFrom<FieldMainAreaArray>(ROM.GetPackedFile("world/data/field/area/field_main_area/field_main_area_array.bin")).Table;
SubAreas[0] = FlatBufferConverter.DeserializeFrom<FieldSubAreaArray>(ROM.GetPackedFile("world/data/field/area/field_sub_area/field_sub_area_array.bin")).Table;
InsideAreas[0] = FlatBufferConverter.DeserializeFrom<FieldInsideAreaArray>(ROM.GetPackedFile("world/data/field/area/field_inside_area/field_inside_area_array.bin")).Table;
DungeonAreas[0] = FlatBufferConverter.DeserializeFrom<FieldDungeonAreaArray>(ROM.GetPackedFile("world/data/field/area/field_dungeon_area/field_dungeon_area_array.bin")).Table;
FieldLocations[0] = FlatBufferConverter.DeserializeFrom<FieldLocationArray>(ROM.GetPackedFile("world/data/field/area/field_location/field_location_array.bin")).Table;
MainAreas[1] = FlatBufferConverter.DeserializeFrom<FieldMainAreaArray>(ROM.GetPackedFile("world/data/field/area_su1/field_main_area_su1/field_main_area_su1_array.bin")).Table;
SubAreas[1] = FlatBufferConverter.DeserializeFrom<FieldSubAreaArray>(ROM.GetPackedFile("world/data/field/area_su1/field_sub_area_su1/field_sub_area_su1_array.bin")).Table;
InsideAreas[1] = FlatBufferConverter.DeserializeFrom<FieldInsideAreaArray>(ROM.GetPackedFile("world/data/field/area_su1/field_inside_area_su1/field_inside_area_su1_array.bin")).Table;
DungeonAreas[1] = FlatBufferConverter.DeserializeFrom<FieldDungeonAreaArray>(ROM.GetPackedFile("world/data/field/area_su1/field_dungeon_area_su1/field_dungeon_area_su1_array.bin")).Table;
FieldLocations[1] = FlatBufferConverter.DeserializeFrom<FieldLocationArray>(ROM.GetPackedFile("world/data/field/area_su1/field_location_su1/field_location_su1_array.bin")).Table;
LoadScenes(ROM);
}
private void LoadScenes(GameManagerSV ROM)
{
// Load default scenes
LoadScene(ROM, ROM.GetPackedFile("world/scene/parts/field/resident_event/resident_area_collision_/resident_area_collision_0.trscn"), 0);
// Load default scenes
LoadScene(ROM, ROM.GetPackedFile(0x441FE0A17C85BEAA), 1);
}
private void LoadScene(GameManagerSV ROM, byte[] collisionFile, int index)
{
var area_collision = FlatBufferConverter.DeserializeFrom<TrinitySceneObjectTemplate>(collisionFile);
foreach (var obj in area_collision.Objects)
{
if (obj is not { Type: "trinity_SceneObject", SubObjects.Count: > 0 })
continue;
if (obj.SubObjects[0].Type != "trinity_CollisionComponent")
continue;
var sceneObject = FlatBufferConverter.DeserializeFrom<TrinitySceneObject>(obj.Data);
var trcData = obj.SubObjects[0].Data;
var trc = FlatBufferConverter.DeserializeFrom<TrinityComponent>(trcData);
var collisionComponent = trc.Component.CollisionComponent;
AreaNames[index].Add(sceneObject.ObjectName);
var areaInfo = FindAreaInfo(index, sceneObject.ObjectName);
var shape = collisionComponent.Shape;
if (shape.TryGet(out Box? box))
{
// Box collision, obj.ObjectPosition.Field_02 is pos, box.Field_01 is size of box
AreaCollisionBoxes[index][sceneObject.ObjectName] = new BoxCollision9
{
Position = sceneObject.ObjectPosition.Field02,
Size = box!.Field01,
};
}
if (shape.TryGet(out Havok? havok))
{
var havokData = ROM.GetPackedFile(havok!.TrcolFilePath);
AreaCollisionTrees[index][sceneObject.ObjectName] = HavokCollision.ParseAABBTree(havokData);
}
Areas[index][sceneObject.ObjectName] = new AreaDef9
{
SceneObject = sceneObject,
CollisionComponent = collisionComponent,
Info = areaInfo,
};
}
}
public AreaInfo FindAreaInfo(int index, string name)
{
foreach (var area in MainAreas[index])
{
if (area.Name == name)
return area.Info;
}
foreach (var area in SubAreas[index])
{
if (area.Name == name)
return area.Info;
}
foreach (var area in InsideAreas[index])
{
if (area.Name == name)
return area.Info;
}
foreach (var area in DungeonAreas[index])
{
if (area.Name == name)
return area.Info;
}
foreach (var area in FieldLocations[index])
{
if (area.Name == name)
return area.Info;
}
throw new ArgumentException($"Unknown area {name}");
}
}
public class AreaDef9
{
public required TrinitySceneObject SceneObject;
public required CollisionComponent CollisionComponent;
public required AreaInfo Info;
}
}