Example #1
0
        private void RefreshBlockCache(MyEntity entity, EntIntersectInfo entInfo)
        {
            var grid = entity as MyCubeGrid;

            if (grid != null)
            {
                var checkSphere = WebSphere;
                checkSphere.Radius += 10;
                GetBlocksInsideSphereFast(grid, ref checkSphere, true, entInfo.CacheBlockList);
            }
        }
        private void BlockIntersect(MyCubeGrid breaching, MyOrientedBoundingBoxD bOriBBoxD, EntIntersectInfo entInfo)
        {
            var collisionAvg = Vector3D.Zero;
            var transformInv = DetectMatrixOutsideInv;
            var normalMat    = MatrixD.Transpose(transformInv);
            var damageBlocks = Session.Enforced.DisableBlockDamage == 0;

            var blockDmgNum = 5;

            if (ShieldMode == ShieldType.Station && DsState.State.Enhancer)
            {
                blockDmgNum = 50;
            }
            var intersection = bOriBBoxD.Intersects(ref SOriBBoxD);

            try
            {
                if (intersection)
                {
                    var      cacheBlockList = entInfo.CacheBlockList;
                    var      bPhysics       = ((IMyCubeGrid)breaching).Physics;
                    var      sPhysics       = Shield.CubeGrid.Physics;
                    var      sGrid          = (MyCubeGrid)Shield.CubeGrid;
                    var      bMass          = breaching.GetCurrentMass();
                    var      sMass          = sGrid.GetCurrentMass();
                    var      momentum       = (bMass * bPhysics.LinearVelocity) + (sMass * sPhysics.LinearVelocity);
                    var      resultVelocity = momentum / (bMass + sMass);
                    Vector3D bBlockCenter;
                    var      stale     = false;
                    var      rawDamage = 0f;
                    var      blockSize = breaching.GridSize;
                    var      gc        = breaching.WorldToGridInteger(DetectionCenter);
                    var      rc        = ShieldSize.AbsMax() / blockSize;
                    rc *= rc;
                    rc  = rc + 1;
                    rc  = Math.Ceiling(rc);
                    var hits        = 0;
                    var blockPoints = new Vector3D[9];
                    for (int i = 0; i < cacheBlockList.Count; i++)
                    {
                        var block    = cacheBlockList[i];
                        var blockPos = block.Position;
                        var num1     = gc.X - blockPos.X;
                        var num2     = gc.Y - blockPos.Y;
                        var num3     = gc.Z - blockPos.Z;
                        var result   = (num1 * num1) + (num2 * num2) + (num3 * num3);

                        if (_isServer)
                        {
                            if (result > rc)
                            {
                                continue;
                            }
                            if (damageBlocks && block.IsDestroyed)
                            {
                                DestroyedBlocks.Enqueue(block);
                                continue;
                            }
                            if (block.CubeGrid != breaching)
                            {
                                stale = true;
                                continue;
                            }
                        }
                        else
                        {
                            if (hits > blockDmgNum)
                            {
                                break;
                            }
                            if (result > rc || block.IsDestroyed || block.CubeGrid != breaching)
                            {
                                continue;
                            }
                        }
                        BoundingBoxD blockBox;
                        block.GetWorldBoundingBox(out blockBox);

                        blockBox.GetCorners(blockPoints);
                        blockPoints[8] = blockBox.Center;
                        for (int j = 8; j > -1; j--)
                        {
                            var point = blockPoints[j];
                            if (Vector3.Transform(point, DetectMatrixOutsideInv).LengthSquared() > 1)
                            {
                                continue;
                            }
                            collisionAvg += point;
                            hits++;
                            if (!_isServer)
                            {
                                break;
                            }

                            if (!damageBlocks)
                            {
                                if (hits > blockDmgNum)
                                {
                                    break;
                                }
                            }
                            else if (CollidingBlocks.Count > blockDmgNum)
                            {
                                break;
                            }

                            rawDamage += MathHelper.Clamp(block.Integrity, 0, 350);
                            if (damageBlocks)
                            {
                                CollidingBlocks.Enqueue(block);
                            }
                            break;
                        }
                    }

                    entInfo.MarkForClose = stale;

                    if (collisionAvg != Vector3D.Zero)
                    {
                        collisionAvg /= hits;

                        if (sPhysics.IsStatic && !bPhysics.IsStatic)
                        {
                            var bLSpeed    = bPhysics.LinearVelocity;
                            var bASpeed    = bPhysics.AngularVelocity * 100;
                            var bLSpeedLen = bLSpeed.Length();
                            var bASpeedLen = bASpeed.Length();
                            bASpeedLen = MathHelper.Clamp(bASpeedLen, 0, 50);
                            var bSpeedLen   = bLSpeedLen > bASpeedLen ? bLSpeedLen : bASpeedLen;
                            var surfaceMass = (bMass > sMass) ? sMass : bMass;

                            var surfaceMulti  = (hits > 5) ? 5 : hits;
                            var localNormal   = Vector3D.Transform(collisionAvg, transformInv);
                            var surfaceNormal = Vector3D.Normalize(Vector3D.TransformNormal(localNormal, normalMat));

                            var impulseData1 = new MyImpulseData {
                                MyGrid = breaching, Direction = (resultVelocity - bLSpeed) * bMass, Position = bPhysics.CenterOfMassWorld
                            };
                            var impulseData2 = new MyImpulseData {
                                MyGrid = breaching, Direction = surfaceMulti * (surfaceMass * 0.025) * -Vector3D.Dot(bLSpeed, surfaceNormal) * surfaceNormal, Position = collisionAvg
                            };
                            var forceData = new MyAddForceData {
                                MyGrid = breaching, Force = (bPhysics.CenterOfMassWorld - collisionAvg) * (bMass * bSpeedLen), MaxSpeed = MathHelper.Clamp(bSpeedLen, 1f, bSpeedLen * 0.5f)
                            };
                            ImpulseData.Enqueue(impulseData1);
                            ImpulseData.Enqueue(impulseData2);
                            ForceData.Enqueue(forceData);
                        }
                        else
                        {
                            var bLSpeed    = bPhysics.LinearVelocity;
                            var bASpeed    = bPhysics.AngularVelocity * 100;
                            var bLSpeedLen = bLSpeed.Length();
                            var bASpeedLen = bASpeed.Length();
                            bASpeedLen = MathHelper.Clamp(bASpeedLen, 0, 50);
                            var   bSpeedLen = bLSpeedLen > bASpeedLen ? bLSpeedLen : bASpeedLen;
                            float?speed;


                            if (!bPhysics.IsStatic)
                            {
                                var bImpulseData = new MyImpulseData {
                                    MyGrid = breaching, Direction = (resultVelocity - bLSpeed) * bMass, Position = bPhysics.CenterOfMassWorld
                                };
                                ImpulseData.Enqueue(bImpulseData);
                            }

                            if (!sPhysics.IsStatic)
                            {
                                var sImpulseData = new MyImpulseData {
                                    MyGrid = sGrid, Direction = (resultVelocity - sPhysics.LinearVelocity) * sMass, Position = sPhysics.CenterOfMassWorld
                                };
                                ImpulseData.Enqueue(sImpulseData);
                            }

                            if (!sPhysics.IsStatic)
                            {
                                if (bMass / sMass > 20)
                                {
                                    speed = MathHelper.Clamp(bSpeedLen, 1f, bSpeedLen * 0.5f);
                                }
                                else
                                {
                                    speed = null;
                                }

                                var sForceData = new MyAddForceData {
                                    MyGrid = sGrid, Force = (sPhysics.CenterOfMassWorld - collisionAvg) * bMass, MaxSpeed = speed
                                };
                                ForceData.Enqueue(sForceData);
                            }

                            if (!bPhysics.IsStatic)
                            {
                                if (sMass / bMass > 20)
                                {
                                    speed = MathHelper.Clamp(bSpeedLen, 1f, bSpeedLen * 0.5f);
                                }
                                else
                                {
                                    speed = null;
                                }

                                var bForceData = new MyAddForceData {
                                    MyGrid = breaching, Force = (bPhysics.CenterOfMassWorld - collisionAvg) * sMass, MaxSpeed = speed
                                };
                                ForceData.Enqueue(bForceData);
                            }
                        }
                        WebDamage    = true;
                        bBlockCenter = collisionAvg;
                    }
                    else
                    {
                        return;
                    }
                    if (!_isServer)
                    {
                        return;
                    }

                    var damage = rawDamage * DsState.State.ModulateEnergy;

                    entInfo.Damage = damage;
                    if (_mpActive)
                    {
                        if (_isServer && bBlockCenter != Vector3D.NegativeInfinity)
                        {
                            AddShieldHit(breaching.EntityId, damage, Session.Instance.MPKinetic, null, false, collisionAvg);
                        }
                    }
                    else
                    {
                        if (bBlockCenter != Vector3D.NegativeInfinity)
                        {
                            entInfo.ContactPoint = bBlockCenter;
                            ImpactSize           = entInfo.Damage;

                            entInfo.Damage      = 0;
                            entInfo.EmpSize     = 0;
                            WorldImpactPosition = bBlockCenter;
                        }
                    }
                    Absorb += damage;
                }
            }
            catch (Exception ex) { Log.Line($"Exception in BlockIntersect: {ex}"); }
        }
Example #3
0
        public void WebEntities()
        {
            PruneList.Clear();
            MyGamePruningStructure.GetTopMostEntitiesInBox(ref WebBox, PruneList);
            if (Missiles.Count > 0)
            {
                var missileBox = WebBox;
                foreach (var missile in Missiles)
                {
                    if (missile.InScene && !missile.MarkedForClose && missileBox.Intersects(missile.PositionComp.WorldAABB))
                    {
                        PruneList.Add(missile);
                    }
                }
            }
            var shieldsStartIndex = PruneList.Count;

            foreach (var eShield in EnemyShields)
            {
                PruneList.Add(eShield);
            }

            var disableVoxels = Session.Enforced.DisableVoxelSupport == 1 || ShieldComp.Modulator == null || ShieldComp.Modulator.ModSet.Settings.ModulateVoxels;
            var voxelFound    = false;
            var shieldFound   = false;
            var entChanged    = false;
            var iMoving       = ShieldComp.GridIsMoving;
            var tick          = Session.Instance.Tick;

            _enablePhysics = false;
            for (int i = 0; i < PruneList.Count; i++)
            {
                var ent        = PruneList[i];
                var entPhysics = ent.Physics;

                if (i < shieldsStartIndex)
                {
                    var voxel = ent as MyVoxelBase;
                    if (ent == null || (voxel == null && (entPhysics == null || entPhysics.IsPhantom || ent.DefinitionId == null)) || (voxel != null && (!iMoving || !GridIsMobile || disableVoxels || voxel != voxel.RootVoxel)))
                    {
                        continue;
                    }

                    bool quickReject;
                    if (_isServer)
                    {
                        quickReject = ent is IMyEngineerToolBase || IgnoreCache.Contains(ent) || EnemyShields.Contains(ent) || FriendlyMissileCache.Contains(ent) || AuthenticatedCache.Contains(ent);
                    }
                    else
                    {
                        quickReject = (!(ent is MyCubeGrid) && voxel == null && !(ent is IMyCharacter)) || IgnoreCache.Contains(ent) || EnemyShields.Contains(ent) || AuthenticatedCache.Contains(ent);
                    }

                    var floater = ent as IMyFloatingObject;
                    if (quickReject || floater != null && (!iMoving && Vector3.IsZero(entPhysics.LinearVelocity, 1e-2f)) || !WebSphere.Intersects(ent.PositionComp.WorldVolume))
                    {
                        continue;
                    }
                    if (voxel != null)
                    {
                        if (VoxelsToIntersect.ContainsKey(voxel))
                        {
                            VoxelsToIntersect[voxel]++;
                        }
                        else
                        {
                            VoxelsToIntersect[voxel] = 1;
                        }
                        voxelFound     = true;
                        entChanged     = true;
                        _enablePhysics = true;
                        continue;
                    }
                }
                Ent relation;

                ProtectCache     protectedEnt;
                EntIntersectInfo entInfo = null;
                ProtectedEntCache.TryGetValue(ent, out protectedEnt);

                var refreshInfo = false;
                if (protectedEnt == null)
                {
                    WebEnts.TryGetValue(ent, out entInfo);
                    if (entInfo != null)
                    {
                        var last        = entInfo.LastTick;
                        var refresh     = entInfo.RefreshTick;
                        var refreshTick = tick - last > 180 || (tick - last == 180 && tick - refresh >= 3600) || (tick - last == 1 && tick - refresh >= 60);
                        refreshInfo = refreshTick;
                        if (refreshInfo || entInfo.RefreshNow)
                        {
                            entInfo.RefreshTick = tick;
                            entInfo.Relation    = EntType(ent);
                        }
                        relation         = entInfo.Relation;
                        entInfo.LastTick = tick;
                    }
                    else
                    {
                        relation = EntType(ent);
                    }
                }
                else
                {
                    var last        = protectedEnt.LastTick;
                    var refresh     = protectedEnt.RefreshTick;
                    var refreshTick = tick - last > 180 || (tick - last == 180 && tick - refresh >= 3600) || (tick - last == 1 && tick - refresh >= 60);
                    refreshInfo = refreshTick;
                    if (refreshInfo)
                    {
                        protectedEnt.RefreshTick      = tick;
                        protectedEnt.PreviousRelation = protectedEnt.Relation;
                        protectedEnt.Relation         = EntType(ent);
                    }
                    relation = protectedEnt.Relation;
                    protectedEnt.LastTick = tick;
                }
                switch (relation)
                {
                case Ent.Authenticated:
                    continue;

                case Ent.Ignore:
                case Ent.Friendly:
                case Ent.Protected:
                    if (relation == Ent.Protected)
                    {
                        if (protectedEnt == null)
                        {
                            ProtectedEntCache[ent] = new ProtectCache(tick, tick, tick, relation, relation);
                        }
                        MyProtectors protectors;
                        Session.Instance.GlobalProtect.TryGetValue(ent, out protectors);
                        if (protectors == null)
                        {
                            protectors = Session.Instance.GlobalProtect[ent] = Session.ProtSets.Get();
                            protectors.Init(LogicSlot, tick);
                        }
                        if (protectors.Shields.Contains(this))
                        {
                            continue;
                        }

                        protectors.Shields.Add(this);
                        protectors.Shields.ApplyAdditions();
                        continue;
                    }
                    IgnoreCache.Add(ent);
                    continue;
                }

                if (relation == Ent.Shielded)
                {
                    shieldFound = true;
                }
                try
                {
                    if (entInfo != null)
                    {
                        var interestingEnts = relation == Ent.Floater || relation == Ent.EnemyGrid || relation == Ent.NobodyGrid || relation == Ent.Shielded;
                        if (entPhysics != null && entPhysics.IsMoving)
                        {
                            entChanged = true;
                        }
                        else if (entInfo.Touched || (refreshInfo && interestingEnts && !ent.PositionComp.LocalAABB.Equals(entInfo.Box)))
                        {
                            entInfo.RefreshTick = tick;
                            entInfo.Box         = ent.PositionComp.LocalAABB;
                            entChanged          = true;
                        }

                        _enablePhysics = true;
                        if (refreshInfo)
                        {
                            if ((relation == Ent.EnemyGrid || relation == Ent.NobodyGrid) && entInfo.CacheBlockList.Count != (ent as MyCubeGrid).BlocksCount)
                            {
                                entInfo.RefreshNow = true;
                            }
                        }
                    }
                    else
                    {
                        if (relation == Ent.Other)
                        {
                            var entPast      = -Vector3D.Normalize(entPhysics.LinearVelocity) * 6;
                            var entTestLoc   = ent.PositionComp.WorldVolume.Center + entPast;
                            var centerStep   = -Vector3D.Normalize(entTestLoc - DetectionCenter) * 2f;
                            var counterDrift = centerStep + entTestLoc;
                            if (CustomCollision.PointInShield(counterDrift, DetectMatrixOutsideInv))
                            {
                                FriendlyMissileCache.Add(ent);
                                continue;
                            }
                        }
                        entChanged     = true;
                        _enablePhysics = true;
                        ProtectedEntCache.Remove(ent);
                        WebEnts.TryAdd(ent, new EntIntersectInfo(false, ent.PositionComp.LocalAABB, tick, tick, tick, relation));
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in WebEntities entInfo: {ex}"); }
            }
            if (!_enablePhysics)
            {
                return;
            }

            ShieldMatrix = ShieldEnt.PositionComp.WorldMatrix;
            if ((_needPhysics && shieldFound) || !ShieldMatrix.EqualsFast(ref OldShieldMatrix))
            {
                OldShieldMatrix = ShieldMatrix;
                if (shieldFound)
                {
                    _needPhysics = false;
                    Icosphere.ReturnPhysicsVerts(DetectMatrixOutside, ShieldComp.PhysicsOutside);
                }
                else
                {
                    _needPhysics = true;
                }
                if (voxelFound)
                {
                    Icosphere.ReturnPhysicsVerts(DetectMatrixOutside, ShieldComp.PhysicsOutsideLow);
                }
            }

            if (iMoving || entChanged)
            {
                Asleep        = false;
                LastWokenTick = tick;
                Session.Instance.WebWrapper.Enqueue(this);
                Session.Instance.WebWrapperOn = true;
            }
        }
Example #4
0
        private void BlockIntersect(MyCubeGrid breaching, ref MyOrientedBoundingBoxD bOriBBoxD, ref EntIntersectInfo entInfo)
        {
            try
            {
                if (entInfo == null || breaching == null || breaching.MarkedForClose)
                {
                    return;
                }

                //Quaternion quadMagic;
                //Quaternion.Divide(ref bOriBBoxD.Orientation, ref SOriBBoxD.Orientation, out quadMagic);
                //var sMatrix = DetectMatrixOutsideInv;

                if (bOriBBoxD.Intersects(ref SOriBBoxD))
                //if (CustomCollision.IntersectEllipsoidObb(ref sMatrix, ref bOriBBoxD.Center, ref bOriBBoxD.HalfExtent, ref SOriBBoxD.HalfExtent, ref quadMagic))
                {
                    if (_tick - entInfo.RefreshTick == 0 || entInfo.CacheBlockList.IsEmpty)
                    {
                        entInfo.CacheBlockList.ClearImmediate();
                        RefreshBlockCache(breaching, entInfo);
                    }

                    var       collisionAvg = Vector3D.Zero;
                    const int blockDmgNum  = 250;

                    var rawDamage = 0f;
                    var hits      = 0;

                    var cubeHitSet = Session.Instance.SetCubeAccelPool.Get();
                    var sMat       = DetectMatrixOutside;

                    for (int i = 0; i < entInfo.CacheBlockList.Count; i++)
                    {
                        var accel = entInfo.CacheBlockList[i];
                        if (_isServer && (accel.Block == null || accel.Block.CubeGrid != breaching))
                        {
                            continue;
                        }

                        if (accel.Block == null || accel.Block.CubeGrid != breaching || accel.Block.IsDestroyed)
                        {
                            continue;
                        }

                        var block = accel.Block;
                        var point = CustomCollision.BlockIntersect(block, accel.CubeExists, ref bOriBBoxD, ref sMat, ref DetectMatrixOutsideInv, ref _blockPoints);
                        if (point == null)
                        {
                            continue;
                        }

                        collisionAvg += (Vector3D)point;
                        hits++;
                        if (!_isServer)
                        {
                            continue;
                        }

                        rawDamage += block.Integrity;
                        if (Session.Enforced.DisableBlockDamage == 0)
                        {
                            cubeHitSet.Add(accel);
                        }

                        if (hits > blockDmgNum)
                        {
                            break;
                        }
                    }

                    if (collisionAvg != Vector3D.Zero)
                    {
                        collisionAvg /= hits;
                        ComputeCollisionPhysics(breaching, MyGrid, collisionAvg);
                        entInfo.Touched = true;
                    }
                    else
                    {
                        return;
                    }
                    if (!_isServer)
                    {
                        return;
                    }

                    var damage = rawDamage * DsState.State.ModulateEnergy;

                    var blockEvent = Session.Instance.ManyBlocksPool.Get();
                    blockEvent.Init(cubeHitSet, this, damage, collisionAvg, breaching.EntityId);

                    Session.Instance.ThreadEvents.Enqueue(blockEvent);
                }
            }
            catch (Exception ex) { Log.Line($"Exception in BlockIntersect: {ex}"); }
        }
        private void BlockIntersect(MyCubeGrid breaching, MyOrientedBoundingBoxD bOriBBoxD, ref EntIntersectInfo entInfo)
        {
            try
            {
                if (entInfo == null || breaching == null || breaching.MarkedForClose)
                {
                    return;
                }

                if (bOriBBoxD.Intersects(ref SOriBBoxD))
                {
                    var collisionAvg = Vector3D.Zero;
                    var damageBlocks = Session.Enforced.DisableBlockDamage == 0;
                    var bQuaternion  = Quaternion.CreateFromRotationMatrix(breaching.WorldMatrix);

                    const int blockDmgNum = 250;

                    var rawDamage       = 0f;
                    var blockSize       = breaching.GridSize;
                    var scaledBlockSize = blockSize * 3;
                    var gc = breaching.WorldToGridInteger(DetectionCenter);
                    var rc = ShieldSize.AbsMax() / blockSize;
                    rc *= rc;
                    rc  = rc + 1;
                    rc  = Math.Ceiling(rc);
                    var hits        = 0;
                    var blockPoints = new Vector3D[9];

                    var cloneCacheList = Session.Instance.ListCubeAccelPool.Get();
                    cloneCacheList.AddRange(entInfo.CacheBlockList);
                    var cubeHitSet = Session.Instance.SetCubeAccelPool.Get();

                    for (int i = 0; i < cloneCacheList.Count; i++)
                    {
                        var accel    = cloneCacheList[i];
                        var blockPos = accel.BlockPos;
                        var num1     = gc.X - blockPos.X;
                        var num2     = gc.Y - blockPos.Y;
                        var num3     = gc.Z - blockPos.Z;
                        var result   = (num1 * num1) + (num2 * num2) + (num3 * num3);

                        if (_isServer)
                        {
                            if (result > rc || accel.CubeExists && result > rc + scaledBlockSize)
                            {
                                continue;
                            }
                            if (accel.Block == null || accel.Block.CubeGrid != breaching)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (hits > blockDmgNum)
                            {
                                break;
                            }
                            if (result > rc || accel.CubeExists && result > rc + scaledBlockSize || accel.Block == null || accel.Block.CubeGrid != breaching || accel.Block.IsDestroyed)
                            {
                                continue;
                            }
                        }

                        var block = accel.Block;
                        var point = CustomCollision.BlockIntersect(block, accel.CubeExists, bQuaternion, DetectMatrixOutside, DetectMatrixOutsideInv, ref blockPoints);
                        if (point == null)
                        {
                            continue;
                        }
                        collisionAvg += (Vector3D)point;
                        hits++;
                        if (!_isServer)
                        {
                            continue;
                        }

                        if (hits > blockDmgNum)
                        {
                            break;
                        }

                        rawDamage += block.Integrity;
                        if (damageBlocks)
                        {
                            cubeHitSet.Add(accel);
                        }
                    }
                    cloneCacheList.Clear();
                    Session.Instance.ListCubeAccelPool.Return(cloneCacheList);

                    if (collisionAvg != Vector3D.Zero)
                    {
                        collisionAvg /= hits;
                        ComputeCollisionPhysics(breaching, MyGrid, collisionAvg);
                        entInfo.Touched = true;
                    }
                    else
                    {
                        return;
                    }
                    if (!_isServer)
                    {
                        return;
                    }

                    var damage = rawDamage * DsState.State.ModulateEnergy;

                    var blockEvent = Session.Instance.ManyBlocksPool.Get();
                    blockEvent.Init(cubeHitSet, this, damage, collisionAvg, breaching.EntityId);

                    Session.Instance.ThreadEvents.Enqueue(blockEvent);
                }
            }
            catch (Exception ex) { Log.Line($"Exception in BlockIntersect: {ex}"); }
        }