Exemple #1
0
 public static ISound PlayToPlayer(Player player, string name, PPos pos)
 {
     return Play(player, name, false, pos, 1);
 }
Exemple #2
0
 public static PPos Lerp(PPos a, PPos b, int mul, int div)
 {
     return a + ((PVecInt)(b - a) * mul / div);
 }
Exemple #3
0
 public static ISound Play(string name, PPos pos)
 {
     return Play(null, name, false, pos, 1);
 }
Exemple #4
0
 public byte ProjectedHeight(PPos puv)
 {
     return projectedHeight[(MPos)puv];
 }
Exemple #5
0
        public List<MPos> Unproject(PPos puv)
        {
            var uv = (MPos)puv;

            if (!initializedCellProjection)
                InitializeCellProjection();

            if (!inverseCellProjection.Contains(uv))
                return new List<MPos>();

            return inverseCellProjection[uv];
        }
Exemple #6
0
        public MPos ChooseClosestEdgeCell(MPos uv)
        {
            var allProjected = ProjectedCellsCovering(uv);

            PPos edge;
            if (allProjected.Any())
            {
                var puv = allProjected.First();
                var horizontalBound = ((puv.U - Bounds.Left) < Bounds.Width / 2) ? Bounds.Left : Bounds.Right;
                var verticalBound = ((puv.V - Bounds.Top) < Bounds.Height / 2) ? Bounds.Top : Bounds.Bottom;

                var du = Math.Abs(horizontalBound - puv.U);
                var dv = Math.Abs(verticalBound - puv.V);

                edge = du < dv ? new PPos(horizontalBound, puv.V) : new PPos(puv.U, verticalBound);
            }
            else
                edge = new PPos(Bounds.Left, Bounds.Top);

            var unProjected = Unproject(edge);
            if (!unProjected.Any())
            {
                // Adjust V until we find a cell that works
                for (var x = 2; x <= 2 * Grid.MaximumTerrainHeight; x++)
                {
                    var dv = ((x & 1) == 1 ? 1 : -1) * x / 2;
                    var test = new PPos(edge.U, edge.V + dv);
                    if (!Contains(test))
                        continue;

                    unProjected = Unproject(test);
                    if (unProjected.Any())
                        break;
                }

                // This shouldn't happen.  But if it does, return the original value and hope the caller doesn't explode.
                if (!unProjected.Any())
                {
                    Log.Write("debug", "Failed to find closest edge for map cell {0}", uv);
                    return uv;
                }
            }

            return edge.V == Bounds.Bottom ? unProjected.MaxBy(x => x.V) : unProjected.MinBy(x => x.V);
        }
Exemple #7
0
 public PPos Clamp(PPos puv)
 {
     var bounds = new Rectangle(Bounds.X, Bounds.Y, Bounds.Width - 1, Bounds.Height - 1);
     return puv.Clamp(bounds);
 }
Exemple #8
0
 public static PPos Lerp(PPos a, PPos b, int mul, int div)
 {
     return(a + ((PVecInt)(b - a) * mul / div));
 }
Exemple #9
0
		void PostInit()
		{
			rules = Exts.Lazy(() =>
			{
				try
				{
					return Game.ModData.RulesetCache.Load(this);
				}
				catch (Exception e)
				{
					InvalidCustomRules = true;
					Log.Write("debug", "Failed to load rules for {0} with error {1}", Title, e.Message);
				}

				return Game.ModData.DefaultRules;
			});

			cachedTileSet = Exts.Lazy(() => Rules.TileSets[Tileset]);

			var tl = new MPos(0, 0).ToCPos(this);
			var br = new MPos(MapSize.X - 1, MapSize.Y - 1).ToCPos(this);
			AllCells = new CellRegion(Grid.Type, tl, br);

			var btl = new PPos(Bounds.Left, Bounds.Top);
			var bbr = new PPos(Bounds.Right - 1, Bounds.Bottom - 1);
			SetBounds(btl, bbr);

			CustomTerrain = new CellLayer<byte>(this);
			foreach (var uv in AllCells.MapCoords)
				CustomTerrain[uv] = byte.MaxValue;

			var leftDelta = Grid.Type == MapGridType.RectangularIsometric ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
			var topDelta = Grid.Type == MapGridType.RectangularIsometric ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
			var rightDelta = Grid.Type == MapGridType.RectangularIsometric ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
			var bottomDelta = Grid.Type == MapGridType.RectangularIsometric ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
			CellCorners = CellCornerHalfHeights.Select(ramp => new WVec[]
			{
				leftDelta + new WVec(0, 0, 512 * ramp[0]),
				topDelta + new WVec(0, 0, 512 * ramp[1]),
				rightDelta + new WVec(0, 0, 512 * ramp[2]),
				bottomDelta + new WVec(0, 0, 512 * ramp[3])
			}).ToArray();
		}
Exemple #10
0
 public static ISound Play(string name, PPos pos)
 {
     return(Play(null, name, false, pos, 1));
 }
Exemple #11
0
 public static PPos Min(PPos a, PPos b)
 {
     return(new PPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)));
 }
Exemple #12
0
 public static ISound PlayToPlayer(Player player, string name, PPos pos)
 {
     return(Play(player, name, false, pos, 1));
 }
Exemple #13
0
 public static ISound Play(string name, PPos pos, float volumeModifier)
 {
     return(Play(null, name, false, pos, volumeModifier));
 }
Exemple #14
0
 // Resolve an array index from map coordinates.
 public int Index(PPos uv)
 {
     return(uv.V * Size.Width + uv.U);
 }
 public bool Contains(PPos uv)
 {
     return(bounds.Contains(uv.U, uv.V));
 }
Exemple #16
0
		public NewMapLogic(Action onExit, Action<string> onSelect, Ruleset modRules, Widget widget, World world)
		{
			panel = widget;

			panel.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };

			var tilesetDropDown = panel.Get<DropDownButtonWidget>("TILESET");
			var tilesets = modRules.TileSets.Select(t => t.Key).ToList();
			Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
			{
				var item = ScrollItemWidget.Setup(template,
					() => tilesetDropDown.Text == option,
					() => { tilesetDropDown.Text = option; });
				item.Get<LabelWidget>("LABEL").GetText = () => option;
				return item;
			};
			tilesetDropDown.Text = tilesets.First();
			tilesetDropDown.OnClick = () =>
				tilesetDropDown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, tilesets, setupItem);

			var widthTextField = panel.Get<TextFieldWidget>("WIDTH");
			var heightTextField = panel.Get<TextFieldWidget>("HEIGHT");

			panel.Get<ButtonWidget>("CREATE_BUTTON").OnClick = () =>
			{
				int width, height;
				int.TryParse(widthTextField.Text, out width);
				int.TryParse(heightTextField.Text, out height);

				// Require at least a 2x2 playable area so that the
				// ground is visible through the edge shroud
				width = Math.Max(2, width);
				height = Math.Max(2, height);

				var maxTerrainHeight = world.Map.Grid.MaximumTerrainHeight;
				var tileset = modRules.TileSets[tilesetDropDown.Text];
				var map = new Map(tileset, width + 2, height + maxTerrainHeight + 2);

				var tl = new PPos(1, 1);
				var br = new PPos(width, height + maxTerrainHeight);
				map.SetBounds(tl, br);

				map.PlayerDefinitions = new MapPlayers(map.Rules, map.SpawnPoints.Value.Length).ToMiniYaml();
				map.FixOpenAreas(modRules);

				Action<string> afterSave = uid =>
				{
					// HACK: Work around a synced-code change check.
					// It's not clear why this is needed here, but not in the other places that load maps.
					Game.RunAfterTick(() =>
					{
						ConnectionLogic.Connect(System.Net.IPAddress.Loopback.ToString(),
							Game.CreateLocalServer(uid), "",
							() => Game.LoadEditor(uid),
							() => { Game.CloseServer(); onExit(); });
					});

					Ui.CloseWindow();
					onSelect(uid);
				};

				Ui.OpenWindow("SAVE_MAP_PANEL", new WidgetArgs()
				{
					{ "onSave", afterSave },
					{ "onExit", () => { Ui.CloseWindow(); onExit(); } },
					{ "map", map },
					{ "playerDefinitions", map.PlayerDefinitions },
					{ "actorDefinitions", map.ActorDefinitions }
				});
			};
		}
Exemple #17
0
        byte ProjectedCellHeightInner(PPos puv)
        {
            while (inverseCellProjection.Contains((MPos)puv))
            {
                var inverse = inverseCellProjection[(MPos)puv];
                if (inverse.Any())
                {
                    // The original games treat the top of cliffs the same way as the bottom
                    // This information isn't stored in the map data, so query the offset from the tileset
                    var temp = inverse.MaxBy(uv => uv.V);
                    var terrain = Tiles[temp];
                    return (byte)(Height[temp] - Rules.TileSet.Templates[terrain.Type][terrain.Index].Height);
                }

                // Try the next cell down if this is a cliff face
                puv = new PPos(puv.U, puv.V + 1);
            }

            return 0;
        }
Exemple #18
0
 public byte ProjectedHeight(PPos puv)
 {
     return(projectedHeight[(MPos)puv]);
 }
Exemple #19
0
        public MPos Clamp(MPos uv)
        {
            if (Grid.MaximumTerrainHeight == 0)
                return (MPos)Clamp((PPos)uv);

            // Already in bounds, so don't need to do anything.
            if (ContainsAllProjectedCellsCovering(uv))
                return uv;

            // Clamping map coordinates is trickier than it might first look!
            // This needs to handle three nasty cases:
            //  * The requested cell is well outside the map region
            //  * The requested cell is near the top edge inside the map but outside the projected layer
            //  * The clamped projected cell lands on a cliff face with no associated map cell
            //
            // Handling these cases properly requires abuse of our knowledge of the projection transform.
            //
            // The U coordinate doesn't change significantly in the projection, so clamp this
            // straight away and ensure the point is somewhere inside the map
            uv = cellProjection.Clamp(new MPos(uv.U.Clamp(Bounds.Left, Bounds.Right), uv.V));

            // Project this guessed cell and take the first available cell
            // If it is projected outside the layer, then make another guess.
            var allProjected = ProjectedCellsCovering(uv);
            var projected = allProjected.Any() ? allProjected.First()
                : new PPos(uv.U, uv.V.Clamp(Bounds.Top, Bounds.Bottom));

            // Clamp the projected cell to the map area
            projected = Clamp(projected);

            // Project the cell back into map coordinates.
            // This may fail if the projected cell covered a cliff or another feature
            // where there is a large change in terrain height.
            var unProjected = Unproject(projected);
            if (!unProjected.Any())
            {
                // Adjust V until we find a cell that works
                for (var x = 2; x <= 2 * Grid.MaximumTerrainHeight; x++)
                {
                    var dv = ((x & 1) == 1 ? 1 : -1) * x / 2;
                    var test = new PPos(projected.U, projected.V + dv);
                    if (!Contains(test))
                        continue;

                    unProjected = Unproject(test);
                    if (unProjected.Any())
                        break;
                }

                // This shouldn't happen.  But if it does, return the original value and hope the caller doesn't explode.
                if (!unProjected.Any())
                {
                    Log.Write("debug", "Failed to clamp map cell {0} to map bounds", uv);
                    return uv;
                }
            }

            return projected.V == Bounds.Bottom ? unProjected.MaxBy(x => x.V) : unProjected.MinBy(x => x.V);
        }
Exemple #20
0
        public MPos Clamp(MPos uv)
        {
            if (Grid.MaximumTerrainHeight == 0)
            {
                return((MPos)Clamp((PPos)uv));
            }

            // Already in bounds, so don't need to do anything.
            if (ContainsAllProjectedCellsCovering(uv))
            {
                return(uv);
            }

            // Clamping map coordinates is trickier than it might first look!
            // This needs to handle three nasty cases:
            //  * The requested cell is well outside the map region
            //  * The requested cell is near the top edge inside the map but outside the projected layer
            //  * The clamped projected cell lands on a cliff face with no associated map cell
            //
            // Handling these cases properly requires abuse of our knowledge of the projection transform.
            //
            // The U coordinate doesn't change significantly in the projection, so clamp this
            // straight away and ensure the point is somewhere inside the map
            uv = cellProjection.Clamp(new MPos(uv.U.Clamp(Bounds.Left, Bounds.Right), uv.V));

            // Project this guessed cell and take the first available cell
            // If it is projected outside the layer, then make another guess.
            var allProjected = ProjectedCellsCovering(uv);
            var projected    = allProjected.Any() ? allProjected.First()
                                : new PPos(uv.U, uv.V.Clamp(Bounds.Top, Bounds.Bottom));

            // Clamp the projected cell to the map area
            projected = Clamp(projected);

            // Project the cell back into map coordinates.
            // This may fail if the projected cell covered a cliff or another feature
            // where there is a large change in terrain height.
            var unProjected = Unproject(projected);

            if (!unProjected.Any())
            {
                // Adjust V until we find a cell that works
                for (var x = 2; x <= 2 * Grid.MaximumTerrainHeight; x++)
                {
                    var dv   = ((x & 1) == 1 ? 1 : -1) * x / 2;
                    var test = new PPos(projected.U, projected.V + dv);
                    if (!Contains(test))
                    {
                        continue;
                    }

                    unProjected = Unproject(test);
                    if (unProjected.Any())
                    {
                        break;
                    }
                }

                // This shouldn't happen.  But if it does, return the original value and hope the caller doesn't explode.
                if (!unProjected.Any())
                {
                    Log.Write("debug", "Failed to clamp map cell {0} to map bounds", uv);
                    return(uv);
                }
            }

            return(projected.V == Bounds.Bottom ? unProjected.MaxBy(x => x.V) : unProjected.MinBy(x => x.V));
        }
Exemple #21
0
 public bool Contains(PPos puv)
 {
     return Bounds.Contains(puv.U, puv.V);
 }
Exemple #22
0
        public PPos Clamp(PPos puv)
        {
            var bounds = new Rectangle(Bounds.X, Bounds.Y, Bounds.Width - 1, Bounds.Height - 1);

            return(puv.Clamp(bounds));
        }
Exemple #23
0
        public void SetBounds(PPos tl, PPos br)
        {
            // The tl and br coordinates are inclusive, but the Rectangle
            // is exclusive.  Pad the right and bottom edges to match.
            Bounds = Rectangle.FromLTRB(tl.U, tl.V, br.U + 1, br.V + 1);

            // Directly calculate the projected map corners in world units avoiding unnecessary
            // conversions.  This abuses the definition that the width of the cell is always
            // 1024 units, and that the height of two rows is 2048 for classic cells and 1024
            // for isometric cells.
            var wtop = tl.V * 1024;
            var wbottom = (br.V + 1) * 1024;
            if (Grid.Type == MapGridType.RectangularIsometric)
            {
                wtop /= 2;
                wbottom /= 2;
            }

            ProjectedTopLeft = new WPos(tl.U * 1024, wtop, 0);
            ProjectedBottomRight = new WPos(br.U * 1024 - 1, wbottom - 1, 0);

            ProjectedCellBounds = new ProjectedCellRegion(this, tl, br);
        }
Exemple #24
0
 public bool Contains(PPos puv)
 {
     return(Bounds.Contains(puv.U, puv.V));
 }
Exemple #25
0
 public static int hash_PPos(PPos i2)
 {
     return(((i2.X * 5) ^ (i2.Y * 3)) / 4);
 }
Exemple #26
0
 public bool ShroudObscures(PPos uv)
 {
     return(RenderPlayer != null && !RenderPlayer.Shroud.IsExplored(uv));
 }
Exemple #27
0
 public static PPos Min(PPos a, PPos b)
 {
     return new PPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y));
 }
Exemple #28
0
        void InitializeCellProjection()
        {
            if (initializedCellProjection)
                return;

            initializedCellProjection = true;

            cellProjection = new CellLayer<PPos[]>(this);
            inverseCellProjection = new CellLayer<List<MPos>>(this);
            projectedHeight = new CellLayer<byte>(this);

            // Initialize collections
            foreach (var cell in AllCells)
            {
                var uv = cell.ToMPos(Grid.Type);
                cellProjection[uv] = new PPos[0];
                inverseCellProjection[uv] = new List<MPos>();
            }

            // Initialize projections
            foreach (var cell in AllCells)
                UpdateProjection(cell);
        }
Exemple #29
0
 public static ISound Play(string name, PPos pos, float volumeModifier)
 {
     return Play(null, name, false, pos, volumeModifier);
 }
Exemple #30
0
        void PostInit()
        {
            try
            {
                Rules = Ruleset.Load(modData, this, Tileset, RuleDefinitions, WeaponDefinitions,
                    VoiceDefinitions, NotificationDefinitions, MusicDefinitions, SequenceDefinitions);
            }
            catch (Exception e)
            {
                InvalidCustomRules = true;
                Rules = Ruleset.LoadDefaultsForTileSet(modData, Tileset);
                Log.Write("debug", "Failed to load rules for {0} with error {1}", Title, e.Message);
            }

            Rules.Sequences.Preload();

            var tl = new MPos(0, 0).ToCPos(this);
            var br = new MPos(MapSize.X - 1, MapSize.Y - 1).ToCPos(this);
            AllCells = new CellRegion(Grid.Type, tl, br);

            var btl = new PPos(Bounds.Left, Bounds.Top);
            var bbr = new PPos(Bounds.Right - 1, Bounds.Bottom - 1);
            SetBounds(btl, bbr);

            CustomTerrain = new CellLayer<byte>(this);
            foreach (var uv in AllCells.MapCoords)
                CustomTerrain[uv] = byte.MaxValue;

            AllEdgeCells = UpdateEdgeCells();
        }
Exemple #31
0
        static ISound Play(Player player, string name, bool headRelative, PPos pos, float volumeModifier)
        {
            if (player != null && player != player.World.LocalPlayer)
                return null;
            if (name == "" || name == null)
                return null;

            return soundEngine.Play2D(sounds[name],
                false, headRelative, pos.ToFloat2(),
                InternalSoundVolume * volumeModifier);
        }
Exemple #32
0
 public static Actor ClosestTo(this IEnumerable <Actor> actors, PPos px)
 {
     return(actors.OrderBy(a => (a.CenterLocation - px).LengthSquared).FirstOrDefault());
 }