public override void UpdateBeforeSimulation()
        {
            int chargesInInventory = (int)m_inventory.GetItemAmount(chargeDefinitionIds [damageUpgrades]);

            IMyCubeBlock cube = Entity as IMyCubeBlock;

            long currentShootTime = ((MyObjectBuilder_SmallGatlingGun)cube.GetObjectBuilderCubeBlock()).GunBase.LastShootTime;


            if (currentHeat > 0f)
            {
                if ((ticks - lastShootTimeTicks) > beamWeaponInfo.heatDissipationDelay)
                {
                    currentHeat -= beamWeaponInfo.heatDissipationPerTick;

                    if (currentHeat <= 0f)
                    {
                        currentHeat = 0f;

                        overheated = false;
                    }
                }
            }

            //MyAPIGateway.Utilities.ShowNotification("TIME: " + currentShootTime + " :: " + lastShootTime, 17, MyFontEnum.Red);


            if (currentShootTime != lastShootTime)
            {
                // test

                hitBool = false;

                MyEntitySubpart subpart1 = cubeBlock.GetSubpart("Barrel");;
                //MyAPIGateway.Utilities.ShowNotification("Dif: " + (currentShootTime - lastShootTime), 17, MyFontEnum.Blue);

                from = subpart1.WorldMatrix.Translation + subpart1.WorldMatrix.Forward * 2.5d;
                to   = subpart1.WorldMatrix.Translation + subpart1.WorldMatrix.Forward * 3000d;

                LineD testRay = new LineD(from, to);

                List <MyLineSegmentOverlapResult <MyEntity> > result = new List <MyLineSegmentOverlapResult <MyEntity> >();

                MyGamePruningStructure.GetAllEntitiesInRay(ref testRay, result);


                foreach (var resultItem in result)
                {
                    IMyCubeGrid grid = resultItem.Element as IMyCubeGrid;

                    IMyDestroyableObject destroyableEntity = resultItem.Element as IMyDestroyableObject;

                    if (grid != null)
                    {
                        IMySlimBlock slimblock;

                        double hitd;

                        Vector3D?resultVec = grid.GetLineIntersectionExactAll(ref testRay, out hitd, out slimblock);

                        if (resultVec != null)
                        {
                            hitBool = true;

                            toTarget = from + subpart1.WorldMatrix.Forward * hitd;

                            if (!MyAPIGateway.Session.CreativeMode)
                            {
                                slimblock.DoDamage(beamWeaponInfo.damage * (currentHeat / beamWeaponInfo.maxHeat + 0.2f), MyStringHash.GetOrCompute("Laser"), false, default(MyHitInfo), cubeBlock.EntityId);
                            }
                            else
                            {
                                slimblock.DoDamage(beamWeaponInfo.damage * 1.2f, MyStringHash.GetOrCompute("Laser"), false, default(MyHitInfo), cubeBlock.EntityId);
                            }
                            //MyAPIGateway.Utilities.ShowNotification("" + s.BlockDefinition.Id.SubtypeId + " ::: " + resultItem.Distance, 17);
                        }
                    }
                    if (destroyableEntity != null)
                    {
                        IMyEntity ent  = (IMyEntity)destroyableEntity;
                        double    hitd = (from - ent.WorldMatrix.Translation).Length();

                        toTarget = from + subpart1.WorldMatrix.Forward * hitd;

                        hitBool = true;

                        if (!MyAPIGateway.Session.CreativeMode)
                        {
                            destroyableEntity.DoDamage(beamWeaponInfo.damage * (currentHeat / beamWeaponInfo.maxHeat + 0.2f), MyStringHash.GetOrCompute("Laser"), false, default(MyHitInfo), cubeBlock.EntityId);
                        }
                        else
                        {
                            destroyableEntity.DoDamage(beamWeaponInfo.damage * 1.2f, MyStringHash.GetOrCompute("Laser"), false, default(MyHitInfo), cubeBlock.EntityId);
                        }
                    }
                }


                // test

                lastShootTime      = currentShootTime;
                lastShootTimeTicks = ticks;

                currentHeat += beamWeaponInfo.heatPerTick;

                if (currentHeat > beamWeaponInfo.maxHeat)
                {
                    currentHeat = beamWeaponInfo.maxHeat;

                    overheated = true;
                }
            }

            if (ticks - lastShootTimeTicks < 3)
            {
                var beamcolor     = Color.LightSkyBlue;
                var beamcolor_aux = Color.Azure;
                var maincolor     = new Vector4(beamcolor.X / 30, beamcolor.Y / 30, beamcolor.Z / 30, 1f);
                var auxcolor      = new Vector4(beamcolor_aux.X / 30, beamcolor_aux.Y / 30, beamcolor_aux.Z / 30, 1f);
                var material      = MyStringId.GetOrCompute("WeaponLaser");
                if (hitBool == false)
                {
                    if (!MyAPIGateway.Utilities.IsDedicated)
                    {
                        if (!MyAPIGateway.Session.CreativeMode)
                        {
                            VRage.Game.MySimpleObjectDraw.DrawLine(from, to, material, ref auxcolor, 0.45f);
                            VRage.Game.MySimpleObjectDraw.DrawLine(from, to, material, ref maincolor, 1.5f);
                        }
                        else
                        {
                            VRage.Game.MySimpleObjectDraw.DrawLine(from, to, material, ref auxcolor, 0.45f * 1.2f);
                            VRage.Game.MySimpleObjectDraw.DrawLine(from, to, material, ref maincolor, 1.5f * 1.2f);
                        }
                    }
                }
                else
                {
                    if (!MyAPIGateway.Utilities.IsDedicated)
                    {
                        if (!MyAPIGateway.Session.CreativeMode)
                        {
                            VRage.Game.MySimpleObjectDraw.DrawLine(from, toTarget, material, ref auxcolor, 0.45f);
                            VRage.Game.MySimpleObjectDraw.DrawLine(from, toTarget, material, ref maincolor, 1.5f);
                        }
                        else
                        {
                            VRage.Game.MySimpleObjectDraw.DrawLine(from, toTarget, material, ref auxcolor, 0.45f * 1.2f);
                            VRage.Game.MySimpleObjectDraw.DrawLine(from, toTarget, material, ref maincolor, 1.5f * 1.2f);
                        }
                    }
                }
            }

            if (chargesInInventory < beamWeaponInfo.keepAtCharge)
            {
                if (resourceSink.RequiredInputByType(electricityDefinition) != (beamWeaponInfo.powerUsage / efficiencyUpgrades))
                {
                    resourceSink.SetRequiredInputByType(electricityDefinition, (beamWeaponInfo.powerUsage / efficiencyUpgrades));

                    setPowerConsumption = (beamWeaponInfo.powerUsage / efficiencyUpgrades);
                    powerConsumption    = (beamWeaponInfo.powerUsage / efficiencyUpgrades);
                }
                else
                {
                    if (!functionalBlock.Enabled)
                    {
                        powerConsumption = 0.0001f;
                    }
                }

                if (resourceSink.CurrentInputByType(electricityDefinition) == (beamWeaponInfo.powerUsage / efficiencyUpgrades))
                {
                    if (!overheated)
                    {
                        m_inventory.AddItems((MyFixedPoint)(beamWeaponInfo.keepAtCharge - chargesInInventory), chargeObjectBuilders [damageUpgrades]);
                    }
                }
            }
            else if (chargesInInventory > beamWeaponInfo.keepAtCharge)
            {
                m_inventory.RemoveItemsOfType((MyFixedPoint)(chargesInInventory - beamWeaponInfo.keepAtCharge), chargeObjectBuilders [damageUpgrades]);
            }
            else
            {
                if (setPowerConsumption != 0.0001f)
                {
                    resourceSink.SetRequiredInputByType(electricityDefinition, 0.0001f);

                    setPowerConsumption = 0.0001f;
                    powerConsumption    = 0.0001f;
                }
            }

            terminalBlock.RefreshCustomInfo();

            ticks++;
        }
        protected override void ReadEntitiesInRange()
        {
            m_entitiesInRange.Clear();
            m_hits.Clear();
            MyPhysics.CastRay(m_origin, FrontPoint, m_hits, MyPhysics.ObjectDetectionCollisionLayer);

            DetectionInfo value = new DetectionInfo();

            foreach (var hit in m_hits)
            {
                if (hit.HkHitInfo.Body == null)
                {
                    continue;
                }
                var entity = hit.HkHitInfo.Body.GetEntity();
                if (entity == null)
                {
                    continue;
                }
                var rootEntity = entity.GetTopMostParent();
                if (!IgnoredEntities.Contains(rootEntity))
                {
                    Vector3D fixedDetectionPoint = hit.Position;
                    if (rootEntity is MyCubeGrid)
                    {
                        MyCubeGrid grid = rootEntity as MyCubeGrid;
                        if (grid.GridSizeEnum == Common.ObjectBuilders.MyCubeSize.Large)
                        {
                            fixedDetectionPoint += hit.HkHitInfo.Normal * -0.08f;
                        }
                        else
                        {
                            fixedDetectionPoint += hit.HkHitInfo.Normal * -0.02f;
                        }
                    }

                    if (m_entitiesInRange.TryGetValue(rootEntity.EntityId, out value))
                    {
                        if (Vector3.DistanceSquared(value.DetectionPoint, m_origin) > Vector3.DistanceSquared(fixedDetectionPoint, m_origin))
                        {
                            m_entitiesInRange[rootEntity.EntityId] = new DetectionInfo(rootEntity as MyEntity, fixedDetectionPoint);
                        }
                    }
                    else
                    {
                        m_entitiesInRange[rootEntity.EntityId] = new DetectionInfo(rootEntity as MyEntity, fixedDetectionPoint);
                    }
                }
            }

            LineD line = new LineD(m_origin, FrontPoint);

            using (m_raycastResults.GetClearToken())
            {
                MyGamePruningStructure.GetAllEntitiesInRay(ref line, m_raycastResults);
                foreach (var segment in m_raycastResults)
                {
                    if (segment.Element == null)
                    {
                        continue;
                    }
                    var rootEntity = segment.Element.GetTopMostParent();
                    if (!IgnoredEntities.Contains(rootEntity))
                    {
                        if (!(segment.Element is MyCubeBlock))
                        {
                            continue;
                        }

                        Vector3D point = new Vector3D();

                        MyCubeBlock block = segment.Element as MyCubeBlock;
                        if (block.SlimBlock.HasPhysics == false)
                        {
                            Vector3D localOrigin = Vector3D.Transform(m_origin, block.PositionComp.WorldMatrixNormalizedInv);
                            Vector3D localFront  = Vector3D.Transform(FrontPoint, block.PositionComp.WorldMatrixNormalizedInv);
                            Ray      ray         = new Ray(localOrigin, Vector3.Normalize(localFront - localOrigin));
                            //MyRenderProxy.DebugDrawAABB(block.WorldAABB, Color.Red.ToVector3(), 1.0f, 1.0f, false);
                            float?dist = ray.Intersects(block.PositionComp.LocalAABB);
                            dist += 0.01f;
                            if (dist.HasValue && dist <= m_rayLength)
                            {
                                point = m_origin + Vector3D.Normalize(FrontPoint - m_origin) * dist.Value;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            // This entity was caught by Havok raycast
                            continue;
                        }

                        if (m_entitiesInRange.TryGetValue(rootEntity.EntityId, out value))
                        {
                            if (Vector3.DistanceSquared(value.DetectionPoint, m_origin) > Vector3.DistanceSquared(point, m_origin))
                            {
                                m_entitiesInRange[rootEntity.EntityId] = new DetectionInfo(rootEntity, point);
                            }
                        }
                        else
                        {
                            m_entitiesInRange[rootEntity.EntityId] = new DetectionInfo(rootEntity, point);
                        }
                    }
                }
            }
        }
        //  This method realy initiates/starts the missile
        //  IMPORTANT: Direction vector must be normalized!
        // Projectile count multiplier - when real rate of fire it 45, but we shoot only 10 projectiles as optimization count multiplier will be 4.5
        public void Start(MyProjectileAmmoDefinition ammoDefinition, MyEntity ignoreEntity, Vector3D origin, Vector3 initialVelocity, Vector3 directionNormalized, MyEntity weapon)
        {
            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Projectile.Start");

            m_projectileAmmoDefinition = ammoDefinition;
            m_state        = MyProjectileStateEnum.ACTIVE;
            m_ignoreEntity = ignoreEntity;
            m_origin       = origin + 0.1 * (Vector3D)directionNormalized;
            m_position     = m_origin;
            m_weapon       = weapon;

            if (ammoDefinition.ProjectileTrailProbability >= MyUtils.GetRandomFloat(0, 1))
            {
                LengthMultiplier = 40;
            }
            else
            {
                LengthMultiplier = 0;
            }

            /*
             * if (MyConstants.EnableAimCorrection)
             * {
             * if (m_ammoProperties.AllowAimCorrection) // Autoaim only available for player
             * {
             * VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Projectile.Start autoaim generic");
             * //Intersection ignores children of "ignoreEntity", thus we must not hit our own barrels
             * correctedDirection = MyEntities.GetDirectionFromStartPointToHitPointOfNearestObject(ignoreEntity, m_weapon, origin, m_ammoProperties.MaxTrajectory);
             * VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
             * }
             * }             */

            m_directionNormalized = directionNormalized;
            m_speed         = ammoDefinition.DesiredSpeed * (ammoDefinition.SpeedVar > 0.0f ? MyUtils.GetRandomFloat(1 - ammoDefinition.SpeedVar, 1 + ammoDefinition.SpeedVar) : 1.0f);
            m_velocity      = initialVelocity + m_directionNormalized * m_speed;
            m_maxTrajectory = ammoDefinition.MaxTrajectory * MyUtils.GetRandomFloat(0.8f, 1.2f); // +/- 20%

            m_checkIntersectionIndex  = checkIntersectionCounter % CHECK_INTERSECTION_INTERVAL;
            checkIntersectionCounter += 3;
            m_positionChecked         = false;

            LineD line = new LineD(m_origin, m_origin + m_directionNormalized * m_maxTrajectory);

            if (m_entityRaycastResult == null)
            {
                m_entityRaycastResult = new List <MyLineSegmentOverlapResult <MyEntity> >(16);
            }
            else
            {
                m_entityRaycastResult.Clear();
            }
            MyGamePruningStructure.GetAllEntitiesInRay(ref line, m_entityRaycastResult, MyEntityQueryType.Static);

            foreach (var entity in m_entityRaycastResult)
            {
                MyVoxelPhysics planetPhysics = entity.Element as MyVoxelPhysics;
                if (planetPhysics != null)
                {
                    planetPhysics.PrefetchShapeOnRay(ref line);
                }
            }

            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }
        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;
                    }
                }
            } while (entity == null && ++raycastListIndex < m_entityRaycastResult.Count);
        }
Exemple #5
0
        void GetObjectsToPenetrate(Vector3D start, Vector3D end)
        {
            MyLog.Default.WriteLine($">>>>>>>>> Getting railgun penetrated objects START <<<<<<<<<");

            _objectsToPenetrate.Clear();
            var testRay = new LineD(start, end);

            MyGamePruningStructure.GetAllEntitiesInRay(ref testRay, _overlappingEntities);

            foreach (var hit in _overlappingEntities)
            {
                var destroyable = hit.Element as IMyDestroyableObject;
                if (destroyable != null)
                {
                    MyLog.Default.WriteLine($"Destroyable object found");
                    var penetratedEntity = new PenetratedEntityContainer()
                    {
                        PenetratedEntity = destroyable,
                        WorldPosition    = hit.Element.PositionComp.GetPosition(),
                    };

                    _objectsToPenetrate.Add(penetratedEntity);
                    continue;
                }

                var grid = hit.Element as IMyCubeGrid;
                if (grid != null)
                {
                    MyLog.Default.WriteLine($"Cube grid found");
                    IMySlimBlock slimBlock;

                    grid.RayCastCells(start, end, _hitPositions);

                    if (_hitPositions.Count == 0)
                    {
                        MyLog.Default.WriteLine(" No slim block found in intersection");
                        continue;
                    }

                    MyLog.Default.WriteLine($" {_hitPositions.Count} slim blocks in intersection");

                    foreach (var position in _hitPositions)
                    {
                        slimBlock = grid.GetCubeBlock(position);
                        if (slimBlock == null)
                        {
                            continue;
                        }

                        var penetratedEntity = new PenetratedEntityContainer()
                        {
                            PenetratedEntity = slimBlock,
                            WorldPosition    = Vector3D.Transform(position * grid.GridSize, grid.WorldMatrix),
                        };
                        _objectsToPenetrate.Add(penetratedEntity);
                    }
                    continue;
                }
            }

            MyLog.Default.WriteLine($"<<<<<<<<< Getting railgun penetrated objects END >>>>>>>>>");
        }
Exemple #6
0
        void CreatePenetrationDamage(Vector3D start, Vector3D end, float damage)
        {
            var testRay = new LineD(start, end);

            MyGamePruningStructure.GetAllEntitiesInRay(ref testRay, overlappingEntities);
            //MyAPIGateway.Utilities.ShowNotification($"Entities penetrated: {overlappingEntities.Count}", 3000, MyFontEnum.Green);

            MyLog.Default.WriteLine(">>>>>>>>>> Railgun Penetration Start <<<<<<<<<<");
            MyLog.Default.WriteLine($"Railgun initial pooled damage: {damage}");;

            foreach (var hit in overlappingEntities)
            {
                MyLog.Default.WriteLine("----------------Railgun hit entity: " + $"{hit.Element.GetType()}");

                if (damage <= 0)
                {
                    MyLog.Default.WriteLine("-------------Pooled damage expended");
                    break;
                }

                //IMyCubeGrid grid = hit.Element as IMyCubeGrid;
                if (hit.Element is IMyCubeGrid)
                {
                    var grid = (IMyCubeGrid)hit.Element;

                    MyLog.Default.WriteLine($"--------------Grid found");

                    IMySlimBlock slimBlock;

                    grid.RayCastCells(start, end, hitPositions);
                    var localStart = Vector3D.Transform(start, grid.WorldMatrixNormalizedInv);
                    localStart /= grid.GridSize;

                    hitPositions.Sort((x, y) => Vector3D.DistanceSquared(localStart, x).CompareTo(Vector3D.DistanceSquared(localStart, y)));

                    if (hitPositions.Count == 0)
                    {
                        MyLog.Default.WriteLine("-----No slim block found in intersection");
                        continue;
                    }

                    MyLog.Default.WriteLine($"-----{hitPositions.Count} slim blocks in intersection");

                    foreach (var position in hitPositions)
                    {
                        MyLog.Default.WriteLine("-----");

                        slimBlock = grid.GetCubeBlock(position);
                        MyLog.Default.WriteLine($"dist: {Vector3D.DistanceSquared(position, localStart)}");

                        if (slimBlock == null)
                        {
                            MyLog.Default.WriteLine($">> slim is null at");
                            MyLog.Default.WriteLine($"position: {position}");
                            continue;
                        }

                        var blockIntegrity = slimBlock.Integrity;
                        var cube           = slimBlock.FatBlock;
                        MyLog.Default.WriteLine($"cube type: {(cube == null ? "null" : cube.GetType().ToString())}");
                        MyLog.Default.WriteLine($"pooled damage before: {damage}");
                        MyLog.Default.WriteLine($"block integrity before: {blockIntegrity}");

                        var invDamageMultiplier = 1f;
                        var cubeDef             = slimBlock.BlockDefinition as MyCubeBlockDefinition;
                        if (cubeDef != null)
                        {
                            MyLog.Default.WriteLine($"block damage mult: {cubeDef.GeneralDamageMultiplier}");
                            invDamageMultiplier = 1f / cubeDef.GeneralDamageMultiplier;
                        }

                        try
                        {
                            if (damage > blockIntegrity)
                            {
                                slimBlock.DoDamage(blockIntegrity * invDamageMultiplier, MyStringHash.GetOrCompute("Railgun"), false, default(MyHitInfo), _gunEntityID); //because some blocks have a stupid damage intake modifier
                            }
                            else
                            {
                                slimBlock.DoDamage(invDamageMultiplier * damage, MyStringHash.GetOrCompute("Railgun"), false, default(MyHitInfo), _gunEntityID);
                            }
                        }
                        catch (Exception ex)
                        {
                            MyLog.Default.WriteLine(ex);
                        }

                        if (damage < blockIntegrity)
                        {
                            damage = 0;
                            MyLog.Default.WriteLine($"pooled damage after: {damage}");
                            MyLog.Default.WriteLine($"block integrity after: {slimBlock.Integrity}");
                            break;
                        }
                        else
                        {
                            damage -= blockIntegrity;
                        }

                        MyLog.Default.WriteLine($"pooled damage after: {damage}");
                        MyLog.Default.WriteLine($"block integrity after: {slimBlock.Integrity}");
                    }
                }
                else if (hit.Element is IMyDestroyableObject)
                {
                    var destroyableEntity = (IMyDestroyableObject)hit.Element;

                    MyLog.Default.WriteLine($"----------------------------Destroyable entity found");
                    var cachedIntegrity = destroyableEntity.Integrity;

                    destroyableEntity.DoDamage(damage, MyStringHash.GetOrCompute("Railgun"), false, default(MyHitInfo), _gunEntityID);
                    if (damage < cachedIntegrity)
                    {
                        damage = 0;
                    }
                    else
                    {
                        damage -= cachedIntegrity;
                    }

                    //continue;
                }
            }
            MyLog.Default.WriteLine("<<<<<<<<<< Railgun Penetration End >>>>>>>>>>");
        }
        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;

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("MyEntities.GetIntersectionWithLine()");
            //m_intersection = MyEntities.GetIntersectionWithLine(ref line, m_ignoreEntity, m_weapon, false, false, true, IntersectionFlags.ALL_TRIANGLES, VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS * CHECK_INTERSECTION_INTERVAL);
            m_intersection = null;
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

            if (m_intersection != null)
            {
                // will never trigger, see commented code above ^
                entity      = m_intersection.Value.Entity;
                hitPosition = m_intersection.Value.IntersectionPointInWorldSpace;
                hitNormal   = m_intersection.Value.NormalInWorldSpace;
            }
            // 1. rough raycast
            if (entity == null)
            {
                ProfilerShort.Begin("MyGamePruningStructure::CastProjectileRay");
                MyPhysics.HitInfo?hitInfo = MyPhysics.CastRay(line.From, line.To, MyPhysics.CollisionLayers.DefaultCollisionLayer);
                //MyPhysics.HitInfo? hitInfo = null;
                //if (Sandbox.Game.Gui.MyMichalDebugInputComponent.Static.CastLongRay)
                //    hitInfo = MyPhysics.CastLongRay(line.From, line.To);
                //else
                //    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
            {
                //entity = entity.GetTopMostParent();
            }
        }
Exemple #8
0
        protected override void ReadEntitiesInRange()
        {
            m_entitiesInRange.Clear();
            m_hits.Clear();
            MyPhysics.CastRay(m_origin, FrontPoint, m_hits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer);

            DetectionInfo value = new DetectionInfo();

            foreach (var hit in m_hits)
            {
                var hitInfo = hit.HkHitInfo;
                if (hitInfo.Body == null)
                {
                    continue;
                }
                var entity = hitInfo.GetHitEntity();

                if (entity == null)
                {
                    continue;
                }
                var rootEntity = entity.GetTopMostParent();
                if (!IgnoredEntities.Contains(rootEntity))
                {
                    Vector3D detectionPoint = hit.Position;

                    MyCubeGrid grid = rootEntity as MyCubeGrid;
                    if (grid != null)
                    {
                        var shape    = hitInfo.Body.GetShape();
                        int shapeIdx = 0;
                        if (grid.Physics.IsWelded || grid.GetPhysicsBody().WeldInfo.Children.Count != 0)
                        {
                            if (shape.IsContainer())
                            {
                                shape    = shape.GetContainer().GetShape(hitInfo.GetShapeKey(0));
                                shapeIdx = 1;
                            }
                        }
                        if (!GetShapeCenter(shape, hitInfo.GetShapeKey(shapeIdx), grid, ref detectionPoint))
                        {
                            if (grid.GridSizeEnum == MyCubeSize.Large)
                            {
                                detectionPoint += hit.HkHitInfo.Normal * -0.08f;
                            }
                            else
                            {
                                detectionPoint += hit.HkHitInfo.Normal * -0.02f;
                            }
                        }
                    }

                    if (m_entitiesInRange.TryGetValue(rootEntity.EntityId, out value))
                    {
                        var oldDistance = Vector3.DistanceSquared(value.DetectionPoint, m_origin);
                        var newDistance = Vector3.DistanceSquared(detectionPoint, m_origin);
                        if (oldDistance > newDistance)
                        {
                            m_entitiesInRange[rootEntity.EntityId] = new DetectionInfo(rootEntity as MyEntity, detectionPoint);
                        }
                    }
                    else
                    {
                        m_entitiesInRange[rootEntity.EntityId] = new DetectionInfo(rootEntity as MyEntity, detectionPoint);
                    }
                }
            }

            LineD line = new LineD(m_origin, FrontPoint);

            using (m_raycastResults.GetClearToken())
            {
                MyGamePruningStructure.GetAllEntitiesInRay(ref line, m_raycastResults);
                foreach (var segment in m_raycastResults)
                {
                    if (segment.Element == null)
                    {
                        continue;
                    }
                    var rootEntity = segment.Element.GetTopMostParent();
                    if (!IgnoredEntities.Contains(rootEntity))
                    {
                        MyCubeBlock block = segment.Element as MyCubeBlock;
                        if (block == null)
                        {
                            continue;
                        }

                        Vector3D point = new Vector3D();

                        if (block.SlimBlock.HasPhysics == false)
                        {
                            MatrixD  blockWorldMatrixNormalizedInv = block.PositionComp.WorldMatrixNormalizedInv;
                            Vector3D localOrigin = Vector3D.Transform(m_origin, ref blockWorldMatrixNormalizedInv);
                            Vector3D localFront  = Vector3D.Transform(FrontPoint, ref blockWorldMatrixNormalizedInv);
                            Ray      ray         = new Ray(localOrigin, Vector3.Normalize(localFront - localOrigin));
                            //MyRenderProxy.DebugDrawAABB(block.WorldAABB, Color.Red.ToVector3(), 1.0f, 1.0f, false);
                            float?dist = ray.Intersects(block.PositionComp.LocalAABB);
                            dist += 0.01f;
                            if (dist.HasValue && dist <= m_rayLength)
                            {
                                point = m_origin + Vector3D.Normalize(FrontPoint - m_origin) * dist.Value;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            // This entity was caught by Havok raycast
                            continue;
                        }

                        if (m_entitiesInRange.TryGetValue(rootEntity.EntityId, out value))
                        {
                            if (Vector3.DistanceSquared(value.DetectionPoint, m_origin) > Vector3.DistanceSquared(point, m_origin))
                            {
                                m_entitiesInRange[rootEntity.EntityId] = new DetectionInfo(rootEntity, point);
                            }
                        }
                        else
                        {
                            m_entitiesInRange[rootEntity.EntityId] = new DetectionInfo(rootEntity, point);
                        }
                    }
                }
            }
        }
        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;
                }
            }
        }