示例#1
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);
        }
示例#2
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 * 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;
            bool      headShot;

            GetHitEntityAndPosition(line, out entity, out hitPosition, out hitNormal, out headShot);
            if (entity == null || entity == m_ignoreEntity || entity.Physics == null)
            {
                return(true);
            }

            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);
                }
                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);
        }