Ejemplo n.º 1
0
        void OnTriggerEnter(Collider other)
        {
            //hitting parts
            Part explodePart = null;

            try
            {
                explodePart = other.gameObject.GetComponentUpwards <Part>();
                explodePart.Unpack();
            }
            catch (NullReferenceException)
            {
            }

            if (explodePart != null)
            {
                explodePart.Destroy();
            }
            else
            {
                //hitting buildings
                DestructibleBuilding hitBuilding = null;
                try
                {
                    hitBuilding = other.gameObject.GetComponentUpwards <DestructibleBuilding>();
                }
                catch (NullReferenceException)
                {
                }
                if (hitBuilding != null && hitBuilding.IsIntact)
                {
                    hitBuilding.Demolish();
                }
            }
        }
Ejemplo n.º 2
0
        private bool CheckBuildingHit(RaycastHit hit)
        {
            DestructibleBuilding building = null;

            try
            {
                building             = hit.collider.gameObject.GetComponentUpwards <DestructibleBuilding>();
                building.damageDecay = 600f;
            }
            catch (Exception) { }

            if (building != null && building.IsIntact)
            {
                float damageToBuilding = ((0.5f * (bulletMass * Mathf.Pow(currentVelocity.magnitude, 2)))
                                          * (BDArmorySettings.DMG_MULTIPLIER / 100) * bulletDmgMult
                                          * 1e-4f);
                damageToBuilding /= 8f;
                building.AddDamage(damageToBuilding);
                if (building.Damage > building.impactMomentumThreshold * 150)
                {
                    building.Demolish();
                }
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BDArmory]: Ballistic hit destructible building! Hitpoints Applied: " + Mathf.Round(damageToBuilding) +
                              ", Building Damage : " + Mathf.Round(building.Damage) +
                              " Building Threshold : " + building.impactMomentumThreshold);
                }

                return(true);
            }
            return(false);
        }
Ejemplo n.º 3
0
        private void ExecuteBuildingBlastEvent(BuildingBlastHitEvent eventToExecute)
        {
            //TODO: Review if the damage is sensible after so many changes
            //buildings
            DestructibleBuilding building = eventToExecute.Building;

            building.damageDecay = 600f;

            if (building)
            {
                var   distanceFactor   = Mathf.Clamp01((Range - eventToExecute.Distance) / Range);
                float damageToBuilding = (BDArmorySettings.DMG_MULTIPLIER / 100) * BDArmorySettings.EXP_DMG_MOD_BALLISTIC_NEW * Power * distanceFactor;

                damageToBuilding *= 2f;

                building.AddDamage(damageToBuilding);

                if (building.Damage > building.impactMomentumThreshold)
                {
                    building.Demolish();
                }
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BDArmory]: Explosion hit destructible building! Hitpoints Applied: " + Mathf.Round(damageToBuilding) +
                              ", Building Damage : " + Mathf.Round(building.Damage) +
                              " Building Threshold : " + building.impactMomentumThreshold);
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// If we call building.Demolish() then we woud trigger the KSP event and send a message to the server.
        /// Therefore we add the id to the ignore field so the event FacilityCollapsing doesn't send a network message
        /// </summary>
        public void CollapseFacilityWithoutSendingMessage(DestructibleBuilding building)
        {
            if (building == null || !building.IsIntact || building.IsDestroyed)
            {
                return;
            }

            BuildingIdToIgnore = building.id;
            building.Demolish();
            BuildingIdToIgnore = string.Empty;
        }
Ejemplo n.º 5
0
        public static void DoExplosionRay(Ray ray, float power, float maxDistance, ref List <Part> ignoreParts, ref List <DestructibleBuilding> ignoreBldgs)
        {
            RaycastHit rayHit;

            if (Physics.Raycast(ray, out rayHit, maxDistance, 557057))
            {
                float sqrDist        = (rayHit.point - ray.origin).sqrMagnitude;
                float sqrMaxDist     = maxDistance * maxDistance;
                float distanceFactor = Mathf.Clamp01((sqrMaxDist - sqrDist) / sqrMaxDist);
                //parts
                Part part = rayHit.collider.GetComponentInParent <Part>();
                if (part && !ignoreParts.Contains(part) && part.physicalSignificance == Part.PhysicalSignificance.FULL)
                {
                    ignoreParts.Add(part);
                    Rigidbody rb = part.GetComponent <Rigidbody>();
                    if (rb)
                    {
                        rb.AddForceAtPosition(ray.direction * power * distanceFactor * ExplosionImpulseMultiplier, rayHit.point, ForceMode.Impulse);
                    }

                    float heatDamage = ExplosionHeatMultiplier * power * distanceFactor / part.crashTolerance;
                    part.temperature += heatDamage;
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("====== Explosion ray hit part! Damage: " + heatDamage);
                    }
                    return;
                }

                //buildings
                DestructibleBuilding building = rayHit.collider.GetComponentInParent <DestructibleBuilding>();
                if (building && !ignoreBldgs.Contains(building))
                {
                    ignoreBldgs.Add(building);
                    float damageToBuilding = ExplosionHeatMultiplier * 0.00685f * power * distanceFactor;
                    if (damageToBuilding > building.impactMomentumThreshold / 10)
                    {
                        building.AddDamage(damageToBuilding);
                    }
                    if (building.Damage > building.impactMomentumThreshold)
                    {
                        building.Demolish();
                    }
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("== Explosion hit destructible building! Damage: " + (damageToBuilding).ToString("0.00") + ", total Damage: " + building.Damage);
                    }
                }
            }
        }
Ejemplo n.º 6
0
        public static bool CheckBuildingHit(RaycastHit hit, float projMass, Vector3 currentVelocity, float DmgMult)
        {
            DestructibleBuilding building = null;

            try
            {
                building = hit.collider.gameObject.GetComponentUpwards <DestructibleBuilding>();
                if (building != null)
                {
                    building.damageDecay = 600f;
                }
            }
            catch (Exception e)
            {
                Debug.LogWarning("[BDArmory.ProjectileUtils]: Exception thrown in CheckBuildingHit: " + e.Message + "\n" + e.StackTrace);
            }

            if (building != null && building.IsIntact)
            {
                float damageToBuilding = ((0.5f * (projMass * Mathf.Pow(currentVelocity.magnitude, 2)))
                                          * (BDArmorySettings.DMG_MULTIPLIER / 100) * DmgMult
                                          * 1e-4f);
                damageToBuilding /= 8f;
                building.AddDamage(damageToBuilding);
                if (building.Damage > building.impactMomentumThreshold * 150)
                {
                    building.Demolish();
                }
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BDArmory.ProjectileUtils]: Ballistic hit destructible building! Hitpoints Applied: " + Mathf.Round(damageToBuilding) +
                              ", Building Damage : " + Mathf.Round(building.Damage) +
                              " Building Threshold : " + building.impactMomentumThreshold);
                }

                return(true);
            }
            return(false);
        }
Ejemplo n.º 7
0
        void OnTriggerEnter(Collider other)
        {
            //hitting parts
            Part explodePart = null;

            try
            {
                explodePart = other.gameObject.GetComponentUpwards <Part>();
                explodePart.Unpack();
            }
            catch (NullReferenceException e)
            {
                Debug.LogWarning("[BDArmory.SeismicChargeFX]: Exception thrown in OnTriggerEnter: " + e.Message + "\n" + e.StackTrace);
            }

            if (explodePart != null)
            {
                explodePart.Destroy();
            }
            else
            {
                //hitting buildings
                DestructibleBuilding hitBuilding = null;
                try
                {
                    hitBuilding = other.gameObject.GetComponentUpwards <DestructibleBuilding>();
                }
                catch (NullReferenceException e)
                {
                    Debug.LogWarning("[BDArmory.SeismicChargeFX]: Exception thrown in OnTriggerEnter: " + e.Message + "\n" + e.StackTrace);
                }
                if (hitBuilding != null && hitBuilding.IsIntact)
                {
                    hitBuilding.Demolish();
                }
            }
            Destroy(gameObject);
        }
Ejemplo n.º 8
0
        public static void DoExplosionRay(Ray ray, float power, float heat, float maxDistance, ref List <Part> ignoreParts, ref List <DestructibleBuilding> ignoreBldgs, Vessel sourceVessel = null)
        {
            RaycastHit rayHit;

            if (Physics.Raycast(ray, out rayHit, maxDistance, 557057))
            {
                float sqrDist        = (rayHit.point - ray.origin).sqrMagnitude;
                float sqrMaxDist     = maxDistance * maxDistance;
                float distanceFactor = Mathf.Clamp01((sqrMaxDist - sqrDist) / sqrMaxDist);
                //parts
                Part part = rayHit.collider.GetComponentInParent <Part>();
                if (part)
                {
                    Vessel missileSource = null;
                    if (sourceVessel != null)
                    {
                        var ml = part.FindModuleImplementing <MissileBase>();
                        if (ml)
                        {
                            missileSource = ml.SourceVessel;
                        }
                    }


                    if (!ignoreParts.Contains(part) && part.physicalSignificance == Part.PhysicalSignificance.FULL &&
                        (!sourceVessel || sourceVessel != missileSource))
                    {
                        ignoreParts.Add(part);
                        Rigidbody rb = part.GetComponent <Rigidbody>();
                        if (rb)
                        {
                            rb.AddForceAtPosition(ray.direction * power * distanceFactor * ExplosionImpulseMultiplier,
                                                  rayHit.point, ForceMode.Impulse);
                        }
                        if (heat < 0)
                        {
                            heat = power;
                        }
                        float heatDamage = (BDArmorySettings.DMG_MULTIPLIER / 100) * ExplosionHeatMultiplier * heat *
                                           distanceFactor / part.crashTolerance;
                        float excessHeat = Mathf.Max(0, (float)(part.temperature + heatDamage - part.maxTemp));
                        part.temperature += heatDamage;
                        if (BDArmorySettings.DRAW_DEBUG_LABELS)
                        {
                            Debug.Log("[BDArmory]:====== Explosion ray hit part! Damage: " + heatDamage);
                        }
                        if (excessHeat > 0 && part.parent)
                        {
                            part.parent.temperature += excessHeat;
                        }
                        return;
                    }
                }

                //buildings
                DestructibleBuilding building = rayHit.collider.GetComponentInParent <DestructibleBuilding>();
                if (building && !ignoreBldgs.Contains(building))
                {
                    ignoreBldgs.Add(building);
                    float damageToBuilding = (BDArmorySettings.DMG_MULTIPLIER / 100) * ExplosionHeatMultiplier * 0.00645f *
                                             power * distanceFactor;
                    if (damageToBuilding > building.impactMomentumThreshold / 10)
                    {
                        building.AddDamage(damageToBuilding);
                    }
                    if (building.Damage > building.impactMomentumThreshold)
                    {
                        building.Demolish();
                    }
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("[BDArmory]:== Explosion hit destructible building! Damage: " +
                                  (damageToBuilding).ToString("0.00") + ", total Damage: " + building.Damage);
                    }
                }
            }
        }
Ejemplo n.º 9
0
        void FixedUpdate()
        {
            float distanceFromStart = Vector3.Distance(transform.position, startPosition);

            if (!gameObject.activeInHierarchy)
            {
                return;
            }
            flightTimeElapsed += TimeWarp.fixedDeltaTime;       //calculate flight time for drag purposes

            if (bulletDrop && FlightGlobals.RefFrameIsRotating)
            {
                currentVelocity += FlightGlobals.getGeeForceAtPosition(transform.position) * TimeWarp.fixedDeltaTime;
            }
            if (dragType == BulletDragTypes.NumericalIntegration)
            {
                Vector3 dragAcc = currentVelocity * currentVelocity.magnitude * (float)FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(transform.position), FlightGlobals.getExternalTemperature(transform.position));
                dragAcc *= 0.5f;
                dragAcc /= ballisticCoefficient;

                currentVelocity -= dragAcc * TimeWarp.fixedDeltaTime;       //numerical integration; using Euler is silly, but let's go with it anyway
            }


            if (tracerLength == 0)
            {
                bulletTrail.SetPosition(0, transform.position + (currentVelocity * tracerDeltaFactor * TimeWarp.fixedDeltaTime / TimeWarp.CurrentRate) - (FlightGlobals.ActiveVessel.rb_velocity * TimeWarp.fixedDeltaTime));
            }
            else
            {
                bulletTrail.SetPosition(0, transform.position + ((currentVelocity - sourceOriginalV).normalized * tracerLength));
            }
            if (fadeColor)
            {
                FadeColor();
                bulletTrail.material.SetColor("_TintColor", currentColor * tracerLuminance);
            }



            bulletTrail.SetPosition(1, transform.position);



            currPosition = gameObject.transform.position;

            if (distanceFromStart > maxDistance)
            {
                //GameObject.Destroy(gameObject);
                KillBullet();
                return;
            }

            if (collisionEnabled)
            {
                float dist = initialSpeed * TimeWarp.fixedDeltaTime;

                Ray        ray = new Ray(prevPosition, currPosition - prevPosition);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit, dist, 557057))
                {
                    bool  penetrated = true;
                    Part  hitPart    = null;                   //determine when bullet collides with a target
                    float hitAngle   = Vector3.Angle(currentVelocity, -hit.normal);

                    if (bulletType != PooledBulletTypes.Explosive)                    //dont do bullet damage if it is explosive
                    {
                        float impactVelocity = currentVelocity.magnitude;
                        if (dragType == BulletDragTypes.AnalyticEstimate)
                        {
                            float analyticDragVelAdjustment = (float)FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(currPosition), FlightGlobals.getExternalTemperature(currPosition));
                            analyticDragVelAdjustment *= flightTimeElapsed * initialSpeed;
                            analyticDragVelAdjustment += 2 * ballisticCoefficient;

                            analyticDragVelAdjustment = 2 * ballisticCoefficient * initialSpeed / analyticDragVelAdjustment; //velocity as a function of time under the assumption of a projectile only acted upon by drag with a constant drag area

                            analyticDragVelAdjustment = analyticDragVelAdjustment - initialSpeed;                            //since the above was velocity as a function of time, but we need a difference in drag, subtract the initial velocity
                            //the above number should be negative...
                            impactVelocity += analyticDragVelAdjustment;                                                     //so add it to the impact velocity

                            if (impactVelocity < 0)
                            {
                                impactVelocity = 0;                                     //clamp the velocity to > 0, since it could drop below 0 if the bullet is fired upwards
                            }
                            //Debug.Log("flight time: " + flightTimeElapsed + " BC: " + ballisticCoefficient + "\ninit speed: " + initialSpeed + " vel diff: " + analyticDragVelAdjustment);
                        }

                        //hitting a vessel Part

                        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                        /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE START//////////////////////////////////////////////////////////////
                        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


                        try
                        {
                            hitPart = Part.FromGO(hit.rigidbody.gameObject);
                        }
                        catch (NullReferenceException)
                        {
                        }


                        if (hitPart != null)                        //see if it will ricochet of the part
                        {
                            penetrated = !RicochetOnPart(hitPart, hitAngle, impactVelocity);
                        }
                        else                         //see if it will ricochet off scenery
                        {
                            float reflectRandom = UnityEngine.Random.Range(-150f, 90f);
                            if (reflectRandom > 90 - hitAngle)
                            {
                                penetrated = false;
                            }
                        }


                        if (hitPart != null && !hitPart.partInfo.name.Contains("Strut"))                                                                             //when a part is hit, execute damage code (ignores struts to keep those from being abused as armor)(no, because they caused weird bugs :) -BahamutoD)
                        {
                            float heatDamage = (mass / (hitPart.crashTolerance * hitPart.mass)) * impactVelocity * impactVelocity * BDArmorySettings.DMG_MULTIPLIER; //how much heat damage will be applied based on bullet mass, velocity, and part's impact tolerance and mass
                            if (!penetrated)
                            {
                                heatDamage = heatDamage / 8;
                            }
                            if (BDArmorySettings.INSTAKILL)                             //instakill support, will be removed once mod becomes officially MP
                            {
                                heatDamage = (float)hitPart.maxTemp + 100;              //make heat damage equal to the part's max temperture, effectively instakilling any part it hits
                            }
                            if (BDArmorySettings.DRAW_DEBUG_LABELS)
                            {
                                Debug.Log("Hit! damage applied: " + heatDamage);                                                                //debugging stuff
                            }
                            if (hitPart.vessel != sourceVessel)
                            {
                                hitPart.temperature += heatDamage;                                                             //apply heat damage to the hit part.
                            }
                            float overKillHeatDamage = (float)(hitPart.temperature - hitPart.maxTemp);

                            if (overKillHeatDamage > 0)                                 //if the part is destroyed by overheating, we want to add the remaining heat to attached parts.  This prevents using tiny parts as armor
                            {
                                overKillHeatDamage *= hitPart.crashTolerance;           //reset to raw damage
                                float numConnectedParts = hitPart.children.Count;
                                if (hitPart.parent != null)
                                {
                                    numConnectedParts++;
                                    overKillHeatDamage         /= numConnectedParts;
                                    hitPart.parent.temperature += overKillHeatDamage / (hitPart.parent.crashTolerance * hitPart.parent.mass);

                                    for (int i = 0; i < hitPart.children.Count; i++)
                                    {
                                        hitPart.children[i].temperature += overKillHeatDamage / hitPart.children[i].crashTolerance;
                                    }
                                }
                                else
                                {
                                    overKillHeatDamage /= numConnectedParts;
                                    for (int i = 0; i < hitPart.children.Count; i++)
                                    {
                                        hitPart.children[i].temperature += overKillHeatDamage / hitPart.children[i].crashTolerance;
                                    }
                                }
                            }
                        }

                        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                        /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE END////////////////////////////////////////////////////////////////
                        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


                        //hitting a Building
                        DestructibleBuilding hitBuilding = null;
                        try
                        {
                            hitBuilding = hit.collider.gameObject.GetComponentUpwards <DestructibleBuilding>();
                        }
                        catch (NullReferenceException)
                        {
                        }
                        if (hitBuilding != null && hitBuilding.IsIntact)
                        {
                            float damageToBuilding = mass * initialSpeed * initialSpeed * BDArmorySettings.DMG_MULTIPLIER / 12000;
                            if (!penetrated)
                            {
                                damageToBuilding = damageToBuilding / 8;
                            }
                            hitBuilding.AddDamage(damageToBuilding);
                            if (hitBuilding.Damage > hitBuilding.impactMomentumThreshold)
                            {
                                hitBuilding.Demolish();
                            }
                            if (BDArmorySettings.DRAW_DEBUG_LINES)
                            {
                                Debug.Log("bullet hit destructible building! Damage: " + (damageToBuilding).ToString("0.00") + ", total Damage: " + hitBuilding.Damage);
                            }
                        }
                    }

                    if (hitPart == null || (hitPart != null && hitPart.vessel != sourceVessel))
                    {
                        if (!penetrated && !hasBounced)
                        {
                            //ricochet
                            hasBounced = true;
                            if (BDArmorySettings.BULLET_HITS)
                            {
                                BulletHitFX.CreateBulletHit(hit.point, hit.normal, true);
                            }

                            tracerStartWidth /= 2;
                            tracerEndWidth   /= 2;

                            transform.position = hit.point;
                            currentVelocity    = Vector3.Reflect(currentVelocity, hit.normal);
                            currentVelocity    = (hitAngle / 150) * currentVelocity * 0.65f;

                            Vector3 randomDirection = UnityEngine.Random.rotation * Vector3.one;

                            currentVelocity = Vector3.RotateTowards(currentVelocity, randomDirection, UnityEngine.Random.Range(0f, 5f) * Mathf.Deg2Rad, 0);
                        }
                        else
                        {
                            if (bulletType == PooledBulletTypes.Explosive)
                            {
                                ExplosionFX.CreateExplosion(hit.point - (ray.direction * 0.1f), radius, blastPower, blastHeat, sourceVessel, currentVelocity.normalized, explModelPath, explSoundPath);
                            }
                            else if (BDArmorySettings.BULLET_HITS)
                            {
                                BulletHitFX.CreateBulletHit(hit.point, hit.normal, false);
                            }



                            //GameObject.Destroy(gameObject); //destroy bullet on collision
                            KillBullet();
                            return;
                        }
                    }
                }

                /*
                 * if(isUnderwater)
                 * {
                 *      if(FlightGlobals.getAltitudeAtPos(transform.position) > 0)
                 *      {
                 *              isUnderwater = false;
                 *      }
                 *      else
                 *      {
                 *              rigidbody.AddForce(-rigidbody.velocity * 0.15f);
                 *      }
                 * }
                 * else
                 * {
                 *      if(FlightGlobals.getAltitudeAtPos(transform.position) < 0)
                 *      {
                 *              isUnderwater = true;
                 *              //FXMonger.Splash(transform.position, 1);
                 *              //make a custom splash here
                 *      }
                 * }
                 */
            }

            if (bulletType == PooledBulletTypes.Explosive && airDetonation && distanceFromStart > detonationRange)
            {
                //detonate
                ExplosionFX.CreateExplosion(transform.position, radius, blastPower, blastHeat, sourceVessel, currentVelocity.normalized, explModelPath, explSoundPath);
                //GameObject.Destroy(gameObject); //destroy bullet on collision
                KillBullet();
                return;
            }


            prevPosition = currPosition;

            //move bullet
            transform.position += currentVelocity * Time.fixedDeltaTime;
        }
Ejemplo n.º 10
0
        void FixedUpdate()
        {
            float distanceFromStart = Vector3.Distance(transform.position, startPosition);

            if (!gameObject.activeInHierarchy)
            {
                return;
            }

            if (bulletDrop && FlightGlobals.RefFrameIsRotating)
            {
                currentVelocity += FlightGlobals.getGeeForceAtPosition(transform.position) * TimeWarp.fixedDeltaTime;
            }


            if (tracerLength == 0)
            {
                bulletTrail.SetPosition(0, transform.position + (currentVelocity * 1.35f * TimeWarp.fixedDeltaTime / TimeWarp.CurrentRate) - (FlightGlobals.ActiveVessel.rb_velocity * TimeWarp.fixedDeltaTime));
            }
            else
            {
                bulletTrail.SetPosition(0, transform.position + ((currentVelocity - sourceOriginalV).normalized * tracerLength));
            }
            if (fadeColor)
            {
                FadeColor();
                bulletTrail.material.SetColor("_TintColor", currentColor);
            }



            bulletTrail.SetPosition(1, transform.position);



            currPosition = gameObject.transform.position;

            if (distanceFromStart > maxDistance)
            {
                //GameObject.Destroy(gameObject);
                KillBullet();
                return;
            }

            if (collisionEnabled)
            {
                float dist = initialSpeed * TimeWarp.fixedDeltaTime;

                Ray        ray = new Ray(prevPosition, currPosition - prevPosition);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit, dist, 557057))
                {
                    bool penetrated = true;


                    //hitting a vessel Part

                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE START//////////////////////////////////////////////////////////////
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

                    Part hitPart = null;                        //determine when bullet collides with a target
                    try{
                        hitPart = Part.FromGO(hit.rigidbody.gameObject);
                    }catch (NullReferenceException) {}

                    float hitAngle = Vector3.Angle(currentVelocity, -hit.normal);
                    if (hitPart != null)                  //see if it will ricochet of the part
                    {
                        penetrated = !RicochetOnPart(hitPart, hitAngle);
                    }
                    else                     //see if it will ricochet off scenery
                    {
                        float reflectRandom = UnityEngine.Random.Range(-150f, 90f);
                        if (reflectRandom > 90 - hitAngle)
                        {
                            penetrated = false;
                        }
                    }


                    if (hitPart != null && !hitPart.partInfo.name.Contains("Strut"))                                                           //when a part is hit, execute damage code (ignores struts to keep those from being abused as armor)(no, because they caused weird bugs :) -BahamutoD)
                    {
                        float heatDamage = (mass / hitPart.crashTolerance) * currentVelocity.magnitude * 50 * BDArmorySettings.DMG_MULTIPLIER; //how much heat damage will be applied based on bullet mass, velocity, and part's impact tolerance
                        if (!penetrated)
                        {
                            heatDamage = heatDamage / 8;
                        }
                        if (BDArmorySettings.INSTAKILL)                         //instakill support, will be removed once mod becomes officially MP
                        {
                            heatDamage = (float)hitPart.maxTemp + 100;          //make heat damage equal to the part's max temperture, effectively instakilling any part it hits
                        }
                        if (BDArmorySettings.DRAW_DEBUG_LINES)
                        {
                            Debug.Log("Hit! damage applied: " + heatDamage); //debugging stuff
                        }
                        if (hitPart.mass <= 0.01)                            //if part mass is below 0.01, instakill it and do minor collateral (anti-exploit and to keep people from abusing near massless or massless crap as armor)
                        {
                            if (hitPart.vessel != sourceVessel)
                            {
                                hitPart.temperature += hitPart.maxTemp + 500;                                                              //make heat damage equal to the part's max temperture, and add 500 extra heat damage which should do minor collateral to teh surrounding parts
                            }
                        }
                        else                            //apply damage normally if no special case present
                        {
                            if (hitPart.vessel != sourceVessel)
                            {
                                hitPart.temperature += heatDamage;                                                              //apply heat damage to the hit part.
                            }
                        }
                    }

                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE END////////////////////////////////////////////////////////////////
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


                    //hitting a Building
                    DestructibleBuilding hitBuilding = null;
                    try{
                        hitBuilding = hit.collider.gameObject.GetComponentUpwards <DestructibleBuilding>();
                    }
                    catch (NullReferenceException) {}
                    if (hitBuilding != null && hitBuilding.IsIntact)
                    {
                        float damageToBuilding = mass * initialSpeed * BDArmorySettings.DMG_MULTIPLIER / 120;
                        if (!penetrated)
                        {
                            damageToBuilding = damageToBuilding / 8;
                        }
                        hitBuilding.AddDamage(damageToBuilding);
                        if (hitBuilding.Damage > hitBuilding.impactMomentumThreshold)
                        {
                            hitBuilding.Demolish();
                        }
                        if (BDArmorySettings.DRAW_DEBUG_LINES)
                        {
                            Debug.Log("bullet hit destructible building! Damage: " + (damageToBuilding).ToString("0.00") + ", total Damage: " + hitBuilding.Damage);
                        }
                    }

                    if (hitPart == null || (hitPart != null && hitPart.vessel != sourceVessel))
                    {
                        if (!penetrated && !hasBounced)
                        {
                            //ricochet
                            hasBounced = true;
                            if (BDArmorySettings.BULLET_HITS)
                            {
                                BulletHitFX.CreateBulletHit(hit.point, hit.normal, true);
                            }

                            transform.position = hit.point;
                            currentVelocity    = Vector3.Reflect(currentVelocity, hit.normal);
                            currentVelocity    = (hitAngle / 150) * currentVelocity * 0.65f;

                            Vector3 randomDirection = UnityEngine.Random.rotation * Vector3.one;

                            currentVelocity = Vector3.RotateTowards(currentVelocity, randomDirection, UnityEngine.Random.Range(0f, 5f) * Mathf.Deg2Rad, 0);
                        }
                        else
                        {
                            if (BDArmorySettings.BULLET_HITS)
                            {
                                BulletHitFX.CreateBulletHit(hit.point, hit.normal, false);
                            }

                            if (bulletType == PooledBulletTypes.Explosive)
                            {
                                ExplosionFX.CreateExplosion(hit.point, radius, blastPower, sourceVessel, currentVelocity.normalized, explModelPath, explSoundPath);
                            }

                            //GameObject.Destroy(gameObject); //destroy bullet on collision
                            KillBullet();
                            return;
                        }
                    }
                }

                /*
                 * if(isUnderwater)
                 * {
                 *      if(FlightGlobals.getAltitudeAtPos(transform.position) > 0)
                 *      {
                 *              isUnderwater = false;
                 *      }
                 *      else
                 *      {
                 *              rigidbody.AddForce(-rigidbody.velocity * 0.15f);
                 *      }
                 * }
                 * else
                 * {
                 *      if(FlightGlobals.getAltitudeAtPos(transform.position) < 0)
                 *      {
                 *              isUnderwater = true;
                 *              //FXMonger.Splash(transform.position, 1);
                 *              //make a custom splash here
                 *      }
                 * }
                 */
            }

            if (bulletType == PooledBulletTypes.Explosive && airDetonation && distanceFromStart > detonationRange)
            {
                //detonate
                ExplosionFX.CreateExplosion(transform.position, radius, blastPower, sourceVessel, currentVelocity.normalized, explModelPath, explSoundPath);
                //GameObject.Destroy(gameObject); //destroy bullet on collision
                KillBullet();
                return;
            }


            prevPosition = currPosition;

            //move bullet
            transform.position += currentVelocity * Time.fixedDeltaTime;
        }
Ejemplo n.º 11
0
        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 (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();
            }
        }
Ejemplo n.º 12
0
        void FixedUpdate()
        {
            float distanceFromStartSqr = (transform.position - startPosition).sqrMagnitude;

            if (!gameObject.activeInHierarchy)
            {
                return;
            }
            flightTimeElapsed += TimeWarp.fixedDeltaTime; //calculate flight time for drag purposes

            if (bulletDrop && FlightGlobals.RefFrameIsRotating)
            {
                currentVelocity += FlightGlobals.getGeeForceAtPosition(transform.position) * TimeWarp.fixedDeltaTime;
            }
            if (dragType == BulletDragTypes.NumericalIntegration)
            {
                Vector3 dragAcc = currentVelocity * currentVelocity.magnitude *
                                  (float)
                                  FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(transform.position),
                                                              FlightGlobals.getExternalTemperature(transform.position));
                dragAcc *= 0.5f;
                dragAcc /= ballisticCoefficient;

                currentVelocity -= dragAcc * TimeWarp.fixedDeltaTime;
                //numerical integration; using Euler is silly, but let's go with it anyway
            }


            if (tracerLength == 0)
            {
                bulletTrail.SetPosition(0,
                                        transform.position +
                                        (currentVelocity * tracerDeltaFactor * TimeWarp.fixedDeltaTime / TimeWarp.CurrentRate) -
                                        (FlightGlobals.ActiveVessel.Velocity() * TimeWarp.fixedDeltaTime));
            }
            else
            {
                bulletTrail.SetPosition(0,
                                        transform.position + ((currentVelocity - sourceOriginalV).normalized * tracerLength));
            }
            if (fadeColor)
            {
                FadeColor();
                bulletTrail.material.SetColor("_TintColor", currentColor * tracerLuminance);
            }


            bulletTrail.SetPosition(1, transform.position);


            currPosition = gameObject.transform.position;

            if (distanceFromStartSqr > maxDistance * maxDistance)
            {
                //GameObject.Destroy(gameObject);
                KillBullet();
                return;
            }

            if (collisionEnabled)
            {
                float dist = initialSpeed * TimeWarp.fixedDeltaTime;

                Ray        ray = new Ray(prevPosition, currPosition - prevPosition);
                RaycastHit hit;
                try
                {
                    if (Physics.Raycast(ray, out hit, dist, 688129))
                    {
                        bool penetrated = true;
                        bool hitEva     = false;
                        Part hitPart    = null; //determine when bullet collides with a target
                        try
                        {
                            // Look for any Kerbal first. The part, KerbalEVA, is functionally similar to regular parts.
                            KerbalEVA eva = hit.collider.gameObject.GetComponentUpwards <KerbalEVA>();
                            hitPart = eva ? eva.part : hit.collider.gameObject.GetComponentInParent <Part>();
                            hitEva  = eva;
                        }
                        catch (NullReferenceException)
                        {
                        }
                        // Need to make sure Kerbals don't get armor.
                        BDArmor armor = hitEva ? null : BDArmor.GetArmor(hit.collider, hitPart);
                        ArmorPenetration.BulletPenetrationData armorData = new ArmorPenetration.BulletPenetrationData(ray, hit);
                        ArmorPenetration.DoPenetrationRay(armorData, bullet.positiveCoefficient);
                        float penetration      = bullet.penetration.Evaluate(Mathf.Sqrt(distanceFromStartSqr)) / 1000;
                        bool  fulllyPenetrated = penetration * leftPenetration >
                                                 ((armor == null) ? 1f : armor.EquivalentThickness) * armorData.armorThickness;
                        Vector3 finalDirect = Vector3.Lerp(ray.direction, -hit.normal, bullet.positiveCoefficient);


                        if (fulllyPenetrated)
                        {
                            currentVelocity = finalDirect * currentVelocity.magnitude * leftPenetration;
                        }
                        else
                        {
                            currPosition = hit.point;
                            bulletTrail.SetPosition(1, currPosition);
                        }
                        float hitAngle = Vector3.Angle(currentVelocity, -hit.normal);

                        if (bulletType != PooledBulletTypes.Explosive) //dont do bullet damage if it is explosive
                        {
                            float impactVelocity = currentVelocity.magnitude;
                            if (dragType == BulletDragTypes.AnalyticEstimate)
                            {
                                float analyticDragVelAdjustment =
                                    (float)
                                    FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(currPosition),
                                                                FlightGlobals.getExternalTemperature(currPosition));
                                analyticDragVelAdjustment *= flightTimeElapsed * initialSpeed;
                                analyticDragVelAdjustment += 2 * ballisticCoefficient;

                                analyticDragVelAdjustment = 2 * ballisticCoefficient * initialSpeed / analyticDragVelAdjustment;
                                //velocity as a function of time under the assumption of a projectile only acted upon by drag with a constant drag area

                                analyticDragVelAdjustment = analyticDragVelAdjustment - initialSpeed;
                                //since the above was velocity as a function of time, but we need a difference in drag, subtract the initial velocity
                                //the above number should be negative...
                                impactVelocity += analyticDragVelAdjustment; //so add it to the impact velocity

                                if (impactVelocity < 0)
                                {
                                    impactVelocity = 0;
                                    //clamp the velocity to > 0, since it could drop below 0 if the bullet is fired upwards
                                }
                                //Debug.Log("flight time: " + flightTimeElapsed + " BC: " + ballisticCoefficient + "\ninit speed: " + initialSpeed + " vel diff: " + analyticDragVelAdjustment);
                            }

                            //hitting a vessel Part

                            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                            /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE START//////////////////////////////////////////////////////////////
                            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


                            if (hitPart != null) //see if it will ricochet of the part
                            {
                                penetrated = !RicochetOnPart(hitPart, hitAngle, impactVelocity);
                            }
                            else //see if it will ricochet off scenery
                            {
                                float reflectRandom = UnityEngine.Random.Range(-75f, 90f);
                                if (reflectRandom > 90 - hitAngle)
                                {
                                    penetrated = false;
                                }
                            }


                            if (hitPart != null && !hitPart.partInfo.name.Contains("Strut"))
                            //when a part is hit, execute damage code (ignores struts to keep those from being abused as armor)(no, because they caused weird bugs :) -BahamutoD)
                            {
                                float heatDamage = (mass / (hitPart.crashTolerance * hitPart.mass)) * impactVelocity *
                                                   impactVelocity * BDArmorySettings.DMG_MULTIPLIER *
                                                   bulletDmgMult
                                ;
                                //how much heat damage will be applied based on bullet mass, velocity, and part's impact tolerance and mass
                                if (!penetrated)
                                {
                                    heatDamage = heatDamage / 8;
                                }
                                if (fulllyPenetrated)
                                {
                                    heatDamage /= 8;
                                }
                                if (BDArmorySettings.INSTAKILL)
                                //instakill support, will be removed once mod becomes officially MP
                                {
                                    heatDamage = (float)hitPart.maxTemp + 100;
                                    //make heat damage equal to the part's max temperture, effectively instakilling any part it hits
                                }
                                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                                {
                                    Debug.Log("[BDArmory]: Hit! damage applied: " + heatDamage); //debugging stuff
                                }
                                if (hitPart.vessel != sourceVessel)
                                {
                                    hitPart.AddDamage(heatDamage);
                                }

                                float overKillHeatDamage = (float)(hitPart.temperature - hitPart.maxTemp);

                                if (overKillHeatDamage > 0)
                                //if the part is destroyed by overheating, we want to add the remaining heat to attached parts.  This prevents using tiny parts as armor
                                {
                                    overKillHeatDamage *= hitPart.crashTolerance; //reset to raw damage
                                    float numConnectedParts = hitPart.children.Count;
                                    if (hitPart.parent != null)
                                    {
                                        numConnectedParts++;
                                        overKillHeatDamage /= numConnectedParts;
                                        hitPart.parent.AddDamage(overKillHeatDamage /
                                                                 (hitPart.parent.crashTolerance * hitPart.parent.mass));

                                        for (int i = 0; i < hitPart.children.Count; i++)
                                        {
                                            hitPart.children[i].AddDamage(overKillHeatDamage /
                                                                          hitPart.children[i].crashTolerance);
                                        }
                                    }
                                    else
                                    {
                                        overKillHeatDamage /= numConnectedParts;
                                        for (int i = 0; i < hitPart.children.Count; i++)
                                        {
                                            hitPart.children[i].AddDamage(overKillHeatDamage /
                                                                          hitPart.children[i].crashTolerance);
                                        }
                                    }
                                }
                            }

                            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                            /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE END////////////////////////////////////////////////////////////////
                            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


                            //hitting a Building
                            DestructibleBuilding hitBuilding = null;
                            try
                            {
                                hitBuilding = hit.collider.gameObject.GetComponentUpwards <DestructibleBuilding>();
                            }
                            catch (NullReferenceException)
                            {
                            }
                            if (hitBuilding != null && hitBuilding.IsIntact)
                            {
                                float damageToBuilding = mass * initialSpeed * initialSpeed * BDArmorySettings.DMG_MULTIPLIER /
                                                         12000;
                                if (!penetrated)
                                {
                                    damageToBuilding = damageToBuilding / 8;
                                }
                                hitBuilding.AddDamage(damageToBuilding);
                                if (hitBuilding.Damage > hitBuilding.impactMomentumThreshold)
                                {
                                    hitBuilding.Demolish();
                                }
                                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                                {
                                    Debug.Log("[BDArmory]: bullet hit destructible building! Damage: " +
                                              (damageToBuilding).ToString("0.00") + ", total Damage: " + hitBuilding.Damage);
                                }
                            }
                        }

                        if (hitPart == null || (hitPart != null && hitPart.vessel != sourceVessel))
                        {
                            if (!penetrated && !hasBounced && !fulllyPenetrated)
                            {
                                //ricochet
                                hasBounced = true;
                                if (BDArmorySettings.BULLET_HITS)
                                {
                                    BulletHitFX.CreateBulletHit(hit.point, hit.normal, true);
                                }

                                tracerStartWidth /= 2;
                                tracerEndWidth   /= 2;

                                transform.position = hit.point;
                                currentVelocity    = Vector3.Reflect(currentVelocity, hit.normal);
                                currentVelocity    = (hitAngle / 150) * currentVelocity * 0.65f;

                                Vector3 randomDirection = UnityEngine.Random.rotation * Vector3.one;

                                currentVelocity = Vector3.RotateTowards(currentVelocity, randomDirection,
                                                                        UnityEngine.Random.Range(0f, 5f) * Mathf.Deg2Rad, 0);
                            }
                            else
                            {
                                if (bulletType == PooledBulletTypes.Explosive)
                                {
                                    ExplosionFX.CreateExplosion(hit.point - (ray.direction * 0.1f), radius, blastPower,
                                                                blastHeat, sourceVessel, currentVelocity.normalized, explModelPath, explSoundPath);
                                }
                                else if (BDArmorySettings.BULLET_HITS)
                                {
                                    BulletHitFX.CreateBulletHit(hit.point, hit.normal, false);
                                }


                                if (armor != null &&
                                    (penetration * leftPenetration > armor.outerArmorThickness / 1000 * armor.EquivalentThickness ||
                                     fulllyPenetrated))
                                {
                                    switch (armor.explodeMode)
                                    {
                                    case BDArmor.ExplodeMode.Always:
                                        armor.CreateExplosion(hitPart);
                                        break;

                                    case BDArmor.ExplodeMode.Dynamic:
                                        float probability = CalculateExplosionProbability(hitPart);
                                        if (probability > 0.1f)
                                        {
                                            armor.CreateExplosion(hitPart);
                                        }
                                        break;

                                    case BDArmor.ExplodeMode.Never:
                                        break;
                                    }
                                }
                                if (fulllyPenetrated)
                                {
                                    leftPenetration   -= armorData.armorThickness / penetration;
                                    transform.position = armorData.hitResultOut.point;
                                    flightTimeElapsed -= Time.fixedDeltaTime;
                                    prevPosition       = transform.position;
                                    FixedUpdate();
                                    return;
                                }
                                else
                                {
                                    KillBullet();
                                    return;
                                }
                            }
                        }
                    }
                } catch (NullReferenceException e) // Exception handling
                {
                    Debug.Log("[BDArmory]: Ran afoul of exception filter\n" + e.StackTrace);
                }
            }

            if (bulletType == PooledBulletTypes.Explosive && airDetonation && distanceFromStartSqr > detonationRange * detonationRange)
            {
                //detonate
                ExplosionFX.CreateExplosion(transform.position, radius, blastPower, blastHeat, sourceVessel,
                                            currentVelocity.normalized, explModelPath, explSoundPath);
                //GameObject.Destroy(gameObject); //destroy bullet on collision
                KillBullet();
                return;
            }


            prevPosition = currPosition;

            //move bullet
            transform.position += currentVelocity * Time.fixedDeltaTime;
        }
Ejemplo n.º 13
0
        public static void DoExplosionRay(Ray ray, float power, float heat, float maxDistance, ref List <Part> ignoreParts, ref List <DestructibleBuilding> ignoreBldgs, Vessel sourceVessel = null)
        {
            RaycastHit rayHit;

            //KerbalEVA hitEVA = null;
            //if (Physics.Raycast(ray, out rayHit, maxDistance, 2228224))
            //{
            //    float sqrDist = (rayHit.point - ray.origin).sqrMagnitude;
            //    float sqrMaxDist = maxDistance * maxDistance;
            //    float distanceFactor = Mathf.Clamp01((sqrMaxDist - sqrDist) / sqrMaxDist);

            //    try
            //    {
            //        hitEVA = rayHit.collider.gameObject.GetComponentUpwards<KerbalEVA>();
            //        if (hitEVA != null)
            //            Debug.Log("[BDArmory]:Hit on kerbal confirmed!");
            //    }
            //    catch (System.NullReferenceException)
            //    {
            //        Debug.Log("[BDArmory]:Whoops ran amok of the exception handler");
            //    }

            //    Part part = hitEVA.part;
            //    Vessel missileSource = null;
            //    if (sourceVessel != null)
            //    {
            //        MissileBase ml = part.FindModuleImplementing<MissileBase>();
            //        if (ml)
            //        {
            //            missileSource = ml.SourceVessel;
            //        }
            //    }


            //    if (!ignoreParts.Contains(part) && part.physicalSignificance == Part.PhysicalSignificance.FULL &&
            //        (!sourceVessel || sourceVessel != missileSource))
            //    {
            //        ignoreParts.Add(part);
            //        Rigidbody rb = part.GetComponent<Rigidbody>();
            //        if (rb)
            //        {
            //            rb.AddForceAtPosition(ray.direction * power * distanceFactor * ExplosionImpulseMultiplier,
            //                rayHit.point, ForceMode.Impulse);
            //        }
            //        if (heat < 0)
            //        {
            //            heat = power;
            //        }
            //        float heatDamage = (BDArmorySettings.DMG_MULTIPLIER / 100) * ExplosionHeatMultiplier * heat *
            //                           distanceFactor / part.crashTolerance;
            //        float excessHeat = Mathf.Max(0, (float)(part.temperature + heatDamage - part.maxTemp));
            //        part.AddDamage(heatDamage);
            //        if (BDArmorySettings.DRAW_DEBUG_LABELS)
            //            Debug.Log("[BDArmory]:====== Explosion ray hit part! Damage: " + heatDamage);
            //        if (excessHeat > 0 && part.parent)
            //        {
            //            part.parent.AddDamage(excessHeat);
            //        }
            //        return;
            //    }
            //}

            if (Physics.Raycast(ray, out rayHit, maxDistance, 688129))
            {
                float sqrDist        = (rayHit.point - ray.origin).sqrMagnitude;
                float sqrMaxDist     = maxDistance * maxDistance;
                float distanceFactor = Mathf.Clamp01((sqrMaxDist - sqrDist) / sqrMaxDist);
                //parts
                KerbalEVA eva  = rayHit.collider.gameObject.GetComponentUpwards <KerbalEVA>();
                Part      part = eva ? eva.part : rayHit.collider.GetComponentInParent <Part>();

                if (part)
                {
                    Vessel missileSource = null;
                    if (sourceVessel != null)
                    {
                        MissileBase ml = part.FindModuleImplementing <MissileBase>();
                        if (ml)
                        {
                            missileSource = ml.SourceVessel;
                        }
                    }


                    if (!ignoreParts.Contains(part) && part.physicalSignificance == Part.PhysicalSignificance.FULL &&
                        (!sourceVessel || sourceVessel != missileSource))
                    {
                        ignoreParts.Add(part);
                        Rigidbody rb = part.GetComponent <Rigidbody>();
                        if (rb)
                        {
                            rb.AddForceAtPosition(ray.direction * power * distanceFactor * ExplosionImpulseMultiplier,
                                                  rayHit.point, ForceMode.Impulse);
                        }
                        if (heat < 0)
                        {
                            heat = power;
                        }
                        float heatDamage = (BDArmorySettings.DMG_MULTIPLIER / 100) * ExplosionHeatMultiplier * heat *
                                           distanceFactor / part.crashTolerance;
                        float excessHeat = Mathf.Max(0, (float)(part.temperature + heatDamage - part.maxTemp));
                        part.AddDamage(heatDamage);
                        if (BDArmorySettings.DRAW_DEBUG_LABELS)
                        {
                            Debug.Log("[BDArmory]:====== Explosion ray hit part! Damage: " + heatDamage);
                        }
                        if (excessHeat > 0 && part.parent)
                        {
                            part.parent.AddDamage(excessHeat);
                        }
                        return;
                    }
                }

                //buildings
                DestructibleBuilding building = rayHit.collider.GetComponentInParent <DestructibleBuilding>();
                if (building && !ignoreBldgs.Contains(building))
                {
                    ignoreBldgs.Add(building);
                    float damageToBuilding = (BDArmorySettings.DMG_MULTIPLIER / 100) * ExplosionHeatMultiplier * 0.00645f *
                                             power * distanceFactor;
                    if (damageToBuilding > building.impactMomentumThreshold / 10)
                    {
                        building.AddDamage(damageToBuilding);
                    }
                    if (building.Damage > building.impactMomentumThreshold)
                    {
                        building.Demolish();
                    }
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("[BDArmory]:== Explosion hit destructible building! Damage: " +
                                  (damageToBuilding).ToString("0.00") + ", total Damage: " + building.Damage);
                    }
                }
            }
        }