/// <summary> /// This method gets called when the death timer starts. /// </summary> public virtual void WaitingToDestroyKillable(Killable deadKillable) { // your code here; }
/// <summary> /// This method gets called when the Killable is prevented taking damage by invicibility. /// </summary> public virtual void DamagePrevented(int pointsDamage, Killable enemyHitBy) { // your code here. }
/// <summary> /// This method gets called when the Killable is spawned. /// </summary> public virtual void Spawned(Killable newKillable) { // your code here }
/// <summary> /// This method gets called when the Killable is taking damage. /// </summary> public virtual void TakingDamage(int pointsDamage, Killable enemyHitBy) { // your code here. }
/// <summary> /// Call this method to inflict X points of damage to a Killable. /// </summary> /// <param name="damagePoints">The number of points of damage to inflict.</param> /// <param name="enemy">The other Killable that collided with this one.</param> public virtual void TakeDamage(int damagePoints, Killable enemy) { var dmgPrefabsSpawned = false; var varsModded = false; var eventsFired = false; var knockBackSent = false; if (IsInvincible()) { if (damagePoints >= 0) { LogIfEnabled("Taking no damage because Invincible is checked!"); } if (listener != null) { listener.DamagePrevented(damagePoints, enemy); } if (despawnMode == DespawnMode.CollisionOrTrigger) { DestroyKillable(); } // mod variables and spawn dmg prefabs // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (!varsModded) { ModifyWorldVariables(playerStatDamageModifiers, true); varsModded = true; } // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (!eventsFired && damageFireEvents) { // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < damageCustomEvents.Count; i++) { var anEvent = damageCustomEvents[i].CustomEventName; LevelSettings.FireCustomEventIfValid(anEvent, Trans.position); } eventsFired = true; } dmgPrefabsSpawned = SpawnDamagePrefabsIfPerHit(damagePoints); // end mod variables and spawn dmg prefabs if (sendDamageKnockback) { knockBackSent = true; Knockback(enemy); } if (damagePoints >= 0) { // allow negative damage to continue return; } } if (listener != null) { listener.TakingDamage(damagePoints, enemy); } if (sendDamageKnockback && !knockBackSent) { Knockback(enemy); } // mod variables and spawn dmg prefabs if (!varsModded) { ModifyWorldVariables(playerStatDamageModifiers, true); varsModded = true; } // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (!eventsFired && damageFireEvents) { // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < damageCustomEvents.Count; i++) { var anEvent = damageCustomEvents[i].CustomEventName; LevelSettings.FireCustomEventIfValid(anEvent, Trans.position); } // ReSharper disable once RedundantAssignment eventsFired = true; } if (!dmgPrefabsSpawned) { dmgPrefabsSpawned = SpawnDamagePrefabsIfPerHit(damagePoints); } // end mod variables and spawn dmg prefabs if (damagePoints == 0) { return; } if (enableLogging) { LogIfEnabled("Taking " + damagePoints + " points damage!"); } currentHitPoints -= damagePoints; if (currentHitPoints < 0) { currentHitPoints = 0; } else if (currentHitPoints > maxHitPoints.Value) { currentHitPoints = maxHitPoints.Value; } if (hitPoints.variableSource == LevelSettings.VariableSource.Variable && syncHitPointWorldVariable) { var aVar = WorldVariableTracker.GetWorldVariable(hitPoints.worldVariableName); if (aVar != null) { aVar.CurrentIntValue = currentHitPoints; } } switch (retriggerLimitMode) { case TriggeredSpawner.RetriggerLimitMode.FrameBased: _triggeredLastFrame = Time.frameCount; break; case TriggeredSpawner.RetriggerLimitMode.TimeBased: _triggeredLastTime = Time.time; break; } // mod variables and spawn dmg prefabs // ReSharper disable once ConditionIsAlwaysTrueOrFalse // ReSharper disable HeuristicUnreachableCode if (!varsModded) { ModifyWorldVariables(playerStatDamageModifiers, true); // ReSharper disable once RedundantAssignment varsModded = true; } // ReSharper restore HeuristicUnreachableCode if (!dmgPrefabsSpawned) { SpawnDamagePrefabs(damagePoints); } // end mod variables and spawn dmg prefabs switch (despawnMode) { case DespawnMode.ZeroHitPoints: if (currentHitPoints > 0) { return; } break; case DespawnMode.None: return; } KilledBy = enemy; DestroyKillable(); }
public void UnregisterChildKillable(Killable kill) { _childKillables.Remove(kill); deathDespawnBehavior = DeathDespawnBehavior.Disable; if (_childKillables.Count == 0 && invincibleWhileChildrenKillablesExist && disableCollidersWhileChildrenKillablesExist) { EnableColliders(); } // Diagnostic code to uncomment if things are going wrong. //Debug.Log("REMOVE - children of '" + name + "': " + childKillables.Count); }
public void RecordChildToDie(Killable kilChild) { if (_childrenToDestroy.Contains(kilChild)) { return; } _childrenToDestroy.Add(kilChild); }
/// <summary> /// This method when damage is valid and is about to be inflicted (no invincibility). /// </summary> /// <param name="damagePoints">Number of damage points to take.</param> /// <param name="enemy">The enemy that dealt the damage.</param> protected virtual void TakingDamage(int damagePoints, Killable enemy) { if (listener != null) { listener.TakingDamage(damagePoints, enemy); } }
private void CheckForAttackPoints(Killable enemy, GameObject goHit) { if (enemy == null) { LogIfEnabled("Not taking any damage because you've collided with non-Killable object '" + goHit.name + "'."); return; } if (ignoreKillablesSpawnedByMe) { if (enemy.SpawnedFromObjectId == KillableId) { LogIfEnabled("Not taking any damage because you've collided with a Killable named '" + goHit.name + "' spawned by this Killable."); return; } } TakeDamage(enemy.atckPoints.Value, enemy); }
/// <summary> /// This will knock back (and up) any combatents fighting with this Killable. /// </summary> /// <param name="enemy">The enemy knocking this Killable back.</param> public virtual void Knockback(Killable enemy) { if (atckPoints.Value <= 0 || !sendDamageKnockback || enemy == null) { return; } if (enemy.IsInvincible()) { if (!enemy.ReceiveKnockbackWhenInvince) { return; } } else { if (!enemy.ReceiveKnockbackWhenDamaged) { return; } } if (!IsGravBody) { return; } var pushHeight = damageKnockUpMeters.Value; var pushForce = damageKnockBackFactor.Value; var pushDir = (enemy.transform.position - transform.position); pushDir.y = 0f; if (Body != null) { var enemyBody = enemy.GetComponent<Rigidbody>(); enemyBody.velocity = new Vector3(0, 0, 0); enemyBody.AddForce(pushDir.normalized * pushForce, ForceMode.VelocityChange); enemyBody.AddForce(Vector3.up * pushHeight, ForceMode.VelocityChange); } else { // Rigidbody 2D var enemyBody2D = enemy.GetComponent<Rigidbody2D>(); enemyBody2D.velocity = new Vector2(0, 0); var knockback = Vector2.right * pushForce; // knock right if (enemy.transform.position.x < Trans.position.x) { knockback *= -1; // knock left } enemyBody2D.AddForce(knockback, ForceMode2D.Impulse); enemyBody2D.AddForce(Vector3.up * pushHeight, ForceMode2D.Impulse); } }
/// <summary> /// This method gets called whenever the object is spawned or starts in a Scene (from Awake event) /// </summary> /// <param name="spawned">True if spawned, false if in the Scene at beginning.</param> protected virtual void SpawnedOrAwake(bool spawned = true) { if (listener != null) { listener.Spawned(this); } KilledBy = null; _waitingToDestroy = false; _childrenToDestroy.Clear(); if (parentDestroyedAction != SpawnerDestroyedBehavior.DoNothing && parentKillableForParentDestroyed != null) { parentKillableForParentDestroyed.RecordChildToDie(this); } // anything you want to do each time this is spawned. if (_timesRespawned == 0) { isVisible = false; _becameVisible = false; } _isDespawning = false; _spawnTime = Time.time; _isTemporarilyInvincible = false; if (respawnType != RespawnType.None && !_spawnLocationSet) { _respawnLocation = Trans.position; _spawnLocationSet = true; } // respawning from "respawn" setting. if (_timesRespawned > 0) { Trans.position = _respawnLocation; } else { // register child Killables with parent, if any var aParent = Trans.parent; while (aParent != null) { _parentKillable = aParent.GetComponent<Killable>(); if (_parentKillable == null) { aParent = aParent.parent; continue; } _parentKillable.RegisterChildKillable(this); break; } } currentHitPoints = hitPoints.Value; _damageTaken = 0; _damagePrefabsSpawned = 0; if (deathPrefabPoolName != null && deathPrefabSource == WaveSpecifics.SpawnOrigin.PrefabPool) { _deathPrefabWavePool = LevelSettings.GetFirstMatchingPrefabPool(deathPrefabPoolName); if (_deathPrefabWavePool == null) { LevelSettings.LogIfNew("Death Prefab Pool '" + deathPrefabPoolName + "' not found for Killable '" + name + "'."); } } if (damagePrefabSpawnMode != DamagePrefabSpawnMode.None && damagePrefabPoolName != null && damagePrefabSource == SpawnSource.PrefabPool) { _damagePrefabWavePool = LevelSettings.GetFirstMatchingPrefabPool(damagePrefabPoolName); if (_damagePrefabWavePool == null) { LevelSettings.LogIfNew("Damage Prefab Pool '" + _damagePrefabWavePool + "' not found for Killable '" + name + "'."); } } if (damagePrefabSpawnMode != DamagePrefabSpawnMode.None && damagePrefabSource == SpawnSource.Specific && damagePrefabSpecific == null) { LevelSettings.LogIfNew(string.Format("Damage Prefab for '{0}' is not assigned.", Trans.name)); } CheckForValidVariables(); StopAllCoroutines(); // for respawn purposes. StartCoroutine(CoUpdate()); deathDespawnBehavior = DeathDespawnBehavior.ReturnToPool; if (invincibleOnSpawn) { TemporaryInvincibility(invincibleTimeSpawn.Value); } }
/// <summary> /// Call this method to inflict X points of damage to a Killable. /// </summary> /// <param name="damagePoints">The number of points of damage to inflict.</param> /// <param name="enemy">The other Killable that collided with this one.</param> public virtual void TakeDamage(int damagePoints, Killable enemy) { var dmgPrefabsSpawned = false; var dealDmgPrefabSpawned = false; var varsModded = false; var eventsFired = false; var knockBackSent = false; if (IsInvincible()) { SpawnInvinceHitPrefab(); if (damagePoints >= 0) { LogIfEnabled("Taking no damage because it's currently invincible!"); } if (listener != null) { DamagePrevented(damagePoints, enemy); } if (despawnMode == DespawnMode.CollisionOrTrigger) { DestroyKillable(); } // mod variables and spawn dmg prefabs // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (!varsModded) { ModifyWorldVariables(playerStatDamageModifiers, true); varsModded = true; } // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (!eventsFired && damageFireEvents) { // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < damageCustomEvents.Count; i++) { var anEvent = damageCustomEvents[i].CustomEventName; LevelSettings.FireCustomEventIfValid(anEvent, Trans.position); } eventsFired = true; } dmgPrefabsSpawned = SpawnDamagePrefabsIfPerHit(damagePoints); // end mod variables and spawn dmg prefabs if (sendDamageKnockback) { knockBackSent = true; Knockback(enemy); } if (damagePoints >= 0) { // allow negative damage to continue return; } } TakingDamage(damagePoints, enemy); if (sendDamageKnockback && !knockBackSent) { Knockback(enemy); } var newHP = currentHitPoints - damagePoints; var isDeathHit = newHP <= 0 || (despawnMode == DespawnMode.LostAnyHitPoints && damagePoints > 0) || (despawnMode == DespawnMode.CollisionOrTrigger); // mod variables and spawn dmg prefabs if (!varsModded) { ModifyWorldVariables(playerStatDamageModifiers, true); varsModded = true; } // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (!eventsFired && damageFireEvents) { // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < damageCustomEvents.Count; i++) { var anEvent = damageCustomEvents[i].CustomEventName; LevelSettings.FireCustomEventIfValid(anEvent, Trans.position); } // ReSharper disable once RedundantAssignment eventsFired = true; } var shouldSpawnDmgPrefab = !isDeathHit || damagePrefabOnDeathHit; var shouldSpawnDealDmgPrefab = !isDeathHit || (enemy != null && enemy.dealDamagePrefabOnDeathHit); if (!dmgPrefabsSpawned && shouldSpawnDmgPrefab) { dmgPrefabsSpawned = SpawnDamagePrefabsIfPerHit(damagePoints); } if (shouldSpawnDealDmgPrefab) { dealDmgPrefabSpawned = SpawnDealDamagePrefabsIfTakingDamage(damagePoints, enemy); } // end mod variables and spawn dmg prefabs if (damagePoints == 0 && !isDeathHit) { return; } if (enableLogging) { LogIfEnabled("Taking " + damagePoints + " points damage!"); } currentHitPoints = newHP; if (currentHitPoints < 0) { currentHitPoints = 0; } else if (currentHitPoints > maxHitPoints.Value) { currentHitPoints = maxHitPoints.Value; } // must do this first so you don't turn invincible by the next lines! if (!dealDmgPrefabSpawned && isDeathHit && (enemy != null && enemy.dealDamagePrefabOnDeathHit)) { SpawnDealDamagePrefabsIfTakingDamage(damagePoints, enemy); } if (invincibleWhenDamaged && currentHitPoints > 0) { TemporaryInvincibility(invincibleDamageTime.Value); } if (hitPoints.variableSource == LevelSettings.VariableSource.Variable && syncHitPointWorldVariable) { var aVar = WorldVariableTracker.GetWorldVariable(hitPoints.worldVariableName); if (aVar != null) { aVar.CurrentIntValue = currentHitPoints; } } // mod variables and spawn dmg prefabs // ReSharper disable once ConditionIsAlwaysTrueOrFalse // ReSharper disable HeuristicUnreachableCode if (!varsModded) { ModifyWorldVariables(playerStatDamageModifiers, true); // ReSharper disable once RedundantAssignment varsModded = true; } // ReSharper restore HeuristicUnreachableCode if (!dmgPrefabsSpawned && shouldSpawnDmgPrefab) { SpawnDamagePrefabs(damagePoints); } // end mod variables and spawn dmg prefabs switch (despawnMode) { case DespawnMode.ZeroHitPoints: if (currentHitPoints > 0) { return; } break; case DespawnMode.None: return; } KilledBy = enemy; DestroyKillable(); }
private bool SpawnDealDamagePrefabsIfTakingDamage(int damagePoints, Killable enemy) { if (IsInvincible() || damagePoints <= 0) { // do not spawn deal damage prefabs when invincible or no damage return false; } if (enemy == null) { return false; } var prefabToSpawn = enemy.CurrentDealDamagePrefab; if (prefabToSpawn == null) { // empty element, spawn nothing return false; } var spawnedDealDamagePrefab = SpawnPrefab(prefabToSpawn, Trans.position); // ReSharper disable once InvertIf if (spawnedDealDamagePrefab != null) { SpawnUtility.RecordSpawnerObjectIfKillable(spawnedDealDamagePrefab, GameObj); // affect the spawned object. var euler = prefabToSpawn.rotation.eulerAngles; if (enemy.dealDamagePrefabRandomizeXRotation) { euler.x = UnityEngine.Random.Range(0f, 360f); } if (enemy.dealDamagePrefabRandomizeYRotation) { euler.y = UnityEngine.Random.Range(0f, 360f); } if (enemy.dealDamagePrefabRandomizeZRotation) { euler.z = UnityEngine.Random.Range(0f, 360f); } spawnedDealDamagePrefab.rotation = Quaternion.Euler(euler); } return true; }
/// <summary> /// This method gets called when the Killable is destroyed. /// </summary> public virtual void DestroyingKillable(Killable deadKillable) { // your code here. }
public void RegisterChildKillable(Killable kill) { if (_childKillables.Contains(kill)) { return; } _childKillables.Add(kill); if (invincibleWhileChildrenKillablesExist && disableCollidersWhileChildrenKillablesExist) { DisableColliders(); } // Diagnostic code to uncomment if things are going wrong. //Debug.Log("ADD - children of '" + name + "': " + childKillables.Count); }
/// <summary> /// This method gets called when the Scenario is about to be decided. You can add logic to decide the Scenario here. /// </summary> public virtual string DeterminingScenario(Killable deadKillable, string scenario) { // if you wish to use logic to change the Scenario, do it here. Example below. // if (yourLogicHere == true) { // scenario = "ReachedTower"; // } return scenario; }
/// <summary> /// This method is called when damage is prevents by Invincibility /// </summary> /// <param name="pointsDamage">The number of points prevented.</param> /// <param name="enemyHitBy">The enemy that tried to inflict damage.</param> protected virtual void DamagePrevented(int pointsDamage, Killable enemyHitBy) { listener.DamagePrevented(pointsDamage, enemyHitBy); }