private void ReturnToRuin(ConstructionSpace space, GameObject buildingLogic)
    {
        Tilemap ruinShape = space.Data.RuinShape;

        if (Map != null)
        {
            foreach (Vector3Int ruinShapePosition in ruinShape.cellBounds.allPositionsWithin)
            {
                Vector3Int mapPosition = space.LocalOrigin + ruinShapePosition;
                Map.SetTile(mapPosition, ruinShape.GetTile(ruinShapePosition));
                _positionToBuildingLogic.Remove(mapPosition);
            }
            audioManager.PlayBuildingDestroyed();
        }

        if (buildingLogic != null)
        {
            _activeBuildingLogic.Remove(buildingLogic);
            OnHealthBonusMayHaveChanged();
        }

        if (_constructionSpaceToWallSprite.ContainsKey(space))
        {
            Destroy(_constructionSpaceToWallSprite[space]);
            _constructionSpaceToWallSprite.Remove(space);
        }

        GameObject ruinLogic = _constructionSpaceToRuinLogic[space];

        if (ruinLogic != null)
        {
            ruinLogic.SetActive(true);
        }
    }
    public void ConstructBuildingOnTile(Vector3Int position, BuildingData buildingOption)
    {
        if (!HasRuin(position))
        {
            Debug.LogError($"Position {position} does not have a ruined building to restore");
            return;
        }

        ConstructionSpace space         = _positionToConstructionSpace[position];
        Tilemap           buildingShape = buildingOption.BuildingShape;

        GameObject buildingLogic = null;

        if (buildingOption.LogicPrefab != null)
        {
            int buildingCost = GetConstructionCost(buildingOption);

            if (playerStats.GetMind() - buildingCost < 0)
            {
                return;
            }
            playerStats.UpdateMind(buildingCost * -1.0f);

            buildingLogic = Instantiate(buildingOption.LogicPrefab);
            buildingLogic.transform.position = GetConstructionSpaceWorldCenter(space);
            _activeBuildingLogic.Add(buildingLogic);
            OnHealthBonusMayHaveChanged();

            buildingLogic.GetComponent <BuildingHealth>().BuildingManager    = this;
            buildingLogic.GetComponent <BuildingLogicBase>().BuildingManager = this;

            audioManager.PlayBuildingBuilt();

            BuildingOnDestroyProxy proxy = buildingLogic.AddComponent <BuildingOnDestroyProxy>();
            proxy.OnDestroyEvent.AddListener(() => ReturnToRuin(space, buildingLogic));
        }

        BoundsInt ruinBounds = _positionToConstructionSpace[position].Data.RuinShape.cellBounds;

        foreach (Vector3Int buildingPosition in buildingShape.cellBounds.allPositionsWithin)
        {
            Vector3Int buildingOffsetCompensation = ruinBounds.min - buildingShape.cellBounds.min;
            Vector3Int mapPosition = space.LocalOrigin + buildingOffsetCompensation + buildingPosition;
            Map.SetTile(mapPosition, buildingShape.GetTile(buildingPosition));
            _positionToBuildingLogic.Add(mapPosition, buildingLogic);
        }

        GameObject ruinLogic = _constructionSpaceToRuinLogic[space];

        if (ruinLogic != null)
        {
            ruinLogic.SetActive(false);
        }
    }
    private void OnDrawGizmos()
    {
        for (int i = 0; i < ConstructionSpaces.Length; i++)
        {
            ConstructionSpace space = ConstructionSpaces[i];

            Gizmos.color = Color.HSVToRGB((float)(i + 1) / ConstructionSpaces.Length, 1, 1);

            if (space.Data == null || space.Data.RuinShape == null)
            {
                continue;
            }
            BoundsInt bounds = space.Data.RuinShape.cellBounds;
            Vector3   min    = Map.CellToWorld(space.LocalOrigin + bounds.min);
            Vector3   max    = Map.CellToWorld(space.LocalOrigin + bounds.max);

            Gizmos.DrawCube((min + max) / 2, max - min);
        }
    }
 private Vector3 GetConstructionSpaceWorldCenter(ConstructionSpace space)
 {
     return(Map.LocalToWorld(Map.CellToLocalInterpolated(space.LocalOrigin + space.Data.RuinShape.cellBounds.center)));
 }
    public void ExecuteActionOnBuilding(Vector3Int position, BuildingAction action)
    {
        GameObject        buildingLogic = _positionToBuildingLogic[position];
        BuildingHealth    health        = buildingLogic.GetComponent <BuildingHealth>();
        BuildingLogicBase logic         = buildingLogic.GetComponent <BuildingLogicBase>();

        switch (action)
        {
        case BuildingAction.UPGRADE_HEALTH:
            int healthUpgradeCost = GetHealthUpgradeCost(health);
            if (healthUpgradeCost > playerStats.GetMind())
            {
                Debug.Log("Upgrade health failed");
                return;
            }
            health.DoUpgradeHealth();
            playerStats.UpdateMind(-healthUpgradeCost);

            ConstructionSpace space = _positionToConstructionSpace[position];
            if (health.WallSprite != null && !_constructionSpaceToWallSprite.ContainsKey(space))
            {
                GameObject wallSprite = Instantiate(WallPrefab);
                wallSprite.GetComponent <SpriteRenderer>().sprite = health.WallSprite;
                wallSprite.transform.position         = GetConstructionSpaceWorldCenter(space) + Vector3.back;
                _constructionSpaceToWallSprite[space] = wallSprite;
            }

            switch (logic.GetBuildingType())
            {
            case "library":
                audioManager.PlayUpLibrary();
                break;

            case "market":
                audioManager.PlayUpMarket();
                break;

            case "gym":
                audioManager.PlayUpGym();
                break;

            case "amp":
                audioManager.PlayUpAmp();
                break;

            case "vice":
                audioManager.PlayUpVice();
                break;
            }
            return;

        case BuildingAction.UPGRADE_PRODUCTION:
            int productionUpgradeCost = GetProductionUpgradeCost(logic);
            if (productionUpgradeCost > playerStats.GetMind())
            {
                Debug.Log("Upgrade production failed");
                return;
            }
            logic.DoUpgradeProduction();
            playerStats.UpdateMind(-productionUpgradeCost);
            switch (logic.GetBuildingType())
            {
            case "library":
                audioManager.PlayUpLibrary();
                break;

            case "market":
                audioManager.PlayUpMarket();
                break;

            case "gym":
                audioManager.PlayUpGym();
                break;

            case "amp":
                audioManager.PlayUpAmp();
                break;

            case "vice":
                audioManager.PlayUpVice();
                break;
            }
            return;

        case BuildingAction.REPAIR:
            audioManager.PlayBuildingBuilt();
            int repairCost = GetRepairCost(health);
            if (repairCost > playerStats.GetMind())
            {
                Debug.Log("Repair failed");
                return;
            }
            health.DoRepair();
            playerStats.UpdateMind(-repairCost);
            return;
        }
    }