// Modified from Prop.cs to allow tweaking through code/cvar rather than having to go through model doc. private async Task Explode() { try { IsArmed = false; await Task.DelaySeconds(0.1f); Sound.FromWorld("rust_pumpshotgun.shootdouble", PhysicsBody.MassCenter); Particles.Create("particles/explosion_fireball.vpcf", PhysicsBody.MassCenter); Vector3 sourcePos = PhysicsBody.MassCenter; IEnumerable <Entity> overlaps = FindInSphere(sourcePos, BOMB_RADIUS); foreach (Entity overlap in overlaps) { if (overlap is not ModelEntity ent || !ent.IsValid() || ent.LifeState != LifeState.Alive || !ent.PhysicsBody.IsValid() || ent.IsWorld) { continue; } Vector3 targetPos = ent.PhysicsBody.MassCenter; float dist = Vector3.DistanceBetween(sourcePos, targetPos); if (dist > BOMB_RADIUS) { continue; } TraceResult tr = Trace.Ray(sourcePos, targetPos) .Ignore(this) .WorldOnly() .Run(); if (tr.Fraction < 1.0f) { continue; } float distanceMul = 1.0f - Math.Clamp(dist / BOMB_RADIUS, 0.0f, 1.0f); float damage = BOMB_DAMAGE * distanceMul; float force = BOMB_FORCE * distanceMul * ent.PhysicsBody.Mass; Vector3 forceDir = (targetPos - sourcePos).Normal; ent.TakeDamage(DamageInfo.Explosion(sourcePos, forceDir * force, damage) .WithAttacker(this)); } } catch (Exception e) { if (e.Message.Trim() == "A task was canceled.") { return; } Log.Error($"[TASK] {e.Message}: {e.StackTrace}"); } base.OnKilled(); }
private void Explode() { // TODO: Rework this effect and damage var explosionBehavior = new ModelExplosionBehavior() { Sound = "", Effect = "particles/prophunt/explosion.vpcf", Damage = 100f, Radius = 100f, Force = 20f }; if (!string.IsNullOrWhiteSpace(explosionBehavior.Sound)) { Sound.FromWorld(explosionBehavior.Sound, PhysicsBody.MassCenter); } if (!string.IsNullOrWhiteSpace(explosionBehavior.Effect)) { Particles.Create(explosionBehavior.Effect, PhysicsBody.MassCenter); } if (explosionBehavior.Radius > 0.0f) { var sourcePos = PhysicsBody.MassCenter; var overlaps = Physics.GetEntitiesInSphere(sourcePos, explosionBehavior.Radius); foreach (var overlap in overlaps) { if (overlap is not ModelEntity ent || !ent.IsValid()) { continue; } if (ent.LifeState != LifeState.Alive) { continue; } if (!ent.PhysicsBody.IsValid()) { continue; } if (ent.IsWorld) { continue; } var targetPos = ent.PhysicsBody.MassCenter; var dist = Vector3.DistanceBetween(sourcePos, targetPos); if (dist > explosionBehavior.Radius) { continue; } var tr = Trace.Ray(sourcePos, targetPos) .Ignore(this) .WorldOnly() .Run(); if (tr.Fraction < 1.0f) { continue; } var distanceMul = 1.0f - Math.Clamp(dist / explosionBehavior.Radius, 0.0f, 1.0f); var damage = explosionBehavior.Damage * distanceMul; var force = (explosionBehavior.Force * distanceMul) * ent.PhysicsBody.Mass; var forceDir = (targetPos - sourcePos).Normal; ent.TakeDamage(DamageInfo.Explosion(sourcePos, forceDir * force, damage) .WithAttacker(Owner)); } } }