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}"); } }
private void ShieldIntersect(MyEntity ent) { var grid = ent as MyCubeGrid; if (grid == null) { return; } if (GridInside(grid, MyOrientedBoundingBoxD.CreateFromBoundingBox(grid.PositionComp.WorldAABB))) { return; } ShieldGridComponent shieldComponent; grid.Components.TryGet(out shieldComponent); if (shieldComponent?.DefenseShields == null) { return; } var ds = shieldComponent.DefenseShields; if (!ds.WasOnline) { EntIntersectInfo entInfo; WebEnts.TryRemove(ent, out entInfo); } var dsVerts = ds.ShieldComp.PhysicsOutside; var dsMatrixInv = ds.DetectMatrixOutsideInv; var myGrid = Shield.CubeGrid; var insidePoints = new List <Vector3D>(); if (_isServer) { CustomCollision.ShieldX2PointsInside(dsVerts, dsMatrixInv, ShieldComp.PhysicsOutside, DetectMatrixOutsideInv, insidePoints); } else { CustomCollision.ClientShieldX2PointsInside(dsVerts, dsMatrixInv, ShieldComp.PhysicsOutsideLow, DetectMatrixOutsideInv, insidePoints); } var bPhysics = ((IMyCubeGrid)grid).Physics; var sPhysics = myGrid.Physics; var bMass = grid.GetCurrentMass(); var sMass = ((MyCubeGrid)myGrid).GetCurrentMass(); if (bMass <= 0) { bMass = int.MaxValue; } if (sMass <= 0) { sMass = int.MaxValue; } var bVel = bPhysics.LinearVelocity; var bVelLen = bVel.Length(); var momentum = (bMass * bVel) + (sMass * sPhysics.LinearVelocity); var resultVelocity = momentum / (bMass + sMass); var collisionAvg = Vector3D.Zero; var numOfPointsInside = insidePoints.Count; for (int i = 0; i < numOfPointsInside; i++) { collisionAvg += insidePoints[i]; } collisionAvg /= numOfPointsInside; if (numOfPointsInside > 0 && !bPhysics.IsStatic) { var ejectorAccel = numOfPointsInside > 10 ? numOfPointsInside : 10; var impulseData = new MyImpulseData { MyGrid = grid, Direction = (resultVelocity - bVel) * bMass, Position = bPhysics.CenterOfMassWorld }; var forceData = new MyAddForceData { MyGrid = grid, Force = (bPhysics.CenterOfMassWorld - collisionAvg) * bMass * ejectorAccel, MaxSpeed = MathHelper.Clamp(bVelLen, 1f, 50f) }; ImpulseData.Enqueue(impulseData); ForceData.Enqueue(forceData); } if (!_isServer || numOfPointsInside <= 0) { return; } var shieldMaxChargeRate = ds._shieldMaxChargeRate; var damage = ((shieldMaxChargeRate * ConvToHp) * DsState.State.ModulateKinetic) * 0.01666666666f; if (_mpActive) { if (_isServer) { AddShieldHit(ds.Shield.EntityId, damage, Session.Instance.MPEnergy, null, false, collisionAvg); } } else { EnergyHit = true; WorldImpactPosition = collisionAvg; ds.EnergyHit = true; ds.WorldImpactPosition = collisionAvg; Absorb += damage; ImpactSize = damage; WebDamage = true; } }