/// <summary> /// Runs when the script starts, initialize vars, start coroutines, etc /// </summary> public override void Init() { offset = new Sansar.Vector(0, 0, 1.2f); Script.UnhandledException += UnhandledException; ScenePrivate.User.Subscribe(User.AddUser, NewUser); }
public override void Init() { Script.UnhandledException += (object o, Exception e) => { if (DebugSpam) { Log.Write("UnhandledException", "[" + (o?.ToString() ?? "NULL") + "] " + e.ToString()); } }; SoundSettings.Loudness = LoudnessPercentToDb(LoudnessPct); Admins.AddRange(AdminHandles.Trim().ToLower().Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)); Admins.Add(ScenePrivate.SceneInfo.AvatarId); OriginalOrientation = ObjectPrivate.InitialRotation; OriginalPosition = ObjectPrivate.InitialPosition; if (ObjectPrivate.TryGetFirstComponent(out RigidBody)) { if (!RigidBody.GetCanGrab()) { RigidBody.SetCanGrab(true, (data) => { if (!data.Success) { Log.Write("Could not set ModHammer to grabbable - won't be able to pick up the gun."); } }); } RigidBody.SubscribeToHeldObject(HeldObjectEventType.Grab, OnPickup); RigidBody.SubscribeToHeldObject(HeldObjectEventType.Release, OnDrop); } ScenePrivate.User.Subscribe("AddUser", AddUser); if (BanDuration > 0) { Timer.Create(TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1), CleanupBans); } }
public void fireRez(Sansar.Vector position, Sansar.Vector fwd, Sansar.Quaternion orientation) { Sansar.Vector rezPosition; if (Sound_To_Play != null) { ScenePrivate.PlaySoundAtPosition(Sound_To_Play, position, PlaySettings.PlayOnce); } for (int i = 0; i < numberOfRez; i++) { //so i starts at 0, and will eventually be spacing away, if we add .5 that means .5 of fwd which means if the object is centered //it will come right out of our av, .6 is 10% more so we dont hit ourself rezPosition = position + offset + ( fwd * (spacing * (i + .6f)) ); ScenePrivate.CreateCluster( Bullet_Object, rezPosition, orientation, Sansar.Vector.Zero, CreateClusterHandler ); Wait(TimeSpan.FromSeconds(.1)); } }
// 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)); }
// 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. var distance = (RigidBody.GetPosition() - Home).GetMagnetude(); // 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(); Direction = Direction.Normalize(); // 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.Normalize(); } // 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.Normalize(); } // Wait after each push for between 0.5 and 1.5 seconds. Wait(TimeSpan.FromSeconds(0.5 + rng.NextDouble())); } }
// Return a Normalized copy of the Vector4f public static Sansar.Vector Normalize(this Sansar.Vector val) { double mag = val.GetMagnetude(); Sansar.Vector ret = new Sansar.Vector(); ret.X = (float)(val.X / mag); ret.Y = (float)(val.Y / mag); ret.Z = (float)(val.Z / mag); ret.W = (float)(val.W / mag); return(ret); }
void OnCollision(CollisionData data) { Log.Write(LogLevel.Info, $"Choppable Struck by: {data.HitObject.ObjectId}"); if (data.HitObject.ObjectId != Axe.ObjectIdReflected()) { return; } Sansar.Vector pos = RigidBody.GetPosition(); WaitFor(RigidBody.SetPosition, new Sansar.Vector(0, 2, 0)); foreach (INamedRigidThing p in Pieces) { p.SetPosition(pos); } Log.Write(LogLevel.Info, $"Done setting stuff to ({pos.X}, {pos.Y}, {pos.Z})"); }
// 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.Normalize(); 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)); } }
public void SetPosition(Sansar.Vector position) { WaitFor(RigidBody.SetPosition, position); Log.Write(LogLevel.Info, $"Position of chopped bit was set to: ({position.X}, {position.Y}, {position.Z})"); }
// Return the magnitude of the Vector4f public static double GetMagnetude(this Sansar.Vector val) { return(Math.Sqrt((val.Z * val.Z) + (val.X * val.X) + (val.Y * val.Y) + (val.W * val.W))); }