Пример #1
0
        private Vector3D ComputeHandlerImpact()
        {
            WebDamage            = false;
            HandlerImpact.Active = false;
            if (HandlerImpact.HitBlock == null)
            {
                return(DetectionCenter);
            }

            Vector3D originHit;

            HandlerImpact.HitBlock.ComputeWorldCenter(out originHit);

            var line = new LineD(HandlerImpact.Attacker.PositionComp.WorldAABB.Center, originHit);

            var testDir       = Vector3D.Normalize(line.From - line.To);
            var ray           = new RayD(line.From, -testDir);
            var matrix        = DetectionMatrix;
            var invMatrix     = MatrixD.Invert(matrix);
            var intersectDist = CustomCollision.IntersectEllipsoid(ref invMatrix, matrix, ref ray);
            var ellipsoid     = intersectDist ?? line.Length;
            var shieldHitPos  = line.From + (testDir * -ellipsoid);

            return(shieldHitPos);
        }
Пример #2
0
        private static Vector3D?TAPI_LineIntersectShield(IMyTerminalBlock block, LineD line)
        {
            var logic = block?.GameLogic?.GetAs <DefenseShields>()?.ShieldComp?.DefenseShields;

            if (logic == null)
            {
                return(null);
            }
            var ray = new RayD(line.From, line.Direction);

            float?intersectDist;

            lock (logic.MatrixLock)
                intersectDist = CustomCollision.IntersectEllipsoid(logic.DetectMatrixOutsideInv, logic.DetectMatrixOutside, ray);

            if (!intersectDist.HasValue)
            {
                return(null);
            }
            var ellipsoid = intersectDist ?? 0;

            if (ellipsoid > line.Length)
            {
                return(null);
            }
            return(ray.Position + (ray.Direction * ellipsoid));
        }
Пример #3
0
        // ModApi only methods below
        private static Vector3D?TAPI_RayAttackShield(IMyTerminalBlock block, RayD ray, long attackerId, float damage, bool energy, bool drawParticle)
        {
            var logic = block?.GameLogic?.GetAs <DefenseShields>()?.ShieldComp?.DefenseShields;

            if (logic == null)
            {
                return(null);
            }

            float?intersectDist;

            lock (logic.MatrixLock)
                intersectDist = CustomCollision.IntersectEllipsoid(logic.DetectMatrixOutsideInv, logic.DetectMatrixOutside, ray);

            if (!intersectDist.HasValue)
            {
                return(null);
            }
            var ellipsoid = intersectDist ?? 0;
            var hitPos    = ray.Position + (ray.Direction * ellipsoid);

            if (energy)
            {
                damage *= logic.DsState.State.ModulateKinetic;
            }
            else
            {
                damage *= logic.DsState.State.ModulateEnergy;
            }

            if (Session.Instance.MpActive)
            {
                var damageType = energy ? Session.Instance.MPEnergy : Session.Instance.MPKinetic;
                logic.AddShieldHit(attackerId, damage, damageType, null, true, hitPos);
            }
            else
            {
                if (!drawParticle)
                {
                    logic.EnergyHit = DefenseShields.HitType.Other;
                }
                else if (energy)
                {
                    logic.EnergyHit = DefenseShields.HitType.Energy;
                }
                else
                {
                    logic.EnergyHit = DefenseShields.HitType.Kinetic;
                }

                logic.ImpactSize          = damage;
                logic.WorldImpactPosition = hitPos;
            }
            logic.WebDamage = true;
            logic.Absorb   += damage;

            return(hitPos);
        }
Пример #4
0
        private static MyTuple <float?, IMyTerminalBlock> TAPI_ClosestShieldInLine(LineD line, bool onlyIfOnline)
        {
            var segment = SegmentPool.Get();

            MyGamePruningStructure.GetTopmostEntitiesOverlappingRay(ref line, segment, MyEntityQueryType.Dynamic);
            var ray = new RayD(line.From, line.Direction);

            var closest = float.MaxValue;
            IMyTerminalBlock closestShield = null;

            for (int i = 0; i < segment.Count; i++)
            {
                var ent = segment[i].Element;
                if (ent == null || ent.Physics != null && !ent.Physics.IsPhantom)
                {
                    continue;
                }
                ShieldGridComponent c;
                if (Session.Instance.IdToBus.TryGetValue(ent.EntityId, out c) && c.DefenseShields != null)
                {
                    if (onlyIfOnline && (!c.DefenseShields.DsState.State.Online || c.DefenseShields.DsState.State.Lowered))
                    {
                        continue;
                    }
                    var s             = c.DefenseShields;
                    var intersectDist = CustomCollision.IntersectEllipsoid(s.DetectMatrixOutsideInv, s.DetectMatrixOutside, ray);
                    if (!intersectDist.HasValue)
                    {
                        continue;
                    }
                    var ellipsoid = intersectDist ?? 0;
                    if (ellipsoid > line.Length || ellipsoid > closest || CustomCollision.PointInShield(ray.Position, s.DetectMatrixOutsideInv))
                    {
                        continue;
                    }
                    closest       = ellipsoid;
                    closestShield = s.Shield;
                }
            }
            segment.Clear();
            SegmentPool.Return(segment);
            var response = new MyTuple <float?, IMyTerminalBlock>();

            if (closestShield == null)
            {
                response.Item1 = null;
                response.Item2 = null;
                return(response);
            }
            response.Item1 = closest;
            response.Item2 = closestShield;
            return(response);
        }
Пример #5
0
        public void CheckDamage(object target, ref MyDamageInformation info)
        {
            try
            {
                var damageType = info.Type;
                if (damageType == MpIgnoreDamage || damageType == MyDamageType.Drill || damageType == MyDamageType.Grind || ManagedAttackers.ContainsKey(info.AttackerId))
                {
                    return;
                }
                var block     = target as IMySlimBlock;
                var character = target as IMyCharacter;
                if (block != null)
                {
                    var myGrid = block.CubeGrid as MyCubeGrid;
                    if (myGrid == null)
                    {
                        return;
                    }

                    MyProtectors protectors;
                    GlobalProtect.TryGetValue(myGrid, out protectors);
                    if (protectors == null)
                    {
                        return;
                    }

                    MyEntity hostileEnt;
                    var      attackerId = info.AttackerId;
                    if (attackerId == _previousEntId)
                    {
                        hostileEnt = _previousEnt;
                    }
                    else
                    {
                        UpdatedHostileEnt(attackerId, out hostileEnt);
                    }

                    if (!IsServer && attackerId != 0 && hostileEnt == null)
                    {
                        ForceEntity(out hostileEnt);
                    }

                    MyEntity trueAttacker = null;
                    var      isVoxelBase  = false;

                    try
                    {
                        if (hostileEnt != null)
                        {
                            MyCubeGrid grid;
                            if (damageType != MyDamageType.Environment)
                            {
                                grid = hostileEnt as MyCubeGrid;
                            }
                            else
                            {
                                grid = hostileEnt.Parent as MyCubeGrid;
                            }
                            if (grid == null)
                            {
                                var hostileCube = hostileEnt.Parent as MyCubeBlock;
                                trueAttacker = (hostileCube ?? (hostileEnt as IMyGunBaseUser)?.Owner) ?? hostileEnt;
                                if (trueAttacker is MyVoxelBase)
                                {
                                    isVoxelBase = true;
                                }
                            }
                            else
                            {
                                trueAttacker = grid;
                            }
                            protectors.LastAttackerWasInside = true;
                            Vector3D originHit;
                            block.ComputeWorldCenter(out originHit);

                            var line       = new LineD(trueAttacker.PositionComp.WorldAABB.Center, originHit);
                            var lineLength = (float)line.Length;
                            var testDir    = Vector3D.Normalize(line.From - line.To);
                            var ray        = new RayD(line.From, -testDir);
                            var hitDist    = double.MaxValue;
                            foreach (var shield in protectors.Shields.Keys)
                            {
                                shield.Asleep        = false;
                                shield.LastWokenTick = Tick;

                                var shieldActive = shield.DsState.State.Online && !shield.DsState.State.Lowered;
                                if (!shieldActive)
                                {
                                    continue;
                                }
                                var intersectDist = CustomCollision.IntersectEllipsoid(ref shield.DetectMatrixOutsideInv, shield.DetectionMatrix, ref ray);
                                var ellipsoid     = intersectDist ?? 0;

                                var notContained = isVoxelBase || intersectDist <= 0 && shield.GridIsMobile && !CustomCollision.PointInShield(trueAttacker.PositionComp.WorldAABB.Center, MatrixD.Invert(shield.ShieldShapeMatrix * shield.MyGrid.WorldMatrix));
                                if (notContained)
                                {
                                    ellipsoid = lineLength;
                                }

                                var intersect = ellipsoid > 0 && lineLength + 1 >= ellipsoid;

                                if (intersect && ellipsoid <= hitDist)
                                {
                                    protectors.LastAttackerWasInside = false;
                                    hitDist = ellipsoid;
                                    protectors.BlockingShield = shield;
                                    protectors.BlockingTick   = Tick;
                                }
                            }
                        }
                        if (Tick - protectors.BlockingTick > 10 && protectors.LastAttackerWasInside)
                        {
                            protectors.BlockingShield = null;
                        }
                    }
                    catch (Exception ex) { Log.Line($"Exception in DamageFindShield: {ex}"); }

                    try
                    {
                        var activeProtector = protectors.BlockingShield != null && protectors.BlockingShield.DsState.State.Online && !protectors.BlockingShield.DsState.State.Lowered;
                        if (activeProtector)
                        {
                            var shield = protectors.BlockingShield;
                            if (!IsServer && !shield.WarmedUp)
                            {
                                info.Amount = 0;
                                return;
                            }
                            var isExplosionDmg   = damageType == MyDamageType.Explosion;
                            var isDeformationDmg = damageType == MyDamageType.Deformation;

                            if (isVoxelBase)
                            {
                                shield.DeformEnabled = true;
                                return;
                            }
                            if (damageType == Bypass)
                            {
                                shield.DeformEnabled = true;
                                return;
                            }

                            if (!isDeformationDmg && !isExplosionDmg)
                            {
                                shield.DeformEnabled        = false;
                                protectors.IgnoreAttackerId = -1;
                            }
                            else if (shield.DeformEnabled && trueAttacker == null)
                            {
                                return;
                            }
                            else if (!shield.DeformEnabled && trueAttacker == null)
                            {
                                info.Amount = 0;
                                return;
                            }

                            var bullet = damageType == MyDamageType.Bullet;
                            if (bullet || isDeformationDmg)
                            {
                                info.Amount = info.Amount * shield.DsState.State.ModulateEnergy;
                            }
                            else
                            {
                                info.Amount = info.Amount * shield.DsState.State.ModulateKinetic;
                            }

                            var noHits           = !DedicatedServer && shield.Absorb < 1;
                            var hitSlotAvailable = noHits & (bullet && shield.KineticCoolDown == -1) || (!bullet && shield.EnergyCoolDown == -1);
                            if (hitSlotAvailable)
                            {
                                lock (shield.HandlerImpact)
                                {
                                    if (trueAttacker != null && block != null)
                                    {
                                        shield.HandlerImpact.Attacker = trueAttacker;
                                        shield.HandlerImpact.HitBlock = block;
                                        shield.ImpactSize             = info.Amount;
                                        shield.HandlerImpact.Active   = true;
                                        if (!bullet)
                                        {
                                            shield.EnergyHit = DefenseShields.HitType.Energy;
                                        }
                                    }
                                }
                            }
                            if (isDeformationDmg && trueAttacker != null)
                            {
                                protectors.IgnoreAttackerId = attackerId;
                            }

                            if (!bullet)
                            {
                                shield.EnergyDamage += info.Amount;
                            }
                            else
                            {
                                shield.KineticDamage += info.Amount;
                            }

                            shield.Absorb += info.Amount;
                            info.Amount    = 0f;
                            return;
                        }
                    }
                    catch (Exception ex) { Log.Line($"Exception in DamageHandlerActive: {ex}"); }

                    var iShield = protectors.IntegrityShield;
                    if (iShield != null && iShield.DsState.State.Online && !iShield.DsState.State.Lowered)
                    {
                        var attackingVoxel = trueAttacker as MyVoxelBase;
                        if (attackingVoxel != null || (trueAttacker is MyCubeGrid) && !(damageType == MPEnergy || damageType == MPKinetic || damageType == MPExplosion))
                        {
                            iShield.DeformEnabled = true;
                        }
                        else if (trueAttacker != null)
                        {
                            iShield.DeformEnabled = false;
                        }

                        if (damageType == MyDamageType.Deformation && iShield.DeformEnabled)
                        {
                            if (attackingVoxel != null)
                            {
                                if (iShield.Absorb < 1 && iShield.WorldImpactPosition == Vector3D.NegativeInfinity && iShield.KineticCoolDown == -1)
                                {
                                    attackingVoxel.RootVoxel.RequestVoxelOperationElipsoid(Vector3.One, iShield.DetectMatrixOutside, 0, MyVoxelBase.OperationType.Cut);
                                }
                            }
                            var dmgAmount = info.Amount;
                            if (IsServer)
                            {
                                iShield.AddShieldHit(attackerId, dmgAmount, damageType, block, false);
                                iShield.Absorb        += dmgAmount;
                                iShield.KineticDamage += dmgAmount;
                            }
                            info.Amount = 0;
                            return;
                        }
                    }

                    if (info.AttackerId == protectors.IgnoreAttackerId && damageType == MyDamageType.Deformation)
                    {
                        if (Enforced.Debug >= 2)
                        {
                            Log.Line($"old Del/Mp Attacker, ignoring: {damageType} - {info.Amount} - attackerId:{attackerId}");
                        }
                        info.Amount = 0;
                        return;
                    }
                    protectors.IgnoreAttackerId = -1;
                    if (Enforced.Debug >= 2)
                    {
                        Log.Line($"[Uncaught Damage] Type:{damageType} - Amount:{info.Amount} - nullTrue:{trueAttacker == null} - nullHostile:{hostileEnt == null} - nullShield:{protectors.BlockingShield == null} - iShell:{protectors.IntegrityShield != null} - protectorShields:{protectors.Shields.Count} - attackerId:{info.AttackerId}");
                    }
                }
                if (character != null && CharacterProtection(character, info.AttackerId, info.Type))
                {
                    info.Amount = 0;
                }
            }
            catch (Exception ex) { Log.Line($"Exception in SessionDamageHandler {_previousEnt == null}: {ex}"); }
        }
Пример #6
0
        public void AbsorbEmp()
        {
            if (Vector3D.DistanceSquared(DetectionCenter, Session.Instance.EmpWork.EpiCenter) <= Session.Instance.EmpWork.RangeCapSqr)
            {
                var        empResistenceRatio    = 1f;
                const long AttackerId            = 0L;
                var        energyResistenceRatio = DsState.State.ModulateKinetic;
                var        epiCenter             = Session.Instance.EmpWork.EpiCenter;
                var        rangeCap    = Session.Instance.EmpWork.RangeCap;
                var        empDirYield = Session.Instance.EmpWork.DirYield;

                if (DsState.State.EmpProtection)
                {
                    if (energyResistenceRatio < 0.4)
                    {
                        energyResistenceRatio = 0.4f;
                    }
                    empResistenceRatio = 0.1f;
                }
                //if (Session.Enforced.Debug >= 2) Log.Line($"[EmpBlastShield - Start] ShieldOwner:{MyGrid.DebugName} - Yield:{warHeadYield} - StackCount:{stackCount} - ProtectionRatio:{energyResistenceRatio * empResistenceRatio} - epiCenter:{epiCenter}");
                var line      = new LineD(epiCenter, SOriBBoxD.Center);
                var testDir   = Vector3D.Normalize(line.From - line.To);
                var ray       = new RayD(line.From, -testDir);
                var ellipsoid = CustomCollision.IntersectEllipsoid(DetectMatrixOutsideInv, DetectionMatrix, ray);
                if (!ellipsoid.HasValue)
                {
                    //if (Session.Enforced.Debug >= 2) Log.Line($"[EmpBlastShield - Ellipsoid null hit] ShieldOwner:{MyGrid.DebugName} - Yield:{warHeadYield} - StackCount:{stackCount} - ProtectionRatio:{energyResistenceRatio * empResistenceRatio} - epiCenter:{epiCenter}");
                    return;
                }
                var      impactPos = line.From + (testDir * -ellipsoid.Value);
                IHitInfo hitInfo;
                MyAPIGateway.Physics.CastRay(epiCenter, impactPos, out hitInfo, CollisionLayers.DefaultCollisionLayer);
                if (hitInfo != null)
                {
                    //if (Session.Enforced.Debug >= 2) Log.Line($"[EmpBlastShield - occluded] ShieldOwner:{MyGrid.DebugName} - by {((MyEntity)hitInfo.HitEntity).DebugName}");
                    return;
                }
                var gridLocalMatrix    = MyGrid.PositionComp.LocalMatrix;
                var worldDirection     = impactPos - gridLocalMatrix.Translation;
                var localPosition      = Vector3D.TransformNormal(worldDirection, MatrixD.Transpose(gridLocalMatrix));
                var hitFaceSurfaceArea = UtilsStatic.GetIntersectingSurfaceArea(ShieldShapeMatrix, localPosition);

                var invSqrDist   = UtilsStatic.InverseSqrDist(epiCenter, impactPos, rangeCap);
                var damageScaler = invSqrDist * hitFaceSurfaceArea;
                if (invSqrDist <= 0)
                {
                    //if (Session.Enforced.Debug >= 2) Log.Line($"[EmpBlastShield - Range] ShieldOwner:{MyGrid.DebugName} - insqrDist was 0");
                    return;
                }

                var targetDamage = (float)(((empDirYield * damageScaler) * energyResistenceRatio) * empResistenceRatio);

                if (targetDamage >= DsState.State.Charge * ConvToHp)
                {
                    _empOverLoad = true;
                }
                //if (Session.Enforced.Debug >= 2) Log.Line($"-----------------------] epiDist:{Vector3D.Distance(epiCenter, impactPos)} - iSqrDist:{invSqrDist} - RangeCap:{rangeCap} - SurfaceA:{hitFaceSurfaceArea}({_ellipsoidSurfaceArea * 0.5}) - dirYield:{empDirYield} - damageScaler:{damageScaler} - Damage:{targetDamage}(toOver:{(targetDamage / (DsState.State.Charge * ConvToHp))})");

                if (_isServer && _mpActive)
                {
                    AddEmpBlastHit(AttackerId, targetDamage, Session.Instance.MPEMP, impactPos);
                }

                EnergyHit           = HitType.Energy;
                WorldImpactPosition = epiCenter;
                Absorb += targetDamage;
            }
        }
Пример #7
0
        public void CheckDamage(object target, ref MyDamageInformation info)
        {
            try
            {
                var block = target as IMySlimBlock;
                if (block != null)
                {
                    var damageType = info.Type;
                    if (damageType == MpIgnoreDamage || damageType == MyDamageType.Drill || damageType == MyDamageType.Grind)
                    {
                        return;
                    }

                    var myEntity = block.CubeGrid as MyEntity;

                    if (myEntity == null)
                    {
                        return;
                    }

                    MyProtectors protectors;
                    GlobalProtect.TryGetValue(myEntity, out protectors);
                    if (protectors == null)
                    {
                        return;
                    }

                    MyEntity hostileEnt;
                    var      attackerId = info.AttackerId;
                    if (attackerId == _previousEntId)
                    {
                        hostileEnt = _previousEnt;
                    }
                    else
                    {
                        UpdatedHostileEnt(attackerId, out hostileEnt);
                    }

                    var      shieldHitPos = Vector3D.NegativeInfinity;
                    MyEntity trueAttacker = null;
                    if (hostileEnt != null)
                    {
                        var blockingShield    = false;
                        var notBlockingShield = false;
                        protectors.ProtectDamageReset();

                        MyCubeGrid myGrid;
                        if (damageType != MyDamageType.Environment)
                        {
                            myGrid = hostileEnt as MyCubeGrid;
                        }
                        else
                        {
                            myGrid = hostileEnt.Parent as MyCubeGrid;
                        }
                        if (myGrid == null)
                        {
                            var hostileCube = hostileEnt.Parent as MyCubeBlock;
                            trueAttacker = (hostileCube ?? (hostileEnt as IMyGunBaseUser)?.Owner) ?? hostileEnt;
                        }
                        else
                        {
                            trueAttacker = myGrid;
                        }

                        protectors.OriginBlock = block;
                        protectors.OriginBlock.ComputeWorldCenter(out protectors.OriginHit);
                        var line    = new LineD(trueAttacker.PositionComp.WorldAABB.Center, protectors.OriginHit);
                        var testDir = Vector3D.Normalize(line.From - line.To);
                        var ray     = new RayD(line.From, -testDir);
                        var hitDist = double.MaxValue;
                        foreach (var shield in protectors.Shields)
                        {
                            var shieldActive = shield.DsState.State.Online && !shield.DsState.State.Lowered;
                            if (!shieldActive)
                            {
                                continue;
                            }
                            var intersectDist = CustomCollision.IntersectEllipsoid(shield.DetectMatrixOutsideInv, shield.DetectionMatrix, ray);
                            var ellipsoid     = intersectDist ?? 0;
                            var intersect     = ellipsoid > 0 && line.Length > ellipsoid;
                            var noIntersect   = ellipsoid <= 0 || line.Length < ellipsoid;
                            if (intersect && ellipsoid <= hitDist)
                            {
                                hitDist      = ellipsoid;
                                shieldHitPos = line.From + (testDir * -ellipsoid);
                                protectors.BlockingShield = shield;
                                notBlockingShield         = false;
                                blockingShield            = true;
                            }
                            else if (noIntersect && protectors.BlockingShield == null)
                            {
                                protectors.NotBlockingShield         = shield;
                                protectors.NotBlockingAttackerId     = attackerId;
                                protectors.NotBlockingMainDamageType = damageType;
                                notBlockingShield = true;
                                blockingShield    = false;
                            }
                        }
                        if (!blockingShield)
                        {
                            protectors.BlockingShield = null;
                        }
                        if (!notBlockingShield)
                        {
                            protectors.NotBlockingShield = null;
                        }
                    }

                    var activeProtector = protectors.BlockingShield != null && protectors.BlockingShield.DsState.State.Online && !protectors.BlockingShield.DsState.State.Lowered && protectors.Shields.Contains(protectors.BlockingShield);
                    if (activeProtector)
                    {
                        var shield = protectors.BlockingShield;

                        if (!IsServer && !shield.WarmedUp)
                        {
                            info.Amount = 0;
                            return;
                        }
                        var isExplosionDmg   = damageType == MyDamageType.Explosion;
                        var isDeformationDmg = damageType == MyDamageType.Deformation;
                        if (trueAttacker is MyVoxelBase || (trueAttacker is MyCubeGrid && isDeformationDmg && shield.ModulateGrids))
                        {
                            shield.DeformEnabled = true;
                            return;
                        }
                        if (damageType == Bypass)
                        {
                            shield.DeformEnabled = true;
                            return;
                        }
                        if (damageType == DSdamage || damageType == DSheal || damageType == DSbypass)
                        {
                            info.Amount = 0f;
                            return;
                        }

                        if (!isDeformationDmg && !isExplosionDmg)
                        {
                            if (!IsServer)
                            {
                                protectors.NotBlockingShield = null;
                            }
                            shield.ExplosionEnabled     = false;
                            shield.DeformEnabled        = false;
                            protectors.IgnoreAttackerId = -1;
                        }
                        else if (!shield.DeformEnabled && trueAttacker == null)
                        {
                            info.Amount = 0;
                            return;
                        }

                        var bullet = damageType == MyDamageType.Bullet;
                        if (bullet || isDeformationDmg)
                        {
                            info.Amount = info.Amount * shield.DsState.State.ModulateEnergy;
                        }
                        else
                        {
                            info.Amount = info.Amount * shield.DsState.State.ModulateKinetic;
                        }

                        if (!DedicatedServer && shield.Absorb < 1 && shield.WorldImpactPosition == Vector3D.NegativeInfinity && shield.BulletCoolDown == -1)
                        {
                            shield.WorldImpactPosition = shieldHitPos;
                            shield.ImpactSize          = info.Amount;
                            if (!bullet)
                            {
                                shield.EnergyHit = true;
                            }
                        }
                        if (isDeformationDmg && trueAttacker != null)
                        {
                            protectors.IgnoreAttackerId = attackerId;
                        }
                        shield.Absorb += info.Amount;
                        info.Amount    = 0f;
                        return;
                    }

                    var iShield = protectors.IntegrityShield;
                    if (iShield != null && iShield.DsState.State.Online && !iShield.DsState.State.Lowered)
                    {
                        var attackingVoxel = trueAttacker as MyVoxelBase;
                        if (attackingVoxel != null || trueAttacker is MyCubeGrid)
                        {
                            iShield.DeformEnabled = true;
                        }
                        else if (trueAttacker != null)
                        {
                            iShield.DeformEnabled = false;
                        }

                        if (damageType == MyDamageType.Deformation && iShield.DeformEnabled)
                        {
                            if (attackingVoxel != null)
                            {
                                if (iShield.Absorb < 1 && iShield.WorldImpactPosition == Vector3D.NegativeInfinity && iShield.BulletCoolDown == -1)
                                {
                                    attackingVoxel.RootVoxel.RequestVoxelOperationElipsoid(Vector3.One, iShield.DetectMatrixOutside, 0, MyVoxelBase.OperationType.Cut);
                                }
                            }
                            var dmgAmount = info.Amount * 10;
                            if (IsServer)
                            {
                                iShield.AddShieldHit(attackerId, dmgAmount, damageType, block, false);
                                iShield.Absorb += dmgAmount;
                            }
                            info.Amount = 0;
                            return;
                        }
                    }

                    if (info.AttackerId == protectors.IgnoreAttackerId && damageType == MyDamageType.Deformation)
                    {
                        if (Enforced.Debug >= 2)
                        {
                            Log.Line($"old Del/Mp Attacker, ignoring: {damageType} - {info.Amount} - attackerId:{attackerId}");
                        }
                        info.Amount = 0;
                        return;
                    }
                    protectors.IgnoreAttackerId = -1;

                    if (Enforced.Debug >= 2)
                    {
                        Log.Line($"[Uncaught Damage] Type:{damageType} - Amount:{info.Amount} - nullHostileEnt:{trueAttacker == null} - nullShield:{protectors.BlockingShield == null} - iShell:{protectors.IntegrityShield != null} - protectorShields:{protectors.Shields.Count} - attackerId:{info.AttackerId}");
                    }
                }
                else if (target is IMyCharacter)
                {
                    CharacterProtection(target, info);
                }
            }
            catch (Exception ex) { Log.Line($"Exception in SessionDamageHandler: {ex}"); }
        }
Пример #8
0
        private void SyncThreadedEnts(bool clear = false, bool client = false)
        {
            try
            {
                if (clear)
                {
                    Eject.Clear();
                    DestroyedBlocks.Clear();
                    MissileDmg.Clear();
                    MeteorDmg.Clear();
                    VoxelDmg.Clear();
                    CharacterDmg.Clear();
                    FewDmgBlocks.Clear();
                    CollidingBlocks.Clear();
                    ForceData.Clear();
                    ImpulseData.Clear();
                    return;
                }

                try
                {
                    if (!Eject.IsEmpty)
                    {
                        MyCubeGrid myGrid;
                        while (Eject.TryDequeue(out myGrid))
                        {
                            if (myGrid == null || myGrid.MarkedForClose)
                            {
                                continue;
                            }
                            myGrid.Physics.LinearVelocity *= -0.25f;
                        }
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in Eject: {ex}"); }

                try
                {
                    if (!ForceData.IsEmpty)
                    {
                        MyAddForceData data;
                        while (ForceData.TryDequeue(out data))
                        {
                            var myGrid = data.MyGrid;
                            if (myGrid == null || myGrid.MarkedForClose)
                            {
                                continue;
                            }
                            myGrid.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_FORCE, data.Force, null, Vector3D.Zero, data.MaxSpeed, data.Immediate);
                        }
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in forceData: {ex}"); }

                try
                {
                    if (!ImpulseData.IsEmpty)
                    {
                        MyImpulseData data;
                        while (ImpulseData.TryDequeue(out data))
                        {
                            var myGrid = data.MyGrid;
                            if (myGrid == null || myGrid.MarkedForClose)
                            {
                                continue;
                            }
                            myGrid.Physics.ApplyImpulse(data.Direction, data.Position);
                        }
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in impulseData: {ex}"); }

                if (client)
                {
                    return;
                }

                try
                {
                    if (!DestroyedBlocks.IsEmpty)
                    {
                        IMySlimBlock block;
                        var          nullCount = 0;
                        while (DestroyedBlocks.TryDequeue(out block))
                        {
                            var myGrid = block.CubeGrid as MyCubeGrid;
                            if (myGrid == null)
                            {
                                continue;
                            }
                            EntIntersectInfo entInfo;
                            WebEnts.TryGetValue(myGrid, out entInfo);
                            if (entInfo == null)
                            {
                                nullCount++;
                                myGrid.EnqueueDestroyedBlock(block.Position);
                                continue;
                            }

                            EntIntersectInfo entRemoved;
                            if (nullCount > 0)
                            {
                                WebEnts.TryRemove(myGrid, out entRemoved);
                            }
                            entInfo.CacheBlockList.Remove(block);
                            myGrid.EnqueueDestroyedBlock(block.Position);
                        }
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in destroyedBlocks: {ex}"); }

                try
                {
                    if (!MissileDmg.IsEmpty)
                    {
                        MyEntity ent;
                        while (MissileDmg.TryDequeue(out ent))
                        {
                            if (ent == null || !ent.InScene || ent.MarkedForClose)
                            {
                                continue;
                            }
                            var computedDamage = ComputeAmmoDamage(ent);

                            var damage = computedDamage * DsState.State.ModulateKinetic;
                            if (computedDamage < 0)
                            {
                                damage = computedDamage;
                            }

                            var rayDir    = Vector3D.Normalize(ent.Physics.LinearVelocity);
                            var ray       = new RayD(ent.PositionComp.WorldVolume.Center, rayDir);
                            var intersect = CustomCollision.IntersectEllipsoid(DetectMatrixOutsideInv, DetectionMatrix, ray);
                            var hitDist   = intersect ?? 0;
                            var hitPos    = ray.Position + (ray.Direction * -hitDist);

                            if (_mpActive)
                            {
                                AddShieldHit(ent.EntityId, damage, Session.Instance.MPExplosion, null, false, hitPos);
                                ent.Close();
                                ent.InScene = false;
                            }
                            else
                            {
                                EnergyHit           = true;
                                WorldImpactPosition = hitPos;
                                Absorb    += damage;
                                ImpactSize = damage;
                                UtilsStatic.CreateFakeSmallExplosion(hitPos);
                                ent.Close();
                                ent.InScene = false;
                            }
                        }
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in missileDmg: {ex}"); }

                try
                {
                    if (!MeteorDmg.IsEmpty)
                    {
                        IMyMeteor meteor;
                        while (MeteorDmg.TryDequeue(out meteor))
                        {
                            if (meteor == null || meteor.MarkedForClose || meteor.Closed)
                            {
                                continue;
                            }
                            var damage = 5000 * DsState.State.ModulateEnergy;
                            if (_mpActive)
                            {
                                AddShieldHit(meteor.EntityId, damage, Session.Instance.MPKinetic, null, false, meteor.PositionComp.WorldVolume.Center);
                                meteor.DoDamage(10000f, Session.Instance.MpIgnoreDamage, true, null, MyCube.EntityId);
                            }
                            else
                            {
                                WorldImpactPosition = meteor.PositionComp.WorldVolume.Center;
                                Absorb    += damage;
                                ImpactSize = damage;
                                meteor.DoDamage(10000f, Session.Instance.MpIgnoreDamage, true, null, MyCube.EntityId);
                            }
                        }
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in missileDmg: {ex}"); }

                try
                {
                    if (!VoxelDmg.IsEmpty)
                    {
                        MyVoxelBase voxel;
                        while (VoxelDmg.TryDequeue(out voxel))
                        {
                            if (voxel == null || voxel.RootVoxel.MarkedForClose || voxel.RootVoxel.Closed)
                            {
                                continue;
                            }
                            voxel.RootVoxel.RequestVoxelOperationElipsoid(Vector3.One * 1.0f, DetectMatrixOutside, 0, MyVoxelBase.OperationType.Cut);
                        }
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in missileDmg: {ex}"); }

                try
                {
                    if (!CharacterDmg.IsEmpty)
                    {
                        IMyCharacter character;
                        while (CharacterDmg.TryDequeue(out character))
                        {
                            var npcname = character.ToString();
                            if (npcname.Equals("Space_Wolf"))
                            {
                                character.Delete();
                                continue;
                            }
                            var hId            = MyCharacterOxygenComponent.HydrogenId;
                            var playerGasLevel = character.GetSuitGasFillLevel(hId);
                            character.Components.Get <MyCharacterOxygenComponent>().UpdateStoredGasLevel(ref hId, (playerGasLevel * -0.0001f) + .002f);
                            MyVisualScriptLogicProvider.CreateExplosion(character.GetPosition(), 0, 0);
                            character.DoDamage(50f, Session.Instance.MpIgnoreDamage, true, null, MyCube.EntityId);
                            var vel = character.Physics.LinearVelocity;
                            if (vel == new Vector3D(0, 0, 0))
                            {
                                vel = MyUtils.GetRandomVector3Normalized();
                            }
                            var speedDir        = Vector3D.Normalize(vel);
                            var rnd             = new Random();
                            var randomSpeed     = rnd.Next(10, 20);
                            var additionalSpeed = vel + (speedDir * randomSpeed);
                            character.Physics.LinearVelocity = additionalSpeed;
                        }
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in missileDmg: {ex}"); }

                try
                {
                    if (!CollidingBlocks.IsEmpty)
                    {
                        IMySlimBlock block;
                        var          damageMulti = 350;
                        if (ShieldMode == ShieldType.Station && DsState.State.Enhancer)
                        {
                            damageMulti = 10000;
                        }
                        while (CollidingBlocks.TryDequeue(out block))
                        {
                            if (block == null)
                            {
                                continue;
                            }
                            var myGrid = block.CubeGrid as MyCubeGrid;
                            if (block.IsDestroyed)
                            {
                                myGrid.EnqueueDestroyedBlock(block.Position);
                                continue;
                            }
                            block.DoDamage(damageMulti, Session.Instance.MpIgnoreDamage, true, null, MyCube.EntityId);
                            if (myGrid.BlocksCount == 0)
                            {
                                myGrid.SendGridCloseRequest();
                            }
                        }
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in dmgBlocks: {ex}"); }

                try
                {
                    if (!FewDmgBlocks.IsEmpty)
                    {
                        IMySlimBlock block;
                        while (FewDmgBlocks.TryDequeue(out block))
                        {
                            if (block == null)
                            {
                                continue;
                            }
                            var myGrid = block.CubeGrid as MyCubeGrid;

                            if (block.IsDestroyed)
                            {
                                myGrid.EnqueueDestroyedBlock(block.Position);
                                myGrid.Close();
                                continue;
                            }
                            block.DoDamage(block.MaxIntegrity * 0.9f, Session.Instance.MpIgnoreDamage, true, null, MyCube.EntityId);
                            if (myGrid.BlocksCount == 0)
                            {
                                myGrid.SendGridCloseRequest();
                            }
                        }
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in fewBlocks: {ex}"); }

                try
                {
                    if (Session.Instance.EmpWork.EventRunning && Vector3D.DistanceSquared(DetectionCenter, Session.Instance.EmpWork.EpiCenter) <= Session.Instance.EmpWork.RangeCapSqr)
                    {
                        var        empResistenceRatio    = 1f;
                        const long AttackerId            = 0L;
                        var        energyResistenceRatio = DsState.State.ModulateKinetic;
                        var        epiCenter             = Session.Instance.EmpWork.EpiCenter;
                        var        rangeCap    = Session.Instance.EmpWork.RangeCap;
                        var        empDirYield = Session.Instance.EmpWork.DirYield;

                        if (DsState.State.EmpProtection)
                        {
                            if (energyResistenceRatio < 0.4)
                            {
                                energyResistenceRatio = 0.4f;
                            }
                            empResistenceRatio = 0.1f;
                        }
                        //if (Session.Enforced.Debug >= 2) Log.Line($"[EmpBlastShield - Start] ShieldOwner:{MyGrid.DebugName} - Yield:{warHeadYield} - StackCount:{stackCount} - ProtectionRatio:{energyResistenceRatio * empResistenceRatio} - epiCenter:{epiCenter}");
                        var line      = new LineD(epiCenter, SOriBBoxD.Center);
                        var testDir   = Vector3D.Normalize(line.From - line.To);
                        var ray       = new RayD(line.From, -testDir);
                        var ellipsoid = CustomCollision.IntersectEllipsoid(DetectMatrixOutsideInv, DetectionMatrix, ray);
                        if (!ellipsoid.HasValue)
                        {
                            //if (Session.Enforced.Debug >= 2) Log.Line($"[EmpBlastShield - Ellipsoid null hit] ShieldOwner:{MyGrid.DebugName} - Yield:{warHeadYield} - StackCount:{stackCount} - ProtectionRatio:{energyResistenceRatio * empResistenceRatio} - epiCenter:{epiCenter}");
                            return;
                        }
                        var      impactPos = line.From + (testDir * -ellipsoid.Value);
                        IHitInfo hitInfo;
                        MyAPIGateway.Physics.CastRay(epiCenter, impactPos, out hitInfo, CollisionLayers.DefaultCollisionLayer);
                        if (hitInfo != null)
                        {
                            //if (Session.Enforced.Debug >= 2) Log.Line($"[EmpBlastShield - occluded] ShieldOwner:{MyGrid.DebugName} - by {((MyEntity)hitInfo.HitEntity).DebugName}");
                            return;
                        }
                        var gridLocalMatrix    = MyGrid.PositionComp.LocalMatrix;
                        var worldDirection     = impactPos - gridLocalMatrix.Translation;
                        var localPosition      = Vector3D.TransformNormal(worldDirection, MatrixD.Transpose(gridLocalMatrix));
                        var hitFaceSurfaceArea = UtilsStatic.GetIntersectingSurfaceArea(ShieldShapeMatrix, localPosition);

                        var invSqrDist   = UtilsStatic.InverseSqrDist(epiCenter, impactPos, rangeCap);
                        var damageScaler = invSqrDist * hitFaceSurfaceArea;
                        if (invSqrDist <= 0)
                        {
                            //if (Session.Enforced.Debug >= 2) Log.Line($"[EmpBlastShield - Range] ShieldOwner:{MyGrid.DebugName} - insqrDist was 0");
                            return;
                        }

                        var targetDamage = (float)(((empDirYield * damageScaler) * energyResistenceRatio) * empResistenceRatio);

                        if (targetDamage >= DsState.State.Charge * ConvToHp)
                        {
                            _empOverLoad = true;
                        }
                        //if (Session.Enforced.Debug >= 2) Log.Line($"-----------------------] epiDist:{Vector3D.Distance(epiCenter, impactPos)} - iSqrDist:{invSqrDist} - RangeCap:{rangeCap} - SurfaceA:{hitFaceSurfaceArea}({_ellipsoidSurfaceArea * 0.5}) - dirYield:{empDirYield} - damageScaler:{damageScaler} - Damage:{targetDamage}(toOver:{(targetDamage / (DsState.State.Charge * ConvToHp))})");

                        if (_isServer && _mpActive)
                        {
                            AddEmpBlastHit(AttackerId, targetDamage, Session.Instance.MPEMP, impactPos);
                        }

                        EnergyHit           = true;
                        WorldImpactPosition = epiCenter;
                        Absorb += targetDamage;
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in EmpBlast: {ex}"); }
            }
            catch (Exception ex) { Log.Line($"Exception in DamageGrids: {ex}"); }
        }