Exemplo n.º 1
0
        public static void Break(Model model, Vector3 pos, Rotation rot, Result result = null, PhysicsBody sourcePhysics = null)
        {
            if (model == null || model.IsError)
            {
                return;
            }

            var breakList = model.GetBreakPieces();

            if (breakList == null || breakList.Length <= 0)
            {
                return;
            }

            foreach (var piece in breakList)
            {
                var mdl    = Model.Load(piece.Model);
                var offset = mdl.GetAttachment("placementOrigin");

                var gib = new Prop
                {
                    WorldPos       = pos + rot * (piece.Offset - offset.Pos),
                    WorldRot       = rot,
                    CollisionGroup = piece.GetCollisionGroup(),
                };

                gib.SetModel(mdl);

                var phys = gib.PhysicsBody;
                if (phys != null)
                {
                    // Apply the velocity at the parent object's position
                    if (sourcePhysics != null)
                    {
                        phys.Velocity        = sourcePhysics.GetVelocityAtPoint(phys.Pos);
                        phys.AngularVelocity = sourcePhysics.AngularVelocity;
                    }
                }

                if (piece.FadeTime > 0)
                {
                    _ = FadeAsync(gib, piece.FadeTime);
                }

                result?.AddProp(gib);
            }
        }
Exemplo n.º 2
0
        private void UpdateBody(Entity ent, PhysicsBody body)
        {
            var waterDensity = 1000;

            var oldLevel     = body.WaterLevel;
            var density      = body.Density;
            var waterSurface = WaterEntity.WorldPos;
            var bounds       = body.GetBounds();
            var velocity     = body.Velocity;
            var pos          = bounds.Center;

            pos.z = waterSurface.z;

            var densityDiff = density - waterDensity;
            var volume      = bounds.Volume;
            var level       = waterSurface.z.LerpInverse(bounds.Mins.z, bounds.Maxs.z, true);

            body.WaterLevel = level;

            if (ent.IsClientOnly == Host.IsClient)
            {
                var bouyancy = densityDiff.LerpInverse(0.0f, -300f);
                bouyancy = MathF.Pow(bouyancy, 0.1f);

                //	DebugOverlay.Text( pos, $"{bouyancy}", Host.Color, 0.1f, 10000 );

                if (bouyancy <= 0)
                {
                    body.GravityScale = 1.0f - body.WaterLevel * 0.8f;
                }
                else
                {
                    var point = bounds.Center;
                    if (level < 1.0f)
                    {
                        point.z = bounds.Mins.z - 100;
                    }
                    var closestpoint = body.FindClosestPoint(point);

                    float depth = (waterSurface.z - bounds.Maxs.z) / 100.0f;
                    depth = depth.Clamp(1.0f, 10.0f);
                    //DebugOverlay.Text( point, $"{depth}", Host.Color, 0.1f, 10000 );
                    //DebugOverlay.Line( point, closestpoint, 1.0f );

                    //body.ApplyImpulseAt( closestpoint, (Vector3.Up * volume * level * bouyancy * 0.0001f) );
                    body.ApplyForceAt(closestpoint, (Vector3.Up * volume * level * bouyancy * 0.05f * depth));

                    //body.ApplyImpulseAt( )
                    body.GravityScale = 1.0f - MathF.Pow(body.WaterLevel.Clamp(0, 0.5f) * 2.0f, 0.5f);
                }

                body.LinearDrag  = body.WaterLevel * WaterThickness;
                body.AngularDrag = body.WaterLevel * WaterThickness * 0.5f;
            }

            if (Host.IsClient)
            {
                if (oldLevel == 0)
                {
                    return;
                }

                var change = MathF.Abs(oldLevel - level);

                //Log.Info( $"{change}" );

                if (change > 0.001f && body.LastWaterEffect > 0.2f)
                {
                    if (oldLevel < 0.3f && level >= 0.35f)
                    {
                        var particle = Particles.Create("particles/water_splash.vpcf", pos);
                        particle.SetForward(0, Vector3.Up);
                        body.LastWaterEffect = 0;

                        Sound.FromWorld("water_splash_medium", pos);
                    }

                    if (velocity.Length > 2f && velocity.z > -10 && velocity.z < 10)
                    {
                        var particle = Particles.Create("particles/water_bob.vpcf", pos);
                        particle.SetForward(0, Vector3.Up);
                        body.LastWaterEffect = 0;
                    }
                }
            }
        }
Exemplo n.º 3
0
        public void Weld(Prop prop)
        {
            Host.AssertServer();

            if (!prop.IsValid())
            {
                return;
            }

            // Don't weld myself to myself, stupid
            if (prop == this)
            {
                return;
            }

            // Don't weld myself twice, stupid
            if (prop.weldParent == this || weldParent == prop)
            {
                return;
            }

            // Only allow welding of two root props
            if (Parent != null || prop.Parent != null)
            {
                return;
            }

            // Only allow welding of props that have physics bodies
            if (!PhysicsBody.IsValid() || !prop.PhysicsBody.IsValid())
            {
                return;
            }

            // Only allow welding of props that have a single body
            if (PhysicsGroup.BodyCount > 1 || prop.PhysicsGroup.BodyCount > 1)
            {
                return;
            }

            if (prop.childrenProps.Count > 0)
            {
                // Reweld everything to this
                prop.Unweld(true, this);
            }

            var thisBody  = PhysicsBody;
            var otherBody = prop.PhysicsBody;

            // We want traces to now think the other body is now this body
            otherBody.Parent = thisBody;

            // Disable solid collisions on other prop so things attached with constraints wont collide with it
            prop.EnableSolidCollisions = false;

            // Merge all other shapes from other body into this body
            for (int shapeIndex = 0; shapeIndex < otherBody.ShapeCount; ++shapeIndex)
            {
                var clonedShape = thisBody.AddCloneShape(otherBody.GetShape(shapeIndex));

                // We don't want to be able to trace this cloned shape (but we want it to generate contacts)
                clonedShape.DisableTraceQuery();

                // Keep track of the cloned shape so they can be removed when unwelded
                prop.clonedShapes.Add(clonedShape);
            }

            // Visually parent other prop to this prop
            prop.Parent     = this;
            prop.weldParent = this;

            // Keep track of welded children
            childrenProps.Add(prop);
        }
Exemplo n.º 4
0
 public static bool IsValid(this PhysicsBody body)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 5
0
        public void Unweld(bool reweldChildren = false, Prop reweldProp = null)
        {
            if (!weldParent.IsValid())
            {
                // Unweld our group, reweld them to the first child or something else
                if (childrenProps.Count > 0)
                {
                    // Create a copy of the child list so it doesn't get invalidated
                    var chilrenPropsCopy = childrenProps.ToList();

                    // Unweld all children
                    foreach (var childProp in chilrenPropsCopy)
                    {
                        childProp.Unweld();
                    }

                    if (!reweldChildren)
                    {
                        return;
                    }

                    if (!reweldProp.IsValid())
                    {
                        // If no reweld prop has been specified, reweld everything to the first child
                        // So that the child becomes the new weld parent
                        reweldProp = chilrenPropsCopy.First();
                    }

                    // For whatever reason, we don't have a prop to reweld to, bail
                    if (!reweldProp.IsValid())
                    {
                        return;
                    }

                    // Reweld all children to the new parent
                    foreach (var childProp in chilrenPropsCopy)
                    {
                        if (childProp != reweldProp)
                        {
                            reweldProp.Weld(childProp);
                        }
                    }
                }

                return;
            }

            // Remove us from the weld parent
            weldParent.childrenProps.Remove(this);

            // If weld parent has no physics body, it's probably pending destroy
            if (weldParent.PhysicsBody.IsValid())
            {
                // Remove all of our cloned shapes from the weld parent
                foreach (var shape in clonedShapes)
                {
                    weldParent.PhysicsBody.RemoveShape(shape);
                }
            }

            clonedShapes.Clear();

            // If there's no physics body, we're probably pending destroy
            if (PhysicsBody.IsValid())
            {
                Parent                = null;
                PhysicsBody.Parent    = null;
                EnableSolidCollisions = true;
            }

            weldParent = null;
        }