private void ApplyVolumetriDamageToGrid(MyGridExplosion damageInfo, long attackerId) { var damagedBlocks = damageInfo.DamagedBlocks; var explodedBlocks = damageInfo.AffectedCubeBlocks; var explodedGrids = damageInfo.AffectedCubeGrids; VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("foreach (var damagedBlock in damagedBlocks)"); if (MyDebugDrawSettings.DEBUG_DRAW_VOLUMETRIC_EXPLOSION_COLORING) { foreach (var explodedBlock in explodedBlocks) { explodedBlock.CubeGrid.ChangeColor(explodedBlock, new Vector3(0.66f, 1f, 1f)); } foreach (var damagedBlock in damagedBlocks) { float hue = 1f - damagedBlock.Value / damageInfo.Damage; damagedBlock.Key.CubeGrid.ChangeColor(damagedBlock.Key, new Vector3(hue / 3f, 1.0f, 0.5f)); } } else { foreach (var damagedBlock in damagedBlocks) { var cubeBlock = damagedBlock.Key; if (cubeBlock.FatBlock != null && cubeBlock.FatBlock.MarkedForClose) continue; if (!cubeBlock.CubeGrid.BlocksDestructionEnabled) continue; // Allow mods to modify damage. This will cause a double call. Once here and once in the DoDamage, but only real way to do a check here MyDamageInformation checkInfo = new MyDamageInformation(false, damagedBlock.Value, MyDamageType.Explosion, attackerId); if (cubeBlock.UseDamageSystem) MyDamageSystem.Static.RaiseBeforeDamageApplied(cubeBlock, ref checkInfo); if (cubeBlock.FatBlock == null && cubeBlock.Integrity / cubeBlock.DeformationRatio < checkInfo.Amount) { VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("RemoveBlock"); cubeBlock.CubeGrid.RemoveDestroyedBlock(cubeBlock); VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); } else { VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyDestructionDeformation"); float damage = damagedBlock.Value; if (cubeBlock.FatBlock != null) { damage *= 7f; } (cubeBlock as IMyDestroyableObject).DoDamage(damage, MyDamageType.Explosion, true); if (!cubeBlock.IsDestroyed) { cubeBlock.CubeGrid.ApplyDestructionDeformation(cubeBlock); } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); } foreach (var neighbour in cubeBlock.Neighbours) { neighbour.CubeGrid.Physics.AddDirtyBlock(neighbour); } cubeBlock.CubeGrid.Physics.AddDirtyBlock(cubeBlock); } } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); var sphere = damageInfo.Sphere; if (!MyDebugDrawSettings.DEBUG_DRAW_VOLUMETRIC_EXPLOSION_COLORING) { foreach (var grid in explodedGrids) { /*VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("UpdateDirty"); grid.UpdateDirty(); VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();*/ VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("CreateExplosionDebris"); if (m_explosionInfo.HitEntity == grid) { BoundingBoxD aabb = BoundingBoxD.CreateFromSphere(new BoundingSphereD(sphere.Center, sphere.Radius * 1.5f)); MyDebris.Static.CreateExplosionDebris(ref sphere, grid, ref aabb, 0.5f, false); } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); } } }
private void ApplyVolumetricExplosionOnEntities(ref MyExplosionInfo m_explosionInfo, List<MyEntity> entities, MyGridExplosion explosionDamageInfo) { Debug.Assert(Sync.IsServer); float explosionRadiusR = (float)(1/explosionDamageInfo.Sphere.Radius); foreach (var entity in entities) { if (entity is MyCubeGrid) //we already have blocks continue; var ammoBase = entity as MyAmmoBase; if (!(entity is IMyDestroyableObject) && ammoBase == null && !m_explosionInfo.ApplyForceAndDamage) continue; //Special case for characters in cockpits var character = entity as MyCharacter; if (character != null) { var cockpit = character.IsUsing as MyCockpit; if (cockpit != null) { if (explosionDamageInfo.DamagedBlocks.ContainsKey(cockpit.SlimBlock)) { float damageRemaining = explosionDamageInfo.DamageRemaining[cockpit.SlimBlock].DamageRemaining; character.DoDamage(damageRemaining, MyDamageType.Explosion, true, attackerId: m_explosionInfo.OwnerEntity != null ? m_explosionInfo.OwnerEntity.EntityId : 0); } continue; } } //ProfilerShort.Begin("ComputeDamageForEntity"); //var raycastDamageInfo = explosionDamageInfo.ExplosionDamage.ComputeDamageForEntity(entity.PositionComp.WorldAABB.Center); //ProfilerShort.End(); //float damage = raycastDamageInfo.DamageRemaining; float entityDistanceToExplosion = (float)(entity.PositionComp.WorldAABB.Center - explosionDamageInfo.Sphere.Center).Length(); //damage *= (float)(1 - (entityDistanceToExplosion - raycastDamageInfo.DistanceToExplosion) / (explosionDamageInfo.Sphere.Radius - raycastDamageInfo.DistanceToExplosion)); float damage = explosionDamageInfo.Damage * (1 - (entityDistanceToExplosion * explosionRadiusR)); if (damage <= 0f) continue; if (ammoBase != null) { Debug.Assert(Vector3.DistanceSquared(m_explosionSphere.Center, ammoBase.PositionComp.GetPosition()) < 4 * m_explosionSphere.Radius * m_explosionSphere.Radius); ammoBase.MarkedToDestroy = true; ammoBase.Explode(); } if (entity.Physics != null && entity.Physics.Enabled) { float forceMultiplier = damage / 50000f; // Throws surrounding objects away from centre of the explosion. if (m_explosionInfo.ApplyForceAndDamage) { m_explosionInfo.StrengthImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_IMPULSE * (float)m_explosionSphere.Radius; m_explosionInfo.StrengthAngularImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_ANGULAR_IMPULSE; m_explosionInfo.HitEntity = m_explosionInfo.HitEntity != null ? m_explosionInfo.HitEntity.GetBaseEntity() : null; VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyExplosionForceAndDamage"); if (entity.PositionComp.WorldAABB.Center != m_explosionSphere.Center) { entity.Physics.AddForce( MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, forceMultiplier * m_explosionInfo.StrengthImpulse * Vector3.Normalize(entity.PositionComp.WorldAABB.Center - m_explosionSphere.Center), entity.PositionComp.WorldAABB.Center, null); } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); } } var destroyableObj = entity as IMyDestroyableObject; if (destroyableObj == null) continue; ProfilerShort.Begin("DoDamage"); destroyableObj.DoDamage(damage, MyDamageType.Explosion, true, attackerId: m_explosionInfo.OwnerEntity != null ? m_explosionInfo.OwnerEntity.EntityId : 0); ProfilerShort.End(); } }