public Unity_Object_R1(R1_EventData eventData, Unity_ObjectManager_R1 objManager, int?ETAIndex = null, R1_WorldMapInfo worldInfo = null) { // Set properties EventData = eventData; ObjManager = objManager; TypeInfo = EventData.Type.GetAttribute <ObjTypeInfoAttribute>(); WorldInfo = worldInfo; // Set editor states EventData.InitialEtat = EventData.Etat; EventData.InitialSubEtat = EventData.SubEtat; //EventData.InitialDisplayPrio = EventData.DisplayPrio; EventData.InitialDisplayPrio = objManager.GetDisplayPrio(EventData.Type, EventData.HitPoints, EventData.DisplayPrio); EventData.InitialXPosition = (short)EventData.XPosition; EventData.InitialYPosition = (short)EventData.YPosition; EventData.RuntimeCurrentAnimIndex = 0; EventData.InitialHitPoints = EventData.HitPoints; UpdateZDC(); // Set random frame if (EventData.Type.UsesRandomFrame()) { ForceFrame = (byte)ObjManager.GetNextRandom(CurrentAnimation?.Frames.Length ?? 1); } // Find matching name from event sheet SecondaryName = ObjManager.FindMatchingEventInfo(EventData)?.Name; if (ETAIndex.HasValue) { if (ObjManager.UsesPointers) { EventData.ETAPointer = ObjManager.ETA[ETAIndex.Value].PrimaryPointer; } else { EventData.PC_ETAIndex = (uint)ETAIndex.Value; } } }
/// <summary> /// Loads the specified level for the editor /// </summary> /// <param name="context">The serialization context</param> /// <param name="loadTextures">Indicates if textures should be loaded</param> /// <returns>The level</returns> public override async UniTask <Unity_Level> LoadAsync(Context context, bool loadTextures) { // Get the level folder path var basePath = await GetLevelFolderPath(context); // TODO: Parse .ini file to get background etc. // Get file paths var mapPath = GetMapFilePath(basePath); var mapEventsPath = GetMapEventsFilePath(basePath); var saveEventsPath = GetSaveEventsFilePath(basePath); var pcxPath = GetPCXFilePath(context.Settings); var eventsCsvPath = GetEventManfiestFilePath(context.Settings.R1_World); // Load files to context await AddFile(context, mapPath); await AddFile(context, mapEventsPath, endianness : BinaryFile.Endian.Big); // Big endian just like on Jaguar await AddFile(context, pcxPath); // Read the files Controller.DetailedState = $"Loading map data"; await Controller.WaitIfNecessary(); var mapData = FileFactory.Read <MapData>(mapPath, context); Controller.DetailedState = $"Loading event data"; await Controller.WaitIfNecessary(); var mapEvents = FileFactory.Read <R1Jaguar_MapEvents>(mapEventsPath, context); var saveEvents = FileFactory.ReadText <R1_Mapper_SaveEvents>(saveEventsPath, context); var csv = FileFactory.ReadText <R1_Mapper_EventManifest>(eventsCsvPath, context); Controller.DetailedState = $"Loading tileset"; await Controller.WaitIfNecessary(); var pcx = FileFactory.Read <PCX>(pcxPath, context); // Get the palette from the PCX file var vgaPalette = pcx.VGAPalette; // Load the sprites var eventDesigns = loadTextures ? await LoadSpritesAsync(context, vgaPalette) : new Unity_ObjectManager_R1.DESData[0]; // Read the world data var worldData = FileFactory.Read <R1_PC_WorldFile>(GetWorldFilePath(context.Settings), context); var maps = new Unity_Map[] { new Unity_Map() { // Set the dimensions Width = mapData.Width, Height = mapData.Height, // Create the tile arrays TileSet = new Unity_MapTileMap[1], MapTiles = mapData.Tiles.Select(x => new Unity_Tile(x)).ToArray(), TileSetWidth = 1 } }; var allEventInstances = saveEvents.SaveEventInstances.SelectMany(x => x).ToArray(); // Create a linking table var linkTable = new ushort[allEventInstances.Length]; // Handle each event link group foreach (var linkedEvents in allEventInstances.Select((x, i) => new { Index = i, Data = x }).GroupBy(x => x.Data.LinkID)) { // Get the group var group = linkedEvents.ToArray(); // Handle every event for (int i = 0; i < group.Length; i++) { // Get the item var item = group[i]; if (group.Length == i + 1) { linkTable[item.Index] = (ushort)group[0].Index; } else { linkTable[item.Index] = (ushort)group[i + 1].Index; } } } // Create the object manager var objManager = new Unity_ObjectManager_R1( context: context, des: eventDesigns.Select((x, i) => new Unity_ObjectManager_R1.DataContainer <Unity_ObjectManager_R1.DESData>(x, i, worldData.DESFileNames?.ElementAtOrDefault(i))).ToArray(), eta: GetCurrentEventStates(context).Select((x, i) => new Unity_ObjectManager_R1.DataContainer <R1_EventState[][]>(x.States, i, worldData.ETAFileNames?.ElementAtOrDefault(i))).ToArray(), linkTable: linkTable, usesPointers: false, hasDefinedDesEtaNames: true); Controller.DetailedState = $"Loading events"; await Controller.WaitIfNecessary(); var levelEvents = new List <Unity_Object>(); // Create events for (var i = 0; i < saveEvents.SaveEventInstances.Length; i++) { // Get the map base position, based on the event map var mapPos = mapEvents.EventIndexMap.FindItemIndex(z => z == i + 1); // Get the x and y positions var mapY = (uint)Math.Floor(mapPos / (double)(mapEvents.Width)); var mapX = (uint)(mapPos - (mapY * mapEvents.Width)); // Calculate the actual position on the map mapX *= 4 * (uint)Settings.CellSize; mapY *= 4 * (uint)Settings.CellSize; // Add every instance foreach (var instance in saveEvents.SaveEventInstances[i]) { // Get the definition var def = csv.EventDefinitions.FirstOrDefault(x => x.Name == instance.EventDefinitionKey); if (def == null) { throw new Exception($"No matching event definition found for {instance.EventDefinitionKey}"); } var ed = new R1_EventData() { Type = def.Type, Etat = def.Etat, SubEtat = def.SubEtat, XPosition = (short)(mapX + instance.OffsetX), YPosition = (short)(mapY + instance.OffsetY), OffsetBX = def.OffsetBX, OffsetBY = def.OffsetBY, OffsetHY = def.OffsetHY, FollowSprite = def.FollowSprite, ActualHitPoints = (uint)instance.HitPoints, DisplayPrio = instance.DisplayPrio, HitSprite = def.HitSprite, PS1Demo_Unk1 = new byte[40], Unk_98 = new byte[5], LabelOffsets = new ushort[0], Commands = R1_EventCommandCollection.FromBytes(def.EventCommands, context.Settings), }; ed.SetFollowEnabled(context.Settings, def.FollowEnabled > 0); // Add the event levelEvents.Add(new Unity_Object_R1( eventData: ed, objManager: objManager, ETAIndex: worldData.ETAFileNames.FindItemIndex(x => x == def.ETAFile)) { DESIndex = worldData.DESFileNames.FindItemIndex(x => x.Length > 4 && x.Substring(0, x.Length - 4) == def.DESFile) }); } } // Convert levelData to common level format var level = new Unity_Level(maps, objManager, levelEvents, rayman: new Unity_Object_R1(R1_EventData.GetRayman(context, levelEvents.Cast <Unity_Object_R1>().FirstOrDefault(x => x.EventData.Type == R1_EventType.TYPE_RAY_POS)?.EventData), objManager)); Controller.DetailedState = $"Creating tileset"; await Controller.WaitIfNecessary(); // Load the tile set level.Maps[0].TileSet[0] = LoadTileSet(pcx); // Return the level return(level); }