public async Task Store(Hit hit) { var entity = new HitEntity { CapturedData = hit.CapturedDataString, Data = hit.DataString, Date = hit.Date, Proxy = hit.ProxyString, Type = hit.Type, ConfigId = hit.Config.Id, ConfigName = hit.Config.Metadata.Name, ConfigCategory = hit.Config.Metadata.Category, OwnerId = hit.OwnerId }; if (hit.DataPool is WordlistDataPool) { var wordlist = (hit.DataPool as WordlistDataPool).Wordlist; entity.WordlistId = wordlist.Id; entity.WordlistName = wordlist.Name; } // Only allow saving one hit at a time (multiple threads should // not use the same DbContext at the same time). await semaphore.WaitAsync(); try { await hitRepo.Add(entity); } finally { semaphore.Release(); } }
public void Initialize(NPCConfig config, HitEntity target) { this.config = config; this.target = target; navMeshAgent.speed = config.MoveSpeed; SetUpHealth(config.Health); }
private void UpdateField(HitEntity hitEnt, ProInfo info) { if (info.AmmoDef.Const.AreaEffect == PullField || info.AmmoDef.Const.AreaEffect == PushField) { PushPull(hitEnt, info); return; } var grid = hitEnt.Entity as MyCubeGrid; if (grid?.Physics == null || grid.MarkedForClose) { return; } var attackerId = info.Target.FiringCube.EntityId; GetAndSortBlocksInSphere(info.AmmoDef, hitEnt.Info.System, grid, hitEnt.PruneSphere, !hitEnt.DamageOverTime, hitEnt.Blocks); var depletable = info.AmmoDef.AreaEffect.EwarFields.Depletable; var healthPool = depletable && info.BaseHealthPool > 0 ? info.BaseHealthPool : float.MaxValue; ComputeEffects(grid, info.AmmoDef, info.AmmoDef.Const.AreaEffectDamage, ref healthPool, attackerId, info.System.WeaponIdHash, hitEnt.Blocks); if (depletable) { info.BaseHealthPool -= healthPool; } }
private void UpdateEffect(HitEntity hitEnt, ProInfo info) { if (info.AmmoDef.Const.AreaEffect == PullField || info.AmmoDef.Const.AreaEffect == PushField) { PushPull(hitEnt, info); return; } var grid = hitEnt.Entity as MyCubeGrid; if (grid == null || grid.MarkedForClose) { return; } if (IsServer) { Dictionary <AreaEffectType, GridEffect> effects; var attackerId = info.Target.FiringCube.EntityId; if (_gridEffects.TryGetValue(grid, out effects)) { GridEffect gridEffect; if (effects.TryGetValue(info.AmmoDef.AreaEffect.AreaEffect, out gridEffect)) { gridEffect.Damage += info.AmmoDef.Const.AreaEffectDamage; gridEffect.Ai = info.Ai; gridEffect.AttackerId = attackerId; gridEffect.Hits++; var hitPos = hitEnt.HitPos ?? info.Hit.SurfaceHit; gridEffect.HitPos = (gridEffect.HitPos + hitPos) / 2; } } else { effects = GridEffectsPool.Get(); var gridEffect = GridEffectPool.Get(); gridEffect.System = info.System; gridEffect.Damage = info.AmmoDef.Const.AreaEffectDamage; gridEffect.Ai = info.Ai; gridEffect.AmmoDef = info.AmmoDef; gridEffect.AttackerId = attackerId; gridEffect.Hits++; var hitPos = hitEnt.HitPos ?? info.Hit.SurfaceHit; gridEffect.HitPos = hitPos; effects.Add(info.AmmoDef.AreaEffect.AreaEffect, gridEffect); _gridEffects.Add(grid, effects); } } info.BaseHealthPool = 0; info.BaseDamagePool = 0; }
public async Task CreateNewAsync(DateTimeOffset eventDate, string shortCode) { var table = await _cloudTableFactory.GetCloudTableReferenceAsync(TableNames.Hits); var entity = new HitEntity { PartitionKey = PartitionKeys.Hit, RowKey = Guid.NewGuid().ToString(), CreatedOn = eventDate, ShortCode = shortCode, Timestamp = DateTimeOffset.UtcNow }; var operation = TableOperation.Insert(entity); await table.ExecuteAsync(operation); }
public static async Task Run( [EventHubTrigger(HubNames.ClickEventsHub, Connection = "CloudSettings:EventHubListenerConnectionString")] LinkClickedMessage events, [Table(TableNames.Hits)] CloudTable table, ILogger log) { var entity = new HitEntity { PartitionKey = PartitionKeys.Hit, RowKey = Guid.NewGuid().ToString(), CreatedOn = events.ClickedAt, ShortCode = events.Key, Timestamp = DateTimeOffset.UtcNow }; var operation = TableOperation.Insert(entity); await table.CreateIfNotExistsAsync(); await table.ExecuteAsync(operation); }
public override void OnTravel(VRIL_ControllerActionEventArgs e) { // if a valid position is selected, travel is triggered if (PositionSelected && !DelayToNextTravel) { // allow no other input while travelling to target position Manager.InputLocked = true; TravelMode = true; SaveDistancesToViewpoint(); PlayAudio(); StartCoroutine(DashMovement()); DelayToNextTravel = true; } if (HitEntity) { HitEntity.SetActive(false); } IsActivated = false; }
private bool HitDoor(HitEntity hitEnt, MyDoorBase door) { var ray = new RayD(ref hitEnt.Intersection.From, ref hitEnt.Intersection.Direction); var rayHit = ray.Intersects(door.PositionComp.WorldVolume); if (rayHit != null) { var hitPos = hitEnt.Intersection.From + (hitEnt.Intersection.Direction * (rayHit.Value + 0.25f)); IHitInfo hitInfo; if (MyAPIGateway.Physics.CastRay(hitPos, hitEnt.Intersection.To, out hitInfo, 15)) { var rotMatrix = Quaternion.CreateFromRotationMatrix(door.WorldMatrix); var obb = new MyOrientedBoundingBoxD(door.PositionComp.WorldAABB.Center, door.PositionComp.LocalAABB.HalfExtents, rotMatrix); var sphere = new BoundingSphereD(hitInfo.Position + (hitEnt.Intersection.Direction * 0.15f), 0.01f); if (obb.Intersects(ref sphere)) { return(true); } } } return(false); }
/// <summary> /// Called when the travel should be performed /// </summary> /// <param name="e">ControllerActionEventArgs</param> public override void OnTravel(VRIL_ControllerActionEventArgs e) { if (IsActivated && !DelayToNextTravel) { // if a valid position is selected, travel is triggered if (PositionSelected) { PlayAudio(); SaveDistancesToViewpoint(); Viewpoint.transform.position = TargetPosition; TransferSelectedObjects(); PositionSelected = false; Timer = 0.0f; DelayToNextTravel = true; // blink scene away immediately if (SceneBlinksAway) { SteamVR_Fade.View(SceneOffColor, 0); SceneOff = true; } } if (HitEntity != null) { HitEntity.SetActive(false); } IsActivated = false; // in case travel does not disabled technique, selection mode is actived again if (!TravelDisablesTechnique) { IsActivated = true; StartCoroutine(SelectPosition(e)); } } }
public async Task Store(Hit hit) { var entity = new HitEntity { CapturedData = hit.CapturedDataString, Data = hit.DataString, Date = hit.Date, Proxy = hit.ProxyString, Type = hit.Type, ConfigId = hit.Config.Id, ConfigName = hit.Config.Metadata.Name, ConfigCategory = hit.Config.Metadata.Category, OwnerId = hit.OwnerId }; if (hit.DataPool is WordlistDataPool) { var wordlist = (hit.DataPool as WordlistDataPool).Wordlist; entity.WordlistId = wordlist.Id; entity.WordlistName = wordlist.Name; } await hitRepo.Add(entity); }
private void UpdateField(HitEntity hitEnt, ProInfo info) { var grid = hitEnt.Entity as MyCubeGrid; if (grid == null || grid.MarkedForClose) { return; } var depletable = info.AmmoDef.AreaEffect.EwarFields.Depletable; var healthPool = depletable && info.BaseHealthPool > 0 ? info.BaseHealthPool : float.MaxValue; if (healthPool <= 0) { return; } if (info.AmmoDef.Const.AreaEffect == PullField || info.AmmoDef.Const.AreaEffect == PushField) { if (grid.Physics == null || !grid.Physics.Enabled || grid.Physics.IsStatic) { return; } var dir = info.AmmoDef.Const.AreaEffect == PushField ? hitEnt.Intersection.Direction : -hitEnt.Intersection.Direction; grid.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, dir * info.AmmoDef.Const.AreaEffectDamage, grid.Physics?.CenterOfMassWorld, Vector3.Zero); } else { var attackerId = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass ? grid.EntityId : info.Target.FiringCube.EntityId; GetAndSortBlocksInSphere(info.AmmoDef, hitEnt.Info.Ai, grid, hitEnt.PruneSphere, !hitEnt.DamageOverTime, hitEnt.Blocks); ComputeEffects(grid, info.AmmoDef, info.AreaEffectDamage, healthPool, attackerId, hitEnt.Blocks); } if (depletable) { info.BaseHealthPool -= healthPool; } }
private void DamageGrid(HitEntity hitEnt, ProInfo t) { var grid = hitEnt.Entity as MyCubeGrid; if (grid == null || grid.MarkedForClose || !hitEnt.HitPos.HasValue || hitEnt.Blocks == null) { hitEnt.Blocks?.Clear(); return; } if (t.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Heal || (!t.AmmoDef.Const.SelfDamage || !MyAPIGateway.Session.SessionSettings.EnableTurretsFriendlyFire) && t.Ai.MyGrid.IsSameConstructAs(grid)) { t.BaseDamagePool = 0; return; } _destroyedSlims.Clear(); _destroyedSlimsClient.Clear(); var largeGrid = grid.GridSizeEnum == MyCubeSize.Large; var areaRadius = largeGrid ? t.AmmoDef.Const.AreaRadiusLarge : t.AmmoDef.Const.AreaRadiusSmall; var detonateRadius = largeGrid ? t.AmmoDef.Const.DetonateRadiusLarge : t.AmmoDef.Const.DetonateRadiusSmall; var maxObjects = t.AmmoDef.Const.MaxObjectsHit; var areaEffect = t.AmmoDef.AreaEffect.AreaEffect; var explosive = areaEffect == AreaEffectType.Explosive; var radiant = areaEffect == AreaEffectType.Radiant; var detonateOnEnd = t.AmmoDef.AreaEffect.Detonation.DetonateOnEnd; var detonateDmg = t.DetonationDamage; var shieldBypass = t.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass; var attackerId = shieldBypass ? grid.EntityId : t.Target.FiringCube.EntityId; var attacker = shieldBypass ? (MyEntity)grid : t.Target.FiringCube; var areaEffectDmg = areaEffect != AreaEffectType.Disabled ? t.AreaEffectDamage : 0; var hitMass = t.AmmoDef.Mass; var sync = MpActive && (DedicatedServer || IsServer); var hasAreaDmg = areaEffectDmg > 0; var radiantCascade = radiant && !detonateOnEnd; var primeDamage = !radiantCascade || !hasAreaDmg; var radiantBomb = radiant && detonateOnEnd; var damageType = explosive || radiant ? MyDamageType.Explosion : MyDamageType.Bullet; var fallOff = t.AmmoDef.Const.FallOffScaling && t.DistanceTraveled > t.AmmoDef.DamageScales.FallOff.Distance; var fallOffMultipler = 1f; if (fallOff) { fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((t.DistanceTraveled - t.AmmoDef.DamageScales.FallOff.Distance) / (t.AmmoDef.Const.MaxTrajectory - t.AmmoDef.DamageScales.FallOff.Distance)), t.AmmoDef.DamageScales.FallOff.MinMultipler, 1); } var damagePool = t.BaseDamagePool; if (t.AmmoDef.Const.VirtualBeams) { var hits = t.WeaponCache.Hits; damagePool *= hits; areaEffectDmg *= hits; } var objectsHit = t.ObjectsHit; var countBlocksAsObjects = t.AmmoDef.ObjectsHit.CountBlocks; List <Vector3I> radiatedBlocks = null; if (radiant) { GetBlockSphereDb(grid, areaRadius, out radiatedBlocks); } var done = false; var nova = false; var outOfPew = false; for (int i = 0; i < hitEnt.Blocks.Count; i++) { if (done || outOfPew && !nova) { break; } var rootBlock = hitEnt.Blocks[i]; if (!nova) { if (_destroyedSlims.Contains(rootBlock) || _destroyedSlimsClient.Contains(rootBlock)) { continue; } if (rootBlock.IsDestroyed) { _destroyedSlims.Add(rootBlock); if (IsClient) { _destroyedSlimsClient.Add(rootBlock); if (_slimHealthClient.ContainsKey(rootBlock)) { _slimHealthClient.Remove(rootBlock); } } continue; } } var door = rootBlock.FatBlock as MyDoorBase; if (door != null && door.Open && !HitDoor(hitEnt, door)) { continue; } var radiate = radiantCascade || nova; var dmgCount = 1; if (radiate) { if (nova) { GetBlockSphereDb(grid, detonateRadius, out radiatedBlocks); } if (radiatedBlocks != null) { ShiftAndPruneBlockSphere(grid, rootBlock.Position, radiatedBlocks, _slimsSortedList); } done = nova; dmgCount = _slimsSortedList.Count; } for (int j = 0; j < dmgCount; j++) { var block = radiate ? _slimsSortedList[j].Slim : rootBlock; var blockHp = !IsClient ? block.Integrity : _slimHealthClient.ContainsKey(block) ? _slimHealthClient[block] : block.Integrity; float damageScale = 1; if (t.AmmoDef.Const.DamageScaling) { var d = t.AmmoDef.DamageScales; if (d.MaxIntegrity > 0 && blockHp > d.MaxIntegrity) { outOfPew = true; damagePool = 0; continue; } if (d.Grids.Large >= 0 && largeGrid) { damageScale *= d.Grids.Large; } else if (d.Grids.Small >= 0 && !largeGrid) { damageScale *= d.Grids.Small; } MyDefinitionBase blockDef = null; if (t.AmmoDef.Const.ArmorScaling) { blockDef = block.BlockDefinition; var isArmor = AllArmorBaseDefinitions.Contains(blockDef); if (isArmor && d.Armor.Armor >= 0) { damageScale *= d.Armor.Armor; } else if (!isArmor && d.Armor.NonArmor >= 0) { damageScale *= d.Armor.NonArmor; } if (isArmor && (d.Armor.Light >= 0 || d.Armor.Heavy >= 0)) { var isHeavy = HeavyArmorBaseDefinitions.Contains(blockDef); if (isHeavy && d.Armor.Heavy >= 0) { damageScale *= d.Armor.Heavy; } else if (!isHeavy && d.Armor.Light >= 0) { damageScale *= d.Armor.Light; } } } if (t.AmmoDef.Const.CustomDamageScales) { if (blockDef == null) { blockDef = block.BlockDefinition; } float modifier; var found = t.AmmoDef.Const.CustomBlockDefinitionBasesToScales.TryGetValue(blockDef, out modifier); if (found) { damageScale *= modifier; } else if (t.AmmoDef.DamageScales.Custom.IgnoreAllOthers) { continue; } } if (fallOff) { damageScale *= fallOffMultipler; } } var blockIsRoot = block == rootBlock; var primaryDamage = primeDamage || blockIsRoot; if (damagePool <= 0 && primaryDamage || objectsHit >= maxObjects) { break; } var scaledDamage = damagePool * damageScale; if (primaryDamage) { if (countBlocksAsObjects) { objectsHit++; } if (scaledDamage <= blockHp) { outOfPew = true; damagePool = 0; } else { _destroyedSlims.Add(block); if (IsClient) { _destroyedSlimsClient.Add(block); if (_slimHealthClient.ContainsKey(block)) { _slimHealthClient.Remove(block); } } damagePool -= blockHp; } } else { scaledDamage = areaEffectDmg * damageScale; if (scaledDamage >= blockHp) { _destroyedSlims.Add(block); if (IsClient) { _destroyedSlimsClient.Add(block); if (_slimHealthClient.ContainsKey(block)) { _slimHealthClient.Remove(block); } } } } if (!IsClient) { block.DoDamage(scaledDamage, damageType, sync, null, attackerId); } else { var hasBlock = _slimHealthClient.ContainsKey(block); if (hasBlock && _slimHealthClient[block] - scaledDamage > 0) { _slimHealthClient[block] -= scaledDamage; } else if (hasBlock) { _slimHealthClient.Remove(block); } else if (block.Integrity - scaledDamage > 0) { _slimHealthClient[block] = blockHp - scaledDamage; } } var theEnd = damagePool <= 0 || objectsHit >= maxObjects; if (explosive && (!detonateOnEnd && blockIsRoot || detonateOnEnd && theEnd)) { var rootPos = grid.GridIntegerToWorld(rootBlock.Position); if (areaEffectDmg > 0) { SUtils.CreateMissileExplosion(this, areaEffectDmg * damageScale, areaRadius, rootPos, hitEnt.Intersection.Direction, attacker, grid, t.AmmoDef, true); } if (detonateOnEnd && theEnd) { SUtils.CreateMissileExplosion(this, detonateDmg * damageScale, detonateRadius, rootPos, hitEnt.Intersection.Direction, attacker, grid, t.AmmoDef, true); } } else if (!nova) { if (hitMass > 0 && blockIsRoot) { var speed = t.AmmoDef.Trajectory.DesiredSpeed > 0 ? t.AmmoDef.Trajectory.DesiredSpeed : 1; ApplyProjectileForce(grid, grid.GridIntegerToWorld(rootBlock.Position), hitEnt.Intersection.Direction, (hitMass * speed)); } if (radiantBomb && theEnd) { nova = true; i--; t.BaseDamagePool = 0; t.ObjectsHit = maxObjects; objectsHit = int.MinValue; var aInfo = t.AmmoDef.AreaEffect; var dInfo = aInfo.Detonation; if (dInfo.DetonationDamage > 0) { damagePool = detonateDmg; } else if (aInfo.AreaEffectDamage > 0) { damagePool = areaEffectDmg; } else { damagePool = scaledDamage; } break; } } } } if (!countBlocksAsObjects) { t.ObjectsHit += 1; } if (!nova) { t.BaseDamagePool = damagePool; t.ObjectsHit = objectsHit; } if (radiantCascade || nova) { _slimsSortedList.Clear(); } hitEnt.Blocks.Clear(); }
internal int GetEntityCompareDist(HitEntity x, HitEntity y, List <Vector3I> slims, ProInfo info) { var xDist = double.MaxValue; var yDist = double.MaxValue; var beam = x.Intersection; var count = y != null ? 2 : 1; var eWarPulse = info.AmmoDef.Const.Ewar && info.AmmoDef.Const.Pulse; var triggerEvent = eWarPulse && !info.TriggeredPulse && info.AmmoDef.Const.EwarTriggerRange > 0; for (int i = 0; i < count; i++) { var isX = i == 0; MyEntity ent; HitEntity hitEnt; if (isX) { hitEnt = x; ent = hitEnt.Entity; } else { hitEnt = y; ent = hitEnt.Entity; } var dist = double.MaxValue; var shield = ent as IMyTerminalBlock; var grid = ent as MyCubeGrid; var voxel = ent as MyVoxelBase; if (triggerEvent && (info.Ai.Targets.ContainsKey(ent) || shield != null)) { hitEnt.PulseTrigger = true; } else if (hitEnt.Projectile != null) { dist = hitEnt.HitDist.Value; } else if (shield != null) { hitEnt.Hit = true; dist = hitEnt.HitDist.Value; } else if (grid != null) { if (hitEnt.Hit) { dist = Vector3D.Distance(hitEnt.Intersection.From, hitEnt.HitPos.Value); hitEnt.HitDist = dist; } else { if (hitEnt.SphereCheck || info.EwarActive) { var ewarActive = hitEnt.EventType == Field || hitEnt.EventType == Effect; var hitPos = !ewarActive ? hitEnt.PruneSphere.Center + (hitEnt.Intersection.Direction * hitEnt.PruneSphere.Radius) : hitEnt.PruneSphere.Center; if (grid.IsSameConstructAs(hitEnt.Info.Ai.MyGrid) && Vector3D.DistanceSquared(hitPos, hitEnt.Info.Origin) <= grid.GridSize * grid.GridSize) { continue; } if (!ewarActive) { GetAndSortBlocksInSphere(hitEnt.Info.AmmoDef, hitEnt.Info.Ai, grid, hitEnt.PruneSphere, false, hitEnt.Blocks); } if (hitEnt.Blocks.Count > 0 || ewarActive) { dist = 0; hitEnt.HitDist = dist; hitEnt.Hit = true; hitEnt.HitPos = hitPos; } } else { grid.RayCastCells(beam.From, beam.To, slims, null, true, true); var closestBlockFound = false; var rotMatrix = Quaternion.CreateFromRotationMatrix(grid.PositionComp.WorldMatrixRef); var hitSelf = grid.IsSameConstructAs(hitEnt.Info.Target.FiringCube.CubeGrid); for (int j = 0; j < slims.Count; j++) { var firstBlock = grid.GetCubeBlock(slims[j]) as IMySlimBlock; if (firstBlock != null && !firstBlock.IsDestroyed && firstBlock != hitEnt.Info.Target.FiringCube.SlimBlock) { hitEnt.Blocks.Add(firstBlock); if (closestBlockFound) { continue; } MyOrientedBoundingBoxD obb; var fat = firstBlock.FatBlock; if (fat != null) { obb = new MyOrientedBoundingBoxD(fat.Model.BoundingBox, fat.PositionComp.WorldMatrixRef); } else { Vector3D center; firstBlock.ComputeWorldCenter(out center); Vector3 halfExt; firstBlock.ComputeScaledHalfExtents(out halfExt); var blockBox = new BoundingBoxD(-halfExt, halfExt); obb = new MyOrientedBoundingBoxD(center, blockBox.HalfExtents, rotMatrix); } var hitDist = obb.Intersects(ref beam) ?? Vector3D.Distance(beam.From, obb.Center); var hitPos = beam.From + (beam.Direction * hitDist); if (hitSelf) { if (Vector3D.DistanceSquared(hitPos, hitEnt.Info.Origin) <= grid.GridSize * 3) { hitEnt.Blocks.Clear(); } else { dist = hitDist; hitEnt.HitDist = dist; hitEnt.Hit = true; hitEnt.HitPos = hitPos; } break; } dist = hitDist; hitEnt.HitDist = dist; hitEnt.Hit = true; hitEnt.HitPos = hitPos; closestBlockFound = true; } } } } } else if (voxel != null) { hitEnt.Hit = true; dist = hitEnt.HitDist.Value; hitEnt.HitDist = dist; } else if (ent is IMyDestroyableObject) { if (hitEnt.Hit) { dist = Vector3D.Distance(hitEnt.Intersection.From, hitEnt.HitPos.Value); } else { if (hitEnt.SphereCheck || info.EwarActive) { var ewarActive = hitEnt.EventType == Field || hitEnt.EventType == Effect; dist = 0; hitEnt.HitDist = dist; hitEnt.Hit = true; var hitPos = !ewarActive ? hitEnt.PruneSphere.Center + (hitEnt.Intersection.Direction * hitEnt.PruneSphere.Radius) : hitEnt.PruneSphere.Center; hitEnt.HitPos = hitPos; } else { var rotMatrix = Quaternion.CreateFromRotationMatrix(ent.PositionComp.WorldMatrixRef); var obb = new MyOrientedBoundingBoxD(ent.PositionComp.WorldAABB.Center, ent.PositionComp.LocalAABB.HalfExtents, rotMatrix); dist = obb.Intersects(ref beam) ?? double.MaxValue; if (dist < double.MaxValue) { hitEnt.Hit = true; hitEnt.HitPos = beam.From + (beam.Direction * dist); hitEnt.HitDist = dist; } } } } if (isX) { xDist = dist; } else { yDist = dist; } } V3Pool.Return(slims); return(xDist.CompareTo(yDist)); }
private void DamageDestObj(HitEntity hitEnt, ProInfo info) { var entity = hitEnt.Entity; var destObj = hitEnt.Entity as IMyDestroyableObject; if (destObj == null || entity == null) { return; } var shieldHeal = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Heal; var shieldByPass = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass; var sync = MpActive && IsServer; var attackerId = info.Target.FiringCube.EntityId; var objHp = destObj.Integrity; var integrityCheck = info.AmmoDef.DamageScales.MaxIntegrity > 0; if (integrityCheck && objHp > info.AmmoDef.DamageScales.MaxIntegrity || shieldHeal) { info.BaseDamagePool = 0; return; } var character = hitEnt.Entity as IMyCharacter; float damageScale = 1; if (info.AmmoDef.Const.VirtualBeams) { damageScale *= info.WeaponCache.Hits; } if (character != null && info.AmmoDef.DamageScales.Characters >= 0) { damageScale *= info.AmmoDef.DamageScales.Characters; } var scaledDamage = info.BaseDamagePool * damageScale; var fallOff = info.AmmoDef.Const.FallOffScaling && info.DistanceTraveled > info.AmmoDef.DamageScales.FallOff.Distance; if (fallOff) { var fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((info.DistanceTraveled - info.AmmoDef.DamageScales.FallOff.Distance) / (info.AmmoDef.Const.MaxTrajectory - info.AmmoDef.DamageScales.FallOff.Distance)), info.AmmoDef.DamageScales.FallOff.MinMultipler, 1); scaledDamage *= fallOffMultipler; } if (scaledDamage < objHp) { info.BaseDamagePool = 0; } else { info.BaseDamagePool -= objHp; } if (!IsClient) { destObj.DoDamage(scaledDamage, !shieldByPass ? MyDamageType.Bullet : MyDamageType.Drill, sync, null, attackerId); } if (info.AmmoDef.Mass > 0) { var speed = info.AmmoDef.Trajectory.DesiredSpeed > 0 ? info.AmmoDef.Trajectory.DesiredSpeed : 1; ApplyProjectileForce(entity, entity.PositionComp.WorldAABB.Center, hitEnt.Intersection.Direction, (info.AmmoDef.Mass * speed)); } }
private static void DamageProjectile(HitEntity hitEnt, ProInfo attacker) { var pTarget = hitEnt.Projectile; if (pTarget == null) { return; } attacker.ObjectsHit++; var objHp = pTarget.Info.BaseHealthPool; var integrityCheck = attacker.AmmoDef.DamageScales.MaxIntegrity > 0; if (integrityCheck && objHp > attacker.AmmoDef.DamageScales.MaxIntegrity) { return; } float damageScale = 1; if (attacker.AmmoDef.Const.VirtualBeams) { damageScale *= attacker.WeaponCache.Hits; } var scaledDamage = attacker.BaseDamagePool * damageScale; var fallOff = attacker.AmmoDef.Const.FallOffScaling && attacker.DistanceTraveled > attacker.AmmoDef.DamageScales.FallOff.Distance; if (fallOff) { var fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((attacker.DistanceTraveled - attacker.AmmoDef.DamageScales.FallOff.Distance) / (attacker.AmmoDef.Const.MaxTrajectory - attacker.AmmoDef.DamageScales.FallOff.Distance)), attacker.AmmoDef.DamageScales.FallOff.MinMultipler, 1); scaledDamage *= fallOffMultipler; } if (scaledDamage >= objHp) { attacker.BaseDamagePool -= objHp; pTarget.Info.BaseHealthPool = 0; pTarget.State = Projectile.ProjectileState.Destroy; } else { attacker.BaseDamagePool = 0; pTarget.Info.BaseHealthPool -= scaledDamage; if (attacker.DetonationDamage > 0 && attacker.AmmoDef.AreaEffect.Detonation.DetonateOnEnd) { var areaSphere = new BoundingSphereD(pTarget.Position, attacker.AmmoDef.AreaEffect.Detonation.DetonationRadius); foreach (var sTarget in attacker.Ai.LiveProjectile) { if (areaSphere.Contains(sTarget.Position) != ContainmentType.Disjoint) { if (attacker.DetonationDamage >= sTarget.Info.BaseHealthPool) { sTarget.Info.BaseHealthPool = 0; sTarget.State = Projectile.ProjectileState.Destroy; } else { sTarget.Info.BaseHealthPool -= attacker.DetonationDamage; } } } } } }
private void DamageVoxel(HitEntity hitEnt, ProInfo info) { var entity = hitEnt.Entity; var destObj = hitEnt.Entity as MyVoxelBase; if (destObj == null || entity == null || !hitEnt.HitPos.HasValue) { return; } var shieldHeal = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Heal; if (!info.AmmoDef.Const.VoxelDamage || shieldHeal) { info.BaseDamagePool = 0; return; } using (destObj.Pin()) { var detonateOnEnd = info.AmmoDef.Const.AmmoAreaEffect && info.AmmoDef.AreaEffect.Detonation.DetonateOnEnd && info.AmmoDef.AreaEffect.AreaEffect != AreaEffectType.Radiant; info.ObjectsHit++; float damageScale = 1; if (info.AmmoDef.Const.VirtualBeams) { damageScale *= info.WeaponCache.Hits; } var scaledDamage = info.BaseDamagePool * damageScale; var fallOff = info.AmmoDef.Const.FallOffScaling && info.DistanceTraveled > info.AmmoDef.DamageScales.FallOff.Distance; if (fallOff) { var fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((info.DistanceTraveled - info.AmmoDef.DamageScales.FallOff.Distance) / (info.AmmoDef.Const.MaxTrajectory - info.AmmoDef.DamageScales.FallOff.Distance)), info.AmmoDef.DamageScales.FallOff.MinMultipler, 1); scaledDamage *= fallOffMultipler; } var oRadius = info.AmmoDef.AreaEffect.AreaEffectRadius; var minTestRadius = info.DistanceTraveled - info.PrevDistanceTraveled; var tRadius = oRadius < minTestRadius ? minTestRadius : oRadius; var objHp = (int)MathHelper.Clamp(MathFuncs.VolumeCube(MathFuncs.LargestCubeInSphere(tRadius)), 1, double.MaxValue); var sync = MpActive && IsServer; if (tRadius > 5) { objHp *= 5; } if (scaledDamage < objHp) { var reduceBy = objHp / scaledDamage; oRadius /= reduceBy; if (oRadius < 1) { oRadius = 1; } info.BaseDamagePool = 0; } else { info.BaseDamagePool -= objHp; if (oRadius < minTestRadius) { oRadius = minTestRadius; } } destObj.PerformCutOutSphereFast(hitEnt.HitPos.Value, (float)oRadius, true); if (detonateOnEnd) { var det = info.AmmoDef.AreaEffect.Detonation; var dRadius = det.DetonationRadius; var dObjHp = (int)MathHelper.Clamp(MathFuncs.VolumeCube(MathFuncs.LargestCubeInSphere(dRadius)), 1, double.MaxValue); if (dRadius > 5) { dObjHp *= 5; } dObjHp *= 5; var dDamage = det.DetonationDamage; var reduceBy = dObjHp / dDamage; dRadius /= reduceBy; if (dRadius < 1.5) { dRadius = 1.5f; } if (sync) { destObj.PerformCutOutSphereFast(hitEnt.HitPos.Value, dRadius, true); } } } }
private void DamageShield(HitEntity hitEnt, ProInfo info) { var shield = hitEnt.Entity as IMyTerminalBlock; if (shield == null || !hitEnt.HitPos.HasValue) { return; } info.ObjectsHit++; var damageScale = 1; var fallOff = info.AmmoDef.Const.FallOffScaling && info.DistanceTraveled > info.AmmoDef.DamageScales.FallOff.Distance; if (info.AmmoDef.Const.VirtualBeams) { damageScale *= info.WeaponCache.Hits; } var damageType = info.AmmoDef.DamageScales.Shields.Type; var energy = damageType == ShieldDef.ShieldType.Energy; var heal = damageType == ShieldDef.ShieldType.Heal; var shieldByPass = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass; var areaEffect = info.AmmoDef.AreaEffect; var detonateOnEnd = info.AmmoDef.AreaEffect.Detonation.DetonateOnEnd && areaEffect.AreaEffect != AreaEffectType.Disabled && !shieldByPass; var areaDamage = areaEffect.AreaEffect != AreaEffectType.Disabled ? areaEffect.AreaEffectDamage * (areaEffect.AreaEffectRadius * 0.5f) : 0; var scaledDamage = (((info.BaseDamagePool * damageScale) + areaDamage) * info.AmmoDef.Const.ShieldModifier) * info.AmmoDef.Const.ShieldBypassMod; if (fallOff) { var fallOffMultipler = MathHelperD.Clamp(1.0 - ((info.DistanceTraveled - info.AmmoDef.DamageScales.FallOff.Distance) / (info.AmmoDef.Const.MaxTrajectory - info.AmmoDef.DamageScales.FallOff.Distance)), info.AmmoDef.DamageScales.FallOff.MinMultipler, 1); scaledDamage *= fallOffMultipler; } var detonateDamage = detonateOnEnd ? (areaEffect.Detonation.DetonationDamage * (areaEffect.Detonation.DetonationRadius * 0.5f)) * info.AmmoDef.Const.ShieldModifier : 0; var combinedDamage = (float)(scaledDamage + detonateDamage); if (heal) { combinedDamage *= -1; } var hit = SApi.PointAttackShieldExt(shield, hitEnt.HitPos.Value, info.Target.FiringCube.EntityId, combinedDamage, energy, info.AmmoDef.AmmoGraphics.ShieldHitDraw); if (hit.HasValue) { if (heal) { info.BaseDamagePool = 0; return; } var objHp = hit.Value; if (info.EwarActive) { info.BaseHealthPool -= 1; } else if (objHp > 0) { if (!shieldByPass) { info.BaseDamagePool = 0; } else { info.BaseDamagePool *= info.AmmoDef.Const.ShieldBypassMod; } } else { info.BaseDamagePool = (objHp * -1); } if (info.AmmoDef.Mass <= 0) { return; } var speed = info.AmmoDef.Trajectory.DesiredSpeed > 0 ? info.AmmoDef.Trajectory.DesiredSpeed : 1; ApplyProjectileForce((MyEntity)shield.CubeGrid, hitEnt.HitPos.Value, hitEnt.Intersection.Direction, info.AmmoDef.Mass * speed); } }
internal void InitialHitCheck() { var vhCount = ValidateHits.Count; var minCount = Session.Settings.Enforcement.ServerOptimizations ? 96 : 99999; var stride = vhCount < minCount ? 100000 : 48; MyAPIGateway.Parallel.For(0, ValidateHits.Count, x => { var p = ValidateHits[x]; var shieldByPass = p.Info.ConsumableDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass; var shieldFullBypass = shieldByPass && p.Info.ConsumableDef.Const.ShieldBypassMod >= 1; var genericFields = p.Info.EwarActive && (p.Info.ConsumableDef.Const.AreaEffect == DotField || p.Info.ConsumableDef.Const.AreaEffect == PushField || p.Info.ConsumableDef.Const.AreaEffect == PullField); p.FinalizeIntersection = false; var lineCheck = p.Info.ConsumableDef.Const.CollisionIsLine && !p.Info.EwarAreaPulse; var ewarProjectile = (p.Info.EwarActive || p.Info.ConsumableDef.Const.EwarEffect); bool projetileInShield = false; var tick = p.Info.System.Session.Tick; var useEntityCollection = p.CheckType != Projectile.CheckTypes.Ray; var entityCollection = p.UseEntityCache ? p.Info.Ai.NearByEntityCache : p.MyEntityList; var collectionCount = !useEntityCollection ? p.MySegmentList.Count : entityCollection.Count; var ray = new RayD(ref p.Beam.From, ref p.Beam.Direction); var myGrid = p.Info.Target.FiringCube.CubeGrid; Water water = null; if (Session.WaterApiLoaded && p.Info.MyPlanet != null) { Session.WaterMap.TryGetValue(p.Info.MyPlanet, out water); } for (int i = 0; i < collectionCount; i++) { var ent = !useEntityCollection ? p.MySegmentList[i].Element : entityCollection[i]; var grid = ent as MyCubeGrid; var entIsSelf = grid != null && (grid == myGrid || myGrid.IsSameConstructAs(grid)); if (entIsSelf && p.SmartsOn || ent.MarkedForClose || !ent.InScene || ent == p.Info.MyShield) { continue; } var character = ent as IMyCharacter; if (p.Info.EwarActive && character != null && !genericFields) { continue; } var entSphere = ent.PositionComp.WorldVolume; if (useEntityCollection) { if (p.CheckType == Projectile.CheckTypes.CachedRay) { var dist = ray.Intersects(entSphere); if (!dist.HasValue || dist > p.Beam.Length) { continue; } } else if (p.CheckType == Projectile.CheckTypes.CachedSphere && p.PruneSphere.Contains(entSphere) == ContainmentType.Disjoint) { continue; } } if (grid != null || character != null) { var extBeam = new LineD(p.Beam.From - p.Beam.Direction * (entSphere.Radius * 2), p.Beam.To); var transform = ent.PositionComp.WorldMatrixRef; var box = ent.PositionComp.LocalAABB; var obb = new MyOrientedBoundingBoxD(box, transform); if (lineCheck && obb.Intersects(ref extBeam) == null || !lineCheck && !obb.Intersects(ref p.PruneSphere)) { continue; } } var safeZone = ent as MySafeZone; if (safeZone != null && safeZone.Enabled) { var action = (Session.SafeZoneAction)safeZone.AllowedActions; if ((action & Session.SafeZoneAction.Damage) == 0) { bool intersects; if (safeZone.Shape == MySafeZoneShape.Sphere) { var sphere = new BoundingSphereD(safeZone.PositionComp.WorldVolume.Center, safeZone.Radius); var dist = ray.Intersects(sphere); intersects = dist != null && dist <= p.Beam.Length; } else { intersects = new MyOrientedBoundingBoxD(safeZone.PositionComp.LocalAABB, safeZone.PositionComp.WorldMatrixRef).Intersects(ref p.Beam) != null; } if (intersects) { p.State = Projectile.ProjectileState.Depleted; p.EarlyEnd = true; if (p.EnableAv) { p.Info.AvShot.ForceHitParticle = true; } break; } } } HitEntity hitEntity = null; var checkShield = Session.ShieldApiLoaded && Session.ShieldHash == ent.DefinitionId?.SubtypeId && ent.Render.Visible; MyTuple <IMyTerminalBlock, MyTuple <bool, bool, float, float, float, int>, MyTuple <MatrixD, MatrixD> >?shieldInfo = null; if (checkShield && (!shieldFullBypass && !p.ShieldBypassed || p.Info.EwarActive && (p.Info.ConsumableDef.Const.AreaEffect == DotField || p.Info.ConsumableDef.Const.AreaEffect == EmpField))) { shieldInfo = p.Info.System.Session.SApi.MatchEntToShieldFastExt(ent, true); if (shieldInfo != null && !myGrid.IsSameConstructAs(shieldInfo.Value.Item1.CubeGrid)) { if (p.Info.IsShrapnel || Vector3D.Transform(p.Info.Origin, shieldInfo.Value.Item3.Item1).LengthSquared() > 1) { p.EntitiesNear = true; var dist = MathFuncs.IntersectEllipsoid(shieldInfo.Value.Item3.Item1, shieldInfo.Value.Item3.Item2, new RayD(p.Beam.From, p.Beam.Direction)); if (p.Info.Target.IsProjectile && Vector3D.Transform(p.Info.Target.Projectile.Position, shieldInfo.Value.Item3.Item1).LengthSquared() <= 1) { projetileInShield = true; } if (dist != null && (dist.Value < p.Beam.Length || p.Info.EwarActive)) { if (shieldByPass) { p.ShieldBypassed = true; } hitEntity = HitEntityPool.Get(); hitEntity.EventType = Shield; hitEntity.HitPos = p.Beam.From + (p.Beam.Direction * dist.Value); hitEntity.HitDist = dist; } else { continue; } } } } var destroyable = ent as IMyDestroyableObject; var voxel = ent as MyVoxelBase; if (voxel != null && voxel == voxel?.RootVoxel) { if (ent == p.Info.MyPlanet && !(p.LinePlanetCheck || p.DynamicGuidance || p.CachedPlanetHit)) { continue; } VoxelIntersectBranch voxelState = VoxelIntersectBranch.None; Vector3D?voxelHit = null; if (tick - p.Info.VoxelCache.HitRefreshed < 60) { var cacheDist = ray.Intersects(p.Info.VoxelCache.HitSphere); if (cacheDist.HasValue && cacheDist.Value <= p.Beam.Length) { voxelHit = p.Beam.From + (p.Beam.Direction * cacheDist.Value); voxelState = VoxelIntersectBranch.PseudoHit1; } else if (cacheDist.HasValue) { p.Info.VoxelCache.MissSphere.Center = p.Beam.To; } } if (voxelState != VoxelIntersectBranch.PseudoHit1) { if (voxel == p.Info.MyPlanet && p.Info.VoxelCache.MissSphere.Contains(p.Beam.To) == ContainmentType.Disjoint) { if (p.LinePlanetCheck) { if (water != null && !p.Info.ConsumableDef.IgnoreWater) { var waterSphere = new BoundingSphereD(p.Info.MyPlanet.PositionComp.WorldAABB.Center, water.radius); var estiamtedSurfaceDistance = ray.Intersects(waterSphere); if (estiamtedSurfaceDistance.HasValue && estiamtedSurfaceDistance.Value <= p.Beam.Length) { var estimatedHit = ray.Position + (ray.Direction * estiamtedSurfaceDistance.Value); voxelHit = estimatedHit; voxelState = VoxelIntersectBranch.PseudoHit2; } } if (voxelState != VoxelIntersectBranch.PseudoHit2) { var surfacePos = p.Info.MyPlanet.GetClosestSurfacePointGlobal(ref p.Position); var planetCenter = p.Info.MyPlanet.PositionComp.WorldAABB.Center; double surfaceToCenter; Vector3D.DistanceSquared(ref surfacePos, ref planetCenter, out surfaceToCenter); double endPointToCenter; Vector3D.DistanceSquared(ref p.Position, ref planetCenter, out endPointToCenter); double startPointToCenter; Vector3D.DistanceSquared(ref p.Info.Origin, ref planetCenter, out startPointToCenter); var prevEndPointToCenter = p.PrevEndPointToCenterSqr; Vector3D.DistanceSquared(ref surfacePos, ref p.Position, out p.PrevEndPointToCenterSqr); if (surfaceToCenter > endPointToCenter || p.PrevEndPointToCenterSqr <= (p.Beam.Length * p.Beam.Length) || endPointToCenter > startPointToCenter && prevEndPointToCenter > p.DistanceToTravelSqr || surfaceToCenter > Vector3D.DistanceSquared(planetCenter, p.LastPosition)) { var estiamtedSurfaceDistance = ray.Intersects(p.Info.VoxelCache.PlanetSphere); var fullCheck = p.Info.VoxelCache.PlanetSphere.Contains(p.Info.Origin) != ContainmentType.Disjoint || !estiamtedSurfaceDistance.HasValue; if (!fullCheck && estiamtedSurfaceDistance.HasValue && (estiamtedSurfaceDistance.Value <= p.Beam.Length || p.Info.VoxelCache.PlanetSphere.Radius < 1)) { double distSqr; var estimatedHit = ray.Position + (ray.Direction * estiamtedSurfaceDistance.Value); Vector3D.DistanceSquared(ref p.Info.VoxelCache.FirstPlanetHit, ref estimatedHit, out distSqr); if (distSqr > 625) { fullCheck = true; } else { voxelHit = estimatedHit; voxelState = VoxelIntersectBranch.PseudoHit2; } } if (fullCheck) { voxelState = VoxelIntersectBranch.DeferFullCheck; } if (voxelHit.HasValue && Vector3D.DistanceSquared(voxelHit.Value, p.Info.VoxelCache.PlanetSphere.Center) > p.Info.VoxelCache.PlanetSphere.Radius * p.Info.VoxelCache.PlanetSphere.Radius) { p.Info.VoxelCache.GrowPlanetCache(voxelHit.Value); } } } } } else if (voxelHit == null && p.Info.VoxelCache.MissSphere.Contains(p.Beam.To) == ContainmentType.Disjoint) { voxelState = VoxelIntersectBranch.DeferedMissUpdate; } } if (voxelState == VoxelIntersectBranch.PseudoHit1 || voxelState == VoxelIntersectBranch.PseudoHit2) { if (!voxelHit.HasValue) { if (p.Info.VoxelCache.MissSphere.Contains(p.Beam.To) == ContainmentType.Disjoint) { p.Info.VoxelCache.MissSphere.Center = p.Beam.To; } continue; } hitEntity = HitEntityPool.Get(); var hitPos = voxelHit.Value; hitEntity.HitPos = hitPos; double dist; Vector3D.Distance(ref p.Beam.From, ref hitPos, out dist); hitEntity.HitDist = dist; hitEntity.EventType = Voxel; } else if (voxelState == VoxelIntersectBranch.DeferedMissUpdate || voxelState == VoxelIntersectBranch.DeferFullCheck) { DeferedVoxels.Add(new DeferedVoxels { Projectile = p, Branch = voxelState, Voxel = voxel }); } } else if (ent.Physics != null && !ent.Physics.IsPhantom && !ent.IsPreview && grid != null) { if (grid != null) { hitEntity = HitEntityPool.Get(); if (entIsSelf) { if (!p.Info.ConsumableDef.Const.IsBeamWeapon && p.Beam.Length <= grid.GridSize * 2) { MyCube cube; if (!(grid.TryGetCube(grid.WorldToGridInteger(p.Position), out cube) && cube.CubeBlock != p.Info.Target.FiringCube.SlimBlock || grid.TryGetCube(grid.WorldToGridInteger(p.LastPosition), out cube) && cube.CubeBlock != p.Info.Target.FiringCube.SlimBlock)) { HitEntityPool.Return(hitEntity); continue; } } if (!p.Info.EwarAreaPulse) { var forwardPos = p.Info.Age != 1 ? p.Beam.From : p.Beam.From + (p.Beam.Direction * Math.Min(grid.GridSizeHalf, p.Info.DistanceTraveled - p.Info.PrevDistanceTraveled)); grid.RayCastCells(forwardPos, p.Beam.To, hitEntity.Vector3ICache, null, true, true); if (hitEntity.Vector3ICache.Count > 0) { IHitInfo hitInfo; p.Info.System.Session.Physics.CastRay(forwardPos, p.Beam.To, out hitInfo, CollisionLayers.DefaultCollisionLayer); var hitGrid = hitInfo?.HitEntity?.GetTopMostParent() as MyCubeGrid; if (hitGrid == null || !myGrid.IsSameConstructAs(hitGrid)) { HitEntityPool.Return(hitEntity); continue; } hitEntity.HitPos = hitInfo.Position; hitEntity.Blocks.Add(grid.GetCubeBlock(hitEntity.Vector3ICache[0])); } } } else { grid.RayCastCells(p.Beam.From, p.Beam.To, hitEntity.Vector3ICache, null, true, true); } if (!ewarProjectile) { hitEntity.EventType = Grid; } else if (!p.Info.EwarAreaPulse) { hitEntity.EventType = Effect; } else { hitEntity.EventType = Field; } p.EntitiesNear = true; } } else if (destroyable != null) { hitEntity = HitEntityPool.Get(); hitEntity.EventType = Destroyable; } if (hitEntity != null) { p.FinalizeIntersection = true; hitEntity.Info = p.Info; hitEntity.Entity = hitEntity.EventType != Shield ? ent : (MyEntity)shieldInfo.Value.Item1; hitEntity.Intersection = p.Beam; hitEntity.SphereCheck = !lineCheck; hitEntity.PruneSphere = p.PruneSphere; hitEntity.SelfHit = entIsSelf; hitEntity.DamageOverTime = p.Info.ConsumableDef.Const.AreaEffect == DotField; p.Info.HitList.Add(hitEntity); } } if (p.Info.Target.IsProjectile && !p.Info.ConsumableDef.Const.EwarEffect && !projetileInShield) { var detonate = p.State == Projectile.ProjectileState.Detonate; var hitTolerance = detonate ? p.Info.ConsumableDef.Const.DetonationRadius : p.Info.ConsumableDef.Const.AreaEffectSize > p.Info.ConsumableDef.Const.CollisionSize ? p.Info.ConsumableDef.Const.AreaEffectSize : p.Info.ConsumableDef.Const.CollisionSize; var useLine = p.Info.ConsumableDef.Const.CollisionIsLine && !detonate && p.Info.ConsumableDef.Const.AreaEffectSize <= 0; var sphere = new BoundingSphereD(p.Info.Target.Projectile.Position, p.Info.Target.Projectile.Info.ConsumableDef.Const.CollisionSize); sphere.Include(new BoundingSphereD(p.Info.Target.Projectile.LastPosition, 1)); bool rayCheck = false; if (useLine) { var dist = sphere.Intersects(new RayD(p.LastPosition, p.Info.Direction)); if (dist <= hitTolerance || p.Info.ConsumableDef.Const.IsBeamWeapon && dist <= p.Beam.Length) { rayCheck = true; } } var testSphere = p.PruneSphere; testSphere.Radius = hitTolerance; if (rayCheck || sphere.Intersects(testSphere)) { ProjectileHit(p, p.Info.Target.Projectile, lineCheck, ref p.Beam); } } if (!useEntityCollection) { p.MySegmentList.Clear(); } else if (p.CheckType == Projectile.CheckTypes.Sphere) { entityCollection.Clear(); } if (p.FinalizeIntersection) { FinalHitCheck.Add(p); } }, stride); ValidateHits.ClearImmediate(); }
private static void PushPull(HitEntity hitEnt, ProInfo info) { var depletable = info.AmmoDef.AreaEffect.EwarFields.Depletable; var healthPool = depletable && info.BaseHealthPool > 0 ? info.BaseHealthPool : float.MaxValue; if (healthPool <= 0) { return; } if (hitEnt.Entity.Physics == null || !hitEnt.Entity.Physics.Enabled || hitEnt.Entity.Physics.IsStatic || !hitEnt.HitPos.HasValue) { return; } var forceDef = info.AmmoDef.AreaEffect.EwarFields.Force; Vector3D forceFrom = Vector3D.Zero; Vector3D forceTo = Vector3D.Zero; Vector3D forcePosition = Vector3D.Zero; if (forceDef.ForceFrom == Force.ProjectileLastPosition) { forceFrom = hitEnt.Intersection.From; } else if (forceDef.ForceFrom == Force.ProjectileOrigin) { forceFrom = info.Origin; } else if (forceDef.ForceFrom == Force.HitPosition) { forceFrom = hitEnt.HitPos.Value; } else if (forceDef.ForceFrom == Force.TargetCenter) { forceFrom = hitEnt.Entity.PositionComp.WorldAABB.Center; } else if (forceDef.ForceFrom == Force.TargetCenterOfMass) { forceFrom = hitEnt.Entity.Physics.CenterOfMassWorld; } if (forceDef.ForceTo == Force.ProjectileLastPosition) { forceTo = hitEnt.Intersection.From; } else if (forceDef.ForceTo == Force.ProjectileOrigin) { forceTo = info.Origin; } else if (forceDef.ForceTo == Force.HitPosition) { forceTo = hitEnt.HitPos.Value; } else if (forceDef.ForceTo == Force.TargetCenter) { forceTo = hitEnt.Entity.PositionComp.WorldAABB.Center; } else if (forceDef.ForceTo == Force.TargetCenterOfMass) { forceTo = hitEnt.Entity.Physics.CenterOfMassWorld; } if (forceDef.Position == Force.ProjectileLastPosition) { forcePosition = hitEnt.Intersection.From; } else if (forceDef.Position == Force.ProjectileOrigin) { forcePosition = info.Origin; } else if (forceDef.Position == Force.HitPosition) { forcePosition = hitEnt.HitPos.Value; } else if (forceDef.Position == Force.TargetCenter) { forcePosition = hitEnt.Entity.PositionComp.WorldAABB.Center; } else if (forceDef.Position == Force.TargetCenterOfMass) { forcePosition = hitEnt.Entity.Physics.CenterOfMassWorld; } var hitDir = forceTo - forceFrom; Vector3D normHitDir; Vector3D.Normalize(ref hitDir, out normHitDir); normHitDir = info.AmmoDef.Const.AreaEffect == PushField ? normHitDir : -normHitDir; if (info.System.Session.IsServer) { hitEnt.Entity.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, normHitDir * (info.AmmoDef.Const.AreaEffectDamage * hitEnt.Entity.Physics.Mass), forcePosition, Vector3.Zero); } if (depletable) { info.BaseHealthPool -= healthPool; } }
private void UpdateEffect(HitEntity hitEnt, ProInfo info) { var grid = hitEnt.Entity as MyCubeGrid; if (grid == null || grid.MarkedForClose) { return; } Dictionary <AreaEffectType, GridEffect> effects; var attackerId = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass ? grid.EntityId : info.Target.FiringCube.EntityId; var found = false; if (_gridEffects.TryGetValue(grid, out effects)) { GridEffect gridEffect; if (effects.TryGetValue(info.AmmoDef.AreaEffect.AreaEffect, out gridEffect)) { found = true; gridEffect.Damage += info.AreaEffectDamage; gridEffect.Ai = info.Ai; gridEffect.AttackerId = attackerId; gridEffect.Hits++; if (hitEnt.HitPos != null) { gridEffect.HitPos = hitEnt.HitPos.Value / gridEffect.Hits; } } } if (!found) { if (effects == null) { effects = GridEffectsPool.Get(); } GridEffect gridEffect; if (effects.TryGetValue(info.AmmoDef.AreaEffect.AreaEffect, out gridEffect)) { gridEffect.Damage += info.AreaEffectDamage; gridEffect.Ai = info.Ai; gridEffect.AmmoDef = info.AmmoDef; gridEffect.AttackerId = attackerId; gridEffect.Hits++; if (hitEnt.HitPos != null) { gridEffect.HitPos += hitEnt.HitPos.Value / gridEffect.Hits; } } else { gridEffect = GridEffectPool.Get(); gridEffect.System = info.System; gridEffect.Damage = info.AreaEffectDamage; gridEffect.Ai = info.Ai; gridEffect.AmmoDef = info.AmmoDef; gridEffect.AttackerId = attackerId; gridEffect.Hits++; if (hitEnt.HitPos != null) { gridEffect.HitPos = hitEnt.HitPos.Value; } effects.Add(info.AmmoDef.AreaEffect.AreaEffect, gridEffect); } _gridEffects.Add(grid, effects); } info.BaseHealthPool = 0; info.BaseDamagePool = 0; }
internal int GetEntityCompareDist(HitEntity x, HitEntity y, ProInfo info) { var xDist = double.MaxValue; var yDist = double.MaxValue; var beam = x.Intersection; var count = y != null ? 2 : 1; var eWarPulse = info.ConsumableDef.Const.Ewar && info.ConsumableDef.Const.Pulse; var triggerEvent = eWarPulse && !info.EwarAreaPulse && info.ConsumableDef.Const.EwarTriggerRange > 0; for (int i = 0; i < count; i++) { var isX = i == 0; MyEntity ent; HitEntity hitEnt; HitEntity otherHit; if (isX) { hitEnt = x; otherHit = y; ent = hitEnt.Entity; } else { hitEnt = y; otherHit = x; ent = hitEnt.Entity; } var dist = double.MaxValue; var shield = ent as IMyTerminalBlock; var grid = ent as MyCubeGrid; var voxel = ent as MyVoxelBase; if (triggerEvent && (info.Ai.Targets.ContainsKey(ent) || shield != null)) { hitEnt.PulseTrigger = true; } else if (hitEnt.Projectile != null) { dist = hitEnt.HitDist.Value; } else if (shield != null) { hitEnt.Hit = true; dist = hitEnt.HitDist.Value; } else if (grid != null) { if (hitEnt.Hit) { dist = Vector3D.Distance(hitEnt.Intersection.From, hitEnt.HitPos.Value); hitEnt.HitDist = dist; } else if (hitEnt.HitPos != null) { dist = Vector3D.Distance(hitEnt.Intersection.From, hitEnt.HitPos.Value); hitEnt.HitDist = dist; hitEnt.Hit = true; } else { if (hitEnt.SphereCheck || info.EwarActive && eWarPulse) { var ewarActive = hitEnt.EventType == Field || hitEnt.EventType == Effect; var hitPos = !ewarActive ? hitEnt.PruneSphere.Center + (hitEnt.Intersection.Direction * hitEnt.PruneSphere.Radius) : hitEnt.PruneSphere.Center; if (hitEnt.SelfHit && Vector3D.DistanceSquared(hitPos, hitEnt.Info.Origin) <= grid.GridSize * grid.GridSize) { continue; } if (!ewarActive) { GetAndSortBlocksInSphere(hitEnt.Info.ConsumableDef, hitEnt.Info.System, grid, hitEnt.PruneSphere, false, hitEnt.Blocks); } if (hitEnt.Blocks.Count > 0 || ewarActive) { dist = 0; hitEnt.HitDist = dist; hitEnt.Hit = true; hitEnt.HitPos = hitPos; } } else { var closestBlockFound = false; for (int j = 0; j < hitEnt.Vector3ICache.Count; j++) { var firstBlock = grid.GetCubeBlock(hitEnt.Vector3ICache[j]) as IMySlimBlock; MatrixD transform = grid.WorldMatrix; if (firstBlock != null && !firstBlock.IsDestroyed && firstBlock != hitEnt.Info.Target.FiringCube.SlimBlock) { hitEnt.Blocks.Add(firstBlock); if (closestBlockFound) { continue; } MyOrientedBoundingBoxD obb; var fat = firstBlock.FatBlock; if (fat != null) { obb = new MyOrientedBoundingBoxD(fat.Model.BoundingBox, fat.PositionComp.WorldMatrixRef); } else { Vector3 halfExt; firstBlock.ComputeScaledHalfExtents(out halfExt); var blockBox = new BoundingBoxD(-halfExt, halfExt); transform.Translation = grid.GridIntegerToWorld(firstBlock.Position); obb = new MyOrientedBoundingBoxD(blockBox, transform); } var hitDist = obb.Intersects(ref beam) ?? Vector3D.Distance(beam.From, obb.Center); var hitPos = beam.From + (beam.Direction * hitDist); if (hitEnt.SelfHit) { if (Vector3D.DistanceSquared(hitPos, hitEnt.Info.Origin) <= grid.GridSize * 3) { hitEnt.Blocks.Clear(); } else { dist = hitDist; hitEnt.HitDist = dist; hitEnt.Hit = true; hitEnt.HitPos = hitPos; } break; } dist = hitDist; hitEnt.HitDist = dist; hitEnt.Hit = true; hitEnt.HitPos = hitPos; closestBlockFound = true; } } } } } else if (voxel != null) { hitEnt.Hit = true; dist = hitEnt.HitDist.Value; hitEnt.HitDist = dist; } else if (ent is IMyDestroyableObject) { if (hitEnt.Hit) { dist = Vector3D.Distance(hitEnt.Intersection.From, hitEnt.HitPos.Value); } else { if (hitEnt.SphereCheck || info.EwarActive && eWarPulse) { var ewarActive = hitEnt.EventType == Field || hitEnt.EventType == Effect; dist = 0; hitEnt.HitDist = dist; hitEnt.Hit = true; var hitPos = !ewarActive ? hitEnt.PruneSphere.Center + (hitEnt.Intersection.Direction * hitEnt.PruneSphere.Radius) : hitEnt.PruneSphere.Center; hitEnt.HitPos = hitPos; } else { var transform = ent.PositionComp.WorldMatrixRef; var box = ent.PositionComp.LocalAABB; var obb = new MyOrientedBoundingBoxD(box, transform); dist = obb.Intersects(ref beam) ?? double.MaxValue; if (dist < double.MaxValue) { hitEnt.Hit = true; hitEnt.HitPos = beam.From + (beam.Direction * dist); hitEnt.HitDist = dist; } } } } if (isX) { xDist = dist; } else { yDist = dist; } } return(xDist.CompareTo(yDist)); }
private void DamageVoxel(HitEntity hitEnt, ProInfo info, bool canDamage) { var entity = hitEnt.Entity; var destObj = hitEnt.Entity as MyVoxelBase; if (destObj == null || entity == null || !hitEnt.HitPos.HasValue) { return; } var shieldHeal = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Heal; if (!info.AmmoDef.Const.VoxelDamage || shieldHeal) { info.BaseDamagePool = 0; return; } using (destObj.Pin()) { var detonateOnEnd = info.AmmoDef.Const.AmmoAreaEffect && info.AmmoDef.AreaEffect.Detonation.DetonateOnEnd && info.AmmoDef.AreaEffect.AreaEffect != AreaEffectType.Radiant; info.ObjectsHit++; float damageScale = 1; if (info.AmmoDef.Const.VirtualBeams) { damageScale *= info.WeaponCache.Hits; } var scaledDamage = info.BaseDamagePool * damageScale; var fallOff = info.AmmoDef.Const.FallOffScaling && info.DistanceTraveled > info.AmmoDef.DamageScales.FallOff.Distance; if (fallOff) { var fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((info.DistanceTraveled - info.AmmoDef.DamageScales.FallOff.Distance) / (info.AmmoDef.Const.MaxTrajectory - info.AmmoDef.DamageScales.FallOff.Distance)), info.AmmoDef.DamageScales.FallOff.MinMultipler, 1); scaledDamage *= fallOffMultipler; } var oRadius = info.AmmoDef.AreaEffect.AreaEffectRadius; var minTestRadius = info.DistanceTraveled - info.PrevDistanceTraveled; var tRadius = oRadius < minTestRadius ? minTestRadius : oRadius; var objHp = (int)MathHelper.Clamp(MathFuncs.VolumeCube(MathFuncs.LargestCubeInSphere(tRadius)), 5000, double.MaxValue); if (tRadius > 5) { objHp *= 5; } if (scaledDamage < objHp) { var reduceBy = objHp / scaledDamage; oRadius /= reduceBy; if (oRadius < 1) { oRadius = 1; } info.BaseDamagePool = 0; } else { info.BaseDamagePool -= objHp; if (oRadius < minTestRadius) { oRadius = minTestRadius; } } destObj.PerformCutOutSphereFast(hitEnt.HitPos.Value, (float)oRadius, true); //Log.Line($"TestHealth: {objHp} - tRadius:{tRadius} - oRadius:{oRadius} - travel:{minTestRadius} - base:{info.BaseDamagePool} - det:{detonateOnEnd}"); if (detonateOnEnd && info.BaseDamagePool <= 0) { var det = info.AmmoDef.AreaEffect.Detonation; var dRadius = det.DetonationRadius; var dDamage = det.DetonationDamage; //var dObjHp = (int)MathHelper.Clamp(MathFuncs.VolumeCube(MathFuncs.LargestCubeInSphere(dRadius)), 5000, double.MaxValue); //if (dRadius > 5) dObjHp *= 5; //dObjHp *= 5; //var reduceBy = dObjHp / dDamage; //dRadius /= reduceBy; if (dRadius < 1.5) { dRadius = 1.5f; } //Log.Line($"radius: {det.DetonationRadius} - dRadius:{dRadius} - reduceBy:{reduceBy} - dObjHp:{dObjHp}"); if (canDamage) { //destObj.PerformCutOutSphereFast(hitEnt.HitPos.Value, dRadius, true); SUtils.CreateMissileExplosion(this, dDamage, dRadius, hitEnt.HitPos.Value, hitEnt.Intersection.Direction, info.Target.FiringCube, destObj, info.AmmoDef, true); } } } }