private void OnRockLanded(GameObject rock, float damage) { var landingPosition = rock.RegisterTile().WorldPositionServer; Explosion.StartExplosion(landingPosition, damage); ExplosionUtils.PlaySoundAndShake(landingPosition, 16, 4); }
private void OnRockLanded(GameObject rock, float damage) { var landingPosition = rock.RegisterTile().WorldPositionServer; var matrixInfo = MatrixManager.AtPoint(landingPosition, true); Explosion.StartExplosion(landingPosition, damage, matrixInfo.Matrix); ExplosionUtils.PlaySoundAndShake(landingPosition, 16, 4); }
void OnTriggerEnter(Collider other) { Debug.Log(other.name + "Just entered!"); var explodable = other.GetComponent <IExplodeable>(); if (explodable == null) { return; } Vector3 vec = other.transform.position - transform.position; explodable.Explode(ExplosionUtils.ExplosiveForce(vec, vec.magnitude, GameSettings.Instance.ExplosionRadius)); }
private void ExplodeContainer() { var shakeIntensity = (byte)Mathf.Lerp( byte.MinValue, byte.MaxValue / 2, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); var shakeDistance = Mathf.Lerp(1, 64, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); //release all of our gases at once when destroyed ReleaseContentsInstantly(); ExplosionUtils.PlaySoundAndShake(WorldPosition, shakeIntensity, (int)shakeDistance); Chat.AddLocalDestroyMsgToChat(gameObject.ExpensiveName(), " exploded!", gameObject); ServerContainerExplode?.Invoke(); // Disable this script, gameObject has no valid container now. enabled = false; }
IEnumerator ExplosionSequence(float countdownTime) { // show countdown for non trivial explosion timings if (countdownTime >= GameSettings.Instance.MinDelayForCountdownPopup) { createCountdownText(countdownTime).transform.SetParent(transform, false); } yield return(new WaitForSeconds(countdownTime)); LevelSingleton.Instance.OnBarrelExplosion.Invoke(transform.position); int explosionBlockersLayer = 1 << LayerMask.NameToLayer("ExplosionBlockers"); // check only explosion blockers (walls etc.). We don't want barrels to block other barrels. int explodeablesLayer = 1 << LayerMask.NameToLayer("Explodeables"); var radius = MyExplosionRadius(); Vector3 myCenter = GetObjectCenter(); var collisions = Physics.OverlapSphere(myCenter, radius, explodeablesLayer); // find all nearby barrels (only) foreach (Collider collision in collisions) { // If it's not something that can explode, we don't care. var explodeable = collision.GetComponent <IExplodeable>(); if (explodeable == null) { continue; } Vector3 displacement = explodeable.GetObjectCenter() - myCenter; float distance = displacement.magnitude; // If there's a wall in the way, or if we're checking out ourselves, we also don't care. RaycastHit hit; if (displacement.sqrMagnitude < 0.01f || Physics.Raycast(myCenter, displacement, out hit, distance, explosionBlockersLayer)) { continue; } explodeable.Explode(ExplosionUtils.ExplosiveForce(displacement, distance, radius)); } if (ExplosionPrefab != null) { GameObject.Instantiate(ExplosionPrefab.gameObject, gameObject.transform.position, LevelSingleton.Instance.GroundRotator.transform.rotation, LevelSingleton.Instance.GroundRotator.transform); } Destroy(this.gameObject); }
private void OnWillDestroyServer(DestructionInfo info) { var tileWorldPosition = gameObject.TileWorldPosition().To3Int(); //release all of our gases at once when destroyed MetaDataLayer metaDataLayer = MatrixManager.AtPoint(tileWorldPosition, true).MetaDataLayer; Vector3Int position = transform.localPosition.RoundToInt(); MetaDataNode node = metaDataLayer.Get(position, false); var shakeIntensity = (byte)Mathf.Lerp(byte.MinValue, byte.MaxValue / 2, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); var shakeDistance = Mathf.Lerp(1, 64, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); node.GasMix += GasMix; metaDataLayer.UpdateSystemsAt(position); Chat.AddLocalMsgToChat($"{name} exploded!", gameObject.TileWorldPosition()); ObjectFactory.SpawnMetal(2, tileWorldPosition.To2Int(), parent: transform.parent); ExplosionUtils.PlaySoundAndShake(tileWorldPosition, shakeIntensity, (int)shakeDistance); }
private void OnWillDestroyServer(DestructionInfo info) { var tileWorldPosition = gameObject.TileWorldPosition().To3Int(); //release all of our gases at once when destroyed MetaDataLayer metaDataLayer = MatrixManager.AtPoint(tileWorldPosition, true).MetaDataLayer; Vector3Int position = transform.localPosition.RoundToInt(); MetaDataNode node = metaDataLayer.Get(position, false); var shakeIntensity = (byte)Mathf.Lerp(byte.MinValue, byte.MaxValue / 2, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); var shakeDistance = Mathf.Lerp(1, 64, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); node.GasMix += GasMix; metaDataLayer.UpdateSystemsAt(position); Chat.AddLocalDestroyMsgToChat(gameObject.ExpensiveName(), " exploded!", gameObject.TileWorldPosition()); Spawn.ServerPrefab("Metal", gameObject.TileWorldPosition().To3Int(), transform.parent, count: 2, scatterRadius: Spawn.DefaultScatterRadius, cancelIfImpassable: true); ExplosionUtils.PlaySoundAndShake(tileWorldPosition, shakeIntensity, (int)shakeDistance); }
public static void StartExplosion(Vector3Int MatrixPOS, float strength, Matrix matrix) { int Radius = (int)Math.Round(strength / (Math.PI * 75)); if (Radius > 150) { Radius = 150; } byte ShakingStrength = 25; if (strength > 800) { ShakingStrength = 75; } else if (strength > 8000) { ShakingStrength = 125; } else if (strength > 80000) { ShakingStrength = 255; } ExplosionUtils.PlaySoundAndShake(MatrixManager.LocalToWorld(MatrixPOS, matrix).RoundToInt(), ShakingStrength, Radius / 20); //Generates the conference var explosionData = new ExplosionData(); circleBres(explosionData, MatrixPOS.x, MatrixPOS.y, Radius); float InitialStrength = strength / explosionData.CircleCircumference.Count; foreach (var ToPoint in explosionData.CircleCircumference) { var Line = ExplosionPropagationLine.Getline(); Line.SetUp(MatrixPOS.x, MatrixPOS.y, ToPoint.x, ToPoint.y, InitialStrength, matrix); Line.Step(); } }
private void CheckTileCollisions(MatrixIntersection i) { byte collisions = 0; foreach (Vector3Int worldPos in i.Rect.ToBoundsInt().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); i.Matrix2.ReactionManager.ExposeHotspot(cellPos2); //Other foreach (var layer in layersToRemove) { i.Matrix1.TileChangeManager.RemoveTile(cellPos1, layer); i.Matrix2.TileChangeManager.RemoveTile(cellPos2, layer); } foreach (var layer in effectsToRemove) { i.Matrix1.TileChangeManager.RemoveOverlay(cellPos1, layer); i.Matrix2.TileChangeManager.RemoveOverlay(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) { 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) { matrix.MetaTileMap.ApplyDamage(cellPos, damage, worldPos); if (damage > 9000) { foreach (var damageableLayer in matrix.MetaTileMap.LayersValues) { if (damageableLayer.LayerType == LayerType.Objects) { continue; } matrix.TileChangeManager.RemoveTile(cellPos, damageableLayer.LayerType); } } } void ApplyWireDamage(MatrixInfo matrix, Vector3Int cellPos) { 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) { 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) { byte count = 0; foreach (var healthBehaviour in matrix.Matrix.Get <LivingHealthBehaviour>(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 (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.AssumedWorldPosition().RoundToInt(), shakeIntensity, (int)shakeDistance); }
/// <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); }