Beispiel #1
0
        private bool IsTargetVisible(MyEntity target, Vector3D predictedPosition)
        {
            if (target == null)
            {
                return(false);
            }
            if (target.GetTopMostParent()?.Physics == null)
            {
                return(false);
            }

            Vector3D from = gun.GunBase.GetMuzzleWorldPosition() + gun.GunBase.WorldMatrix.Forward * 0.5;

            List <IHitInfo> hits = new List <IHitInfo>();

            MyAPIGateway.Physics.CastRay(from, predictedPosition, hits, 15);

            foreach (IHitInfo hit in hits)
            {
                if (hit != null && hit.HitEntity != null)
                {
                    if (target == hit.HitEntity || target.Parent == hit.HitEntity || (target.Parent != null && target.Parent == hit.HitEntity.Parent) || hit.HitEntity is MyFloatingObject || hit.HitEntity.GetType().Name == "MyMissile")
                    {
                        continue;
                    }

                    return(false);
                }
            }

            return(true);
        }
        private MyDetectedEntityInfo GetDetailedEntityInfo(MyTuple <bool, bool, bool, IMyEntity> target, MyEntity shooter)
        {
            var  e           = target.Item4;
            var  shooterGrid = shooter.GetTopMostParent() as MyCubeGrid;
            var  topTarget   = e?.GetTopMostParent() as MyEntity;
            var  block       = e as IMyTerminalBlock;
            var  player      = e as IMyCharacter;
            long entityId    = 0;
            var  relation    = MyRelationsBetweenPlayerAndBlock.NoOwnership;
            var  type        = MyDetectedEntityType.Unknown;
            var  name        = string.Empty;

            GridAi ai;

            GridAi.TargetInfo info = null;

            if (shooterGrid != null && topTarget != null && _session.GridToMasterAi.TryGetValue(shooterGrid, out ai) && ai.Targets.TryGetValue(topTarget, out info))
            {
                relation = info.EntInfo.Relationship;
                type     = info.EntInfo.Type;
            }

            if (!target.Item1 || e == null || topTarget?.Physics == null)
            {
                var projectile = target.Item2;
                var fake       = target.Item3;
                if (fake)
                {
                    name     = "ManualTargeting";
                    type     = MyDetectedEntityType.None;
                    entityId = -2;
                }
                else if (projectile)
                {
                    name     = "Projectile";
                    type     = MyDetectedEntityType.Missile;
                    entityId = -1;
                }
                return(new MyDetectedEntityInfo(entityId, name, type, info?.TargetPos, MatrixD.Zero, info != null ? (Vector3)info.Velocity : Vector3.Zero, relation, BoundingBoxD.CreateInvalid(), _session.Tick));
            }
            entityId = e.EntityId;
            var grid = topTarget as MyCubeGrid;

            if (grid != null)
            {
                name = block != null ? block.CustomName : grid.DisplayName;
            }
            else if (player != null)
            {
                name = player.GetFriendlyName();
            }
            else
            {
                name = e.GetFriendlyName();
            }

            return(new MyDetectedEntityInfo(entityId, name, type, e.PositionComp.WorldAABB.Center, e.PositionComp.WorldMatrixRef, topTarget.Physics.LinearVelocity, relation, e.PositionComp.WorldAABB, _session.Tick));
        }
        public static void InsertEntityInternalPostfix(MyEntity entity, ref MySafeZone __instance, ref bool __result)
        {
            if (!__result)
            {
                return;
            }
            var top = entity.GetTopMostParent();

            top.SetSafeZone(__instance);
        }
Beispiel #4
0
        private static void ConcealEntity(MyEntity entity)
        {
            int pos = 0;

            try
            {
                pos = 1;
                long ownerId = 0;
                if (((MyCubeGrid)entity).BigOwners.Count > 0)
                {
                    ownerId = ((MyCubeGrid)entity).BigOwners[0];
                }

                string ownerName = PlayerMap.Instance.GetPlayerNameFromPlayerId(ownerId);

                if (PluginSettings.Instance.DynamicShowMessages)
                {
                    Essentials.Log.Info($"{entity.EntityId} {ownerId} {ownerName}");
                }

                //pos = 2;
                //            if ( entity.Physics != null )
                //{
                //	entity.Physics.LinearVelocity = Vector3.Zero;
                //	entity.Physics.AngularVelocity = Vector3.Zero;
                //}

                //pos = 3;
                //if ( UnregisteredEntities.Contains( entity ) )
                //{
                //	Essentials.Log.Info( $"Concealing - Id: {entity.EntityId} DUPE FOUND - Display: {entity.DisplayName} OwnerId: {ownerId} OwnerName: {ownerName}");
                //    Wrapper.GameAction( entity.Close );
                //}
                pos = 4;
                //else
                //{
                //UnregisteredEntities.Add( entity );
                Wrapper.GameAction(() => UnregisterHierarchy(entity.GetTopMostParent(  )));
                if (PluginSettings.Instance.DynamicShowMessages)
                {
                    Essentials.Log.Info($"Concealed - Id: {entity.EntityId} -> Display: {entity.DisplayName} OwnerId: {ownerId} OwnerName: {ownerName}");
                }

                //}
            }
            catch (Exception ex)
            {
                Essentials.Log.Error(ex, $"Failure while concealing entity {pos}.");
            }
        }
Beispiel #5
0
        internal void LockTarget(Weapon w, MyEntity ent)
        {
            double rayDist;
            var    targetPos = ent.PositionComp.WorldAABB.Center;

            Vector3D.Distance(ref w.MyPivotPos, ref targetPos, out rayDist);
            var shortDist = rayDist - 1;
            var origDist  = rayDist;
            var topEntId  = ent.GetTopMostParent().EntityId;

            Set(ent, targetPos, shortDist, origDist, topEntId);
            if (w.System.Session.MpActive && !w.System.Session.IsClient)
            {
                PushTargetToClient(w);
            }
        }
Beispiel #6
0
        private MyDetectedEntityInfo GetEntityInfo(IMyEntity target, MyEntity shooter)
        {
            var e = target;

            if (e?.Physics == null)
            {
                return(new MyDetectedEntityInfo());
            }

            var shooterGrid = shooter.GetTopMostParent() as MyCubeGrid;

            GridAi ai;

            if (shooterGrid != null && _session.GridToMasterAi.TryGetValue(shooterGrid, out ai))
            {
                var maxDist = ai.MaxTargetingRange + shooterGrid.PositionComp.WorldAABB.Extents.Max();
                if (Vector3D.DistanceSquared(target.PositionComp.WorldMatrixRef.Translation, shooterGrid.PositionComp.WorldMatrixRef.Translation) > (maxDist * maxDist))
                {
                    return(new MyDetectedEntityInfo());
                }
            }

            var grid   = e.GetTopMostParent() as MyCubeGrid;
            var block  = e as IMyTerminalBlock;
            var player = e as IMyCharacter;

            string name;
            MyDetectedEntityType type;
            var relation = MyRelationsBetweenPlayerAndBlock.Enemies;

            if (grid != null)
            {
                name = block != null ? block.CustomName : grid.DisplayName;
                type = grid.GridSizeEnum == MyCubeSize.Large ? MyDetectedEntityType.LargeGrid : MyDetectedEntityType.SmallGrid;
            }
            else if (player != null)
            {
                type = MyDetectedEntityType.CharacterOther;
                name = player.GetFriendlyName();
            }
            else
            {
                type = MyDetectedEntityType.Unknown;
                name = e.GetFriendlyName();
            }
            return(new MyDetectedEntityInfo(e.EntityId, name, type, e.PositionComp.WorldAABB.Center, e.PositionComp.WorldMatrixRef, e.Physics.LinearVelocity, relation, e.PositionComp.WorldAABB, _session.Tick));
        }
Beispiel #7
0
 private void GetControlledEntity(out MyEntity controlledEntity, out bool hasControl)
 {
     controlledEntity = null;
     hasControl       = false;
     if ((!Sync.IsServer && ((base.EndpointId.Index == 0) && (MySession.Static.HasCreativeRights && ReferenceEquals(MySession.Static.CameraController, MySpectatorCameraController.Static)))) && ((MySpectatorCameraController.Static.SpectatorCameraMovement == MySpectatorCameraMovementEnum.UserControlled) || (MySpectatorCameraController.Static.SpectatorCameraMovement == MySpectatorCameraMovementEnum.Orbit)))
     {
         MyCharacter topMostControlledEntity = MySession.Static.TopMostControlledEntity as MyCharacter;
         if ((topMostControlledEntity == null) || !topMostControlledEntity.UpdateRotationsOverride)
         {
             return;
         }
     }
     foreach (KeyValuePair <long, MyPlayer.PlayerId> pair in Sync.Players.ControlledEntities)
     {
         if (pair.Value == new MyPlayer.PlayerId(base.EndpointId.Id.Value, base.EndpointId.Index))
         {
             controlledEntity = MyEntities.GetEntityById(pair.Key, false);
             if (controlledEntity != null)
             {
                 MyEntity topMostParent     = controlledEntity.GetTopMostParent(null);
                 MyPlayer controllingPlayer = Sync.Players.GetControllingPlayer(topMostParent);
                 if ((controllingPlayer != null) && (pair.Value == controllingPlayer.Id))
                 {
                     controlledEntity = topMostParent;
                 }
                 break;
             }
         }
     }
     if (controlledEntity != null)
     {
         if (Sync.IsServer)
         {
             hasControl = true;
         }
         else
         {
             MyPlayer player = this.GetPlayer();
             hasControl = ReferenceEquals(MySession.Static.LocalHumanPlayer, player);
         }
     }
 }
        private MyCubeGrid GetTargetShip()
        {
            MyEntity entity = MyCubeBuilder.Static.FindClosestGrid();

            if (entity == null)
            {
                var line = new LineD(MySector.MainCamera.Position, MySector.MainCamera.Position + MySector.MainCamera.ForwardVector * 10000);

                List <MyLineSegmentOverlapResult <MyEntity> > result = new List <MyLineSegmentOverlapResult <MyEntity> >();
                MyEntities.OverlapAllLineSegment(ref line, result);
                if (result.Count > 0)
                {
                    entity = result.OrderBy(s => s.Distance).First().Element;

                    entity = entity.GetTopMostParent();
                }
            }

            return(entity as MyCubeGrid);
        }
        public virtual void ClientUpdate(uint timestamp)
        {
            MyEntity entity = MySession.Static.ControlledEntity as MyEntity;

            if (entity == null || entity.GetTopMostParent() != Entity)
            {
                if (m_timestamp != null)
                {
                    m_timestamp.Clear();
                }
                return;
            }
            if (m_timestamp == null)
            {
                m_timestamp = new MyTimestampHelper(Entity);
            }

            m_timestamp.Update(timestamp);
            m_currentTimeStamp = timestamp;
        }
Beispiel #10
0
        /// <summary>
        /// Adjusts input for the autopilot's velocity and entity's velocity.
        /// </summary>
        /// <param name="input">Original TestInput with Direction as the desired direction of travel and Length as the distance to the destination.</param>
        /// <param name="adjusted">Offset will be zero, Direction and Length will be modified from input for the velocity of autopilot and entity.</param>
        /// <param name="entity">The potential obstruction, if null, assumes a static entity</param>
        public void AdjustForCurrentVelocity(ref TestInput input, out TestInput adjusted, MyEntity entity, bool destination)
        {
            Vector3 autopilotVelocity = AutopilotGrid.Physics.LinearVelocity;
            Vector3 relativeVelocity;

            if (entity == null)
            {
                relativeVelocity = autopilotVelocity;
            }
            else
            {
                MyPhysicsComponentBase physics = entity.GetTopMostParent().Physics;
                if (physics == null || physics.IsStatic)
                {
                    relativeVelocity = autopilotVelocity;
                }
                else
                {
                    Vector3 entityVelocity = physics.LinearVelocity;
                    Vector3.Subtract(ref autopilotVelocity, ref entityVelocity, out relativeVelocity);
                }
            }

            Vector3.Add(ref relativeVelocity, ref input.Direction, out adjusted.Direction);
            adjusted.Offset = Vector3D.Zero;
            if (adjusted.Direction == Vector3.Zero)
            {
                adjusted.Length = 0f;
            }
            else
            {
                adjusted.Length = 20f + adjusted.Direction.Normalize() * Pathfinder.SpeedFactor;
                if (destination && input.Length < adjusted.Length)
                {
                    adjusted.Length = input.Length;
                }
            }
        }
Beispiel #11
0
 public static bool IsTopMostParent <T>(this MyEntity self)
 {
     return(self.GetTopMostParent(typeof(T)) == self);
 }
Beispiel #12
0
        //  Update position, check collisions, etc.
        //  Return false if projectile dies/timeouts in this tick.
        public bool Update()
        {
            //  Projectile was killed , but still not last time drawn, so we don't need to do update (we are waiting for last draw)
            if (m_state == MyProjectileStateEnum.KILLED)
            {
                return(true);
            }
            //  Projectile was killed and last time drawn, so we can finally remove it from buffer
            if (m_state == MyProjectileStateEnum.KILLED_AND_DRAWN)
            {
                StopEffect();
                return(false);
            }

            Vector3D position = m_position;

            m_position += m_velocity * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * MyFakes.SIMULATION_SPEED;

            //  Distance timeout
            Vector3 positionDelta = m_position - m_origin;

            if (Vector3.Dot(positionDelta, positionDelta) >= m_maxTrajectory * m_maxTrajectory)
            {
                StopEffect();
                m_state = MyProjectileStateEnum.KILLED;
                return(true);
            }

            m_checkIntersectionIndex = ++m_checkIntersectionIndex % CHECK_INTERSECTION_INTERVAL;
            if (m_checkIntersectionIndex != 0 && m_positionChecked) //check only each n-th intersection
            {
                return(true);
            }

            //  Calculate hit point, create decal and throw debris particles
            Vector3D lineEndPosition = position + CHECK_INTERSECTION_INTERVAL * (m_velocity * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * MyFakes.SIMULATION_SPEED);

            LineD line = new LineD(m_positionChecked ? position : m_origin, lineEndPosition);

            m_positionChecked = true;

            IMyEntity entity;
            MyHitInfo hitInfo;
            object    customdata;

            GetHitEntityAndPosition(line, out entity, out hitInfo, out customdata);
            if (entity == null || entity.Physics == null)
            {
                return(true);
            }

            if (IsIgnoredEntity(entity))
            {
                return(true); // prevent player shooting himself
            }

            ProfilerShort.Begin("Projectile.Update");

            bool        headShot     = false;
            MyCharacter hitCharacter = entity as MyCharacter;

            if (hitCharacter != null)
            {
                IStoppableAttackingTool stoppableTool = hitCharacter.CurrentWeapon as IStoppableAttackingTool;
                if (stoppableTool != null)
                {
                    stoppableTool.StopShooting(OwnerEntity);
                }

                headShot = (customdata as MyCharacterHitInfo).HitHead && m_projectileAmmoDefinition.HeadShot; // allow head shots only for ammo supporting it in definition
            }

            m_position = hitInfo.Position;

            bool isProjectileGroupKilled = false;

            if (!isProjectileGroupKilled)
            {
                MySurfaceImpactEnum surfaceImpact;
                MyStringHash        materialType;
                GetSurfaceAndMaterial(entity, ref line, ref hitInfo.Position, out surfaceImpact, out materialType);

                PlayHitSound(materialType, entity, hitInfo.Position, m_projectileAmmoDefinition.PhysicalMaterial);

                hitInfo.Velocity = m_velocity;

                float damage = entity is IMyCharacter ? (headShot ? m_projectileAmmoDefinition.ProjectileHeadShotDamage : m_projectileAmmoDefinition.ProjectileHealthDamage) : m_projectileAmmoDefinition.ProjectileMassDamage;
                DoDamage(damage, hitInfo, customdata, entity);

                MyDecals.HandleAddDecal(entity, hitInfo, materialType, m_projectileAmmoDefinition.PhysicalMaterial, (customdata as MyCharacterHitInfo), damage);

                //particle effect defined in materialProperties.sbc
                Vector3D particleHitPosition = hitInfo.Position + (Vector3D)line.Direction * -0.2;
                bool     createdEffect       = MyMaterialPropertiesHelper.Static.TryCreateCollisionEffect(MyMaterialPropertiesHelper.CollisionType.Hit, particleHitPosition, hitInfo.Normal, m_projectileAmmoDefinition.PhysicalMaterial, materialType);
                if (!createdEffect && surfaceImpact != MySurfaceImpactEnum.CHARACTER)
                {
                    MyParticleEffects.CreateBasicHitParticles(m_projectileAmmoDefinition.ProjectileOnHitEffectName, ref hitInfo.Position, ref hitInfo.Normal, ref line.Direction, entity, m_weapon, 1, OwnerEntity);
                }

                CreateDecal(materialType);

                if (m_weapon == null || (entity.GetTopMostParent() != m_weapon.GetTopMostParent()))
                {
                    ApplyProjectileForce(entity, hitInfo.Position, m_directionNormalized, false, m_projectileAmmoDefinition.ProjectileHitImpulse * m_impulseMultiplier);
                }

                StopEffect();
                m_state = MyProjectileStateEnum.KILLED;
            }
            ProfilerShort.End();
            return(true);
        }
        //  Update position, check collisions, etc.
        //  Return false if projectile dies/timeouts in this tick.
        public bool Update()
        {
            //  Projectile was killed , but still not last time drawn, so we don't need to do update (we are waiting for last draw)
            if (m_state == MyProjectileStateEnum.KILLED)
            {
                return(true);
            }
            //  Projectile was killed and last time drawn, so we can finally remove it from buffer
            if (m_state == MyProjectileStateEnum.KILLED_AND_DRAWN)
            {
                StopEffect();
                return(false);
            }

            Vector3D position = m_position;

            m_position += m_velocity * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;

            //  Distance timeout
            Vector3 positionDelta = m_position - m_origin;

            if (Vector3.Dot(positionDelta, positionDelta) >= m_maxTrajectory * m_maxTrajectory)
            {
                StopEffect();
                m_state = MyProjectileStateEnum.KILLED;
                return(true);
            }

            m_checkIntersectionIndex = ++m_checkIntersectionIndex % CHECK_INTERSECTION_INTERVAL;
            if (m_checkIntersectionIndex != 0 && m_positionChecked) //check only each n-th intersection
            {
                return(true);
            }

            //  Calculate hit point, create decal and throw debris particles
            Vector3D lineEndPosition = position + CHECK_INTERSECTION_INTERVAL * (m_velocity * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);

            LineD line = new LineD(m_positionChecked ? position : m_origin, lineEndPosition);

            m_positionChecked = true;

            IMyEntity entity;
            Vector3D  hitPosition;
            Vector3   hitNormal;

            GetHitEntityAndPosition(line, out entity, out hitPosition, out hitNormal);
            if (entity == null || entity == m_ignoreEntity || entity.Physics == null)
            {
                return(true);
            }
            ProfilerShort.Begin("Projectile.Update");
            m_position = hitPosition;

            bool isProjectileGroupKilled = false;

            if (!isProjectileGroupKilled)
            {
                MySurfaceImpactEnum surfaceImpact;
                MyStringHash        materialType;
                GetSurfaceAndMaterial(entity, out surfaceImpact, out materialType);

                PlayHitSound(materialType, entity, hitPosition);
                DoDamage(hitPosition, entity);
                //  Create smoke and debris particle at the place of voxel/model hit

                if (surfaceImpact != MySurfaceImpactEnum.CHARACTER)
                {
                    m_projectileAmmoDefinition.ProjectileOnHitParticles(ref hitPosition, ref hitNormal, ref line.Direction, entity, m_weapon, 1, OwnerEntity);
                }
                m_projectileAmmoDefinition.ProjectileOnHitMaterialParticles(ref hitPosition, ref hitNormal, ref line.Direction, entity, surfaceImpact, m_weapon, 1);

                CreateDecal(materialType);

                if (m_weapon == null || (entity.GetTopMostParent() != m_weapon.GetTopMostParent()))
                {
                    ApplyProjectileForce(entity, hitPosition, m_directionNormalized, false, m_projectileAmmoDefinition.ProjectileHitImpulse * m_impulseMultiplier);
                }

                StopEffect();
                m_state = MyProjectileStateEnum.KILLED;
            }
            ProfilerShort.End();
            return(true);
        }
Beispiel #14
0
        private void Attach(MyEntity entity, Vector3 gearSpacePivot, Matrix otherBodySpacePivot)
        {
            if (CubeGrid.Physics != null && CubeGrid.Physics.Enabled)
            {
                var handle = StateChanged;

                if (Sync.IsServer && entity is MyCubeGrid)
                {
                    (entity as MyCubeGrid).OnGridSplit += CubeGrid_OnGridSplit;
                }

                if (MyFakes.WELD_LANDING_GEARS && CanWeldTo(entity, ref otherBodySpacePivot))
                {
                    if (m_attachedTo != null || entity == null)
                    {
                        return;
                    }

                    if (entity is MyVoxelBase)
                    {
                        if (CubeGrid.Physics.RigidBody.IsFixed == false && !CubeGrid.IsStatic)
                        {
                            CubeGrid.Physics.ConvertToStatic();
                            m_converted = true;
                        }
                    }
                    else
                    {
                        MyEntity parent = entity.GetTopMostParent();
                        MyWeldingGroups.Static.CreateLink(EntityId, CubeGrid, parent);
                    }
                    //OnConstraintAdded(GridLinkTypeEnum.LandingGear, entity);
                    m_lockModeSync.Value           = LandingGearMode.Locked;
                    m_attachedTo                   = entity;
                    m_attachedTo.OnPhysicsChanged += m_physicsChangedHandler;
                    this.OnPhysicsChanged         += m_physicsChangedHandler;
                    if (CanAutoLock)
                    {
                        ResetAutolock();
                    }

                    OnConstraintAdded(GridLinkTypeEnum.Physical, entity);
                    //OnConstraintAdded(GridLinkTypeEnum.NoContactDamage, entity);

                    if (!m_needsToRetryLock)
                    {
                        StartSound(m_lockSound);
                    }

                    if (handle != null)
                    {
                        handle(true);
                    }

                    return;
                }

                //var entity = body.GetBody().Entity;
                Debug.Assert(m_attachedTo == null, "Already attached");
                Debug.Assert(entity != null, "Landing gear is attached to body which has no entity");
                Debug.Assert(m_constraint == null);

                if (m_attachedTo != null || entity == null || m_constraint != null)
                {
                    return;
                }

                var body = entity.GetTopMostParent().Physics.RigidBody;

                body.Activate();
                CubeGrid.Physics.RigidBody.Activate();

                m_attachedTo = entity;

                m_attachedTo.OnPhysicsChanged += m_physicsChangedHandler;

                this.OnPhysicsChanged += m_physicsChangedHandler;

                Matrix gearLocalSpacePivot = Matrix.Identity;
                gearLocalSpacePivot.Translation = gearSpacePivot;

                var fixedData = new HkFixedConstraintData();
                if (MyFakes.OVERRIDE_LANDING_GEAR_INERTIA)
                {
                    fixedData.SetInertiaStabilizationFactor(MyFakes.LANDING_GEAR_INTERTIA);
                }
                else
                {
                    fixedData.SetInertiaStabilizationFactor(1);
                }

                fixedData.SetSolvingMethod(HkSolvingMethod.MethodStabilized);
                fixedData.SetInBodySpace(gearLocalSpacePivot, otherBodySpacePivot, CubeGrid.Physics, entity.Physics as MyPhysicsBody);

                HkConstraintData data = fixedData;

                if (MyFakes.LANDING_GEAR_BREAKABLE && BreakForce < MyObjectBuilder_LandingGear.MaxSolverImpulse)
                {
                    var breakData = new HkBreakableConstraintData(fixedData);
                    fixedData.Dispose();

                    breakData.Threshold = BreakForce;
                    breakData.ReapplyVelocityOnBreak = true;
                    breakData.RemoveFromWorldOnBrake = true;

                    data = breakData;
                }

                if (!m_needsToRetryLock)
                {
                    StartSound(m_lockSound);
                }

                m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, body, data);
                CubeGrid.Physics.AddConstraint(m_constraint);
                m_constraint.Enabled = true;

                m_lockModeSync.Value = LandingGearMode.Locked;
                if (CanAutoLock)
                {
                    ResetAutolock();
                }

                OnConstraintAdded(GridLinkTypeEnum.Physical, entity);
                OnConstraintAdded(GridLinkTypeEnum.NoContactDamage, entity);

                if (handle != null)
                {
                    handle(true);
                }
            }
        }
        //  Update position, check collisions, etc.
        //  Return false if projectile dies/timeouts in this tick.
        public bool Update()
        {
            //  Projectile was killed , but still not last time drawn, so we don't need to do update (we are waiting for last draw)
            if (m_state == MyProjectileStateEnum.KILLED)
            {
                return(true);
            }
            //  Projectile was killed and last time drawn, so we can finally remove it from buffer
            if (m_state == MyProjectileStateEnum.KILLED_AND_DRAWN)
            {
                StopEffect();
                return(false);
            }

            Vector3D position = m_position;

            m_position += m_velocity * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;

            //  Distance timeout
            Vector3 positionDelta = m_position - m_origin;

            if (Vector3.Dot(positionDelta, positionDelta) >= m_maxTrajectory * m_maxTrajectory)
            {
                StopEffect();
                m_state = MyProjectileStateEnum.KILLED;
                return(true);
            }

            m_checkIntersectionIndex = ++m_checkIntersectionIndex % CHECK_INTERSECTION_INTERVAL;
            if (m_checkIntersectionIndex != 0 && m_positionChecked) //check only each n-th intersection
            {
                return(true);
            }

            //  Calculate hit point, create decal and throw debris particles
            Vector3D lineEndPosition = position + CHECK_INTERSECTION_INTERVAL * (m_velocity * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);

            LineD line = new LineD(m_positionChecked ? position : m_origin, lineEndPosition);

            m_positionChecked = true;

            IMyEntity entity;
            Vector3D  hitPosition;
            Vector3   hitNormal;
            bool      headShot;

            GetHitEntityAndPosition(line, out entity, out hitPosition, out hitNormal, out headShot);
            if (entity == null || entity == m_ignoreEntity || entity.Physics == null)
            {
                return(true);
            }
            if ((m_ignoreEntity is IMyGunBaseUser) && (m_ignoreEntity as IMyGunBaseUser).Owner is MyCharacter &&
                (m_ignoreEntity as IMyGunBaseUser).Owner == entity)
            {
                return(true); // prevent player shooting himself
            }

            ProfilerShort.Begin("Projectile.Update");

            {
                MyCharacter hitCharacter = entity as MyCharacter;
                if (hitCharacter != null)
                {
                    IStoppableAttackingTool stoppableTool = hitCharacter.CurrentWeapon as IStoppableAttackingTool;
                    if (stoppableTool != null)
                    {
                        stoppableTool.StopShooting(OwnerEntity);
                    }
                }
            }

            m_position = hitPosition;

            bool isProjectileGroupKilled = false;

            if (!isProjectileGroupKilled)
            {
                MySurfaceImpactEnum surfaceImpact;
                MyStringHash        materialType;
                GetSurfaceAndMaterial(entity, ref hitPosition, out surfaceImpact, out materialType);

                PlayHitSound(materialType, entity, hitPosition);
                DoDamage(headShot ? m_projectileAmmoDefinition.ProjectileHeadShotDamage : m_projectileAmmoDefinition.ProjectileMassDamage, hitPosition, entity);
                //  Create smoke and debris particle at the place of voxel/model hit
                if (surfaceImpact != MySurfaceImpactEnum.CHARACTER)
                {
                    m_projectileAmmoDefinition.ProjectileOnHitParticles(ref hitPosition, ref hitNormal, ref line.Direction, entity, m_weapon, 1, OwnerEntity);
                }

                if (surfaceImpact == MySurfaceImpactEnum.CHARACTER && entity is MyCharacter)
                {
                    MyStringHash bullet = MyStringHash.GetOrCompute("RifleBullet");//temporary
                    MyMaterialPropertiesHelper.Static.TryCreateCollisionEffect(
                        MyMaterialPropertiesHelper.CollisionType.Start,
                        hitPosition,
                        hitNormal,
                        bullet, materialType);
                }

                Vector3D particleHitPosition = hitPosition + line.Direction * -0.2;
                m_projectileAmmoDefinition.ProjectileOnHitMaterialParticles(ref particleHitPosition, ref hitNormal, ref line.Direction, entity, surfaceImpact, m_weapon, 1);

                CreateDecal(materialType);

                if (m_weapon == null || (entity.GetTopMostParent() != m_weapon.GetTopMostParent()))
                {
                    ApplyProjectileForce(entity, hitPosition, m_directionNormalized, false, m_projectileAmmoDefinition.ProjectileHitImpulse * m_impulseMultiplier);
                }

                StopEffect();
                m_state = MyProjectileStateEnum.KILLED;
            }
            ProfilerShort.End();
            return(true);
        }
        private void Attach(MyEntity entity, Vector3 gearSpacePivot, Matrix otherBodySpacePivot)
        {
            if (CubeGrid.Physics != null && CubeGrid.Physics.Enabled)
            {
                var handle = StateChanged;

                if (Sync.IsServer && entity is MyCubeGrid)
                {
                    (entity as MyCubeGrid).OnGridSplit += CubeGrid_OnGridSplit;
                }

                if (MyFakes.WELD_LANDING_GEARS && CanWeldTo(entity, ref otherBodySpacePivot))
                {
                    if (m_attachedTo != null || entity == null)
                        return;

                    if (entity is MyVoxelBase)
                    {
                        if (CubeGrid.Physics.RigidBody.IsFixed == false)
                        {
                            CubeGrid.Physics.ConvertToStatic();
                            m_converted = true;
                        }
                    }
                    else
                    {
                        MyEntity parent = entity.GetTopMostParent();
                        MyWeldingGroups.Static.CreateLink(EntityId, CubeGrid, parent);
                    }
                    //OnConstraintAdded(GridLinkTypeEnum.LandingGear, entity);
                    m_lockModeSync.Value = LandingGearMode.Locked;
                    m_attachedTo = entity;
                    m_attachedTo.OnPhysicsChanged += m_physicsChangedHandler;
                    this.OnPhysicsChanged += m_physicsChangedHandler;
                    if (CanAutoLock)
                        ResetAutolock();

                    OnConstraintAdded(GridLinkTypeEnum.Physical, entity);
                    //OnConstraintAdded(GridLinkTypeEnum.NoContactDamage, entity);

                    if (!m_needsToRetryLock)
                        StartSound(m_lockSound);

                    if (handle != null) handle(true);

                    return;
                }

                //var entity = body.GetBody().Entity;
                Debug.Assert(m_attachedTo == null, "Already attached");
                Debug.Assert(entity != null, "Landing gear is attached to body which has no entity");
                Debug.Assert(m_constraint == null);

                if (m_attachedTo != null || entity == null || m_constraint != null)
                    return;

                var body = entity.GetTopMostParent().Physics.RigidBody;

                body.Activate();
                CubeGrid.Physics.RigidBody.Activate();

                m_attachedTo = entity;

                m_attachedTo.OnPhysicsChanged += m_physicsChangedHandler;

                this.OnPhysicsChanged += m_physicsChangedHandler;

                Matrix gearLocalSpacePivot = Matrix.Identity;
                gearLocalSpacePivot.Translation = gearSpacePivot;

                var fixedData = new HkFixedConstraintData();
                if (MyFakes.OVERRIDE_LANDING_GEAR_INERTIA)
                {
                    fixedData.SetInertiaStabilizationFactor(MyFakes.LANDING_GEAR_INTERTIA);
                }
                else
                {
                    fixedData.SetInertiaStabilizationFactor(1);
                }

                fixedData.SetSolvingMethod(HkSolvingMethod.MethodStabilized);
                fixedData.SetInBodySpace(gearLocalSpacePivot, otherBodySpacePivot, CubeGrid.Physics, entity.Physics as MyPhysicsBody);

                HkConstraintData data = fixedData;

                if (MyFakes.LANDING_GEAR_BREAKABLE && BreakForce < MyObjectBuilder_LandingGear.MaxSolverImpulse)
                {
                    var breakData = new HkBreakableConstraintData(fixedData);
                    fixedData.Dispose();

                    breakData.Threshold = BreakForce;
                    breakData.ReapplyVelocityOnBreak = true;
                    breakData.RemoveFromWorldOnBrake = true;

                    data = breakData;
                }

                if (!m_needsToRetryLock)
                    StartSound(m_lockSound);

                m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, body, data);
                CubeGrid.Physics.AddConstraint(m_constraint);
                m_constraint.Enabled = true;

                m_lockModeSync.Value = LandingGearMode.Locked;
                if (CanAutoLock)
                    ResetAutolock();

                OnConstraintAdded(GridLinkTypeEnum.Physical, entity);
                OnConstraintAdded(GridLinkTypeEnum.NoContactDamage, entity);

                if (handle != null) handle(true);
            }
        }
Beispiel #17
0
        internal bool CreateEntInfo(MyEntity entity, long gridOwner, out Sandbox.ModAPI.Ingame.MyDetectedEntityInfo entInfo)
        {
            if (entity == null)
            {
                entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo();
                return(false);
            }

            var topMostParent = entity.GetTopMostParent() as MyCubeGrid;

            if (topMostParent != null)
            {
                var type     = topMostParent.GridSizeEnum != MyCubeSize.Small ? Sandbox.ModAPI.Ingame.MyDetectedEntityType.LargeGrid : Sandbox.ModAPI.Ingame.MyDetectedEntityType.SmallGrid;
                var hasOwner = topMostParent.BigOwners.Count != 0;
                MyRelationsBetweenPlayerAndBlock relationship;
                if (hasOwner)
                {
                    var topOwner = topMostParent.BigOwners[0];
                    relationship = MyIDModule.GetRelationPlayerBlock(gridOwner, topOwner, MyOwnershipShareModeEnum.Faction);

                    if (relationship == MyRelationsBetweenPlayerAndBlock.Neutral)
                    {
                        var topFaction = MyAPIGateway.Session.Factions.TryGetPlayerFaction(topOwner);
                        if (topFaction != null)
                        {
                            var aiFaction = MyAPIGateway.Session.Factions.TryGetPlayerFaction(gridOwner);
                            if (aiFaction != null && MyAPIGateway.Session.Factions.GetReputationBetweenPlayerAndFaction(aiFaction.FactionId, topFaction.FactionId) < -500)
                            {
                                relationship = MyRelationsBetweenPlayerAndBlock.Enemies;
                            }
                        }
                    }
                }
                else
                {
                    relationship = MyRelationsBetweenPlayerAndBlock.Owner;
                }

                entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo(topMostParent.EntityId, string.Empty, type, null, MatrixD.Zero, Vector3.Zero, relationship, new BoundingBoxD(), Session.Tick);
                return(true);
            }

            var myCharacter = entity as IMyCharacter;

            if (myCharacter != null)
            {
                var controllingId = myCharacter.ControllerInfo?.ControllingIdentityId;
                var playerId      = controllingId ?? 0;

                var type = !myCharacter.IsPlayer ? Sandbox.ModAPI.Ingame.MyDetectedEntityType.CharacterOther : Sandbox.ModAPI.Ingame.MyDetectedEntityType.CharacterHuman;
                var relationPlayerBlock = MyIDModule.GetRelationPlayerBlock(gridOwner, playerId, MyOwnershipShareModeEnum.Faction);

                entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo(entity.EntityId, string.Empty, type, null, MatrixD.Zero, Vector3.Zero, relationPlayerBlock, new BoundingBoxD(), Session.Tick);
                return(!myCharacter.IsDead);
            }
            const MyRelationsBetweenPlayerAndBlock relationship1 = MyRelationsBetweenPlayerAndBlock.Neutral;
            var myPlanet = entity as MyPlanet;

            if (myPlanet != null)
            {
                const Sandbox.ModAPI.Ingame.MyDetectedEntityType type = Sandbox.ModAPI.Ingame.MyDetectedEntityType.Planet;
                entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo(entity.EntityId, string.Empty, type, null, MatrixD.Zero, Vector3.Zero, relationship1, new BoundingBoxD(), Session.Tick);
                return(true);
            }
            if (entity is MyVoxelMap)
            {
                const Sandbox.ModAPI.Ingame.MyDetectedEntityType type = Sandbox.ModAPI.Ingame.MyDetectedEntityType.Asteroid;
                entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo(entity.EntityId, string.Empty, type, null, MatrixD.Zero, Vector3.Zero, relationship1, new BoundingBoxD(), Session.Tick);
                return(true);
            }
            if (entity is MyMeteor)
            {
                const Sandbox.ModAPI.Ingame.MyDetectedEntityType type = Sandbox.ModAPI.Ingame.MyDetectedEntityType.Meteor;
                entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo(entity.EntityId, string.Empty, type, null, MatrixD.Zero, Vector3.Zero, MyRelationsBetweenPlayerAndBlock.Enemies, new BoundingBoxD(), Session.Tick);
                return(true);
            }
            entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo();
            return(false);
        }
        private static void ConcealEntity( MyEntity entity )
        {
            int pos = 0;
            try
            {
                pos = 1;
                long ownerId = 0;
                if ( ( (MyCubeGrid)entity ).BigOwners.Count > 0 )
                    ownerId = ( (MyCubeGrid)entity ).BigOwners[0];

                string ownerName = PlayerMap.Instance.GetPlayerNameFromPlayerId( ownerId );

                if ( PluginSettings.Instance.DynamicShowMessages )
                    Essentials.Log.Info($"{entity.EntityId} {ownerId} {ownerName}" );

                //pos = 2;
            //            if ( entity.Physics != null )
                //{
                //	entity.Physics.LinearVelocity = Vector3.Zero;
                //	entity.Physics.AngularVelocity = Vector3.Zero;
                //}

                //pos = 3;
                //if ( UnregisteredEntities.Contains( entity ) )
                //{
                //	Essentials.Log.Info( $"Concealing - Id: {entity.EntityId} DUPE FOUND - Display: {entity.DisplayName} OwnerId: {ownerId} OwnerName: {ownerName}");
                //    Wrapper.GameAction( entity.Close );
                //}
                pos = 4;
                //else
                //{
                    //UnregisteredEntities.Add( entity );
                    Wrapper.GameAction( () => UnregisterHierarchy( entity.GetTopMostParent(  ) ) );
                    if ( PluginSettings.Instance.DynamicShowMessages )
                        Essentials.Log.Info( $"Concealed - Id: {entity.EntityId} -> Display: {entity.DisplayName} OwnerId: {ownerId} OwnerName: {ownerName}" );

                //}
            }
            catch ( Exception ex )
            {
                Essentials.Log.Error( ex, $"Failure while concealing entity {pos}." );
            }
        }
        /// <summary>
        /// Handles camera collisions with environment
        /// </summary>
        /// <returns>False if no correct position was found</returns>
        private void HandleIntersection(MyEntity controlledEntity)
        {
            Debug.Assert(controlledEntity != null);
            MyEntity parentEntity = controlledEntity.GetTopMostParent() ?? controlledEntity;

            // line from target to eye
            LineD line = new LineD(m_target, m_position);
            // oriented bb of the entity
            MyOrientedBoundingBoxD safeObb = GetEntitySafeOBB(parentEntity);
            // oriented bb of the entity + camera radius
            MyOrientedBoundingBoxD safeObbWithCollisionExtents =
                new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + (controlledEntity.Parent == null ? 0.5 : 2.0) * CAMERA_RADIUS, safeObb.Orientation);

            // start = target, end = eye
            // find safe start...
            LineD    safeOBBLine      = new LineD(line.From + line.Direction * 2 * safeObb.HalfExtent.Length(), line.From);
            double?  safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
            Vector3D castStartSafe    = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target;

            if (controlledEntity.Parent != null && safeIntersection != null)
            {
                HkShape hkSphere = new HkSphereShape(CAMERA_RADIUS * 2);
                //var hitInfo = MyPhysics.CastRay(castStartSafe, m_target);

                MatrixD shapeCastStart = MatrixD.CreateTranslation(castStartSafe);
                var     hitInfo        = MyPhysics.CastShapeReturnContactBodyData(m_target, hkSphere, ref shapeCastStart, 0, 0);

                MyEntity hitEntity = hitInfo.HasValue ? hitInfo.Value.HkHitInfo.GetHitEntity() as MyEntity : null;
                MyEntity entity    = controlledEntity;

                var hitEntityWeldingGroup = hitEntity != null?MyWeldingGroups.Static.GetGroup(hitEntity) : null;

                bool weldingGroupEquals = false;

                while (entity != null && !weldingGroupEquals)
                {
                    if (hitEntityWeldingGroup == MyWeldingGroups.Static.GetGroup(entity))
                    {
                        weldingGroupEquals = true;
                    }

                    entity = entity.Parent;
                }

                if (hitInfo.HasValue && hitEntityWeldingGroup != null && weldingGroupEquals)
                {
                    castStartSafe = hitInfo.Value.Position + line.Direction;
                }
                else
                {
                    safeObb = GetEntitySafeOBB(controlledEntity);
                    safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + 0.5f * CAMERA_RADIUS, safeObb.Orientation);
                    safeIntersection            = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
                    castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target;
                }
                hkSphere.RemoveReference();
            }

            // raycast against occluders
            Vector3D safePositionCandidate;

            //double lastSafeMinimumDistance = m_safeMinimumDistance;
            m_safeMinimumDistance = controlledEntity is MyCharacter ? 0 : (castStartSafe - m_target).Length(); // store current safe minimum dist
            m_safeMinimumDistance = Math.Max(m_safeMinimumDistance, MIN_VIEWER_DISTANCE);
            //if (lastSafeMinimumDistance + 30.0f < m_safeMinimumDistance)
            //{
            //    castStartSafe = m_target + (castStartSafe - m_target) / m_safeMinimumDistance * lastSafeMinimumDistance;
            //    m_safeMinimumDistance = lastSafeMinimumDistance;
            //}
            Vector3D raycastOrigin = (controlledEntity is MyCharacter) ? m_target : castStartSafe;
            MyCameraRaycastResult raycastResult = RaycastOccludingObjects(controlledEntity, ref raycastOrigin, ref m_position,
                                                                          ref castStartSafe, out safePositionCandidate);

            // visual debugging :)
            if (m_debugDraw)
            {
                VRageRender.MyRenderProxy.DebugDrawOBB(safeObb, Color.Red, 0.1f, false, true);
                VRageRender.MyRenderProxy.DebugDrawOBB(safeObbWithCollisionExtents, Color.Yellow, 0.0f, false, true);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, safeOBBLine.To, Color.White, Color.Purple,
                                                           false);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, castStartSafe, Color.White, Color.Red,
                                                           false);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(castStartSafe, m_position, Color.White, Color.Orange, false);

                VRageRender.MyRenderProxy.DebugDrawSphere(castStartSafe, 0.2f, Color.Green, 1.0f, false, true);
            }

            switch (raycastResult)
            {
            case MyCameraRaycastResult.Ok:
            case MyCameraRaycastResult.FoundOccluder:
                m_positionCurrentIsSafe = true;
                {
                    double distFromCandidateToTarget = (safePositionCandidate - m_target).Length();
                    if ((distFromCandidateToTarget > m_lastRaycastDist + CAMERA_RADIUS && distFromCandidateToTarget > m_safeMinimumDistance) ||
                        raycastResult == MyCameraRaycastResult.Ok)
                    {
                        // now we need it from the other side
                        double newDist = (safePositionCandidate - m_position).Length();
                        // new safe position is further from target => change over time (zoom out)
                        if (m_positionSafeZoomingOutTimeout <= 0)
                        {
                            float distDiffZoomSpeed = 1 -
                                                      MathHelper.Clamp((float)Math.Abs(m_lastRaycastDist - newDist), 0.0f,
                                                                       1.0f - MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);
                            m_positionSafeZoomingOutSpeed += distDiffZoomSpeed;
                            m_positionSafeZoomingOutSpeed  = MathHelper.Clamp(m_positionSafeZoomingOutSpeed, 0.0f,
                                                                              1.0f);

                            Vector3D targetToPosSafe     = m_positionSafe - m_target;
                            double   lenTargetToPosSafe  = targetToPosSafe.Length();
                            Vector3D rotatedPositionSafe = m_target +
                                                           Vector3D.Normalize(safePositionCandidate - m_target) *
                                                           lenTargetToPosSafe;
                            m_positionSafe = Vector3D.Lerp(rotatedPositionSafe, safePositionCandidate,
                                                           m_positionSafeZoomingOutSpeed);
                        }
                        else
                        {
                            m_positionSafeZoomingOutTimeout -= MyEngineConstants.UPDATE_STEP_SIZE_IN_MILLISECONDS;

                            Vector3D targetToPosSafe    = m_positionSafe - m_target;
                            double   lenTargetToPosSafe = targetToPosSafe.Length();
                            m_positionSafe = m_target + Vector3D.Normalize(safePositionCandidate - m_target) * lenTargetToPosSafe;
                        }
                    }
                    else
                    {
                        // new safe position is closer or closer than safe distance => instant change
                        m_positionSafeZoomingOutSpeed = 0.0f;   // set zooming out speed to zero for next time
                        m_positionSafe = safePositionCandidate;
                        m_positionSafeZoomingOutTimeout = 0;    // controlledEntity.Parent != null ? m_positionSafeZoomingOutDefaultTimeoutMs : 0;
                        m_disableSpringThisFrame        = true;
                    }
                }
                break;

            //case MyCameraRaycastResult.FoundOccluderNoSpace:
            default:
                m_positionSafeZoomingOutSpeed = 1.0f;     // we're in first person, change instantly to third if possible
                m_positionCurrentIsSafe       = false;
                break;
            }

            m_lastRaycastDist = (float)(m_positionSafe - m_position).Length();

            if (m_debugDraw)
            {
                VRageRender.MyRenderProxy.DebugDrawSphere(m_positionSafe, 0.225f, Color.Purple, 1, false);
                VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 0.2f, Color.Azure, 1, false);
            }
        }
        /// <summary>
        /// Handles camera collisions with environment
        /// </summary>
        /// <returns>False if no correct position was found</returns>
        private void HandleIntersection(MyEntity controlledEntity)
        {
            Debug.Assert(controlledEntity != null);
            MyEntity parentEntity = controlledEntity.GetTopMostParent() ?? controlledEntity;
            var parentEntityAsCubeGrid = parentEntity as MyCubeGrid;
            if (parentEntityAsCubeGrid != null && parentEntityAsCubeGrid.IsStatic)
                parentEntity = controlledEntity;  // cancel previous assignment, topmost parent is a station, we need smaller bounding box

            // line from target to eye
            LineD line = new LineD(m_target, m_position);
            // oriented bb of the entity
            MyOrientedBoundingBoxD safeObb = GetEntitySafeOBB(parentEntity);
            // oriented bb of the entity + camera radius
            MyOrientedBoundingBoxD safeObbWithCollisionExtents = 
                new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + (controlledEntity.Parent == null ? 0.5 : 2.0) * CAMERA_RADIUS, safeObb.Orientation);

            // start = target, end = eye
            // find safe start...
            LineD safeOBBLine = new LineD(line.From + line.Direction * 2 * safeObb.HalfExtent.Length(), line.From);
            double? safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
            Vector3D castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target;

            if (controlledEntity.Parent != null && safeIntersection != null)
            {
                MatrixD shapeCastStart = MatrixD.CreateTranslation(castStartSafe);
                HkShape hkSphere = new HkSphereShape(CAMERA_RADIUS * 2);
                var hitInfo = MyPhysics.CastShapeReturnContactBodyData(m_target, hkSphere, ref shapeCastStart, 0, 0);

                //VRageRender.MyRenderProxy.DebugDrawCapsule(castStartSafe, m_target, CAMERA_RADIUS * 2, Color.Orange, false);
                
                MyEntity hitEntity = hitInfo.HasValue ? hitInfo.Value.HkHitInfo.GetHitEntity() as MyEntity : null;
                MyEntity entity = controlledEntity;

                var hitEntityWeldingGroup = hitEntity != null ? MyWeldingGroups.Static.GetGroup(hitEntity) : null;
                bool weldingGroupEquals = false;

                while (entity != null && !weldingGroupEquals)
                {
                    if (hitEntityWeldingGroup == MyWeldingGroups.Static.GetGroup(entity))
                        weldingGroupEquals = true;

                    entity = entity.Parent;
                }

                if (hitInfo.HasValue && hitEntityWeldingGroup != null && weldingGroupEquals)
                {
                    castStartSafe = castStartSafe + hitInfo.Value.HkHitInfo.HitFraction * (m_target - castStartSafe);
                }
                else
                {
                    safeObb = GetEntitySafeOBB(controlledEntity);
                    safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + 0.5f * CAMERA_RADIUS, safeObb.Orientation);
                    safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
                    castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target;
                }
                hkSphere.RemoveReference();
            }

            // raycast against occluders
            Vector3D safePositionCandidate;
            //double lastSafeMinimumDistance = m_safeMinimumDistance;
            m_safeMinimumDistance = controlledEntity is MyCharacter ? 0 : (castStartSafe - m_target).Length(); // store current safe minimum dist
            m_safeMinimumDistance = Math.Max(m_safeMinimumDistance, MIN_VIEWER_DISTANCE);
            //if (lastSafeMinimumDistance + 30.0f < m_safeMinimumDistance)
            //{
            //    castStartSafe = m_target + (castStartSafe - m_target) / m_safeMinimumDistance * lastSafeMinimumDistance;
            //    m_safeMinimumDistance = lastSafeMinimumDistance;
            //}
            Vector3D raycastOrigin = (controlledEntity is MyCharacter) ? m_target : castStartSafe;
            MyCameraRaycastResult raycastResult = RaycastOccludingObjects(controlledEntity, ref raycastOrigin, ref m_position,
                ref castStartSafe, out safePositionCandidate);

            // visual debugging :)
            if (m_debugDraw)
            {
                VRageRender.MyRenderProxy.DebugDrawOBB(safeObb, Color.Red, 0.1f, false, true);
                VRageRender.MyRenderProxy.DebugDrawOBB(safeObbWithCollisionExtents, Color.Yellow, 0.0f, false, true);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, safeOBBLine.To, Color.White, Color.Purple,
                    false);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, castStartSafe, Color.White, Color.Red,
                    false);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(castStartSafe, m_position, Color.White, Color.Orange, false);

                VRageRender.MyRenderProxy.DebugDrawSphere(castStartSafe, 0.2f, Color.Green, 1.0f, false, true);
                VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 1.0f, Color.LightPink, 1, false);
            }

            switch (raycastResult)
            {
                case MyCameraRaycastResult.Ok:
                case MyCameraRaycastResult.FoundOccluder:
                    m_positionCurrentIsSafe = true;
                    {
                        double distFromCandidateToTarget = (safePositionCandidate - m_target).Length();
                        if (m_disableSpringThisFrame)
                        {
                            m_lastRaycastDist = (float) distFromCandidateToTarget;
                        }

                        if (!m_disableSpringThisFrame && 
                            ((distFromCandidateToTarget > m_lastRaycastDist + CAMERA_RADIUS && distFromCandidateToTarget > m_safeMinimumDistance)
                            || raycastResult == MyCameraRaycastResult.Ok))
                        {
                            // now we need it from the other side
                            double newDist = (safePositionCandidate - m_position).Length();
                            // new safe position is further from target => change over time (zoom out)
                            if (m_positionSafeZoomingOutTimeout <= 0)
                            {
                                float distDiffZoomSpeed = 1 -
                                                          MathHelper.Clamp((float) Math.Abs(m_lastRaycastDist - newDist), 0.0f,
                                                              1.0f - MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);
                                m_positionSafeZoomingOutSpeed += distDiffZoomSpeed;
                                m_positionSafeZoomingOutSpeed = MathHelper.Clamp(m_positionSafeZoomingOutSpeed, 0.0f,
                                    1.0f);

                                Vector3D targetToPosSafe = m_positionSafe - m_target;
                                double lenTargetToPosSafe = targetToPosSafe.Length();
                                Vector3D rotatedPositionSafe = m_target +
                                                               Vector3D.Normalize(safePositionCandidate - m_target) *
                                                               lenTargetToPosSafe;
                                m_positionSafe = Vector3D.Lerp(rotatedPositionSafe, safePositionCandidate,
                                    m_positionSafeZoomingOutSpeed);
                            }
                            else
                            {
                                m_positionSafeZoomingOutTimeout -= MyEngineConstants.UPDATE_STEP_SIZE_IN_MILLISECONDS;

                                Vector3D targetToPosSafe = m_positionSafe - m_target;
                                double lenTargetToPosSafe = targetToPosSafe.Length();
                                m_positionSafe = m_target + Vector3D.Normalize(safePositionCandidate - m_target) * lenTargetToPosSafe;
                            }
                        }
                        else
                        {
                            // new safe position is closer or closer than safe distance => instant change
                            m_positionSafeZoomingOutSpeed = 0.0f;    // set zooming out speed to zero for next time
                            m_positionSafeZoomingOutTimeout = 0;// controlledEntity.Parent != null ? m_positionSafeZoomingOutDefaultTimeoutMs : 0;
                            m_positionSafe = safePositionCandidate;
                            m_disableSpringThisFrame = true;
                            m_positionCurrentIsSafe = distFromCandidateToTarget >= m_safeMinimumDistance;
                        }
                    }
                    break;
                //case MyCameraRaycastResult.FoundOccluderNoSpace:
                default:
                    m_positionSafeZoomingOutSpeed = 1.0f; // we're in first person, change instantly to third if possible
                    m_positionCurrentIsSafe = false;
                    break;    
            }

            m_lastRaycastDist = (float)(m_positionSafe - m_position).Length();

            if (m_debugDraw)
            {
                VRageRender.MyRenderProxy.DebugDrawSphere(m_positionSafe, 0.225f, Color.Purple, 1, false);
                VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 0.2f, Color.Azure, 1, false);
            }
        }
        private static void MoveInternal(MyEntity entity)
        {
            if (entity.Parent != null && (entity.Flags & EntityFlags.IsGamePrunningStructureObject) == 0)
                return;
            ProfilerShort.Begin(string.Format("Move:{0}", (entity.GetTopMostParent() == entity ? "Topmost" : "Child")));
            if (entity.TopMostPruningProxyId != MyVRageConstants.PRUNING_PROXY_ID_UNITIALIZED)
            {
                BoundingBoxD bbox = GetEntityAABB(entity);

                if (bbox.Size == Vector3D.Zero)  // remove entities with zero bounding boxes
                {
                    Remove(entity);
                    ProfilerShort.End();
                    return;
                }

                var voxelMap = entity as MyVoxelBase;
                if (voxelMap != null)
                {
                    m_voxelMapsTree.MoveProxy(voxelMap.VoxelMapPruningProxyId, ref bbox, Vector3D.Zero);
                }

                if (entity.TopMostPruningProxyId != MyVRageConstants.PRUNING_PROXY_ID_UNITIALIZED)
                {
                    bool stat = IsEntityStatic(entity);

                    // Swap trees if necessary.
                    if (stat != entity.StaticForPruningStructure)
                    {
                        if (entity.StaticForPruningStructure)
                        {
                            m_staticObjectsTree.RemoveProxy(entity.TopMostPruningProxyId);
                            entity.TopMostPruningProxyId = m_dynamicObjectsTree.AddProxy(ref bbox, entity, 0);
                        }
                        else
                        {
                            m_dynamicObjectsTree.RemoveProxy(entity.TopMostPruningProxyId);
                            entity.TopMostPruningProxyId = m_staticObjectsTree.AddProxy(ref bbox, entity, 0);
                        }
                        entity.StaticForPruningStructure = stat;
                    }
                    else
                    {
                        if (entity.StaticForPruningStructure)
                            m_staticObjectsTree.MoveProxy(entity.TopMostPruningProxyId, ref bbox, Vector3D.Zero);
                        else
                            m_dynamicObjectsTree.MoveProxy(entity.TopMostPruningProxyId, ref bbox, Vector3D.Zero);
                    }
                }
            }
            ProfilerShort.End();
        }
Beispiel #22
0
        internal bool CreateEntInfo(MyEntity entity, long gridOwner, out Sandbox.ModAPI.Ingame.MyDetectedEntityInfo entInfo)
        {
            try
            {
                MyRelationsBetweenPlayerAndBlock relationship = MyRelationsBetweenPlayerAndBlock.Neutral;
                if (entity == null)
                {
                    entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo();
                    return(false);
                }
                var grid = entity.GetTopMostParent() as MyCubeGrid;
                if (grid != null)
                {
                    if (!grid.DestructibleBlocks || grid.Immune || grid.GridGeneralDamageModifier <= 0)
                    {
                        entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo();
                        return(false);
                    }

                    var bigOwners = grid.BigOwners;
                    var topOwner  = bigOwners.Count > 0 ? bigOwners[0] : long.MaxValue;

                    relationship = topOwner != long.MaxValue ? MyIDModule.GetRelationPlayerBlock(gridOwner, topOwner, MyOwnershipShareModeEnum.Faction) : MyRelationsBetweenPlayerAndBlock.NoOwnership;

                    var type = grid.GridSizeEnum != MyCubeSize.Small ? Sandbox.ModAPI.Ingame.MyDetectedEntityType.LargeGrid : Sandbox.ModAPI.Ingame.MyDetectedEntityType.SmallGrid;
                    entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo(grid.EntityId, string.Empty, type, null, MatrixD.Zero, Vector3.Zero, relationship, new BoundingBoxD(), Session.Tick);
                    return(true);
                }

                var myCharacter = entity as IMyCharacter;
                if (myCharacter != null)
                {
                    var type = !myCharacter.IsPlayer ? Sandbox.ModAPI.Ingame.MyDetectedEntityType.CharacterOther : Sandbox.ModAPI.Ingame.MyDetectedEntityType.CharacterHuman;

                    var getComponentOwner = entity as IMyComponentOwner <MyIDModule>;

                    long       playerId;
                    MyIDModule targetIdModule;
                    if (getComponentOwner != null && getComponentOwner.GetComponent(out targetIdModule))
                    {
                        playerId = targetIdModule.Owner;
                    }
                    else
                    {
                        var controllingId = myCharacter.ControllerInfo?.ControllingIdentityId;
                        playerId = controllingId ?? 0;
                    }

                    relationship = MyIDModule.GetRelationPlayerBlock(gridOwner, playerId, MyOwnershipShareModeEnum.Faction);

                    entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo(entity.EntityId, string.Empty, type, null, MatrixD.Zero, Vector3.Zero, relationship, new BoundingBoxD(), Session.Tick);
                    return(!myCharacter.IsDead && myCharacter.Integrity > 0);
                }

                var myPlanet = entity as MyPlanet;

                if (myPlanet != null)
                {
                    const Sandbox.ModAPI.Ingame.MyDetectedEntityType type = Sandbox.ModAPI.Ingame.MyDetectedEntityType.Planet;
                    entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo(entity.EntityId, string.Empty, type, null, MatrixD.Zero, Vector3.Zero, relationship, new BoundingBoxD(), Session.Tick);
                    return(true);
                }
                if (entity is MyVoxelMap)
                {
                    const Sandbox.ModAPI.Ingame.MyDetectedEntityType type = Sandbox.ModAPI.Ingame.MyDetectedEntityType.Asteroid;
                    entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo(entity.EntityId, string.Empty, type, null, MatrixD.Zero, Vector3.Zero, relationship, new BoundingBoxD(), Session.Tick);
                    return(true);
                }
                if (entity is MyMeteor)
                {
                    const Sandbox.ModAPI.Ingame.MyDetectedEntityType type = Sandbox.ModAPI.Ingame.MyDetectedEntityType.Meteor;
                    entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo(entity.EntityId, string.Empty, type, null, MatrixD.Zero, Vector3.Zero, MyRelationsBetweenPlayerAndBlock.Enemies, new BoundingBoxD(), Session.Tick);
                    return(true);
                }
            }
            catch (Exception ex) { Log.Line($"Exception in CreateEntInfo: {ex}"); }

            entInfo = new Sandbox.ModAPI.Ingame.MyDetectedEntityInfo();
            return(false);
        }