Exemplo n.º 1
0
        public GeneralEventInfoData FindMatchingEventInfo(R1_EventData e)
        {
            byte[]   compiledCmds;
            ushort[] labelOffsets;

            if (UsesLocalCommands)
            {
                var compiledData = e.Commands == null ? null : EventCommandCompiler.Compile(e.Commands, e.Commands.ToBytes(Context.Settings));
                compiledCmds = compiledData?.Commands?.ToBytes(Context.Settings) ?? new byte[0];
                labelOffsets = compiledData?.LabelOffsets ?? new ushort[0];
            }
            else
            {
                compiledCmds = e.Commands?.ToBytes(Context.Settings) ?? new byte[0];
                labelOffsets = e.LabelOffsets ?? new ushort[0];
            }

            // Helper method for comparing the commands
            bool compareCommands(GeneralEventInfoData eventInfo) =>
            eventInfo.LabelOffsets.SequenceEqual(labelOffsets) &&
            eventInfo.Commands.SequenceEqual(compiledCmds);

            // Find a matching item
            var match = findMatch(EventMatchFlags.All) ??
                        findMatch(EventMatchFlags.All & ~EventMatchFlags.HitSprite & ~EventMatchFlags.Commands) ??
                        findMatch(EventMatchFlags.Type | EventMatchFlags.Etat | EventMatchFlags.SubEtat);

            GeneralEventInfoData findMatch(EventMatchFlags flags)
            {
                return(AvailableEvents.FindItem(x => (!flags.HasFlag(EventMatchFlags.Type) || x.Type == (ushort)e.Type) &&
                                                (!flags.HasFlag(EventMatchFlags.Etat) || x.Etat == e.Etat) &&
                                                (!flags.HasFlag(EventMatchFlags.SubEtat) || x.SubEtat == e.SubEtat) &&
                                                (!flags.HasFlag(EventMatchFlags.OffsetBX) || x.OffsetBX == e.OffsetBX) &&
                                                (!flags.HasFlag(EventMatchFlags.OffsetBY) || x.OffsetBY == e.OffsetBY) &&
                                                (!flags.HasFlag(EventMatchFlags.OffsetHY) || x.OffsetHY == e.OffsetHY) &&
                                                (!flags.HasFlag(EventMatchFlags.FollowSprite) || x.FollowSprite == e.FollowSprite) &&
                                                (!flags.HasFlag(EventMatchFlags.HitPoints) || x.HitPoints == e.ActualHitPoints) &&
                                                (!flags.HasFlag(EventMatchFlags.HitSprite) || x.HitSprite == e.HitSprite) &&
                                                (!flags.HasFlag(EventMatchFlags.FollowEnabled) || x.FollowEnabled == e.GetFollowEnabled(Context.Settings)) &&
                                                (!flags.HasFlag(EventMatchFlags.Commands) || compareCommands(x))));
            }

            // Log if not found
            if (match == null && AvailableEvents.Any())
            {
                Debug.LogWarning($"Matching event not found for event with type {e.Type}, etat {e.Etat} & subetat {e.SubEtat} in level {Settings.World}-{Settings.Level}");
            }

            // Return the item
            return(match);
        }
Exemplo n.º 2
0
        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;
                }
            }
        }
Exemplo n.º 3
0
 /// <summary>
 /// Gets a new event instance for Rayman
 /// </summary>
 public static R1_EventData GetRayman(Context context, R1_EventData rayPos) => new R1_EventData().InitRayman(context, rayPos);
Exemplo n.º 4
0
        /// <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);
        }