public bool ExtractData(GetDataEventArgs args, MemoryStream data, PvPPlayer attacker, out ProjectileNewArgs arg) { arg = null; if (PresetData.ProjectileDummy.Contains(Type)) { return(false); } arg = new ProjectileNewArgs { Args = args, Attacker = attacker, Identity = data.ReadInt16(), Position = new Vector2(data.ReadSingle(), data.ReadSingle()), Velocity = new Vector2(data.ReadSingle(), data.ReadSingle()), Knockback = data.ReadSingle(), Damage = data.ReadInt16(), Owner = data.ReadByte(), Type = data.ReadInt16(), AiFlags = (BitsByte)data.ReadByte(), Ai0 = AiFlags[0] ? Ai0 = data.ReadSingle() : 0, Ai1 = AiFlags[1] ? data.ReadSingle() : 0, Ai = new float[Projectile.maxAI], Proj = new PvPProjectile(Type, Identity), Weapon = ProjectileUtils.GetProjectileWeapon(attacker, Type) }; return(true); }
void OnDrawGizmos() { // Positions of this object and the target on the same plane Vector3 planarTarget = new Vector3(target.position.x, 0, target.position.z); Vector3 planarPostion = new Vector3(transform.position.x, 0, transform.position.z); // Planar distance between objects distance = Vector3.Distance(planarTarget, planarPostion); // Distance along the y axis between objects float yOffset = transform.position.y - target.position.y; speed = ProjectileUtils.LaunchSpeed(distance, yOffset, 9.8f, angle * Mathf.Deg2Rad); Vector3 velocity = new Vector3(0, speed * Mathf.Sin(angle * Mathf.Deg2Rad), speed * Mathf.Cos(angle * Mathf.Deg2Rad)); float angleBetweenObjects = Vector3.SignedAngle(Vector3.forward, planarTarget - planarPostion, Vector3.up); Vector3 finalVelocity = Quaternion.AngleAxis(angleBetweenObjects, Vector3.up) * velocity; Gizmos.DrawLine(transform.position, transform.position + finalVelocity); Vector3 lastPosition = transform.position; for (float t = 0.0f; t < 10.0f; t += 0.05f) { Vector3 nextPosition = transform.position + finalVelocity * t + Vector3.down * (9.8f / 2.0f) * t * t; Gizmos.DrawLine(lastPosition, nextPosition); lastPosition = nextPosition; } }
/* * public void Observe(SlugEvents ev) { * if (ev == SlugEvents.HitGround) { * bounceCount++; * ZRotationStepCurrent *= 2; * if (bounceCount >= bouncesToExplode) { * Explode(); * } * } * } */ private void Explode(Collider2D col) { ProjectileUtils.ImpactAnimationAndSound(transform, col, properties); ProjectileUtils.NotifyCollider(col, properties); explosionWave.CastAOE("enemy", transform.position); gameObject.SetActive(false); }
public ProjectileNewArgs(GetDataEventArgs args, MemoryStream data, PvPPlayer attacker) { Args = args; Attacker = attacker; Identity = data.ReadInt16(); Position = new Vector2(data.ReadSingle(), data.ReadSingle()); Velocity = new Vector2(data.ReadSingle(), data.ReadSingle()); Knockback = data.ReadSingle(); Damage = data.ReadInt16(); Owner = data.ReadByte(); Type = data.ReadInt16(); AiFlags = (BitsByte)data.ReadByte(); Ai0 = 0; Ai1 = 0; if (AiFlags[0]) { Ai0 = data.ReadSingle(); } if (AiFlags[1]) { Ai1 = data.ReadSingle(); } Ai = new float[Projectile.maxAI]; Weapon = ProjectileUtils.GetProjectileWeapon(attacker, Type); }
void Update() { if (launched) { ProjectileUtils.UpdatePositionStraightLine(transform, properties); } }
public void OnTriggerEnter2D(Collider2D col) { if (col.tag == properties.victimTag) { ProjectileUtils.ImpactAnimationAndSound(transform, col, properties); ProjectileUtils.NotifyCollider(col, properties); gameObject.SetActive(false); } }
private void Explode(Collider2D col) { explosion.gameObject.SetActive(true); explosion.transform.position = this.transform.position; explosion.Play("1"); //ProjectileUtils.ImpactAnimationAndSound(transform, col, properties); ProjectileUtils.NotifyCollider(col, properties); gameObject.SetActive(false); }
// Update is called once per frame void Update() { Vector3 force = transform.forward * transform.localScale.z; RaycastHit hit; if (ProjectileUtils.BallisticCast(transform.position, force, out hit, precision)) { hitPosition = hit.point; } }
private void Explode(Collider2D col = null) { explosion.transform.position = this.transform.position; explosion.gameObject.SetActive(true); if (col != null) { ProjectileUtils.NotifyCollider(col, properties); } flash.ResetMaterial(); gameObject.SetActive(false); }
/// <summary> /// This method will calculate if there is valid line of sight between the explosion origin and the specific Part /// In order to avoid collisions with the same missile part, It will not take into account those parts beloging to same vessel that contains the explosive part /// </summary> /// <param name="part"></param> /// <param name="explosivePart"></param> /// <param name="hit"> out property with the actual hit</param> /// <returns></returns> private bool IsInLineOfSight(Part part, Part explosivePart, out RaycastHit hit, out float distance, out List <Tuple <float, float, float> > intermediateParts) { Ray partRay = new Ray(Position, part.transform.position - Position); var hitCount = Physics.RaycastNonAlloc(partRay, lineOfSightHits, Range, 9076737); if (hitCount == lineOfSightHits.Length) // If there's a whole bunch of stuff in the way (unlikely), then we need to increase the size of our hits buffer. { lineOfSightHits = Physics.RaycastAll(partRay, Range, 9076737); hitCount = lineOfSightHits.Length; } intermediateParts = new List <Tuple <float, float, float> >(); using (var hitsEnu = lineOfSightHits.Take(hitCount).OrderBy(x => x.distance).GetEnumerator()) while (hitsEnu.MoveNext()) { Part partHit = hitsEnu.Current.collider.GetComponentInParent <Part>(); if (partHit == null) { continue; } if (ProjectileUtils.IsIgnoredPart(partHit)) { continue; // Ignore ignored parts. } hit = hitsEnu.Current; distance = hit.distance; if (partHit == part) { return(true); } if (partHit != part) { // ignoring collisions against the explosive if (explosivePart != null && partHit.vessel == explosivePart.vessel) { continue; } if (FlightGlobals.currentMainBody != null && hit.collider.gameObject == FlightGlobals.currentMainBody.gameObject) { return(false); // Terrain hit. Full absorption. Should avoid NREs in the following. } var partHP = partHit.Damage(); var partArmour = partHit.GetArmorThickness(); if (partHP > 0) // Ignore parts that are already dead but not yet removed from the game. { intermediateParts.Add(new Tuple <float, float, float>(hit.distance, partHP, partArmour)); } } } hit = new RaycastHit(); distance = 0; return(false); }
private void SetupTransition() { Service.UXController.HUD.Visible = false; if (this.battleData.BattleType == BattleType.PveDefend) { List <IAssetVO> battleProjectileAssets = ProjectileUtils.GetBattleProjectileAssets(Service.CurrentPlayer.Map, this.battleData.BattleVO, this.battleData.AttackerDeployableData, null, null, null, null, this.battleData.AttackerEquipment, this.battleData.DefenderEquipment); Service.SpecialAttackController.PreloadSpecialAttackMiscAssets(); Service.ProjectileViewManager.LoadProjectileAssetsAndCreatePools(battleProjectileAssets); Service.GameStateMachine.SetState(this); this.OnWorldLoadComplete(); Service.EventManager.SendEvent(EventId.BattleLoadedForDefend, this.battleData); this.OnWorldTransitionComplete(); return; } IMapDataLoader mapDataLoader; if (this.battleData.PvpTarget != null) { mapDataLoader = Service.PvpMapDataLoader; ((PvpMapDataLoader)mapDataLoader).Initialize(this.battleData); } else if (this.battleData.MemberWarData != null) { mapDataLoader = Service.WarBaseMapDataLoader; ((WarBaseMapDataLoader)mapDataLoader).Initialize(this.battleData); } else { mapDataLoader = Service.NpcMapDataLoader; bool isPveBuffBase = this.battleData.BattleType == BattleType.PveBuffBase; ((NpcMapDataLoader)mapDataLoader).Initialize(this.battleData, isPveBuffBase); } EventManager eventManager = Service.EventManager; eventManager.RegisterObserver(this, EventId.MapDataProcessingStart, EventPriority.Default); eventManager.RegisterObserver(this, EventId.WorldLoadComplete, EventPriority.Default); WorldTransitioner worldTransitioner = Service.WorldTransitioner; if (worldTransitioner.IsSoftWiping()) { worldTransitioner.ContinueWipe(this, mapDataLoader, new TransitionCompleteDelegate(this.OnWorldTransitionComplete)); } else if (this.battleData.BattleType == BattleType.PvpAttackSquadWar || this.battleData.BattleType == BattleType.PveBuffBase) { worldTransitioner.StartTransition(new WarboardToWarbaseTransition(this, mapDataLoader, new TransitionCompleteDelegate(this.OnWorldTransitionComplete), false, false)); } else { worldTransitioner.StartTransition(new WorldToWorldTransition(this, mapDataLoader, new TransitionCompleteDelegate(this.OnWorldTransitionComplete), false, false)); } }
public void OnTriggerEnter2D(Collider2D col) { if (col.tag == "Player") { if (properties.explosionAnimator != null) { ProjectileUtils.ImpactAnimationAndSound(transform, col, properties); } ProjectileUtils.NotifyCollider(col, properties); // NO WE DONT DO THAT FOR BREATH OR ANY AOE PROJ gameObject.SetActive(false); // 2 types de proj se distingue les aoe (leurs effets dure sur la duree et sur un espace) // et les non aoe (bullets) } }
public List <IAssetVO> GetProjectilePreloads(Map map) { List <string> attackerWarBuffs = null; List <string> defenderWarBuffs = null; Squad currentSquad = Service.SquadController.StateManager.GetCurrentSquad(); if (currentSquad != null) { SquadWarManager warManager = Service.SquadController.WarManager; attackerWarBuffs = warManager.GetBuffBasesOwnedBySquad(currentSquad.SquadID); defenderWarBuffs = warManager.GetBuffBasesOwnedBySquad(this.squadId); } return(ProjectileUtils.GetBattleProjectileAssets(map, null, null, attackerWarBuffs, defenderWarBuffs, this.defenderSquadTroops, this.defenderChampions, this.battleData.AttackerEquipment, this.battleData.DefenderEquipment)); }
public override void Execute() { base.Execute(); IntPosition position = new IntPosition(Units.GridToBoardX(this.gridX), Units.GridToBoardZ(this.gridZ)); IDataController dataController = Service.Get <IDataController>(); List <IAssetVO> assets = new List <IAssetVO>(); ProjectileUtils.AddTroopProjectileAssets(this.troopUid, assets, dataController); Service.Get <ProjectileViewManager>().LoadProjectileAssetsAndCreatePools(assets); TroopTypeVO troop = dataController.Get <TroopTypeVO>(this.troopUid); TroopSpawnData troopSpawnData = new TroopSpawnData(troop, position, TroopSpawnMode.LeashedToSpawnPoint, this.amount); Service.Get <SimTimerManager>().CreateSimTimer(1500u, false, new TimerDelegate(this.OnSpawnTimer), troopSpawnData); this.parent.ChildComplete(this); }
private bool tryHitTarget(RangedAttackAbility rangedAttack, Vector3 position, Frame target, out Vector3 force, int steps) { float velocity = rangedAttack.weapon.range / 2.0f; float velocityStep = velocity / (float)steps; Vector3 direction = target.position - position; direction.y = 0.0f; float distance = direction.magnitude; direction.Normalize(); for (int i = 0; i < steps + 1; i++) { if (ProjectileUtils.canHitCoordinate(distance, 0.0f, velocity)) { float angle1 = ProjectileUtils.calculateAngle1ToHitCoordinate(distance, 0.0f, velocity); float angle2 = ProjectileUtils.calculateAngle2ToHitCoordinate(distance, 0.0f, velocity); if (ProjectileUtils.tryHitWithBallisticCast(target, position, velocity * direction, angle1, out force)) { return(true); } if (ProjectileUtils.tryHitWithBallisticCast(target, position, velocity * direction, angle2, out force)) { return(true); } if (!hasFallback) { fallbackPosition = position; fallBackVelocity = force; hasFallback = true; } } velocity += velocityStep; } force = Vector3.negativeInfinity; return(false); }
private void LoadBulletAssets(Bullet bullet) { IDataController dc = Service.Get <IDataController>(); List <IAssetVO> list = new List <IAssetVO>(); ProjectileUtils.AddProjectileAssets(bullet.ProjectileType, list, dc); if (bullet.AppliedBuffs != null) { int i = 0; int count = bullet.AppliedBuffs.Count; while (i < count) { list.Add(bullet.AppliedBuffs[i].BuffType); i++; } } this.LoadProjectileAssetsAndCreatePools(list); }
public override void Execute() { base.Execute(); Vector3 zero = Vector3.zero; zero.x = Units.BoardToWorldX(this.boardX); zero.z = Units.BoardToWorldX(this.boardZ); IDataController dataController = Service.Get <IDataController>(); SpecialAttackTypeVO specialAttackTypeVO = dataController.Get <SpecialAttackTypeVO>(this.prepareArgs[0]); SpecialAttack specialAttack = Service.Get <SpecialAttackController>().DeploySpecialAttack(specialAttackTypeVO, TeamType.Attacker, zero); if (specialAttack != null) { List <IAssetVO> assets = new List <IAssetVO>(); ProjectileUtils.AddProjectileAssets(specialAttackTypeVO.ProjectileType, assets, dataController); Service.Get <ProjectileViewManager>().LoadProjectileAssetsAndCreatePools(assets); Service.Get <EventManager>().SendEvent(EventId.SpecialAttackDeployed, specialAttack); } this.parent.ChildComplete(this); }
public void OnTriggerEnter2D(Collider2D col) { if (col.tag == properties.victimTag || col.tag == "World") { ProjectileUtils.RandomizeImpactPosition(transform, impactAnimator.transform); impactAnimator.gameObject.SetActive(true); if (col.tag == "World") { impactAnimator.transform.right = transform.right; impactAnimator.Play("2"); } else { impactAnimator.Play("1"); ProjectileUtils.NotifyCollider(col, properties); } gameObject.SetActive(false); } }
public static bool tryHitWithBallisticCast(Frame target, Vector3 position, Vector3 velocity, float angle, out Vector3 force) { force = Vector3.RotateTowards(velocity, Vector3.up, angle, 0.0f); // Cast the ballistic curve to see, if it hits the target, otherwise, keep looking! RaycastHit hit; if (ProjectileUtils.BallisticCast(position, force, out hit)) { Frame d = hit.collider.GetComponent <Frame>(); if (d == target) { return(true); } } return(false); }
public override void AI() { int num1 = Dust.NewDust(projectile.position, projectile.width, projectile.height, 15, projectile.velocity.X * 0.5f, projectile.velocity.Y * 0.5f); Main.dust[num1].noGravity = true; Main.dust[num1].velocity *= 0.9f; if (projectile.timeLeft <= 300f || (ProjectileUtils.CountProjectiles(projectile.type) > 1 && ProjectileUtils.HasLeastTimeleft(projectile.whoAmI))) { projectile.alpha += 5; if (projectile.alpha > 255) { projectile.alpha = 255; projectile.Kill(); } } projectile.localAI[1]--; if (projectile.owner == Main.myPlayer) { float max = 400f; for (int i = 0; i < Main.npc.Length; i++) { NPC nPC = Main.npc[i]; if (nPC.active && !nPC.friendly && nPC.damage > 0 && !nPC.dontTakeDamage && Vector2.Distance(projectile.Center, nPC.Center) <= max) { float Speed = 9f; float rotation = (float)Math.Atan2(projectile.Center.Y - nPC.Center.Y, projectile.Center.X - nPC.Center.X); if (projectile.localAI[1] <= 0) { Vector2 speed = new Vector2((float)((Math.Cos(rotation) * Speed) * -1), (float)((Math.Sin(rotation) * Speed) * -1)); //Main.PlaySound(2, (int)projectile.position.X, (int)projectile.position.Y, 12); Projectile.NewProjectile(projectile.Center.X, projectile.Center.Y, speed.X, speed.Y, mod.ProjectileType("LightningBlast"), projectile.damage, projectile.knockBack, projectile.owner); projectile.localAI[1] = Main.rand.Next(16, 60); } } } } }
private Vector3 getVelocityForTarget(Vector3 position, Vector3 target, float initialAngle) { float gravity = GameSettings.gravity; // Selected angle in radians float angle = initialAngle * Mathf.Deg2Rad; // Positions of this object and the target on the same plane Vector3 planarTarget = new Vector3(target.x, 0, target.z); Vector3 planarPostion = new Vector3(position.x, 0, position.z); // Planar distance between objects float distance = Vector3.Distance(planarTarget, planarPostion); // Distance along the y axis between objects float yOffset = position.y - target.y; float speed = ProjectileUtils.LaunchSpeed(distance, yOffset, gravity, angle); Vector3 velocity = new Vector3(0, speed * Mathf.Sin(angle), speed * Mathf.Cos(angle)); float angleBetweenObjects = Vector3.SignedAngle(Vector3.forward, planarTarget - planarPostion, Vector3.up); timeOfFlight = ProjectileUtils.TimeOfFlight(speed, angle, yOffset, gravity); return(Quaternion.AngleAxis(angleBetweenObjects, Vector3.up) * velocity); }
public List <IAssetVO> GetProjectilePreloads(Map map) { List <string> attackerWarBuffs = null; List <string> defenderWarBuffs = null; if (this.isPveBuffBase) { Squad currentSquad = Service.Get <SquadController>().StateManager.GetCurrentSquad(); if (currentSquad != null) { SquadWarManager warManager = Service.Get <SquadController>().WarManager; attackerWarBuffs = warManager.GetBuffBasesOwnedBySquad(currentSquad.SquadID); } } List <string> attackerEquipment = null; List <string> defenderEquipment = null; if (this.battleData != null) { attackerEquipment = this.battleData.AttackerEquipment; defenderEquipment = this.battleData.DefenderEquipment; } return(ProjectileUtils.GetBattleProjectileAssets(map, this.battle, null, attackerWarBuffs, defenderWarBuffs, null, null, attackerEquipment, defenderEquipment)); }
public void CastAOE(string victimsTag, Vector2 pos) { Vector2 center = new Vector2(pos.x - transform.right.x * (boxSize.x / 2) + boxOffset.x * transform.right.x, pos.y - (boxSize.y / 2) + boxOffset.y); float duration = 1.5f; Debug.DrawLine(center, new Vector2(center.x, center.y + boxSize.y), Color.red, duration); Debug.DrawLine(center, new Vector2(center.x + boxSize.x * transform.right.x, center.y), Color.blue, duration); Debug.DrawLine(new Vector2(center.x + boxSize.x * transform.right.x, center.y), new Vector2(center.x + boxSize.x * transform.right.x, center.y + boxSize.y), Color.cyan, duration); Vector2 centre = new Vector2(pos.x + boxOffset.x * transform.right.x, pos.y + boxOffset.y); RaycastHit2D[] hits = Physics2D.BoxCastAll(centre, boxSize, 0, transform.right, 0, layerMask); for (int i = 0; i < hits.Length; i++) { if (hits[i].collider.tag == victimsTag) { ProjectileUtils.NotifyCollider(hits[i].collider, projectileProp); } } }
void FixedUpdate() { if (!gameObject.activeInHierarchy) { return; } //floating origin and velocity offloading corrections if (!FloatingOrigin.Offset.IsZero() || !Krakensbane.GetFrameVelocity().IsZero()) { transform.position -= FloatingOrigin.OffsetNonKrakensbane; prevPosition -= FloatingOrigin.OffsetNonKrakensbane; startPosition -= FloatingOrigin.OffsetNonKrakensbane; } distanceFromStart = Vector3.Distance(transform.position, startPosition); if (Time.time - startTime < stayTime && transform.parent != null) { transform.rotation = transform.parent.rotation; transform.position = spawnTransform.position; //+(transform.parent.rigidbody.velocity*Time.fixedDeltaTime); } else { if (transform.parent != null && parentRB) { transform.parent = null; rb.isKinematic = false; rb.velocity = parentRB.velocity + Krakensbane.GetFrameVelocityV3f(); } } if (rb && !rb.isKinematic) { //physics if (FlightGlobals.RefFrameIsRotating) { rb.velocity += FlightGlobals.getGeeForceAtPosition(transform.position) * Time.fixedDeltaTime; } //guidance and attitude stabilisation scales to atmospheric density. float atmosMultiplier = Mathf.Clamp01(2.5f * (float) FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(transform.position), FlightGlobals.getExternalTemperature(), FlightGlobals.currentMainBody)); //model transform. always points prograde transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(rb.velocity + Krakensbane.GetFrameVelocity(), transform.up), atmosMultiplier * (0.5f * (Time.time - startTime)) * 50 * Time.fixedDeltaTime); if (Time.time - startTime < thrustTime && Time.time - startTime > stayTime) { thrustVector.x = randomThrustDeviation * (1 - (Mathf.PerlinNoise(4 * Time.time, randThrustSeed) * 2)) / massScalar; //this needs to scale w/ rocket mass, or light projectiles will be thrustVector.y = randomThrustDeviation * (1 - (Mathf.PerlinNoise(randThrustSeed, 4 * Time.time) * 2)) / massScalar; //far more affected than heavier ones rb.AddRelativeForce(thrustVector); }//0.012/rocketmass - use .012 as baseline, it's the mass of hte hydra, which the randomTurstdeviation was originally calibrated for } if (Time.time - startTime > thrustTime) { foreach (var pe in pEmitters) { if (pe != null) { pe.emit = false; } } } if (Time.time - startTime > 0.1f + stayTime) { hasPenetrated = true; hasDetonated = false; penTicker = 0; currPosition = transform.position; float dist = (currPosition - prevPosition).magnitude; RocketRay = new Ray(prevPosition, currPosition - prevPosition); var hits = Physics.RaycastAll(RocketRay, dist, 9076737); if (hits.Length > 0) { var orderedHits = hits.OrderBy(x => x.distance); using (var hitsEnu = orderedHits.GetEnumerator()) { while (hitsEnu.MoveNext()) { if (!hasPenetrated || hasDetonated) { break; } RaycastHit hit = hitsEnu.Current; Part hitPart = null; KerbalEVA hitEVA = null; try { hitPart = hit.collider.gameObject.GetComponentInParent <Part>(); hitEVA = hit.collider.gameObject.GetComponentUpwards <KerbalEVA>(); } catch (NullReferenceException e) { Debug.LogWarning("[BDArmory.BDArmory]:NullReferenceException for Kinetic Hit: " + e.Message); return; } if (hitEVA != null) { hitPart = hitEVA.part; // relative velocity, separate from the below statement, because the hitpart might be assigned only above if (hitPart.rb != null) { impactVelocity = (rb.velocity - (hitPart.rb.velocity + Krakensbane.GetFrameVelocityV3f())).magnitude; } else { impactVelocity = rb.velocity.magnitude; } ProjectileUtils.ApplyDamage(hitPart, hit, 1, 1, caliber, rocketMass, impactVelocity, bulletDmgMult, distanceFromStart, explosive, false, sourceVessel, rocketName); break; } if (hitPart != null && hitPart.vessel == sourceVessel) { continue; //avoid autohit; } Vector3 impactVector = rb.velocity; if (hitPart != null && hitPart.rb != null) { // using relative velocity vector instead of just rocket velocity // since KSP vessels can easily be moving faster than rockets impactVector = rb.velocity - (hitPart.rb.velocity + Krakensbane.GetFrameVelocityV3f()); } float hitAngle = Vector3.Angle(impactVector, -hit.normal); if (ProjectileUtils.CheckGroundHit(hitPart, hit, caliber)) { ProjectileUtils.CheckBuildingHit(hit, rocketMass, rb.velocity, bulletDmgMult); Detonate(hit.point, false); return; } impactVelocity = impactVector.magnitude; if (gravitic) { var ME = hitPart.FindModuleImplementing <ModuleMassAdjust>(); if (ME == null) { ME = (ModuleMassAdjust)hitPart.AddModule("ModuleMassAdjust"); } ME.massMod += massMod; ME.duration += BDArmorySettings.WEAPON_FX_DURATION; } if (concussion) { hitPart.rb.AddForceAtPosition(impactVector.normalized * impulse, hit.point, ForceMode.Acceleration); Detonate(hit.point, false); hasDetonated = true; return; //impulse rounds shouldn't penetrate/do damage } float anglemultiplier = (float)Math.Cos(Math.PI * hitAngle / 180.0); float thickness = ProjectileUtils.CalculateThickness(hitPart, anglemultiplier); float penetration = ProjectileUtils.CalculatePenetration(caliber, rocketMass, impactVelocity); float penetrationFactor = ProjectileUtils.CalculateArmorPenetration(hitPart, anglemultiplier, hit, penetration, thickness, caliber); if (penetration > thickness) { rb.velocity = rb.velocity * (float)Math.Sqrt(thickness / penetration); if (penTicker > 0) { rb.velocity *= 0.55f; } } if (penetrationFactor > 1) { hasPenetrated = true; ProjectileUtils.ApplyDamage(hitPart, hit, 1, penetrationFactor, caliber, rocketMass, impactVelocity, bulletDmgMult, distanceFromStart, explosive, false, sourceVessel, rocketName); penTicker += 1; ProjectileUtils.CheckPartForExplosion(hitPart); if (explosive) { transform.position += (rb.velocity * Time.fixedDeltaTime) / 3; Detonate(transform.position, false); hasDetonated = true; } } else // stopped by armor { if (hitPart.rb != null && hitPart.rb.mass > 0) { float forceAverageMagnitude = impactVelocity * impactVelocity * (1f / hit.distance) * rocketMass; float accelerationMagnitude = forceAverageMagnitude / (hitPart.vessel.GetTotalMass() * 1000); hitPart.rb.AddForceAtPosition(impactVector.normalized * accelerationMagnitude, hit.point, ForceMode.Acceleration); if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.PooledRocket]: Force Applied " + Math.Round(accelerationMagnitude, 2) + "| Vessel mass in kgs=" + hitPart.vessel.GetTotalMass() * 1000 + "| rocket effective mass =" + rocketMass); } } hasPenetrated = false; ProjectileUtils.ApplyDamage(hitPart, hit, 1, penetrationFactor, caliber, rocketMass, impactVelocity, bulletDmgMult, distanceFromStart, explosive, false, sourceVessel, rocketName); Detonate(hit.point, false); hasDetonated = true; } if (penTicker >= 2) { Detonate(hit.point, false); return; } if (rb.velocity.magnitude <= 100 && hasPenetrated && (Time.time - startTime > thrustTime)) { if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.PooledRocket]: Rocket ballistic velocity too low, stopping"); } Detonate(hit.point, false); return; } if (!hasPenetrated || hasDetonated) { break; } } } } } else if (FlightGlobals.getAltitudeAtPos(currPosition) <= 0) { Detonate(currPosition, false); } prevPosition = currPosition; if (Time.time - startTime > lifeTime) // life's 10s, quite a long time for faster rockets { Detonate(transform.position, true); } if (distanceFromStart >= maxAirDetonationRange)//rockets are performance intensive, lets cull those that have flown too far away { Detonate(transform.position, false); } if (ProximityAirDetonation(distanceFromStart)) { Detonate(transform.position, false); } }
private List <BlastHitEvent> ProcessingBlastSphere() { explosionEventsPreProcessing.Clear(); explosionEventsPartsAdded.Clear(); explosionEventsBuildingAdded.Clear(); explosionEventsVesselsHitByMissiles.Clear(); string sourceVesselName = null; if (BDACompetitionMode.Instance) { switch (ExplosionSource) { case ExplosionSourceType.Missile: var explosivePart = ExplosivePart ? ExplosivePart.FindModuleImplementing <BDExplosivePart>() : null; sourceVesselName = explosivePart ? explosivePart.sourcevessel.GetName() : SourceVesselName; break; case ExplosionSourceType.Bullet: sourceVesselName = SourceVesselName; break; default: break; } } var overlapSphereColliderCount = Physics.OverlapSphereNonAlloc(Position, Range, overlapSphereColliders, 9076737); if (overlapSphereColliderCount == overlapSphereColliders.Length) { overlapSphereColliders = Physics.OverlapSphere(Position, Range, 9076737); overlapSphereColliderCount = overlapSphereColliders.Length; } using (var hitCollidersEnu = overlapSphereColliders.Take(overlapSphereColliderCount).GetEnumerator()) { while (hitCollidersEnu.MoveNext()) { if (hitCollidersEnu.Current == null) { continue; } Part partHit = hitCollidersEnu.Current.GetComponentInParent <Part>(); if (partHit == null) { continue; } if (ProjectileUtils.IsIgnoredPart(partHit)) { continue; // Ignore ignored parts. } if (partHit != null && partHit.mass > 0 && !explosionEventsPartsAdded.Contains(partHit)) { var damaged = ProcessPartEvent(partHit, sourceVesselName, explosionEventsPreProcessing, explosionEventsPartsAdded); // If the explosion derives from a missile explosion, count the parts damaged for missile hit scores. if (damaged && ExplosionSource == ExplosionSourceType.Missile && BDACompetitionMode.Instance) { if (sourceVesselName != null && BDACompetitionMode.Instance.Scores.ContainsKey(sourceVesselName)) // Check that the source vessel is in the competition. { var damagedVesselName = partHit.vessel != null?partHit.vessel.GetName() : null; if (damagedVesselName != null && damagedVesselName != sourceVesselName && BDACompetitionMode.Instance.Scores.ContainsKey(damagedVesselName)) // Check that the damaged vessel is in the competition and isn't the source vessel. { if (BDACompetitionMode.Instance.Scores[damagedVesselName].missilePartDamageCounts.ContainsKey(sourceVesselName)) { ++BDACompetitionMode.Instance.Scores[damagedVesselName].missilePartDamageCounts[sourceVesselName]; } else { BDACompetitionMode.Instance.Scores[damagedVesselName].missilePartDamageCounts[sourceVesselName] = 1; } if (!BDACompetitionMode.Instance.Scores[damagedVesselName].everyoneWhoHitMeWithMissiles.Contains(sourceVesselName)) { BDACompetitionMode.Instance.Scores[damagedVesselName].everyoneWhoHitMeWithMissiles.Add(sourceVesselName); } ++BDACompetitionMode.Instance.Scores[sourceVesselName].totalDamagedPartsDueToMissiles; BDACompetitionMode.Instance.Scores[damagedVesselName].lastMissileHitTime = Planetarium.GetUniversalTime(); BDACompetitionMode.Instance.Scores[damagedVesselName].lastPersonWhoHitMeWithAMissile = sourceVesselName; if (explosionEventsVesselsHitByMissiles.ContainsKey(damagedVesselName)) { ++explosionEventsVesselsHitByMissiles[damagedVesselName]; } else { explosionEventsVesselsHitByMissiles[damagedVesselName] = 1; } if (BDArmorySettings.REMOTE_LOGGING_ENABLED) { BDAScoreService.Instance.TrackMissileParts(sourceVesselName, damagedVesselName, 1); } } } } } else { DestructibleBuilding building = hitCollidersEnu.Current.GetComponentInParent <DestructibleBuilding>(); if (building != null && !explosionEventsBuildingAdded.Contains(building)) { ProcessBuildingEvent(building, explosionEventsPreProcessing, explosionEventsBuildingAdded); } } } } if (explosionEventsVesselsHitByMissiles.Count > 0) { string message = ""; foreach (var vesselName in explosionEventsVesselsHitByMissiles.Keys) { message += (message == "" ? "" : " and ") + vesselName + " had " + explosionEventsVesselsHitByMissiles[vesselName]; } message += " parts damaged due to missile strike" + (SourceWeaponName != null ? " (" + SourceWeaponName + ")" : "") + (sourceVesselName != null ? " from " + sourceVesselName : "") + "."; BDACompetitionMode.Instance.competitionStatus.Add(message); // Note: damage hasn't actually been applied to the parts yet, just assigned as events, so we can't know if they survived. foreach (var vesselName in explosionEventsVesselsHitByMissiles.Keys) // Note: sourceVesselName is already checked for being in the competition before damagedVesselName is added to explosionEventsVesselsHitByMissiles, so we don't need to check it here. { if (BDACompetitionMode.Instance.Scores[vesselName].missileHitCounts.ContainsKey(sourceVesselName)) { ++BDACompetitionMode.Instance.Scores[vesselName].missileHitCounts[sourceVesselName]; } else { BDACompetitionMode.Instance.Scores[vesselName].missileHitCounts[sourceVesselName] = 1; } } } return(explosionEventsPreProcessing); }
void Detonate() //borrowed from Stockalike Project Orion { if (hasDetonated || FlightGlobals.currentMainBody == null || VesselSpawner.Instance.vesselsSpawning) // Don't trigger on scene changes or during spawning. { return; } if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.NukeTest]: Running Detonate() on nerva in vessel " + Sourcevessel); } //affect any nearby parts/vessels that aren't the source vessel Dictionary <string, int> vesselsHitByMissiles = new Dictionary <string, int>(); using (var blastHits = Physics.OverlapSphere(part.transform.position, thermalRadius, 9076737).AsEnumerable().GetEnumerator()) { partsHit.Clear(); while (blastHits.MoveNext()) { if (blastHits.Current == null) { continue; } if (blastHits.Current.gameObject == FlightGlobals.currentMainBody.gameObject) { continue; // Ignore terrain hits. } Part partHit = blastHits.Current.GetComponentInParent <Part>(); if (partHit == null) { continue; } if (ProjectileUtils.IsIgnoredPart(partHit)) { continue; // Ignore ignored parts. } if (partsHit.Contains(partHit)) { continue; // Don't hit the same part multiple times. } partsHit.Add(partHit); if (partHit != null && partHit.mass > 0) { var distToG0 = Math.Max((part.transform.position - partHit.transform.position).magnitude, 1f); float radiativeArea = !double.IsNaN(partHit.radiativeArea) ? (float)partHit.radiativeArea : partHit.GetArea(); if (BDArmorySettings.DRAW_DEBUG_LABELS && double.IsNaN(partHit.radiativeArea)) { Debug.Log("[BDArmory.NukeTest]: radiative area of part " + partHit + " was NaN, using approximate area " + radiativeArea + " instead."); } //if (partHit.vessel != this.vessel) if (partHit != part) { partHit.skinTemperature += fluence * 3370000000 / (4 * Math.PI * Math.Pow(distToG0, 2.0)) * radiativeArea / 2; // Fluence scales linearly w/ yield, 1 Kt will produce between 33 TJ and 337 kJ at 0-1000m, } // everything gets heated via atmosphere Ray LoSRay = new Ray(part.transform.position, partHit.transform.position - part.transform.position); RaycastHit hit; if (Physics.Raycast(LoSRay, out hit, distToG0, 9076737)) // only add impulse to parts with line of sight to detonation { KerbalEVA eva = hit.collider.gameObject.GetComponentUpwards <KerbalEVA>(); Part p = eva ? eva.part : hit.collider.gameObject.GetComponentInParent <Part>(); float blastDamage = 100; if (p == partHit) { //if (p.vessel != this.vessel) if (p != part) { // Forces if (p.rb != null && p.rb.mass > 0) // Don't apply forces to physicsless parts. { var blastImpulse = Mathf.Pow(3.01f * 1100f / distToG0, 1.25f) * 6.894f * lastValidAtmDensity * yieldCubeRoot * radiativeArea / 3f; // Math.Pow(Math.Pow(Math.Pow(9.54e-3 * 2200.0 / distToG0, 1.95), 4.0) + Math.Pow(Math.Pow(3.01 * 1100.0 / distToG0, 1.25), 4.0), 0.25) * 6.894 * vessel.atmDensity * Math.Pow(yield, 1.0 / 3.0) * partHit.radiativeArea / 3.0; //assuming a 0.05 kT yield if (float.IsNaN(blastImpulse)) { Debug.LogWarning("[BDArmory.NukeTest]: blast impulse is NaN. distToG0: " + distToG0 + ", vessel: " + vessel + ", atmDensity: " + lastValidAtmDensity + ", yield^(1/3): " + yieldCubeRoot + ", partHit: " + partHit + ", radiativeArea: " + radiativeArea); } else { if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.NukeTest]: Applying " + blastImpulse.ToString("0.0") + " impulse to " + p + " of mass " + p.mass + " at distance " + distToG0 + "m"); } p.rb.AddForceAtPosition((partHit.transform.position - part.transform.position).normalized * (float)blastImpulse, partHit.transform.position, ForceMode.Impulse); } } // Damage blastDamage = ((float)((yield * 3370000000) / (4f * Mathf.PI * distToG0 * distToG0) * (radiativeArea / 2f))); if (float.IsNaN(blastDamage)) { Debug.LogWarning("[BDArmory.NukeTest]: blast damage is NaN. distToG0: " + distToG0 + ", yield: " + yield + ", part: " + partHit + ", radiativeArea: " + radiativeArea); continue; } p.AddExplosiveDamage(blastDamage, 100, ExplosionSourceType.Missile); // Scoring var aName = Sourcevessel; // Attacker var tName = p.vessel.GetName(); // Target if (tName != null && aName != tName && BDACompetitionMode.Instance.Scores.ContainsKey(tName) && BDACompetitionMode.Instance.Scores.ContainsKey(aName)) { // Part hit counts if (BDACompetitionMode.Instance.Scores[tName].missilePartDamageCounts.ContainsKey(aName)) { ++BDACompetitionMode.Instance.Scores[tName].missilePartDamageCounts[aName]; } else { BDACompetitionMode.Instance.Scores[tName].missilePartDamageCounts[aName] = 1; } if (!BDACompetitionMode.Instance.Scores[tName].everyoneWhoHitMeWithMissiles.Contains(aName)) { BDACompetitionMode.Instance.Scores[tName].everyoneWhoHitMeWithMissiles.Add(aName); } ++BDACompetitionMode.Instance.Scores[aName].totalDamagedPartsDueToMissiles; BDACompetitionMode.Instance.Scores[tName].lastMissileHitTime = Planetarium.GetUniversalTime(); BDACompetitionMode.Instance.Scores[tName].lastPersonWhoHitMeWithAMissile = aName; if (vesselsHitByMissiles.ContainsKey(tName)) { ++vesselsHitByMissiles[tName]; } else { vesselsHitByMissiles[tName] = 1; } if (BDArmorySettings.REMOTE_LOGGING_ENABLED) { BDAScoreService.Instance.TrackMissileParts(aName, tName, 1); } // Part damage scoring var tData = BDACompetitionMode.Instance.Scores[tName]; if (tData.damageFromMissiles.ContainsKey(aName)) { tData.damageFromMissiles[aName] += blastDamage; } else { tData.damageFromMissiles.Add(aName, blastDamage); } if (BDArmorySettings.REMOTE_LOGGING_ENABLED) { BDAScoreService.Instance.TrackMissileDamage(aName, tName, blastDamage); } if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.NukeTest]: " + aName + " did " + blastDamage + " blast damage to " + tName + " at " + distToG0.ToString("0.000") + "m"); } } } } } } else { DestructibleBuilding building = blastHits.Current.GetComponentInParent <DestructibleBuilding>(); if (building != null) { var distToEpicenter = Mathf.Max((part.transform.position - building.transform.position).magnitude, 1f); var blastImpulse = Mathf.Pow(3.01f * 1100f / distToEpicenter, 1.25f) * 6.894f * lastValidAtmDensity * yieldCubeRoot; // blastImpulse = (((((Math.Pow((Math.Pow((Math.Pow((9.54 * Math.Pow(10.0, -3.0) * (2200.0 / distToEpicenter)), 1.95)), 4.0) + Math.Pow((Math.Pow((3.01 * (1100.0 / distToEpicenter)), 1.25)), 4.0)), 0.25)) * 6.894) * (vessel.atmDensity)) * Math.Pow(yield, (1.0 / 3.0)))); if (!double.IsNaN(blastImpulse) && blastImpulse > 140) //140kPa, level at which reinforced concrete structures are destroyed { building.Demolish(); } } } } } if (vesselsHitByMissiles.Count > 0) { string message = ""; foreach (var vesselName in vesselsHitByMissiles.Keys) { message += (message == "" ? "" : " and ") + vesselName + " had " + vesselsHitByMissiles[vesselName]; } message += " parts damaged (Blast Wave) by " + Sourcevessel + "'s exploding engine core."; BDACompetitionMode.Instance.competitionStatus.Add(message); Debug.Log("[BDArmory.NukeTest]: " + message); } ExplosionFx.CreateExplosion(part.transform.position, 1, explModelPath, explSoundPath, ExplosionSourceType.Missile, 0, null, Sourcevessel, "Reactor Containment Failure"); hasDetonated = true; if (part.vessel != null) // Already in the process of being destroyed. { part.Destroy(); } }
/// <summary> /// Gets the position of the projectile. /// </summary> /// <returns></returns> public Vector2 GetPosition() { return(ProjectileUtils.GetMainProjectile(this.identity, this.type, this.OwnerProjectile.Index).position); }
public List <IAssetVO> GetProjectilePreloads(Map map) { return(ProjectileUtils.GetBattleProjectileAssets(map, null, null, null, null, this.pvpTarget.GuildDonatedTroops, this.pvpTarget.Champions, this.battleData.AttackerEquipment, this.pvpTarget.Equipment)); }
public override bool PreDraw(SpriteBatch spriteBatch, Color lightColor) { ProjectileUtils.DrawAfterImages(projectile, spriteBatch, lightColor); return(true); }
private ProjectileView SpawnProjectile(Bullet bullet, bool isOnGround) { if (!ProjectileUtils.AreAllBulletAssetsLoaded(bullet, this.loadedAssets)) { this.LoadBulletAssets(bullet); if (bullet.ProjectileType != null) { Service.Get <StaRTSLogger>().Warn("Loading assets on demand for projectile " + bullet.ProjectileType.Uid); } } bool isDeflection = bullet.IsDeflection; ProjectileTypeVO projectileType = bullet.ProjectileType; GameObject gunLocator = bullet.GunLocator; Vector3 vector; if (!isDeflection && gunLocator != null) { vector = gunLocator.transform.position; } else { vector = bullet.SpawnWorldLocation; } Vector3 targetWorldLocation = bullet.TargetWorldLocation; if (isOnGround) { vector.y = 0f; targetWorldLocation.y = 0f; } else if (projectileType.IsBeam || (bullet.Owner != null && bullet.Target != null && bullet.Target.ShieldBorderComp != null)) { targetWorldLocation.y = vector.y; } ProjectileView projectileView = (this.projectilePool.Count > 0) ? this.projectilePool.Pop() : new ProjectileView(); projectileView.Init(projectileType, bullet, isOnGround); if (!isDeflection && !string.IsNullOrEmpty(projectileType.MuzzleFlashAssetName)) { this.StartDirectionalEmitter(bullet.Owner, gunLocator, vector, targetWorldLocation, projectileType.MuzzleFlashAssetName, projectileType.MuzzleFlashFadeTime); int num = 0; if (bullet.AppliedBuffs != null) { num = bullet.AppliedBuffs.Count; } FactionType ownerFaction = bullet.OwnerFaction; for (int i = 0; i < num; i++) { string muzzleAssetNameBasedOnFaction = bullet.AppliedBuffs[i].BuffType.GetMuzzleAssetNameBasedOnFaction(ownerFaction); if (!string.IsNullOrEmpty(muzzleAssetNameBasedOnFaction)) { this.StartDirectionalEmitter(bullet.Owner, gunLocator, vector, targetWorldLocation, muzzleAssetNameBasedOnFaction, projectileType.MuzzleFlashFadeTime); } } } GameObject gameObject = null; float num2 = bullet.TravelTime / 1000f; GameObject gameObject2 = null; ParticleSystem particleSystem = null; string bulletAssetName = projectileType.GetBulletAssetName(isOnGround); EmitterPool emitter = this.GetEmitter(bulletAssetName); if (emitter != null) { float num3 = num2; float delayPostEmitterStop = 0f; if (projectileType.IsBeam) { num3 = num2 * (float)(projectileType.BeamEmitterLength - projectileType.BeamInitialZeroes) / (float)(projectileType.BeamLifeLength - projectileType.BeamInitialZeroes); delayPostEmitterStop = num2 - num3; } if (emitter is MultipleEmittersPool) { MultipleEmittersPool multipleEmittersPool = (MultipleEmittersPool)emitter; gameObject = multipleEmittersPool.GetEmitterRoot(); if (gameObject != null) { multipleEmittersPool.StopEmissionAndReturnToPool(gameObject, num3, delayPostEmitterStop); } } else if (emitter is SingleEmitterPool) { SingleEmitterPool singleEmitterPool = (SingleEmitterPool)emitter; particleSystem = singleEmitterPool.GetEmitter(); if (particleSystem != null) { singleEmitterPool.StopEmissionAndReturnToPool(particleSystem, num3, delayPostEmitterStop); } } if (this.meshes.ContainsKey(bulletAssetName)) { gameObject2 = this.meshes[bulletAssetName].GetMesh(); } } Transform targetTransform = this.GetTargetTransform(bullet, vector, targetWorldLocation); if (gameObject2 != null && particleSystem != null) { projectileView.InitWithMeshAndEmitter(num2, vector, targetWorldLocation, gameObject2, particleSystem, targetTransform); } else if (gameObject2 != null && gameObject == null) { projectileView.InitWithMesh(num2, vector, targetWorldLocation, gameObject2, targetTransform); } else if (particleSystem != null) { projectileView.InitWithEmitter(num2, vector, targetWorldLocation, particleSystem, targetTransform); } else if (gameObject != null) { projectileView.InitWithEmitters(num2, vector, targetWorldLocation, gameObject, gameObject2, targetTransform); } else { projectileView.InitWithoutBullet(num2, vector, targetWorldLocation, targetTransform); } this.activeProjectiles.Add(projectileView); if (!isOnGround && !string.IsNullOrEmpty(projectileType.GroundBulletAssetName)) { this.SpawnProjectile(bullet, true); } return(projectileView); }