public override void UpdateBeforeSimulation()
        {
            try
            {
                MyRender.GetRenderProfiler().StartProfilingBlock("MyCannonShot.UpdateBeforeSimulation");

                if (this.WorldMatrix.Translation != m_previousPosition)
                {
                    MyLine line = new MyLine(this.WorldMatrix.Translation, m_previousPosition);
                    MyDangerZones.Instance.Notify(line, OwnerEntity);
                }

                //  Kill this missile
                if (m_isExploded && !m_wasPenetration)
                {
                    //  Create explosion
                    MyExplosion newExplosion = MyExplosions.AddExplosion();
                    if (newExplosion != null)
                    {
                        float           radius          = MyMwcUtils.GetRandomFloat(m_ammoProperties.ExplosionRadius - 2, m_ammoProperties.ExplosionRadius + 2);
                        BoundingSphere  explosionSphere = new BoundingSphere((m_collisionPoint.HasValue ? m_collisionPoint.Value : GetPosition()), radius);
                        MyExplosionInfo info            = new MyExplosionInfo(m_ammoProperties.HealthDamage, m_ammoProperties.ShipDamage, m_ammoProperties.EMPDamage, explosionSphere, m_explosionType, true)
                        {
                            GroupMask            = Physics.GroupMask,
                            CascadeLevel         = CascadedExplosionLevel,
                            HitEntity            = m_collidedEntity,
                            OwnerEntity          = this.OwnerEntity,
                            Direction            = WorldMatrix.Forward,
                            ParticleScale        = 1.5f,
                            VoxelExplosionCenter = explosionSphere.Center + radius * WorldMatrix.Forward * 0.6f,
                        };
                        info.CreateParticleEffect = !m_hasExplosion;
                        newExplosion.Start(ref info);
                    }

                    if (m_collidedEntity != null && !m_collidedEntity.IsExploded())
                    {
                        m_collidedEntity.Physics.AddForce(
                            MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE,
                            WorldMatrix.Forward * MyMissileConstants.HIT_STRENGTH_IMPULSE,
                            GetPosition() + MyMwcUtils.GetRandomVector3Normalized() * 2,
                            MyMissileConstants.HIT_STRENGTH_IMPULSE * MyMwcUtils.GetRandomVector3Normalized());
                    }

                    MarkForClose();

                    return;
                }

                base.UpdateBeforeSimulation();

                //  Chech timeout and max distance
                if ((m_elapsedMiliseconds > MyCannonConstants.SHOT_TIMEOUT) || (Vector3.Distance(this.WorldMatrix.Translation, m_origin) >= m_ammoProperties.MaxTrajectory))
                {
                    MarkForClose();
                    return;
                }



                Matrix orientation = GetWorldRotation();

                //  Update thruster cue/sound
                MyAudio.UpdateCuePosition(m_thrusterCue, this.WorldMatrix.Translation, orientation.Forward, orientation.Up, this.Physics.LinearVelocity);

                Vector3 pos = this.WorldMatrix.Translation;

                if (m_penetratedVoxelMap == null)
                {
                    if (m_smokeEffect != null)
                    {
                        m_smokeEffect.WorldMatrix = WorldMatrix;
                    }
                }

                /*
                 * if (m_wasPenetration)
                 * {
                 * //  Create explosion
                 * MyExplosion newExplosion = MyExplosions.AddExplosion();
                 * if (newExplosion != null)
                 * {
                 * float radius = MyMwcUtils.GetRandomFloat(1, 2);
                 * float particleScale = 2.2f; // must be large enough to cover the hole
                 * newExplosion.StartWithPositionOffset(m_ammoProperties.HealthDamage, m_ammoProperties.ShipDamage, m_ammoProperties.EMPDamage, m_explosionType, m_penetrationOrigin - WorldMatrix.Forward * 2, radius, MyExplosionsConstants.EXPLOSION_LIFESPAN, CascadedExplosionLevel, particleScale: particleScale, hitEntity: m_collidedEntity, ownerEntity: m_ownerEntity);
                 * }
                 * m_wasPenetration = false;
                 * m_hasExplosion = true;
                 * }        */

                if (m_usedAmmo.AmmoType == MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Proximity_Explosive)
                {
                    //  Look for small ships in shots's proximity
                    BoundingSphere boundingSphere = new BoundingSphere(GetPosition(), MyCannonShotConstants.PROXIMITY_DETECTION_RADIUS);
                    BoundingBox    boundingBox    = new BoundingBox();
                    BoundingBox.CreateFromSphere(ref boundingSphere, out boundingBox);

                    var elements = MyEntities.GetElementsInBox(ref boundingBox);
                    for (int i = 0; i < elements.Count; i++)
                    {
                        var rigidBody = (MyPhysicsBody)elements[i].GetRigidBody().m_UserData;
                        var entity    = rigidBody.Entity;


                        if (!(entity is MinerWars.AppCode.Game.Entities.MySmallShip))
                        {
                            continue;
                        }
                        if (entity == OwnerEntity)
                        {
                            continue;
                        }
                        if (entity == this)
                        {
                            continue;
                        }

                        Explode(entity);
                        break;
                    }
                    elements.Clear();
                }

                /*
                 * if (m_usedAmmo.AmmoType == MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Tunnel_Buster)
                 * {
                 *  m_cuttingSphere.Center = GetPosition();
                 *
                 *  //  We found voxel so lets make tunel into it
                 *  MyPhysObjectBase collisionResult = MyEntities.GetIntersectionWithSphere(ref m_cuttingSphere, this, (MySmallShip)Parent);
                 *  if (collisionResult is MyVoxelMap)
                 *  {
                 *      MyVoxelMap voxelMap = collisionResult as MyVoxelMap;
                 *      if (m_penetratedVoxelMap == null)
                 *      {
                 *          m_penetratedVoxelMap = voxelMap;
                 *          m_penetrationOrigin = GetPosition();
                 *      }
                 *
                 *      Game.Voxels.MyVoxelGenerator.CutOutSphereFast(voxelMap, m_cuttingSphere);
                 *  }
                 * } */
                /*
                 * if (m_usedAmmo.AmmoType == MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Tunnel_Buster)
                 * {
                 * if (m_penetratedVoxelMap != null)
                 * {
                 * //MyCannonShotConstants.BUSTER_PENETRATION_LENGTH
                 * float busterPenetrationLength = m_ammoProperties.ExplosionRadius * 0.75f;
                 * if (Vector3.Distance(m_penetrationOrigin, GetPosition()) >= busterPenetrationLength)
                 * {
                 *    m_collisionPoint = GetPosition(); //We want to explode inside voxel, not on collision point
                 *    Explode(m_penetratedVoxelMap);
                 * }
                 * }
                 * }    */
            }
            finally
            {
                MyRender.GetRenderProfiler().EndProfilingBlock();
            }
        }
Beispiel #2
0
        /// <summary>
        /// Updates resource.
        /// </summary>
        public override void UpdateBeforeSimulation()
        {
            try
            {
                MyRender.GetRenderProfiler().StartProfilingBlock("MyMissile.UpdateBeforeSimulation");

                //Large ship weapons wont make bots curious
                if ((!(OwnerEntity is MyLargeShipMissileLauncherBarrel)) && MyMwcUtils.HasValidLength(this.WorldMatrix.Translation - m_previousPosition))
                {
                    MyLine line = new MyLine(this.WorldMatrix.Translation, m_previousPosition);
                    MyDangerZones.Instance.Notify(line, OwnerEntity);
                }

                if (m_isExploded)
                {
                    //  Create explosion
                    MyExplosion newExplosion = MyExplosions.AddExplosion();
                    if (newExplosion != null)
                    {
                        float radius = m_ammoProperties.ExplosionRadius;

                        // Explicitly on Marek's request (ticket 4740)
                        bool amplifyRadius = m_collidedEntity != null?MyFactions.GetFactionsRelation(m_collidedEntity.Faction, Faction) != MyFactionRelationEnum.Friend : false;

                        if (amplifyRadius)
                        {
                            radius *= 2;
                        }

                        BoundingSphere explosionSphere = new BoundingSphere(m_collisionPoint.HasValue ? m_collisionPoint.Value : GetPosition(), radius);

                        //  Call main explosion starter
                        MyExplosionInfo info = new MyExplosionInfo()
                        {
                            PlayerDamage            = m_ammoProperties.HealthDamage,
                            Damage                  = m_ammoProperties.ShipDamage,
                            EmpDamage               = m_ammoProperties.EMPDamage,
                            ExplosionType           = m_explosionType,
                            ExplosionSphere         = explosionSphere,
                            LifespanMiliseconds     = MyExplosionsConstants.EXPLOSION_LIFESPAN,
                            ExplosionForceDirection = MyExplosionForceDirection.EXPLOSION,
                            GroupMask               = Physics.GroupMask,
                            CascadeLevel            = CascadedExplosionLevel,
                            HitEntity               = m_collidedEntity,
                            ParticleScale           = 1.5f,
                            OwnerEntity             = this.OwnerEntity,
                            Direction               = WorldMatrix.Forward,
                            VoxelExplosionCenter    = explosionSphere.Center + m_ammoProperties.ExplosionRadius * WorldMatrix.Forward * 0.5f,
                            ExplosionFlags          = MyExplosionFlags.AFFECT_VOXELS | MyExplosionFlags.APPLY_FORCE_AND_DAMAGE | MyExplosionFlags.CREATE_DEBRIS | MyExplosionFlags.CREATE_DECALS | MyExplosionFlags.CREATE_PARTICLE_EFFECT,
                            VoxelCutoutScale        = amplifyRadius ? 0.5f : 1.0f,
                            PlaySound               = true,
                        };

                        newExplosion.Start(ref info);
                    }

                    if (m_collidedEntity != null && !m_collidedEntity.IsExploded())
                    {
                        m_collidedEntity.Physics.AddForce(
                            MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE,
                            WorldMatrix.Forward * MyMissileConstants.HIT_STRENGTH_IMPULSE,
                            GetPosition() + MyMwcUtils.GetRandomVector3Normalized() * 2,
                            MyMissileConstants.HIT_STRENGTH_IMPULSE * MyMwcUtils.GetRandomVector3Normalized());
                        m_collidedEntity.OnClose -= m_collidedEntity_OnClose;
                    }

                    MarkForClose();

                    return;
                }

                bool firstTargetting = m_elapsedMiliseconds == 0;

                base.UpdateBeforeSimulation();

                m_missileTargetUpdate += MyConstants.PHYSICS_STEP_SIZE_IN_MILLISECONDS;

                if (m_missileTargetUpdate >= MyGuidedMissileConstants.MISSILE_TARGET_UPDATE_INTERVAL_IN_MS || firstTargetting)
                {
                    m_missileTargetUpdate = 0;

                    switch (m_missileType)
                    {
                    case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Guided_Missile_Radar_Detection:
                    {
                        MySmallShip targetShip = m_targetEntity as MySmallShip;
                        if (targetShip != null && targetShip.IsRadarJammed())
                        {
                            m_targetEntity = null;
                        }
                    }
                    break;

                    case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Guided_Missile_Engine_Detection:
                    {
                        m_targetEntities.Clear();

                        Matrix proj = Matrix.CreateOrthographic(MyGuidedMissileConstants.ENGINE_GUIDED_MISSILE_RADIUS, MyGuidedMissileConstants.ENGINE_GUIDED_MISSILE_RADIUS, 0, 1000);
                        Matrix view = Matrix.CreateLookAt(GetPosition(), GetPosition() + WorldMatrix.Forward, WorldMatrix.Up);
                        m_visualFrustum.Matrix = view * proj;

                        MyEntities.GetAllIntersectionWithBoundingFrustum(ref m_visualFrustum, m_targetEntities);

                        if (m_targetEntities.Contains(m_targetEntity))
                        {
                            break;
                        }

                        MyEntity target = null;
                        float    closestToMissileDirection = float.MaxValue;

                        foreach (MyEntity entity in m_targetEntities)
                        {
                            if (CanTarget(entity))
                            {
                                MySmallShip targetShip = entity as MySmallShip;
                                if (targetShip != null)
                                {
                                    if ((targetShip.IsEngineTurnedOff()))
                                    {
                                        continue;
                                    }
                                }

                                Vector3 targetPos     = entity.GetPosition();
                                Vector3 missilePos    = this.GetPosition();
                                Vector3 missilePosEnd = this.GetPosition() + this.WorldMatrix.Forward * 10000;
                                Vector3 closestPos    = MyUtils.GetClosestPointOnLine(ref missilePos, ref missilePosEnd, ref targetPos);

                                float distance = Vector3.Distance(closestPos, targetPos);
                                if (distance < closestToMissileDirection)
                                {
                                    closestToMissileDirection = distance;
                                    target = entity;
                                }
                            }
                        }

                        UpdateTarget(target);
                    }
                    break;

                    case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Guided_Missile_Visual_Detection:
                    {
                        Matrix projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(MyGuidedMissileConstants.VISUAL_GUIDED_MISSILE_FOV), 1, 10, MyGuidedMissileConstants.VISUAL_GUIDED_MISSILE_RANGE);
                        m_visualFrustum.Matrix = Matrix.Invert(WorldMatrix) * projectionMatrix;

                        m_targetEntities.Clear();
                        MyEntities.GetAllIntersectionWithBoundingFrustum(ref m_visualFrustum, m_targetEntities);
                        int testsLimit = 8;

                        if (m_targetEntities.Contains(m_targetEntity))
                        {
                            break;
                        }

                        MyEntity target = null;         //looks better if missile gets "lost"

                        float closestToMissileDirection = float.MaxValue;

                        foreach (MyEntity entity in m_targetEntities)
                        {
                            if (!CanTarget(entity))
                            {
                                continue;
                            }

                            if (testsLimit-- == 0)
                            {
                                break;
                            }

                            if (MyEnemyTargeting.CanSee(this, entity) == null)
                            {
                                Vector3 targetPos     = entity.GetPosition();
                                Vector3 missilePos    = this.GetPosition();
                                Vector3 missilePosEnd = this.GetPosition() + this.WorldMatrix.Forward * 10000;
                                Vector3 closestPos    = MyUtils.GetClosestPointOnLine(ref missilePos, ref missilePosEnd, ref targetPos);

                                float distance = Vector3.Distance(closestPos, targetPos);
                                if (distance < closestToMissileDirection)
                                {
                                    closestToMissileDirection = distance;
                                    target = entity;
                                }
                            }
                        }

                        UpdateTarget(target);
                    }
                    break;
                    }
                }

                if ((m_initTime - m_elapsedMiliseconds) > 0)
                {   //simulating missile launch and engine ignition
                    MyEntity owner = OwnerEntity;
                    if (owner != null)
                    {
                        Vector3 transformedInitDir = Vector3.TransformNormal(m_initDir, owner.WorldMatrix); //
                        Vector3 initialVelocity    = Vector3.Zero;
                        if (owner.Physics != null)
                        {
                            initialVelocity = owner.Physics.LinearVelocity;
                        }
                        Physics.LinearVelocity = transformedInitDir * m_ammoProperties.InitialSpeed + initialVelocity;
                    }
                }
                else
                {
                    //  This will help blend "initial velocity" and "thrust velocity" so at the beginning missile is powered by initiatal velocity only, but later
                    float velocityBlend = MathHelper.Clamp((float)(m_elapsedMiliseconds - m_initTime) / m_blendVelocities, 0, 1);

                    if (velocityBlend == 1.0f)
                    {
                        m_actualSpeed = m_ammoProperties.DesiredSpeed;
                    }
                    else
                    {
                        float    initialSpeed = 0.0f;
                        MyEntity owner        = OwnerEntity;
                        if (owner != null)
                        {
                            if (owner.Physics != null)
                            {
                                initialSpeed = owner.Physics.LinearVelocity.Length();
                            }
                        }

                        m_actualSpeed = velocityBlend * m_ammoProperties.DesiredSpeed + ((1.0f - velocityBlend) * (m_ammoProperties.InitialSpeed + initialSpeed));

                        if (m_missileType != MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Missile_Basic && m_smokeEffect == null)
                        {
                            // if (MyCamera.GetDistanceWithFOV(GetPosition()) < 150)
                            {
                                /*
                                 * MyParticleEffect startEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_MissileStart);
                                 * startEffect.WorldMatrix = WorldMatrix;
                                 */
                                m_smokeEffect             = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_Missile);
                                m_smokeEffect.WorldMatrix = WorldMatrix;
                                m_smokeEffect.AutoDelete  = false;
                            }
                        }
                    }

                    m_desiredVelocity = GetDesiredVelocity(m_targetEntity);

                    Physics.LinearVelocity = m_desiredVelocity * m_actualSpeed * 1.0f;
                }

                Physics.AngularVelocity = Vector3.Zero;

                if ((m_elapsedMiliseconds > m_missileTimeout) || (Vector3.Distance(GetPosition(), m_origin) >= m_maxTrajectory))
                {
                    Explode();
                    return;
                }


                if (m_smokeEffect != null)
                {
                    Matrix smokeMatrix = Matrix.CreateWorld(WorldMatrix.Translation - 0.5f * WorldMatrix.Forward, WorldMatrix.Forward, WorldMatrix.Up);
                    m_smokeEffect.WorldMatrix = smokeMatrix;
                }

                if (m_targetEntity != null)
                {
                    if (m_targetEntity.Physics != null)
                    {
                        m_targetVelocity = m_targetEntity.Physics.LinearVelocity;
                    }
                    else
                    {
                        m_targetVelocity = Vector3.Zero;
                    }
                }
            }
            finally
            {
                MyRender.GetRenderProfiler().EndProfilingBlock();
            }
        }