Пример #1
0
        /// <param name="damage">Not used for now but could be used as a multiplier instead of random decal size</param>
        public static void HandleAddDecal(IMyEntity entity, MyHitInfo hitInfo, MyStringHash source = default(MyStringHash), float damage = -1)
        {
            IMyDecalProxy proxy = entity as IMyDecalProxy;

            if (proxy != null)
            {
                AddDecal(proxy, ref hitInfo, damage, source);
                return;
            }

            MyCubeGrid grid = entity.GetTopMostParent() as MyCubeGrid;

            if (grid != null)
            {
                var block = grid.GetTargetedBlock(hitInfo.Position);
                if (block != null)
                {
                    var compoundBlock = block.FatBlock as MyCompoundCubeBlock;
                    if (compoundBlock == null)
                    {
                        proxy = block;
                    }
                    else
                    {
                        proxy = compoundBlock;
                    }
                }
            }

            if (proxy != null)
            {
                AddDecal(proxy, ref hitInfo, damage, source);
            }
        }
        void IMyDecalProxy.AddDecals(MyHitInfo hitInfo, MyStringHash source, object customdata, IMyDecalHandler decalHandler)
        {
            Debug.Assert(m_mapIdToBlock.Count > 0);
            MyCubeGridHitInfo            gridHitInfo      = customdata as MyCubeGridHitInfo;
            MySlimBlock                  block            = m_mapIdToBlock.First().Value;
            MyPhysicalMaterialDefinition physicalMaterial = block.BlockDefinition.PhysicalMaterial;
            MyDecalRenderInfo            renderable       = new MyDecalRenderInfo();

            renderable.Flags          = physicalMaterial.Transparent ? MyDecalFlags.Transparent : MyDecalFlags.None;
            renderable.Position       = Vector3D.Transform(hitInfo.Position, CubeGrid.PositionComp.WorldMatrixInvScaled);
            renderable.Normal         = Vector3D.TransformNormal(hitInfo.Normal, CubeGrid.PositionComp.WorldMatrixInvScaled);
            renderable.RenderObjectId = CubeGrid.Render.GetRenderObjectID();
            renderable.Material       = MyStringHash.GetOrCompute(physicalMaterial.Id.SubtypeName);

            if (gridHitInfo != null)
            {
                VertexBoneIndicesWeights?boneIndicesWeights = gridHitInfo.Triangle.GetAffectingBoneIndicesWeights(ref m_boneIndexWeightTmp);
                if (boneIndicesWeights.HasValue)
                {
                    renderable.BoneIndices = boneIndicesWeights.Value.Indices;
                    renderable.BoneWeights = boneIndicesWeights.Value.Weights;

                    var decalId = decalHandler.AddDecal(ref renderable);
                    if (decalId != null)
                    {
                        CubeGrid.RenderData.AddDecal(Position, gridHitInfo, decalId.Value);
                    }

                    return;
                }
            }

            decalHandler.AddDecal(ref renderable);
        }
Пример #3
0
 void IMyDecalProxy.AddDecals(ref MyHitInfo hitInfo, MyStringHash source, object customdata, IMyDecalHandler decalHandler, MyStringHash material)
 {
     MyCubeGrid.MyCubeGridHitInfo gridHitInfo = customdata as MyCubeGrid.MyCubeGridHitInfo;
     if (gridHitInfo != null)
     {
         MyPhysicalMaterialDefinition physicalMaterial = this.m_mapIdToBlock.First <KeyValuePair <ushort, MySlimBlock> >().Value.BlockDefinition.PhysicalMaterial;
         MyDecalRenderInfo            renderInfo       = new MyDecalRenderInfo {
             Position        = Vector3D.Transform(hitInfo.Position, base.CubeGrid.PositionComp.WorldMatrixInvScaled),
             Normal          = (Vector3)Vector3D.TransformNormal(hitInfo.Normal, base.CubeGrid.PositionComp.WorldMatrixInvScaled),
             RenderObjectIds = base.CubeGrid.Render.RenderObjectIDs,
             Source          = source
         };
         VertexBoneIndicesWeights?affectingBoneIndicesWeights = gridHitInfo.Triangle.GetAffectingBoneIndicesWeights(ref m_boneIndexWeightTmp);
         if (affectingBoneIndicesWeights != null)
         {
             renderInfo.BoneIndices = affectingBoneIndicesWeights.Value.Indices;
             renderInfo.BoneWeights = affectingBoneIndicesWeights.Value.Weights;
         }
         renderInfo.Material = (material.GetHashCode() != 0) ? material : MyStringHash.GetOrCompute(physicalMaterial.Id.SubtypeName);
         m_tmpIds.Clear();
         decalHandler.AddDecal(ref renderInfo, m_tmpIds);
         foreach (uint num in m_tmpIds)
         {
             base.CubeGrid.RenderData.AddDecal(base.Position, gridHitInfo, num);
         }
     }
 }
Пример #4
0
        private bool fireAt(Vector3 target)
        {
            List <IHitInfo> hits = new List <IHitInfo>();

            MyAPIGateway.Physics.CastRay(animator.getMuzzlePosition(), target, hits);
            //drawDebugLine(animator.grid.GetPosition(), target);
            IHitInfo hitInfo;

            if (findFirstNonNPC(hits, out hitInfo, true))
            {
                var entity = hitInfo.HitEntity;

                var clearLOS = isEnemy(entity);
                if (!clearLOS)
                {
                    return(false);
                }

                var grid = entity as MyCubeGrid;
                IMyDestroyableObject destroyable;

                spawnImpactParticle(hitInfo.Position, hitInfo.Normal);
                spawnLaunchParticle(animator.getMuzzlePosition(), -animator.grid.WorldMatrix.Forward);
                //spawnLaunchParticle(animator.getMuzzlePosition(), target - animator.getMuzzlePosition());
                weaponLineAnimator.addAnim(animator.getMuzzlePosition(), hitInfo.Position);
                //spawnLaunchParticle(animator.grid.GetPosition(), hitInfo.Position - animator.grid.GetPosition());
                shotAnimDur = 0;

                if (grid != null)
                {
                    if (grid.Physics == null || !grid.Physics.Enabled || !grid.BlocksDestructionEnabled)
                    {
                        return(false);
                    }

                    var block = grid.GetTargetedBlock(hitInfo.Position) as IMySlimBlock;

                    if (block == null)
                    {
                        return(false);
                    }

                    var myHitInfo = new MyHitInfo {
                        Position = hitInfo.Position, Normal = hitInfo.Normal
                    };
                    grid.DoDamage(damage, myHitInfo, null, animator.grid.EntityId);
                    return(true);
                }
                else if ((destroyable = entity as IMyDestroyableObject) != null)
                {
                    var myHitInfo = new MyHitInfo {
                        Position = hitInfo.Position, Normal = hitInfo.Normal
                    };
                    destroyable.DoDamage(damage, MyDamageType.Bullet, true, myHitInfo, animator.grid.EntityId);
                    return(true);
                }
            }

            return(false);
        }
Пример #5
0
        /// <param name="damage">Not used for now but could be used as a multiplier instead of random decal size</param>
        public static void HandleAddDecal(IMyEntity entity, MyHitInfo hitInfo, MyStringHash material = default(MyStringHash), MyStringHash source = default(MyStringHash), object customdata = null, float damage = -1)
        {
            IMyDecalProxy proxy = entity as IMyDecalProxy;

            if (proxy != null)
            {
                AddDecal(proxy, ref hitInfo, damage, source, customdata, material);
                return;
            }

            MyCubeGrid grid = entity as MyCubeGrid;

            if (grid != null)
            {
                MyCubeGridHitInfo info = customdata as MyCubeGridHitInfo;
                MySlimBlock       block;
                if (info == null)
                {
                    block = grid.GetTargetedBlock(hitInfo.Position);
                    if (block == null)
                    {
                        return;
                    }

                    // If info is not provided, provide info with just block position
                    m_gridHitInfo.Position = block.Position;
                    customdata             = m_gridHitInfo;
                }
                else
                {
                    // If info is provided, lookup for the cube using provided position
                    MyCube cube;
                    bool   found = grid.TryGetCube(info.Position, out cube);
                    if (!found)
                    {
                        return;
                    }

                    block = cube.CubeBlock;
                }

                var compoundBlock = block != null ? block.FatBlock as MyCompoundCubeBlock : null;
                if (compoundBlock == null)
                {
                    proxy = block;
                }
                else
                {
                    proxy = compoundBlock;
                }
            }

            if (proxy == null)
            {
                return;
            }

            AddDecal(proxy, ref hitInfo, damage, source, customdata, material);
        }
Пример #6
0
 void IMyDecalProxy.GetDecalRenderData(MyHitInfo hitInfo, out MyDecalRenderData renderable)
 {
     renderable                = new MyDecalRenderData();
     renderable.Position       = hitInfo.Position;
     renderable.Normal         = hitInfo.Normal;
     renderable.RenderObjectId = Render.GetRenderObjectID();
     renderable.Material       = Physics.GetMaterialAt(hitInfo.Position);
 }
Пример #7
0
        void IMyDecalProxy.AddDecals(MyHitInfo hitInfo, MyStringHash source, object customdata, IMyDecalHandler decalHandler)
        {
            MyDecalRenderInfo info = new MyDecalRenderInfo();

            info.Position       = hitInfo.Position;
            info.Normal         = hitInfo.Normal;
            info.RenderObjectId = -1;
            info.Flags          = MyDecalFlags.World;
            info.Material       = Physics.MaterialType;
            decalHandler.AddDecal(ref info);
        }
Пример #8
0
        void IMyDecalProxy.GetDecalRenderData(MyHitInfo hitInfo, out MyDecalRenderData renderable)
        {
            Debug.Assert(m_mapIdToBlock.Count > 0);
            MySlimBlock block = m_mapIdToBlock.First().Value;

            renderable                = new MyDecalRenderData();
            renderable.Position       = Vector3D.Transform(hitInfo.Position, CubeGrid.PositionComp.WorldMatrixInvScaled);
            renderable.Normal         = Vector3D.TransformNormal(hitInfo.Normal, CubeGrid.PositionComp.WorldMatrixInvScaled);
            renderable.RenderObjectId = CubeGrid.Render.GetRenderObjectID();
            renderable.Material       = MyStringHash.GetOrCompute(block.BlockDefinition.PhysicalMaterial.Id.SubtypeName);
        }
Пример #9
0
        private Vector3D PlaceDecal()
        {
            Vector3D  explosionPoint = m_collisionPoint.Value;
            MyHitInfo hitInfo        = new MyHitInfo()
            {
                Position = explosionPoint, Normal = m_collisionNormal
            };

            MyDecals.HandleAddDecal(m_collidedEntity, hitInfo, this.m_missileAmmoDefinition.PhysicalMaterial);
            return(explosionPoint);
        }
Пример #10
0
        private static void AddDecal(IMyDecalProxy proxy, ref MyHitInfo hitInfo, float damage, MyStringHash source, object customdata)
        {
            bool skip = DefaultFilterProxy(proxy);
            if (skip)
                return;

            m_handler.Source = source;
            m_handler.Enabled = true;
            proxy.AddDecals(hitInfo, source, customdata, m_handler);
            m_handler.Enabled = false;
            m_handler.Source = MyStringHash.NullOrEmpty;
        }
Пример #11
0
        void IMyDecalProxy.AddDecals(MyHitInfo hitInfo, MyStringHash source, object customdata, IMyDecalHandler decalHandler)
        {
            MyDecalRenderInfo renderable = new MyDecalRenderInfo();

            renderable.Flags          = MyDecalFlags.World;
            renderable.Position       = hitInfo.Position;
            renderable.Normal         = hitInfo.Normal;
            renderable.RenderObjectId = Render.GetRenderObjectID();
            renderable.Material       = Physics.GetMaterialAt(hitInfo.Position);

            decalHandler.AddDecal(ref renderable);
        }
Пример #12
0
        void IMyDecalProxy.AddDecals(ref MyHitInfo hitInfo, MyStringHash source, object customdata, IMyDecalHandler decalHandler, MyStringHash material)
        {
            MyDecalRenderInfo renderInfo = new MyDecalRenderInfo {
                Position        = hitInfo.Position,
                Normal          = hitInfo.Normal,
                RenderObjectIds = null,
                Flags           = MyDecalFlags.World,
                Source          = source
            };

            renderInfo.Material = (material.GetHashCode() != 0) ? material : base.Physics.MaterialType;
            decalHandler.AddDecal(ref renderInfo, null);
        }
        void IMyDecalProxy.AddDecals(MyHitInfo hitInfo, MyStringHash source, object customdata, IMyDecalHandler decalHandler)
        {
            Debug.Assert(m_mapIdToBlock.Count > 0);
            MySlimBlock block = m_mapIdToBlock.First().Value;
            MyPhysicalMaterialDefinition physicalMaterial = block.BlockDefinition.PhysicalMaterial;
            MyDecalRenderInfo            renderable       = new MyDecalRenderInfo();

            renderable.Flags          = physicalMaterial.Transparent ? MyDecalFlags.Transparent : MyDecalFlags.None;
            renderable.Position       = Vector3D.Transform(hitInfo.Position, CubeGrid.PositionComp.WorldMatrixInvScaled);
            renderable.Normal         = Vector3D.TransformNormal(hitInfo.Normal, CubeGrid.PositionComp.WorldMatrixInvScaled);
            renderable.RenderObjectId = CubeGrid.Render.GetRenderObjectID();
            renderable.Material       = MyStringHash.GetOrCompute(physicalMaterial.Id.SubtypeName);

            var decalId = decalHandler.AddDecal(ref renderable);

            if (decalId != null)
            {
                CubeGrid.RenderData.AddDecal(Position, decalId.Value);
            }
        }
Пример #14
0
        public override void UpdateAfterSimulation()
        {
            base.UpdateAfterSimulation();

            bool isShooting = IsShooting;

            if (!m_isHit && IsShooting && (MySandboxGame.Static.UpdateTime - m_lastShot > MyTimeSpan.FromSeconds(m_shotToolAction.Value.HitStart)))
            {
                IMyHandToolComponent toolComponent;
                if (m_toolComponents.TryGetValue(m_shotHitCondition.Component, out toolComponent))
                {
                    MyCharacterDetectorComponent detectorComponent = m_owner.Components.Get <MyCharacterDetectorComponent>();
                    if (detectorComponent != null)
                    {
                        if (m_shotToolAction.Value.CustomShapeRadius > 0 && detectorComponent is MyCharacterShapecastDetectorComponent)
                        {
                            var shapeCastComponent = detectorComponent as MyCharacterShapecastDetectorComponent;
                            shapeCastComponent.ShapeRadius = m_shotToolAction.Value.CustomShapeRadius;
                            shapeCastComponent.DoDetectionModel();
                            shapeCastComponent.ShapeRadius = MyCharacterShapecastDetectorComponent.DEFAULT_SHAPE_RADIUS;
                        }

                        if (detectorComponent.DetectedEntity != null)
                        {
                            MyHitInfo hitInfo = new MyHitInfo();
                            hitInfo.Position = detectorComponent.HitPosition;
                            hitInfo.Normal   = detectorComponent.HitNormal;

                            bool  isBlock = false;
                            float efficiencyMultiplier = 1.0f;
                            bool  canHit = CanHit(toolComponent, detectorComponent, ref isBlock, out efficiencyMultiplier);

                            MyDecals.HandleAddDecal(detectorComponent.DetectedEntity, hitInfo, MyDamageType.Weapon);

                            bool isHit = false;
                            if (canHit)
                            {
                                if (!string.IsNullOrEmpty(m_shotToolAction.Value.StatsEfficiency) && Owner.StatComp != null)
                                {
                                    efficiencyMultiplier *= Owner.StatComp.GetEfficiencyModifier(m_shotToolAction.Value.StatsEfficiency);
                                }

                                float efficiency = m_shotToolAction.Value.Efficiency * efficiencyMultiplier;
                                var   tool       = detectorComponent.DetectedEntity as MyHandToolBase;
                                if (isBlock && tool != null)
                                {
                                    isHit = toolComponent.Hit(tool.Owner, hitInfo, detectorComponent.ShapeKey, efficiency);
                                }
                                else
                                {
                                    isHit = toolComponent.Hit((MyEntity)detectorComponent.DetectedEntity, hitInfo, detectorComponent.ShapeKey, efficiency);
                                }

                                if (isHit && Sync.IsServer && Owner.StatComp != null)
                                {
                                    if (!string.IsNullOrEmpty(m_shotHitCondition.StatsActionIfHit))
                                    {
                                        Owner.StatComp.DoAction(m_shotHitCondition.StatsActionIfHit);
                                    }
                                    if (!string.IsNullOrEmpty(m_shotHitCondition.StatsModifierIfHit))
                                    {
                                        Owner.StatComp.ApplyModifier(m_shotHitCondition.StatsModifierIfHit);
                                    }
                                }
                            }

                            if (canHit || isBlock)  // real hit is not controlled now - there isn't any server-client synchronization of hit currently and hit is performed only at server
                            {
                                if (!string.IsNullOrEmpty(m_shotToolAction.Value.HitSound))
                                {
                                    PlaySound(m_shotToolAction.Value.HitSound);
                                }
                                else
                                {
                                    MyStringId collisionType = MyMaterialPropertiesHelper.CollisionType.Hit;
                                    bool       showParticles = false;

                                    // If it didn't play the Sound with "Hit", it will try with "Start"
                                    if (MyAudioComponent.PlayContactSound(EntityId, m_hitCue, detectorComponent.HitPosition,
                                                                          m_toolItemDef.PhysicalMaterial, detectorComponent.HitMaterial))
                                    {
                                        showParticles = true;
                                    }
                                    else if (MyAudioComponent.PlayContactSound(EntityId, m_startCue, detectorComponent.HitPosition,
                                                                               m_toolItemDef.PhysicalMaterial, detectorComponent.HitMaterial))
                                    {
                                        showParticles = true;
                                        collisionType = MyMaterialPropertiesHelper.CollisionType.Start;
                                    }

                                    if (showParticles)
                                    {
                                        MyMaterialPropertiesHelper.Static.TryCreateCollisionEffect(
                                            collisionType,
                                            detectorComponent.HitPosition,
                                            detectorComponent.HitNormal,
                                            m_toolItemDef.PhysicalMaterial, detectorComponent.HitMaterial);
                                    }
                                }

                                this.RaiseEntityEvent(MyStringHash.GetOrCompute("Hit"), new MyEntityContainerEventExtensions.HitParams(MyStringHash.GetOrCompute(m_shotHitCondition.Component), detectorComponent.HitMaterial));
                                m_soundEmitter.StopSound(true);
                            }
                        }
                    }
                }

                m_isHit = true;
            }

            if (!m_swingSoundPlayed && IsShooting && !m_isHit && (MySandboxGame.Static.UpdateTime - m_lastShot > MyTimeSpan.FromSeconds(m_shotToolAction.Value.SwingSoundStart)))
            {
                if (!string.IsNullOrEmpty(m_shotToolAction.Value.SwingSound))
                {
                    PlaySound(m_shotToolAction.Value.SwingSound);
                }
                m_swingSoundPlayed = true;
            }


            if (!isShooting && m_wasShooting)
            {
                m_owner.StopUpperCharacterAnimation(0.4f);
                m_shotToolAction = null;
            }


            m_wasShooting = isShooting;

            if (m_owner != null)
            {
                MatrixD blockingMatrix = MatrixD.CreateWorld(((MyEntity)m_owner.CurrentWeapon).PositionComp.GetPosition(), m_owner.WorldMatrix.Forward, m_owner.WorldMatrix.Up);

                ((MyBlockingBody)Physics).SetWorldMatrix(blockingMatrix);
            }


            foreach (var c in m_toolComponents.Values)
            {
                c.Update();
            }
        }
Пример #15
0
        private void GetHitEntityAndPosition(LineD line, out IMyEntity entity, out Vector3D hitPosition, out Vector3 hitNormal, out bool hitHead)
        {
            entity      = null;
            hitPosition = hitNormal = Vector3.Zero;
            hitHead     = false;

            // 1. rough raycast
            if (entity == null)
            {
                ProfilerShort.Begin("MyGamePruningStructure::CastProjectileRay");
                MyPhysics.HitInfo?hitInfo = MyPhysics.CastRay(line.From, line.To, MyPhysics.CollisionLayers.DefaultCollisionLayer);
                ProfilerShort.End();
                if (hitInfo.HasValue)
                {
                    entity      = hitInfo.Value.HkHitInfo.GetHitEntity() as MyEntity;
                    hitPosition = hitInfo.Value.Position;
                    hitNormal   = hitInfo.Value.HkHitInfo.Normal;
                }
            }

            // 2. prevent shooting through characters, retest trajectory between entity and player
            if (!(entity is MyCharacter) || entity == null)
            {
                // first: raycast, get all entities in line, limit distance if possible
                LineD lineLimited = new LineD(line.From, entity == null ? line.To : hitPosition);
                if (m_entityRaycastResult == null)
                {
                    m_entityRaycastResult = new List <MyLineSegmentOverlapResult <MyEntity> >(16);
                }
                else
                {
                    m_entityRaycastResult.Clear();
                }
                MyGamePruningStructure.GetAllEntitiesInRay(ref lineLimited, m_entityRaycastResult);
                // second: precise tests, find best result
                double    bestDistanceSq = double.MaxValue;
                IMyEntity entityBest     = null;
                for (int i = 0; i < m_entityRaycastResult.Count; i++)
                {
                    if (m_entityRaycastResult[i].Element is MyCharacter)
                    {
                        MyCharacter hitCharacter = m_entityRaycastResult[i].Element as MyCharacter;
                        VRage.Game.Models.MyIntersectionResultLineTriangleEx?t;
                        hitCharacter.GetIntersectionWithLine(ref line, out t, out hitHead);

                        if (t != null)
                        {
                            double distanceSq = Vector3D.DistanceSquared(t.Value.IntersectionPointInWorldSpace, line.From);
                            if (distanceSq < bestDistanceSq)
                            {
                                bestDistanceSq = distanceSq;
                                entityBest     = hitCharacter;
                                hitPosition    = t.Value.IntersectionPointInWorldSpace;
                                hitNormal      = t.Value.NormalInWorldSpace;
                            }
                        }
                    }
                }
                // finally: do we have best result? then return it
                if (entityBest != null)
                {
                    entity = entityBest;
                    return; // this was precise result, so return
                }
            }

            // 3. nothing found in the precise test? then fallback to already found results
            if (entity == null)
            {
                return;                // no fallback results
            }
            if (entity is MyCharacter) // retest character found in fallback
            {
                MyCharacter hitCharacter = entity as MyCharacter;
                VRage.Game.Models.MyIntersectionResultLineTriangleEx?t;
                hitCharacter.GetIntersectionWithLine(ref line, out t, out hitHead);
                if (t == null)
                {
                    entity = null; // no hit.
                }
                else
                {
                    hitPosition = t.Value.IntersectionPointInWorldSpace;
                    hitNormal   = t.Value.NormalInWorldSpace;
                    hitHead     = hitHead && m_projectileAmmoDefinition.HeadShot; // allow head shots only for ammo supporting it in definition
                }
            }
            else
            {
                MyCubeGrid grid = entity as MyCubeGrid;
                if (grid != null)
                {
                    MyIntersectionResultLineTriangleEx?result;
                    bool success = grid.GetIntersectionWithLine(ref line, out result);
                    if (success)
                    {
                        hitPosition = result.Value.IntersectionPointInWorldSpace;
                        hitNormal   = result.Value.NormalInWorldSpace;
                    }

                    MyHitInfo info = new MyHitInfo();
                    info.Position = hitPosition;
                    info.Normal   = hitNormal;
                }
            }
        }
Пример #16
0
        private void DoDamage(float damage, MyHitInfo hitInfo, object customdata, IMyEntity damagedEntity)
        {
            //damage tracking
            MyEntity ent = (MyEntity)MySession.Static.ControlledEntity;

            if (this.OwnerEntityAbsolute != null && this.OwnerEntityAbsolute.Equals(MySession.Static.ControlledEntity) && (damagedEntity is IMyDestroyableObject || damagedEntity is MyCubeGrid))
            {
                MySession.Static.TotalDamageDealt += (uint)damage;
            }

            if (!Sync.IsServer)
            {
                return;
            }

            if (m_projectileAmmoDefinition.PhysicalMaterial == m_hashBolt)
            {
                IMyDestroyableObject destroyable = damagedEntity as IMyDestroyableObject;
                if (destroyable != null && damagedEntity is MyCharacter)
                {
                    destroyable.DoDamage(damage, MyDamageType.Bolt, true, hitInfo, m_weapon != null ? GetSubpartOwner(m_weapon).EntityId : 0);
                }
            }
            else
            {
                var grid = damagedEntity as MyCubeGrid;
                IMyDestroyableObject destroyable;
                if (grid != null)
                {
                    if (grid.Physics != null && grid.Physics.Enabled && (grid.BlocksDestructionEnabled || MyFakes.ENABLE_VR_FORCE_BLOCK_DESTRUCTIBLE))
                    {
                        bool causeDeformation = false;
                        var  block            = grid.GetTargetedBlock(hitInfo.Position);
                        if (block != null && (grid.BlocksDestructionEnabled || block.ForceBlockDestructible))
                        {
                            block.DoDamage(damage, MyDamageType.Bullet, true, hitInfo, m_weapon != null ? GetSubpartOwner(m_weapon).EntityId : 0);
                            if (block.FatBlock == null)
                            {
                                causeDeformation = true;
                            }
                        }

                        if (grid.BlocksDestructionEnabled && causeDeformation)
                        {
                            ApllyDeformationCubeGrid(hitInfo.Position, grid);
                        }
                    }
                }
                //By Gregory: When MyEntitySubpart (e.g. extended parts of pistons and doors) damage the whole parent component
                //Temporary fix! Maybe other solution? MyEntitySubpart cannot implement IMyDestroyableObject cause is on dependent namespace
                else if (damagedEntity is MyEntitySubpart)
                {
                    if (damagedEntity.Parent != null && damagedEntity.Parent.Parent is MyCubeGrid)
                    {
                        hitInfo.Position = damagedEntity.Parent.WorldAABB.Center;
                        DoDamage(damage, hitInfo, customdata, damagedEntity.Parent.Parent);
                    }
                }
                else if ((destroyable = damagedEntity as IMyDestroyableObject) != null)
                {
                    destroyable.DoDamage(damage, MyDamageType.Bullet, true, hitInfo, m_weapon != null ? GetSubpartOwner(m_weapon).EntityId : 0);
                }
            }

            //Handle damage ?? some WIP code by Ondrej
            //MyEntity damagedObject = entity;
            //damagedObject.DoDamage(m_ammoProperties.HealthDamage, m_ammoProperties.ShipDamage, m_ammoProperties.EMPDamage, m_ammoProperties.DamageType, m_ammoProperties.AmmoType, m_ignorePhysObject);
            //if (MyMultiplayerGameplay.IsRunning)
            //    MyMultiplayerGameplay.Static.ProjectileHit(damagedObject, intersectionValue.IntersectionPointInWorldSpace, this.m_directionNormalized, MyAmmoConstants.FindAmmo(m_ammoProperties), this.OwnerEntity);
        }
Пример #17
0
        private void GetHitEntityAndPosition(LineD line, out IMyEntity entity, out MyHitInfo hitInfoRet, out object customdata)
        {
            entity     = null;
            hitInfoRet = new MyHitInfo();
            customdata = null;

            // 1. rough raycast
            int raycastListIndex = 0;

            do
            {
                if (entity == null)
                {
                    if (raycastListIndex == 0) // cast only the first iteration
                    {
                        ProfilerShort.Begin("MyGamePruningStructure::CastProjectileRay");
                        MyPhysics.CastRay(line.From, line.To, m_raycastResult,
                                          MyPhysics.CollisionLayers.DefaultCollisionLayer);
                        ProfilerShort.End();
                    }

                    if (raycastListIndex < m_raycastResult.Count)
                    {
                        MyPhysics.HitInfo hitInfo = m_raycastResult[raycastListIndex];

                        entity = hitInfo.HkHitInfo.GetHitEntity() as MyEntity;
                        hitInfoRet.Position = hitInfo.Position;
                        hitInfoRet.Normal   = hitInfo.HkHitInfo.Normal;
                        hitInfoRet.ShapeKey = hitInfo.HkHitInfo.GetShapeKey(0);
                    }
                }

                // 2. prevent shooting through characters, retest trajectory between entity and player
                if (!(entity is MyCharacter) || entity == null)
                {
                    // first: raycast, get all entities in line, limit distance if possible
                    LineD lineLimited = new LineD(line.From, entity == null ? line.To : hitInfoRet.Position);
                    if (m_entityRaycastResult == null)
                    {
                        m_entityRaycastResult = new List <MyLineSegmentOverlapResult <MyEntity> >(16);
                    }
                    else
                    {
                        m_entityRaycastResult.Clear();
                    }
                    MyGamePruningStructure.GetAllEntitiesInRay(ref lineLimited, m_entityRaycastResult);
                    // second: precise tests, find best result
                    double    bestDistanceSq = double.MaxValue;
                    IMyEntity entityBest     = null;
                    for (int i = 0; i < m_entityRaycastResult.Count; i++)
                    {
                        if (m_entityRaycastResult[i].Element is MyCharacter)
                        {
                            MyCharacter hitCharacter = m_entityRaycastResult[i].Element as MyCharacter;
                            bool        intersection = hitCharacter.GetIntersectionWithLine(ref line, ref m_charHitInfo);
                            if (intersection)
                            {
                                double distanceSq =
                                    Vector3D.DistanceSquared(m_charHitInfo.Triangle.IntersectionPointInWorldSpace,
                                                             line.From);
                                if (distanceSq < bestDistanceSq && !IsIgnoredEntity(hitCharacter))
                                {
                                    bestDistanceSq      = distanceSq;
                                    entityBest          = hitCharacter;
                                    hitInfoRet.Position = m_charHitInfo.Triangle.IntersectionPointInWorldSpace;
                                    hitInfoRet.Normal   = m_charHitInfo.Triangle.NormalInWorldSpace;
                                    customdata          = m_charHitInfo;
                                }
                            }
                        }
                    }
                    // finally: do we have best result? then return it
                    if (entityBest != null)
                    {
                        entity = entityBest;
                        return; // this was precise result, so return
                    }
                }

                // 3. nothing found in the precise test? then fallback to already found results
                if (entity == null)
                {
                    return;                // no fallback results
                }
                if (entity is MyCharacter) // retest character found in fallback
                {
                    MyCharacter hitCharacter = entity as MyCharacter;
                    bool        intersection = hitCharacter.GetIntersectionWithLine(ref line, ref m_charHitInfo);
                    if (intersection)
                    {
                        hitInfoRet.Position = m_charHitInfo.Triangle.IntersectionPointInWorldSpace;
                        hitInfoRet.Normal   = m_charHitInfo.Triangle.NormalInWorldSpace;
                        customdata          = m_charHitInfo;
                    }
                    else
                    {
                        entity = null; // no hit.
                    }
                }
                else
                {
                    MyCubeGrid grid = entity as MyCubeGrid;
                    if (grid != null)
                    {
                        bool success = grid.GetIntersectionWithLine(ref line, ref m_cubeGridHitInfo);
                        if (success)
                        {
                            hitInfoRet.Position = m_cubeGridHitInfo.Triangle.IntersectionPointInWorldSpace;
                            hitInfoRet.Normal   = m_cubeGridHitInfo.Triangle.NormalInWorldSpace;
                            if (Vector3.Dot(hitInfoRet.Normal, line.Direction) > 0)
                            {
                                hitInfoRet.Normal = -hitInfoRet.Normal;
                            }

                            customdata = m_cubeGridHitInfo;
                        }

                        MyHitInfo info = new MyHitInfo();
                        info.Position = hitInfoRet.Position;
                        info.Normal   = hitInfoRet.Normal;
                    }

                    MyVoxelBase voxel = entity as MyVoxelBase;
                    if (voxel != null)
                    { //get accurate hit because of particles and decals
                        MyIntersectionResultLineTriangleEx?res;
                        if (voxel.GetIntersectionWithLine(ref line, out res, IntersectionFlags.DIRECT_TRIANGLES))
                        {
                            hitInfoRet.Position = res.Value.IntersectionPointInWorldSpace;
                            hitInfoRet.Normal   = res.Value.NormalInWorldSpace;
                            hitInfoRet.ShapeKey = 0;
                        }
                    }
                }
            } while (entity == null && ++raycastListIndex < m_entityRaycastResult.Count);
        }
Пример #18
0
        private static void AddDecal(IMyDecalProxy proxy, ref MyHitInfo hitInfo, float damage, MyStringHash source)
        {
            bool skip = DefaultFilterProxy(proxy);

            if (skip)
            {
                return;
            }

            MyDecalRenderData data;

            proxy.GetDecalRenderData(hitInfo, out data);
            if (data.Skip)
            {
                return;
            }

            MyDecalMaterial material;
            bool            found = MyDecalMaterials.TryGetDecalMaterial(data.Material.String, source.String, out material);

            if (!found)
            {
                if (MyFakes.ENABLE_USE_DEFAULT_DAMAGE_DECAL)
                {
                    found = MyDecalMaterials.TryGetDecalMaterial(DEFAULT, DEFAULT, out material);
                }

                if (!found)
                {
                    return;
                }
            }

            var perp = Vector3.CalculatePerpendicularVector(data.Normal);

            float rotation = material.Rotation;

            if (material.Rotation == float.PositiveInfinity)
            {
                rotation = MyRandom.Instance.NextFloat() * MathHelper.TwoPi;
            }

            if (rotation != 0)
            {
                // Rotate around normal
                Quaternion q = Quaternion.CreateFromAxisAngle(data.Normal, rotation);
                perp = new Vector3((new Quaternion(perp, 0) * q).ToVector4());
            }

            var pos = MatrixD.CreateWorld(data.Position, data.Normal, perp);

            var size = material.MinSize;

            if (material.MaxSize > material.MinSize)
            {
                size += MyRandom.Instance.NextFloat() * (material.MaxSize - material.MinSize);
            }

            pos = Matrix.CreateScale(new Vector3(size, size, material.Depth)) * pos;

            var decalId = MyRenderProxy.CreateDecal(data.RenderObjectId, pos, material.GetStringId());

            proxy.OnAddDecal(decalId, ref data);
        }
Пример #19
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;
            Vector3D           hitPosition;
            Vector3            hitNormal;
            MyCharacterHitInfo charHitInfo;

            GetHitEntityAndPosition(line, out entity, out hitPosition, out hitNormal, out charHitInfo);
            if (entity == null || entity == m_ignoreEntity || 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 = charHitInfo.HitHead && m_projectileAmmoDefinition.HeadShot; // allow head shots only for ammo supporting it in definition
            }

            m_position = hitPosition;

            bool isProjectileGroupKilled = false;

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

                PlayHitSound(materialType, entity, hitPosition, m_projectileAmmoDefinition.PhysicalMaterial);

                MyHitInfo hitInfo = new MyHitInfo();
                hitInfo.Normal   = hitNormal;
                hitInfo.Position = hitPosition;
                hitInfo.Velocity = m_velocity;

                float damage = headShot ? m_projectileAmmoDefinition.ProjectileHeadShotDamage : m_projectileAmmoDefinition.ProjectileMassDamage;
                DoDamage(damage, hitInfo, charHitInfo, entity);

                //particle effect defined in materialProperties.sbc
                Vector3D particleHitPosition = hitPosition + line.Direction * -0.2;
                if (MyMaterialPropertiesHelper.Static.TryCreateCollisionEffect(MyMaterialPropertiesHelper.CollisionType.Hit, particleHitPosition, hitNormal, m_projectileAmmoDefinition.PhysicalMaterial, materialType) == false)
                {
                    //default effect when none other was found
                    if (surfaceImpact != MySurfaceImpactEnum.CHARACTER)
                    {
                        MyParticleEffects.CreateBasicHitParticles(m_projectileAmmoDefinition.ProjectileOnHitEffectName, ref hitPosition, ref hitNormal, ref line.Direction, entity, m_weapon, 1, OwnerEntity);
                    }
                }

                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);
        }
Пример #20
0
        public void Apply(IReadOnlyList <IMyCubeGrid> group)
        {
            var totalAABB = BoundingBoxD.CreateInvalid();

            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (var grid in group)
            {
                totalAABB = totalAABB.Include(grid.WorldAABB);
            }
            var totalSphere = new BoundingSphereD(totalAABB.Center, totalAABB.HalfExtents.Length());

            foreach (var impact in m_impactDirectionRadius)
            {
                var      speed = impact.Velocity.Length();
                var      direction = (Vector3D)impact.Velocity / speed;
                Vector3D start, end;
                {
                    var rayOffset = totalAABB.HalfExtents * 0.8 * (Vector3D)impact.Shift;
                    // mag2(rayOffset + l*direction) == radius*radius
                    // (rayOffset + l*direction)*(rayOffset + l*direction)
                    // mag2(rayOffset) + 2*l*dot(direction, rayOffset) + l*l*mag2(direction)
                    // mag2(rayOffset) - (radius*radius) + 2*l*dot(direction, rayOffset) + l*l == 0
                    var         c   = rayOffset.LengthSquared() - totalSphere.Radius * totalSphere.Radius;
                    var         b   = 2 * Vector3D.Dot(direction, rayOffset);
                    const float a   = 1;
                    var         rad = b * b - 4 * a * c;
                    if (rad <= double.Epsilon)
                    {
                        continue;
                    }
                    var lLow  = (-b - Math.Sqrt(rad)) / (2 * a);
                    var lHigh = (-b + Math.Sqrt(rad)) / (2 * a);
                    start = totalSphere.Center + rayOffset + lLow * direction;
                    end   = totalSphere.Center + rayOffset + lHigh * direction;
                }
                var ray = new RayD(start, direction);

                var bestHitLocation        = default(Vector3D);
                var bestHitDistanceSquared = double.MaxValue;
                foreach (var grid in group)
                {
                    if (!grid.WorldAABB.Intersects(ray).HasValue)
                    {
                        continue;
                    }
                    var block = grid.RayCastBlocks(start, end);
                    if (!block.HasValue)
                    {
                        continue;
                    }
                    var world    = Vector3D.Transform(block.Value * grid.GridSize, grid.WorldMatrix);
                    var distance = Vector3D.DistanceSquared(world, start);
                    if (distance > bestHitDistanceSquared)
                    {
                        continue;
                    }
                    bestHitDistanceSquared = distance;
                    bestHitLocation        = world;
                }
                if (bestHitDistanceSquared > double.MaxValue / 2)
                {
                    continue;
                }
                var impactSphere = new BoundingSphereD(bestHitLocation, impact.Radius);
                var localSphere  = new BoundingSphereD();
                var damageAmount = impact.Mass * speed * speed * (4.0 / 3.0) * Math.PI;
                var damageTotals = new Dictionary <IMySlimBlock, double>();
                foreach (var grid in group)
                {
                    if (grid.WorldAABB.Intersects(impactSphere))
                    {
                        // compute local sphere.
                        localSphere.Center = Vector3D.Transform(impactSphere.Center, grid.WorldMatrixNormalizedInv) / grid.GridSize;
                        localSphere.Radius = impactSphere.Radius / grid.GridSize;
                        var min = Vector3I.Max(Vector3I.Floor(localSphere.Center - localSphere.Radius), grid.Min);
                        var max = Vector3I.Min(Vector3I.Ceiling(localSphere.Center + localSphere.Radius), grid.Max);
                        for (var itr = new Vector3I_RangeIterator(ref min, ref max); itr.IsValid(); itr.MoveNext())
                        {
                            if (localSphere.Contains(itr.Current) == ContainmentType.Disjoint)
                            {
                                continue;
                            }
                            var block = grid.GetCubeBlock(itr.Current);
                            if (block == null)
                            {
                                continue;
                            }
                            var distanceFactor = 1 - ((Vector3D)itr.Current - localSphere.Center).LengthSquared() / (localSphere.Radius * localSphere.Radius);
                            var blockDamage    = damageAmount * distanceFactor * ((block.BlockDefinition as MyCubeBlockDefinition)?.DeformationRatio ?? 1);
                            damageTotals.AddValue(block, blockDamage);
                        }
                    }
                }
                // No idea what shape key should be.
                Logger.Debug("Apply damage to {0} blocks", damageTotals.Count);
                var hitInfo = new MyHitInfo()
                {
                    Normal = direction, Position = impactSphere.Center, Velocity = impact.Velocity, ShapeKey = 0
                };
                foreach (var kv in damageTotals)
                {
                    kv.Key.DoDamage((float)kv.Value, MyDamageType.Explosion, true, hitInfo);
                }
            }
        }
Пример #21
0
 void IMyDecalProxy.AddDecals(MyHitInfo hitInfo, MyStringHash source, object customdata, IMyDecalHandler decalHandler, MyStringHash material)
 {
     // TODO
 }
Пример #22
0
        /// <summary>
        /// Updates resource.
        /// </summary>
        public override void UpdateBeforeSimulation()
        {
            try
            {
                VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("MyMissile.UpdateBeforeSimulation");

                if (m_isExploded)
                {
                    if (Sandbox.Game.Multiplayer.Sync.IsServer)
                    {
                        //  Create explosion
                        float           radius          = m_missileAmmoDefinition.MissileExplosionRadius;
                        BoundingSphereD explosionSphere = new BoundingSphereD(m_collisionPoint.HasValue ? m_collisionPoint.Value : PositionComp.GetPosition(), radius);

                        MyEntity ownerEntity = null;
                        var      ownerId     = Sync.Players.TryGetIdentity(m_owner);
                        if (ownerId != null)
                        {
                            ownerEntity = ownerId.Character;
                        }
                        //MyEntities.TryGetEntityById(m_owner, out ownerEntity);


                        //  Call main explosion starter
                        MyExplosionInfo info = new MyExplosionInfo()
                        {
                            PlayerDamage = 0,
                            //Damage = m_ammoProperties.Damage,
                            Damage              = MyFakes.ENABLE_VOLUMETRIC_EXPLOSION ? m_missileAmmoDefinition.MissileExplosionDamage : 200,
                            ExplosionType       = m_explosionType,
                            ExplosionSphere     = explosionSphere,
                            LifespanMiliseconds = MyExplosionsConstants.EXPLOSION_LIFESPAN,
                            CascadeLevel        = CascadedExplosionLevel,
                            HitEntity           = m_collidedEntity,
                            ParticleScale       = 0.2f,
                            OwnerEntity         = ownerEntity,

                            Direction            = WorldMatrix.Forward,
                            VoxelExplosionCenter = explosionSphere.Center + radius * WorldMatrix.Forward * 0.25f,

                            ExplosionFlags      = MyExplosionFlags.AFFECT_VOXELS | MyExplosionFlags.APPLY_FORCE_AND_DAMAGE | MyExplosionFlags.CREATE_DEBRIS | MyExplosionFlags.CREATE_DECALS | MyExplosionFlags.CREATE_SHRAPNELS | MyExplosionFlags.APPLY_DEFORMATION,
                            VoxelCutoutScale    = 0.3f,
                            PlaySound           = true,
                            ApplyForceAndDamage = true
                        };
                        if (!MarkedToDestroy)
                        {
                            info.ExplosionFlags |= MyExplosionFlags.CREATE_PARTICLE_EFFECT;
                        }
                        MyExplosions.AddExplosion(ref info);

                        if (m_collidedEntity != null && !(m_collidedEntity is MyAmmoBase))
                        {
                            if (!m_collidedEntity.Physics.IsStatic)
                            {
                                m_collidedEntity.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE,
                                                                  100 * Physics.LinearVelocity, m_collisionPoint, null);
                            }
                        }
                    }

                    //by Gregory: added null check. Decal won't be added if m_collidedEntity not found
                    if (m_collisionPoint.HasValue && m_collidedEntity != null)
                    {
                        MyHitInfo hitInfo = new MyHitInfo();
                        hitInfo.Position = m_collisionPoint.Value;
                        hitInfo.Normal   = new Vector3D(1, 0, 0); // FIXME

                        MyDecals.HandleAddDecal(m_collidedEntity, hitInfo, MyDamageType.Rocket);
                    }

                    Close();

                    return;
                }

                base.UpdateBeforeSimulation();

                if (m_missileAmmoDefinition.MissileSkipAcceleration)
                {
                    Physics.LinearVelocity = WorldMatrix.Forward * m_missileAmmoDefinition.DesiredSpeed * 0.7f;
                }
                else
                {
                    Physics.LinearVelocity += PositionComp.WorldMatrix.Forward * m_missileAmmoDefinition.MissileAcceleration * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
                }

                if (m_smokeEffect == null)
                {
                    // if (MyCamera.GetDistanceWithFOV(GetPosition()) < 150)
                    {
                        if (MyParticlesManager.TryCreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_Missile, out m_smokeEffect))
                        {
                            m_smokeEffect.UserScale = 0.3f;

                            var matrix = PositionComp.WorldMatrix;
                            matrix.Translation       -= matrix.Forward * m_smokeEffectOffsetMultiplier;
                            m_smokeEffect.WorldMatrix = matrix;
                            //m_smokeEffect.WorldMatrix = PositionComp.WorldMatrix;
                            m_smokeEffect.AutoDelete           = false;
                            m_smokeEffect.CalculateDeltaMatrix = true;
                        }
                    }
                }
                Physics.AngularVelocity = Vector3.Zero;

                if ((Vector3.Distance(PositionComp.GetPosition(), m_origin) >= m_maxTrajectory))
                {
                    Explode();
                    return;
                }
            }
            finally
            {
                VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
            }
        }
Пример #23
0
 void IMyDecalProxy.GetDecalRenderData(MyHitInfo hitInfo, out MyDecalRenderData renderable)
 {
     // TODO
     renderable      = new MyDecalRenderData();
     renderable.Skip = true;
 }