private static void Stage2_MakeStartRoom(ref char[][] map, MapMeta meta, List <RoomMeta> rooms)
        {
            Random r = new Random((int)DateTime.Now.Ticks);

            int x = r.Next(0, meta.MapSizeX);
            int y = r.Next(0, meta.MapSizeY);

            for (int i = 0; i < meta.StartRoomSize; i++)
            {
                for (int j = 0; j < meta.StartRoomSize; j++)
                {
                    int pan = meta.StartRoomSize / 2;

                    if (x + (i - pan) >= 0 && x + (i - pan) < meta.MapSizeX &&
                        y + (j - pan) >= 0 && y + (j - pan) < meta.MapSizeY)
                    {
                        map[x + (i - pan)][y + (j - pan)] = (char)TileType.FLOOR;

                        if ((i - pan == 0) && (j - pan == 0))
                        {
                            map[x + (i - pan)][y + (j - pan)] = (char)TileType.FLOOR_START;

                            rooms.Add(new RoomMeta {
                                X           = x + (i - pan),
                                Y           = y + (j - pan),
                                Width       = meta.StartRoomSize,
                                Height      = meta.StartRoomSize,
                                Connections = 0
                            });
                        }
                    }
                }
            }
        }
Exemplo n.º 2
0
        public override void Update(Scene scene)
        {
            AreaData area = -1 < Area && Area < (AreaData.Areas?.Count ?? 0) ? AreaData.Get(Area) : null;
            MapMeta  meta = area?.GetMeta();

            bool wasFreeCam = inFreeCameraDebugMode;

            if (meta?.Mountain?.ShowCore ?? false)
            {
                Area = 9;
                orig_Update(scene);
                Area = area.ID;
            }
            else
            {
                orig_Update(scene);
            }

            Overworld overworld = scene as Overworld;

            if (!wasFreeCam && inFreeCameraDebugMode && (
                    ((overworld.Current ?? overworld.Next) is patch_OuiFileNaming naming && naming.UseKeyboardInput) ||
                    ((overworld.Current ?? overworld.Next) is OuiModOptionString stringInput && stringInput.UseKeyboardInput)))
            {
                // we turned on free cam mode (by pressing Space) while on an text entry screen using keyboard input... we should turn it back off.
                inFreeCameraDebugMode = false;
            }
        }
Exemplo n.º 3
0
        private IEnumerator Routine()
        {
            if (ErrorMessage != null)
            {
                string message = ErrorMessage;
                ErrorMessage = null;
                return(ErrorRoutine(message));
            }

            if (AreaData.Get(session) == null)
            {
                string message = Dialog.Get("postcard_levelgone")
                                 .Replace("((player))", SaveData.Instance.Name)
                                 .Replace("((sid))", session.Area.GetSID())
                ;
                return(ErrorRoutine(message));
            }

            AreaData areaData = AreaData.Get(session);
            MapMeta  areaMeta = areaData.GetMeta();

            if (areaMeta != null && areaData.GetLevelSet() != "Celeste" &&
                Dialog.Has(areaData.Name + "_postcard") &&
                session.StartedFromBeginning && !fromSaveData &&
                session.Area.Mode == AreaMode.Normal &&
                (!SaveData.Instance.Areas[session.Area.ID].Modes[0].Completed || SaveData.Instance.DebugMode))
            {
                return(EnterWithPostcardRoutine(Dialog.Get(areaData.Name + "_postcard"), areaMeta.PostcardSoundID));
            }

            return(orig_Routine());
        }
Exemplo n.º 4
0
        public static IEnumerator getMetaFile(BmobFile metaFile, Action <List <GameObject> > after)
        {
            MapMeta meta = null;

            yield return(TapOnUtils.downloadFile(
                             metaFile.url,
                             wr =>
            {
                meta = JsonUtility.FromJson <MapMeta>(wr.downloadHandler.text);
            }));

            List <GameObject>  objects = new List <GameObject>();
            List <IEnumerator> tasks   = new List <IEnumerator>();

            foreach (MapMeta.PropInfo propInfo in meta.Props)
            {
                if (propInfo.type == MapMeta.PropType.Text)
                {
                    GameObject instance = GameObject.Instantiate(Globals.instance.templetes[0]);
                    instance.tag = "word";
                    instance.SetActive(false);
                    TextMesh tm = instance.GetComponentInChildren <TextMesh>();
                    tm.text = propInfo.text;
                    instance.transform.position   = new Vector3(propInfo.Position[0], propInfo.Position[1], propInfo.Position[2]);
                    instance.transform.rotation   = new Quaternion(propInfo.Rotation[0], propInfo.Rotation[1], propInfo.Rotation[2], propInfo.Rotation[3]);
                    instance.transform.localScale = new Vector3(propInfo.Scale[0], propInfo.Scale[1], propInfo.Scale[2]);
                    objects.Add(instance);
                }
                if (propInfo.type == MapMeta.PropType.Texture)
                {
                    GameObject instance = GameObject.Instantiate(Globals.instance.templetes[1]);
                    instance.tag = "texture";
                    instance.SetActive(false);
                    Renderer rd = instance.GetComponentInChildren <Renderer>();
                    instance.transform.position   = new Vector3(propInfo.Position[0], propInfo.Position[1], propInfo.Position[2]);
                    instance.transform.rotation   = new Quaternion(propInfo.Rotation[0], propInfo.Rotation[1], propInfo.Rotation[2], propInfo.Rotation[3]);
                    instance.transform.localScale = new Vector3(propInfo.Scale[0], propInfo.Scale[1], propInfo.Scale[2]);
                    objects.Add(instance);

                    IEnumerator downloadTexture = TapOnUtils.downloadFile(
                        propInfo.infoUrl,
                        wr_dt =>
                    {
                        Texture2D texture = new Texture2D(10, 10);
                        texture.LoadImage(wr_dt.downloadHandler.data);
                        rd.material.mainTexture = texture;
                    });
                    tasks.Add(downloadTexture);
                }
            }
            foreach (IEnumerator t in tasks)
            {
                yield return(t);
            }
            if (after != null)
            {
                after(objects);
            }
        }
        private static void Stage3_MakeRooms(ref char[][] map, MapMeta meta, List <RoomMeta> rooms)
        {
            // TODO: Try to remove overlapping
            for (int k = 0; k < meta.MaxRoomNumber;)
            {
RetryRoomPositioning:
                int x = RandomNumber.Between(0, meta.MapSizeX);
                int y = RandomNumber.Between(0, meta.MapSizeY);

                Point pt = new Point(x, y);

                for (int i = 0; i < rooms.Count; i++)
                {
                    if ((pt - new Point(rooms[i].X, rooms[i].Y)).LengthSquared < meta.MinRoomDistance)
                    {
                        //Console.WriteLine("Failed to make room, dist=" + (pt - new Point(rooms[i].X, rooms[i].Y)).LengthSquared
                        //    + ", but meta.MinRoomDistance is " + meta.MinRoomDistance);
                        goto RetryRoomPositioning;
                    }
                }

                int w = RandomNumber.Between(meta.MinRoomSize, meta.MaxRoomSize);
                int h = RandomNumber.Between(meta.MinRoomSize, meta.MaxRoomSize);

                for (int i = 0; i < w; i++)
                {
                    for (int j = 0; j < h; j++)
                    {
                        int panW = w / 2;
                        int panH = h / 2;

                        if (x + (i - panW) >= 0 && x + (i - panW) < meta.MapSizeX &&
                            y + (j - panH) >= 0 && y + (j - panH) < meta.MapSizeY)
                        {
                            if (map[x + (i - panW)][y + (j - panH)] != (char)TileType.FLOOR_START)
                            {
                                map[x + (i - panW)][y + (j - panH)] = (char)TileType.FLOOR;
                            }

                            if ((i - panW == 0) && (j - panH == 0))
                            {
                                rooms.Add(new RoomMeta
                                {
                                    X           = x + (i - panW),
                                    Y           = y + (j - panH),
                                    Width       = w,
                                    Height      = h,
                                    Connections = 0
                                });
                            }
                        }
                    }
                }

                k++;
            }
        }
        private static void Stage8_InsertComponent(ref char[][] map, MapMeta meta, List <RoomMeta> rooms, List <string> componentsPath)
        {
            // Insert pre built map from filePath, but not near rooms[0] (starting area)
            foreach (string filePath in componentsPath)
            {
                string[] dataRaw  = File.ReadAllLines(filePath);
                var      totalRow = dataRaw.Length;

                if (totalRow < 2)
                {
                    continue;
                }

                var chance = Convert.ToInt32(dataRaw[0]);

                // get component size
                int width  = dataRaw[1].Length;
                int height = totalRow - 1;

                // choose random coordinates
RetryComponentPositioning:
                int x = RandomNumber.Between(0, meta.MapSizeX - width - 1);
                int y = RandomNumber.Between(0, meta.MapSizeY - height - 1);

                Point pt = new Point(x, y);

                if ((pt - new Point(rooms[0].X, rooms[0].Y)).LengthSquared < meta.MinRoomDistance ||
                    (pt - new Point(rooms[0].X - width, rooms[0].Y - height)).LengthSquared < meta.MinRoomDistance)
                {
                    goto RetryComponentPositioning;
                }

                // try roll
                if (RandomNumber.Between(0, (int)(ChancePool / Convert.ToDouble(dataRaw[0]))) == 0)
                {
                    Console.WriteLine("Inserting component : " + filePath + ", size=" + width + "x" + height);

                    // insert
                    for (int i = 0; i < height; i++)
                    {
                        string line = dataRaw[i + 1];

                        for (int j = 0; j < width; j++)
                        {
                            map[x + j][y + i] = (char)(line[j] - '0');
                        }
                    }
                }

                // TODO: try connect if isolated

                return;
            }
        }
        private static char[][] Stage1_MapInit(MapMeta meta)
        {
            char[][] map = new char[meta.MapSizeX][];

            for (int i = 0; i < meta.MapSizeX; i++)
            {
                map[i] = new char[meta.MapSizeY];
            }

            return(map);
        }
Exemplo n.º 8
0
        public void OnLoad(MapEventArgs e)
        {
            e.Map.FileName = Path.GetFileNameWithoutExtension(e.FilePath);
            string filePath = Directory.GetParent(e.FilePath).ToString();

            m_mapMeta = m_dataStore.Load <MapMeta>($"{filePath}\\{e.Map.FileName}.MapMeta");

            // no file was found, create new map
            if (m_mapMeta == null)
            {
                m_mapMeta = new MapMeta();
            }
        }
Exemplo n.º 9
0
 private static bool resolveModel(MapMeta meta, string modelName, out ModAsset matchingAsset, out string path)
 {
     if (Everest.Content.TryGet(Path.Combine(meta.Mountain.MountainModelDirectory, modelName + ".obj"), out matchingAsset) && matchingAsset.Type == typeof(AssetTypeObjModelExport))
     {
         path = Path.Combine(meta.Mountain.MountainModelDirectory, modelName + ".export").Replace("\\", "/");
         return(true);
     }
     else if (Everest.Content.TryGet(Path.Combine(meta.Mountain.MountainModelDirectory, modelName), out matchingAsset) && matchingAsset.Type == typeof(ObjModel))
     {
         path = Path.Combine(meta.Mountain.MountainModelDirectory, modelName + ".obj").Replace("\\", "/");
         return(true);
     }
     path = null;
     return(false);
 }
Exemplo n.º 10
0
        public override void Update(Scene scene)
        {
            AreaData area = -1 < Area && Area < (AreaData.Areas?.Count ?? 0) ? AreaData.Get(Area) : null;
            MapMeta  meta = area?.GetMeta();

            if (meta?.Mountain?.ShowCore ?? false)
            {
                Area = 9;
                orig_Update(scene);
                Area = area.ID;
            }
            else
            {
                orig_Update(scene);
            }
        }
Exemplo n.º 11
0
        private static void Stage7_MakePrefab(
            ref char[][] map,
            MapMeta meta,
            List <Corridors> corridors,
            List <Prefabs> prefabs)
        {
            // If tile is Floor, have chance to make something
            bool[][] visited = new bool[meta.MapSizeX][];

            for (int i = 0; i < meta.MapSizeX; i++)
            {
                visited[i] = new bool[meta.MapSizeY];
            }

            for (int i = 0; i < corridors.Count; i++)
            {
                Stack <Point> stack = corridors[i].CorridorData;

                for (int j = 0; j < stack.Count; j++)
                {
                    Point pt = stack.Pop();

                    // Not sure why this sentence hit
                    if (pt.X + 1 > meta.MapSizeX || pt.X < 0 ||
                        pt.Y + 1 > meta.MapSizeY || pt.Y < 0)
                    {
                        continue;
                    }

                    if (map[(int)pt.X][(int)pt.Y] == (char)TileType.FLOOR &&
                        visited[(int)pt.X][(int)pt.Y] == false)
                    {
                        for (int k = 0; k < prefabs.Count; k++)
                        {
                            if (RandomNumber.Between(0, (int)(ChancePool / (double)prefabs[k].SpawnChance))
                                == 0)
                            {
                                map[(int)pt.X][(int)pt.Y] = (char)prefabs[k].Tile;
                            }

                            visited[(int)pt.X][(int)pt.Y] = true;
                        }
                    }
                }
            }
        }
Exemplo n.º 12
0
        private static void Stage6_ConnectionValidate(
            ref char[][] map,
            MapMeta meta,
            List <RoomMeta> rooms,
            List <Corridors> corridors)
        {
            bool[]           connected = new bool[rooms.Count];
            LinkedList <int> list      = new LinkedList <int>();

            for (int i = 1; i < connected.Length; i++)
            {
                if (connected[i] == false)
                {
                    Aux_RoomValidationUpdate(ref connected, list, corridors);
                    Stage4_ConnectRooms(ref map, meta, rooms, corridors, 0, i);
                    connected[i] = true;
                }
            }
        }
Exemplo n.º 13
0
        private static void Stage5_MakeCorridorBranch(
            ref char[][]    map,
            MapMeta meta,
            List <RoomMeta> rooms,
            List <Corridors> corridors)
        {
            // TODO: Beautify random corridors

            // Make branches of exist corridors
            for (int i = 0; i < corridors.Count; i++)
            {
                Stack <Point> stack = corridors[i].CorridorData;

                if (corridors.Count > meta.MaxCorridorBranchCount)
                {
                    break;
                }

                for (int j = 0; stack.Count > 0; j++)
                {
                    Point coord = stack.Pop();

                    if (coord.X < 0 || coord.X + 1 > meta.MapSizeX ||
                        coord.Y < 0 || coord.Y + 1 > meta.MapSizeY)
                    {
                        continue;
                    }

                    if (corridors[i].IsBranch == false &&
                        RandomNumber.Between(0, meta.RouteBranchFactor) == 0)
                    {
                        Aux_MakeRandomCorridor(ref map, meta, coord, corridors);
                    }
                    else if (corridors[i].IsBranch == true &&
                             RandomNumber.Between(0, meta.RouteAdditionalBranchFactor) == 0)
                    {
                        Aux_MakeRandomCorridor(ref map, meta, coord, corridors);
                    }
                }
            }
        }
Exemplo n.º 14
0
        private void ProcessMeta(BinaryPacker.Element meta)
        {
            AreaData area = AreaData.Get(Area);
            AreaMode mode = Area.Mode;

            if (mode == AreaMode.Normal)
            {
                new MapMeta(meta).ApplyTo(area);
                Area = area.ToKey();

                // Backup A-Side's Metadata. Only back up useful data.
                area.SetASideAreaDataBackup(new AreaData {
                    IntroType     = area.IntroType,
                    ColorGrade    = area.ColorGrade,
                    DarknessAlpha = area.DarknessAlpha,
                    BloomBase     = area.BloomBase,
                    BloomStrength = area.BloomStrength,
                    CoreMode      = area.CoreMode,
                    Dreaming      = area.Dreaming
                });
            }

            BinaryPacker.Element modeMeta = meta.Children?.FirstOrDefault(el => el.Name == "mode");
            if (modeMeta == null)
            {
                return;
            }

            new MapMetaModeProperties(modeMeta).ApplyTo(area, mode);

            // Metadata for B-Side and C-Side are parsed and stored.
            if (mode != AreaMode.Normal)
            {
                MapMeta mapMeta = new MapMeta(meta)
                {
                    Modes = area.GetMeta().Modes
                };
                area.Mode[(int)mode].SetMapMeta(mapMeta);
            }
        }
Exemplo n.º 15
0
 public static void SetMapMeta(this ModeProperties self, MapMeta value)
 => ((patch_ModeProperties)self).MapMeta = value;
Exemplo n.º 16
0
        private static void Stage4_ConnectRooms(
            ref char[][] map,
            MapMeta meta,
            List <RoomMeta> rooms,
            List <Corridors> corridors,
            int overrideRoomStart,
            int overrideRoomTarget)
        {
            bool completeFlag = false;
            bool overrideFlag = false;

            if (overrideRoomStart != 0 || overrideRoomTarget != 0)
            {
                overrideFlag = true;
            }

            if (meta.MaxRoomNumber != rooms.Count)
            {
                meta.MaxRoomNumber = rooms.Count;
            }

            while (completeFlag == false)
            {
                Stack <Point> stack      = new Stack <Point>();
                int           targetRoom = RandomNumber.Between(1, meta.MaxRoomNumber - 1);
                int           startRoom  = 0;
                int           maxConn    = RandomNumber.Between(1, meta.MaxRoomConnection);

                for (int i = 0; i < rooms.Count; i++)
                {
                    if (rooms[i].Connections < maxConn)
                    {
                        startRoom = i;
                        break;
                    }

                    // there is no more room that 0 connection
                    if (i == rooms.Count - 1)
                    {
                        completeFlag = true;
                    }
                }

                if (overrideFlag)
                {
                    startRoom    = overrideRoomStart;
                    targetRoom   = overrideRoomTarget;
                    completeFlag = true;
                }

                // starting position
                stack.Push(new Point {
                    X = rooms[startRoom].X, Y = rooms[startRoom].Y
                });

                Point  start  = stack.Pop();
                int    curX   = (int)start.X;
                int    curY   = (int)start.Y;
                double dist   = double.MaxValue;
                int    cs     = RandomNumber.Between(meta.MinCorridorStraight, meta.MaxCorridorStraight);
                int    headTo = 0;

                while (dist > 1.412)
                {
                    // Readjust point that out of bound
                    double distN = (new Point(curX, curY + 1) - new Point(rooms[targetRoom].X, rooms[targetRoom].Y)).LengthSquared;
                    double distS = (new Point(curX, curY - 1) - new Point(rooms[targetRoom].X, rooms[targetRoom].Y)).LengthSquared;
                    double distW = (new Point(curX - 1, curY) - new Point(rooms[targetRoom].X, rooms[targetRoom].Y)).LengthSquared;
                    double distE = (new Point(curX + 1, curY) - new Point(rooms[targetRoom].X, rooms[targetRoom].Y)).LengthSquared;

                    double min = Math.Min(distE, Math.Min(distW, Math.Min(distN, distS)));

                    // Corridor twister here (set on meta) - 0, 4 = 25%
                    int rb = RandomNumber.Between(0, meta.RouteTwistFactor);

                    if (rb == 0)
                    {
                        int rc = RandomNumber.Between(0, 4);

                        if (rc == N)
                        {
                            min = distN;
                        }
                        else if (rc == S)
                        {
                            min = distS;
                        }
                        else if (rc == W)
                        {
                            min = distW;
                        }
                        else if (rc == E)
                        {
                            min = distE;
                        }
                    }

                    dist = min;

                    // Boundary check
                    if (curX > meta.MapSizeX)
                    {
                        curX--; continue;
                    }
                    else if (curY > meta.MapSizeY)
                    {
                        curY--; continue;
                    }
                    else if (curX - 1 < 0)
                    {
                        curX++; continue;
                    }
                    else if (curY - 1 < 0)
                    {
                        curY++; continue;
                    }

                    // Push cursor
                    if (min == distN)
                    {
                        stack.Push(new Point {
                            X = curX, Y = ++curY
                        }); headTo = N;
                    }
                    if (min == distS)
                    {
                        stack.Push(new Point {
                            X = curX, Y = --curY
                        }); headTo = S;
                    }
                    if (min == distW)
                    {
                        stack.Push(new Point {
                            X = --curX, Y = curY
                        }); headTo = W;
                    }
                    if (min == distE)
                    {
                        stack.Push(new Point {
                            X = ++curX, Y = curY
                        }); headTo = E;
                    }

                    // Make corridor straight
                    int straight = RandomNumber.Between(0, meta.RouteDirectFactor);

                    if (straight == 0)
                    {
                        cs = RandomNumber.Between(meta.MinCorridorStraight, meta.MaxCorridorStraight);

                        switch (headTo)
                        {
                        case N:
                            for (int i = 0; i < cs; i++)
                            {
                                stack.Push(new Point {
                                    X = curX, Y = ++curY
                                });
                            }
                            break;

                        case S:
                            for (int i = 0; i < cs; i++)
                            {
                                stack.Push(new Point {
                                    X = curX, Y = --curY
                                });
                            }
                            break;

                        case W:
                            for (int i = 0; i < cs; i++)
                            {
                                stack.Push(new Point {
                                    X = --curX, Y = curY
                                });
                            }
                            break;

                        case E:
                            for (int i = 0; i < cs; i++)
                            {
                                stack.Push(new Point {
                                    X = ++curX, Y = curY
                                });
                            }
                            break;

                        default:
                            break;
                        }
                    }
                }

                // Save corridors data
                Stack <Point> tmp = new Stack <Point>();
                tmp = CopyStack.Clone(stack);
                Corridors crd = new Corridors
                {
                    CorridorData    = tmp,
                    IsBranch        = false,
                    CorridorStartAt = startRoom,
                    CorridorEndAt   = targetRoom,
                };
                corridors.Add(crd);

                // Draw path
                while (stack.Count > 0)
                {
                    Point pt = stack.Pop();

                    if (pt.X < meta.MapSizeX &&
                        pt.X >= 0 &&
                        pt.Y < meta.MapSizeY &&
                        pt.Y >= 0)
                    {
                        if (map[(int)pt.X][(int)pt.Y] != (char)TileType.FLOOR_START)
                        {
                            map[(int)pt.X][(int)pt.Y] = (char)TileType.FLOOR;
                        }
                    }
                }

                // Add connections
                rooms[startRoom].Connections++;
                rooms[targetRoom].Connections++;
            }
        }
Exemplo n.º 17
0
 private static bool hasCustomSettings(MapMeta meta)
 {
     return(!string.IsNullOrEmpty(meta.Mountain.MountainModelDirectory) || !string.IsNullOrEmpty(meta.Mountain.MountainTextureDirectory) ||
            meta.Mountain.FogColors != null || !string.IsNullOrEmpty(meta.Mountain.StarFogColor) || meta.Mountain.StarStreamColors != null ||
            (meta.Mountain.StarBeltColors1 != null && meta.Mountain.StarBeltColors2 != null));
 }
Exemplo n.º 18
0
        private static int AreaComparison(AreaData a, AreaData b)
        {
            string  aSet  = a.GetLevelSet();
            string  aSID  = a.GetSID();
            MapMeta aMeta = a.GetMeta();
            string  bSet  = b.GetLevelSet();
            string  bSID  = b.GetSID();
            MapMeta bMeta = b.GetMeta();

            // Celeste appears before everything else.
            if (aSet == "Celeste" && bSet != "Celeste")
            {
                return(-1);
            }
            if (aSet != "Celeste" && bSet == "Celeste")
            {
                return(1);
            }

            // Uncategorized appears after everything else.
            if (string.IsNullOrEmpty(aSet) && !string.IsNullOrEmpty(bSet))
            {
                return(1);
            }
            if (!string.IsNullOrEmpty(aSet) && string.IsNullOrEmpty(bSet))
            {
                return(-1);
            }

            // Compare level sets alphabetically.
            if (aSet != bSet)
            {
                return(string.Compare(aSet, bSet));
            }

            // Put "parented" levels at the end.
            if (!string.IsNullOrEmpty(aMeta?.Parent) && string.IsNullOrEmpty(bMeta?.Parent))
            {
                return(1);
            }
            if (string.IsNullOrEmpty(aMeta?.Parent) && !string.IsNullOrEmpty(bMeta?.Parent))
            {
                return(-1);
            }

            int?     aOrder;
            AreaMode aSide;
            string   aName;

            ParseName(aSID, out aOrder, out aSide, out aName);

            int?     bOrder;
            AreaMode bSide;
            string   bName;

            ParseName(bSID, out bOrder, out bSide, out bName);

            // put the "unordered" levels at the end. (Farewell is one of them.)
            if (aOrder != null && bOrder == null)
            {
                return(-1);
            }

            if (aOrder == null && bOrder != null)
            {
                return(1);
            }

            // order the rest by order, then by name, then by side
            if (aOrder != null && bOrder != null && aOrder.Value != bOrder.Value)
            {
                return(aOrder.Value - bOrder.Value);
            }

            if (aName != bName)
            {
                return(string.Compare(aName, bName));
            }

            if (aSide != bSide)
            {
                return(aSide - bSide);
            }

            // everything is the same: this is the same level
            return(0);
        }
Exemplo n.º 19
0
        private void ProcessLevels(BinaryPacker.Element levels)
        {
            AreaData       area = AreaData.Get(Area);
            ModeProperties mode = area.Mode[(int)Area.Mode];

            // Mod levels are... different.

            // levels.Children.Sort((a, b) => a.Attr("name").Replace("lvl_", "").CompareTo(b.Attr("name").Replace("lvl_", "")));

            int checkpoint = 0;
            List <CheckpointData> checkpointsAuto = null;

            if (mode.Checkpoints == null)
            {
                checkpointsAuto = new List <CheckpointData>();
            }

            int strawberry             = 0;
            int strawberryInCheckpoint = 0;

            if (levels.Children != null)
            {
                foreach (BinaryPacker.Element level in levels.Children)
                {
                    string[] levelTags = level.Attr("name").Split(':');
                    string   levelName = levelTags[0];
                    if (levelName.StartsWith("lvl_"))
                    {
                        levelName = levelName.Substring(4);
                    }
                    level.SetAttr("name", "lvl_" + levelName); // lvl_ was optional before Celeste 1.2.5.0 made it mandatory.

                    BinaryPacker.Element entities = level.Children.FirstOrDefault(el => el.Name == "entities");
                    BinaryPacker.Element triggers = level.Children.FirstOrDefault(el => el.Name == "triggers");

                    // Celeste 1.2.5.0 optimizes BinaryPacker, which causes some issues.
                    // Let's "unoptimize" entities and triggers.
                    if (entities == null)
                    {
                        level.Children.Add(entities = new BinaryPacker.Element {
                            Name = "entities"
                        });
                    }
                    if (entities.Children == null)
                    {
                        entities.Children = new List <BinaryPacker.Element>();
                    }

                    if (triggers == null)
                    {
                        level.Children.Add(triggers = new BinaryPacker.Element {
                            Name = "triggers"
                        });
                    }
                    if (triggers.Children == null)
                    {
                        triggers.Children = new List <BinaryPacker.Element>();
                    }

                    if (levelTags.Contains("checkpoint") || levelTags.Contains("cp"))
                    {
                        entities.Children.Add(new BinaryPacker.Element {
                            Name       = "checkpoint",
                            Attributes = new Dictionary <string, object>()
                            {
                                { "x", "0" },
                                { "y", "0" }
                            }
                        });
                    }

                    if (level.AttrBool("space"))
                    {
                        if (level.AttrBool("spaceSkipWrap") || levelTags.Contains("nospacewrap") || levelTags.Contains("nsw"))
                        {
                            entities.Children.Add(new BinaryPacker.Element {
                                Name = "everest/spaceControllerBlocker"
                            });
                        }
                        if (level.AttrBool("spaceSkipGravity") || levelTags.Contains("nospacegravity") || levelTags.Contains("nsg"))
                        {
                            entities.Children.Add(new BinaryPacker.Element {
                                Name = "everest/spaceController"
                            });
                            level.SetAttr("space", false);
                        }

                        if (!levelTags.Contains("nospacefix") && !levelTags.Contains("nsf") &&
                            !triggers.Children.Any(el => el.Name == "cameraTargetTrigger") &&
                            !entities.Children.Any(el => el.Name == "everest/spaceControllerBlocker"))
                        {
                            // Camera centers tile-perfectly on uneven heights.
                            int heightForCenter = level.AttrInt("height");
                            heightForCenter /= 8;
                            if (heightForCenter % 2 == 0)
                            {
                                heightForCenter--;
                            }
                            heightForCenter *= 8;

                            triggers.Children.Add(new BinaryPacker.Element {
                                Name       = "cameraTargetTrigger",
                                Attributes = new Dictionary <string, object>()
                                {
                                    { "x", 0f },
                                    { "y", 0f },
                                    { "width", level.AttrInt("width") },
                                    { "height", level.AttrInt("height") },
                                    { "yOnly", true },
                                    { "lerpStrength", 1f }
                                },
                                Children = new List <BinaryPacker.Element>()
                                {
                                    new BinaryPacker.Element {
                                        Attributes = new Dictionary <string, object>()
                                        {
                                            { "x", 160f },
                                            { "y", heightForCenter / 2f }
                                        }
                                    }
                                }
                            });
                        }
                    }

                    foreach (BinaryPacker.Element levelChild in level.Children)
                    {
                        switch (levelChild.Name)
                        {
                        case "entities":
                            foreach (BinaryPacker.Element entity in levelChild.Children)
                            {
                                switch (entity.Name)
                                {
                                case "checkpoint":
                                    if (checkpointsAuto != null)
                                    {
                                        CheckpointData c = new CheckpointData(
                                            levelName,
                                            (area.GetSID() + "_" + levelName).DialogKeyify(),
                                            MapMeta.GetInventory(entity.Attr("inventory")),
                                            entity.Attr("dreaming") == "" ? area.Dreaming : entity.AttrBool("dreaming"),
                                            null
                                            );
                                        int id = entity.AttrInt("checkpointID", -1);
                                        if (id == -1)
                                        {
                                            checkpointsAuto.Add(c);
                                        }
                                        else
                                        {
                                            while (checkpointsAuto.Count <= id)
                                            {
                                                checkpointsAuto.Add(null);
                                            }
                                            checkpointsAuto[id] = c;
                                        }
                                    }
                                    checkpoint++;
                                    strawberryInCheckpoint = 0;
                                    break;

                                case "cassette":
                                    if (area.CassetteCheckpointIndex == 0)
                                    {
                                        area.CassetteCheckpointIndex = checkpoint;
                                    }
                                    break;

                                case "strawberry":
                                    if (entity.AttrInt("checkpointID", -1) == -1)
                                    {
                                        entity.SetAttr("checkpointID", checkpoint);
                                    }
                                    if (entity.AttrInt("order", -1) == -1)
                                    {
                                        entity.SetAttr("order", strawberryInCheckpoint);
                                    }
                                    strawberry++;
                                    strawberryInCheckpoint++;
                                    break;
                                }
                            }
                            break;
                        }
                    }
                }
            }

            if (mode.Checkpoints == null)
            {
                mode.Checkpoints = checkpointsAuto.Where(c => c != null).ToArray();
            }
        }
Exemplo n.º 20
0
        public void ctor(Session session, Vector2?startPosition = default(Vector2?))
        {
            if (CoreModule.Settings.LazyLoading)
            {
                VirtualContentExt.UnloadOverworld();
            }

            // Vanilla TileToIndex mappings.
            SurfaceIndex.TileToIndex = new Dictionary <char, int> {
                { '1', 3 },
                { '3', 4 },
                { '4', 7 },
                { '5', 8 },
                { '6', 8 },
                { '7', 8 },
                { '8', 8 },
                { '9', 13 },
                { 'a', 8 },
                { 'b', 23 },
                { 'c', 8 },
                { 'd', 8 },
                { 'e', 8 },
                { 'f', 8 },
                { 'g', 8 },
                { 'h', 33 },
                { 'i', 4 },
                { 'j', 8 },
                { 'k', 3 },
                { 'l', 33 },
                { 'm', 3 }
            };

            AreaData area = AreaData.Get(session);
            MapMeta  meta = area.GetMeta();
            string   path;

            path = meta?.BackgroundTiles;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "BackgroundTiles.xml");
            }
            GFX.BGAutotiler = new Autotiler(path);

            path = meta?.ForegroundTiles;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "ForegroundTiles.xml");
            }
            GFX.FGAutotiler = new Autotiler(path);

            path = meta?.AnimatedTiles;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "AnimatedTiles.xml");
            }
            GFX.AnimatedTilesBank = new AnimatedTilesBank();
            XmlElement animatedData = Calc.LoadContentXML(path)["Data"];

            foreach (XmlElement el in animatedData)
            {
                if (el != null)
                {
                    GFX.AnimatedTilesBank.Add(
                        el.Attr("name"),
                        el.AttrFloat("delay", 0f),
                        el.AttrVector2("posX", "posY", Vector2.Zero),
                        el.AttrVector2("origX", "origY", Vector2.Zero),
                        GFX.Game.GetAtlasSubtextures(el.Attr("path"))
                        );
                }
            }

            path = meta?.Sprites;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "Sprites.xml");
            }
            GFX.SpriteBank = new SpriteBank(GFX.Game, path);

            path = meta?.Portraits;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "Portraits.xml");
            }
            GFX.PortraitsSpriteBank = new SpriteBank(GFX.Portraits, path);

            orig_ctor(session, startPosition);
        }
Exemplo n.º 21
0
        public static new void Load()
        {
            orig_Load();

            foreach (AreaData area in Areas)
            {
                area.SetSID("Celeste/" + area.Mode[0].Path);
            }

            // Separate array as we sort it afterwards.
            List <AreaData> modAreas = new List <AreaData>();

            foreach (ModAsset asset in Everest.Content.ListMaps)
            {
                string  path = asset.PathMapped.Substring(5);
                MapMeta meta = asset.GetMeta <MapMeta>();

                AreaData area = new AreaData();

                // Default values.

                area.SetSID(path);

                area.Name = path;
                area.Icon = "areas/" + path.ToLowerInvariant();
                if (!GFX.Gui.Has(area.Icon))
                {
                    area.Icon = "areas/null";
                }

                area.TitleBaseColor   = Calc.HexToColor("6c7c81");
                area.TitleAccentColor = Calc.HexToColor("2f344b");
                area.TitleTextColor   = Color.White;

                area.IntroType = Player.IntroTypes.WakeUp;

                area.Dreaming   = false;
                area.ColorGrade = null;

                area.Mode = new ModeProperties[] {
                    new ModeProperties {
                        Path       = asset.PathMapped.Substring(5),
                        Inventory  = PlayerInventory.Default,
                        AudioState = new AudioState(Sfxs.music_city, Sfxs.env_amb_00_main)
                    }
                };

                area.Wipe = (Scene scene, bool wipeIn, Action onComplete)
                            => new AngledWipe(scene, wipeIn, onComplete);

                area.DarknessAlpha = 0.05f;
                area.BloomBase     = 0f;
                area.BloomStrength = 1f;

                area.Jumpthru = "wood";

                area.CassseteNoteColor = Calc.HexToColor("33a9ee");
                area.CassetteSong      = Sfxs.cas_01_forsaken_city;

                // Custom values.
                if (meta != null)
                {
                    if (!string.IsNullOrEmpty(meta.Name))
                    {
                        area.Name = meta.Name;
                    }

                    if (!string.IsNullOrEmpty(meta.SID))
                    {
                        area.SetSID(meta.SID);
                    }

                    if (!string.IsNullOrEmpty(meta.Icon) && GFX.Gui.Has(meta.Icon))
                    {
                        area.Icon = meta.Icon;
                    }

                    area.Interlude = meta.Interlude;
                    if (!string.IsNullOrEmpty(meta.CompleteScreenName))
                    {
                        area.CompleteScreenName = meta.CompleteScreenName;
                    }

                    area.CassetteCheckpointIndex = meta.CassetteCheckpointIndex;

                    if (!string.IsNullOrEmpty(meta.TitleBaseColor))
                    {
                        area.TitleBaseColor = Calc.HexToColor(meta.TitleBaseColor);
                    }
                    if (!string.IsNullOrEmpty(meta.TitleAccentColor))
                    {
                        area.TitleAccentColor = Calc.HexToColor(meta.TitleAccentColor);
                    }
                    if (!string.IsNullOrEmpty(meta.TitleTextColor))
                    {
                        area.TitleTextColor = Calc.HexToColor(meta.TitleTextColor);
                    }

                    area.IntroType = meta.IntroType;

                    area.Dreaming = meta.Dreaming;
                    if (!string.IsNullOrEmpty(meta.ColorGrade))
                    {
                        area.ColorGrade = meta.ColorGrade;
                    }

                    area.Mode = MapMeta.Convert(meta.Modes) ?? area.Mode;

                    if (!string.IsNullOrEmpty(meta.Wipe))
                    {
                        Type            type = Assembly.GetEntryAssembly().GetType(meta.Wipe);
                        ConstructorInfo ctor = type?.GetConstructor(new Type[] { typeof(Scene), typeof(bool), typeof(Action) });
                        if (type != null && ctor != null)
                        {
                            area.Wipe = (scene, wipeIn, onComplete) => ctor.Invoke(new object[] { scene, wipeIn, onComplete });
                        }
                    }

                    area.DarknessAlpha = meta.DarknessAlpha;
                    area.BloomBase     = meta.BloomBase;
                    area.BloomStrength = meta.BloomStrength;

                    if (!string.IsNullOrEmpty(meta.Jumpthru))
                    {
                        area.Jumpthru = meta.Jumpthru;
                    }

                    if (!string.IsNullOrEmpty(meta.CassetteNoteColor))
                    {
                        area.CassseteNoteColor = Calc.HexToColor(meta.CassetteNoteColor);
                    }
                    if (!string.IsNullOrEmpty(meta.CassetteSong))
                    {
                        area.CassetteSong = meta.CassetteSong;
                    }

                    area.MountainIdle   = meta.Mountain?.Idle?.Convert() ?? area.MountainIdle;
                    area.MountainSelect = meta.Mountain?.Select?.Convert() ?? area.MountainSelect;
                    area.MountainZoom   = meta.Mountain?.Zoom?.Convert() ?? area.MountainZoom;
                    area.MountainCursor = meta.Mountain?.Cursor?.ToVector3() ?? area.MountainCursor;
                    area.MountainState  = meta.Mountain?.State ?? area.MountainState;

                    area.SetCompleteScreenMeta(meta.CompleteScreen);
                }

                // Some of the game's code checks for [1] / [2] explicitly.
                // Let's just provide null modes to fill any gaps.
                if (area.Mode.Length < 3)
                {
                    ModeProperties[] larger = new ModeProperties[3];
                    for (int i = 0; i < area.Mode.Length; i++)
                    {
                        larger[i] = area.Mode[i];
                    }
                    area.Mode = larger;
                }

                // Celeste levelset always appears first.
                if (area.GetLevelSet() == "Celeste")
                {
                    Areas.Add(area);
                }
                else
                {
                    modAreas.Add(area);
                }
            }


            // Sort and merge modAreas into Areas. Makes for easier levelset handling.
            Areas.Sort(AreaComparison);
            modAreas.Sort(AreaComparison);
            Areas.AddRange(modAreas);

            // Find duplicates and remove the earlier copy.
            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area       = Areas[i];
                int      otherIndex = Areas.FindIndex(other => other.GetSID() == area.GetSID());
                if (otherIndex < i)
                {
                    Areas[otherIndex] = area;
                    Areas.RemoveAt(i);
                    i--;
                }
            }

            // Remove AreaDatas which are now a mode of another AreaData.
            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area       = Areas[i];
                int      otherIndex = Areas.FindIndex(other => other.Mode.Any(otherMode => otherMode?.Path == area.Mode[0].Path));
                if (otherIndex != -1 && otherIndex != i)
                {
                    Areas.RemoveAt(i);
                    i--;
                }
            }

            // Update old MapData areas and load any new areas.
            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area = Areas[i];
                area.ID = i;
                if (area.Mode[0].MapData != null)
                {
                    area.Mode[0].MapData.Area = area.ToKey();
                }
                else
                {
                    area.Mode[0].MapData = new MapData(area.ToKey());
                }
                if (area.Interlude)
                {
                    continue;
                }
                for (int mode = 1; mode < area.Mode.Length; mode++)
                {
                    if (area.Mode[mode] == null)
                    {
                        continue;
                    }
                    if (area.Mode[mode].MapData != null)
                    {
                        area.Mode[mode].MapData.Area = area.ToKey((AreaMode)mode);
                    }
                    else
                    {
                        area.Mode[mode].MapData = new MapData(area.ToKey((AreaMode)mode));
                    }
                }
            }
        }
Exemplo n.º 22
0
        public void ctor(Session session, Vector2?startPosition = default(Vector2?))
        {
            if (LastLoadingThread != null &&
                LastLoadingThread.TryGetTarget(out Thread lastThread) &&
                (lastThread?.IsAlive ?? false))
            {
                lastThread?.Abort();
            }

            if (CoreModule.Settings.LazyLoading)
            {
                MainThreadHelper.Do(() => VirtualContentExt.UnloadOverworld());
            }

            // Vanilla TileToIndex mappings.
            SurfaceIndex.TileToIndex = new Dictionary <char, int> {
                { '1', 3 },
                { '3', 4 },
                { '4', 7 },
                { '5', 8 },
                { '6', 8 },
                { '7', 8 },
                { '8', 8 },
                { '9', 13 },
                { 'a', 8 },
                { 'b', 23 },
                { 'c', 8 },
                { 'd', 8 },
                { 'e', 8 },
                { 'f', 8 },
                { 'g', 8 },
                { 'G', 8 }, // Reflection alt - unassigned in vanilla.
                { 'h', 33 },
                { 'i', 4 },
                { 'j', 8 },
                { 'k', 3 },
                { 'l', 25 },
                { 'm', 44 },
                { 'n', 40 },
                { 'o', 43 }
            };

            AreaData area = AreaData.Get(session);
            MapMeta  meta = area.GetMeta();
            string   path;

            path = meta?.BackgroundTiles;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "BackgroundTiles.xml");
            }
            GFX.BGAutotiler = new Autotiler(path);

            path = meta?.ForegroundTiles;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "ForegroundTiles.xml");
            }
            GFX.FGAutotiler = new Autotiler(path);

            path = meta?.AnimatedTiles;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "AnimatedTiles.xml");
            }
            GFX.AnimatedTilesBank = new AnimatedTilesBank();
            XmlElement animatedData = Calc.LoadContentXML(path)["Data"];

            foreach (XmlElement el in animatedData)
            {
                if (el != null)
                {
                    GFX.AnimatedTilesBank.Add(
                        el.Attr("name"),
                        el.AttrFloat("delay", 0f),
                        el.AttrVector2("posX", "posY", Vector2.Zero),
                        el.AttrVector2("origX", "origY", Vector2.Zero),
                        GFX.Game.GetAtlasSubtextures(el.Attr("path"))
                        );
                }
            }

            GFX.SpriteBank = new SpriteBank(GFX.Game, Path.Combine("Graphics", "Sprites.xml"));

            path = meta?.Sprites;
            if (!string.IsNullOrEmpty(path))
            {
                SpriteBank bankOrig = GFX.SpriteBank;
                SpriteBank bankMod  = new SpriteBank(GFX.Game, path);

                foreach (KeyValuePair <string, SpriteData> kvpBank in bankMod.SpriteData)
                {
                    string     key      = kvpBank.Key;
                    SpriteData valueMod = kvpBank.Value;

                    if (bankOrig.SpriteData.TryGetValue(key, out SpriteData valueOrig))
                    {
                        IDictionary animsOrig = valueOrig.Sprite.GetAnimations();
                        IDictionary animsMod  = valueMod.Sprite.GetAnimations();
                        foreach (DictionaryEntry kvpAnim in animsMod)
                        {
                            animsOrig[kvpAnim.Key] = kvpAnim.Value;
                        }

                        valueOrig.Sources.AddRange(valueMod.Sources);

                        // replay the starting animation to be sure it is referring to the new sprite.
                        valueOrig.Sprite.Stop();
                        if (valueMod.Sprite.CurrentAnimationID != "")
                        {
                            valueOrig.Sprite.Play(valueMod.Sprite.CurrentAnimationID);
                        }
                    }
                    else
                    {
                        bankOrig.SpriteData[key] = valueMod;
                    }
                }
            }

            // This is done exactly once in the vanilla GFX.LoadData method.
            PlayerSprite.ClearFramesMetadata();
            PlayerSprite.CreateFramesMetadata("player");
            PlayerSprite.CreateFramesMetadata("player_no_backpack");
            PlayerSprite.CreateFramesMetadata("badeline");
            PlayerSprite.CreateFramesMetadata("player_badeline");
            PlayerSprite.CreateFramesMetadata("player_playback");

            path = meta?.Portraits;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "Portraits.xml");
            }
            GFX.PortraitsSpriteBank = new SpriteBank(GFX.Portraits, path);

            orig_ctor(session, startPosition);

            LastLoadingThread = patch_RunThread.Current;
        }
Exemplo n.º 23
0
        private static void Aux_MakeRandomCorridor(ref char[][] map, MapMeta meta, Point coord, List <Corridors> corridors)
        {
            int           headTo = RandomNumber.Between(0, 4);
            int           direction = RandomNumber.Between(0, 3); // +/- , + , -
            int           lengthPositive = 0, lengthNegative = 0;
            Stack <Point> path      = new Stack <Point>();
            Point         baseCoord = new Point(coord.X, coord.Y);

            if (direction == 0)
            {
                lengthPositive = RandomNumber.Between(meta.MinCorridorStraight, meta.MaxCorridorStraight);
                lengthNegative = RandomNumber.Between(meta.MinCorridorStraight, meta.MaxCorridorStraight);
            }
            else if (direction == 1)
            {
                lengthPositive = RandomNumber.Between(meta.MinCorridorStraight, meta.MaxCorridorStraight);
            }
            else
            {
                lengthNegative = RandomNumber.Between(meta.MinCorridorStraight, meta.MaxCorridorStraight);
            }

            for (int i = 0; i < lengthPositive; i++)
            {
                switch (headTo)
                {
                case N:
                case S:
                    coord.Y++; break;

                case W:
                case E:
                    coord.X++; break;

                default:
                    break;
                }

                if (coord.X + 1 > meta.MapSizeX)
                {
                    coord.X--; continue;
                }
                else if (coord.Y + 1 > meta.MapSizeY)
                {
                    coord.Y--; continue;
                }

                if (map[(int)coord.X][(int)coord.Y] != (char)TileType.FLOOR_START)
                {
                    map[(int)coord.X][(int)coord.Y] = (char)TileType.FLOOR;
                }

                path.Push(coord);
            }

            coord = baseCoord;

            for (int i = 0; i < lengthNegative; i++)
            {
                switch (headTo)
                {
                case N:
                case S:
                    coord.Y--; break;

                case W:
                case E:
                    coord.X--; break;

                default:
                    break;
                }

                if (coord.X - 1 < 0)
                {
                    coord.X++; continue;
                }
                else if (coord.Y - 1 < 0)
                {
                    coord.Y++; continue;
                }

                if (map[(int)coord.X][(int)coord.Y] != (char)TileType.FLOOR_START)
                {
                    map[(int)coord.X][(int)coord.Y] = (char)TileType.FLOOR;
                }

                path.Push(coord);
            }

            Corridors crd = new Corridors
            {
                CorridorData    = path,
                IsBranch        = true,
                CorridorStartAt = -1,
                CorridorEndAt   = -1,
            };

            corridors.Add(crd);
        }
Exemplo n.º 24
0
        public static new void Load()
        {
            orig_Load();

            // assign SIDs and CheckpointData.Area for vanilla maps.
            foreach (AreaData area in Areas)
            {
                area.SetSID("Celeste/" + area.Mode[0].Path);

                for (int modeId = 0; modeId < area.Mode.Length; modeId++)
                {
                    ModeProperties mode = area.Mode[modeId];
                    if (mode?.Checkpoints == null)
                    {
                        continue;
                    }

                    foreach (CheckpointData checkpoint in mode.Checkpoints)
                    {
                        checkpoint.SetArea(area.ToKey((AreaMode)modeId));
                    }
                }
            }

            // Separate array as we sort it afterwards.
            List <AreaData> modAreas = new List <AreaData>();

            lock (Everest.Content.Map) {
                foreach (ModAsset asset in Everest.Content.Map.Values.Where(asset => asset.Type == typeof(AssetTypeMap)))
                {
                    string path = asset.PathVirtual.Substring(5);

                    AreaData area = new AreaData();

                    // Default values.

                    area.SetSID(path);
                    area.Name = path;
                    area.Icon = "areas/" + path.ToLowerInvariant();
                    if (!GFX.Gui.Has(area.Icon))
                    {
                        area.Icon = "areas/null";
                    }

                    area.Interlude    = false;
                    area.CanFullClear = true;

                    area.TitleBaseColor   = Calc.HexToColor("6c7c81");
                    area.TitleAccentColor = Calc.HexToColor("2f344b");
                    area.TitleTextColor   = Color.White;

                    area.IntroType = Player.IntroTypes.WakeUp;

                    area.Dreaming   = false;
                    area.ColorGrade = null;

                    area.Mode = new ModeProperties[] {
                        new ModeProperties {
                            Inventory  = PlayerInventory.Default,
                            AudioState = new AudioState(SFX.music_city, SFX.env_amb_00_main)
                        }
                    };

                    area.Wipe = (Scene scene, bool wipeIn, Action onComplete)
                                => new AngledWipe(scene, wipeIn, onComplete);

                    area.DarknessAlpha = 0.05f;
                    area.BloomBase     = 0f;
                    area.BloomStrength = 1f;

                    area.Jumpthru = "wood";

                    area.CassseteNoteColor = Calc.HexToColor("33a9ee");
                    area.CassetteSong      = SFX.cas_01_forsaken_city;

                    // Custom values can be set via the MapMeta.
                    MapMeta meta = new MapMeta();
                    meta.ApplyTo(area);
                    MapMeta metaLoaded = asset.GetMeta <MapMeta>();
                    if (metaLoaded != null)
                    {
                        area.SetMeta(null);
                        metaLoaded.ApplyTo(area);
                        meta = metaLoaded;
                    }

                    if (string.IsNullOrEmpty(area.Mode[0].Path))
                    {
                        area.Mode[0].Path = asset.PathVirtual.Substring(5);
                    }

                    // Some of the game's code checks for [1] / [2] explicitly.
                    // Let's just provide null modes to fill any gaps.
                    meta.Modes = meta.Modes ?? new MapMetaModeProperties[3];
                    if (meta.Modes.Length < 3)
                    {
                        MapMetaModeProperties[] larger = new MapMetaModeProperties[3];
                        for (int i = 0; i < meta.Modes.Length; i++)
                        {
                            larger[i] = meta.Modes[i];
                        }
                        meta.Modes = larger;
                    }
                    if (area.Mode.Length < 3)
                    {
                        ModeProperties[] larger = new ModeProperties[3];
                        for (int i = 0; i < area.Mode.Length; i++)
                        {
                            larger[i] = area.Mode[i];
                        }
                        area.Mode = larger;
                    }

                    // Celeste levelset always appears first.
                    if (area.GetLevelSet() == "Celeste")
                    {
                        Areas.Add(area);
                    }
                    else
                    {
                        modAreas.Add(area);
                    }

                    // Some special handling.
                    area.OnLevelBegin = (level) => {
                        MapMeta levelMeta = AreaData.Get(level.Session).GetMeta();
                        MapMetaModeProperties levelMetaMode = level.Session.MapData.GetMeta();

                        if (levelMetaMode?.SeekerSlowdown ?? false)
                        {
                            level.Add(new SeekerEffectsController());
                        }
                    };
                }
            }


            // Merge modAreas into Areas.
            Areas.AddRange(modAreas);

            // Find duplicates and remove any earlier copies.
            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area       = Areas[i];
                int      otherIndex = Areas.FindIndex(other => other.GetSID() == area.GetSID());
                if (otherIndex < i)
                {
                    Areas[otherIndex] = area;
                    Areas.RemoveAt(i);
                    i--;
                }
            }

            // Sort areas.
            Areas.Sort(AreaComparison);

            // Remove AreaDatas which are now a mode of another AreaData.
            // This can happen late as the map data (.bin) can contain additional metadata.
            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area       = Areas[i];
                string   path       = area.Mode[0].Path;
                int      otherIndex = Areas.FindIndex(other => other.Mode.Any(otherMode => otherMode?.Path == path));
                if (otherIndex != -1 && otherIndex != i)
                {
                    Areas.RemoveAt(i);
                    i--;
                    continue;
                }

                int?     order;
                AreaMode side;
                string   name;
                ParseName(path, out order, out side, out name);

                // Also check for .bins possibly belonging to A side .bins by their path and lack of existing modes.
                for (int ii = 0; ii < Areas.Count; ii++)
                {
                    AreaData other = Areas[ii];
                    int?     otherOrder;
                    AreaMode otherSide;
                    string   otherName;
                    ParseName(other.Mode[0].Path, out otherOrder, out otherSide, out otherName);

                    if (area.GetLevelSet() == other.GetLevelSet() && order == otherOrder && name == otherName && side != otherSide &&
                        !other.HasMode(side))
                    {
                        if (other.Mode[(int)side] == null)
                        {
                            other.Mode[(int)side] = new ModeProperties {
                                Inventory  = PlayerInventory.Default,
                                AudioState = new AudioState(SFX.music_city, SFX.env_amb_00_main)
                            }
                        }
                        ;
                        other.Mode[(int)side].Path = path;
                        Areas.RemoveAt(i);
                        i--;
                        break;
                    }
                }
            }

            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area = Areas[i];
                area.ID = i;

                // Clean up non-existing modes.
                int modei = 0;
                for (; modei < area.Mode.Length; modei++)
                {
                    ModeProperties mode = area.Mode[modei];
                    if (mode == null || string.IsNullOrEmpty(mode.Path))
                    {
                        break;
                    }
                }
                Array.Resize(ref area.Mode, modei);

                Logger.Log("AreaData", $"{i}: {area.GetSID()} - {area.Mode.Length} sides");

                // Update old MapData areas and load any new areas.

                // Add the A side MapData or update its area key.
                if (area.Mode[0].MapData != null)
                {
                    area.Mode[0].MapData.Area = area.ToKey();
                }
                else
                {
                    area.Mode[0].MapData = new MapData(area.ToKey());
                }

                if (area.IsInterludeUnsafe())
                {
                    continue;
                }

                // A and (some) B sides have PoemIDs. Can be overridden via empty PoemID.
                if (area.Mode[0].PoemID == null)
                {
                    area.Mode[0].PoemID = area.GetSID().DialogKeyify() + "_A";
                }
                if (area.Mode.Length > 1 &&
                    area.Mode[1] != null &&
                    area.Mode[1].PoemID == null)
                {
                    area.Mode[1].PoemID = area.GetSID().DialogKeyify() + "_B";
                }

                // Update all other existing mode's area keys.
                for (int mode = 1; mode < area.Mode.Length; mode++)
                {
                    if (area.Mode[mode] == null)
                    {
                        continue;
                    }
                    if (area.Mode[mode].MapData != null)
                    {
                        area.Mode[mode].MapData.Area = area.ToKey((AreaMode)mode);
                    }
                    else
                    {
                        area.Mode[mode].MapData = new MapData(area.ToKey((AreaMode)mode));
                    }
                }
            }

            // Load custom mountains
            // This needs to be done after areas are loaded because it depends on the MapMeta
            MTNExt.LoadMod();
            MTNExt.LoadModData();
        }
Exemplo n.º 25
0
        public override Dictionary <string, Action <BinaryPacker.Element> > Init()
        => new Dictionary <string, Action <BinaryPacker.Element> >()
        {
            { "root", root => {
                  foreach (BinaryPacker.Element el in root.Children)
                  {
                      Context.Run(el.Name, el);
                  }
              } },

            { "Style", style => {
                  // Celeste 1.2.5.0 optimizes BinaryPacker, which causes some issues.
                  // Let's "unoptimize" Style and its Backgrounds and Foregrounds.
                  if (style.Children == null)
                  {
                      style.Children = new List <BinaryPacker.Element>();
                  }
                  foreach (BinaryPacker.Element el in style.Children)
                  {
                      if ((el.Name == "Backgrounds" ||
                           el.Name == "Foregrounds") &&
                          el.Children == null)
                      {
                          el.Children = new List <BinaryPacker.Element>();
                      }
                  }
              } },

            { "levels", levels => {
                  if (levels.Children != null)
                  {
                      foreach (BinaryPacker.Element level in levels.Children)
                      {
                          Context.Run("level", level);

                          if (level.Children != null)
                          {
                              foreach (BinaryPacker.Element levelChild in level.Children)
                              {
                                  Context.Run(levelChild.Name, levelChild);
                              }
                          }
                      }
                  }
              } },

            { "level", level => {
                  // lvl_ was optional before Celeste 1.2.5.0 made it mandatory.
                  // Certain level "tags" are supported as very early mods used them.
                  LevelTags = level.Attr("name").Split(':');
                  LevelName = LevelTags[0];
                  if (LevelName.StartsWith("lvl_"))
                  {
                      LevelName = LevelName.Substring(4);
                  }
                  level.SetAttr("name", "lvl_" + LevelName);

                  BinaryPacker.Element entities = level.Children.FirstOrDefault(el => el.Name == "entities");
                  BinaryPacker.Element triggers = level.Children.FirstOrDefault(el => el.Name == "triggers");

                  // Celeste 1.2.5.0 optimizes BinaryPacker (null instead of empty lists),
                  // which causes some issues where the game still expects an empty list.
                  // Let's "unoptimize" entities and triggers.
                  if (entities == null)
                  {
                      level.Children.Add(entities = new BinaryPacker.Element {
                            Name = "entities"
                        });
                  }
                  if (entities.Children == null)
                  {
                      entities.Children = new List <BinaryPacker.Element>();
                  }

                  if (triggers == null)
                  {
                      level.Children.Add(triggers = new BinaryPacker.Element {
                            Name = "triggers"
                        });
                  }
                  if (triggers.Children == null)
                  {
                      triggers.Children = new List <BinaryPacker.Element>();
                  }

                  if (LevelTags.Contains("checkpoint") || LevelTags.Contains("cp"))
                  {
                      entities.Children.Add(new BinaryPacker.Element {
                            Name       = "checkpoint",
                            Attributes = new Dictionary <string, object>()
                            {
                                { "x", "0" },
                                { "y", "0" }
                            }
                        });
                  }

                  if (level.AttrBool("space"))
                  {
                      if (level.AttrBool("spaceSkipWrap") || LevelTags.Contains("nospacewrap") || LevelTags.Contains("nsw"))
                      {
                          entities.Children.Add(new BinaryPacker.Element {
                                Name = "everest/spaceControllerBlocker"
                            });
                      }
                      if (level.AttrBool("spaceSkipGravity") || LevelTags.Contains("nospacegravity") || LevelTags.Contains("nsg"))
                      {
                          entities.Children.Add(new BinaryPacker.Element {
                                Name = "everest/spaceController"
                            });
                          level.SetAttr("space", false);
                      }

                      if (!LevelTags.Contains("nospacefix") && !LevelTags.Contains("nsf") &&
                          !triggers.Children.Any(el => el.Name == "cameraTargetTrigger") &&
                          !entities.Children.Any(el => el.Name == "everest/spaceControllerBlocker"))
                      {
                          // Camera centers tile-perfectly on uneven heights.
                          int heightForCenter = level.AttrInt("height");
                          heightForCenter /= 8;
                          if (heightForCenter % 2 == 0)
                          {
                              heightForCenter--;
                          }
                          heightForCenter *= 8;

                          triggers.Children.Add(new BinaryPacker.Element {
                                Name       = "cameraTargetTrigger",
                                Attributes = new Dictionary <string, object>()
                                {
                                    { "x", 0f },
                                    { "y", 0f },
                                    { "width", level.AttrInt("width") },
                                    { "height", level.AttrInt("height") },
                                    { "yOnly", true },
                                    { "lerpStrength", 1f }
                                },
                                Children = new List <BinaryPacker.Element>()
                                {
                                    new BinaryPacker.Element {
                                        Attributes = new Dictionary <string, object>()
                                        {
                                            { "x", 160f },
                                            { "y", heightForCenter / 2f }
                                        }
                                    }
                                }
                            });
                      }
                  }
              } },

            { "entities", levelChild => {
                  // check if the room has a checkpoint first.
                  foreach (BinaryPacker.Element entity in levelChild.Children)
                  {
                      if (entity.Name == "checkpoint")
                      {
                          if (CheckpointsAuto != null)
                          {
                              MapMeta        modeMeta = AreaData.GetModeMeta(AreaKey.Mode);
                              CheckpointData c        = new CheckpointData(
                                  LevelName,
                                  (AreaData.GetSID() + "_" + LevelName).DialogKeyify(),
                                  MapMeta.GetInventory(entity.Attr("inventory")),
                                  entity.Attr("dreaming") == "" ? modeMeta.Dreaming ?? AreaData.Dreaming : entity.AttrBool("dreaming"),
                                  null
                                  );
                              if (entity.Attr("coreMode") == "")
                              {
                                  c.CoreMode = modeMeta.CoreMode ?? AreaData.CoreMode;
                              }
                              else
                              {
                                  entity.AttrIf("coreMode", v => c.CoreMode = (Session.CoreModes)Enum.Parse(typeof(Session.CoreModes), v, true));
                              }

                              int id = entity.AttrInt("checkpointID", -1);
                              if (id == -1)
                              {
                                  CheckpointsAuto.Add(c);
                              }
                              else
                              {
                                  while (CheckpointsAuto.Count <= id)
                                  {
                                      CheckpointsAuto.Add(null);
                                  }
                                  CheckpointsAuto[id] = c;
                              }
                          }
                          Checkpoint++;
                          StrawberryInCheckpoint = 0;
                      }
                  }

                  // then, auto-assign strawberries and cassettes to checkpoints.
                  foreach (BinaryPacker.Element entity in levelChild.Children)
                  {
                      Context.Run("entity:" + entity.Name, entity);
                  }
              } },

            { "entity:cassette", entity => {
                  if (AreaData.CassetteCheckpointIndex < 0)
                  {
                      AreaData.CassetteCheckpointIndex = Checkpoint;
                  }
              } },

            { "entity:strawberry", entity => {
                  if (!entity.AttrBool("moon", false))
                  {
                      if (entity.AttrInt("checkpointID", -1) == -1)
                      {
                          entity.SetAttr("checkpointID", Checkpoint);
                      }
                      if (entity.AttrInt("order", -1) == -1)
                      {
                          entity.SetAttr("order", StrawberryInCheckpoint);
                      }
                      Strawberry++;
                      StrawberryInCheckpoint++;
                  }
              } }
        };
Exemplo n.º 26
0
 /// <summary>
 /// Set the custom metadata.
 /// </summary>
 public static AreaData SetMeta(this AreaData self, MapMeta value)
 {
     ((patch_AreaData)self).Meta = value;
     return(self);
 }
Exemplo n.º 27
0
        public void Draw(Vector pos)
        {
            for (var y = 0; y <= WindowRows; y++)
            {
                for (var x = 0; x <= WindowColumns; x++)
                {
                    // don't draw extra tile if on the boundary
                    if (pos.Y >= Height - Screen.HalfHeight && y == WindowRows)
                    {
                        break;
                    }
                    if (pos.X >= Width - Screen.HalfWidth && x == WindowColumns)
                    {
                        continue;
                    }

                    int playerTileX, playerTileY;
                    int offsetX = 0, offsetY = 0;

                    // handle player X coordinate
                    if (pos.X < Screen.HalfWidth)
                    {
                        // offset player when near the left boundary of the map
                        playerTileX = 0;
                    }
                    else if (pos.X > Width - Screen.HalfWidth)
                    {
                        // offset player when near the right boundary of the map
                        playerTileX = (Width - Screen.Width) / TileWidth;
                    }
                    else
                    {
                        // position the player in the middle of the screen
                        playerTileX = (pos.X - Screen.HalfWidth) / TileWidth;
                        offsetX     = pos.X % TileWidth;
                    }

                    // handle player Y coordinate
                    if (pos.Y < Screen.HalfHeight)
                    {
                        // offset player when near the top boundary of the map
                        playerTileY = 0;
                    }
                    else if (pos.Y > Height - Screen.HalfHeight)
                    {
                        // offset player when near the bottom boundary of the map
                        playerTileY = (Height - Screen.Height) / TileHeight;
                    }
                    else
                    {
                        // position the player in the middle of the screen
                        playerTileY = (pos.Y - Screen.HalfHeight) / TileHeight;
                        offsetY     = (pos.Y + TileHeight / 2) % TileHeight;
                    }

                    // draw all tile layers
                    for (var layer = 0; layer < Layers.Length; layer++)
                    {
                        var tile = Layers[layer].Tiles[x + playerTileX, y + playerTileY];

                        if (tile?.Tileset != null)
                        {
                            var drawRect = new Rect(x * TileWidth - offsetX, y * TileHeight - offsetY, TileWidth, TileHeight);

                            _tilesetManager.Draw(tile.Tileset, drawRect, tile.SpriteRect);

                            if (layer == 0)
                            {
                                DrawEventCollection(MapMeta.GetEventId(new Vector(x + playerTileX, y + playerTileY)), new Vector(x * TileWidth - offsetX, y * TileHeight - offsetY));
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 28
0
        static void Main(string[] args)
        {
            Console.WriteLine("FLT-DungeonMapGenerator");

            MapMeta meta = new MapMeta
            {
                MapSizeX                    = 96,
                MapSizeY                    = 64,
                StartRoomSize               = 6,
                MaxRoomSize                 = 8,
                MinRoomSize                 = 4,
                MaxRoomNumber               = 10,
                MaxRoomConnection           = 2,
                MinRoomDistance             = 200,
                MaxCorridorBranchCount      = 100,
                MinCorridorStraight         = 3,
                MaxCorridorStraight         = 12,
                RouteTwistFactor            = 3,
                RouteDirectFactor           = 6,
                RouteBranchFactor           = 12,
                RouteAdditionalBranchFactor = 12,
            };

            char[][]         map;
            List <RoomMeta>  rooms     = new List <RoomMeta>();
            List <Corridors> corridors = new List <Corridors>();
            List <Prefabs>   prefabs   = new List <Prefabs>
            {
                new Prefabs {
                    Name = "Test", Tile = (int)TileType.TEST, SpawnChance = 20,
                }                                                                           // 2%
            };
            List <string> componentsPath = new List <string>
            {
                filePath
            };

            Console.WriteLine("Initializing...");
            map = Stage1_MapInit(meta);

            // Maybe can merge Stage2 and Stage3
            Console.WriteLine("Making starting area...");
            Stage2_MakeStartRoom(ref map, meta, rooms);

            Console.WriteLine("Making rooms...");
            Stage3_MakeRooms(ref map, meta, rooms);

            Console.WriteLine("Making corridors...");
            Stage4_ConnectRooms(ref map, meta, rooms, corridors, 0, 0);

            Console.WriteLine("Current corridors=" + corridors.Count);

            Console.WriteLine("Making branches...");
            Stage5_MakeCorridorBranch(ref map, meta, rooms, corridors);

            Console.WriteLine("Current corridors=" + corridors.Count);

            Console.WriteLine("Validating connections...");
            Stage6_ConnectionValidate(ref map, meta, rooms, corridors);

            Console.WriteLine("Current corridors=" + corridors.Count);

            Console.WriteLine("Making entities...");
            Stage7_MakePrefab(ref map, meta, corridors, prefabs);

            Console.WriteLine("Current corridors=" + corridors.Count);
            Stage8_InsertComponent(ref map, meta, rooms, componentsPath);

            // Draw on Console
            for (int j = 0; j < meta.MapSizeY; j++)
            {
                for (int i = 0; i < meta.MapSizeX; i++)
                {
                    if (map[i][j] == (char)TileType.WALL)
                    {
                        Console.Write('X');
                    }
                    else if (map[i][j] == (char)TileType.FLOOR)
                    {
                        Console.Write(' ');
                    }
                    else if (map[i][j] == (char)TileType.FLOOR_START)
                    {
                        Console.Write('@');
                    }
                    else if (map[i][j] == (char)TileType.TEST)
                    {
                        Console.Write('T');
                    }
                    else
                    {
                        Console.Write('?');
                    }
                }

                Console.Write(Environment.NewLine);
            }

            Console.ReadKey();
        }
Exemplo n.º 29
0
        public void ctor(Session session, Vector2?startPosition = default(Vector2?))
        {
            if (CoreModule.Settings.LazyLoading)
            {
                MainThreadHelper.Do(() => VirtualContentExt.UnloadOverworld());
            }

            // Vanilla TileToIndex mappings.
            SurfaceIndex.TileToIndex = new Dictionary <char, int> {
                { '1', 3 },
                { '3', 4 },
                { '4', 7 },
                { '5', 8 },
                { '6', 8 },
                { '7', 8 },
                { '8', 8 },
                { '9', 13 },
                { 'a', 8 },
                { 'b', 23 },
                { 'c', 8 },
                { 'd', 8 },
                { 'e', 8 },
                { 'f', 8 },
                { 'g', 8 },
                { 'h', 33 },
                { 'i', 4 },
                { 'j', 8 },
                { 'k', 3 },
                { 'l', 25 },
                { 'm', 44 },
                { 'n', 40 },
                { 'o', 43 }
            };

            AreaData area = AreaData.Get(session);
            MapMeta  meta = area.GetMeta();
            string   path;

            path = meta?.BackgroundTiles;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "BackgroundTiles.xml");
            }
            GFX.BGAutotiler = new Autotiler(path);

            path = meta?.ForegroundTiles;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "ForegroundTiles.xml");
            }
            GFX.FGAutotiler = new Autotiler(path);

            path = meta?.AnimatedTiles;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "AnimatedTiles.xml");
            }
            GFX.AnimatedTilesBank = new AnimatedTilesBank();
            XmlElement animatedData = Calc.LoadContentXML(path)["Data"];

            foreach (XmlElement el in animatedData)
            {
                if (el != null)
                {
                    GFX.AnimatedTilesBank.Add(
                        el.Attr("name"),
                        el.AttrFloat("delay", 0f),
                        el.AttrVector2("posX", "posY", Vector2.Zero),
                        el.AttrVector2("origX", "origY", Vector2.Zero),
                        GFX.Game.GetAtlasSubtextures(el.Attr("path"))
                        );
                }
            }

            GFX.SpriteBank = new SpriteBank(GFX.Game, Path.Combine("Graphics", "Sprites.xml"));

            path = meta?.Sprites;
            if (!string.IsNullOrEmpty(path))
            {
                SpriteBank bankOrig = GFX.SpriteBank;
                SpriteBank bankMod  = new SpriteBank(GFX.Game, path);

                foreach (KeyValuePair <string, SpriteData> kvpBank in bankMod.SpriteData)
                {
                    string     key      = kvpBank.Key;
                    SpriteData valueMod = kvpBank.Value;

                    if (bankOrig.SpriteData.TryGetValue(key, out SpriteData valueOrig))
                    {
                        IDictionary animsOrig = valueOrig.Sprite.GetAnimations();
                        IDictionary animsMod  = valueMod.Sprite.GetAnimations();

                        foreach (DictionaryEntry kvpAnim in animsMod)
                        {
                            animsOrig[kvpAnim.Key] = kvpAnim.Value;
                        }
                    }
                    else
                    {
                        bankOrig.SpriteData[key] = valueMod;
                    }
                }
            }

            path = meta?.Portraits;
            if (string.IsNullOrEmpty(path))
            {
                path = Path.Combine("Graphics", "Portraits.xml");
            }
            GFX.PortraitsSpriteBank = new SpriteBank(GFX.Portraits, path);

            orig_ctor(session, startPosition);
        }