private void CalculateClosest() { //int unitsUpdatedThisFrame = 0; _attackers = Units.Concat <IDealDamage>(TowerMgr.Towers).ToList(); foreach (var attacker in _attackers) { if (attacker == null || attacker.GetHealth() <= 0) { continue; } if (attacker.TimeTillNextMgrUpdate > 0) { attacker.TimeTillNextMgrUpdate -= GameTime.DeltaTime; continue; } //unitsUpdatedThisFrame++; //DEBUG attacker.TimeTillNextMgrUpdate = UNIT_UPDATE_PERIOD_DELAY; //reset //Find closest non-spawner enemy ITakeDamage closestEnemy = null; float closestEnemyDistanceSquared = float.MaxValue; Vector3 ownPosition = attacker.transform.position; foreach (var other in Units) { //reasons to skip: looking at itself, not a valid unit, or on same team if (other == null || (IDealDamage)other == attacker || other.Team == attacker.Team || other.Health <= 0) { continue; } float testDistance = Vector3.SqrMagnitude(other.transform.position - ownPosition); if (testDistance < closestEnemyDistanceSquared) { closestEnemyDistanceSquared = testDistance; closestEnemy = other; //push to unit for AI calculations attacker.DistanceSquaredFromNearestEnemyUnit = closestEnemyDistanceSquared; } } foreach (var other in TowerMgr.Towers) { //reasons to skip: looking at itself, not a valid unit, or on same team if (other == null || (IDealDamage)other == attacker || other.Team == attacker.Team || other.Health <= 0) { continue; } float testDistance = Vector3.SqrMagnitude(other.transform.position - ownPosition); if (testDistance < closestEnemyDistanceSquared) { closestEnemyDistanceSquared = testDistance; closestEnemy = other; //push to unit for AI calculations attacker.DistanceSquaredFromNearestEnemyUnit = closestEnemyDistanceSquared; } } //get a more precise distance to current closest unit, taking into account its irregular/variable boundary if (closestEnemy != null && closestEnemyDistanceSquared < attacker.ReachSight * attacker.ReachSight * 2 * 2) { closestEnemyDistanceSquared = Vector3.SqrMagnitude( closestEnemy.transform.GetComponent <Collider>().ClosestPoint(ownPosition) - ownPosition); //push to unit for AI calculations attacker.DistanceSquaredFromNearestEnemyUnit = closestEnemyDistanceSquared; } //NOTE: null check when Unit goes to use attacker.ClosestNonSpawnerEnemy = closestEnemy; //Find closest spawners Spawner closestEnemySpawner = null; float closestEnemySpawnerDistanceSquared = float.MaxValue; Spawner closestTeamSpawner = null; float closestTeamSpawnerDistanceSquared = float.MaxValue; foreach (var s in LevelsMgr.CurrentLevel.Spawners) { if (s == null || s.Health <= 0) { continue; //if not valid, skip } float testDistance = Vector3.SqrMagnitude(s.transform.position - ownPosition); if (s.Team == attacker.Team) { if (testDistance < closestTeamSpawnerDistanceSquared) { closestTeamSpawnerDistanceSquared = testDistance; closestTeamSpawner = s; } } else { if (testDistance < closestEnemySpawnerDistanceSquared) { closestEnemySpawnerDistanceSquared = testDistance; closestEnemySpawner = s; } } } //if unit close to an enemy spawner, get a more precise distance to its irregular/variable boundary if (closestEnemySpawner != null && closestEnemySpawnerDistanceSquared < attacker.ReachSight * attacker.ReachSight * 2 * 2) { closestEnemySpawnerDistanceSquared = Vector3.SqrMagnitude( closestEnemySpawner.GetComponent <Collider>().ClosestPoint(ownPosition) - ownPosition); } //push to unit for AI calculations //NOTE: null checks when Unit goes to use attacker.ClosestEnemySpawner = closestEnemySpawner; attacker.ClosestTeamSpawner = closestTeamSpawner; attacker.DistanceSquaredFromNearestEnemySpawner = closestEnemySpawnerDistanceSquared; attacker.DistanceSquaredFromNearestVillage = closestTeamSpawnerDistanceSquared; } //NumberOfUnitUpdatesThisFrame = unitsUpdatedThisFrame; //DEBUG }
void Awake() { SampleHole = SampleHoleInspector; SampleTown = SampleTownInspector; LevelElementsInstance = GetComponent <LevelElements>(); }
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; } } }
public void SetRallyPoint(Vector3 point) { _rallyPoint = point; _rallyPointActive = true; TargetSpawner = null; }
public void SetAttack(Spawner enemy) { MentalState = MentalStates.Attacking; //SetUpWeapons(true, UnitWeapon.WeaponClasses.Ranged); TargetSpawner = enemy; }
private void WanderingLogic() { _opponent = null; _movementActive = true; _idleTimer -= GameTime.DeltaTime; if (_idleTimer > 0) { return; //skip logic till timer runs out } if (TEXT_DEBUG_ENABLED) { TestDebugOutput = "Idle | "; //DEBUG } //stow any weapons SetUpWeapon(false); if (ClosestTeamSpawner == null || ClosestTeamSpawner.Health <= 0) { return; //wander skip conditions } //if too far from home... float cutoffDistanceSquared = Mathf.Pow(Mathf.Sqrt(MAX_DIST_SQ_FROM_VILLAGE_DESIRED) + ClosestTeamSpawner.CurrentRadius, 2); if (_rallyPointActive) { if ((_rallyPoint - transform.position).sqrMagnitude < ReachMelee * ReachMelee * 2 * 2) //if "close enough" already... { _rallyPointActive = false; //turn off rallying } else //still heading there, eyes wide open (since this in the Idle state) { SpeedWalkReturnToBase = true; SetDestinationData(_rallyPoint); } } else //...no rallying, normal wandering logic... { if (DistanceSquaredFromNearestVillage > cutoffDistanceSquared) //if far from home (and Idle) { _idleTimer = 2; //check distance again in a little while SpeedWalkReturnToBase = true; SetDestinationData(ClosestTeamSpawner.transform.position); if (TEXT_DEBUG_ENABLED) { TestDebugOutput += ClosestTeamSpawner.gameObject.name + "dist: " + DistanceSquaredFromNearestVillage + "/" + cutoffDistanceSquared; //DEBUG } } else //...wander near home { _idleTimer = Random.Range(0, IDLE_PERIOD_MAX); //reset if (Spawner.FindASpot(transform.position, WANDER_RADIUS, Radius, out var wanderDestination)) { SpeedWalkReturnToBase = false; SetDestinationData(wanderDestination); if (TEXT_DEBUG_ENABLED) { TestDebugOutput += "Random"; //DEBUG } } } } }
protected override void OnAttach() { base.OnAttach(); window = ControlDeclarationManager.Instance.CreateControl("Gui\\TechLabUnitCustomizeWindow.gui"); Controls.Add(window); if (spawner == null) { spawner = Entities.Instance.GetByName("TechlabMechSpawn") as Spawner; } else { spawner = Entities.Instance.GetByName("TechlabMechSpawn") as Spawner; } if (camera == null) { camera = Entities.Instance.GetByName("TechlabCam") as MapCamera; } else { camera = Entities.Instance.GetByName("TechlabCam") as MapCamera; } //declare controls btnMechs = (Button)window.Controls["Mechs"]; btnMechs.Click += new Button.ClickDelegate(btnMechs_Click); btnGroundUnits = (Button)window.Controls["Gunit"]; btnGroundUnits.Click += new Button.ClickDelegate(btnGroundUnits_Click); btnAirUnits = (Button)window.Controls["Aunit"]; btnAirUnits.Click += new Button.ClickDelegate(btnAirUnits_Click); btnJets = (Button)window.Controls["Junit"]; btnJets.Click += new Button.ClickDelegate(btnJets_Click); btnNext = (Button)window.Controls["Next"]; btnNext.Click += new Button.ClickDelegate(btnNext_Click); btnPrevious = (Button)window.Controls["Previous"]; btnPrevious.Click += new Button.ClickDelegate(btnPrevious_Click); btnRA = (Button)window.Controls["RA"]; btnRA.Click += new Button.ClickDelegate(btnRA_Click); btnRT = (Button)window.Controls["RT"]; btnRT.Click += new Button.ClickDelegate(btnRT_Click); btnCT = (Button)window.Controls["CT"]; btnCT.Click += new Button.ClickDelegate(btnCT_Click); btnLT = (Button)window.Controls["LT"]; btnLT.Click += new Button.ClickDelegate(btnLT_Click); btnLA = (Button)window.Controls["LA"]; btnLA.Click += new Button.ClickDelegate(btnLA_Click); //iNCIN -- SlotList cbxWeaponSlots = (ListBox)window.Controls["SlotList"]; cbxWeaponSlots.SelectedIndexChange += new ListBox.SelectedIndexChangeDelegate(cbxWeaponSlots_SelectedIndexChange); cbxVariantList = (ListBox)window.Controls["VariantList"]; cbxVariantList.SelectedIndexChange += new ListBox.SelectedIndexChangeDelegate(cbxVariantList_SelectedIndexChange); lstWeaponList = (ListBox)window.Controls["WeaponList"]; lstWeaponList.SelectedIndexChange += new ListBox.SelectedIndexChangeDelegate(lstWeaponList_SelectedIndexChange); btnAddWeapon = (Button)window.Controls["AddWeapon"]; btnAddWeapon.Click += new Button.ClickDelegate(btnAddWeapon_Click); txtWeaponInfo = (EditBox)window.Controls["WeaponInfo"]; txtCash = (TextBox)window.Controls["Cash"]; btnSaveVariant = (Button)window.Controls["SaveCustomUnit"]; btnSaveVariant.Click += new Button.ClickDelegate(btnSaveVariant_Click); btnExit = (Button)window.Controls["Quit"]; btnExit.Click += new Button.ClickDelegate(btnExit_Click); txtUnitName = (TextBox)window.Controls["UnitName"]; MechsPriceList = (PriceListC)Entities.Instance.Create("MechPriceList", Map.Instance); AunitPriceList = (PriceListC)Entities.Instance.Create("AunitPriceList", Map.Instance); GunitPriceList = (PriceListC)Entities.Instance.Create("GunitPriceList", Map.Instance); JunitPriceList = (PriceListC)Entities.Instance.Create("JunitPriceList", Map.Instance); GetListOfPlayerUnits(); cash = GetPlayerCashSQL(); if (MechDBUnits.Count == 0) { btnMechs.Enable = false; } if (ADBUnits.Count == 0) { btnAirUnits.Enable = false; } if (GDBUnits.Count == 0) { btnGroundUnits.Enable = false; } if (JDBUnits.Count == 0) { btnJets.Enable = false; } if (MechDBUnits.Count == 0 || ADBUnits.Count == 0 || GDBUnits.Count == 0 || JDBUnits.Count == 0) { //player has not bought any units Log.Info("No units purchased. TODO: ask user if they want to go to buy window"); } InitCameraViewFromTarget(); //positionY = maxout; spawner.UnitSpawned += new Spawner.OnUnitSpawned(spawner_UnitSpawned); }
protected override void OnAttach() { window = ControlDeclarationManager.Instance.CreateControl("Gui\\TechLabUnitBuyWindow.gui"); Controls.Add(window); if (spawner == null) { spawner = Entities.Instance.GetByName("TechlabMechSpawn") as Spawner; } else { spawner = Entities.Instance.GetByName("TechlabMechSpawn") as Spawner; } if (camera == null) { camera = Entities.Instance.GetByName("TechlabCam") as MapCamera; } else { camera = Entities.Instance.GetByName("TechlabCam") as MapCamera; } btnMechs = (Button)window.Controls["Mechs"]; btnMechs.Click += new Button.ClickDelegate(btnMechs_Click); btnGroundUnits = (Button)window.Controls["Gunit"]; btnGroundUnits.Click += new Button.ClickDelegate(btnGroundUnits_Click); btnAirUnits = (Button)window.Controls["Aunit"]; btnAirUnits.Click += new Button.ClickDelegate(btnAirUnits_Click); btnJets = (Button)window.Controls["Junit"]; btnJets.Click += new Button.ClickDelegate(btnJets_Click); btnExit = (Button)window.Controls["Quit"]; btnExit.Click += new Button.ClickDelegate(btnExit_Click); btnNext = (Button)window.Controls["Next"]; btnNext.Click += new Button.ClickDelegate(btnNext_Click); btnPrevious = (Button)window.Controls["Previous"]; btnPrevious.Click += new Button.ClickDelegate(btnPrevious_Click); btnBuy = (Button)window.Controls["Buy"]; btnBuy.Click += new Button.ClickDelegate(btnBuy_Click); txtUnitName = (TextBox)window.Controls["UnitName"]; txtUnitCost = (TextBox)window.Controls["UnitCost"]; txtCash = (TextBox)window.Controls["Cash"]; txtCash.Text = "Cash: " + cash.ToString(); lstWeapons = (ListBox)window.Controls["Weapons"]; spawner.UnitSpawned += new Spawner.OnUnitSpawned(spawner_UnitSpawned); InitCameraViewFromTarget(); //positionY = maxout; MechsPriceList = (PriceListC)Entities.Instance.Create("MechPriceList", Map.Instance); AunitPriceList = (PriceListC)Entities.Instance.Create("AunitPriceList", Map.Instance); GunitPriceList = (PriceListC)Entities.Instance.Create("GunitPriceList", Map.Instance); JunitPriceList = (PriceListC)Entities.Instance.Create("JunitPriceList", Map.Instance); GetListOfPlayerUnits(); cash = GetPlayerCashSQL(); base.OnAttach(); }