Ejemplo n.º 1
0
 /// <summary>
 /// Prefetches planetary voxel physics along a ray
 /// </summary>
 /// <param name="ray">ray to prefetch</param>
 /// <param name="force">force a new prefetch task</param>
 public static void PrefetchRay(ref LineD ray, bool force = false)
 {
     // Force is second so we still update the cache for forced
     if (!_raycastPrefetchCache.IsItemPresent(ray.GetHash(),
                                              (int)MyAPIGateway.Session.ElapsedPlayTime.TotalSeconds) || force)
     {
         var voxelHits = _voxelCache.Get();
         try
         {
             MyGamePruningStructure.GetVoxelMapsOverlappingRay(ref ray, voxelHits);
             foreach (var e in voxelHits)
             {
                 var planet = (e.Element?.RootVoxel ?? e.Element) as MyPlanet;
                 // This needs to be done for all voxel maps. To bad we can't.
                 planet?.PrefetchShapeOnRay(ref ray);
             }
         }
         finally
         {
             voxelHits.Clear();
             if (_voxelCache.Count <= 1)
             {
                 _voxelCache.Return(voxelHits);
             }
         }
     }
 }
Ejemplo n.º 2
0
        public void Update()
        {
            if (_targetHit)
            {
                Kill();
                return;
            }

            // Update velocity due to gravity
            Vector3D totalGravity      = MyParticlesManager.CalculateGravityInPoint(_position); // Does this get affected by artificial grav? If so... cooooool
            Vector3D naturalGravity    = RailgunCore.GetNaturalGravityAtPoint(_position);
            Vector3D artificialGravity = totalGravity - naturalGravity;

            _velocity += (naturalGravity * RailgunCore.MyConfig.NaturalGravityMultiplier + artificialGravity * RailgunCore.MyConfig.ArtificialGravityMultiplier) * _tick;

            // Update direction if velocity has changed
            if (!_velocity.Equals(_lastVelocity, 1e-3))
            {
                _direction = Vector3D.Normalize(_velocity);
            }

            _lastVelocity = _velocity;

            // Update position
            _position += _velocity * _tick;
            var _toOrigin = _position - _origin;

            //draw tracer line
            if (_drawTrail && _currentTracerFadeTicks < _maxTracerFadeTicks)
            {
                _lineColor *= _trailColorDecayRatio;
                _currentTracerFadeTicks++;
            }

            if (_toOrigin.LengthSquared() > _maxTrajectory * _maxTrajectory)
            {
                MyLog.Default.WriteLine(">> Max range hit");

                _targetHit   = true;
                _hitPosition = _position;
                Kill();
                if (_shouldExplode)
                {
                    CreateExplosion(_position, _direction, _explosionRadius, _explosionDamage);
                }
                return;
            }

            _checkIntersectionIndex = ++_checkIntersectionIndex % 5;
            if (_checkIntersectionIndex != 0 && _positionChecked)
            {
                return;
            }

            // Add current position to trajectory list
            _trajectoryPoints.Add(_position);

            var to   = _position; //_position + 5.0 * _velocity * _tick;
            var from = _lastPositionChecked;

            _positionChecked     = true;
            _lastPositionChecked = _position;

            IHitInfo hitInfo;
            bool     hit = false;

            if (Vector3D.DistanceSquared(to, from) > 50 * 50)
            {
                // Use faster raycast if ray is long enough
                hit = MyAPIGateway.Physics.CastLongRay(from, to, out hitInfo, true);
            }
            else
            {
                hit = MyAPIGateway.Physics.CastRay(from, to, out hitInfo, 0);
            }

            if (hit)
            {
                MyLog.Default.WriteLine(">> Raycast hit");
                _hitPosition = hitInfo.Position + -0.5 * _direction;
                if ((_hitPosition - _origin).LengthSquared() > _minimumArmDistance * _minimumArmDistance) //only explode if beyond arm distance
                {
                    if (_shouldExplode)
                    {
                        CreateExplosion(_hitPosition, _direction, _explosionRadius, _explosionDamage);
                    }

                    if (_shouldPenetrate)
                    {
                        GetObjectsToPenetrate(_hitPosition, _hitPosition + _direction * _penetrationRange);
                    }

                    _targetHit = true;
                    Kill();
                }
                else
                {
                    _targetHit   = true;
                    _hitPosition = _position;
                    Kill();
                }
                return;
            }

            // implied else
            var line = new LineD(from, to);

            MyGamePruningStructure.GetVoxelMapsOverlappingRay(ref line, _voxelOverlap);
            foreach (var result in _voxelOverlap)
            {
                MatrixD matrix;
                MatrixD matrixInv;
                Vector3 sizeInMetersHalf;

                MyPlanet    planet   = result.Element as MyPlanet;
                IMyVoxelMap voxelMap = result.Element as IMyVoxelMap;
                if (planet == null && voxelMap == null)
                {
                    continue;
                }

                if (planet != null)
                {
                    matrix           = planet.WorldMatrix;
                    matrixInv        = planet.PositionComp.WorldMatrixInvScaled;
                    sizeInMetersHalf = planet.SizeInMetresHalf;
                }
                else
                {
                    matrix           = voxelMap.WorldMatrix;
                    matrixInv        = voxelMap.PositionComp.WorldMatrixInvScaled;
                    sizeInMetersHalf = new Vector3(voxelMap.Storage.Size) * 0.5f;
                }

                Vector3 localTo;
                Vector3 localFrom;
                MyVoxelCoordSystems.WorldPositionToLocalPosition(from, matrix, matrixInv, sizeInMetersHalf, out localFrom);
                MyVoxelCoordSystems.WorldPositionToLocalPosition(to, matrix, matrixInv, sizeInMetersHalf, out localTo);
                var localLine = new LineD(localFrom, localTo);

                if (planet != null && ((IMyStorage)(planet.Storage)).Intersect(ref localLine))
                {
                    MyLog.Default.WriteLine(">> Railgun projectile hit planet");
                    _hitPosition = _position;
                    _targetHit   = true;
                    Kill();
                    return;
                }

                // This is very broken
                //if (voxelMap != null && ((IMyStorage)(voxelMap.Storage)).Intersect(ref localLine))
                //{
                //    MyLog.Default.WriteLine(">> Railgun projectile hit voxel");
                //    _hitPosition = _position;
                //    _targetHit = true;
                //    Kill();
                //    return;
                //}
            }
        }