terraria-source-code/GameContent/Biomes/DeadMansChestBiome.cs
2021-10-26 12:45:26 -04:00

461 lines
16 KiB
C#

// Decompiled with JetBrains decompiler
// Type: Terraria.GameContent.Biomes.DeadMansChestBiome
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using Microsoft.Xna.Framework;
using Newtonsoft.Json;
using System.Collections.Generic;
using Terraria.ID;
using Terraria.Utilities;
using Terraria.WorldBuilding;
namespace Terraria.GameContent.Biomes
{
public class DeadMansChestBiome : MicroBiome
{
private List<DeadMansChestBiome.DartTrapPlacementAttempt> _dartTrapPlacementSpots = new List<DeadMansChestBiome.DartTrapPlacementAttempt>();
private List<DeadMansChestBiome.WirePlacementAttempt> _wirePlacementSpots = new List<DeadMansChestBiome.WirePlacementAttempt>();
private List<DeadMansChestBiome.BoulderPlacementAttempt> _boulderPlacementSpots = new List<DeadMansChestBiome.BoulderPlacementAttempt>();
private List<DeadMansChestBiome.ExplosivePlacementAttempt> _explosivePlacementAttempt = new List<DeadMansChestBiome.ExplosivePlacementAttempt>();
[JsonProperty("NumberOfDartTraps")]
private IntRange _numberOfDartTraps = new IntRange(3, 6);
[JsonProperty("NumberOfBoulderTraps")]
private IntRange _numberOfBoulderTraps = new IntRange(2, 4);
[JsonProperty("NumberOfStepsBetweenBoulderTraps")]
private IntRange _numberOfStepsBetweenBoulderTraps = new IntRange(2, 4);
public override bool Place(Point origin, StructureMap structures)
{
if (!DeadMansChestBiome.IsAGoodSpot(origin))
return false;
this.ClearCaches();
Point position = new Point(origin.X, origin.Y + 1);
this.FindBoulderTrapSpots(position);
this.FindDartTrapSpots(position);
this.FindExplosiveTrapSpots(position);
if (!this.AreThereEnoughTraps())
return false;
this.TurnGoldChestIntoDeadMansChest(origin);
foreach (DeadMansChestBiome.DartTrapPlacementAttempt trapPlacementSpot in this._dartTrapPlacementSpots)
this.ActuallyPlaceDartTrap(trapPlacementSpot.position, trapPlacementSpot.directionX, trapPlacementSpot.x, trapPlacementSpot.y, trapPlacementSpot.xPush, trapPlacementSpot.t);
foreach (DeadMansChestBiome.WirePlacementAttempt wirePlacementSpot in this._wirePlacementSpots)
this.PlaceWireLine(wirePlacementSpot.position, wirePlacementSpot.dirX, wirePlacementSpot.dirY, wirePlacementSpot.steps);
foreach (DeadMansChestBiome.BoulderPlacementAttempt boulderPlacementSpot in this._boulderPlacementSpots)
this.ActuallyPlaceBoulderTrap(boulderPlacementSpot.position, boulderPlacementSpot.yPush, boulderPlacementSpot.requiredHeight, boulderPlacementSpot.bestType);
foreach (DeadMansChestBiome.ExplosivePlacementAttempt placementAttempt in this._explosivePlacementAttempt)
this.ActuallyPlaceExplosive(placementAttempt.position);
this.PlaceWiresForExplosives(origin);
return true;
}
private void PlaceWiresForExplosives(Point origin)
{
if (this._explosivePlacementAttempt.Count <= 0)
return;
this.PlaceWireLine(origin, 0, 1, this._explosivePlacementAttempt[0].position.Y - origin.Y);
int x1 = this._explosivePlacementAttempt[0].position.X;
int num = this._explosivePlacementAttempt[0].position.X;
int y = this._explosivePlacementAttempt[0].position.Y;
for (int index = 1; index < this._explosivePlacementAttempt.Count; ++index)
{
int x2 = this._explosivePlacementAttempt[index].position.X;
if (x1 > x2)
x1 = x2;
if (num < x2)
num = x2;
}
this.PlaceWireLine(new Point(x1, y), 1, 0, num - x1);
}
private bool AreThereEnoughTraps() => (this._boulderPlacementSpots.Count >= 1 || this._explosivePlacementAttempt.Count >= 1) && this._dartTrapPlacementSpots.Count >= 1;
private void ClearCaches()
{
this._dartTrapPlacementSpots.Clear();
this._wirePlacementSpots.Clear();
this._boulderPlacementSpots.Clear();
this._explosivePlacementAttempt.Clear();
}
private void FindBoulderTrapSpots(Point position)
{
int x1 = position.X;
int num1 = GenBase._random.Next(this._numberOfBoulderTraps);
int num2 = GenBase._random.Next(this._numberOfStepsBetweenBoulderTraps);
int x2 = x1 - num1 / 2 * num2;
int y = position.Y - 6;
for (int index = 0; index <= num1; ++index)
{
this.FindBoulderTrapSpot(new Point(x2, y));
x2 += num2;
}
if (this._boulderPlacementSpots.Count <= 0)
return;
int x3 = this._boulderPlacementSpots[0].position.X;
int num3 = this._boulderPlacementSpots[0].position.X;
for (int index = 1; index < this._boulderPlacementSpots.Count; ++index)
{
int x4 = this._boulderPlacementSpots[index].position.X;
if (x3 > x4)
x3 = x4;
if (num3 < x4)
num3 = x4;
}
if (x3 > position.X)
x3 = position.X;
if (num3 < position.X)
num3 = position.X;
this._wirePlacementSpots.Add(new DeadMansChestBiome.WirePlacementAttempt(new Point(x3, y - 1), 1, 0, num3 - x3));
this._wirePlacementSpots.Add(new DeadMansChestBiome.WirePlacementAttempt(position, 0, -1, 7));
}
private void FindBoulderTrapSpot(Point position)
{
int x = position.X;
int y = position.Y;
for (int yPush = 0; yPush < 50; ++yPush)
{
if (Main.tile[x, y - yPush].active())
{
this.PlaceBoulderTrapSpot(new Point(x, y - yPush), yPush);
break;
}
}
}
private void PlaceBoulderTrapSpot(Point position, int yPush)
{
int[] numArray = new int[623];
for (int x = position.X; x < position.X + 2; ++x)
{
for (int index = position.Y - 4; index <= position.Y; ++index)
{
Tile tile = Main.tile[x, index];
if (tile.active() && !Main.tileFrameImportant[(int) tile.type] && Main.tileSolid[(int) tile.type])
++numArray[(int) tile.type];
if (tile.active() && !TileID.Sets.CanBeClearedDuringGeneration[(int) tile.type])
return;
}
}
for (int index1 = position.X - 1; index1 < position.X + 2 + 1; ++index1)
{
for (int index2 = position.Y - 4 - 1; index2 <= position.Y - 4 + 2; ++index2)
{
if (!Main.tile[index1, index2].active())
return;
}
}
int bestType = -1;
for (int index = 0; index < numArray.Length; ++index)
{
if (bestType == -1 || numArray[bestType] < numArray[index])
bestType = index;
}
this._boulderPlacementSpots.Add(new DeadMansChestBiome.BoulderPlacementAttempt(position, yPush - 1, 4, bestType));
}
private void FindDartTrapSpots(Point position)
{
int num1 = GenBase._random.Next(this._numberOfDartTraps);
int directionX = GenBase._random.Next(2) == 0 ? -1 : 1;
int steps = -1;
for (int index = 0; index < num1; ++index)
{
int num2 = this.FindDartTrapSpotSingle(position, directionX) ? 1 : 0;
directionX *= -1;
--position.Y;
if (num2 != 0)
steps = index;
}
this._wirePlacementSpots.Add(new DeadMansChestBiome.WirePlacementAttempt(new Point(position.X, position.Y + num1), 0, -1, steps));
}
private bool FindDartTrapSpotSingle(Point position, int directionX)
{
int x = position.X;
int y = position.Y;
for (int xPush = 0; xPush < 20; ++xPush)
{
Tile t = Main.tile[x + xPush * directionX, y];
if (t.type != (ushort) 467 && t.active() && Main.tileSolid[(int) t.type])
{
if (xPush < 5 || t.actuator() || Main.tileFrameImportant[(int) t.type] || !TileID.Sets.CanBeClearedDuringGeneration[(int) t.type])
return false;
this._dartTrapPlacementSpots.Add(new DeadMansChestBiome.DartTrapPlacementAttempt(position, directionX, x, y, xPush, t));
return true;
}
}
return false;
}
private void FindExplosiveTrapSpots(Point position)
{
int x1 = position.X;
int y = position.Y + 3;
List<int> intList = new List<int>();
if (this.IsGoodSpotsForExplosive(x1, y))
intList.Add(x1);
int x2 = x1 + 1;
if (this.IsGoodSpotsForExplosive(x2, y))
intList.Add(x2);
int x3 = -1;
if (intList.Count > 0)
x3 = intList[GenBase._random.Next(intList.Count)];
intList.Clear();
int num1 = x2 + GenBase._random.Next(2, 6);
int num2 = 4;
for (int x4 = num1; x4 < num1 + num2; ++x4)
{
if (this.IsGoodSpotsForExplosive(x4, y))
intList.Add(x4);
}
int x5 = -1;
if (intList.Count > 0)
x5 = intList[GenBase._random.Next(intList.Count)];
int num3 = position.X - num2 - GenBase._random.Next(2, 6);
for (int x6 = num3; x6 < num3 + num2; ++x6)
{
if (this.IsGoodSpotsForExplosive(x6, y))
intList.Add(x6);
}
int x7 = -1;
if (intList.Count > 0)
x7 = intList[GenBase._random.Next(intList.Count)];
if (x7 != -1)
this._explosivePlacementAttempt.Add(new DeadMansChestBiome.ExplosivePlacementAttempt(new Point(x7, y)));
if (x3 != -1)
this._explosivePlacementAttempt.Add(new DeadMansChestBiome.ExplosivePlacementAttempt(new Point(x3, y)));
if (x5 == -1)
return;
this._explosivePlacementAttempt.Add(new DeadMansChestBiome.ExplosivePlacementAttempt(new Point(x5, y)));
}
private bool IsGoodSpotsForExplosive(int x, int y)
{
Tile tile = Main.tile[x, y];
return tile.active() && Main.tileSolid[(int) tile.type] && !Main.tileFrameImportant[(int) tile.type] && !Main.tileSolidTop[(int) tile.type];
}
public List<int> GetPossibleChestsToTrapify(StructureMap structures)
{
List<int> intList = new List<int>();
bool[] validTiles = new bool[TileID.Sets.GeneralPlacementTiles.Length];
for (int index = 0; index < validTiles.Length; ++index)
validTiles[index] = TileID.Sets.GeneralPlacementTiles[index];
validTiles[21] = true;
validTiles[467] = true;
for (int index = 0; index < 8000; ++index)
{
Chest chest = Main.chest[index];
if (chest != null)
{
Point position1 = new Point(chest.x, chest.y);
if (DeadMansChestBiome.IsAGoodSpot(position1))
{
this.ClearCaches();
Point position2 = new Point(position1.X, position1.Y + 1);
this.FindBoulderTrapSpots(position2);
this.FindDartTrapSpots(position2);
if (this.AreThereEnoughTraps() && (structures == null || structures.CanPlace(new Microsoft.Xna.Framework.Rectangle(position1.X, position1.Y, 1, 1), validTiles, 10)))
intList.Add(index);
}
}
}
return intList;
}
private static bool IsAGoodSpot(Point position)
{
if (!WorldGen.InWorld(position.X, position.Y, 50) || WorldGen.oceanDepths(position.X, position.Y))
return false;
Tile tile1 = Main.tile[position.X, position.Y];
if (tile1.type != (ushort) 21 || (int) tile1.frameX / 36 != 1)
return false;
Tile tile2 = Main.tile[position.X, position.Y + 2];
return TileID.Sets.CanBeClearedDuringGeneration[(int) tile2.type] && WorldGen.countWires(position.X, position.Y, 20) <= 0 && WorldGen.countTiles(position.X, position.Y, lavaOk: true) >= 40;
}
private void TurnGoldChestIntoDeadMansChest(Point position)
{
for (int index1 = 0; index1 < 2; ++index1)
{
for (int index2 = 0; index2 < 2; ++index2)
{
int index3 = position.X + index1;
int index4 = position.Y + index2;
Tile tile = Main.tile[index3, index4];
tile.type = (ushort) 467;
tile.frameX = (short) (144 + index1 * 18);
tile.frameY = (short) (index2 * 18);
}
}
if (GenBase._random.Next(3) != 0)
return;
int chest = Chest.FindChest(position.X, position.Y);
if (chest <= -1)
return;
Item[] objArray = Main.chest[chest].item;
for (int index = objArray.Length - 2; index > 0; --index)
{
Item obj = objArray[index];
if (obj.stack != 0)
objArray[index + 1] = obj.DeepClone();
}
objArray[1] = new Item();
objArray[1].SetDefaults(5007);
Main.chest[chest].item = objArray;
}
private void ActuallyPlaceDartTrap(
Point position,
int directionX,
int x,
int y,
int xPush,
Tile t)
{
t.type = (ushort) 137;
t.frameY = (short) 0;
t.frameX = directionX != -1 ? (short) 0 : (short) 18;
t.slope((byte) 0);
t.halfBrick(false);
WorldGen.TileFrame(x, y, true);
this.PlaceWireLine(position, directionX, 0, xPush);
}
private void PlaceWireLine(Point start, int offsetX, int offsetY, int steps)
{
for (int index = 0; index <= steps; ++index)
Main.tile[start.X + offsetX * index, start.Y + offsetY * index].wire(true);
}
private void ActuallyPlaceBoulderTrap(
Point position,
int yPush,
int requiredHeight,
int bestType)
{
for (int x = position.X; x < position.X + 2; ++x)
{
for (int j = position.Y - requiredHeight; j <= position.Y + 2; ++j)
{
Tile tile = Main.tile[x, j];
if (j < position.Y - requiredHeight + 2)
tile.ClearTile();
else if (j <= position.Y)
{
if (!tile.active())
{
tile.active(true);
tile.type = (ushort) bestType;
}
tile.slope((byte) 0);
tile.halfBrick(false);
tile.actuator(true);
tile.wire(true);
WorldGen.TileFrame(x, j, true);
}
else
tile.ClearTile();
}
}
int i = position.X + 1;
int j1 = position.Y - requiredHeight + 1;
int num1 = 3;
int num2 = i - num1;
int num3 = j1 - num1;
int num4 = i + num1 - 1;
int num5 = j1 + num1 - 1;
for (int index1 = num2; index1 <= num4; ++index1)
{
for (int index2 = num3; index2 <= num5; ++index2)
{
if (Main.tile[index1, index2].type != (ushort) 138)
Main.tile[index1, index2].type = (ushort) 1;
}
}
WorldGen.PlaceTile(i, j1, 138);
this.PlaceWireLine(position, 0, 1, yPush);
}
private void ActuallyPlaceExplosive(Point position)
{
Tile tile = Main.tile[position.X, position.Y];
tile.type = (ushort) 141;
int num1;
short num2 = (short) (num1 = 0);
tile.frameY = (short) num1;
tile.frameX = num2;
tile.slope((byte) 0);
tile.halfBrick(false);
WorldGen.TileFrame(position.X, position.Y, true);
}
private class DartTrapPlacementAttempt
{
public int directionX;
public int xPush;
public int x;
public int y;
public Point position;
public Tile t;
public DartTrapPlacementAttempt(
Point position,
int directionX,
int x,
int y,
int xPush,
Tile t)
{
this.position = position;
this.directionX = directionX;
this.x = x;
this.y = y;
this.xPush = xPush;
this.t = t;
}
}
private class BoulderPlacementAttempt
{
public Point position;
public int yPush;
public int requiredHeight;
public int bestType;
public BoulderPlacementAttempt(Point position, int yPush, int requiredHeight, int bestType)
{
this.position = position;
this.yPush = yPush;
this.requiredHeight = requiredHeight;
this.bestType = bestType;
}
}
private class WirePlacementAttempt
{
public Point position;
public int dirX;
public int dirY;
public int steps;
public WirePlacementAttempt(Point position, int dirX, int dirY, int steps)
{
this.position = position;
this.dirX = dirX;
this.dirY = dirY;
this.steps = steps;
}
}
private class ExplosivePlacementAttempt
{
public Point position;
public ExplosivePlacementAttempt(Point position) => this.position = position;
}
}
}