public static void RestoreTerrain(VM vm, TerrainBlend blend, byte roads) { var arch = vm.Context.Architecture; arch.DisableClip = true; var baseB = blend.Base; arch.Terrain.LightType = (baseB == TerrainType.WATER) ? TerrainType.SAND : blend.Base; arch.Terrain.DarkType = (blend.Blend == TerrainType.WATER) ? blend.Base : blend.Blend; arch.Terrain.GenerateGrassStates(); //clear all previous roads/sea VMArchitectureTools.FloorPatternRect(arch, new Rectangle(0, 0, arch.Width, 5), 0, 0, 1); VMArchitectureTools.FloorPatternRect(arch, new Rectangle(arch.Width - 7, 0, 7, arch.Height), 0, 0, 1); VMArchitectureTools.FloorPatternRect(arch, new Rectangle(0, arch.Height - 7, arch.Width, 7), 0, 0, 1); VMArchitectureTools.FloorPatternRect(arch, new Rectangle(0, 0, 5, arch.Height), 0, 0, 1); if (baseB == TerrainType.WATER) { //... VMArchitectureTools.FloorPatternRect(arch, new Rectangle(1, 1, arch.Width - 3, arch.Height - 3), 0, 65534, 1); } //blend flags start at top left, then go clockwise. (top right, bottom right..) if ((blend.WaterFlags & 1) > 0) { FillTileLine(arch, W, 0, 0, 1, WaterLineSegments, false); } if ((blend.WaterFlags & 4) > 0) { FillTileLine(arch, W, 0, 0, 1, WaterLineSegments, true); } if ((blend.WaterFlags & 16) > 0) { FillTileLine(arch, W, (short)(arch.Width - 1), 0, 1, WaterLineSegments, false); } if ((blend.WaterFlags & 64) > 0) { FillTileLine(arch, W, 0, (short)(arch.Height - 1), 1, WaterLineSegments, true); } if ((blend.WaterFlags & 2) > 0) { FillTiles(arch, W, 1, 1, 1, 1, 1); } if ((blend.WaterFlags & 8) > 0) { FillTiles(arch, W, (short)(arch.Width - 2), 1, 1, 1, 1); } if ((blend.WaterFlags & 32) > 0) { FillTiles(arch, W, (short)(arch.Width - 2), (short)(arch.Height - 2), 1, 1, 1); } if ((blend.WaterFlags & 128) > 0) { FillTiles(arch, W, 1, (short)(arch.Height - 2), 1, 1, 1); } if ((blend.WaterFlags & 5) == 5) { StampTilemap(arch, TopWaterCorner, 1, 1, 1); } if ((blend.WaterFlags & 20) == 20) { StampTilemap(arch, RightWaterCorner, (short)(arch.Width - 7), 1, 1); } if ((blend.WaterFlags & 80) == 80) { StampTilemap(arch, BottomWaterCorner, (short)(arch.Width - 7), (short)(arch.Height - 7), 1); } if ((blend.WaterFlags & 65) == 65) { StampTilemap(arch, LeftWaterCorner, 1, (short)(arch.Height - 7), 1); } /* * * if ((blend.WaterFlags & 1) > 0) VMArchitectureTools.FloorPatternRect(arch, new Rectangle(1, 1, 4, arch.Height - 2), 0, 65534, 1); * if ((blend.WaterFlags & 2) > 0) VMArchitectureTools.FloorPatternRect(arch, new Rectangle(1, 1, arch.Width-2, 4), 0, 65534, 1); * if ((blend.WaterFlags & 4) > 0) VMArchitectureTools.FloorPatternRect(arch, new Rectangle(arch.Width-5, 1, 4, arch.Height - 2), 0, 65534, 1); * if ((blend.WaterFlags & 8) > 0) VMArchitectureTools.FloorPatternRect(arch, new Rectangle(1, arch.Height-5, arch.Width-2, 4), 0, 65534, 1); * */ //hard blends into the next terrain type FillTerrainRect(arch, new Rectangle(0, 0, 1, arch.Height - 1), (byte)(((blend.AdjFlags & 1) > 0) ? 255 : 0)); FillTerrainRect(arch, new Rectangle(0, 0, arch.Width - 1, 1), (byte)(((blend.AdjFlags & 4) > 0) ? 255 : 0)); FillTerrainRect(arch, new Rectangle(arch.Width - 2, 0, 1, arch.Height - 1), (byte)(((blend.AdjFlags & 16) > 0) ? 255 : 0)); FillTerrainRect(arch, new Rectangle(0, arch.Height - 2, arch.Width - 1, 1), (byte)(((blend.AdjFlags & 64) > 0) ? 255 : 0)); /* * FillTerrainRect(arch, new Rectangle(0, 0, 1, 1), (byte)(((blend.AdjFlags & 2) > 0) ? 255 : 0)); * FillTerrainRect(arch, new Rectangle(arch.Width - 2, 0, 1, 1), (byte)(((blend.AdjFlags & 8) > 0) ? 255 : 0)); * FillTerrainRect(arch, new Rectangle(arch.Width - 2, arch.Height - 2, 1, 1), (byte)(((blend.AdjFlags & 32) > 0) ? 255 : 0)); * FillTerrainRect(arch, new Rectangle(0, arch.Height - 2, 1, 1), (byte)(((blend.AdjFlags & 128) > 0) ? 255 : 0)); */ //smooth blends into the next terrain type ApplyTerrainBlend(arch, RotateByte(blend.AdjFlags, 0), new Rectangle(0, 0, arch.Width - 1, 24), 255, 0, -11, new Point[] { new Point(0, 0), new Point(arch.Width - 1, 0) }, new float[] { (135f / 180f) * (float)Math.PI, (225f / 180f) * (float)Math.PI }, new float[] { (15f / 180f) * (float)Math.PI, (-15f / 180f) * (float)Math.PI }); ApplyTerrainBlend(arch, RotateByte(blend.AdjFlags, 6), new Rectangle(arch.Width - 25, 0, 24, arch.Height - 1), 0, 11, 0, new Point[] { new Point(arch.Width - 1, 0), new Point(arch.Width - 1, arch.Height - 1) }, new float[] { (225f / 180f) * (float)Math.PI, (315f / 180f) * (float)Math.PI }, new float[] { (15f / 180f) * (float)Math.PI, (-15f / 180f) * (float)Math.PI }); ApplyTerrainBlend(arch, RotateByte(blend.AdjFlags, 4), new Rectangle(0, arch.Height - 25, arch.Width - 1, 24), 0, 0, 11, new Point[] { new Point(arch.Width - 1, arch.Height - 1), new Point(0, arch.Height - 1) }, new float[] { (315f / 180f) * (float)Math.PI, (45f / 180f) * (float)Math.PI }, new float[] { (15f / 180f) * (float)Math.PI, (-15f / 180f) * (float)Math.PI }); ApplyTerrainBlend(arch, RotateByte(blend.AdjFlags, 2), new Rectangle(0, 0, 24, arch.Height - 1), 255, -11, 0, new Point[] { new Point(0, arch.Height - 1), new Point(0, 0) }, new float[] { (45f / 180f) * (float)Math.PI, (135f / 180f) * (float)Math.PI }, new float[] { (15f / 180f) * (float)Math.PI, (-15f / 180f) * (float)Math.PI }); RestoreRoad(vm, roads); if (vm.GetGlobalValue(11) == -1) { //set road dir. should only really do this FIRST EVER time, then road dir changes after are manual and rotate the contents of the lot. vm.TSOState.Size &= 0xFFFF; vm.TSOState.Size |= PickRoadDir(roads) << 16; } PositionLandmarkObjects(vm); arch.SignalTerrainRedraw(); arch.DisableClip = false; }
public static int RestoreHeight(VM vm, VMTSOSurroundingTerrain terrain, int x, int y) { var sr = new float[4, 4]; for (int oy = 0; oy < 4; oy++) { var srcY = Math.Min(3, Math.Max(0, oy + y - 1)); for (int ox = 0; ox < 4; ox++) { var srcX = Math.Min(3, Math.Max(0, ox + x - 1)); sr[3 - oy, ox] = terrain.Height[srcX, srcY]; } } var baseLevel = (int)(((sr[1, 1] + sr[1, 2] + sr[2, 2] + sr[2, 1]) / 4) * 100); var target = vm.Context.Architecture.Terrain; var xn = VMArchitectureTerrain.TerrainXNoise; var yn = VMArchitectureTerrain.TerrainYNoise; for (int oy = 1; oy < target.Height; oy++) { for (int ox = 1; ox < target.Width; ox++) { int index = (target.Height - oy) * target.Width + (target.Height - ox); float fracy = (oy - 1f) / (target.Height - 2f); fracy -= (yn[index] - 0.5f) / 5f; float y1 = Cubic(sr[0, 0], sr[0, 1], sr[0, 2], sr[0, 3], fracy); float y2 = Cubic(sr[1, 0], sr[1, 1], sr[1, 2], sr[1, 3], fracy); float y3 = Cubic(sr[2, 0], sr[2, 1], sr[2, 2], sr[2, 3], fracy); float y4 = Cubic(sr[3, 0], sr[3, 1], sr[3, 2], sr[3, 3], fracy); float fracx = (ox - 1f) / (target.Width - 2f); fracx -= (xn[index] - 0.5f) / 5f; var h = Cubic(y1, y2, y3, y4, fracx); target.Heights[index] = (short)(((h * 100f) - baseLevel)); } } var lotSInfo = vm.TSOState.Size; if (vm.TSOState.OwnerID == 0) { lotSInfo = 10; } var ret = vm.Context.GetTSOBuildableArea(lotSInfo); var mailbox = vm.Entities.FirstOrDefault(m => (m.Object.OBJ.GUID == 0xEF121974 || m.Object.OBJ.GUID == 0x1D95C9B0)); if (mailbox != null && mailbox.Position != LotTilePos.OUT_OF_WORLD) { var mailheight = target.Heights[mailbox.Position.TileY * target.Width + mailbox.Position.TileX]; ret.Inflate(-1, -1); vm.Context.Architecture.DisableClip = true; VMArchitectureTools.RaiseTerrain(vm.Context.Architecture, ret, mailheight, false); vm.Context.Architecture.DisableClip = false; ret.Width--; ret.Height--; for (int oy = ret.Top; oy < ret.Bottom; oy++) { for (int ox = ret.Left; ox < ret.Right; ox++) { int index = (oy) * target.Width + (ox); target.GrassState[index] = 0; } } } target.RegenerateCenters(); if (VM.UseWorld) { vm.Context.Blueprint.Altitude = target.Heights; vm.Context.Blueprint.AltitudeCenters = target.Centers; } foreach (var obj in vm.Entities) { obj.Position = obj.Position; } return(baseLevel); }