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 }
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 }
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 }
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)); } } }
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)); }
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)); }
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)); }