Example #1
0
        private void OnRockLanded(GameObject rock, float damage)
        {
            var landingPosition = rock.RegisterTile().WorldPositionServer;

            Explosion.StartExplosion(landingPosition, damage);
            ExplosionUtils.PlaySoundAndShake(landingPosition, 16, 4);
        }
Example #2
0
        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);
        }
Example #3
0
    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));
    }
Example #4
0
        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;
        }
Example #5
0
    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);
    }
Example #6
0
        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);
        }
Example #8
0
        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();
            }
        }
    }
Example #10
0
    /// <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);
    }
Example #11
0
    /// <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);
    }