Skip to content

Commit

Permalink
prevent invalid building destructions
Browse files Browse the repository at this point in the history
  • Loading branch information
ar1a committed Oct 4, 2024
1 parent 4b7d78d commit 8479dff
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 14 deletions.
2 changes: 1 addition & 1 deletion puzzle course.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Godot.NET.Sdk/4.4.0-dev.1">
<Project Sdk="Godot.NET.Sdk/4.4.0-dev.3">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework>
Expand Down
9 changes: 9 additions & 0 deletions puzzle course.csproj.old.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Godot.NET.Sdk/4.4.0-dev.1">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>puzzlecourse</RootNamespace>
</PropertyGroup>
</Project>
3 changes: 3 additions & 0 deletions resources/building/BuildingResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ public partial class BuildingResource : Resource
[Export]
public string Description { get; private set; }

[Export]
public bool IsBase { get; private set; }

[Export]
public bool IsDeletable { get; private set; } = true;

Expand Down
4 changes: 4 additions & 0 deletions resources/building/base.tres
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
[resource]
script = ExtResource("1_ccreb")
DisplayName = "Base"
Description = ""
IsBase = true
IsDeletable = false
Dimensions = Vector2i(5, 2)
ResourceCost = 0
BuildableRadius = 6
ResourceRadius = 0
DangerRadius = 0
AttackRadius = 0
BuildingScene = ExtResource("1_ei3r1")
2 changes: 1 addition & 1 deletion scenes/level/Level3.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ position = Vector2(1216, 192)
position = Vector2(0, 896)

[node name="GoblinCamp" parent="YSortRoot" index="4" instance=ExtResource("5_o0rsf")]
position = Vector2(192, 640)
position = Vector2(-512, 192)

[editable path="YSortRoot/BaseTerrainTileMapLayer/ElevationLayer"]
2 changes: 2 additions & 0 deletions scenes/manager/BuildingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ private void DestroyBuildAtHoveredCellPosition()
);
if (buildingComponent == null)
return;
if (!gridManager.CanDestroyBuilidng(buildingComponent))
return;

currentlyUsedResourceCount -= buildingComponent.BuildingResource.ResourceCost;
buildingComponent.Destroy();
Expand Down
115 changes: 103 additions & 12 deletions scenes/manager/GridManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public partial class GridManager : Node

private List<TileMapLayer> allTilemapLayers = new();
private Dictionary<TileMapLayer, ElevationLayer> tileMapLayerToElevationLayer = new();
private Dictionary<BuildingComponent, HashSet<Vector2I>> buildingToBuildableTiles = new();

public override void _Ready()
{
Expand Down Expand Up @@ -184,6 +185,91 @@ public Vector2I ConvertWorldPositionToTilePosition(Vector2 worldPosition)
return (Vector2I)(worldPosition / 64).Floor();
}

public bool CanDestroyBuilidng(BuildingComponent toDestroyBuildingComponent)
{
if (toDestroyBuildingComponent.BuildingResource.BuildableRadius > 0)
{
var dependentBuildings = BuildingComponent
.GetValidBuildingComponents(this)
.Where(x =>
x.GetTileArea()
.ToTiles()
.Any(
(tilePosition) =>
buildingToBuildableTiles[toDestroyBuildingComponent]
.Contains(tilePosition)
)
&& x != toDestroyBuildingComponent
&& !x.BuildingResource.IsBase
);

var allBuildingsStillValid = dependentBuildings.All(
(dependentBuilding) =>
{
var tilesForBuilding = dependentBuilding.GetTileArea().ToTiles();
return tilesForBuilding.All(tilePosition =>
buildingToBuildableTiles
.Keys.Where(key =>
key != toDestroyBuildingComponent && key != dependentBuilding
)
.Any(key => buildingToBuildableTiles[key].Contains(tilePosition))
);
}
);
if (!allBuildingsStillValid)
return false;

return IsBuildingNetworkConnected(toDestroyBuildingComponent);
}
return true;
}

private bool IsBuildingNetworkConnected(BuildingComponent toDestroyBuildingComponent)
{
var baseBuilding = BuildingComponent
.GetValidBuildingComponents(this)
.First(x => x.BuildingResource.IsBase);
var visitedBuildings = new HashSet<BuildingComponent>();
VisitAllConnectedBuildings(baseBuilding, toDestroyBuildingComponent, visitedBuildings);

var totalBuildingsToVisit = BuildingComponent
.GetValidBuildingComponents(this)
.Count(x => x != toDestroyBuildingComponent && x.BuildingResource.BuildableRadius > 0);
return totalBuildingsToVisit == visitedBuildings.Count;
}

private void VisitAllConnectedBuildings(
BuildingComponent rootBuilding,
BuildingComponent excludeBuilding,
HashSet<BuildingComponent> visitedBuildings
)
{
var dependentBuildings = BuildingComponent
.GetValidBuildingComponents(this)
.Where(x =>
{
if (x.BuildingResource.BuildableRadius == 0)
return false;
if (visitedBuildings.Contains(x))
return false;

return x.GetTileArea()
.ToTiles()
.Any(
(tilePosition) =>
buildingToBuildableTiles[rootBuilding].Contains(tilePosition)
)
&& x != excludeBuilding;
})
.ToList();

visitedBuildings.UnionWith(dependentBuildings);
foreach (var building in dependentBuildings)
{
VisitAllConnectedBuildings(building, excludeBuilding, visitedBuildings);
}
}

private HashSet<Vector2I> GetBuildableTileSet(bool isAttackTiles = false)
{
return isAttackTiles ? validBuildableAttackTiles : validBuildableTiles;
Expand Down Expand Up @@ -252,18 +338,22 @@ private void UpdateValidBuildableTiles(BuildingComponent buildingComponent)
occupiedTiles.UnionWith(buildingComponent.GetOccupiedCellPositions());
var tileArea = buildingComponent.GetTileArea();

var allTiles = GetTilesInRadius(
tileArea,
buildingComponent.BuildingResource.BuildableRadius,
(_) => true
);
allTilesInBuildingRadius.UnionWith(allTiles);
if (buildingComponent.BuildingResource.BuildableRadius > 0)
{
var allTiles = GetTilesInRadius(
tileArea,
buildingComponent.BuildingResource.BuildableRadius,
(_) => true
);
allTilesInBuildingRadius.UnionWith(allTiles);

var validTiles = GetValidTilesInRadius(
tileArea,
buildingComponent.BuildingResource.BuildableRadius
);
validBuildableTiles.UnionWith(validTiles);
var validTiles = GetValidTilesInRadius(
tileArea,
buildingComponent.BuildingResource.BuildableRadius
);
buildingToBuildableTiles[buildingComponent] = validTiles.ToHashSet();
validBuildableTiles.UnionWith(validTiles);
}
validBuildableTiles.ExceptWith(occupiedTiles);

validBuildableAttackTiles.UnionWith(validBuildableTiles);
Expand Down Expand Up @@ -312,6 +402,7 @@ private void RecalculateGrid()
collectedResourceTiles.Clear();
goblinOccupiedTiles.Clear();
attackTiles.Clear();
buildingToBuildableTiles.Clear();

var buildingComponents = BuildingComponent.GetValidBuildingComponents(this);
foreach (var buildingComponent in buildingComponents)
Expand Down Expand Up @@ -403,7 +494,7 @@ private List<Vector2I> GetResourceTilesInRadius(Rect2I tileArea, int radius)
);
}

public void UpdateBuildingComponentGridState(BuildingComponent buildingComponent)
private void UpdateBuildingComponentGridState(BuildingComponent buildingComponent)
{
UpdateGoblinOccupiedTiles(buildingComponent);
UpdateValidBuildableTiles(buildingComponent);
Expand Down

0 comments on commit 8479dff

Please sign in to comment.