//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called every frame. Scales down the unit's transform if its dead & // Despawn when finished. /// </summary> private void UpdateDeathShrinker() { // Check if the unit should be shrinking if (_StartShrinking && !IsAlive() && ShrinkWhenDestroyed) { // Get in the cold ass water transform.localScale -= Vector3.one * ShrinkSpeed * Time.deltaTime; if (transform.localScale.x < 0.01f) { // Deselect / De-highlight if (_Player) { _Player.RemoveFromSelection(this); } SetIsHighlighted(false); SetIsSelected(false); // MAXIMUM shrinkage _StartShrinking = false; // This is so that the next time the object is spawned - it is at its default state already _ObjectState = WorldObjectStates.Default; // Despawn the object transform.localScale = new Vector3(1f, 1f, 1f); ObjectPooling.Despawn(gameObject); } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called each frame. /// </summary> private void Update() { if (_UnitAttached != null && _CameraAttached != null) { // Unit is alive - display the widget if (_UnitAttached.IsInWorld() && _UnitAttached.GetVeterancyLevel() > 0) { // Update text _TextComponent.text = _UnitAttached.GetVeterancyLevel().ToString(); // Set world space position Vector3 pos = _UnitAttached.transform.position + Offsetting; pos.y = pos.y + _UnitAttached.GetObjectHeight(); transform.position = pos; // Constantly face the widget towards the camera transform.LookAt(2 * transform.position - _CameraAttached.transform.position); } // Object is dead/destroyed else { ObjectPooling.Despawn(gameObject); } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called each frame. /// </summary> private void Update() { if (_WorldObject != null && _CameraAttached != null) { // Only show widget if the object is currently being built (or in queue) if (_WorldObject.GetObjectState() == Abstraction.WorldObjectStates.Building || _WorldObject.GetObjectState() == Abstraction.WorldObjectStates.InQueue) { // Update text to show how much time is remaining in the build int time = (int)_WorldObject.GetCurrentBuildTimeRemaining(); string healthString = time.ToString(); _TextComponent.text = healthString; // Set world space position Vector3 pos = _WorldObject.transform.position + Offsetting; pos.y = pos.y + _WorldObject.GetObjectHeight(); transform.position = pos; // Constantly face the widget towards the camera transform.LookAt(2 * transform.position - _CameraAttached.transform.position); } // Destroy prefab instance as we no longer need it anymore else { ObjectPooling.Despawn(this.gameObject); } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // /// </summary> /// <returns> // IEnumerator /// </returns> private IEnumerator DelayedExplosion() { // Delay float normalizedTime = 0f; while (normalizedTime <= 1f) { normalizedTime += Time.deltaTime / CannisterLeakTime; yield return(null); } // Stop leaking & explode if (_CannisterLeakEffect != null) { _CannisterLeakEffect.Stop(); } ExplosionEffectStencil = ObjectPooling.Spawn(ExplosionEffectStencil.gameObject, ExplosionEffectTransform.position, ExplosionEffectTransform.rotation).GetComponent <ParticleSystem>(); ExplosionEffectStencil.Play(); // Camera shake if (_Player == null) { _Player = GameManager.Instance.Players[0]; } if (_Player != null) { _Player.CameraRTS.ExplosionShake(ExplosionEffectTransform.position, ExplosionRadius); } // Hide/despawn the unit _ObjectState = WorldObjectStates.Default; ObjectPooling.Despawn(gameObject); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called each frame. /// </summary> private void Update() { if (_Upgrade != null && _CameraAttached != null) { // Only show widget if the upgrade is currently being built if (_Upgrade.IsUpgrading()) { // Update text to show how much time is remaining in the build int time = (int)_Upgrade.UpgradeTimeRemaining(); string healthString = time.ToString(); _TextComponent.text = healthString; // Set world space position Vector3 pos = _Upgrade.GetBuildingAttached().transform.position + Offsetting; pos.y = pos.y + _Upgrade.GetBuildingAttached().GetObjectHeight(); transform.position = pos; // Constantly face the widget towards the camera transform.LookAt(2 * transform.position - _CameraAttached.transform.position); } // Destroy prefab instance as we no longer need it anymore else { ObjectPooling.Despawn(this.gameObject); } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // A coroutine that waits for the seconds specified then attempts to repool // the particle effect (or destroyed entirely if re-pooling isn't possible) /// </summary> /// <param name="particleEffect"></param> /// <param name="delay"></param> IEnumerator ParticleDespawn(ParticleSystem particleEffect, float delay) { // Delay yield return(new WaitForSeconds(delay)); // Despawn the system ObjectPooling.Despawn(particleEffect.gameObject); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // A coroutine that waits for the seconds specified then attempts to repool // the particle effect (or destroyed entirely if re-pooling isn't possible) /// </summary> /// <param name="particleEffect"></param> /// <param name="delay"></param> public IEnumerator ParticleParentDespawn(ParticleSystem particleEffect, float delay) { // Delay ///yield return new WaitForSeconds(delay); yield return(new WaitUntil(() => !particleEffect.isPlaying)); // Despawn the system ObjectPooling.Despawn(particleEffect.transform.parent.gameObject); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called when the unit 'dies'. /// </summary> public override void OnDeath(WorldObject instigator) { base.OnDeath(instigator); // Stop the engine sound if (_EngineSound != null) { ObjectPooling.Despawn(_EngineSound.gameObject); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called when the player presses a button on the selection wheel with this world object // linked to the button. /// </summary> /// <param name="buildingSlot"> // The building slot that instigated the selection wheel. // (EG: If you're making a building, this is the building slot thats being used.) /// </param> public override void OnWheelSelect(BuildingSlot buildingSlot) { // Gets reference to the original turret (before the upgrade) BaseTurret originalTurret = null; if (buildingSlot != null) { if (buildingSlot.GetBuildingOnSlot() != null) { originalTurret = buildingSlot.GetBuildingOnSlot().GetComponent <BaseTurret>(); } } // Remove old healthbar (if valid) float hitpoints = MaxHitPoints; if (originalTurret != null) { hitpoints = originalTurret.GetHitPoints(); if (originalTurret._HealthBar != null) { ObjectPooling.Despawn(originalTurret._HealthBar.gameObject); } } // Create weapon if (_TowerWeapon != null) { _TowerWeapon = ObjectPooling.Spawn(_TowerWeapon.gameObject).GetComponent <Weapon>(); } // Start building process base.OnWheelSelect(buildingSlot); if (_ClonedWorldObject != null) { // Only proceed if there was a previous building & we're upgrading from that if (originalTurret != null) { // Update player ref _ClonedWorldObject.SetPlayer(originalTurret._Player); // Set the new base's building state object to be the currently active object _ClonedWorldObject.BuildingState = originalTurret.gameObject; } // Update attached building slot turret reference if (buildingSlot != null) { buildingSlot.SetBuildingOnSlot(_ClonedWorldObject.GetComponent <BaseTurret>()); } // Reset turret's health _ClonedWorldObject.SetHitPoints(_ClonedWorldObject.MaxHitPoints); } }
//****************************************************************************************************************************** // // FUNCTIONS // //****************************************************************************************************************************** //////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // A coroutine that waits a few seconds before despawning the sound gameobject reference /// </summary> /// <returns></returns> private IEnumerator DestroySound(AudioSource sound, float delayTime) { // Delay float normalizedTime = 0f; while (normalizedTime <= 1f) { normalizedTime += Time.deltaTime / delayTime; yield return(null); } // Despawn ObjectPooling.Despawn(sound.gameObject); }
//****************************************************************************************************************************** // // FUNCTIONS // //****************************************************************************************************************************** //////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called when the player presses a button on the selection wheel with this world object // linked to the button. /// </summary> /// <param name="buildingSlot"> // The building slot that instigated the selection wheel. // (EG: If you're making a building, this is the building slot thats being used.) /// </param> public override void OnWheelSelect(BuildingSlot buildingSlot) { // Gets reference to the original generator (before the upgrade) Generator originalGenerator = null; if (buildingSlot != null) { if (buildingSlot.GetBuildingOnSlot() != null) { originalGenerator = buildingSlot.GetBuildingOnSlot().GetComponent <Generator>(); } } // Remove old healthbar (if valid) float hitpoints = MaxHitPoints; if (originalGenerator != null) { hitpoints = originalGenerator.GetHitPoints(); if (originalGenerator._HealthBar != null) { ObjectPooling.Despawn(originalGenerator._HealthBar.gameObject); } } // Start building process base.OnWheelSelect(buildingSlot); if (_ClonedWorldObject != null) { // Only proceed if there was a previous building and we are upgrading from that if (originalGenerator != null) { // Update player ref _ClonedWorldObject.SetPlayer(originalGenerator._Player); // Set the new bases building state object to be the currently active object _ClonedWorldObject.BuildingState = originalGenerator.gameObject; } // Update attached buildingSlot generator reference if (buildingSlot != null) { buildingSlot.SetBuildingOnSlot(_ClonedWorldObject.GetComponent <Generator>()); } // Reset building's health _ClonedWorldObject.SetHitPoints(_ClonedWorldObject.MaxHitPoints); } }
//****************************************************************************************************************************** // // FUNCTIONS // //****************************************************************************************************************************** //////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called each frame. /// </summary> private void Update() { if (_ParticleSystem != null) { // Wait until the particle has finished its cycle (for force to stop) if (!_ParticleSystem.IsAlive() || _DespawnNow) { // Despawn ObjectPooling.Despawn(gameObject); } } // Get reference to the particle system else { _ParticleSystem = GetComponent <ParticleSystem>(); if (_ParticleSystem == null) { _ParticleSystem = GetComponentInChildren <ParticleSystem>(); } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called when the object is killed/destroyed /// </summary> public virtual void OnDeath(WorldObject instigator) { // Force deselect SetIsSelected(false); // Set object state _ObjectState = WorldObjectStates.Destroyed; // Destroy healthbar if (_HealthBar != null) { // Null the bitch _HealthBar.SetObjectAttached(null); ObjectPooling.Despawn(_HealthBar.gameObject); } // Clamping health _HitPoints = 0; _Health = 0f; // Play OnDeath effect if (OnDeathEffect != null) { // Play ParticleSystem effect = ObjectPooling.Spawn(OnDeathEffect.gameObject, transform.position, transform.rotation).GetComponent <ParticleSystem>(); effect.Play(); // Despawn particle system once it has finished its cycle float effectDuration = effect.duration + effect.startLifetime; StartCoroutine(ParticleDespawn(effect, effectDuration)); } // Send message to match feed MatchFeed.Instance.AddMessage(string.Concat(ObjectName, " destroyed.")); // Delay then despawn StartCoroutine(DelayedShrinking(3f)); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Update the current showcase object reference. /// </summary> /// <param name="button"></param> public void ChangeSelection(Button button) { // Get button reference component ShowcaseButtonRef btnref = button.gameObject.GetComponent <ShowcaseButtonRef>(); // Update showcase object reference if (btnref != null && _CurrentShowcaseObject != null) { // Destroy old showcase object ObjectPooling.Despawn(_CurrentShowcaseObject.gameObject); // Reset showcase transform if (StartingShowcaseTransform != null) { _ShowcasePosition = StartingShowcaseTransform.position; } if (StartingShowcaseTransform != null) { _ShowcaseRotation = StartingShowcaseTransform.rotation; } // Create new showcase object Selectable select = btnref.ObjectReference; GameObject gObj = ObjectPooling.Spawn(select.gameObject, _ShowcasePosition, _ShowcaseRotation); _CurrentShowcaseObject = gObj.GetComponent <Selectable>(); _CurrentShowcaseObject._ObjectState = Abstraction.WorldObjectStates.Active; (_CurrentShowcaseObject as WorldObject).SetShowHealthBar(false); // Add offset to the showcase position _ShowcasePosition.y += _CurrentShowcaseObject.ShowcaseOffsetY; // Update camera properties if (ShowcaseRenderCamera != null) { ShowcaseRenderCamera.fieldOfView = _CurrentShowcaseObject.ShowcaseFOV; } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called when this object is created. /// </summary> protected override void Start() { base.Start(); if (_PotentialTargets == null) { _PotentialTargets = new List <WorldObject>(); } else { _PotentialTargets.Clear(); } // Create copy of its weaopn & re-assign it to replace the old reference if (_TowerWeapon != null) { ObjectPooling.Despawn(_TowerWeapon.gameObject); } if (TowerWeapon != null) { _TowerWeapon = ObjectPooling.Spawn(TowerWeapon.gameObject, Vector3.zero, Quaternion.identity).GetComponent <Weapon>(); _TowerWeapon.SetTowerAttached(this); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // /// </summary> /// <param name="buildingSlot"></param> public override void StartBuildingObject(BuildingSlot buildingSlot) { base.StartBuildingObject(); float hitpoints = MaxHitPoints; // Only proceed if there was a previous building and we are upgrading from that if (_ClonedWorldObject != null) { Base newBase = _ClonedWorldObject.GetComponent <Base>(); if (newBase._PreviousBase != null) { // Dont allow upgrading stacks if (!newBase._PreviousBase._UpgradingBase) { // Remove old healthbar (if valid) hitpoints = _PreviousBase._HitPoints; if (newBase._PreviousBase._HealthBar != null) { ObjectPooling.Despawn(newBase._PreviousBase._HealthBar.gameObject); } // Update player ref _ClonedWorldObject._Player = newBase._PreviousBase._Player; // Set the new bases queued/building state object to be the currently active base _ClonedWorldObject.InQueueState = newBase._PreviousBase.gameObject; _ClonedWorldObject.BuildingState = newBase._PreviousBase.gameObject; // Get references to all the buildings that were in the previous base & allocate them to the new one // Depot/Generator slots for (int i = 0; i < newBase.DepotSlots.Count; i++) { // Only go as far as the previous bases slot size if (i < newBase._PreviousBase.DepotSlots.Count) { // Reallocate building to new base (if there is one) if (newBase._PreviousBase.DepotSlots[i] != null) { // Send building to new base if (newBase._PreviousBase.DepotSlots[i].GetBuildingOnSlot() != null) { newBase._PreviousBase.DepotSlots[i].GetBuildingOnSlot().AttachedBuildingSlot = newBase.DepotSlots[i]; newBase.DepotSlots[i].SetBuildingOnSlot(newBase._PreviousBase.DepotSlots[i].GetBuildingOnSlot()); newBase._PreviousBase.DepotSlots[i].SetBuildingOnSlot(null); } } else { continue; } } else { break; } } // Tower slots for (int i = 0; i < newBase.TowerSlots.Count; i++) { // Only go as far as the previous bases slot size if (i < newBase._PreviousBase.TowerSlots.Count) { // Reallocate tower to new base (if there is one) if (newBase._PreviousBase.TowerSlots[i] != null) { // Send tower to new base if (newBase._PreviousBase.TowerSlots[i].GetBuildingOnSlot() != null) { newBase._PreviousBase.TowerSlots[i].GetBuildingOnSlot().AttachedBuildingSlot = newBase.TowerSlots[i]; newBase.TowerSlots[i].SetBuildingOnSlot(newBase._PreviousBase.TowerSlots[i].GetBuildingOnSlot()); newBase._PreviousBase.TowerSlots[i].SetBuildingOnSlot(null); } } else { continue; } } else { break; } } } } // Update attached base reference if (buildingSlot != null) { buildingSlot.AttachedBase = _ClonedWorldObject.GetComponent <Base>(); } // Update new bases health with the old bases health _ClonedWorldObject.SetHitPoints(hitpoints); } }
//****************************************************************************************************************************** // // FUNCTIONS // //****************************************************************************************************************************** //////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called each frame. /// </summary> private void Update() { if (_WorldObject != null && _CameraAttached != null) { // Display text if the object is a building if (_BuildingAttached != null) { _TextComponent.text = _WorldObject.ObjectName; // Only show the building name if it is built & active in the game world if (_WorldObject.GetObjectState() == Abstraction.WorldObjectStates.Active) { _TextComponent.enabled = true; } else { _TextComponent.enabled = false; } } // Don't show the text component if the object is NOT a building else { _TextComponent.enabled = false; } // Update health bar if (HealthSlider != null) { HealthSlider.value = _WorldObject.GetHealth(); } // Update shield bar if (ShieldSlider != null) { // Show the shield bar if theres some shield left if (_WorldObject.GetShieldPoints() > 0) { ShieldSlider.value = _WorldObject.GetShield(); ShieldSlider.gameObject.SetActive(true); } // Hide the shield else { ShieldSlider.gameObject.SetActive(false); } } // Object is alive - display the widget if (_WorldObject.IsInWorld()) { // Set world space position Vector3 pos = _WorldObject.transform.position + Offsetting; pos.y = pos.y + _WorldObject.GetObjectHeight(); transform.position = pos; // Constantly face the widget towards the camera transform.LookAt(2 * transform.position - _CameraAttached.transform.position); } // Object is dead/destroyed else { ObjectPooling.Despawn(gameObject); } // Update team colour UpdateTeamColourFill(); } }
//****************************************************************************************************************************** // // FUNCTIONS // //****************************************************************************************************************************** //////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called when the object is killed/destroyed /// </summary> public override void OnDeath(WorldObject instigator) { // Determine whether the character should explode or not float xplode = Random.Range(0f, 1f); if (xplode <= ExplodeOnDeathChance) { _Agent.enabled = false; // Cannister leak then explode _CannisterLeakEffect = ObjectPooling.Spawn(CannisterLeakStencil.gameObject, CannisterLeakTransform.position, CannisterLeakTransform.rotation).GetComponent <ParticleSystem>(); _CannisterLeakEffect.Play(); StartCoroutine(DelayedExplosion()); // If were in the wave manager's enemies array - remove it if (WaveManager.Instance.GetCurrentWaveEnemies().Contains(this)) { WaveManager.Instance.GetCurrentWaveEnemies().Remove(this); } if (Team == GameManager.Team.Attacking) { GameManager.Instance.WaveStatsHUD.DeductLifeFromCurrentPopulation(); } // Remove from player's population counter else if (Team == GameManager.Team.Defending) { _Player.RemoveFromArmy(this); } // Destroy waypoint if (_SeekWaypoint != null) { ObjectPooling.Despawn(_SeekWaypoint.gameObject); } // Add xp to the instigator (if valid) if (instigator != null) { // Only units can gain XP from kills Unit unit = instigator.GetComponent <Unit>(); if (unit != null) { unit.AddVeterancyXP(XPGrantedOnDeath); } } // Force deselect SetIsSelected(false); // Despawn any damaged threshold particles in play for (int i = 0; i < _DamagedParticles.Count; i++) { ParticleSystem effect = _DamagedParticles[i]; effect.Stop(true); ObjectPooling.Despawn(effect.gameObject); } if (_DamagedParticles.Count > 0) { _DamagedParticles.Clear(); } // Set object state _ObjectState = WorldObjectStates.Destroyed; // Destroy healthbar if (_HealthBar != null) { // Null the bitch _HealthBar.SetObjectAttached(null); ObjectPooling.Despawn(_HealthBar.gameObject); } // Clamping health _HitPoints = 0; _Health = 0f; // Camera shake if neccessary if (_Player == null) { _Player = GameManager.Instance.Players[0]; } if (CameraShakeOnDeath && _Player != null) { _Player.CameraRTS.ExplosionShake(transform.position, DeathExplosionRadius); } // Send message to match feed if (Team == GameManager.Team.Defending) { MatchFeed.Instance.AddMessage(string.Concat(ObjectName, " has been killed.")); _Player.AddUnitsLost(); } // Add to enemies killed stats else if (Team == GameManager.Team.Attacking) { _Player.AddUnitsKilled(); } } // Die normally else { base.OnDeath(instigator); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called each frame. /// </summary> protected override void Update() { base.Update(); switch (_ObjectState) { case WorldObjectStates.Default: { // Hide meshes if (InQueueState) { InQueueState.SetActive(false); } if (BuildingState) { BuildingState.SetActive(false); } if (ActiveState) { ActiveState.SetActive(false); } if (DestroyedState) { DestroyedState.SetActive(false); } // Hide fog of war if (_FogOfWarSight != null) { _FogOfWarSight.enabled = false; } break; } case WorldObjectStates.InQueue: { // Show inqueue state object if (BuildingState) { BuildingState.SetActive(false); } if (InQueueState) { InQueueState.SetActive(true); } if (ActiveState) { ActiveState.SetActive(false); } if (DestroyedState) { DestroyedState.SetActive(false); } // Hide fog of war if (_FogOfWarSight != null) { _FogOfWarSight.enabled = false; } break; } case WorldObjectStates.Building: { // Show building state object if (InQueueState) { InQueueState.SetActive(false); } if (BuildingState) { BuildingState.SetActive(true); } if (ActiveState) { ActiveState.SetActive(false); } if (DestroyedState) { DestroyedState.SetActive(false); } // Is unit building complete? if (SceneManager.GetSceneByName("TutorialScene") == SceneManager.GetActiveScene()) { _ReadyForDeployment = _CurrentBuildTime >= BuildingTimeTutorial; } else { _ReadyForDeployment = _CurrentBuildTime >= BuildingTime; } if (!_ReadyForDeployment) { // Add to building timer if (SceneManager.GetSceneByName("TutorialScene") == SceneManager.GetActiveScene()) { if (_CurrentBuildTime < BuildingTimeTutorial) { _CurrentBuildTime += Time.deltaTime; } } else { if (_CurrentBuildTime < BuildingTime) { _CurrentBuildTime += Time.deltaTime; } } } else { // Object has finished building OnBuilt(); _ObjectState = WorldObjectStates.Deployable; } // Hide fog of war if (_FogOfWarSight != null) { _FogOfWarSight.enabled = false; } break; } case WorldObjectStates.Deployable: { break; } case WorldObjectStates.Active: { // Show active state object if (InQueueState) { InQueueState.SetActive(false); } if (BuildingState) { BuildingState.SetActive(false); } if (ActiveState) { ActiveState.SetActive(true); } if (DestroyedState) { DestroyedState.SetActive(false); } // Show fog of war if (_FogOfWarSight != null) { _FogOfWarSight.enabled = true; } break; } case WorldObjectStates.Destroyed: { // Show destroyed state object if (InQueueState) { InQueueState.SetActive(false); } if (BuildingState) { BuildingState.SetActive(false); } if (ActiveState) { ActiveState.SetActive(false); } if (DestroyedState) { DestroyedState.SetActive(true); } // Hide fog of war if (_FogOfWarSight != null) { _FogOfWarSight.enabled = false; } break; } default: break; } // Update shield to be a normalized range of the object's shield-points if (_ShieldPoints > 0) { _Shield = _ShieldPoints / MaxShieldPoints; // Clamp to max points if (_ShieldPoints > MaxShieldPoints) { _ShieldPoints = MaxShieldPoints; } } else { // Clamp the shield _ShieldPoints = 0; _Shield = 0f; } // Update health to be a normalized range of the object's hitpoints if (_HitPoints > 0) { _Health = _HitPoints / MaxHitPoints; // Clamp to max points if (_HitPoints > MaxHitPoints) { _HitPoints = MaxHitPoints; } } else { // Clamping health _HitPoints = 0; _Health = 0f; } // Despawn any damage particles if our health is above the threshold (IE: after being healed) if (_Health > HealthThresholdDamaged) { for (int i = 0; i < _DamagedParticles.Count; i++) { ParticleSystem effect = _DamagedParticles[i]; effect.Stop(true); ObjectPooling.Despawn(effect.gameObject); } if (_DamagedParticles.Count > 0) { _DamagedParticles.Clear(); } } else { // Update the position of the particle effects so that they are constantly at the attached object for (int i = 0; i < _DamagedParticles.Count; i++) { GameObject effect = _DamagedParticles[i].gameObject; effect.transform.position = HealthDamagedParticles[i].ParticleLocation.position; effect.transform.rotation = HealthDamagedParticles[i].ParticleLocation.rotation; } } // Change minimap colour based on attacking/defending & team colour if (_MinimapQuadRenderer != null) { // Attacking team colour if (Team == GameManager.Team.Attacking) { _MinimapQuadRenderer.material.color = WaveManager.Instance.AttackingTeamColour; } // Defending team else if (Team == GameManager.Team.Defending) { // Use individual player colour if (_Player) { _MinimapQuadRenderer.material.color = _Player.TeamColor; } } } // Gradually shrink the character then despawn it once its dead UpdateDeathShrinker(); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Destroys the building & returns some resources back to the player who owns the building. /// </summary> public void RecycleBuilding() { // Deselect all objects foreach (var selectable in GameManager.Instance.Selectables) { selectable.SetIsSelected(false); } // Add resources back to player if (_Player != null) { _Player.SuppliesCount += GetRecycleSuppliesAmount(); _Player.PowerCount += GetRecyclePowerAmount(); } // Destroy building if (_RecycleOption) { // Deselect self SetIsSelected(false); // Destroy Widgets if (AttachedBuildingSlot.GetBuildingOnSlot()._HealthBar) { ObjectPooling.Despawn(AttachedBuildingSlot.GetBuildingOnSlot()._HealthBar.gameObject); } if (AttachedBuildingSlot.GetBuildingOnSlot()._BuildingProgressCounter) { ObjectPooling.Despawn(AttachedBuildingSlot.GetBuildingOnSlot()._BuildingProgressCounter.gameObject); } // Remove from queues/lists // Bases if (AttachedBuildingSlot.AttachedBase != null) { AttachedBuildingSlot.AttachedBase.RemoveFromQueue(AttachedBuildingSlot.GetBuildingOnSlot()); AttachedBuildingSlot.AttachedBase.RemoveFromList(AttachedBuildingSlot.GetBuildingOnSlot()); if (UI_BuildingQueueWrapper.Instance.ContainsQueue(_BuildingQueueUI)) { UI_BuildingQueueWrapper.Instance.RemoveFromQueue(_BuildingQueueUI); Destroy(_BuildingQueueUI); } } // Buildings if (AttachedBuildingSlot.AttachedBuilding != null && AttachedBuildingSlot.AttachedBase == null) { AttachedBuildingSlot.AttachedBuilding.RemoveFromQueue(AttachedBuildingSlot.GetBuildingOnSlot()); if (UI_BuildingQueueWrapper.Instance.ContainsQueue(_BuildingQueueUI)) { UI_BuildingQueueWrapper.Instance.RemoveFromQueue(_BuildingQueueUI); Destroy(_BuildingQueueUI); } } // Destroy Building if (_BuildingQueueUI != null) { UI_BuildingQueueWrapper.Instance.RemoveFromQueue(_BuildingQueueUI); } OnDeath(null); // Send message to match feed MatchFeed.Instance.AddMessage(string.Concat(ObjectName, " recycled.")); } // Make building slot available again AttachedBuildingSlot.SetBuildingOnSlot(null); AttachedBuildingSlot.gameObject.SetActive(true); // Update building queue UI if (AttachedBuildingSlot.AttachedBase != null) { AttachedBuildingSlot.AttachedBase._BuildingQueueUI.UpdateQueueItemList(); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // /// </summary> public void RefreshPanels() { // Reset lists for (int i = 0; i < _UnitInfoPanels.Count; i++) { ObjectPooling.Despawn(_UnitInfoPanels[i].gameObject); } _UnitInfos.Clear(); _UnitInfoPanels.Clear(); // Add a new panel for each type of unit selected by the player for (int i = 0; i < _SelectedUnits.Count; i++) { // Check if this unit already exists in the info lists bool matchingType = false; for (int j = 0; j < _UnitInfos.Count; j++) { // Matching type to existing info if (_SelectedUnits[i].UnitType == _UnitInfos[j]._UnitType) { // Add to count of the unit info _UnitInfos[j]._Amount++; matchingType = true; break; } } // No unit infos match the selected unit were testing against if (!matchingType) { // Create a new iterator in the info lists UnitInfos info = new UnitInfos { _UnitType = _SelectedUnits[i].UnitType, _Logo = _SelectedUnits[i].Logo, _CombatType = _SelectedUnits[i].CombatType, _Amount = 1 }; _UnitInfos.Add(info); } } // Create a new panel for each unit info for (int i = 0; i < _UnitInfos.Count; i++) { if (StencilObject != null) { // Spawn panel & pass unit info data UI_UnitInfoPanel panel = ObjectPooling.Spawn(StencilObject.gameObject).GetComponent <UI_UnitInfoPanel>(); panel.LogoComponent.sprite = _UnitInfos[i]._Logo; panel.UnitName.text = _UnitInfos[i]._UnitType.ToString(); panel.AmountCounter.text = _UnitInfos[i]._Amount.ToString(); panel.SetPanelInfo(_UnitInfos[i]); panel.SetPlayer(_Player); // Set combat type logo switch (_UnitInfos[i]._CombatType) { case Unit.ECombatType.GroundInfantry: panel.TypeComponent.sprite = GroundInfantryLogo; break; case Unit.ECombatType.GroundVehicle: panel.TypeComponent.sprite = GroundVehicleLogo; break; case Unit.ECombatType.AirVehicle: panel.TypeComponent.sprite = AirVehicleLogo; break; default: break; } // Set anchoring position RectTransform rectT = panel.GetComponent <RectTransform>(); panel.transform.SetParent(gameObject.transform); if (i > 0) { // Not the first panel rectT.anchoredPosition = new Vector2((StartingPositionX + (_PanelSize * i) + (OffsetX * i)), StartingPositionY); } else { // First panel rectT.anchoredPosition = new Vector2(StartingPositionX, StartingPositionY); } _UnitInfoPanels.Add(panel); } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called when the projectile is destroyed, this is // usually called when the projectile collides with something /// </summary> protected void OnDestroy() { if (ExplodeOnImpact) { /* * // DEBUGGING SPHERECAST * // Uncomment LINE 273 (the ignore raycast line) otherwise this will give unintended results! * GameObject child = new GameObject(); * child.transform.parent = gameObject.transform; * SphereCollider debug = child.AddComponent<SphereCollider>(); * debug.radius = ExplosionRadius; * debug.isTrigger = true; * debug.transform.localPosition = new Vector3(0, 0, 0); * child.layer = LayerMask.NameToLayer("Ignore Raycast"); */ // Use a spherical raycast for an AOE damage with falloff RaycastHit[] hits = Physics.SphereCastAll(transform.position, ExplosionRadius, transform.forward, 0f); foreach (var rayHit in hits) { WorldObject worldObj = rayHit.transform.gameObject.GetComponentInParent <WorldObject>(); if (worldObj != null) { // Get reference to the instigator this projectile belongs to WorldObject worldObjAttached = null; if (_WeaponAttached.GetUnitAttached() != null) { worldObjAttached = _WeaponAttached.GetUnitAttached(); } if (_WeaponAttached.GetTowerAttached() != null) { worldObjAttached = _WeaponAttached.GetTowerAttached(); } // Friendly fire is OFF if (worldObj.Team != worldObjAttached.Team) { // Determine damage falloff float distanceFromEpicenter = Vector3.Distance(transform.position, rayHit.point); float damageMultiplier = (distanceFromEpicenter / ExplosionRadius) * DamageFalloff; // Damage the object worldObj.Damage(Mathf.FloorToInt(_Damages.DamageDefault * damageMultiplier)); } } } // Play OnDeath effect if (ExplosionEffect != null) { // Play ParticleSystem effect = ObjectPooling.Spawn(ExplosionEffect.gameObject, transform.position, transform.rotation).GetComponent <ParticleSystem>(); effect.Play(); // Despawn particle system once it has finished its cycle float effectDuration = effect.duration + effect.startLifetime; StartCoroutine(ParticleDespawn(effect, effectDuration)); } } gameObject.SetActive(false); ObjectPooling.Despawn(gameObject); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called when the object is killed/destroyed /// </summary> public virtual void OnDeath(WorldObject instigator) { // Force deselect SetIsSelected(false); // Remove from instigators target list if (instigator != null) { (instigator as Unit).RemovePotentialTarget(this); } // Despawn any damaged threshold particles in play for (int i = 0; i < _DamagedParticles.Count; i++) { ParticleSystem effect = _DamagedParticles[i]; effect.Stop(true); ObjectPooling.Despawn(effect.gameObject); } if (_DamagedParticles.Count > 0) { _DamagedParticles.Clear(); } // Set object state _ObjectState = WorldObjectStates.Destroyed; // Destroy healthbar if (_HealthBar != null) { // Null the reference _HealthBar.SetObjectAttached(null); ObjectPooling.Despawn(_HealthBar.gameObject); } // Clamping health _HitPoints = 0; _Health = 0f; // Play OnDeath(s) effect for (int i = 0; i < OnDeathEffects.Count; i++) { // Play at location ParticleSystem effect = ObjectPooling.Spawn(OnDeathEffects[i].ParticleEffect.gameObject, OnDeathEffects[i].ParticleLocation.position, OnDeathEffects[i].ParticleLocation.rotation).GetComponent <ParticleSystem>(); effect.Play(); } // Camera shake if neccessary if (CameraShakeOnDeath && _Player != null) { _Player.CameraRTS.ExplosionShake(transform.position, DeathExplosionRadius); } // Send message to match feed if (Team == GameManager.Team.Defending) { if (this is Unit) { MatchFeed.Instance.AddMessage(string.Concat(ObjectName, " has been killed.")); } if (!(this is Unit)) { MatchFeed.Instance.AddMessage(string.Concat(ObjectName, " destroyed.")); } _Player.AddUnitsLost(); } // Add to enemies killed stats else if (Team == GameManager.Team.Attacking && _Player != null) { _Player.AddUnitsKilled(); } // Delay then despawn StartCoroutine(DelayedShrinking(3f)); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Called when the projectile is destroyed, this is // usually called when the projectile collides with something /// </summary> protected void OnDestroy() { if (ExplodeOnImpact) { /* * // DEBUGGING SPHERECAST * // Uncomment LINE 273 (the ignore raycast line) otherwise this will give unintended results! * GameObject child = new GameObject(); * child.transform.parent = gameObject.transform; * SphereCollider debug = child.AddComponent<SphereCollider>(); * debug.radius = ExplosionRadius; * debug.isTrigger = true; * debug.transform.localPosition = new Vector3(0, 0, 0); * child.layer = LayerMask.NameToLayer("Ignore Raycast"); */ // Use a spherical raycast for an AOE damage with falloff RaycastHit[] hits = Physics.SphereCastAll(transform.position, ExplosionRadius, transform.forward, 0f); foreach (var rayHit in hits) { WorldObject worldObj = rayHit.transform.gameObject.GetComponentInParent <WorldObject>(); if (worldObj != null) { // Get reference to the instigator this projectile belongs to WorldObject worldObjAttached = null; if (_WeaponAttached.GetUnitAttached() != null) { worldObjAttached = _WeaponAttached.GetUnitAttached(); } if (_WeaponAttached.GetTowerAttached() != null) { worldObjAttached = _WeaponAttached.GetTowerAttached(); } // Friendly fire is OFF if (worldObj.Team != worldObjAttached.Team) { // Determine damage falloff float distanceFromEpicenter = Vector3.Distance(transform.position, rayHit.point); float damageMultiplier = (distanceFromEpicenter / ExplosionRadius) * DamageFalloff; // Damage the object worldObj.Damage(Mathf.FloorToInt(_Damages.DamageDefault * damageMultiplier)); } } } // Play OnDeath effect if (ExplosionEffect != null) { // Play ParticleSystem effect = ObjectPooling.Spawn(ExplosionEffect.gameObject, transform.position, transform.rotation).GetComponent <ParticleSystem>(); effect.Play(); } // Camera shake on explosion Player player = null; if (_WeaponAttached.GetUnitAttached() != null) { player = _WeaponAttached.GetUnitAttached()._Player; } if (_WeaponAttached.GetTowerAttached() != null) { player = _WeaponAttached.GetTowerAttached()._Player; } if (player != null) { player.CameraRTS.ExplosionShake(transform.position, ExplosionRadius); } } // Set the projectile's impact effect to match the weapon's impact effect (if set in the weapon) if (_WeaponAttached != null) { if (_WeaponAttached.DefaultImpactEffect != null) { ImpactEffect = _WeaponAttached.DefaultImpactEffect; } } // Play impact effect if (ImpactEffect != null) { // Play ParticleSystem effect = ObjectPooling.Spawn(ImpactEffect, transform.position, transform.rotation).GetComponentInChildren <ParticleSystem>(); effect.Play(); } // Play OnDeath effect (this is for when you dont want to use explosion damage properties, but have the effect play still) if (ExplosionEffect != null && !ExplodeOnImpact) { // Play ParticleSystem effect = ObjectPooling.Spawn(ExplosionEffect.gameObject, transform.position, transform.rotation).GetComponent <ParticleSystem>(); effect.Play(); } ObjectPooling.Despawn(gameObject); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> // Detonates the mine and damages any enemies within the blast radius. /// </summary> public void DetonateMine() { /* * // DEBUGGING SPHERECAST * // Uncomment LINE 273 (the ignore raycast line) otherwise this will give unintended results! * GameObject child = new GameObject(); * child.transform.parent = gameObject.transform; * SphereCollider debug = child.AddComponent<SphereCollider>(); * debug.radius = ExplosionRadius; * debug.isTrigger = true; * debug.transform.localPosition = new Vector3(0, 0, 0); * child.layer = LayerMask.NameToLayer("Ignore Raycast"); */ // Use a spherical raycast for an AOE damage with falloff RaycastHit[] hits = Physics.SphereCastAll(transform.position, ExplosionRadius, transform.forward, 0f); foreach (var rayHit in hits) { WorldObject worldObj = rayHit.transform.gameObject.GetComponentInParent <WorldObject>(); if (worldObj != null) { // Friendly fire is OFF if (worldObj.Team != _Team) { // Determine damage falloff float distanceFromEpicenter = Vector3.Distance(transform.position, rayHit.point); float damageMultiplier = (distanceFromEpicenter / ExplosionRadius) * DamageFalloff; // Damage the object worldObj.Damage(Mathf.FloorToInt(Damages.DamageDefault * damageMultiplier)); } } } // Play OnDeath effect if (ExplosionEffect != null) { // Play ParticleSystem effect = ObjectPooling.Spawn(ExplosionEffect.gameObject, transform.position, transform.rotation).GetComponent <ParticleSystem>(); effect.Play(); // Despawn particle system once it has finished its cycle float effectDuration = effect.duration + effect.startLifetime; StartCoroutine(ParticleDespawn(effect, effectDuration)); } // Remove mine from its attached minefield if (_MineFieldAttached != null) { _MineFieldAttached.GetUndetonatedMines().Remove(this); // Check if the minefield object should be despawned aswell if (_MineFieldAttached.GetUndetonatedMines().Count == 0) { _MineFieldAttached.OnDeath(null); } // Despawn mine ObjectPooling.Despawn(gameObject); } }