Example #1
0
        public virtual void Accepted(CharacterEntity character, Seat seat)
        {
            GainControlOfVehiclePacketOut gcovpo = new GainControlOfVehiclePacketOut(character, this);

            TheRegion.SendToVisible(lPos, gcovpo);
            // TODO: handle players coming into/out-of view of the vehicle + driver!
        }
Example #2
0
        public JointVehicleMotor ConnectWheel(VehiclePartEntity wheel, bool driving, bool powered)
        {
            wheel.SetFriction(2.5f);
            Vector3         left             = Quaternion.Transform(new Vector3(-1, 0, 0), wheel.GetOrientation());
            Vector3         up               = Quaternion.Transform(new Vector3(0, 0, 1), wheel.GetOrientation());
            JointSlider     pointOnLineJoint = new JointSlider(this, wheel, -new Location(up));
            JointLAxisLimit suspensionLimit  = new JointLAxisLimit(this, wheel, 0f, 0.1f, wheel.GetPosition(), wheel.GetPosition(), -new Location(up));
            JointPullPush   spring           = new JointPullPush(this, wheel, -new Location(up), true);

            BEPUphysics.CollisionRuleManagement.CollisionRules.AddRule(wheel.Body, this.Body, BEPUphysics.CollisionRuleManagement.CollisionRule.NoBroadPhase); // TODO: How necessary is this? Should we replicate this clientside?
            if (driving)
            {
                JointSpinner spinner = new JointSpinner(this, wheel, new Location(-left));
                TheRegion.AddJoint(spinner);
            }
            else
            {
                JointSwivelHinge swivelhinge = new JointSwivelHinge(this, wheel, new Location(up), new Location(-left));
                TheRegion.AddJoint(swivelhinge);
            }
            TheRegion.AddJoint(pointOnLineJoint);
            TheRegion.AddJoint(suspensionLimit);
            TheRegion.AddJoint(spring);
            if (powered)
            {
                JointVehicleMotor motor = new JointVehicleMotor(this, wheel, new Location(driving ? left : up), !driving);
                TheRegion.AddJoint(motor);
                return(motor);
            }
            return(null);
        }
Example #3
0
        public void UpdatePath()
        {
            Location goal = TargetPosition;

            if (goal.IsNaN())
            {
                if (TargetEntity == null)
                {
                    Path = null;
                    return;
                }
                goal = TargetEntity.GetPosition();
            }
            Location selfpos = GetPosition();

            if ((goal - selfpos).LengthSquared() > MaxPathFindDistance * MaxPathFindDistance)
            {
                TargetPosition = Location.NaN; // TODO: Configurable "can't find path" result -> giveup vs. teleport
                TargetEntity   = null;
                Path           = null;
                return;
            }
            List <Location> tpath = TheRegion.FindPathAsyncDouble(selfpos, goal, MaxPathFindDistance, new PathfinderOptions());

            if (tpath == null)
            {
                TargetPosition = Location.NaN; // TODO: Configurable "can't find path" result -> giveup vs. teleport
                TargetEntity   = null;
                Path           = null;
                return;
            }
            Path       = new ListQueue <Location>(tpath);
            PathUpdate = 1; // TODO: Configurable update time
        }
Example #4
0
 void Events_ContactCreated(EntityCollidable sender, Collidable other, CollidablePairHandler pair, ContactData contact)
 {
     if (TheRegion.GlobalTickTimeLocal - lastSoundTime < soundmaxrate)
     {
         return;
     }
     lastSoundTime = TheRegion.GlobalTickTimeLocal;
     if (other is FullChunkObject)
     {
         ((ConvexFCOPairHandler)pair).ContactInfo(/*contact.Id*/ 0, out ContactInformation info);
         float vellen = (float)(Math.Abs(info.RelativeVelocity.X) + Math.Abs(info.RelativeVelocity.Y) + Math.Abs(info.RelativeVelocity.Z));
         float mod    = vellen / 5;
         if (mod > 2)
         {
             mod = 2;
         }
         Location      block = new Location(contact.Position - contact.Normal * 0.01f);
         BlockInternal bi    = TheRegion.GetBlockInternal(block);
         MaterialSound sound = ((Material)bi.BlockMaterial).Sound();
         if (sound != MaterialSound.NONE)
         {
             new DefaultSoundPacketIn()
             {
                 TheClient = TheClient
             }.PlayDefaultBlockSound(block, sound, mod, 0.5f * mod);
         }
         MaterialSound sound2 = Mat.Sound();
         if (sound2 != MaterialSound.NONE)
         {
             new DefaultSoundPacketIn()
             {
                 TheClient = TheClient
             }.PlayDefaultBlockSound(block, sound2, mod, 0.5f * mod);
         }
     }
     else if (other is EntityCollidable)
     {
         BEPUphysics.Entities.Entity e        = ((EntityCollidable)other).Entity;
         BEPUutilities.Vector3       velocity = BEPUutilities.Vector3.Zero;
         if (e != null)
         {
             velocity = e.LinearVelocity;
         }
         BEPUutilities.Vector3 relvel = Body.LinearVelocity - velocity;
         float vellen = (float)(Math.Abs(relvel.X) + Math.Abs(relvel.Y) + Math.Abs(relvel.Z));
         float mod    = vellen / 5;
         if (mod > 2)
         {
             mod = 2;
         }
         MaterialSound sound = Mat.Sound();
         if (sound != MaterialSound.NONE)
         {
             new DefaultSoundPacketIn()
             {
                 TheClient = TheClient
             }.PlayDefaultBlockSound(new Location(contact.Position), sound, mod, 0.5f * mod);
         }
     }
 }
Example #5
0
        public void PlayRelevantSounds()
        {
            if (SoundTimeout > 0)
            {
                SoundTimeout -= TheRegion.Delta;
                return;
            }
            Location vel = GetVelocity();

            if (vel.LengthSquared() < 0.2)
            {
                return;
            }
            Material      mat   = TheRegion.GetBlockMaterial(GetPosition() + new Location(0, 0, -0.05f));
            MaterialSound sound = mat.Sound();

            if (sound == MaterialSound.NONE)
            {
                return;
            }
            double velLen = vel.Length();

            new DefaultSoundPacketIn()
            {
                TheClient = TheClient
            }.PlayDefaultBlockSound(GetPosition(), sound, 1f, 0.14f * (float)velLen);
            TheClient.Particles.Steps(GetPosition(), mat, GetVelocity(), (float)velLen);
            SoundTimeout = (Utilities.UtilRandom.NextDouble() * 0.2 + 1.0) / velLen;
        }
Example #6
0
        public bool ConsumeFuel(double amt)
        {
            // TODO: Gamemode check!
            ItemStack stackf = null;

            foreach (ItemStack item in Items.Items)
            {
                if (item.Name == "fuel")
                {
                    stackf = item;
                    break;
                }
            }
            if (stackf == null)
            {
                return(false);
            }
            fuelCom += amt;
            if (fuelCom > 1)
            {
                fuelCom -= 1;
                Items.RemoveItem(stackf, 1);
                TheRegion.SendToVisible(GetPosition(), new FlagEntityPacketOut(this, EntityFlag.HAS_FUEL, ConsumeFuel(0) ? 1f: 0f));
            }
            else
            {
                TheRegion.SendToVisible(GetPosition(), new FlagEntityPacketOut(this, EntityFlag.HAS_FUEL, 1f));
            }
            return(true);
        }
Example #7
0
 public bool ShouldSeePosition(Location pos)
 {
     if (pos.IsNaN())
     {
         return(false);
     }
     return(ShouldSeeChunk(TheRegion.ChunkLocFor(pos)));
 }
Example #8
0
 public bool ShouldSeeLODPositionOneSecondAgo(Location pos)
 {
     if (pos.IsNaN() || losPos.IsNaN())
     {
         return(false);
     }
     return(ShouldSeeLODChunkOneSecondAgo(TheRegion.ChunkLocFor(pos)));
 }
Example #9
0
 public bool ShouldLoadPositionPreviously(Location pos)
 {
     if (pos.IsNaN())
     {
         return(false);
     }
     return(ShouldLoadChunkPreviously(TheRegion.ChunkLocFor(pos)));
 }
Example #10
0
        public override void Accepted(CharacterEntity character, Seat seat)
        {
            base.Accepted(character, seat);
            // TODO: Track players entering/exiting view!
            FlagEntityPacketOut fepo = new FlagEntityPacketOut(this, EntityFlag.HELO_TILT_MOD, TiltMod);

            TheRegion.SendToVisible(lPos, fepo);
        }
Example #11
0
 public override void Die()
 {
     if (Removed)
     {
         return;
     }
     TheRegion.Explode(GetPosition(), 5);
     RemoveMe();
 }
Example #12
0
 public override void Fly()
 {
     if (IsFlying)
     {
         return;
     }
     base.Fly();
     TheRegion.SendToAll(new FlagEntityPacketOut(this, EntityFlag.FLYING, 1));
     TheRegion.SendToAll(new FlagEntityPacketOut(this, EntityFlag.MASS, 0));
 }
Example #13
0
 public override void Unfly()
 {
     if (!IsFlying)
     {
         return;
     }
     base.Unfly();
     TheRegion.SendToAll(new FlagEntityPacketOut(this, EntityFlag.FLYING, 0));
     TheRegion.SendToAll(new FlagEntityPacketOut(this, EntityFlag.MASS, PreFlyMass));
 }
Example #14
0
 public void StartUse(Entity user)
 {
     if (!Removed)
     {
         int    itemMusicType   = Original.GetAttributeI("music_type", 0);
         double itemMusicVolume = Original.GetAttributeF("music_volume", 0.5f);
         double itemMusicPitch  = Original.GetAttributeF("music_pitch", 1f);
         TheRegion.PlaySound("sfx/musicnotes/" + itemMusicType, GetPosition(), itemMusicVolume, itemMusicPitch);
     }
 }
Example #15
0
        public bool ShouldSeeLODChunkOneSecondAgo(Vector3i cpos)
        {
            Vector3i wpos = TheRegion.ChunkLocFor(losPos);

            if (Math.Abs(cpos.X - wpos.X) > (ViewRadiusInChunks + ViewRadExtra5) ||
                Math.Abs(cpos.Y - wpos.Y) > (ViewRadiusInChunks + ViewRadExtra5) ||
                Math.Abs(cpos.Z - wpos.Z) > (ViewRadiusInChunks + ViewRadExtra5Height))
            {
                return(false);
            }
            return(true);
        }
Example #16
0
        /// <summary>
        /// Ticks the physics entity.
        /// </summary>
        public override void Tick()
        {
            if (!TheRegion.IsVisible(GetPosition()))
            {
                if (Body.ActivityInformation.IsActive)
                {
                    wasActive = true;
                    // TODO: Is this needed?
                    if (Body.ActivityInformation.SimulationIsland != null)
                    {
                        Body.ActivityInformation.SimulationIsland.IsActive = false;
                    }
                }
            }
            else if (wasActive)
            {
                wasActive = false;
                Body.ActivityInformation.Activate();
            }
            Vector3i cpos = TheRegion.ChunkLocFor(GetPosition());

            if (CanSave && !TheRegion.TryFindChunk(cpos, out Chunk _)) // TODO: is this really needed every tick?
            {
                TheRegion.LoadChunk(cpos);
            }
            if (!GenBlockShadow)// TODO: and world config allows trackables
            {
                if (TheRegion.GetEntitiesInRadius(GetPosition(), 1.5f, EntityType.SMASHER_PRIMTIVE).Count == 0)
                {
                    // TODO: 5 * 60 -> world config
                    TheRegion.SpawnEntity(new SmasherPrimitiveEntity(TheRegion, Math.Min((float)GetScaleEstimate(), 2f), TheRegion.TheWorld.GlobalTickTime + (5 * 60))
                    {
                        Position = GetPosition()
                    });
                }
            }
            // TODO: More genericish
            if (TheRegion.Generator is SphereGeneratorCore)
            {
                Location pos   = new Location(Body.Position);
                double   scale = TheRegion.TheWorld.GeneratorScale;
                Location gravDir;
                if (pos.LengthSquared() > scale * scale)
                {
                    gravDir = new Location(scale / pos.X, scale / pos.Y, scale / pos.Z);
                }
                else
                {
                    gravDir = pos / scale;
                }
                SetGravity(gravDir * (-TheRegion.GravityStrength));
            }
        }
Example #17
0
        public bool ShouldLoadChunk(Vector3i cpos)
        {
            Vector3i wpos = TheRegion.ChunkLocFor(LoadRelPos);

            if (Math.Abs(cpos.X - wpos.X) > (ViewRadiusInChunks + ViewRadExtra5) ||
                Math.Abs(cpos.Y - wpos.Y) > (ViewRadiusInChunks + ViewRadExtra5) ||
                Math.Abs(cpos.Z - wpos.Z) > (ViewRadiusInChunks + ViewRadExtra5Height))
            {
                return(false);
            }
            return(true);
        }
Example #18
0
 public override void SpawnBody()
 {
     base.SpawnBody();
     Motion = new PlaneMotionConstraint(this);
     TheRegion.PhysicsWorld.Add(Motion);
     Wings = new JointFlyingDisc(this)
     {
         IsAPlane = true
     };
     TheRegion.AddJoint(Wings);
     HandleWheels();
 }
Example #19
0
        public void ConnectFlap(VehiclePartEntity flap, FDSSection flapDat)
        {
            JointBallSocket jbs = new JointBallSocket(this, flap, flap.GetPosition()); // TODO: necessity?

            TheRegion.AddJoint(jbs);
            JointNoCollide jnc = new JointNoCollide(this, flap);

            TheRegion.AddJoint(jnc);
            string      mode = flapDat.GetString("mode");
            VehicleFlap vf   = new VehicleFlap()
            {
                MaxAngle = flapDat.GetDouble("max_angle", 10).Value,
                Speed    = flapDat.GetDouble("corrective_speed", 2.25).Value
            };

            if (mode == "roll/l")
            {
                JointHinge jh = new JointHinge(this, flap, new Location(1, 0, 0));
                TheRegion.AddJoint(jh);
                JointVehicleMotor jvm = new JointVehicleMotor(this, flap, new Location(1, 0, 0), true);
                TheRegion.AddJoint(jvm);
                vf.JVM = jvm;
                Flaps_RollL.Add(vf);
            }
            else if (mode == "roll/r")
            {
                JointHinge jh = new JointHinge(this, flap, new Location(1, 0, 0));
                TheRegion.AddJoint(jh);
                JointVehicleMotor jvm = new JointVehicleMotor(this, flap, new Location(1, 0, 0), true);
                TheRegion.AddJoint(jvm);
                vf.JVM = jvm;
                Flaps_RollR.Add(vf);
            }
            else if (mode == "yaw")
            {
                JointHinge jh = new JointHinge(this, flap, new Location(0, 0, 1));
                TheRegion.AddJoint(jh);
                JointVehicleMotor jvm = new JointVehicleMotor(this, flap, new Location(0, 0, 1), true);
                TheRegion.AddJoint(jvm);
                vf.JVM = jvm;
                Flaps_Yaw.Add(vf);
            }
            else if (mode == "pitch")
            {
                JointHinge jh = new JointHinge(this, flap, new Location(1, 0, 0));
                TheRegion.AddJoint(jh);
                JointVehicleMotor jvm = new JointVehicleMotor(this, flap, new Location(1, 0, 0), true);
                TheRegion.AddJoint(jvm);
                vf.JVM = jvm;
                Flaps_Pitch.Add(vf);
            }
        }
Example #20
0
 public override void Tick()
 {
     timer += TheRegion.Delta;
     if (timer > boomtime)
     {
         RemoveMe();
         TheRegion.PaintBomb(GetPosition(), Color, 5); // TODO: radius, etc. settings
     }
     else
     {
         base.Tick();
     }
 }
 public override void Tick()
 {
     timer += TheRegion.Delta;
     if (timer > boomtime)
     {
         RemoveMe();
         TheRegion.Explode(GetPosition()); // TODO: Damage settings, etc.
     }
     else
     {
         base.Tick();
     }
 }
Example #22
0
 public override void SpawnBody()
 {
     base.SpawnBody();
     Body.LinearDamping = 0.0;
     HandleWheels();
     Motion = new PlaneMotionConstraint(this);
     TheRegion.PhysicsWorld.Add(Motion);
     Wings = new JointFlyingDisc(this)
     {
         IsAPlane = true
     };
     TheRegion.AddJoint(Wings);
     (Wings.CurrentJoint as FlyingDiscConstraint).PlaneLiftHelper = LiftHelper;
 }
Example #23
0
        public void SetTypingStatus(bool isTyping)
        {
            IsTyping = isTyping;
            // TODO: Generic find-all-players-that-can-see-me method
            Vector3i           ch   = TheRegion.ChunkLocFor(GetPosition());
            SetStatusPacketOut pack = new SetStatusPacketOut(this, ClientStatus.TYPING, (byte)(IsTyping ? 1 : 0));

            foreach (PlayerEntity player in TheRegion.Players)
            {
                if (player.CanSeeChunk(ch))
                {
                    player.Network.SendPacket(pack);
                }
            }
        }
Example #24
0
 public override void Tick()
 {
     timer += TheRegion.Delta;
     while (timer > pulse)
     {
         if (SmokeLeft <= 0)
         {
             break;
         }
         Location colo = new Location(col.R / 255f, col.G / 255f, col.B / 255f);
         TheRegion.SendToAll(new ParticleEffectPacketOut(SmokeType, 5, GetPosition(), colo));
         timer -= pulse;
         SmokeLeft--;
     }
     base.Tick();
 }
Example #25
0
 public override void SpawnBody()
 {
     base.SpawnBody();
     if (CursorMarker == null)
     {
         CursorMarker         = new ModelEntity("cube", TheRegion);
         CursorMarker.scale   = new Location(0.1f, 0.1f, 0.1f);
         CursorMarker.mode    = ModelCollisionMode.AABB;
         CursorMarker.CGroup  = CollisionUtil.NonSolid;
         CursorMarker.Visible = false;
         CursorMarker.CanSave = false;
         TheRegion.SpawnEntity(CursorMarker);
     }
     Jetpack = new JetpackMotionConstraint(this);
     TheRegion.PhysicsWorld.Add(Jetpack);
 }
Example #26
0
        public bool ShouldSeeChunk(Vector3i cpos)
        {
            if (LoadRelPos.IsNaN())
            {
                return(false);
            }
            Vector3i wpos = TheRegion.ChunkLocFor(LoadRelPos);

            if (Math.Abs(cpos.X - wpos.X) > ViewRadiusInChunks ||
                Math.Abs(cpos.Y - wpos.Y) > ViewRadiusInChunks ||
                Math.Abs(cpos.Z - wpos.Z) > ViewRadiusInChunks)
            {
                return(false);
            }
            return(true);
        }
Example #27
0
        public void OnCollide(object sender, CollisionEventArgs args)
        {
            if (Stuck)
            {
                return;
            }
            double len = GetVelocity().Length();

            SetPosition(args.Info.Position + (GetVelocity() / len) * 0.05f);
            SetVelocity(Location.Zero);
            Gravity = Location.Zero;
            if (HasHat)
            {
                SolidHat = new ModelEntity("invisbox", TheRegion);
                SolidHat.SetMass(0);
                SolidHat.SetPosition(GetPosition());
                SolidHat.SetOrientation(GetOrientation());
                SolidHat.scale   = new Location(0.6, 1.5, 0.6);
                SolidHat.Visible = false;
                SolidHat.CanSave = false;
                TheRegion.SpawnEntity(SolidHat);
            }
            if (args.Info.HitEnt != null)
            {
                PhysicsEntity pe = (PhysicsEntity)args.Info.HitEnt.Tag;
                if (pe is EntityDamageable)
                {
                    ((EntityDamageable)pe).Damage(Damage + DamageTimesVelocity * (double)len);
                }
                Vector3 loc     = (args.Info.Position - pe.GetPosition()).ToBVector();
                Vector3 impulse = GetVelocity().ToBVector() * DamageTimesVelocity / 1000f;
                pe.Body.ApplyImpulse(ref loc, ref impulse);
                StuckTo = pe;
                if (HasHat)
                {
                    CollisionRules.AddRule(pe.Body, SolidHat.Body, CollisionRule.NoBroadPhase); // TODO: Broadcast this info! Perhaps abuse the joint system?
                }
            }
            TheRegion.SendToAll(new PrimitiveEntityUpdatePacketOut(this));
            if (args.Info.HitEnt != null)
            {
                PhysicsEntity  pe  = (PhysicsEntity)args.Info.HitEnt.Tag;
                JointForceWeld jfw = new JointForceWeld(pe, this);
                TheRegion.AddJoint(jfw);
            }
        }
Example #28
0
        /// <summary>
        /// General entity render.
        /// </summary>
        public override void Render()
        {
            if (!Visible || model.Meshes.Count == 0)
            {
                return;
            }
            TheClient.SetEnts();
            RigidTransform rt = new RigidTransform(Body.Position, Body.Orientation);

            RigidTransform.Transform(ref ModelMin, ref rt, out BEPUutilities.Vector3 bmin);
            RigidTransform.Transform(ref ModelMax, ref rt, out BEPUutilities.Vector3 bmax);
            if (TheClient.MainWorldView.CFrust != null && !TheClient.MainWorldView.CFrust.ContainsBox(new Location(bmin), new Location(bmax)))
            {
                return;
            }
            double maxr   = TheClient.CVars.r_modeldistance.ValueF;
            double distsq = GetPosition().DistanceSquared(TheClient.MainWorldView.RenderRelative);

            if (GenBlockShadows && distsq > maxr * maxr) // TODO: LOD-able option?
            {
                // TODO: Rotation?
                model.DrawLOD(GetPosition() + ClientUtilities.ConvertD(transform.ExtractTranslation()), TheClient.MainWorldView);
                return;
            }
            Matrix4d orient = GetOrientationMatrix();
            Matrix4d mat    = (Matrix4d.Scale(ClientUtilities.ConvertD(scale)) * transform
                               * Matrix4d.CreateTranslation(ClientUtilities.ConvertD(new Location(Body.CollisionInformation.LocalPosition)))
                               * orient * Matrix4d.CreateTranslation(ClientUtilities.ConvertD(GetPosition())));

            TheClient.MainWorldView.SetMatrix(2, mat);
            if (!TheClient.MainWorldView.RenderingShadows)
            {
                TheClient.Rendering.SetMinimumLight(0.0f, TheClient.MainWorldView);
            }
            if (model.Meshes[0].vbo.Tex == null)
            {
                TheClient.Textures.White.Bind();
            }
            if (!TheClient.MainWorldView.RenderingShadows && ((TheClient.CVars.r_fast.ValueB && !TheClient.CVars.r_forward_lights.ValueB) || !TheClient.CVars.r_lighting.ValueB))
            {
                OpenTK.Vector4 sadj = TheRegion.GetSunAdjust();
                float          skyl = TheRegion.GetSkyLightBase(GetPosition() + new Location(0, 0, ModelMax.Z));
                TheClient.Rendering.SetColor(new OpenTK.Vector4(sadj.X * skyl, sadj.Y * skyl, sadj.Z * skyl, 1.0f), TheClient.MainWorldView);
            }
            model.Draw(); // TODO: Animation(s)?
        }
Example #29
0
        public override void Tick()
        {
            base.Tick();
            Location pos     = GetPosition();
            Location rad     = new Location(CBody.BodyRadius, CBody.BodyRadius, 0);
            double   halfeye = CBHHeight * (CBody.StanceManager.CurrentStance == Stance.Standing ? 1.8 : 1.5) * 0.5;
            bool     uw1     = TheRegion.InWater(pos - rad, pos + rad + new Location(0, 0, halfeye));
            bool     uw2     = TheRegion.InWater(pos - rad + new Location(0, 0, halfeye), pos + rad + new Location(0, 0, halfeye * 2));

            if (uw1 || uw2)
            {
                double mult = uw1 ? (uw2 ? 0.6 : 0.3) : 0.3;
                SetForSwim(mult, Body.Space.ForceUpdater.Gravity * (1.0 - mult));
            }
            else
            {
                SetForGround();
            }
        }
Example #30
0
        /// <summary>
        /// Ticks the physics entity.
        /// </summary>
        public override void Tick()
        {
            if (!TheRegion.IsVisible(GetPosition()))
            {
                if (Body.ActivityInformation.IsActive)
                {
                    wasActive = true;
                    // TODO: Is this needed?
                    if (Body.ActivityInformation.SimulationIsland != null)
                    {
                        Body.ActivityInformation.SimulationIsland.IsActive = false;
                    }
                }
            }
            else if (wasActive)
            {
                wasActive = false;
                Body.ActivityInformation.Activate();
            }
            Vector3i cpos = TheRegion.ChunkLocFor(GetPosition());

            if (CanSave && !TheRegion.LoadedChunks.ContainsKey(cpos)) // TODO: is this really needed every tick?
            {
                TheRegion.LoadChunk(cpos);
            }
            // TODO: More genericish
            if (TheRegion.Generator is SphereGeneratorCore)
            {
                Location pos   = new Location(Body.Position);
                double   scale = TheRegion.TheWorld.GeneratorScale;
                Location gravDir;
                if (pos.LengthSquared() > scale * scale)
                {
                    gravDir = new Location(scale / pos.X, scale / pos.Y, scale / pos.Z);
                }
                else
                {
                    gravDir = pos / scale;
                }
                SetGravity(gravDir * (-TheRegion.GravityStrength));
            }
        }