Example #1
0
        public static bool FindASpot(Vector3 centerStartPos, float radiusToPlace, float radiusCircleToFitObjectOn,
                                     out Vector3 resultingPos)
        {
            bool locationFound = false;

            resultingPos = centerStartPos; //default
            for (int attemptCount = 0; attemptCount < Level.PLACEMENT_ATTEMPTS; attemptCount++)
            {
                //find a random spot
                Vector2 spotOnACircle = Random.insideUnitCircle.normalized;
                if (spotOnACircle == Vector2.zero)
                {
                    //edge possibility, probably so rare it "impossible" but saw a hole at dead center once...
                    spotOnACircle = Vector2.one * radiusToPlace;
                }

                Vector2 randomSpot      = spotOnACircle * (radiusToPlace);
                Vector3 prospectiveSpot = new Vector3(randomSpot.x, 0, randomSpot.y) + centerStartPos;

                if (Level.GetIfSpotFree(prospectiveSpot, radiusCircleToFitObjectOn, out RaycastHit landHit))
                {
                    if (Level.GetIfSpotOnNavMesh(landHit.point))
                    {
                        locationFound = true;
                        resultingPos  = landHit.point;
                        //Debug.DrawLine(centerStartPos, prospectiveSpot, Color.green, 3.0f);
                        break;
                    }
                }

                //Debug.DrawLine(centerStartPos, prospectiveSpot, Color.red, 1.5f);
            }

            return(locationFound);
        }
Example #2
0
        void Update() //TODO: move this to user controls somewhere at some point, would really make more sense hah
        {
            //DEBUG
            if (Input.GetKeyDown(KeyCode.Plus) || Input.GetKeyDown(KeyCode.Equals)) //win
            {
                CurrentLevel.DebugKillOffSpawners(Teams.Baddies);
            }
            if (Input.GetKeyDown(KeyCode.Minus)) //lose
            {
                CurrentLevel.DebugKillOffSpawners(Teams.Townsfolk);
            }

            if (Input.GetKey("escape"))
            {
                Application.Quit();
            }

            if (Input.GetKeyDown(KeyCode.V))                           //Deselect All Units
            {
                UnitMgr.GatheredUnits.RemoveAll(item => item == null); //https://stackoverflow.com/questions/3069431/listobject-removeall-how-to-create-an-appropriate-predicate
                foreach (var u in UnitMgr.GatheredUnits)
                {
                    //if (u == null) continue;
                    u.SelectionRing?.gameObject.SetActive(false);
                }
                UnitMgr.GatheredUnits.Clear();
            }

            if (Input.GetKeyDown(KeyCode.C)) //Collect All Units
            {
                foreach (var u in UnitMgr.Units)
                {
                    if (u == null || u.Team != Teams.Townsfolk)
                    {
                        continue;
                    }
                    u.SelectionRing?.gameObject.SetActive(true);
                    UnitMgr.GatheredUnits.Add(u);
                }
            }

            if (Input.GetKeyDown(KeyCode.G)) //Gather Units
            {
                foreach (var u in UnitMgr.Units)
                {
                    if (u == null || u.Team != Teams.Townsfolk)
                    {
                        continue;
                    }
                    if (!((u.transform.position - PlayerUser.PlayerObject.transform.position).sqrMagnitude <
                          UnitMgr.UNIT_GATHER_RADIUS_SQUARED))
                    {
                        continue;
                    }
                    u.SelectionRing?.gameObject.SetActive(true);
                    UnitMgr.GatheredUnits.Add(u);
                }
            }

            if (Input.GetKeyDown(KeyCode.T)) //gathered villagers attack enemy Hole closest to you the user
            {
                //Find closest spawner to player
                Spawner closestHoleSpawner = null;
                float   closestBaddySpawnerDistanceSquared = float.MaxValue;
                foreach (var s in LevelsMgr.CurrentLevel.Spawners)
                {
                    if (s == null)
                    {
                        continue;
                    }
                    float testDistance =
                        Vector3.SqrMagnitude(s.transform.position - PlayerUser.PlayerObject.transform.position);
                    if (s.Team == Teams.Baddies &&
                        testDistance < closestBaddySpawnerDistanceSquared)
                    {
                        closestBaddySpawnerDistanceSquared = testDistance;
                        closestHoleSpawner = s;
                    }
                }

                UnitMgr.GatheredUnits.RemoveAll(item => item == null); //https://stackoverflow.com/questions/3069431/listobject-removeall-how-to-create-an-appropriate-predicate
                foreach (var u in UnitMgr.GatheredUnits)
                {
                    //if (u == null) continue;
                    if (u.Team == Teams.Townsfolk)
                    {
                        u.SelectionRing?.gameObject.SetActive(false);
                        u.SetAttack(closestHoleSpawner);
                    }
                }
                UnitMgr.GatheredUnits.Clear();

                if (closestHoleSpawner != null)
                {
                    PlayerUser.VisualUnitsTargetArrow.GetComponent <ObjectColor>()?.SetOriginalColor(Color.red);
                    PlayerUser.VisualUnitsTargetArrow.SetTarget(PlayerUser.PlayerObject.transform.position,
                                                                closestHoleSpawner.transform.position, 3f);
                }
            }

            if (Input.GetKeyDown(KeyCode.P)) //gathered villagers protect the rally point of your position
            {
                //TODO: make this dependent on mode to select the point (user might be top-down)

                UnitMgr.GatheredUnits.RemoveAll(item => item == null); //https://stackoverflow.com/questions/3069431/listobject-removeall-how-to-create-an-appropriate-predicate
                foreach (var u in UnitMgr.GatheredUnits)
                {
                    //if (u == null) continue;
                    if (u.Team == Teams.Townsfolk)
                    {
                        u.SelectionRing?.gameObject.SetActive(false);
                        u.SetRallyPoint(PlayerUser.PlayerObject.transform.position);
                    }
                }
                UnitMgr.GatheredUnits.Clear();
            }

            if (Input.GetKeyDown(KeyCode.M)) //show or hide menu
            {
                _menuActive = !_menuActive && CurrentLevel != Level.LobbyLevel;
                MenuInGameObject?.GetComponent <MenuInGame>().Show(_menuActive);
            }


            if (Input.GetKeyDown(KeyCode.Y)) //grab a tower for placement mode
            {
                if (!_towerPlacementMode)
                {
                    _towerToBePlaced = TowerMgr.PickATower(Teams.Townsfolk, TowerTypes.Round);
                }
                _towerPlacementMode = true;
            }

            if (Input.GetKeyUp(KeyCode.Y)) //place the tower
            {
                if (_towerPlacementMode)
                {
                    if (_towerPlacementOk)
                    {
                        _towerToBePlaced?.SetDownActivate();
                        PlayerUser.ResourceUnits -= TowerMgr.TOWER_RESOURCE_COST;
                    }
                    else
                    {
                        Destroy(_towerToBePlaced.gameObject);
                    }

                    _towerToBePlaced    = null; //release handle
                    _towerPlacementMode = false;
                    PlayerUser.VisualNewTowerDistanceArrow?.ClearTarget();
                    TowerMgr.ExplanationText.text = "";
                }
            }

            if (_towerPlacementMode)
            {
                _towerPlacementOk             = false;
                TowerMgr.ExplanationText.text = "";

                //raycast from cursor, get nearest grid spot on Level
                if (_cam == null)
                {
                    _cam = FindObjectOfType <Camera>();
                }

                Ray ray = _cam.ScreenPointToRay(Input.mousePosition);

                if (Physics.Raycast(ray, out RaycastHit hit))
                {
                    //check distances
                    bool closeEnoughToPlayer = (hit.point - _cam.transform.position).magnitude <
                                               TowerMgr.TOWER_PLACEMENT_DISTANCE;
                    Spawner nearestSpawner = GetClosestMatchingSpawner(hit.point);
                    if (nearestSpawner != null)
                    {
                        float distanceSquaredToNearestMatchingSpawner =
                            (nearestSpawner.transform.position - hit.point).sqrMagnitude;
                        bool closeEnoughToAVillage =
                            distanceSquaredToNearestMatchingSpawner <
                            (TowerMgr.TOWER_PLACEMENT_DISTANCE + _towerToBePlaced.Radius) *
                            (TowerMgr.TOWER_PLACEMENT_DISTANCE + _towerToBePlaced.Radius);
                        bool leavesEnoughGrowthRoomForAVillage =
                            distanceSquaredToNearestMatchingSpawner >
                            (Level.SPAWN_LAND_FIT_RADIUS + _towerToBePlaced.Radius) *
                            (Level.SPAWN_LAND_FIT_RADIUS + _towerToBePlaced.Radius);
                        bool enoughResources      = PlayerUser.ResourceUnits >= TowerMgr.TOWER_RESOURCE_COST;
                        bool accessibleViaNavMesh = Level.GetIfSpotOnNavMesh(hit.point, 0.25f);


                        if (closeEnoughToPlayer && closeEnoughToAVillage && leavesEnoughGrowthRoomForAVillage &&
                            enoughResources && accessibleViaNavMesh)
                        {
                            //sphere-cast to ensure clear for placement
                            if (Level.GetIfSpotFree(hit.point, _towerToBePlaced.Radius, out RaycastHit landHit))
                            {
                                //if clear, move to new temporary grid location
                                _towerToBePlaced.transform.position = landHit.point;
                                _towerPlacementOk = true;
                            }
                            else
                            {
                                TowerMgr.ExplanationText.text = "Spot not clear!\n";
                            }
                        }
                        else
                        {
                            TowerMgr.ExplanationText.text = (closeEnoughToPlayer ? "" : "Too far from you!\n") +
                                                            (closeEnoughToAVillage
                                                                ? ""
                                                                : "Too far from village!\n") +
                                                            (leavesEnoughGrowthRoomForAVillage
                                                                ? ""
                                                                : ("Too close to village!\n")) +
                                                            (enoughResources
                                                                ? ""
                                                                : "Need " + TowerMgr.TOWER_RESOURCE_COST +
                                                             " resources!\n") +
                                                            (accessibleViaNavMesh ? "" : "Units can't reach!\n");
                        }

                        //show distance reach visual (i.e. arrow)
                        PlayerUser.VisualNewTowerDistanceArrow?.SetTarget(hit.point, nearestSpawner.transform.position);
                        PlayerUser.VisualNewTowerDistanceArrow?.GetComponent <ObjectColor>()
                        ?.SetColor(_towerPlacementOk ? Color.white : Color.red);
                        TowerMgr.ExplanationText.transform.position = hit.point + Vector3.up * 2f;
                    }
                }

                //adjust temporary tower visuals
                if (_towerToBePlaced != null)
                {
                    _towerToBePlaced?.GetComponent <ObjectColor>()?.SetColor(_towerPlacementOk ? Color.white : Color.red);
                    _towerToBePlaced.GetComponent <Renderer>().enabled = _towerPlacementOk;
                }
            }
        }