public void Explode(Vector3 Position) { foreach (Node Body in AffectedBodies) { if (Body is IPushable Pushable) { PhysicsDirectSpaceState State = GetWorld().DirectSpaceState; Godot.Collections.Dictionary Results = State.IntersectRay(Position, Pushable.Translation, new Godot.Collections.Array() { Pushable }, 1); if (Results.Count > 0) { continue; } float Distance = Clamp(Position.DistanceTo(Pushable.Translation), 1, MaxRocketDistance); float Power = LogBase(-Distance + MaxRocketDistance + 1, 2) / LogBase(MaxRocketDistance + 1, 2); Vector3 Push = ((Pushable.Translation - Position) / MaxRocketDistance).Normalized() * MaxRocketPush * Power; { Vector3 Flat = Push.Flattened(); Flat *= RocketHorizontalMultiplyer; Push.x = Flat.x; Push.z = Flat.z; } Push.y *= RocketVerticalMultiplyer; Pushable.ApplyPush(Push); } } AffectedBodies.Clear(); var ExplodeSfxInstance = (AudioStreamPlayer3D)ExplodeSfx.Instance(); ExplodeSfxInstance.Play(); ExplodeSfxInstance.Translation = Position; World.EntitiesRoot.AddChild(ExplodeSfxInstance); var ParticleSystem = (CPUParticles)ExplodeParticles.Instance(); ParticleSystem.Translation = Position; ParticleSystem.Emitting = true; World.EntitiesRoot.AddChild(ParticleSystem); QueueFree(); }
public void ServerExplode(Vector3 Position) { Assert.ActualAssert(Net.Work.IsNetworkServer()); var WithinArea = World.GetEntitiesWithinArea(Position, MaxRocketDistance); foreach (Node Body in WithinArea) { if (Body is IPushable Pushable) { PhysicsDirectSpaceState State = GetWorld().DirectSpaceState; Godot.Collections.Dictionary Results = State.IntersectRay(Position, Pushable.Translation, new Godot.Collections.Array() { Pushable }, 1); if (Results.Count > 0) { continue; } Vector3 Push = CalculatePush(Pushable, Position); if (Pushable is Player Plr && Game.PossessedPlayer.HasValue && Plr != Game.PossessedPlayer.ValueOrFailure()) { continue; } Pushable.ApplyPush(Push); Entities.SendPush(Pushable, Push); } } ExplodeSoundVisual(Position); Entities.SendDestroy(Name, Position); QueueFree(); }