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}"); } }
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; } }
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}"); } }