/// <summary> /// Plays explosion sound and shakes ground /// </summary> private void PlaySoundAndShake(Vector3Int explosionPosition) { byte shakeIntensity = (byte)Mathf.Clamp(damage / 5, byte.MinValue, byte.MaxValue); ExplosionUtils.PlaySoundAndShake(explosionPosition, shakeIntensity, (int)shakeDistance); }
private void CheckTileCollisions(MatrixIntersection i) { if (i.Matrix1 == null || i.Matrix2 == null) { return; } byte collisions = 0; foreach (var worldPos in i.Rect.allPositionsWithin()) { Vector3Int cellPos1 = i.Matrix1.MetaTileMap.WorldToCell(worldPos); if (!i.Matrix1.Matrix.HasTile(cellPos1, true)) { continue; } Vector3Int cellPos2 = i.Matrix2.MetaTileMap.WorldToCell(worldPos); if (!i.Matrix2.Matrix.HasTile(cellPos2, true)) { continue; } float resistance1 = i.Matrix1.MetaTileMap.Resistance(cellPos1, true); if (resistance1 <= 0f) { continue; } float resistance2 = i.Matrix2.MetaTileMap.Resistance(cellPos2, true); if (resistance2 <= 0f) { continue; } collisionLocations.Add(worldPos); // // ******** DESTROY STUFF!!! ******** // //total damage to apply to victim tile if (resistance1 + (10 * i.Matrix1.Speed) >= resistance2 + (10 * i.Matrix2.Speed)) { //attacker tile is stronger: //destroy victim tile TryPushing(i.Matrix2, cellPos2, i.Matrix1.MovementVector, i.Matrix1.Speed); ApplyCritDamage(i.Matrix2, cellPos2, worldPos); //slightly damage adjacent victim tiles ApplyTilemapDamage(i.Matrix2, cellPos2 + Vector3Int.up, resistance1 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix2, cellPos2 + Vector3Int.down, resistance1 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix2, cellPos2 + Vector3Int.left, resistance1 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix2, cellPos2 + Vector3Int.right, resistance1 * 0.4f, worldPos); //damage back attacker TryPushing(i.Matrix1, cellPos1, i.Matrix2.MovementVector, i.Matrix2.Speed); ApplyDamage(i.Matrix1, cellPos1, resistance2, worldPos); if (resistance2 > EXTRA_COLLISION_THRESHOLD) { collisions += (byte)((resistance2 - EXTRA_COLLISION_THRESHOLD) / EXTRA_COLLISION_THRESHOLD); } } else { //victim tile is stronger //destroy weaker tile TryPushing(i.Matrix1, cellPos1, i.Matrix2.MovementVector, i.Matrix2.Speed); ApplyCritDamage(i.Matrix1, cellPos1, worldPos); //slightly damage adjacent tiles ApplyTilemapDamage(i.Matrix1, cellPos1 + Vector3Int.up, resistance2 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix1, cellPos1 + Vector3Int.down, resistance2 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix1, cellPos1 + Vector3Int.left, resistance2 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix1, cellPos1 + Vector3Int.right, resistance2 * 0.4f, worldPos); //damage back TryPushing(i.Matrix2, cellPos2, i.Matrix1.MovementVector, i.Matrix1.Speed); ApplyDamage(i.Matrix2, cellPos2, resistance1, worldPos); if (resistance1 > EXTRA_COLLISION_THRESHOLD) { collisions += (byte)((resistance1 - EXTRA_COLLISION_THRESHOLD) / EXTRA_COLLISION_THRESHOLD); } } collisions++; //Wires (since they don't have Integrity) ApplyWireDamage(i.Matrix1, cellPos1); ApplyWireDamage(i.Matrix2, cellPos2); //Heat shit up i.Matrix1.ReactionManager.ExposeHotspot(cellPos1, 500); i.Matrix2.ReactionManager.ExposeHotspot(cellPos2, 500); //Other foreach (var layer in layersToRemove) { i.Matrix1.TileChangeManager.MetaTileMap.RemoveTileWithlayer(cellPos1, layer); i.Matrix2.TileChangeManager.MetaTileMap.RemoveTileWithlayer(cellPos2, layer); } foreach (var layer in effectsToRemove) { i.Matrix1.TileChangeManager.MetaTileMap.RemoveAllOverlays(cellPos1, layer); i.Matrix2.TileChangeManager.MetaTileMap.RemoveAllOverlays(cellPos2, layer); } } if (collisions > 0) { var epicenter = collisionLocations[collisionLocations.Count / 2]; ExplosionUtils.PlaySoundAndShake( epicenter, (byte)Mathf.Clamp(collisions * 12, 16, byte.MaxValue), Mathf.Clamp(collisions * 8, 15, 127) ); SlowDown(i, collisions); if (collisions > 6 && Mathf.Max(i.Matrix1.Speed, i.Matrix2.Speed) > 6) { i.Matrix1.Matrix.OnEarthquake.Invoke(epicenter, collisions); i.Matrix2.Matrix.OnEarthquake.Invoke(epicenter, collisions); } collisionLocations.Clear(); } //Damage methods void ApplyDamage(MatrixInfo victimMatrix, Vector3Int cellPos, float hitEnergy, Vector3Int worldPos) { //LivingHealthBehaviour hitEnergy -= ApplyLivingDamage(victimMatrix, cellPos, hitEnergy); //TilemapDamage ApplyTilemapDamage(victimMatrix, cellPos, hitEnergy, worldPos); // //Integrity ApplyIntegrityDamage(victimMatrix, cellPos, hitEnergy); } void ApplyCritDamage(MatrixInfo victimMatrix, Vector3Int cellPos, Vector3Int worldPos) { //LivingHealthBehaviour ApplyLivingDamage(victimMatrix, cellPos, 9001); //TilemapDamage ApplyTilemapDamage(victimMatrix, cellPos, 9001, worldPos); //Integrity ApplyIntegrityDamage(victimMatrix, cellPos, 9001); //Underfloor RemoveUnderfloor(victimMatrix, cellPos); } void RemoveUnderfloor(MatrixInfo matrix, Vector3Int cellPos) { if (matrix == null) { return; } var Node = matrix.Matrix.GetMetaDataNode(cellPos); if (Node != null) { foreach (var electricalData in Node.ElectricalData) { electricalData.InData.DestroyThisPlease(); } } } void ApplyTilemapDamage(MatrixInfo matrix, Vector3Int cellPos, float damage, Vector3Int worldPos) { if (matrix == null) { return; } matrix.MetaTileMap.ApplyDamage(cellPos, damage, worldPos); if (damage > 9000) { foreach (var damageableLayer in matrix.MetaTileMap.LayersValues) { if (damageableLayer.LayerType == LayerType.Objects) { continue; } matrix.TileChangeManager.MetaTileMap.RemoveTileWithlayer(cellPos, damageableLayer.LayerType); } } } void ApplyWireDamage(MatrixInfo matrix, Vector3Int cellPos) { if (matrix == null) { return; } foreach (var wire in matrix.Matrix.Get <CableInheritance>(cellPos, true)) { if (Random.value >= 0.5) { // Sparks wire.QueueForDemolition(wire); StartCoroutine(DestroyWireWithDelay(wire, (byte)(Random.value * 20f))); } else { // Destruction wire.ToDestroy(); } } } float ApplyIntegrityDamage(MatrixInfo matrix, Vector3Int cellPos, float damage) { if (matrix == null) { return(0); } float resistance = 0f; foreach (var integrity in matrix.Matrix.Get <Integrity>(cellPos, true)) { resistance += integrity.integrity; integrity.ApplyDamage(damage, AttackType.Melee, DamageType.Brute); } return(resistance); } float ApplyLivingDamage(MatrixInfo matrix, Vector3Int cellPos, float damage) { if (matrix == null) { return(0); } byte count = 0; foreach (var healthBehaviour in matrix.Matrix.Get <LivingHealthMasterBase>(cellPos, true)) { healthBehaviour.ApplyDamageToBodyPart(matrix.GameObject, damage, AttackType.Melee, DamageType.Brute); count++; } return(count * 50); } void TryPushing(MatrixInfo matrix, Vector3Int cellPos, Vector2Int pushVector, float speed) { if (matrix == null || pushVector == Vector2Int.zero) { return; } foreach (var pushPull in matrix.Matrix.Get <PushPull>(cellPos, true)) { byte pushes = (byte)Mathf.Clamp(speed / 4, 1, 4); for (int j = 0; j < pushes; j++) { pushPull.QueuePush(pushVector, speed * Random.Range(0.8f, 1.1f)); } } } IEnumerator DestroyWireWithDelay(CableInheritance wire, byte timer) { yield return(WaitFor.Seconds(timer)); if (wire != null) { wire.ToDestroy(); } } }
/// <summary> /// Plays explosion sound and shakes ground /// </summary> private void PlaySoundAndShake() { byte shakeIntensity = (byte)Mathf.Clamp(damage / 5, byte.MinValue, byte.MaxValue); ExplosionUtils.PlaySoundAndShake(objectBehaviour.AssumedWorldPositionServer().RoundToInt(), shakeIntensity, (int)shakeDistance); }