Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
HouseBuilder.cs
Go to the documentation of this file.
1using System;
4using System.Linq;
9
11
12public class HouseBuilder
13{
14 private const int VERTICAL_EXIT_WIDTH = 3;
15
16 public static readonly HouseBuilder Invalid = new HouseBuilder();
17
18 public readonly HouseType Type;
19
20 public readonly bool IsValid;
21
22 protected ushort[] SkipTilesDuringWallAging = new ushort[5] { 245, 246, 240, 241, 242 };
23
24 public double ChestChance { get; set; }
25
26 public ushort TileType { get; protected set; }
27
28 public ushort WallType { get; protected set; }
29
30 public ushort BeamType { get; protected set; }
31
32 public int PlatformStyle { get; protected set; }
33
34 public int DoorStyle { get; protected set; }
35
36 public int TableStyle { get; protected set; }
37
38 public bool UsesTables2 { get; protected set; }
39
40 public int WorkbenchStyle { get; protected set; }
41
42 public int PianoStyle { get; protected set; }
43
44 public int BookcaseStyle { get; protected set; }
45
46 public int ChairStyle { get; protected set; }
47
48 public int ChestStyle { get; protected set; }
49
50 public bool UsesContainers2 { get; protected set; }
51
52 public ReadOnlyCollection<Rectangle> Rooms { get; private set; }
53
54 public Rectangle TopRoom => Rooms.First();
55
56 public Rectangle BottomRoom => Rooms.Last();
57
59
60 private Tile[,] _tiles => Main.tile;
61
62 private HouseBuilder()
63 {
64 IsValid = false;
65 }
66
68 {
69 Type = type;
70 IsValid = true;
71 List<Rectangle> list = rooms.ToList();
72 list.Sort((Rectangle lhs, Rectangle rhs) => lhs.Top.CompareTo(rhs.Top));
73 Rooms = list.AsReadOnly();
74 }
75
76 protected virtual void AgeRoom(Rectangle room)
77 {
78 }
79
80 public virtual void Place(HouseBuilderContext context, StructureMap structures)
81 {
83 foreach (Rectangle room in Rooms)
84 {
85 structures.AddProtectedStructure(room, 8);
86 }
88 PlaceDoors();
92 FillRooms();
93 foreach (Rectangle room2 in Rooms)
94 {
96 }
99 }
100
101 private void PlaceEmptyRooms()
102 {
103 foreach (Rectangle room in Rooms)
104 {
106 WorldUtils.Gen(new Point(room.X + 1, room.Y + 1), new Shapes.Rectangle(room.Width - 2, room.Height - 2), Actions.Chain(new Actions.ClearTile(frameNeighbors: true), new Actions.PlaceWall(WallType)));
107 }
108 }
109
110 private void FillRooms()
111 {
112 int x = 14;
113 if (UsesTables2)
114 {
115 x = 469;
116 }
117 Point[] choices = new Point[7]
118 {
119 new Point(x, TableStyle),
120 new Point(16, 0),
121 new Point(18, WorkbenchStyle),
122 new Point(86, 0),
123 new Point(87, PianoStyle),
124 new Point(94, 0),
125 new Point(101, BookcaseStyle)
126 };
127 foreach (Rectangle room in Rooms)
128 {
129 int num = room.Width / 8;
130 int num2 = room.Width / (num + 1);
131 int num3 = _random.Next(2);
132 for (int i = 0; i < num; i++)
133 {
134 int num4 = (i + 1) * num2 + room.X;
135 switch (i + num3 % 2)
136 {
137 case 0:
138 {
139 int num5 = room.Y + Math.Min(room.Height / 2, room.Height - 5);
141 WorldGen.PlaceTile(num4, num5, paintingEntry.tileType, mute: true, forced: false, -1, paintingEntry.style);
142 break;
143 }
144 case 1:
145 {
146 int num5 = room.Y + 1;
147 WorldGen.PlaceTile(num4, num5, 34, mute: true, forced: false, -1, _random.Next(6));
148 for (int j = -1; j < 2; j++)
149 {
150 for (int k = 0; k < 3; k++)
151 {
152 _tiles[j + num4, k + num5].frameX += 54;
153 }
154 }
155 break;
156 }
157 }
158 }
159 int num6 = room.Width / 8 + 3;
161 while (num6 > 0)
162 {
163 int num7 = _random.Next(room.Width - 3) + 1 + room.X;
164 int num8 = room.Y + room.Height - 2;
165 switch (_random.Next(4))
166 {
167 case 0:
168 WorldGen.PlaceSmallPile(num7, num8, _random.Next(31, 34), 1, 185);
169 break;
170 case 1:
171 WorldGen.PlaceTile(num7, num8, 186, mute: true, forced: false, -1, _random.Next(22, 26));
172 break;
173 case 2:
174 {
175 int num9 = _random.Next(2, GenVars.statueList.Length);
177 if (GenVars.StatuesWithTraps.Contains(num9))
178 {
180 }
181 break;
182 }
183 case 3:
184 {
185 Point point = Utils.SelectRandom(_random, choices);
186 WorldGen.PlaceTile(num7, num8, point.X, mute: true, forced: false, -1, point.Y);
187 break;
188 }
189 }
190 num6--;
191 }
192 }
193 }
194
195 private void PlaceStairs()
196 {
198 {
199 Point item = item3.Item1;
200 Point item2 = item3.Item2;
201 int num = ((item2.X > item.X) ? 1 : (-1));
203 for (int i = 0; i < item2.Y - item.Y; i++)
204 {
205 shapeData.Add(num * (i + 1), i);
206 }
208 WorldUtils.Gen(new Point(item.X + ((num == 1) ? 1 : (-4)), item.Y - 1), new Shapes.Rectangle(4, 1), Actions.Chain(new Actions.Clear(), new Actions.PlaceWall(WallType), new Actions.PlaceTile(19, PlatformStyle), new Actions.SetFrames(frameNeighbors: true)));
209 }
210 }
211
213 {
215 for (int i = 1; i < Rooms.Count; i++)
216 {
218 Rectangle rectangle2 = Rooms[i - 1];
219 int num = rectangle2.X - rectangle.X;
220 int num2 = rectangle.X + rectangle.Width - (rectangle2.X + rectangle2.Width);
221 if (num > num2)
222 {
223 list.Add(new Tuple<Point, Point>(new Point(rectangle.X + rectangle.Width - 1, rectangle.Y + 1), new Point(rectangle.X + rectangle.Width - rectangle.Height + 1, rectangle.Y + rectangle.Height - 1)));
224 }
225 else
226 {
227 list.Add(new Tuple<Point, Point>(new Point(rectangle.X, rectangle.Y + 1), new Point(rectangle.X + rectangle.Height - 1, rectangle.Y + rectangle.Height - 1)));
228 }
229 }
230 return list;
231 }
232
233 private void PlaceDoors()
234 {
235 foreach (Point item in CreateDoorList())
236 {
238 WorldGen.PlaceTile(item.X, item.Y, 10, mute: true, forced: true, -1, DoorStyle);
239 }
240 }
241
243 {
245 foreach (Rectangle room in Rooms)
246 {
247 if (FindSideExit(new Rectangle(room.X + room.Width, room.Y + 1, 1, room.Height - 2), isLeft: false, out var exitY))
248 {
249 list.Add(new Point(room.X + room.Width - 1, exitY));
250 }
251 if (FindSideExit(new Rectangle(room.X, room.Y + 1, 1, room.Height - 2), isLeft: true, out exitY))
252 {
253 list.Add(new Point(room.X, exitY));
254 }
255 }
256 return list;
257 }
258
259 private void PlacePlatforms()
260 {
261 foreach (Point item in CreatePlatformsList())
262 {
264 }
265 }
266
268 {
272 if (FindVerticalExit(new Rectangle(topRoom.X + 2, topRoom.Y, topRoom.Width - 4, 1), isUp: true, out var exitX))
273 {
274 list.Add(new Point(exitX, topRoom.Y));
275 }
276 if (FindVerticalExit(new Rectangle(bottomRoom.X + 2, bottomRoom.Y + bottomRoom.Height - 1, bottomRoom.Width - 4, 1), isUp: false, out exitX))
277 {
278 list.Add(new Point(exitX, bottomRoom.Y + bottomRoom.Height - 1));
279 }
280 return list;
281 }
282
283 private void PlaceSupportBeams()
284 {
286 {
287 if (item.Height > 1 && _tiles[item.X, item.Y - 1].type != 19)
288 {
290 Tile tile = _tiles[item.X, item.Y + item.Height];
291 tile.slope(0);
292 tile.halfBrick(halfBrick: false);
293 }
294 }
295 }
296
298 {
300 int num = Rooms.Min((Rectangle room) => room.Left);
301 int num2 = Rooms.Max((Rectangle room) => room.Right) - 1;
302 int num3 = 6;
303 while (num3 > 4 && (num2 - num) % num3 != 0)
304 {
305 num3--;
306 }
307 for (int i = num; i <= num2; i += num3)
308 {
309 for (int j = 0; j < Rooms.Count; j++)
310 {
313 {
314 continue;
315 }
316 int num4 = rectangle.Y + rectangle.Height;
317 int num5 = 50;
318 for (int k = j + 1; k < Rooms.Count; k++)
319 {
320 if (i >= Rooms[k].X && i < Rooms[k].X + Rooms[k].Width)
321 {
322 num5 = Math.Min(num5, Rooms[k].Y - num4);
323 }
324 }
325 if (num5 > 0)
326 {
327 Point result;
328 bool flag = WorldUtils.Find(new Point(i, num4), Searches.Chain(new Searches.Down(num5), new Conditions.IsSolid()), out result);
329 if (num5 < 50)
330 {
331 flag = true;
332 result = new Point(i, num4 + num5);
333 }
334 if (flag)
335 {
336 list.Add(new Rectangle(i, num4, 1, result.Y - num4));
337 }
338 }
339 }
340 }
341 return list;
342 }
343
344 private static bool FindVerticalExit(Rectangle wall, bool isUp, out int exitX)
345 {
346 Point result;
347 bool result2 = WorldUtils.Find(new Point(wall.X + wall.Width - 3, wall.Y + (isUp ? (-5) : 0)), Searches.Chain(new Searches.Left(wall.Width - 3), new Conditions.IsSolid().Not().AreaOr(3, 5)), out result);
348 exitX = result.X;
349 return result2;
350 }
351
352 private static bool FindSideExit(Rectangle wall, bool isLeft, out int exitY)
353 {
354 Point result;
355 bool result2 = WorldUtils.Find(new Point(wall.X + (isLeft ? (-4) : 0), wall.Y + wall.Height - 3), Searches.Chain(new Searches.Up(wall.Height - 3), new Conditions.IsSolid().Not().AreaOr(4, 3)), out result);
356 exitY = result.Y;
357 return result2;
358 }
359
360 private void PlaceChests()
361 {
363 {
364 return;
365 }
366 bool flag = false;
367 foreach (Rectangle room in Rooms)
368 {
369 int num = room.Height - 1 + room.Y;
370 bool num2 = num > (int)Main.worldSurface;
371 ushort chestTileType = (ushort)((num2 && UsesContainers2) ? 467 : 21);
372 int style = (num2 ? ChestStyle : 0);
373 for (int i = 0; i < 10; i++)
374 {
375 if (flag = WorldGen.AddBuriedChest(_random.Next(2, room.Width - 2) + room.X, num, 0, notNearOtherChests: false, style, trySlope: false, chestTileType))
376 {
377 break;
378 }
379 }
380 if (flag)
381 {
382 break;
383 }
384 for (int j = room.X + 2; j <= room.X + room.Width - 2; j++)
385 {
386 if (flag = WorldGen.AddBuriedChest(j, num, 0, notNearOtherChests: false, style, trySlope: false, chestTileType))
387 {
388 break;
389 }
390 }
391 if (flag)
392 {
393 break;
394 }
395 }
396 if (!flag)
397 {
398 foreach (Rectangle room2 in Rooms)
399 {
400 int num3 = room2.Y - 1;
401 bool num4 = num3 > (int)Main.worldSurface;
402 ushort chestTileType2 = (ushort)((num4 && UsesContainers2) ? 467 : 21);
403 int style2 = (num4 ? ChestStyle : 0);
404 for (int k = 0; k < 10; k++)
405 {
406 if (flag = WorldGen.AddBuriedChest(_random.Next(2, room2.Width - 2) + room2.X, num3, 0, notNearOtherChests: false, style2, trySlope: false, chestTileType2))
407 {
408 break;
409 }
410 }
411 if (flag)
412 {
413 break;
414 }
415 for (int l = room2.X + 2; l <= room2.X + room2.Width - 2; l++)
416 {
418 {
419 break;
420 }
421 }
422 if (flag)
423 {
424 break;
425 }
426 }
427 }
428 if (flag)
429 {
430 return;
431 }
432 for (int m = 0; m < 1000; m++)
433 {
434 int i2 = _random.Next(Rooms[0].X - 30, Rooms[0].X + 30);
435 int num5 = _random.Next(Rooms[0].Y - 30, Rooms[0].Y + 30);
436 bool num6 = num5 > (int)Main.worldSurface;
437 ushort chestTileType3 = (ushort)((num6 && UsesContainers2) ? 467 : 21);
438 int style3 = (num6 ? ChestStyle : 0);
440 {
441 break;
442 }
443 }
444 }
445
447 {
449 {
450 return;
451 }
452 bool flag = false;
453 foreach (Rectangle room in Rooms)
454 {
455 int num = room.Height - 2 + room.Y;
456 if (WorldGen.remixWorldGen && (double)num > Main.rockLayer)
457 {
458 return;
459 }
460 for (int i = 0; i < 10; i++)
461 {
462 int num2 = _random.Next(2, room.Width - 2) + room.X;
463 WorldGen.PlaceTile(num2, num, 506, mute: true, forced: true);
464 if (flag = _tiles[num2, num].active() && _tiles[num2, num].type == 506)
465 {
466 break;
467 }
468 }
469 if (flag)
470 {
471 break;
472 }
473 for (int j = room.X + 2; j <= room.X + room.Width - 2; j++)
474 {
475 if (flag = WorldGen.PlaceTile(j, num, 506, mute: true, forced: true))
476 {
477 break;
478 }
479 }
480 if (flag)
481 {
482 break;
483 }
484 }
485 if (!flag)
486 {
487 foreach (Rectangle room2 in Rooms)
488 {
489 int num3 = room2.Y - 1;
490 for (int k = 0; k < 10; k++)
491 {
492 int num4 = _random.Next(2, room2.Width - 2) + room2.X;
493 WorldGen.PlaceTile(num4, num3, 506, mute: true, forced: true);
494 if (flag = _tiles[num4, num3].active() && _tiles[num4, num3].type == 506)
495 {
496 break;
497 }
498 }
499 if (flag)
500 {
501 break;
502 }
503 for (int l = room2.X + 2; l <= room2.X + room2.Width - 2; l++)
504 {
505 if (flag = WorldGen.PlaceTile(l, num3, 506, mute: true, forced: true))
506 {
507 break;
508 }
509 }
510 if (flag)
511 {
512 break;
513 }
514 }
515 }
516 if (flag)
517 {
519 }
520 }
521
523 {
524 if (Type == HouseType.Jungle && context.SharpenerCount < _random.Next(2, 5))
525 {
526 bool flag = false;
527 foreach (Rectangle room in Rooms)
528 {
529 int num = room.Height - 2 + room.Y;
530 for (int i = 0; i < 10; i++)
531 {
532 int num2 = _random.Next(2, room.Width - 2) + room.X;
533 WorldGen.PlaceTile(num2, num, 377, mute: true, forced: true);
534 if (flag = _tiles[num2, num].active() && _tiles[num2, num].type == 377)
535 {
536 break;
537 }
538 }
539 if (flag)
540 {
541 break;
542 }
543 for (int j = room.X + 2; j <= room.X + room.Width - 2; j++)
544 {
545 if (flag = WorldGen.PlaceTile(j, num, 377, mute: true, forced: true))
546 {
547 break;
548 }
549 }
550 if (flag)
551 {
552 break;
553 }
554 }
555 if (flag)
556 {
557 context.SharpenerCount++;
558 }
559 }
560 if (Type != HouseType.Desert || context.ExtractinatorCount >= _random.Next(2, 5))
561 {
562 return;
563 }
564 bool flag2 = false;
565 foreach (Rectangle room2 in Rooms)
566 {
567 int num3 = room2.Height - 2 + room2.Y;
568 for (int k = 0; k < 10; k++)
569 {
570 int num4 = _random.Next(2, room2.Width - 2) + room2.X;
571 WorldGen.PlaceTile(num4, num3, 219, mute: true, forced: true);
572 if (flag2 = _tiles[num4, num3].active() && _tiles[num4, num3].type == 219)
573 {
574 break;
575 }
576 }
577 if (flag2)
578 {
579 break;
580 }
581 for (int l = room2.X + 2; l <= room2.X + room2.Width - 2; l++)
582 {
583 if (flag2 = WorldGen.PlaceTile(l, num3, 219, mute: true, forced: true))
584 {
585 break;
586 }
587 }
588 if (flag2)
589 {
590 break;
591 }
592 }
593 if (flag2)
594 {
595 context.ExtractinatorCount++;
596 }
597 }
598}
void Add(TKey key, TValue value)
static byte Min(byte val1, byte val2)
Definition Math.cs:912
HouseBuilder(HouseType type, IEnumerable< Rectangle > rooms)
void PlaceBiomeSpecificTool(HouseBuilderContext context)
static bool FindVerticalExit(Rectangle wall, bool isUp, out int exitX)
virtual void Place(HouseBuilderContext context, StructureMap structures)
void PlaceBiomeSpecificPriorityTool(HouseBuilderContext context)
List< Tuple< Point, Point > > CreateStairsList()
static bool FindSideExit(Rectangle wall, bool isLeft, out int exitY)
static double worldSurface
Definition Main.cs:1272
static double rockLayer
Definition Main.cs:1274
static Tile[,] tile
Definition Main.cs:1675
ushort type
Definition Tile.cs:8
short frameX
Definition Tile.cs:22
byte slope()
Definition Tile.cs:684
bool halfBrick()
Definition Tile.cs:650
static GenAction Chain(params GenAction[] actions)
Definition Actions.cs:470
GenCondition AreaOr(int width, int height)
static List< int > StatuesWithTraps
Definition GenVars.cs:306
static Point16[] statueList
Definition GenVars.cs:304
static GenSearch Chain(GenSearch search, params GenCondition[] conditions)
Definition Searches.cs:123
static bool Find(Point origin, GenSearch search, out Point result)
Definition WorldUtils.cs:27
static bool Gen(Point origin, GenShape shape, GenAction action)
Definition WorldUtils.cs:17
static PaintingEntry RandHousePictureDesert()
static bool remixWorldGen
Definition WorldGen.cs:1148
static bool PlaceSmallPile(int i, int j, int X, int Y, ushort type=185)
static bool PlaceTile(int i, int j, int Type, bool mute=false, bool forced=false, int plr=-1, int style=0)
static UnifiedRandom genRand
Definition WorldGen.cs:1215
static bool AddBuriedChest(Point point, int contain=0, bool notNearOtherChests=false, int Style=-1)
static void SetupStatueList()
Definition WorldGen.cs:1246
static PaintingEntry RandHousePicture()
static void PlaceStatueTrap(int x, int y)
Definition WorldGen.cs:1287