Esempio n. 1
0
        // Override Init to set up event handlers and start coroutines.
        public override void Init()
        {
            // When unhandled exceptions occur, they may be caught with this event handler.
            // Certain exceptions may not be recoverable at all and may cause the script to
            // immediately be removed. This will also break out of any loops in coroutines!
            Script.UnhandledException += UnhandledException;

            // If the object had its components set in the editor they should now have the member initialized
            // [Editor support for Component types is not yet implemented]
            // The component can also be found dynamically
            if (RigidBody == null)
            {
                if (!ObjectPrivate.TryGetFirstComponent(out RigidBody))
                {
                    // Since object scripts are initialized when the scene loads, no one will actually see this message.
                    Log.Write("There is no RigidBodyComponent attached to this object.");
                    return;
                }
            }

            // Initialize the Home position
            Home = RigidBody.GetPosition();

            // StartCoroutine will queue CheckForCollisions to run
            // Arguments after the coroutine method are passed as arguments to the method.
            StartCoroutine(CheckForCollisions);

            // Clamp our chaos to [0,1]
            StartCoroutine(Movement, Speed, Chaos.Clamp(0.0f, 1.0f));
        }
Esempio n. 2
0
        // This is a lot of complex math on choosing some "random" movement, keeping it near home and handling error cases.
        private void Movement(float speed, float chaos)
        {
            // Initialize a random number generator.
            Random rng = new Random();

            // Pick a direction to start with - mostly in the X/Y plane, but just a little push up.
            Direction = new Sansar.Vector((float)(0.5 - rng.NextDouble()), (float)(0.5 - rng.NextDouble()), 0.02f, 0.0f);

            // This will just continually try to move the object (the Wait at the bottom is important!)
            while (true)
            {
                // Calculate how far we are from our home point.
                float distance = (RigidBody.GetPosition() - Home).Length();

                // Pick a new direction based on Chaos level, or if we have wandered off too far
                if (rng.NextDouble() <= Chaos || distance > Range)
                {
                    // If we are far from home point us at home before adjusting the position.
                    if (distance > Range)
                    {
                        // Move toward the center.
                        Direction = (Home - RigidBody.GetPosition()).Normalized();

                        // Note: still letting the randomize adjust the heading.
                    }

                    // This is the most bogus direction adjusting logic you will see today.
                    Direction.X = Direction.X + (float)(0.5 - rng.NextDouble());
                    Direction.Y = Direction.Y + (float)(0.5 - rng.NextDouble());
                    Direction.Z = 0.02f;
                    Direction   = Direction.Normalized();
                }

                // AddLinearImpulse can be picky on accepted values, especially if any math above breaks or the speed is set too high.
                // It will throw an exception if it doesn't like it. This will just skip
                try
                {
                    Log.Write("PUSH! " + Direction.ToString() + " * " + speed + " => " + (Direction * speed).ToString());
                    RigidBody.AddLinearImpulse(Direction * speed);
                }
                catch (Exception e)
                {
                    Log.Write("Exception " + e.GetType().ToString() + " in AddLinearImpulse for value: " + (Direction * speed).ToString());

                    // That direction was bad, so lets choose a new one.
                    Direction.X = (float)(0.5 - rng.NextDouble());
                    Direction.Y = (float)(0.5 - rng.NextDouble());
                    Direction.Z = 0.02f;
                    Direction   = Direction.Normalized();
                }

                // Wait after each push for between 0.5 and 1.5 seconds.
                Wait(TimeSpan.FromSeconds(0.5 + rng.NextDouble()));
            }
        }
Esempio n. 3
0
        // Putting the collision event into a coroutine helps to reduce duplicate events
        // After every collision we give a small bump then sleep this coroutine before waiting on another collision.
        // An Action event handler would get a large queue of events for colliding with the same object which is harder to deal with.
        private void CheckForCollisions()
        {
            while (true)
            {
                // This will block the coroutine until a collision happens
                CollisionData data = (CollisionData)WaitFor(RigidBody.Subscribe, CollisionEventType.AllCollisions, Sansar.Script.ComponentId.Invalid);

                if (data.HitObject == null)
                {
                    // This is slightly more common, collided with something were no object was given from the physics system.
                    // Again, just sleep a little and continue.
                    Log.Write("Hit nothing? " + data.HitComponentId);
                    Wait(TimeSpan.FromSeconds(0.2));
                    continue;
                }

                // This position - collision object position gives a vector away from the object we collided with.
                // This is not "away from the collision point". Complex shapes or large objects will confuse this simple math.
                Sansar.Vector direction = ObjectPrivate.Position - data.HitObject.Position;
                direction = direction.Normalized();

                if (Math.Abs(direction.X) < 0.1 && Math.Abs(direction.Y) < 0.1)
                {
                    // This object is mostly above or below us: it is probably the floor.
                    // This is overly simplistic and will fail for large objects or sloped floors.
                    // Sleep a little and continue.
                    Wait(TimeSpan.FromSeconds(0.2));
                    continue;
                }

                // direction is now pointing _away_ from what we collided with, set it as our Direction for Movement.
                Direction = direction;

                try
                {
                    // Apply an immediate bump away from what we collided with.
                    Log.Write("Bump! " + Direction.ToString() + " * " + Speed + " => " + (Direction * Speed).ToString());
                    RigidBody.AddLinearImpulse(Direction * Speed);
                }
                catch (Exception e)
                {
                    Log.Write("Collision Exception " + e.GetType().ToString() + " in AddLinearImpulse for value: " + (Direction * Speed).ToString());
                }

                // Wait before checking for more collisions to avoid duplicate collisions and give a chance to separate from the other object.
                Wait(TimeSpan.FromSeconds(0.2));
            }
        }
Esempio n. 4
0
 public override void Init()
 {
     if (RigidBody == null)
     {
         if (!ObjectPrivate.TryGetFirstComponent(out RigidBody))
         {
             return;
         }
     }
     lightPositionOffset = new Sansar.Vector(0, 0, 2);
     startRot            = RigidBody.GetOrientation();
     //we want this to float
     RigidBody.SetMass(0);
     //the default light when you add it is off by -90 degrees
     lightOnObjectDirection = Quaternion.FromEulerAngles(new Sansar.Vector(0, 0, (float)(Math.PI / -2.0), 0));
     StartCoroutine(UpdateLoop);
 }
Esempio n. 5
0
        private void SetRandomColorAndIntensityOfAllLights()
        {
            foreach (var light in lights)
            {
                // Pick a random color but don't let it be too dark or else the relative intensity doesn't work well
                Sansar.Vector randomVector = new Sansar.Vector((float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble());
                if (randomVector.LengthSquared() < 0.5f)
                {
                    randomVector = randomVector.Normalized();
                }
                Sansar.Color randomColor = new Sansar.Color(randomVector.X, randomVector.Y, randomVector.Z);

                // Pick a random intensity from min to max
                float randomIntensity = randomMinIntensity + (randomMaxIntensity - randomMinIntensity) * (float)rnd.NextDouble();

                light.SetColorAndIntensity(randomColor, randomIntensity);
            }
        }
Esempio n. 6
0
 private void UpdateLoop()
 {
     while (true)
     {
         //this is only one object, so we have it hard coded in to only follow the first agent., you could split this up later
         Boolean got1 = false;
         foreach (AgentPrivate agent in ScenePrivate.GetAgents())
         {
             if (got1 == false)
             {
                 ObjectPrivate      agentObejct = ScenePrivate.FindObject(agent.AgentInfo.ObjectId);
                 AnimationComponent anim;
                 if (agentObejct.TryGetFirstComponent(out anim))
                 {
                     Sansar.Vector fwd = anim.GetVectorAnimationVariable("LLCameraForward");
                     //Builds a rotation from the fwd vector
                     Quaternion newRot = Quaternion.FromLook(fwd, Sansar.Vector.Up);
                     //This is a basic check to make sure the camera rotation isnt all 0s
                     if (fwd.LengthSquared() > 0)
                     {
                         try
                         {
                             RigidBody.SetAngularVelocity(Vector.Zero);
                             RigidBody.SetLinearVelocity(Vector.Zero);
                             RigidBody.SetPosition(agentObejct.Position + lightPositionOffset);
                             //Order of multiplication matters here I think, start with the base rotation,
                             //multiply by and base offset rotation for the light, then multiply by the rotation of the fwd
                             //Keep in mind that multiplying quad A by quad b will rotate quad A by quad b
                             RigidBody.SetOrientation(QuaternionToVector(startRot * lightOnObjectDirection * newRot).Normalized());
                         }
                         catch
                         {
                         }
                     }
                 }
                 got1 = true;
             }
         }
         Wait(TimeSpan.FromSeconds(.05));
     }
 }
    public void OnFire(AnimationComponent animationComponent)
    {
        if (RezThrottled == true)
        {   // TODO: Play a "click" / misfire sound.
            return;
        }

        ObjectPrivate characterObject = ScenePrivate.FindObject(animationComponent.ComponentId.ObjectId);

        if (Fire_Sound != null)
        {
            ScenePrivate.PlaySoundAtPosition(Fire_Sound, characterObject.Position, SoundSettings);
        }

        Sansar.Vector cameraForward = animationComponent.GetVectorAnimationVariable("LLCameraForward");
        cameraForward.W = 0.0f;
        cameraForward   = cameraForward.Normalized();

        Sansar.Vector offset = new Sansar.Vector(cameraForward[0], cameraForward[1], 0, 0).Normalized();

        Sansar.Vector new_pos = new Sansar.Vector(0f, 0f, 1.5f, 0f);
        new_pos += characterObject.Position; // This script is on the Avatar, so the Avatar is the owning object.
        new_pos += (offset * 0.6f);          // Add to the world just in front of the avatar.

        float speed = InitialSpeed;

        if (InitialSpeed < 1.0f || InitialSpeed > 200.0f)
        {
            const float defaultSpeed = 10.0f;
            Log.Write(string.Format("Bad CannonBall Speed: {0}, using default {1}", InitialSpeed, defaultSpeed));
            speed = defaultSpeed;
        }

        Sansar.Vector vel = cameraForward * speed;

        StartCoroutine(RezCannonball, new_pos, Quaternion.FromLook(cameraForward, Vector.Up), vel);

        Timer.Create(TimeSpan.FromSeconds(Delay), () => { animationComponent.Subscribe(ListenEvent, (data) => { OnFire(animationComponent); }, false); });
    }
Esempio n. 8
0
        private void Subscribe(ScriptEventData sed)
        {
            if (subscriptions == null)
            {
                subscriptions = SubscribeToAll(TurnOnEvent, (data) =>
                {
                    if (TurnOnFadeTime > 0.0f)
                    {
                        previousColor         = lights[0].GetNormalizedColor();
                        previousIntensity     = lights[0].GetRelativeIntensity();
                        targetColor           = initialColor;
                        targetIntensity       = initialIntensity;
                        interpolationDuration = TurnOnFadeTime;
                        interpolationTime     = TurnOnFadeTime;
                        interpolationActive   = true;
                    }
                    else
                    {
                        interpolationActive = false;
                        SetColorAndIntensityOfAllLights(initialColor, initialIntensity);
                    }
                });

                subscriptions += SubscribeToAll(TurnOffEvent, (data) =>
                {
                    if (TurnOffFadeTime > 0.0f)
                    {
                        previousColor         = lights[0].GetNormalizedColor();
                        previousIntensity     = lights[0].GetRelativeIntensity();
                        targetColor           = Sansar.Color.Black;
                        targetIntensity       = 0.0f;
                        interpolationDuration = TurnOffFadeTime;
                        interpolationTime     = TurnOffFadeTime;
                        interpolationActive   = true;
                    }
                    else
                    {
                        interpolationActive = false;
                        SetColorAndIntensityOfAllLights(Sansar.Color.Black, 0.0f);
                    }
                });

                subscriptions += SubscribeToAll(TurnRandomEvent, (data) =>
                {
                    if (TurnRandomFadeTime > 0.0f)
                    {
                        // Pick a random color but don't let it be too dark or else the relative intensity doesn't work well
                        Sansar.Vector randomVector = new Sansar.Vector((float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble());
                        while (randomVector.LengthSquared() < 0.1f)
                        {
                            randomVector = new Sansar.Vector((float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble());
                        }
                        if (randomVector.LengthSquared() < 0.5f)
                        {
                            randomVector = randomVector.Normalized();
                        }
                        Sansar.Color randomColor = new Sansar.Color(randomVector.X, randomVector.Y, randomVector.Z);

                        // Pick a random intensity from min to max
                        float randomIntensity = randomMinIntensity + (randomMaxIntensity - randomMinIntensity) * (float)rnd.NextDouble();

                        previousColor         = lights[0].GetNormalizedColor();
                        previousIntensity     = lights[0].GetRelativeIntensity();
                        targetColor           = randomColor;
                        targetIntensity       = randomIntensity;
                        interpolationDuration = TurnRandomFadeTime;
                        interpolationTime     = TurnRandomFadeTime;
                        interpolationActive   = true;
                    }
                    else
                    {
                        interpolationActive = false;
                        SetRandomColorAndIntensityOfAllLights();
                    }
                });
            }

            if (HasFadeTime())
            {
                StartInterpolation();
            }
        }
    public void RezCannonball(Sansar.Vector initial_pos, Sansar.Quaternion rotation, Sansar.Vector vel)
    {
        ScenePrivate.CreateClusterData createData = null;
        try
        {
            try
            {
                if (Projectile != null)
                {
                    createData = (ScenePrivate.CreateClusterData)WaitFor(ScenePrivate.CreateCluster, Projectile,
                                                                         initial_pos,
                                                                         rotation,
                                                                         vel);
                }
                else
                {   // No projectile override - just use cannon balls.
                    createData = (ScenePrivate.CreateClusterData)WaitFor(ScenePrivate.CreateCluster, "Export/CannonBall/",
                                                                         initial_pos,
                                                                         rotation,
                                                                         vel);
                }
            }
            catch (ThrottleException e)
            {
                Log.Write($"Too many rezzes! Throttle rate is {e.MaxEvents} per {e.Interval.TotalSeconds}.");
                RezThrottled = true;
                Wait(e.Interval - e.Elapsed); // Wait out the rest of the interval before trying again.
                RezThrottled = false;
                return;
            }

            if (createData.Success)
            {
                ObjectPrivate obj = createData.ClusterReference.GetObjectPrivate(0);
                if (obj != null)
                {
                    RigidBodyComponent RigidBody = null;
                    if (obj.TryGetFirstComponent(out RigidBody))
                    {
                        //exit after 3 hits or 1 character hit
                        for (int i = 0; i < 3; i++)
                        {
                            CollisionData data = (CollisionData)WaitFor(RigidBody.Subscribe, CollisionEventType.AllCollisions, ComponentId.Invalid);

                            if ((data.EventType & CollisionEventType.CharacterContact) != 0)
                            {
                                // Use the scene to find the full object API of the other object.
                                AgentPrivate hit = ScenePrivate.FindAgent(data.HitComponentId.ObjectId);
                                if (hit != null)
                                {
                                    ObjectPrivate otherObject = ScenePrivate.FindObject(data.HitComponentId.ObjectId);
                                    if (otherObject != null)
                                    {
                                        if (Hit_Sound != null)
                                        {
                                            ScenePrivate.PlaySoundAtPosition(Hit_Sound, otherObject.Position, SoundSettings);
                                        }

                                        if (Teleport_On_Hit)
                                        {
                                            AnimationComponent anim;
                                            if (otherObject.TryGetFirstComponent(out anim))
                                            {
                                                anim.SetPosition(SpawnPoints[rng.Next(SpawnPoints.Count)]);
                                            }
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            Log.Write(e.ToString());
        }
        finally
        {
            if (createData.ClusterReference != null)
            {
                try
                {
                    createData.ClusterReference.Destroy();
                }
                catch (Exception) { }
            }
        }
    }