Esempio n. 1
0
        void Update()
        {
            if (!gameObject.activeInHierarchy || !HighLogic.LoadedSceneIsFlight || BDArmorySetup.GameIsPaused)
            {
                return;
            }
            transform.rotation = Quaternion.FromToRotation(Vector3.up, -FlightGlobals.getGeeForceAtPosition(transform.position));
            PartResource fuel   = parentPart.Resources.Where(pr => pr.resourceName == "LiquidFuel").FirstOrDefault();
            var          engine = parentPart.FindModuleImplementing <ModuleEngines>();

            if (engine != null)
            {
                if (engine.enabled)
                {
                    if (parentPart.RequestResource("LiquidFuel", (double)(burnRate * TimeWarp.deltaTime)) <= 0)
                    {
                        hasFuel = false;
                    }
                }
            }
            else
            {
                if (fuel != null)
                {
                    if (fuel.amount > (fuel.maxAmount * 0.15f) || (fuel.amount > 0 && fuel.amount < (fuel.maxAmount * 0.10f)))
                    {
                        fuel.amount -= (burnRate * TimeWarp.deltaTime);
                    }
                    else if (fuel.amount < (fuel.maxAmount * 0.15f) && fuel.amount > (fuel.maxAmount * 0.10f))
                    {
                        Detonate();
                    }
                    else
                    {
                        hasFuel = false;
                    }
                }
                PartResource ox = parentPart.Resources.Where(pr => pr.resourceName == "Oxidizer").FirstOrDefault();
                if (ox != null)
                {
                    if (ox.amount > 0)
                    {
                        ox.amount -= (burnRate * TimeWarp.deltaTime);
                    }
                    else
                    {
                        hasFuel = false;
                    }
                }
                PartResource mp = parentPart.Resources.Where(pr => pr.resourceName == "MonoPropellant").FirstOrDefault();
                if (mp != null)
                {
                    if (mp.amount > (mp.maxAmount * 0.15f) || (mp.amount > 0 && mp.amount < (mp.maxAmount * 0.10f)))
                    {
                        mp.amount -= (burnRate * TimeWarp.deltaTime);
                    }
                    else if (mp.amount < (mp.maxAmount * 0.15f) && mp.amount > (mp.maxAmount * 0.10f))
                    {
                        Detonate();
                    }
                    else
                    {
                        hasFuel = false;
                    }
                }
                PartResource ec = parentPart.Resources.Where(pr => pr.resourceName == "ElectricCharge").FirstOrDefault();
                if (ec != null)
                {
                    if (ec.amount > 0)
                    {
                        ec.amount -= (burnRate * TimeWarp.deltaTime);
                        Mathf.Clamp((float)ec.amount, 0, Mathf.Infinity);
                    }
                    if ((Time.time - startTime > 30) && engine == null)
                    {
                        Detonate();
                    }
                }
            }
            if ((!hasFuel && disableTime < 0 && burnTime < 0) || (burnTime > 0 && disableTime < 0 && Time.time - startTime > burnTime))
            {
                disableTime = Time.time; //grab time when emission stops
                foreach (var pe in pEmitters)
                {
                    if (pe != null)
                    {
                        pe.emit = false;
                    }
                }
            }
            if (disableTime > 0 && Time.time - disableTime > _highestEnergy) //wait until last emitted particle has finished
            {
                gameObject.SetActive(false);
            }
            if (BDArmorySettings.BATTLEDAMAGE && BDArmorySettings.BD_FIRE_DOT)
            {
                parentPart.AddDamage(BDArmorySettings.BD_FIRE_DAMAGE * Time.deltaTime);
                ////////////////////////////////////////////////
                if (ScoreAccumulator >= 1)
                {
                    ScoreAccumulator = 0;
                    var aName = SourceVessel;
                    var tName = parentPart.vessel.GetName();

                    if (aName != null && tName != null && aName != tName && BDACompetitionMode.Instance.Scores.ContainsKey(aName) && BDACompetitionMode.Instance.Scores.ContainsKey(tName))
                    {
                        if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                        {
                            BDAScoreService.Instance.TrackDamage(aName, tName, BDArmorySettings.BD_FIRE_DAMAGE);
                        }
                        var aData = BDACompetitionMode.Instance.Scores[aName];
                        aData.Score += 1;

                        if (parentPart.vessel.GetName() == "Pinata")
                        {
                            aData.PinataHits++;
                        }

                        var tData = BDACompetitionMode.Instance.Scores[tName];
                        tData.lastPersonWhoHitMe = aName;
                        tData.lastHitTime        = Planetarium.GetUniversalTime();
                        tData.everyoneWhoHitMe.Add(aName);
                        // Track hits
                        if (tData.hitCounts.ContainsKey(aName))
                        {
                            ++tData.hitCounts[aName];
                        }
                        else
                        {
                            tData.hitCounts.Add(aName, 1);
                        }
                        // Track damage
                        if (tData.damageFromBullets.ContainsKey(aName))
                        {
                            tData.damageFromBullets[aName] += BDArmorySettings.BD_FIRE_DAMAGE;
                        }
                        else
                        {
                            tData.damageFromBullets.Add(aName, BDArmorySettings.BD_FIRE_DAMAGE);
                        }
                    }
                }
                else
                {
                    ScoreAccumulator += 1 * Time.deltaTime;
                }
            }
            ////////////////////////////////////////////
        }
Esempio n. 2
0
        private void ApplyDamage(Part hitPart, RaycastHit hit)
        {
            //hitting a vessel Part
            //No struts, they cause weird bugs :) -BahamutoD
            if (hitPart == null)
            {
                return;
            }
            if (hitPart.partInfo.name.Contains("Strut"))
            {
                return;
            }
            float explDamage = 0;

            if (BDArmorySettings.BULLET_HITS)
            {
                BulletHitFX.CreateBulletHit(hitPart, hit.point, hit, hit.normal, false, 200, 3);
            }
            if (CASELevel == 2)
            {
                explDamage = 100;
                hitPart.AddDamage(explDamage);
                float armorToReduce = hitPart.GetArmorThickness() * 0.25f;
                hitPart.ReduceArmor(armorToReduce);
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BD DEBUG]" + hitPart.name + "damaged, armor reduced by " + armorToReduce);
                }
            }
            else //CASE I
            {
                explDamage = (hitPart.Modules.GetModule <HitpointTracker>().GetMaxHitpoints() * 0.9f);
                explDamage = Mathf.Clamp(explDamage, 0, 600);
                hitPart.AddDamage(explDamage);
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BD DEBUG]" + hitPart.name + "damaged for " + (hitPart.MaxDamage() * 0.9f));
                }
                if (BDArmorySettings.BATTLEDAMAGE)
                {
                    Misc.BattleDamageHandler.CheckDamageFX(hitPart, 200, 3, true, SourceVessel, hit);
                }
            }
            {
                var aName = SourceVessel;
                var tName = part.vessel.GetName();

                if (aName != null && tName != null && aName != tName && BDACompetitionMode.Instance.Scores.ContainsKey(aName) && BDACompetitionMode.Instance.Scores.ContainsKey(tName))
                {
                    if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                    {
                        BDAScoreService.Instance.TrackDamage(aName, tName, explDamage);
                    }
                    var aData = BDACompetitionMode.Instance.Scores[aName];
                    aData.Score += 1;

                    if (part.vessel.GetName() == "Pinata")
                    {
                        aData.PinataHits++;
                    }

                    var tData = BDACompetitionMode.Instance.Scores[tName];
                    tData.lastPersonWhoHitMe = aName;
                    tData.lastHitTime        = Planetarium.GetUniversalTime();
                    tData.everyoneWhoHitMe.Add(aName);
                    // Track hits
                    if (tData.hitCounts.ContainsKey(aName))
                    {
                        ++tData.hitCounts[aName];
                    }
                    else
                    {
                        tData.hitCounts.Add(aName, 1);
                    }
                    // Track damage
                    if (tData.damageFromBullets.ContainsKey(aName))
                    {
                        tData.damageFromBullets[aName] += explDamage;
                    }
                    else
                    {
                        tData.damageFromBullets.Add(aName, explDamage);
                    }
                }
            }
        }
Esempio n. 3
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);
                    }
                }
            }
        }
Esempio n. 4
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;
        }
Esempio n. 5
0
        void Update()
        {
            if (!gameObject.activeInHierarchy || !HighLogic.LoadedSceneIsFlight || BDArmorySetup.GameIsPaused)
            {
                return;
            }
            transform.rotation = Quaternion.FromToRotation(Vector3.up, -FlightGlobals.getGeeForceAtPosition(transform.position));
            fuel = parentPart.Resources.Where(pr => pr.resourceName == "LiquidFuel").FirstOrDefault();
            if (disableTime < 0)  //only have fire do it's stuff while burning and not during FX timeout
            {
                if (!surfaceFire) //is fire inside tank, or an incendiary substance on the part's surface?
                {
                    if (!lookedForEngine)
                    {
                        engine          = parentPart.FindModuleImplementing <ModuleEngines>();
                        lookedForEngine = true; //have this only called once, not once per update tick
                    }
                    if (engine != null)
                    {
                        if (engine.throttleLocked && !engine.allowShutdown) //likely a SRB
                        {
                            if (parentPart.RequestResource("SolidFuel", (double)(burnRate * TimeWarp.deltaTime)) <= 0)
                            {
                                hasFuel = false;
                            }
                            solid = parentPart.Resources.Where(pr => pr.resourceName == "SolidFuel").FirstOrDefault();
                            if (solid != null)
                            {
                                if (solid.amount < solid.maxAmount * 0.66f)
                                {
                                    engine.Activate(); //SRB lights from unintended ignition source
                                }
                                if (solid.amount < solid.maxAmount * 0.15f)
                                {
                                    tntMassEquivilent += Mathf.Clamp((float)solid.amount, ((float)solid.maxAmount * 0.05f), ((float)solid.maxAmount * 0.2f));
                                    Detonate(); //casing's full of holes and SRB fuel's burnt to the point it can easily start venting through those holes
                                }
                            }
                        }
                        else
                        {
                            if (engine.EngineIgnited)
                            {
                                if (parentPart.RequestResource("LiquidFuel", (double)(burnRate * TimeWarp.deltaTime)) <= 0)
                                {
                                    hasFuel = false;
                                }
                            }
                            else
                            {
                                hasFuel = false;
                            }
                        }
                    }
                    else
                    {
                        if (fuel != null)
                        {
                            if (fuel.amount > (fuel.maxAmount * 0.15f) || (fuel.amount > 0 && fuel.amount < (fuel.maxAmount * 0.10f)))
                            {
                                fuel.amount -= (burnRate * Mathf.Clamp((float)((1 - (fuel.amount / fuel.maxAmount)) * 4), 0.1f * BDArmorySettings.BD_TANK_LEAK_RATE, 4 * BDArmorySettings.BD_TANK_LEAK_RATE) * TimeWarp.deltaTime);
                                burnScale    = Mathf.Clamp((float)((1 - (fuel.amount / fuel.maxAmount)) * 4), 0.1f * BDArmorySettings.BD_TANK_LEAK_RATE, 2 * BDArmorySettings.BD_TANK_LEAK_RATE);
                            }
                            else if (fuel.amount < (fuel.maxAmount * 0.15f) && fuel.amount > (fuel.maxAmount * 0.10f))
                            {
                                Detonate();
                            }
                            else
                            {
                                hasFuel = false;
                            }
                        }
                        ox = parentPart.Resources.Where(pr => pr.resourceName == "Oxidizer").FirstOrDefault();
                        if (ox != null)
                        {
                            if (ox.amount > 0)
                            {
                                ox.amount -= (burnRate * Mathf.Clamp((float)((1 - (ox.amount / ox.maxAmount)) * 4), 0.1f * BDArmorySettings.BD_TANK_LEAK_RATE, 4 * BDArmorySettings.BD_TANK_LEAK_RATE) * TimeWarp.deltaTime);
                            }
                            else
                            {
                                hasFuel = false;
                            }
                        }
                        mp = parentPart.Resources.Where(pr => pr.resourceName == "MonoPropellant").FirstOrDefault();
                        if (mp != null)
                        {
                            if (mp.amount > (mp.maxAmount * 0.15f) || (mp.amount > 0 && mp.amount < (mp.maxAmount * 0.10f)))
                            {
                                mp.amount -= (burnRate * Mathf.Clamp((float)((1 - (mp.amount / mp.maxAmount)) * 4), 0.1f * BDArmorySettings.BD_TANK_LEAK_RATE, 4 * BDArmorySettings.BD_TANK_LEAK_RATE) * TimeWarp.deltaTime);
                                if (burnScale < 0)
                                {
                                    burnScale = Mathf.Clamp((float)((1 - (mp.amount / mp.maxAmount)) * 4), 0.1f * BDArmorySettings.BD_TANK_LEAK_RATE, 2 * BDArmorySettings.BD_TANK_LEAK_RATE);
                                }
                            }
                            else if (mp.amount < (mp.maxAmount * 0.15f) && mp.amount > (mp.maxAmount * 0.10f))
                            {
                                Detonate();
                            }
                            else
                            {
                                hasFuel = false;
                            }
                        }
                        ec = parentPart.Resources.Where(pr => pr.resourceName == "ElectricCharge").FirstOrDefault();
                        if (ec != null)
                        {
                            if (ec.amount > 0)
                            {
                                ec.amount -= (burnRate * TimeWarp.deltaTime);
                                Mathf.Clamp((float)ec.amount, 0, Mathf.Infinity);
                                if (burnScale < 0)
                                {
                                    burnScale = 1;
                                }
                            }
                            if ((Time.time - startTime > 30) && engine == null)
                            {
                                Detonate();
                            }
                        }
                    }
                }
                if (BDArmorySettings.BD_FIRE_HEATDMG)
                {
                    if (parentPart.temperature < 1300)
                    {
                        if (fuel != null)
                        {
                            parentPart.temperature += burnRate * Mathf.Clamp((float)((1 - (fuel.amount / fuel.maxAmount)) * 4), 0.1f * BDArmorySettings.BD_TANK_LEAK_RATE, 4 * BDArmorySettings.BD_TANK_LEAK_RATE) * Time.deltaTime;
                        }
                        else if (mp != null)
                        {
                            parentPart.temperature += burnRate * Mathf.Clamp((float)((1 - (mp.amount / mp.maxAmount)) * 4), 0.1f * BDArmorySettings.BD_TANK_LEAK_RATE, 4 * BDArmorySettings.BD_TANK_LEAK_RATE) * Time.deltaTime;
                        }
                        else if (ec != null || ox != null)
                        {
                            parentPart.temperature += burnRate * BDArmorySettings.BD_FIRE_DAMAGE * Time.deltaTime;
                        }
                    }
                }
                if (BDArmorySettings.BATTLEDAMAGE && BDArmorySettings.BD_FIRE_DOT)
                {
                    if (BDArmorySettings.BD_FIRE_HEATDMG)
                    {
                        if (parentPart.temperature > 1000)
                        {
                            parentPart.AddDamage(BDArmorySettings.BD_FIRE_DAMAGE * Time.deltaTime);
                        }
                    }
                    else
                    {
                        parentPart.AddDamage(BDArmorySettings.BD_FIRE_DAMAGE * Time.deltaTime);
                    }
                    ////////////////////////////////////////////////

                    ScoreAccumulator = 0;
                    var aName = SourceVessel;
                    var tName = parentPart.vessel.GetName();

                    if (aName != null && tName != null && aName != tName && BDACompetitionMode.Instance.Scores.ContainsKey(aName) && BDACompetitionMode.Instance.Scores.ContainsKey(tName))
                    {
                        if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                        {
                            BDAScoreService.Instance.TrackDamage(aName, tName, BDArmorySettings.BD_FIRE_DAMAGE);
                        }
                        // Track damage. Moving this here to properly track damage per tick
                        var tData = BDACompetitionMode.Instance.Scores[tName];
                        if (tData.damageFromBullets.ContainsKey(aName))
                        {
                            tData.damageFromBullets[aName] += BDArmorySettings.BD_FIRE_DAMAGE;
                        }
                        else
                        {
                            tData.damageFromBullets.Add(aName, BDArmorySettings.BD_FIRE_DAMAGE);
                        }

                        if (ScoreAccumulator >= 1) //could be reduced, gaining +1 hit per sec, per fire seems high
                        {
                            var aData = BDACompetitionMode.Instance.Scores[aName];
                            aData.Score += 1;

                            if (parentPart.vessel.GetName() == "Pinata")
                            {
                                aData.PinataHits++;
                            }
                            tData.lastPersonWhoHitMe = aName;
                            tData.lastHitTime        = Planetarium.GetUniversalTime();
                            tData.everyoneWhoHitMe.Add(aName);
                            // Track hits
                            if (tData.hitCounts.ContainsKey(aName))
                            {
                                ++tData.hitCounts[aName];
                            }
                            else
                            {
                                tData.hitCounts.Add(aName, 1);
                            }
                        }
                    }
                    else
                    {
                        ScoreAccumulator += 1 * Time.deltaTime;
                    }
                }
            }
            if ((!hasFuel && disableTime < 0 && burnTime < 0) || (burnTime > 0 && disableTime < 0 && Time.time - startTime > burnTime))
            {
                disableTime = Time.time; //grab time when emission stops
                foreach (var pe in pEmitters)
                {
                    if (pe != null)
                    {
                        pe.emit = false;
                    }
                }
            }
            else
            {
                foreach (var pe in pEmitters)
                {
                    pe.maxSize = burnScale;
                    pe.minSize = burnScale * 1.2f;
                }
            }
            if (disableTime > 0 && Time.time - disableTime > _highestEnergy) //wait until last emitted particle has finished
            {
                gameObject.SetActive(false);
            }
            if (engine != null && enginerestartTime > 0 && Time.time - 10 > enginerestartTime)
            {
                engine.Activate();
                enginerestartTime = -1;
            }
            ////////////////////////////////////////////
        }