Beispiel #1
0
        private void ApplyImpact(float impact, Vector2 direction, Contact contact, bool applyDamage = true)
        {
            float minImpact = 3.0f;

            if (impact < minImpact)
            {
                return;
            }

            contact.GetWorldManifold(out Vector2 tempNormal, out FixedArray2 <Vector2> worldPoints);
            Vector2 lastContactPoint = worldPoints[0];

            Vector2 impulse = direction * impact * 0.5f;

            impulse = impulse.ClampLength(5.0f);

            if (!MathUtils.IsValid(impulse))
            {
                string errorMsg =
                    "Invalid impulse in SubmarineBody.ApplyImpact: " + impulse +
                    ". Direction: " + direction + ", body position: " + Body.SimPosition + ", impact: " + impact + ".";
                if (GameMain.NetworkMember != null)
                {
                    errorMsg += GameMain.NetworkMember.IsClient ? " Playing as a client." : " Hosting a server.";
                }
                if (GameSettings.VerboseLogging)
                {
                    DebugConsole.ThrowError(errorMsg);
                }
                GameAnalyticsManager.AddErrorEventOnce(
                    "SubmarineBody.ApplyImpact:InvalidImpulse",
                    GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                    errorMsg);
                return;
            }

#if CLIENT
            if (Character.Controlled != null && Character.Controlled.Submarine == submarine)
            {
                GameMain.GameScreen.Cam.Shake = impact * 2.0f;
                float angularVelocity =
                    (lastContactPoint.X - Body.SimPosition.X) / ConvertUnits.ToSimUnits(submarine.Borders.Width / 2) * impulse.Y
                    - (lastContactPoint.Y - Body.SimPosition.Y) / ConvertUnits.ToSimUnits(submarine.Borders.Height / 2) * impulse.X;
                GameMain.GameScreen.Cam.AngularVelocity = MathHelper.Clamp(angularVelocity * 0.1f, -1.0f, 1.0f);
            }
#endif

            foreach (Character c in Character.CharacterList)
            {
                if (c.Submarine != submarine)
                {
                    continue;
                }
                if (impact > 2.0f)
                {
                    c.SetStun((impact - 2.0f) * 0.1f);
                }

                foreach (Limb limb in c.AnimController.Limbs)
                {
                    limb.body.ApplyLinearImpulse(limb.Mass * impulse, 20.0f);
                }
                c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse, 20.0f);
            }

            foreach (Item item in Item.ItemList)
            {
                if (item.Submarine != submarine || item.CurrentHull == null ||
                    item.body == null || !item.body.Enabled)
                {
                    continue;
                }

                item.body.ApplyLinearImpulse(item.body.Mass * impulse, 20.0f);
            }

            var damagedStructures = Explosion.RangedStructureDamage(
                ConvertUnits.ToDisplayUnits(lastContactPoint),
                impact * 50.0f,
                applyDamage ? impact * ImpactDamageMultiplier : 0.0f);

#if CLIENT
            //play a damage sound for the structure that took the most damage
            float     maxDamage          = 0.0f;
            Structure maxDamageStructure = null;
            foreach (KeyValuePair <Structure, float> structureDamage in damagedStructures)
            {
                if (maxDamageStructure == null || structureDamage.Value > maxDamage)
                {
                    maxDamage          = structureDamage.Value;
                    maxDamageStructure = structureDamage.Key;
                }
            }

            if (maxDamageStructure != null)
            {
                SoundPlayer.PlayDamageSound(
                    "StructureBlunt",
                    impact * 10.0f,
                    ConvertUnits.ToDisplayUnits(lastContactPoint),
                    MathHelper.Lerp(2000.0f, 10000.0f, (impact - minImpact) / 2.0f),
                    maxDamageStructure.Tags);
            }
#endif
        }
Beispiel #2
0
        private void ApplyImpact(float impact, Vector2 direction, Contact contact)
        {
            if (impact < 3.0f)
            {
                return;
            }

            Vector2 tempNormal;
            FixedArray2 <Vector2> worldPoints;

            contact.GetWorldManifold(out tempNormal, out worldPoints);

            Vector2 lastContactPoint = worldPoints[0];

            if (Character.Controlled != null && Character.Controlled.Submarine == submarine)
            {
                GameMain.GameScreen.Cam.Shake = impact * 2.0f;
            }

            Vector2 impulse = direction * impact * 0.5f;

            float length = impulse.Length();

            if (length > 5.0f)
            {
                impulse = (impulse / length) * 5.0f;
            }

            foreach (Character c in Character.CharacterList)
            {
                if (c.Submarine != submarine)
                {
                    continue;
                }

                if (impact > 2.0f)
                {
                    c.SetStun((impact - 2.0f) * 0.1f);
                }

                foreach (Limb limb in c.AnimController.Limbs)
                {
                    limb.body.ApplyLinearImpulse(limb.Mass * impulse);
                }

                c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse);
            }

            foreach (Item item in Item.ItemList)
            {
                if (item.Submarine != submarine || item.CurrentHull == null ||
                    item.body == null || !item.body.Enabled)
                {
                    continue;
                }

                item.body.ApplyLinearImpulse(item.body.Mass * impulse);
            }

            var damagedStructures = Explosion.RangedStructureDamage(ConvertUnits.ToDisplayUnits(lastContactPoint), impact * 50.0f, impact * ImpactDamageMultiplier);

#if CLIENT
            //play a damage sound for the structure that took the most damage
            float     maxDamage          = 0.0f;
            Structure maxDamageStructure = null;
            foreach (KeyValuePair <Structure, float> structureDamage in damagedStructures)
            {
                if (maxDamageStructure == null || structureDamage.Value > maxDamage)
                {
                    maxDamage          = structureDamage.Value;
                    maxDamageStructure = structureDamage.Key;
                }
            }

            if (maxDamageStructure != null)
            {
                SoundPlayer.PlayDamageSound(
                    "StructureBlunt",
                    impact * 10.0f,
                    ConvertUnits.ToDisplayUnits(lastContactPoint),
                    MathHelper.Clamp(maxDamage * 4.0f, 1000.0f, 4000.0f),
                    maxDamageStructure.Tags);
            }
#endif
        }
Beispiel #3
0
        private void ApplyImpact(float impact, Vector2 direction, Vector2 impactPos, bool applyDamage = true)
        {
            if (impact < MinCollisionImpact)
            {
                return;
            }

            Vector2 impulse = direction * impact * 0.5f;

            impulse = impulse.ClampLength(MaxCollisionImpact);

            if (!MathUtils.IsValid(impulse))
            {
                string errorMsg =
                    "Invalid impulse in SubmarineBody.ApplyImpact: " + impulse +
                    ". Direction: " + direction + ", body position: " + Body.SimPosition + ", impact: " + impact + ".";
                if (GameMain.NetworkMember != null)
                {
                    errorMsg += GameMain.NetworkMember.IsClient ? " Playing as a client." : " Hosting a server.";
                }
                if (GameSettings.VerboseLogging)
                {
                    DebugConsole.ThrowError(errorMsg);
                }
                GameAnalyticsManager.AddErrorEventOnce(
                    "SubmarineBody.ApplyImpact:InvalidImpulse",
                    GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                    errorMsg);
                return;
            }

#if CLIENT
            if (Character.Controlled != null && Character.Controlled.Submarine == submarine)
            {
                GameMain.GameScreen.Cam.Shake = impact * 2.0f;
                if (submarine.Info.Type == SubmarineInfo.SubmarineType.Player && !submarine.DockedTo.Any(s => s.Info.Type != SubmarineInfo.SubmarineType.Player))
                {
                    float angularVelocity =
                        (impactPos.X - Body.SimPosition.X) / ConvertUnits.ToSimUnits(submarine.Borders.Width / 2) * impulse.Y
                        - (impactPos.Y - Body.SimPosition.Y) / ConvertUnits.ToSimUnits(submarine.Borders.Height / 2) * impulse.X;
                    GameMain.GameScreen.Cam.AngularVelocity = MathHelper.Clamp(angularVelocity * 0.1f, -1.0f, 1.0f);
                }
            }
#endif

            foreach (Character c in Character.CharacterList)
            {
                if (c.Submarine != submarine)
                {
                    continue;
                }

                foreach (Limb limb in c.AnimController.Limbs)
                {
                    limb.body.ApplyLinearImpulse(limb.Mass * impulse, 10.0f);
                }
                c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse, 10.0f);

                bool holdingOntoSomething = false;
                if (c.SelectedConstruction != null)
                {
                    var controller = c.SelectedConstruction.GetComponent <Items.Components.Controller>();
                    holdingOntoSomething = controller != null && controller.LimbPositions.Any();
                }

                //stun for up to 1 second if the impact equal or higher to the maximum impact
                if (impact >= MaxCollisionImpact && !holdingOntoSomething)
                {
                    c.SetStun(Math.Min(impulse.Length() * 0.2f, 1.0f));
                }
            }

            foreach (Item item in Item.ItemList)
            {
                if (item.Submarine != submarine || item.CurrentHull == null ||
                    item.body == null || !item.body.Enabled)
                {
                    continue;
                }

                item.body.ApplyLinearImpulse(item.body.Mass * impulse, 10.0f);
            }

            var damagedStructures = Explosion.RangedStructureDamage(
                ConvertUnits.ToDisplayUnits(impactPos),
                impact * 50.0f,
                applyDamage ? impact * ImpactDamageMultiplier : 0.0f);

#if CLIENT
            //play a damage sound for the structure that took the most damage
            float     maxDamage          = 0.0f;
            Structure maxDamageStructure = null;
            foreach (KeyValuePair <Structure, float> structureDamage in damagedStructures)
            {
                if (maxDamageStructure == null || structureDamage.Value > maxDamage)
                {
                    maxDamage          = structureDamage.Value;
                    maxDamageStructure = structureDamage.Key;
                }
            }

            if (maxDamageStructure != null)
            {
                SoundPlayer.PlayDamageSound(
                    "StructureBlunt",
                    impact * 10.0f,
                    ConvertUnits.ToDisplayUnits(impactPos),
                    MathHelper.Lerp(2000.0f, 10000.0f, (impact - MinCollisionImpact) / 2.0f),
                    maxDamageStructure.Tags);
            }
#endif
        }
Beispiel #4
0
        partial void AddDamageProjSpecific(Vector2 simPosition, List <Affliction> afflictions, bool playSound, List <DamageModifier> appliedDamageModifiers)
        {
            float bleedingDamage   = character.CharacterHealth.DoesBleed ? afflictions.FindAll(a => a is AfflictionBleeding).Sum(a => a.GetVitalityDecrease(character.CharacterHealth)) : 0;
            float damage           = afflictions.FindAll(a => a.Prefab.AfflictionType == "damage").Sum(a => a.GetVitalityDecrease(character.CharacterHealth));
            float damageMultiplier = 1;

            foreach (DamageModifier damageModifier in appliedDamageModifiers)
            {
                damageMultiplier *= damageModifier.DamageMultiplier;
            }
            if (playSound)
            {
                string damageSoundType = (bleedingDamage > damage) ? "LimbSlash" : "LimbBlunt";
                foreach (DamageModifier damageModifier in appliedDamageModifiers)
                {
                    if (!string.IsNullOrWhiteSpace(damageModifier.DamageSound))
                    {
                        damageSoundType = damageModifier.DamageSound;
                        break;
                    }
                }
                SoundPlayer.PlayDamageSound(damageSoundType, Math.Max(damage, bleedingDamage), WorldPosition);
            }

            // Always spawn damage particles
            float damageParticleAmount = Math.Min(damage / 10, 1.0f) * damageMultiplier;

            foreach (ParticleEmitter emitter in character.DamageEmitters)
            {
                if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air)
                {
                    continue;
                }
                if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water)
                {
                    continue;
                }

                emitter.Emit(1.0f, WorldPosition, character.CurrentHull, amountMultiplier: damageParticleAmount);
            }

            if (bleedingDamage > 0)
            {
                float bloodParticleAmount = Math.Min(bleedingDamage / 5, 1.0f) * damageMultiplier;
                float bloodParticleSize   = MathHelper.Clamp(bleedingDamage / 5, 0.1f, 1.0f);

                foreach (ParticleEmitter emitter in character.BloodEmitters)
                {
                    if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air)
                    {
                        continue;
                    }
                    if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water)
                    {
                        continue;
                    }

                    emitter.Emit(1.0f, WorldPosition, character.CurrentHull, sizeMultiplier: bloodParticleSize, amountMultiplier: bloodParticleAmount);
                }

                if (bloodParticleAmount > 0 && character.CurrentHull != null && !string.IsNullOrEmpty(character.BloodDecalName))
                {
                    character.CurrentHull.AddDecal(character.BloodDecalName, WorldPosition, MathHelper.Clamp(bloodParticleSize, 0.5f, 1.0f));
                }
            }
        }
Beispiel #5
0
        public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, bool playSound)
        {
            List <DamageModifier> appliedDamageModifiers = new List <DamageModifier>();

            foreach (DamageModifier damageModifier in damageModifiers)
            {
                if (damageModifier.DamageType == DamageType.None)
                {
                    continue;
                }
                if (damageModifier.DamageType.HasFlag(damageType) && SectorHit(damageModifier.ArmorSector, position))
                {
                    appliedDamageModifiers.Add(damageModifier);
                }
            }

            foreach (WearableSprite wearable in wearingItems)
            {
                foreach (DamageModifier damageModifier in wearable.WearableComponent.DamageModifiers)
                {
                    if (damageModifier.DamageType == DamageType.None)
                    {
                        continue;
                    }
                    if (damageModifier.DamageType.HasFlag(damageType) && SectorHit(damageModifier.ArmorSector, position))
                    {
                        appliedDamageModifiers.Add(damageModifier);
                    }
                }
            }

            foreach (DamageModifier damageModifier in appliedDamageModifiers)
            {
                amount         *= damageModifier.DamageMultiplier;
                bleedingAmount *= damageModifier.BleedingMultiplier;
            }

#if CLIENT
            if (playSound)
            {
                string damageSoundType = (damageType == DamageType.Blunt) ? "LimbBlunt" : "LimbSlash";

                foreach (DamageModifier damageModifier in appliedDamageModifiers)
                {
                    if (!string.IsNullOrWhiteSpace(damageModifier.DamageSound))
                    {
                        damageSoundType = damageModifier.DamageSound;
                        break;
                    }
                }

                SoundPlayer.PlayDamageSound(damageSoundType, amount, position);
            }

            if (character.UseBloodParticles)
            {
                float bloodParticleAmount = bleedingAmount <= 0.0f ? 0 : (int)Math.Min(amount / 5, 10);
                float bloodParticleSize   = MathHelper.Clamp(amount / 50.0f, 0.1f, 1.0f);

                for (int i = 0; i < bloodParticleAmount; i++)
                {
                    var blood = GameMain.ParticleManager.CreateParticle(inWater ? "waterblood" : "blood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull);
                    if (blood != null)
                    {
                        blood.Size *= bloodParticleSize;
                    }
                }

                if (bloodParticleAmount > 0 && character.CurrentHull != null)
                {
                    character.CurrentHull.AddDecal("blood", WorldPosition, MathHelper.Clamp(bloodParticleSize, 0.5f, 1.0f));
                }
            }
#endif

            if (damageType == DamageType.Burn)
            {
                Burnt += amount * 10.0f;
            }

            damage += Math.Max(amount, bleedingAmount) / character.MaxHealth * 100.0f;

            return(new AttackResult(amount, bleedingAmount, appliedDamageModifiers));
        }
Beispiel #6
0
        public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, bool playSound)
        {
            bool  hitArmor        = false;
            float totalArmorValue = 0.0f;

            if (armorValue > 0.0f && SectorHit(armorSector, position))
            {
                hitArmor         = true;
                totalArmorValue += armorValue;
            }

            foreach (WearableSprite wearable in wearingItems)
            {
                if (wearable.WearableComponent.ArmorValue > 0.0f &&
                    SectorHit(wearable.WearableComponent.ArmorSectorLimits, position))
                {
                    hitArmor         = true;
                    totalArmorValue += wearable.WearableComponent.ArmorValue;
                }
            }

            if (hitArmor)
            {
                totalArmorValue = Math.Max(totalArmorValue, 0.0f);

                amount         = Math.Max(0.0f, amount - totalArmorValue);
                bleedingAmount = Math.Max(0.0f, bleedingAmount - totalArmorValue);
            }

#if CLIENT
            if (playSound)
            {
                DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash;
                if (hitArmor)
                {
                    damageSoundType = DamageSoundType.LimbArmor;
                }

                SoundPlayer.PlayDamageSound(damageSoundType, amount, position);
            }

            float bloodParticleAmount = hitArmor || bleedingAmount <= 0.0f ? 0 : (int)Math.Min(amount / 5, 10);
            float bloodParticleSize   = MathHelper.Clamp(amount / 50.0f, 0.1f, 1.0f);

            for (int i = 0; i < bloodParticleAmount; i++)
            {
                var blood = GameMain.ParticleManager.CreateParticle(inWater ? "waterblood" : "blood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull);
                if (blood != null)
                {
                    blood.Size *= bloodParticleSize;
                }
            }

            if (bloodParticleAmount > 0 && character.CurrentHull != null)
            {
                character.CurrentHull.AddDecal("blood", WorldPosition, MathHelper.Clamp(bloodParticleSize, 0.5f, 1.0f));
            }
#endif

            damage += Math.Max(amount, bleedingAmount) / character.MaxHealth * 100.0f;

            return(new AttackResult(amount, bleedingAmount, hitArmor));
        }
Beispiel #7
0
        public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, bool playSound)
        {
            DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash;

            bool  hitArmor        = false;
            float totalArmorValue = 0.0f;

            if (armorValue > 0.0f && SectorHit(armorSector, position))
            {
                hitArmor         = true;
                totalArmorValue += armorValue;
            }

            foreach (WearableSprite wearable in wearingItems)
            {
                if (wearable.WearableComponent.ArmorValue > 0.0f &&
                    SectorHit(wearable.WearableComponent.ArmorSectorLimits, position))
                {
                    hitArmor         = true;
                    totalArmorValue += wearable.WearableComponent.ArmorValue;
                }
            }


            if (hitArmor)
            {
                totalArmorValue = Math.Max(totalArmorValue, 0.0f);

                damageSoundType = DamageSoundType.LimbArmor;
                amount          = Math.Max(0.0f, amount - totalArmorValue);
                bleedingAmount  = Math.Max(0.0f, bleedingAmount - totalArmorValue);
            }

            if (playSound)
            {
                SoundPlayer.PlayDamageSound(damageSoundType, amount, position);
            }

            //Bleeding += bleedingAmount;
            //Damage += amount;

            float bloodAmount = hitArmor || bleedingAmount <= 0.0f ? 0 : (int)Math.Min((int)(amount * 2.0f), 20);

            for (int i = 0; i < bloodAmount; i++)
            {
                Vector2 particleVel = SimPosition - position;
                if (particleVel != Vector2.Zero)
                {
                    particleVel = Vector2.Normalize(particleVel);
                }

                GameMain.ParticleManager.CreateParticle("blood",
                                                        WorldPosition,
                                                        particleVel * Rand.Range(100.0f, 300.0f), 0.0f, character.AnimController.CurrentHull);
            }

            for (int i = 0; i < bloodAmount / 2; i++)
            {
                GameMain.ParticleManager.CreateParticle("waterblood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull);
            }

            damage += Math.Max(amount, bleedingAmount) / character.MaxHealth * 100.0f;


            return(new AttackResult(amount, bleedingAmount, hitArmor));
        }