Exemplo n.º 1
0
        public async Task Store(Hit hit)
        {
            var entity = new HitEntity
            {
                CapturedData   = hit.CapturedDataString,
                Data           = hit.DataString,
                Date           = hit.Date,
                Proxy          = hit.ProxyString,
                Type           = hit.Type,
                ConfigId       = hit.Config.Id,
                ConfigName     = hit.Config.Metadata.Name,
                ConfigCategory = hit.Config.Metadata.Category,
                OwnerId        = hit.OwnerId
            };

            if (hit.DataPool is WordlistDataPool)
            {
                var wordlist = (hit.DataPool as WordlistDataPool).Wordlist;
                entity.WordlistId   = wordlist.Id;
                entity.WordlistName = wordlist.Name;
            }

            // Only allow saving one hit at a time (multiple threads should
            // not use the same DbContext at the same time).
            await semaphore.WaitAsync();

            try
            {
                await hitRepo.Add(entity);
            }
            finally
            {
                semaphore.Release();
            }
        }
Exemplo n.º 2
0
 public void Initialize(NPCConfig config, HitEntity target)
 {
     this.config        = config;
     this.target        = target;
     navMeshAgent.speed = config.MoveSpeed;
     SetUpHealth(config.Health);
 }
Exemplo n.º 3
0
        private void UpdateField(HitEntity hitEnt, ProInfo info)
        {
            if (info.AmmoDef.Const.AreaEffect == PullField || info.AmmoDef.Const.AreaEffect == PushField)
            {
                PushPull(hitEnt, info);
                return;
            }

            var grid = hitEnt.Entity as MyCubeGrid;

            if (grid?.Physics == null || grid.MarkedForClose)
            {
                return;
            }

            var attackerId = info.Target.FiringCube.EntityId;

            GetAndSortBlocksInSphere(info.AmmoDef, hitEnt.Info.System, grid, hitEnt.PruneSphere, !hitEnt.DamageOverTime, hitEnt.Blocks);

            var depletable = info.AmmoDef.AreaEffect.EwarFields.Depletable;
            var healthPool = depletable && info.BaseHealthPool > 0 ? info.BaseHealthPool : float.MaxValue;

            ComputeEffects(grid, info.AmmoDef, info.AmmoDef.Const.AreaEffectDamage, ref healthPool, attackerId, info.System.WeaponIdHash, hitEnt.Blocks);

            if (depletable)
            {
                info.BaseHealthPool -= healthPool;
            }
        }
Exemplo n.º 4
0
        private void UpdateEffect(HitEntity hitEnt, ProInfo info)
        {
            if (info.AmmoDef.Const.AreaEffect == PullField || info.AmmoDef.Const.AreaEffect == PushField)
            {
                PushPull(hitEnt, info);
                return;
            }

            var grid = hitEnt.Entity as MyCubeGrid;

            if (grid == null || grid.MarkedForClose)
            {
                return;
            }

            if (IsServer)
            {
                Dictionary <AreaEffectType, GridEffect> effects;
                var attackerId = info.Target.FiringCube.EntityId;
                if (_gridEffects.TryGetValue(grid, out effects))
                {
                    GridEffect gridEffect;
                    if (effects.TryGetValue(info.AmmoDef.AreaEffect.AreaEffect, out gridEffect))
                    {
                        gridEffect.Damage    += info.AmmoDef.Const.AreaEffectDamage;
                        gridEffect.Ai         = info.Ai;
                        gridEffect.AttackerId = attackerId;
                        gridEffect.Hits++;
                        var hitPos = hitEnt.HitPos ?? info.Hit.SurfaceHit;
                        gridEffect.HitPos = (gridEffect.HitPos + hitPos) / 2;
                    }
                }
                else
                {
                    effects = GridEffectsPool.Get();
                    var gridEffect = GridEffectPool.Get();
                    gridEffect.System     = info.System;
                    gridEffect.Damage     = info.AmmoDef.Const.AreaEffectDamage;
                    gridEffect.Ai         = info.Ai;
                    gridEffect.AmmoDef    = info.AmmoDef;
                    gridEffect.AttackerId = attackerId;
                    gridEffect.Hits++;
                    var hitPos = hitEnt.HitPos ?? info.Hit.SurfaceHit;

                    gridEffect.HitPos = hitPos;
                    effects.Add(info.AmmoDef.AreaEffect.AreaEffect, gridEffect);
                    _gridEffects.Add(grid, effects);
                }
            }

            info.BaseHealthPool = 0;
            info.BaseDamagePool = 0;
        }
Exemplo n.º 5
0
        public async Task CreateNewAsync(DateTimeOffset eventDate, string shortCode)
        {
            var table = await _cloudTableFactory.GetCloudTableReferenceAsync(TableNames.Hits);

            var entity = new HitEntity
            {
                PartitionKey = PartitionKeys.Hit,
                RowKey       = Guid.NewGuid().ToString(),
                CreatedOn    = eventDate,
                ShortCode    = shortCode,
                Timestamp    = DateTimeOffset.UtcNow
            };

            var operation = TableOperation.Insert(entity);
            await table.ExecuteAsync(operation);
        }
Exemplo n.º 6
0
        public static async Task Run(
            [EventHubTrigger(HubNames.ClickEventsHub, Connection = "CloudSettings:EventHubListenerConnectionString")] LinkClickedMessage events,
            [Table(TableNames.Hits)] CloudTable table,
            ILogger log)
        {
            var entity = new HitEntity
            {
                PartitionKey = PartitionKeys.Hit,
                RowKey       = Guid.NewGuid().ToString(),
                CreatedOn    = events.ClickedAt,
                ShortCode    = events.Key,
                Timestamp    = DateTimeOffset.UtcNow
            };

            var operation = TableOperation.Insert(entity);

            await table.CreateIfNotExistsAsync();

            await table.ExecuteAsync(operation);
        }
        public override void OnTravel(VRIL_ControllerActionEventArgs e)
        {
            // if a valid position is selected, travel is triggered
            if (PositionSelected && !DelayToNextTravel)
            {
                // allow no other input while travelling to target position
                Manager.InputLocked = true;
                TravelMode          = true;
                SaveDistancesToViewpoint();
                PlayAudio();
                StartCoroutine(DashMovement());
                DelayToNextTravel = true;
            }

            if (HitEntity)
            {
                HitEntity.SetActive(false);
            }

            IsActivated = false;
        }
Exemplo n.º 8
0
        private bool HitDoor(HitEntity hitEnt, MyDoorBase door)
        {
            var ray    = new RayD(ref hitEnt.Intersection.From, ref hitEnt.Intersection.Direction);
            var rayHit = ray.Intersects(door.PositionComp.WorldVolume);

            if (rayHit != null)
            {
                var      hitPos = hitEnt.Intersection.From + (hitEnt.Intersection.Direction * (rayHit.Value + 0.25f));
                IHitInfo hitInfo;
                if (MyAPIGateway.Physics.CastRay(hitPos, hitEnt.Intersection.To, out hitInfo, 15))
                {
                    var rotMatrix = Quaternion.CreateFromRotationMatrix(door.WorldMatrix);
                    var obb       = new MyOrientedBoundingBoxD(door.PositionComp.WorldAABB.Center, door.PositionComp.LocalAABB.HalfExtents, rotMatrix);
                    var sphere    = new BoundingSphereD(hitInfo.Position + (hitEnt.Intersection.Direction * 0.15f), 0.01f);
                    if (obb.Intersects(ref sphere))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
        /// <summary>
        /// Called when the travel should be performed
        /// </summary>
        /// <param name="e">ControllerActionEventArgs</param>
        public override void OnTravel(VRIL_ControllerActionEventArgs e)
        {
            if (IsActivated && !DelayToNextTravel)
            {
                // if a valid position is selected, travel is triggered
                if (PositionSelected)
                {
                    PlayAudio();
                    SaveDistancesToViewpoint();
                    Viewpoint.transform.position = TargetPosition;
                    TransferSelectedObjects();
                    PositionSelected  = false;
                    Timer             = 0.0f;
                    DelayToNextTravel = true;

                    // blink scene away immediately
                    if (SceneBlinksAway)
                    {
                        SteamVR_Fade.View(SceneOffColor, 0);
                        SceneOff = true;
                    }
                }

                if (HitEntity != null)
                {
                    HitEntity.SetActive(false);
                }

                IsActivated = false;

                // in case travel does not disabled technique, selection mode is actived again
                if (!TravelDisablesTechnique)
                {
                    IsActivated = true;
                    StartCoroutine(SelectPosition(e));
                }
            }
        }
Exemplo n.º 10
0
        public async Task Store(Hit hit)
        {
            var entity = new HitEntity
            {
                CapturedData   = hit.CapturedDataString,
                Data           = hit.DataString,
                Date           = hit.Date,
                Proxy          = hit.ProxyString,
                Type           = hit.Type,
                ConfigId       = hit.Config.Id,
                ConfigName     = hit.Config.Metadata.Name,
                ConfigCategory = hit.Config.Metadata.Category,
                OwnerId        = hit.OwnerId
            };

            if (hit.DataPool is WordlistDataPool)
            {
                var wordlist = (hit.DataPool as WordlistDataPool).Wordlist;
                entity.WordlistId   = wordlist.Id;
                entity.WordlistName = wordlist.Name;
            }

            await hitRepo.Add(entity);
        }
Exemplo n.º 11
0
        private void UpdateField(HitEntity hitEnt, ProInfo info)
        {
            var grid = hitEnt.Entity as MyCubeGrid;

            if (grid == null || grid.MarkedForClose)
            {
                return;
            }
            var depletable = info.AmmoDef.AreaEffect.EwarFields.Depletable;
            var healthPool = depletable && info.BaseHealthPool > 0 ? info.BaseHealthPool : float.MaxValue;

            if (healthPool <= 0)
            {
                return;
            }
            if (info.AmmoDef.Const.AreaEffect == PullField || info.AmmoDef.Const.AreaEffect == PushField)
            {
                if (grid.Physics == null || !grid.Physics.Enabled || grid.Physics.IsStatic)
                {
                    return;
                }
                var dir = info.AmmoDef.Const.AreaEffect == PushField ? hitEnt.Intersection.Direction : -hitEnt.Intersection.Direction;
                grid.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, dir * info.AmmoDef.Const.AreaEffectDamage, grid.Physics?.CenterOfMassWorld, Vector3.Zero);
            }
            else
            {
                var attackerId = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass ? grid.EntityId : info.Target.FiringCube.EntityId;
                GetAndSortBlocksInSphere(info.AmmoDef, hitEnt.Info.Ai, grid, hitEnt.PruneSphere, !hitEnt.DamageOverTime, hitEnt.Blocks);
                ComputeEffects(grid, info.AmmoDef, info.AreaEffectDamage, healthPool, attackerId, hitEnt.Blocks);
            }

            if (depletable)
            {
                info.BaseHealthPool -= healthPool;
            }
        }
Exemplo n.º 12
0
        private void DamageGrid(HitEntity hitEnt, ProInfo t)
        {
            var grid = hitEnt.Entity as MyCubeGrid;

            if (grid == null || grid.MarkedForClose || !hitEnt.HitPos.HasValue || hitEnt.Blocks == null)
            {
                hitEnt.Blocks?.Clear();
                return;
            }
            if (t.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Heal || (!t.AmmoDef.Const.SelfDamage || !MyAPIGateway.Session.SessionSettings.EnableTurretsFriendlyFire) && t.Ai.MyGrid.IsSameConstructAs(grid))
            {
                t.BaseDamagePool = 0;
                return;
            }

            _destroyedSlims.Clear();
            _destroyedSlimsClient.Clear();
            var largeGrid      = grid.GridSizeEnum == MyCubeSize.Large;
            var areaRadius     = largeGrid ? t.AmmoDef.Const.AreaRadiusLarge : t.AmmoDef.Const.AreaRadiusSmall;
            var detonateRadius = largeGrid ? t.AmmoDef.Const.DetonateRadiusLarge : t.AmmoDef.Const.DetonateRadiusSmall;
            var maxObjects     = t.AmmoDef.Const.MaxObjectsHit;
            var areaEffect     = t.AmmoDef.AreaEffect.AreaEffect;
            var explosive      = areaEffect == AreaEffectType.Explosive;
            var radiant        = areaEffect == AreaEffectType.Radiant;
            var detonateOnEnd  = t.AmmoDef.AreaEffect.Detonation.DetonateOnEnd;
            var detonateDmg    = t.DetonationDamage;
            var shieldBypass   = t.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass;
            var attackerId     = shieldBypass ? grid.EntityId : t.Target.FiringCube.EntityId;
            var attacker       = shieldBypass ? (MyEntity)grid : t.Target.FiringCube;
            var areaEffectDmg  = areaEffect != AreaEffectType.Disabled ? t.AreaEffectDamage : 0;
            var hitMass        = t.AmmoDef.Mass;
            var sync           = MpActive && (DedicatedServer || IsServer);
            var hasAreaDmg     = areaEffectDmg > 0;
            var radiantCascade = radiant && !detonateOnEnd;
            var primeDamage    = !radiantCascade || !hasAreaDmg;
            var radiantBomb    = radiant && detonateOnEnd;
            var damageType     = explosive || radiant ? MyDamageType.Explosion : MyDamageType.Bullet;

            var fallOff          = t.AmmoDef.Const.FallOffScaling && t.DistanceTraveled > t.AmmoDef.DamageScales.FallOff.Distance;
            var fallOffMultipler = 1f;

            if (fallOff)
            {
                fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((t.DistanceTraveled - t.AmmoDef.DamageScales.FallOff.Distance) / (t.AmmoDef.Const.MaxTrajectory - t.AmmoDef.DamageScales.FallOff.Distance)), t.AmmoDef.DamageScales.FallOff.MinMultipler, 1);
            }

            var damagePool = t.BaseDamagePool;

            if (t.AmmoDef.Const.VirtualBeams)
            {
                var hits = t.WeaponCache.Hits;
                damagePool    *= hits;
                areaEffectDmg *= hits;
            }
            var objectsHit           = t.ObjectsHit;
            var countBlocksAsObjects = t.AmmoDef.ObjectsHit.CountBlocks;

            List <Vector3I> radiatedBlocks = null;

            if (radiant)
            {
                GetBlockSphereDb(grid, areaRadius, out radiatedBlocks);
            }

            var done     = false;
            var nova     = false;
            var outOfPew = false;

            for (int i = 0; i < hitEnt.Blocks.Count; i++)
            {
                if (done || outOfPew && !nova)
                {
                    break;
                }

                var rootBlock = hitEnt.Blocks[i];

                if (!nova)
                {
                    if (_destroyedSlims.Contains(rootBlock) || _destroyedSlimsClient.Contains(rootBlock))
                    {
                        continue;
                    }
                    if (rootBlock.IsDestroyed)
                    {
                        _destroyedSlims.Add(rootBlock);
                        if (IsClient)
                        {
                            _destroyedSlimsClient.Add(rootBlock);
                            if (_slimHealthClient.ContainsKey(rootBlock))
                            {
                                _slimHealthClient.Remove(rootBlock);
                            }
                        }
                        continue;
                    }
                }
                var door = rootBlock.FatBlock as MyDoorBase;
                if (door != null && door.Open && !HitDoor(hitEnt, door))
                {
                    continue;
                }

                var radiate  = radiantCascade || nova;
                var dmgCount = 1;
                if (radiate)
                {
                    if (nova)
                    {
                        GetBlockSphereDb(grid, detonateRadius, out radiatedBlocks);
                    }
                    if (radiatedBlocks != null)
                    {
                        ShiftAndPruneBlockSphere(grid, rootBlock.Position, radiatedBlocks, _slimsSortedList);
                    }

                    done     = nova;
                    dmgCount = _slimsSortedList.Count;
                }

                for (int j = 0; j < dmgCount; j++)
                {
                    var   block       = radiate ? _slimsSortedList[j].Slim : rootBlock;
                    var   blockHp     = !IsClient ? block.Integrity : _slimHealthClient.ContainsKey(block) ? _slimHealthClient[block] : block.Integrity;
                    float damageScale = 1;

                    if (t.AmmoDef.Const.DamageScaling)
                    {
                        var d = t.AmmoDef.DamageScales;
                        if (d.MaxIntegrity > 0 && blockHp > d.MaxIntegrity)
                        {
                            outOfPew   = true;
                            damagePool = 0;
                            continue;
                        }

                        if (d.Grids.Large >= 0 && largeGrid)
                        {
                            damageScale *= d.Grids.Large;
                        }
                        else if (d.Grids.Small >= 0 && !largeGrid)
                        {
                            damageScale *= d.Grids.Small;
                        }

                        MyDefinitionBase blockDef = null;
                        if (t.AmmoDef.Const.ArmorScaling)
                        {
                            blockDef = block.BlockDefinition;
                            var isArmor = AllArmorBaseDefinitions.Contains(blockDef);
                            if (isArmor && d.Armor.Armor >= 0)
                            {
                                damageScale *= d.Armor.Armor;
                            }
                            else if (!isArmor && d.Armor.NonArmor >= 0)
                            {
                                damageScale *= d.Armor.NonArmor;
                            }

                            if (isArmor && (d.Armor.Light >= 0 || d.Armor.Heavy >= 0))
                            {
                                var isHeavy = HeavyArmorBaseDefinitions.Contains(blockDef);
                                if (isHeavy && d.Armor.Heavy >= 0)
                                {
                                    damageScale *= d.Armor.Heavy;
                                }
                                else if (!isHeavy && d.Armor.Light >= 0)
                                {
                                    damageScale *= d.Armor.Light;
                                }
                            }
                        }
                        if (t.AmmoDef.Const.CustomDamageScales)
                        {
                            if (blockDef == null)
                            {
                                blockDef = block.BlockDefinition;
                            }
                            float modifier;
                            var   found = t.AmmoDef.Const.CustomBlockDefinitionBasesToScales.TryGetValue(blockDef, out modifier);

                            if (found)
                            {
                                damageScale *= modifier;
                            }
                            else if (t.AmmoDef.DamageScales.Custom.IgnoreAllOthers)
                            {
                                continue;
                            }
                        }
                        if (fallOff)
                        {
                            damageScale *= fallOffMultipler;
                        }
                    }

                    var blockIsRoot   = block == rootBlock;
                    var primaryDamage = primeDamage || blockIsRoot;

                    if (damagePool <= 0 && primaryDamage || objectsHit >= maxObjects)
                    {
                        break;
                    }

                    var scaledDamage = damagePool * damageScale;
                    if (primaryDamage)
                    {
                        if (countBlocksAsObjects)
                        {
                            objectsHit++;
                        }

                        if (scaledDamage <= blockHp)
                        {
                            outOfPew   = true;
                            damagePool = 0;
                        }
                        else
                        {
                            _destroyedSlims.Add(block);
                            if (IsClient)
                            {
                                _destroyedSlimsClient.Add(block);
                                if (_slimHealthClient.ContainsKey(block))
                                {
                                    _slimHealthClient.Remove(block);
                                }
                            }
                            damagePool -= blockHp;
                        }
                    }
                    else
                    {
                        scaledDamage = areaEffectDmg * damageScale;
                        if (scaledDamage >= blockHp)
                        {
                            _destroyedSlims.Add(block);
                            if (IsClient)
                            {
                                _destroyedSlimsClient.Add(block);
                                if (_slimHealthClient.ContainsKey(block))
                                {
                                    _slimHealthClient.Remove(block);
                                }
                            }
                        }
                    }

                    if (!IsClient)
                    {
                        block.DoDamage(scaledDamage, damageType, sync, null, attackerId);
                    }
                    else
                    {
                        var hasBlock = _slimHealthClient.ContainsKey(block);
                        if (hasBlock && _slimHealthClient[block] - scaledDamage > 0)
                        {
                            _slimHealthClient[block] -= scaledDamage;
                        }
                        else if (hasBlock)
                        {
                            _slimHealthClient.Remove(block);
                        }
                        else if (block.Integrity - scaledDamage > 0)
                        {
                            _slimHealthClient[block] = blockHp - scaledDamage;
                        }
                    }

                    var theEnd = damagePool <= 0 || objectsHit >= maxObjects;

                    if (explosive && (!detonateOnEnd && blockIsRoot || detonateOnEnd && theEnd))
                    {
                        var rootPos = grid.GridIntegerToWorld(rootBlock.Position);
                        if (areaEffectDmg > 0)
                        {
                            SUtils.CreateMissileExplosion(this, areaEffectDmg * damageScale, areaRadius, rootPos, hitEnt.Intersection.Direction, attacker, grid, t.AmmoDef, true);
                        }
                        if (detonateOnEnd && theEnd)
                        {
                            SUtils.CreateMissileExplosion(this, detonateDmg * damageScale, detonateRadius, rootPos, hitEnt.Intersection.Direction, attacker, grid, t.AmmoDef, true);
                        }
                    }
                    else if (!nova)
                    {
                        if (hitMass > 0 && blockIsRoot)
                        {
                            var speed = t.AmmoDef.Trajectory.DesiredSpeed > 0 ? t.AmmoDef.Trajectory.DesiredSpeed : 1;
                            ApplyProjectileForce(grid, grid.GridIntegerToWorld(rootBlock.Position), hitEnt.Intersection.Direction, (hitMass * speed));
                        }

                        if (radiantBomb && theEnd)
                        {
                            nova = true;
                            i--;
                            t.BaseDamagePool = 0;
                            t.ObjectsHit     = maxObjects;
                            objectsHit       = int.MinValue;
                            var aInfo = t.AmmoDef.AreaEffect;
                            var dInfo = aInfo.Detonation;

                            if (dInfo.DetonationDamage > 0)
                            {
                                damagePool = detonateDmg;
                            }
                            else if (aInfo.AreaEffectDamage > 0)
                            {
                                damagePool = areaEffectDmg;
                            }
                            else
                            {
                                damagePool = scaledDamage;
                            }
                            break;
                        }
                    }
                }
            }
            if (!countBlocksAsObjects)
            {
                t.ObjectsHit += 1;
            }
            if (!nova)
            {
                t.BaseDamagePool = damagePool;
                t.ObjectsHit     = objectsHit;
            }
            if (radiantCascade || nova)
            {
                _slimsSortedList.Clear();
            }
            hitEnt.Blocks.Clear();
        }
Exemplo n.º 13
0
        internal int GetEntityCompareDist(HitEntity x, HitEntity y, List <Vector3I> slims, ProInfo info)
        {
            var xDist        = double.MaxValue;
            var yDist        = double.MaxValue;
            var beam         = x.Intersection;
            var count        = y != null ? 2 : 1;
            var eWarPulse    = info.AmmoDef.Const.Ewar && info.AmmoDef.Const.Pulse;
            var triggerEvent = eWarPulse && !info.TriggeredPulse && info.AmmoDef.Const.EwarTriggerRange > 0;

            for (int i = 0; i < count; i++)
            {
                var isX = i == 0;

                MyEntity  ent;
                HitEntity hitEnt;
                if (isX)
                {
                    hitEnt = x;
                    ent    = hitEnt.Entity;
                }
                else
                {
                    hitEnt = y;
                    ent    = hitEnt.Entity;
                }

                var dist = double.MaxValue;


                var shield = ent as IMyTerminalBlock;
                var grid   = ent as MyCubeGrid;
                var voxel  = ent as MyVoxelBase;
                if (triggerEvent && (info.Ai.Targets.ContainsKey(ent) || shield != null))
                {
                    hitEnt.PulseTrigger = true;
                }
                else if (hitEnt.Projectile != null)
                {
                    dist = hitEnt.HitDist.Value;
                }
                else if (shield != null)
                {
                    hitEnt.Hit = true;
                    dist       = hitEnt.HitDist.Value;
                }
                else if (grid != null)
                {
                    if (hitEnt.Hit)
                    {
                        dist           = Vector3D.Distance(hitEnt.Intersection.From, hitEnt.HitPos.Value);
                        hitEnt.HitDist = dist;
                    }
                    else
                    {
                        if (hitEnt.SphereCheck || info.EwarActive)
                        {
                            var ewarActive = hitEnt.EventType == Field || hitEnt.EventType == Effect;

                            var hitPos = !ewarActive ? hitEnt.PruneSphere.Center + (hitEnt.Intersection.Direction * hitEnt.PruneSphere.Radius) : hitEnt.PruneSphere.Center;
                            if (grid.IsSameConstructAs(hitEnt.Info.Ai.MyGrid) && Vector3D.DistanceSquared(hitPos, hitEnt.Info.Origin) <= grid.GridSize * grid.GridSize)
                            {
                                continue;
                            }

                            if (!ewarActive)
                            {
                                GetAndSortBlocksInSphere(hitEnt.Info.AmmoDef, hitEnt.Info.Ai, grid, hitEnt.PruneSphere, false, hitEnt.Blocks);
                            }

                            if (hitEnt.Blocks.Count > 0 || ewarActive)
                            {
                                dist           = 0;
                                hitEnt.HitDist = dist;
                                hitEnt.Hit     = true;
                                hitEnt.HitPos  = hitPos;
                            }
                        }
                        else
                        {
                            grid.RayCastCells(beam.From, beam.To, slims, null, true, true);
                            var closestBlockFound = false;
                            var rotMatrix         = Quaternion.CreateFromRotationMatrix(grid.PositionComp.WorldMatrixRef);
                            var hitSelf           = grid.IsSameConstructAs(hitEnt.Info.Target.FiringCube.CubeGrid);
                            for (int j = 0; j < slims.Count; j++)
                            {
                                var firstBlock = grid.GetCubeBlock(slims[j]) as IMySlimBlock;
                                if (firstBlock != null && !firstBlock.IsDestroyed && firstBlock != hitEnt.Info.Target.FiringCube.SlimBlock)
                                {
                                    hitEnt.Blocks.Add(firstBlock);
                                    if (closestBlockFound)
                                    {
                                        continue;
                                    }
                                    MyOrientedBoundingBoxD obb;
                                    var fat = firstBlock.FatBlock;
                                    if (fat != null)
                                    {
                                        obb = new MyOrientedBoundingBoxD(fat.Model.BoundingBox, fat.PositionComp.WorldMatrixRef);
                                    }
                                    else
                                    {
                                        Vector3D center;
                                        firstBlock.ComputeWorldCenter(out center);
                                        Vector3 halfExt;
                                        firstBlock.ComputeScaledHalfExtents(out halfExt);
                                        var blockBox = new BoundingBoxD(-halfExt, halfExt);
                                        obb = new MyOrientedBoundingBoxD(center, blockBox.HalfExtents, rotMatrix);
                                    }

                                    var hitDist = obb.Intersects(ref beam) ?? Vector3D.Distance(beam.From, obb.Center);
                                    var hitPos  = beam.From + (beam.Direction * hitDist);
                                    if (hitSelf)
                                    {
                                        if (Vector3D.DistanceSquared(hitPos, hitEnt.Info.Origin) <= grid.GridSize * 3)
                                        {
                                            hitEnt.Blocks.Clear();
                                        }
                                        else
                                        {
                                            dist           = hitDist;
                                            hitEnt.HitDist = dist;
                                            hitEnt.Hit     = true;
                                            hitEnt.HitPos  = hitPos;
                                        }
                                        break;
                                    }

                                    dist              = hitDist;
                                    hitEnt.HitDist    = dist;
                                    hitEnt.Hit        = true;
                                    hitEnt.HitPos     = hitPos;
                                    closestBlockFound = true;
                                }
                            }
                        }
                    }
                }
                else if (voxel != null)
                {
                    hitEnt.Hit     = true;
                    dist           = hitEnt.HitDist.Value;
                    hitEnt.HitDist = dist;
                }
                else if (ent is IMyDestroyableObject)
                {
                    if (hitEnt.Hit)
                    {
                        dist = Vector3D.Distance(hitEnt.Intersection.From, hitEnt.HitPos.Value);
                    }
                    else
                    {
                        if (hitEnt.SphereCheck || info.EwarActive)
                        {
                            var ewarActive = hitEnt.EventType == Field || hitEnt.EventType == Effect;

                            dist           = 0;
                            hitEnt.HitDist = dist;
                            hitEnt.Hit     = true;
                            var hitPos = !ewarActive ? hitEnt.PruneSphere.Center + (hitEnt.Intersection.Direction * hitEnt.PruneSphere.Radius) : hitEnt.PruneSphere.Center;
                            hitEnt.HitPos = hitPos;
                        }
                        else
                        {
                            var rotMatrix = Quaternion.CreateFromRotationMatrix(ent.PositionComp.WorldMatrixRef);
                            var obb       = new MyOrientedBoundingBoxD(ent.PositionComp.WorldAABB.Center, ent.PositionComp.LocalAABB.HalfExtents, rotMatrix);
                            dist = obb.Intersects(ref beam) ?? double.MaxValue;
                            if (dist < double.MaxValue)
                            {
                                hitEnt.Hit     = true;
                                hitEnt.HitPos  = beam.From + (beam.Direction * dist);
                                hitEnt.HitDist = dist;
                            }
                        }
                    }
                }

                if (isX)
                {
                    xDist = dist;
                }
                else
                {
                    yDist = dist;
                }
            }
            V3Pool.Return(slims);
            return(xDist.CompareTo(yDist));
        }
Exemplo n.º 14
0
        private void DamageDestObj(HitEntity hitEnt, ProInfo info)
        {
            var entity  = hitEnt.Entity;
            var destObj = hitEnt.Entity as IMyDestroyableObject;

            if (destObj == null || entity == null)
            {
                return;
            }
            var shieldHeal   = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Heal;
            var shieldByPass = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass;
            var sync         = MpActive && IsServer;

            var attackerId = info.Target.FiringCube.EntityId;

            var objHp          = destObj.Integrity;
            var integrityCheck = info.AmmoDef.DamageScales.MaxIntegrity > 0;

            if (integrityCheck && objHp > info.AmmoDef.DamageScales.MaxIntegrity || shieldHeal)
            {
                info.BaseDamagePool = 0;
                return;
            }

            var   character   = hitEnt.Entity as IMyCharacter;
            float damageScale = 1;

            if (info.AmmoDef.Const.VirtualBeams)
            {
                damageScale *= info.WeaponCache.Hits;
            }
            if (character != null && info.AmmoDef.DamageScales.Characters >= 0)
            {
                damageScale *= info.AmmoDef.DamageScales.Characters;
            }

            var scaledDamage = info.BaseDamagePool * damageScale;

            var fallOff = info.AmmoDef.Const.FallOffScaling && info.DistanceTraveled > info.AmmoDef.DamageScales.FallOff.Distance;

            if (fallOff)
            {
                var fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((info.DistanceTraveled - info.AmmoDef.DamageScales.FallOff.Distance) / (info.AmmoDef.Const.MaxTrajectory - info.AmmoDef.DamageScales.FallOff.Distance)), info.AmmoDef.DamageScales.FallOff.MinMultipler, 1);
                scaledDamage *= fallOffMultipler;
            }

            if (scaledDamage < objHp)
            {
                info.BaseDamagePool = 0;
            }
            else
            {
                info.BaseDamagePool -= objHp;
            }

            if (!IsClient)
            {
                destObj.DoDamage(scaledDamage, !shieldByPass ? MyDamageType.Bullet : MyDamageType.Drill, sync, null, attackerId);
            }
            if (info.AmmoDef.Mass > 0)
            {
                var speed = info.AmmoDef.Trajectory.DesiredSpeed > 0 ? info.AmmoDef.Trajectory.DesiredSpeed : 1;
                ApplyProjectileForce(entity, entity.PositionComp.WorldAABB.Center, hitEnt.Intersection.Direction, (info.AmmoDef.Mass * speed));
            }
        }
Exemplo n.º 15
0
        private static void DamageProjectile(HitEntity hitEnt, ProInfo attacker)
        {
            var pTarget = hitEnt.Projectile;

            if (pTarget == null)
            {
                return;
            }

            attacker.ObjectsHit++;
            var objHp          = pTarget.Info.BaseHealthPool;
            var integrityCheck = attacker.AmmoDef.DamageScales.MaxIntegrity > 0;

            if (integrityCheck && objHp > attacker.AmmoDef.DamageScales.MaxIntegrity)
            {
                return;
            }

            float damageScale = 1;

            if (attacker.AmmoDef.Const.VirtualBeams)
            {
                damageScale *= attacker.WeaponCache.Hits;
            }

            var scaledDamage = attacker.BaseDamagePool * damageScale;

            var fallOff = attacker.AmmoDef.Const.FallOffScaling && attacker.DistanceTraveled > attacker.AmmoDef.DamageScales.FallOff.Distance;

            if (fallOff)
            {
                var fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((attacker.DistanceTraveled - attacker.AmmoDef.DamageScales.FallOff.Distance) / (attacker.AmmoDef.Const.MaxTrajectory - attacker.AmmoDef.DamageScales.FallOff.Distance)), attacker.AmmoDef.DamageScales.FallOff.MinMultipler, 1);
                scaledDamage *= fallOffMultipler;
            }

            if (scaledDamage >= objHp)
            {
                attacker.BaseDamagePool    -= objHp;
                pTarget.Info.BaseHealthPool = 0;
                pTarget.State = Projectile.ProjectileState.Destroy;
            }
            else
            {
                attacker.BaseDamagePool      = 0;
                pTarget.Info.BaseHealthPool -= scaledDamage;

                if (attacker.DetonationDamage > 0 && attacker.AmmoDef.AreaEffect.Detonation.DetonateOnEnd)
                {
                    var areaSphere = new BoundingSphereD(pTarget.Position, attacker.AmmoDef.AreaEffect.Detonation.DetonationRadius);
                    foreach (var sTarget in attacker.Ai.LiveProjectile)
                    {
                        if (areaSphere.Contains(sTarget.Position) != ContainmentType.Disjoint)
                        {
                            if (attacker.DetonationDamage >= sTarget.Info.BaseHealthPool)
                            {
                                sTarget.Info.BaseHealthPool = 0;
                                sTarget.State = Projectile.ProjectileState.Destroy;
                            }
                            else
                            {
                                sTarget.Info.BaseHealthPool -= attacker.DetonationDamage;
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 16
0
        private void DamageVoxel(HitEntity hitEnt, ProInfo info)
        {
            var entity  = hitEnt.Entity;
            var destObj = hitEnt.Entity as MyVoxelBase;

            if (destObj == null || entity == null || !hitEnt.HitPos.HasValue)
            {
                return;
            }
            var shieldHeal = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Heal;

            if (!info.AmmoDef.Const.VoxelDamage || shieldHeal)
            {
                info.BaseDamagePool = 0;
                return;
            }

            using (destObj.Pin())
            {
                var detonateOnEnd = info.AmmoDef.Const.AmmoAreaEffect && info.AmmoDef.AreaEffect.Detonation.DetonateOnEnd && info.AmmoDef.AreaEffect.AreaEffect != AreaEffectType.Radiant;

                info.ObjectsHit++;
                float damageScale = 1;
                if (info.AmmoDef.Const.VirtualBeams)
                {
                    damageScale *= info.WeaponCache.Hits;
                }

                var scaledDamage = info.BaseDamagePool * damageScale;
                var fallOff      = info.AmmoDef.Const.FallOffScaling && info.DistanceTraveled > info.AmmoDef.DamageScales.FallOff.Distance;
                if (fallOff)
                {
                    var fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((info.DistanceTraveled - info.AmmoDef.DamageScales.FallOff.Distance) / (info.AmmoDef.Const.MaxTrajectory - info.AmmoDef.DamageScales.FallOff.Distance)), info.AmmoDef.DamageScales.FallOff.MinMultipler, 1);
                    scaledDamage *= fallOffMultipler;
                }

                var oRadius       = info.AmmoDef.AreaEffect.AreaEffectRadius;
                var minTestRadius = info.DistanceTraveled - info.PrevDistanceTraveled;
                var tRadius       = oRadius < minTestRadius ? minTestRadius : oRadius;
                var objHp         = (int)MathHelper.Clamp(MathFuncs.VolumeCube(MathFuncs.LargestCubeInSphere(tRadius)), 1, double.MaxValue);
                var sync          = MpActive && IsServer;

                if (tRadius > 5)
                {
                    objHp *= 5;
                }
                if (scaledDamage < objHp)
                {
                    var reduceBy = objHp / scaledDamage;
                    oRadius /= reduceBy;
                    if (oRadius < 1)
                    {
                        oRadius = 1;
                    }

                    info.BaseDamagePool = 0;
                }
                else
                {
                    info.BaseDamagePool -= objHp;
                    if (oRadius < minTestRadius)
                    {
                        oRadius = minTestRadius;
                    }
                }
                destObj.PerformCutOutSphereFast(hitEnt.HitPos.Value, (float)oRadius, true);

                if (detonateOnEnd)
                {
                    var det     = info.AmmoDef.AreaEffect.Detonation;
                    var dRadius = det.DetonationRadius;
                    var dObjHp  = (int)MathHelper.Clamp(MathFuncs.VolumeCube(MathFuncs.LargestCubeInSphere(dRadius)), 1, double.MaxValue);
                    if (dRadius > 5)
                    {
                        dObjHp *= 5;
                    }
                    dObjHp *= 5;
                    var dDamage  = det.DetonationDamage;
                    var reduceBy = dObjHp / dDamage;

                    dRadius /= reduceBy;
                    if (dRadius < 1.5)
                    {
                        dRadius = 1.5f;
                    }
                    if (sync)
                    {
                        destObj.PerformCutOutSphereFast(hitEnt.HitPos.Value, dRadius, true);
                    }
                }
            }
        }
Exemplo n.º 17
0
        private void DamageShield(HitEntity hitEnt, ProInfo info)
        {
            var shield = hitEnt.Entity as IMyTerminalBlock;

            if (shield == null || !hitEnt.HitPos.HasValue)
            {
                return;
            }
            info.ObjectsHit++;

            var damageScale = 1;
            var fallOff     = info.AmmoDef.Const.FallOffScaling && info.DistanceTraveled > info.AmmoDef.DamageScales.FallOff.Distance;

            if (info.AmmoDef.Const.VirtualBeams)
            {
                damageScale *= info.WeaponCache.Hits;
            }
            var damageType   = info.AmmoDef.DamageScales.Shields.Type;
            var energy       = damageType == ShieldDef.ShieldType.Energy;
            var heal         = damageType == ShieldDef.ShieldType.Heal;
            var shieldByPass = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass;

            var areaEffect    = info.AmmoDef.AreaEffect;
            var detonateOnEnd = info.AmmoDef.AreaEffect.Detonation.DetonateOnEnd && areaEffect.AreaEffect != AreaEffectType.Disabled && !shieldByPass;
            var areaDamage    = areaEffect.AreaEffect != AreaEffectType.Disabled ? areaEffect.AreaEffectDamage * (areaEffect.AreaEffectRadius * 0.5f) : 0;
            var scaledDamage  = (((info.BaseDamagePool * damageScale) + areaDamage) * info.AmmoDef.Const.ShieldModifier) * info.AmmoDef.Const.ShieldBypassMod;

            if (fallOff)
            {
                var fallOffMultipler = MathHelperD.Clamp(1.0 - ((info.DistanceTraveled - info.AmmoDef.DamageScales.FallOff.Distance) / (info.AmmoDef.Const.MaxTrajectory - info.AmmoDef.DamageScales.FallOff.Distance)), info.AmmoDef.DamageScales.FallOff.MinMultipler, 1);
                scaledDamage *= fallOffMultipler;
            }

            var detonateDamage = detonateOnEnd ? (areaEffect.Detonation.DetonationDamage * (areaEffect.Detonation.DetonationRadius * 0.5f)) * info.AmmoDef.Const.ShieldModifier : 0;

            var combinedDamage = (float)(scaledDamage + detonateDamage);

            if (heal)
            {
                combinedDamage *= -1;
            }

            var hit = SApi.PointAttackShieldExt(shield, hitEnt.HitPos.Value, info.Target.FiringCube.EntityId, combinedDamage, energy, info.AmmoDef.AmmoGraphics.ShieldHitDraw);

            if (hit.HasValue)
            {
                if (heal)
                {
                    info.BaseDamagePool = 0;
                    return;
                }
                var objHp = hit.Value;
                if (info.EwarActive)
                {
                    info.BaseHealthPool -= 1;
                }
                else if (objHp > 0)
                {
                    if (!shieldByPass)
                    {
                        info.BaseDamagePool = 0;
                    }
                    else
                    {
                        info.BaseDamagePool *= info.AmmoDef.Const.ShieldBypassMod;
                    }
                }
                else
                {
                    info.BaseDamagePool = (objHp * -1);
                }
                if (info.AmmoDef.Mass <= 0)
                {
                    return;
                }

                var speed = info.AmmoDef.Trajectory.DesiredSpeed > 0 ? info.AmmoDef.Trajectory.DesiredSpeed : 1;
                ApplyProjectileForce((MyEntity)shield.CubeGrid, hitEnt.HitPos.Value, hitEnt.Intersection.Direction, info.AmmoDef.Mass * speed);
            }
        }
Exemplo n.º 18
0
        internal void InitialHitCheck()
        {
            var vhCount  = ValidateHits.Count;
            var minCount = Session.Settings.Enforcement.ServerOptimizations ? 96 : 99999;
            var stride   = vhCount < minCount ? 100000 : 48;

            MyAPIGateway.Parallel.For(0, ValidateHits.Count, x => {
                var p = ValidateHits[x];

                var shieldByPass       = p.Info.ConsumableDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass;
                var shieldFullBypass   = shieldByPass && p.Info.ConsumableDef.Const.ShieldBypassMod >= 1;
                var genericFields      = p.Info.EwarActive && (p.Info.ConsumableDef.Const.AreaEffect == DotField || p.Info.ConsumableDef.Const.AreaEffect == PushField || p.Info.ConsumableDef.Const.AreaEffect == PullField);
                p.FinalizeIntersection = false;
                var lineCheck          = p.Info.ConsumableDef.Const.CollisionIsLine && !p.Info.EwarAreaPulse;
                var ewarProjectile     = (p.Info.EwarActive || p.Info.ConsumableDef.Const.EwarEffect);

                bool projetileInShield = false;
                var tick = p.Info.System.Session.Tick;

                var useEntityCollection = p.CheckType != Projectile.CheckTypes.Ray;
                var entityCollection    = p.UseEntityCache ? p.Info.Ai.NearByEntityCache : p.MyEntityList;
                var collectionCount     = !useEntityCollection ? p.MySegmentList.Count : entityCollection.Count;
                var ray    = new RayD(ref p.Beam.From, ref p.Beam.Direction);
                var myGrid = p.Info.Target.FiringCube.CubeGrid;

                Water water = null;
                if (Session.WaterApiLoaded && p.Info.MyPlanet != null)
                {
                    Session.WaterMap.TryGetValue(p.Info.MyPlanet, out water);
                }

                for (int i = 0; i < collectionCount; i++)
                {
                    var ent = !useEntityCollection ? p.MySegmentList[i].Element : entityCollection[i];

                    var grid      = ent as MyCubeGrid;
                    var entIsSelf = grid != null && (grid == myGrid || myGrid.IsSameConstructAs(grid));

                    if (entIsSelf && p.SmartsOn || ent.MarkedForClose || !ent.InScene || ent == p.Info.MyShield)
                    {
                        continue;
                    }

                    var character = ent as IMyCharacter;
                    if (p.Info.EwarActive && character != null && !genericFields)
                    {
                        continue;
                    }

                    var entSphere = ent.PositionComp.WorldVolume;
                    if (useEntityCollection)
                    {
                        if (p.CheckType == Projectile.CheckTypes.CachedRay)
                        {
                            var dist = ray.Intersects(entSphere);
                            if (!dist.HasValue || dist > p.Beam.Length)
                            {
                                continue;
                            }
                        }
                        else if (p.CheckType == Projectile.CheckTypes.CachedSphere && p.PruneSphere.Contains(entSphere) == ContainmentType.Disjoint)
                        {
                            continue;
                        }
                    }

                    if (grid != null || character != null)
                    {
                        var extBeam   = new LineD(p.Beam.From - p.Beam.Direction * (entSphere.Radius * 2), p.Beam.To);
                        var transform = ent.PositionComp.WorldMatrixRef;
                        var box       = ent.PositionComp.LocalAABB;
                        var obb       = new MyOrientedBoundingBoxD(box, transform);
                        if (lineCheck && obb.Intersects(ref extBeam) == null || !lineCheck && !obb.Intersects(ref p.PruneSphere))
                        {
                            continue;
                        }
                    }
                    var safeZone = ent as MySafeZone;
                    if (safeZone != null && safeZone.Enabled)
                    {
                        var action = (Session.SafeZoneAction)safeZone.AllowedActions;
                        if ((action & Session.SafeZoneAction.Damage) == 0)
                        {
                            bool intersects;
                            if (safeZone.Shape == MySafeZoneShape.Sphere)
                            {
                                var sphere = new BoundingSphereD(safeZone.PositionComp.WorldVolume.Center, safeZone.Radius);
                                var dist   = ray.Intersects(sphere);
                                intersects = dist != null && dist <= p.Beam.Length;
                            }
                            else
                            {
                                intersects = new MyOrientedBoundingBoxD(safeZone.PositionComp.LocalAABB, safeZone.PositionComp.WorldMatrixRef).Intersects(ref p.Beam) != null;
                            }

                            if (intersects)
                            {
                                p.State    = Projectile.ProjectileState.Depleted;
                                p.EarlyEnd = true;

                                if (p.EnableAv)
                                {
                                    p.Info.AvShot.ForceHitParticle = true;
                                }
                                break;
                            }
                        }
                    }

                    HitEntity hitEntity = null;
                    var checkShield     = Session.ShieldApiLoaded && Session.ShieldHash == ent.DefinitionId?.SubtypeId && ent.Render.Visible;
                    MyTuple <IMyTerminalBlock, MyTuple <bool, bool, float, float, float, int>, MyTuple <MatrixD, MatrixD> >?shieldInfo = null;
                    if (checkShield && (!shieldFullBypass && !p.ShieldBypassed || p.Info.EwarActive && (p.Info.ConsumableDef.Const.AreaEffect == DotField || p.Info.ConsumableDef.Const.AreaEffect == EmpField)))
                    {
                        shieldInfo = p.Info.System.Session.SApi.MatchEntToShieldFastExt(ent, true);
                        if (shieldInfo != null && !myGrid.IsSameConstructAs(shieldInfo.Value.Item1.CubeGrid))
                        {
                            if (p.Info.IsShrapnel || Vector3D.Transform(p.Info.Origin, shieldInfo.Value.Item3.Item1).LengthSquared() > 1)
                            {
                                p.EntitiesNear = true;
                                var dist       = MathFuncs.IntersectEllipsoid(shieldInfo.Value.Item3.Item1, shieldInfo.Value.Item3.Item2, new RayD(p.Beam.From, p.Beam.Direction));
                                if (p.Info.Target.IsProjectile && Vector3D.Transform(p.Info.Target.Projectile.Position, shieldInfo.Value.Item3.Item1).LengthSquared() <= 1)
                                {
                                    projetileInShield = true;
                                }

                                if (dist != null && (dist.Value < p.Beam.Length || p.Info.EwarActive))
                                {
                                    if (shieldByPass)
                                    {
                                        p.ShieldBypassed = true;
                                    }
                                    hitEntity           = HitEntityPool.Get();
                                    hitEntity.EventType = Shield;
                                    hitEntity.HitPos    = p.Beam.From + (p.Beam.Direction * dist.Value);
                                    hitEntity.HitDist   = dist;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                        }
                    }

                    var destroyable = ent as IMyDestroyableObject;
                    var voxel       = ent as MyVoxelBase;
                    if (voxel != null && voxel == voxel?.RootVoxel)
                    {
                        if (ent == p.Info.MyPlanet && !(p.LinePlanetCheck || p.DynamicGuidance || p.CachedPlanetHit))
                        {
                            continue;
                        }
                        VoxelIntersectBranch voxelState = VoxelIntersectBranch.None;
                        Vector3D?voxelHit = null;
                        if (tick - p.Info.VoxelCache.HitRefreshed < 60)
                        {
                            var cacheDist = ray.Intersects(p.Info.VoxelCache.HitSphere);
                            if (cacheDist.HasValue && cacheDist.Value <= p.Beam.Length)
                            {
                                voxelHit   = p.Beam.From + (p.Beam.Direction * cacheDist.Value);
                                voxelState = VoxelIntersectBranch.PseudoHit1;
                            }
                            else if (cacheDist.HasValue)
                            {
                                p.Info.VoxelCache.MissSphere.Center = p.Beam.To;
                            }
                        }

                        if (voxelState != VoxelIntersectBranch.PseudoHit1)
                        {
                            if (voxel == p.Info.MyPlanet && p.Info.VoxelCache.MissSphere.Contains(p.Beam.To) == ContainmentType.Disjoint)
                            {
                                if (p.LinePlanetCheck)
                                {
                                    if (water != null && !p.Info.ConsumableDef.IgnoreWater)
                                    {
                                        var waterSphere = new BoundingSphereD(p.Info.MyPlanet.PositionComp.WorldAABB.Center, water.radius);
                                        var estiamtedSurfaceDistance = ray.Intersects(waterSphere);

                                        if (estiamtedSurfaceDistance.HasValue && estiamtedSurfaceDistance.Value <= p.Beam.Length)
                                        {
                                            var estimatedHit = ray.Position + (ray.Direction * estiamtedSurfaceDistance.Value);
                                            voxelHit         = estimatedHit;
                                            voxelState       = VoxelIntersectBranch.PseudoHit2;
                                        }
                                    }

                                    if (voxelState != VoxelIntersectBranch.PseudoHit2)
                                    {
                                        var surfacePos   = p.Info.MyPlanet.GetClosestSurfacePointGlobal(ref p.Position);
                                        var planetCenter = p.Info.MyPlanet.PositionComp.WorldAABB.Center;
                                        double surfaceToCenter;
                                        Vector3D.DistanceSquared(ref surfacePos, ref planetCenter, out surfaceToCenter);
                                        double endPointToCenter;
                                        Vector3D.DistanceSquared(ref p.Position, ref planetCenter, out endPointToCenter);
                                        double startPointToCenter;
                                        Vector3D.DistanceSquared(ref p.Info.Origin, ref planetCenter, out startPointToCenter);

                                        var prevEndPointToCenter = p.PrevEndPointToCenterSqr;
                                        Vector3D.DistanceSquared(ref surfacePos, ref p.Position, out p.PrevEndPointToCenterSqr);
                                        if (surfaceToCenter > endPointToCenter || p.PrevEndPointToCenterSqr <= (p.Beam.Length * p.Beam.Length) || endPointToCenter > startPointToCenter && prevEndPointToCenter > p.DistanceToTravelSqr || surfaceToCenter > Vector3D.DistanceSquared(planetCenter, p.LastPosition))
                                        {
                                            var estiamtedSurfaceDistance = ray.Intersects(p.Info.VoxelCache.PlanetSphere);
                                            var fullCheck = p.Info.VoxelCache.PlanetSphere.Contains(p.Info.Origin) != ContainmentType.Disjoint || !estiamtedSurfaceDistance.HasValue;

                                            if (!fullCheck && estiamtedSurfaceDistance.HasValue && (estiamtedSurfaceDistance.Value <= p.Beam.Length || p.Info.VoxelCache.PlanetSphere.Radius < 1))
                                            {
                                                double distSqr;
                                                var estimatedHit = ray.Position + (ray.Direction * estiamtedSurfaceDistance.Value);
                                                Vector3D.DistanceSquared(ref p.Info.VoxelCache.FirstPlanetHit, ref estimatedHit, out distSqr);

                                                if (distSqr > 625)
                                                {
                                                    fullCheck = true;
                                                }
                                                else
                                                {
                                                    voxelHit   = estimatedHit;
                                                    voxelState = VoxelIntersectBranch.PseudoHit2;
                                                }
                                            }

                                            if (fullCheck)
                                            {
                                                voxelState = VoxelIntersectBranch.DeferFullCheck;
                                            }

                                            if (voxelHit.HasValue && Vector3D.DistanceSquared(voxelHit.Value, p.Info.VoxelCache.PlanetSphere.Center) > p.Info.VoxelCache.PlanetSphere.Radius * p.Info.VoxelCache.PlanetSphere.Radius)
                                            {
                                                p.Info.VoxelCache.GrowPlanetCache(voxelHit.Value);
                                            }
                                        }
                                    }
                                }
                            }
                            else if (voxelHit == null && p.Info.VoxelCache.MissSphere.Contains(p.Beam.To) == ContainmentType.Disjoint)
                            {
                                voxelState = VoxelIntersectBranch.DeferedMissUpdate;
                            }
                        }

                        if (voxelState == VoxelIntersectBranch.PseudoHit1 || voxelState == VoxelIntersectBranch.PseudoHit2)
                        {
                            if (!voxelHit.HasValue)
                            {
                                if (p.Info.VoxelCache.MissSphere.Contains(p.Beam.To) == ContainmentType.Disjoint)
                                {
                                    p.Info.VoxelCache.MissSphere.Center = p.Beam.To;
                                }
                                continue;
                            }

                            hitEntity = HitEntityPool.Get();

                            var hitPos       = voxelHit.Value;
                            hitEntity.HitPos = hitPos;

                            double dist;
                            Vector3D.Distance(ref p.Beam.From, ref hitPos, out dist);
                            hitEntity.HitDist = dist;

                            hitEntity.EventType = Voxel;
                        }
                        else if (voxelState == VoxelIntersectBranch.DeferedMissUpdate || voxelState == VoxelIntersectBranch.DeferFullCheck)
                        {
                            DeferedVoxels.Add(new DeferedVoxels {
                                Projectile = p, Branch = voxelState, Voxel = voxel
                            });
                        }
                    }
                    else if (ent.Physics != null && !ent.Physics.IsPhantom && !ent.IsPreview && grid != null)
                    {
                        if (grid != null)
                        {
                            hitEntity = HitEntityPool.Get();
                            if (entIsSelf)
                            {
                                if (!p.Info.ConsumableDef.Const.IsBeamWeapon && p.Beam.Length <= grid.GridSize * 2)
                                {
                                    MyCube cube;
                                    if (!(grid.TryGetCube(grid.WorldToGridInteger(p.Position), out cube) && cube.CubeBlock != p.Info.Target.FiringCube.SlimBlock || grid.TryGetCube(grid.WorldToGridInteger(p.LastPosition), out cube) && cube.CubeBlock != p.Info.Target.FiringCube.SlimBlock))
                                    {
                                        HitEntityPool.Return(hitEntity);
                                        continue;
                                    }
                                }

                                if (!p.Info.EwarAreaPulse)
                                {
                                    var forwardPos = p.Info.Age != 1 ? p.Beam.From : p.Beam.From + (p.Beam.Direction * Math.Min(grid.GridSizeHalf, p.Info.DistanceTraveled - p.Info.PrevDistanceTraveled));
                                    grid.RayCastCells(forwardPos, p.Beam.To, hitEntity.Vector3ICache, null, true, true);

                                    if (hitEntity.Vector3ICache.Count > 0)
                                    {
                                        IHitInfo hitInfo;
                                        p.Info.System.Session.Physics.CastRay(forwardPos, p.Beam.To, out hitInfo, CollisionLayers.DefaultCollisionLayer);
                                        var hitGrid = hitInfo?.HitEntity?.GetTopMostParent() as MyCubeGrid;
                                        if (hitGrid == null || !myGrid.IsSameConstructAs(hitGrid))
                                        {
                                            HitEntityPool.Return(hitEntity);
                                            continue;
                                        }

                                        hitEntity.HitPos = hitInfo.Position;
                                        hitEntity.Blocks.Add(grid.GetCubeBlock(hitEntity.Vector3ICache[0]));
                                    }
                                }
                            }
                            else
                            {
                                grid.RayCastCells(p.Beam.From, p.Beam.To, hitEntity.Vector3ICache, null, true, true);
                            }

                            if (!ewarProjectile)
                            {
                                hitEntity.EventType = Grid;
                            }
                            else if (!p.Info.EwarAreaPulse)
                            {
                                hitEntity.EventType = Effect;
                            }
                            else
                            {
                                hitEntity.EventType = Field;
                            }

                            p.EntitiesNear = true;
                        }
                    }
                    else if (destroyable != null)
                    {
                        hitEntity           = HitEntityPool.Get();
                        hitEntity.EventType = Destroyable;
                    }

                    if (hitEntity != null)
                    {
                        p.FinalizeIntersection   = true;
                        hitEntity.Info           = p.Info;
                        hitEntity.Entity         = hitEntity.EventType != Shield ? ent : (MyEntity)shieldInfo.Value.Item1;
                        hitEntity.Intersection   = p.Beam;
                        hitEntity.SphereCheck    = !lineCheck;
                        hitEntity.PruneSphere    = p.PruneSphere;
                        hitEntity.SelfHit        = entIsSelf;
                        hitEntity.DamageOverTime = p.Info.ConsumableDef.Const.AreaEffect == DotField;

                        p.Info.HitList.Add(hitEntity);
                    }
                }

                if (p.Info.Target.IsProjectile && !p.Info.ConsumableDef.Const.EwarEffect && !projetileInShield)
                {
                    var detonate     = p.State == Projectile.ProjectileState.Detonate;
                    var hitTolerance = detonate ? p.Info.ConsumableDef.Const.DetonationRadius : p.Info.ConsumableDef.Const.AreaEffectSize > p.Info.ConsumableDef.Const.CollisionSize ? p.Info.ConsumableDef.Const.AreaEffectSize : p.Info.ConsumableDef.Const.CollisionSize;
                    var useLine      = p.Info.ConsumableDef.Const.CollisionIsLine && !detonate && p.Info.ConsumableDef.Const.AreaEffectSize <= 0;

                    var sphere = new BoundingSphereD(p.Info.Target.Projectile.Position, p.Info.Target.Projectile.Info.ConsumableDef.Const.CollisionSize);
                    sphere.Include(new BoundingSphereD(p.Info.Target.Projectile.LastPosition, 1));

                    bool rayCheck = false;
                    if (useLine)
                    {
                        var dist = sphere.Intersects(new RayD(p.LastPosition, p.Info.Direction));
                        if (dist <= hitTolerance || p.Info.ConsumableDef.Const.IsBeamWeapon && dist <= p.Beam.Length)
                        {
                            rayCheck = true;
                        }
                    }

                    var testSphere    = p.PruneSphere;
                    testSphere.Radius = hitTolerance;

                    if (rayCheck || sphere.Intersects(testSphere))
                    {
                        ProjectileHit(p, p.Info.Target.Projectile, lineCheck, ref p.Beam);
                    }
                }

                if (!useEntityCollection)
                {
                    p.MySegmentList.Clear();
                }
                else if (p.CheckType == Projectile.CheckTypes.Sphere)
                {
                    entityCollection.Clear();
                }

                if (p.FinalizeIntersection)
                {
                    FinalHitCheck.Add(p);
                }
            }, stride);
            ValidateHits.ClearImmediate();
        }
Exemplo n.º 19
0
        private static void PushPull(HitEntity hitEnt, ProInfo info)
        {
            var depletable = info.AmmoDef.AreaEffect.EwarFields.Depletable;
            var healthPool = depletable && info.BaseHealthPool > 0 ? info.BaseHealthPool : float.MaxValue;

            if (healthPool <= 0)
            {
                return;
            }

            if (hitEnt.Entity.Physics == null || !hitEnt.Entity.Physics.Enabled || hitEnt.Entity.Physics.IsStatic || !hitEnt.HitPos.HasValue)
            {
                return;
            }

            var forceDef = info.AmmoDef.AreaEffect.EwarFields.Force;

            Vector3D forceFrom     = Vector3D.Zero;
            Vector3D forceTo       = Vector3D.Zero;
            Vector3D forcePosition = Vector3D.Zero;

            if (forceDef.ForceFrom == Force.ProjectileLastPosition)
            {
                forceFrom = hitEnt.Intersection.From;
            }
            else if (forceDef.ForceFrom == Force.ProjectileOrigin)
            {
                forceFrom = info.Origin;
            }
            else if (forceDef.ForceFrom == Force.HitPosition)
            {
                forceFrom = hitEnt.HitPos.Value;
            }
            else if (forceDef.ForceFrom == Force.TargetCenter)
            {
                forceFrom = hitEnt.Entity.PositionComp.WorldAABB.Center;
            }
            else if (forceDef.ForceFrom == Force.TargetCenterOfMass)
            {
                forceFrom = hitEnt.Entity.Physics.CenterOfMassWorld;
            }

            if (forceDef.ForceTo == Force.ProjectileLastPosition)
            {
                forceTo = hitEnt.Intersection.From;
            }
            else if (forceDef.ForceTo == Force.ProjectileOrigin)
            {
                forceTo = info.Origin;
            }
            else if (forceDef.ForceTo == Force.HitPosition)
            {
                forceTo = hitEnt.HitPos.Value;
            }
            else if (forceDef.ForceTo == Force.TargetCenter)
            {
                forceTo = hitEnt.Entity.PositionComp.WorldAABB.Center;
            }
            else if (forceDef.ForceTo == Force.TargetCenterOfMass)
            {
                forceTo = hitEnt.Entity.Physics.CenterOfMassWorld;
            }

            if (forceDef.Position == Force.ProjectileLastPosition)
            {
                forcePosition = hitEnt.Intersection.From;
            }
            else if (forceDef.Position == Force.ProjectileOrigin)
            {
                forcePosition = info.Origin;
            }
            else if (forceDef.Position == Force.HitPosition)
            {
                forcePosition = hitEnt.HitPos.Value;
            }
            else if (forceDef.Position == Force.TargetCenter)
            {
                forcePosition = hitEnt.Entity.PositionComp.WorldAABB.Center;
            }
            else if (forceDef.Position == Force.TargetCenterOfMass)
            {
                forcePosition = hitEnt.Entity.Physics.CenterOfMassWorld;
            }

            var hitDir = forceTo - forceFrom;

            Vector3D normHitDir;

            Vector3D.Normalize(ref hitDir, out normHitDir);

            normHitDir = info.AmmoDef.Const.AreaEffect == PushField ? normHitDir : -normHitDir;
            if (info.System.Session.IsServer)
            {
                hitEnt.Entity.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, normHitDir * (info.AmmoDef.Const.AreaEffectDamage * hitEnt.Entity.Physics.Mass), forcePosition, Vector3.Zero);
            }

            if (depletable)
            {
                info.BaseHealthPool -= healthPool;
            }
        }
Exemplo n.º 20
0
        private void UpdateEffect(HitEntity hitEnt, ProInfo info)
        {
            var grid = hitEnt.Entity as MyCubeGrid;

            if (grid == null || grid.MarkedForClose)
            {
                return;
            }
            Dictionary <AreaEffectType, GridEffect> effects;
            var attackerId = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass ? grid.EntityId : info.Target.FiringCube.EntityId;
            var found      = false;

            if (_gridEffects.TryGetValue(grid, out effects))
            {
                GridEffect gridEffect;
                if (effects.TryGetValue(info.AmmoDef.AreaEffect.AreaEffect, out gridEffect))
                {
                    found                 = true;
                    gridEffect.Damage    += info.AreaEffectDamage;
                    gridEffect.Ai         = info.Ai;
                    gridEffect.AttackerId = attackerId;
                    gridEffect.Hits++;
                    if (hitEnt.HitPos != null)
                    {
                        gridEffect.HitPos = hitEnt.HitPos.Value / gridEffect.Hits;
                    }
                }
            }

            if (!found)
            {
                if (effects == null)
                {
                    effects = GridEffectsPool.Get();
                }
                GridEffect gridEffect;
                if (effects.TryGetValue(info.AmmoDef.AreaEffect.AreaEffect, out gridEffect))
                {
                    gridEffect.Damage    += info.AreaEffectDamage;
                    gridEffect.Ai         = info.Ai;
                    gridEffect.AmmoDef    = info.AmmoDef;
                    gridEffect.AttackerId = attackerId;
                    gridEffect.Hits++;
                    if (hitEnt.HitPos != null)
                    {
                        gridEffect.HitPos += hitEnt.HitPos.Value / gridEffect.Hits;
                    }
                }
                else
                {
                    gridEffect            = GridEffectPool.Get();
                    gridEffect.System     = info.System;
                    gridEffect.Damage     = info.AreaEffectDamage;
                    gridEffect.Ai         = info.Ai;
                    gridEffect.AmmoDef    = info.AmmoDef;
                    gridEffect.AttackerId = attackerId;
                    gridEffect.Hits++;
                    if (hitEnt.HitPos != null)
                    {
                        gridEffect.HitPos = hitEnt.HitPos.Value;
                    }
                    effects.Add(info.AmmoDef.AreaEffect.AreaEffect, gridEffect);
                }
                _gridEffects.Add(grid, effects);
            }
            info.BaseHealthPool = 0;
            info.BaseDamagePool = 0;
        }
Exemplo n.º 21
0
        internal int GetEntityCompareDist(HitEntity x, HitEntity y, ProInfo info)
        {
            var xDist        = double.MaxValue;
            var yDist        = double.MaxValue;
            var beam         = x.Intersection;
            var count        = y != null ? 2 : 1;
            var eWarPulse    = info.ConsumableDef.Const.Ewar && info.ConsumableDef.Const.Pulse;
            var triggerEvent = eWarPulse && !info.EwarAreaPulse && info.ConsumableDef.Const.EwarTriggerRange > 0;

            for (int i = 0; i < count; i++)
            {
                var isX = i == 0;

                MyEntity  ent;
                HitEntity hitEnt;
                HitEntity otherHit;
                if (isX)
                {
                    hitEnt   = x;
                    otherHit = y;
                    ent      = hitEnt.Entity;
                }
                else
                {
                    hitEnt   = y;
                    otherHit = x;
                    ent      = hitEnt.Entity;
                }

                var dist   = double.MaxValue;
                var shield = ent as IMyTerminalBlock;
                var grid   = ent as MyCubeGrid;
                var voxel  = ent as MyVoxelBase;

                if (triggerEvent && (info.Ai.Targets.ContainsKey(ent) || shield != null))
                {
                    hitEnt.PulseTrigger = true;
                }
                else if (hitEnt.Projectile != null)
                {
                    dist = hitEnt.HitDist.Value;
                }
                else if (shield != null)
                {
                    hitEnt.Hit = true;
                    dist       = hitEnt.HitDist.Value;
                }
                else if (grid != null)
                {
                    if (hitEnt.Hit)
                    {
                        dist           = Vector3D.Distance(hitEnt.Intersection.From, hitEnt.HitPos.Value);
                        hitEnt.HitDist = dist;
                    }
                    else if (hitEnt.HitPos != null)
                    {
                        dist           = Vector3D.Distance(hitEnt.Intersection.From, hitEnt.HitPos.Value);
                        hitEnt.HitDist = dist;
                        hitEnt.Hit     = true;
                    }
                    else
                    {
                        if (hitEnt.SphereCheck || info.EwarActive && eWarPulse)
                        {
                            var ewarActive = hitEnt.EventType == Field || hitEnt.EventType == Effect;

                            var hitPos = !ewarActive ? hitEnt.PruneSphere.Center + (hitEnt.Intersection.Direction * hitEnt.PruneSphere.Radius) : hitEnt.PruneSphere.Center;
                            if (hitEnt.SelfHit && Vector3D.DistanceSquared(hitPos, hitEnt.Info.Origin) <= grid.GridSize * grid.GridSize)
                            {
                                continue;
                            }

                            if (!ewarActive)
                            {
                                GetAndSortBlocksInSphere(hitEnt.Info.ConsumableDef, hitEnt.Info.System, grid, hitEnt.PruneSphere, false, hitEnt.Blocks);
                            }

                            if (hitEnt.Blocks.Count > 0 || ewarActive)
                            {
                                dist           = 0;
                                hitEnt.HitDist = dist;
                                hitEnt.Hit     = true;
                                hitEnt.HitPos  = hitPos;
                            }
                        }
                        else
                        {
                            var closestBlockFound = false;
                            for (int j = 0; j < hitEnt.Vector3ICache.Count; j++)
                            {
                                var     firstBlock = grid.GetCubeBlock(hitEnt.Vector3ICache[j]) as IMySlimBlock;
                                MatrixD transform  = grid.WorldMatrix;
                                if (firstBlock != null && !firstBlock.IsDestroyed && firstBlock != hitEnt.Info.Target.FiringCube.SlimBlock)
                                {
                                    hitEnt.Blocks.Add(firstBlock);
                                    if (closestBlockFound)
                                    {
                                        continue;
                                    }
                                    MyOrientedBoundingBoxD obb;
                                    var fat = firstBlock.FatBlock;
                                    if (fat != null)
                                    {
                                        obb = new MyOrientedBoundingBoxD(fat.Model.BoundingBox, fat.PositionComp.WorldMatrixRef);
                                    }
                                    else
                                    {
                                        Vector3 halfExt;
                                        firstBlock.ComputeScaledHalfExtents(out halfExt);
                                        var blockBox = new BoundingBoxD(-halfExt, halfExt);
                                        transform.Translation = grid.GridIntegerToWorld(firstBlock.Position);
                                        obb = new MyOrientedBoundingBoxD(blockBox, transform);
                                    }

                                    var hitDist = obb.Intersects(ref beam) ?? Vector3D.Distance(beam.From, obb.Center);
                                    var hitPos  = beam.From + (beam.Direction * hitDist);

                                    if (hitEnt.SelfHit)
                                    {
                                        if (Vector3D.DistanceSquared(hitPos, hitEnt.Info.Origin) <= grid.GridSize * 3)
                                        {
                                            hitEnt.Blocks.Clear();
                                        }
                                        else
                                        {
                                            dist           = hitDist;
                                            hitEnt.HitDist = dist;
                                            hitEnt.Hit     = true;
                                            hitEnt.HitPos  = hitPos;
                                        }
                                        break;
                                    }

                                    dist              = hitDist;
                                    hitEnt.HitDist    = dist;
                                    hitEnt.Hit        = true;
                                    hitEnt.HitPos     = hitPos;
                                    closestBlockFound = true;
                                }
                            }
                        }
                    }
                }
                else if (voxel != null)
                {
                    hitEnt.Hit     = true;
                    dist           = hitEnt.HitDist.Value;
                    hitEnt.HitDist = dist;
                }
                else if (ent is IMyDestroyableObject)
                {
                    if (hitEnt.Hit)
                    {
                        dist = Vector3D.Distance(hitEnt.Intersection.From, hitEnt.HitPos.Value);
                    }
                    else
                    {
                        if (hitEnt.SphereCheck || info.EwarActive && eWarPulse)
                        {
                            var ewarActive = hitEnt.EventType == Field || hitEnt.EventType == Effect;
                            dist           = 0;
                            hitEnt.HitDist = dist;
                            hitEnt.Hit     = true;
                            var hitPos = !ewarActive ? hitEnt.PruneSphere.Center + (hitEnt.Intersection.Direction * hitEnt.PruneSphere.Radius) : hitEnt.PruneSphere.Center;
                            hitEnt.HitPos = hitPos;
                        }
                        else
                        {
                            var transform = ent.PositionComp.WorldMatrixRef;
                            var box       = ent.PositionComp.LocalAABB;
                            var obb       = new MyOrientedBoundingBoxD(box, transform);
                            dist = obb.Intersects(ref beam) ?? double.MaxValue;
                            if (dist < double.MaxValue)
                            {
                                hitEnt.Hit     = true;
                                hitEnt.HitPos  = beam.From + (beam.Direction * dist);
                                hitEnt.HitDist = dist;
                            }
                        }
                    }
                }

                if (isX)
                {
                    xDist = dist;
                }
                else
                {
                    yDist = dist;
                }
            }
            return(xDist.CompareTo(yDist));
        }
        private void DamageVoxel(HitEntity hitEnt, ProInfo info, bool canDamage)
        {
            var entity  = hitEnt.Entity;
            var destObj = hitEnt.Entity as MyVoxelBase;

            if (destObj == null || entity == null || !hitEnt.HitPos.HasValue)
            {
                return;
            }
            var shieldHeal = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Heal;

            if (!info.AmmoDef.Const.VoxelDamage || shieldHeal)
            {
                info.BaseDamagePool = 0;
                return;
            }

            using (destObj.Pin())
            {
                var detonateOnEnd = info.AmmoDef.Const.AmmoAreaEffect && info.AmmoDef.AreaEffect.Detonation.DetonateOnEnd && info.AmmoDef.AreaEffect.AreaEffect != AreaEffectType.Radiant;

                info.ObjectsHit++;
                float damageScale = 1;
                if (info.AmmoDef.Const.VirtualBeams)
                {
                    damageScale *= info.WeaponCache.Hits;
                }

                var scaledDamage = info.BaseDamagePool * damageScale;
                var fallOff      = info.AmmoDef.Const.FallOffScaling && info.DistanceTraveled > info.AmmoDef.DamageScales.FallOff.Distance;
                if (fallOff)
                {
                    var fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((info.DistanceTraveled - info.AmmoDef.DamageScales.FallOff.Distance) / (info.AmmoDef.Const.MaxTrajectory - info.AmmoDef.DamageScales.FallOff.Distance)), info.AmmoDef.DamageScales.FallOff.MinMultipler, 1);
                    scaledDamage *= fallOffMultipler;
                }

                var oRadius       = info.AmmoDef.AreaEffect.AreaEffectRadius;
                var minTestRadius = info.DistanceTraveled - info.PrevDistanceTraveled;
                var tRadius       = oRadius < minTestRadius ? minTestRadius : oRadius;
                var objHp         = (int)MathHelper.Clamp(MathFuncs.VolumeCube(MathFuncs.LargestCubeInSphere(tRadius)), 5000, double.MaxValue);


                if (tRadius > 5)
                {
                    objHp *= 5;
                }
                if (scaledDamage < objHp)
                {
                    var reduceBy = objHp / scaledDamage;
                    oRadius /= reduceBy;
                    if (oRadius < 1)
                    {
                        oRadius = 1;
                    }

                    info.BaseDamagePool = 0;
                }
                else
                {
                    info.BaseDamagePool -= objHp;
                    if (oRadius < minTestRadius)
                    {
                        oRadius = minTestRadius;
                    }
                }

                destObj.PerformCutOutSphereFast(hitEnt.HitPos.Value, (float)oRadius, true);
                //Log.Line($"TestHealth: {objHp} - tRadius:{tRadius} - oRadius:{oRadius} - travel:{minTestRadius} - base:{info.BaseDamagePool} - det:{detonateOnEnd}");

                if (detonateOnEnd && info.BaseDamagePool <= 0)
                {
                    var det     = info.AmmoDef.AreaEffect.Detonation;
                    var dRadius = det.DetonationRadius;
                    var dDamage = det.DetonationDamage;

                    //var dObjHp = (int)MathHelper.Clamp(MathFuncs.VolumeCube(MathFuncs.LargestCubeInSphere(dRadius)), 5000, double.MaxValue);
                    //if (dRadius > 5) dObjHp *= 5;
                    //dObjHp *= 5;
                    //var reduceBy = dObjHp / dDamage;
                    //dRadius /= reduceBy;

                    if (dRadius < 1.5)
                    {
                        dRadius = 1.5f;
                    }

                    //Log.Line($"radius: {det.DetonationRadius} - dRadius:{dRadius} - reduceBy:{reduceBy} - dObjHp:{dObjHp}");
                    if (canDamage)
                    {
                        //destObj.PerformCutOutSphereFast(hitEnt.HitPos.Value, dRadius, true);
                        SUtils.CreateMissileExplosion(this, dDamage, dRadius, hitEnt.HitPos.Value, hitEnt.Intersection.Direction, info.Target.FiringCube, destObj, info.AmmoDef, true);
                    }
                }
            }
        }