Esempio n. 1
0
 private void FindPotato()
 {
     _potato = part.FindModulesImplementing<ModuleAsteroid>().FirstOrDefault();
     _tank = part.FindModulesImplementing<USI_DynamicTank>().FirstOrDefault();
     if (OriginalMass < ResourceUtilities.FLOAT_TOLERANCE)
     {
         OriginalMass = _potato.part.mass;
     }
 }
Esempio n. 2
0
 public override void OnStart(StartState state)
 {
     base.OnStart(state);
     part.fuelCrossFeed = false; //fuel? cross feed? through an asteroid?! >_<
     orig_crash_tolerance = part.crashTolerance;
     asteroid = part.GetModule<ModuleAsteroid>();
     if(Locked) LockAsteroid();
     StartCoroutine(init_params());
 }
		private void asteroidValues(ModuleAsteroid m, float mult)
		{
			aClass = asteroidClass(m.prefabBaseURL);
			sciMult = asteroidValue(aClass) * mult;
		}
 public StockProcAsteroidGeoUpdater(ModuleAsteroid asteroid, GeometryPartModule geoModule)
 {
     this.asteroid  = asteroid;
     this.geoModule = geoModule;
 }
Esempio n. 5
0
 void asteroidSelector_onAsteroidSelected(ModuleAsteroid asteroid)
 {
     this.asteroid = asteroidSelector.asteroid;
 }
Esempio n. 6
0
        //This is where the primary animator runs
        private IEnumerator RunThumper()
        {
            bool showData = silentRun;
            bool dry      = dryRun;

            silentRun = false;
            dryRun    = true;

            float s = values.Score;

            bool  useDistance = false;
            float distance    = 0f;

            float    angle            = 0;
            Vector3  originalRotation = RotationTransform.localEulerAngles;
            float    originalAngle    = originalRotation.x;
            Vector3d hammerLine       = new Vector3d();

            if (values.OnAsteroid)
            {
                var asteroids = vessel.FindPartModulesImplementing <ModuleAsteroid>();

                ModuleAsteroid m           = null;
                float          astDistance = 2000;

                for (int i = 0; i < asteroids.Count; i++)
                {
                    ModuleAsteroid ast = asteroids[i];

                    if (ast == null)
                    {
                        continue;
                    }

                    float d = (RotationTransform.position - ast.part.transform.position).magnitude;

                    if (d < astDistance)
                    {
                        astDistance = d;
                        m           = ast;
                    }
                }

                if (m == null)
                {
                    animator(-1f, 1f, Anim, hammerAnimation);
                    dryRun = true;

                    ScreenMessages.PostScreenMessage("Seismic Hammer can't find an asteroid to impact...", 6f, ScreenMessageStyle.UPPER_CENTER);
                    yield break;
                }

                hammerLine = RotationTransform.InverseTransformPoint(m.part.transform.position);
            }
            else
            {
                //First we draw a line from the rotation transform object to the point on the surface directly below it
                Vector3d surfacePos = vessel.mainBody.GetWorldSurfacePosition(vessel.mainBody.GetLatitude(RotationTransform.position), vessel.mainBody.GetLongitude(RotationTransform.position), vessel.pqsAltitude);
                hammerLine = RotationTransform.InverseTransformPoint(surfacePos);
            }

            //Take any changes to the rescale factor into account
            float scale = part.rescaleFactor * scaleModifier * modelTransform.localScale.y;

            //Make a first distance check before anything moves; this will only be used if the angle is small and prevents errors where the drill punches through the surface
            if (rayImpact(values.OnAsteroid, ExtensionTransform, scale, 2.45f + 1.41f, out distance))
            {
                useDistance = true;

                DMUtils.DebugLog("Hammer Hit: Distance: {0:N3}", distance);

                //Subtract the distance that the hammer body will move
                distance -= (1.41f * scale);

                DMUtils.DebugLog("Hammer Hit: New Distance: {0:N3}", distance);
            }

            //Calculate the angle on the Z axis
            angle = Mathf.Atan2((float)hammerLine.y, (float)hammerLine.z) * Mathf.Rad2Deg;

            //Make sure the angle is within a normal range
            angle = normalizeAngle(angle);

            DMUtils.DebugLog("Hammer Angle: {0:N7}", angle);

            //Clamp the rotation between maximum limits for the model
            angle = Mathf.Clamp(angle, -30, 90);

            //Reverse the angle to compensate for initial transform rotation
            angle *= -1;

            //If the angle is small enough use the first distance calculated
            if (useDistance && Mathf.Abs(angle) < 15)
            {
                useDistance = true;
            }
            else
            {
                useDistance = false;
            }

            DMUtils.DebugLog("Clamped Angle: {0:N7}", angle);

            //Wait while the primary animator is playing so that the hammer transform can clear the base
            while (Anim.IsPlaying(hammerAnimation) && Anim[hammerAnimation].normalizedTime < 0.03f)
            {
                yield return(null);
            }

            DMUtils.DebugLog("Hammer Starting Angle: {0:N7}", RotationTransform.localEulerAngles.x);

            //Cache the original rotation angle of the transform and calculate the target angle
            float newAngle = fixAngle(originalAngle + angle);

            DMUtils.DebugLog("New Angle: {0:N7}", newAngle);

            //Rotate the transform while the primary animator is playing; only allow this to go on for a certain amount of time

            //Rotation check is dependent on the sign of the target rotation angle
            if (angle > 0)
            {
                while (Anim.IsPlaying(hammerAnimation) && Anim[hammerAnimation].normalizedTime < 0.30f && RotationTransform.localEulerAngles.x < newAngle)
                {
                    //DMUtils.DebugLog("Rotation positive: {0:N7}", RotationTransform.localEulerAngles.x);
                    rotation(angle, TimeWarp.deltaTime * 30f);
                    yield return(null);
                }
            }
            else if (angle < 0)
            {
                while (Anim.IsPlaying(hammerAnimation) && Anim[hammerAnimation].normalizedTime <0.30f && fixAngle(RotationTransform.localEulerAngles.x)> newAngle)
                {
                    //DMUtils.DebugLog("Rotation negative: {0:N7}", RotationTransform.localEulerAngles.x);
                    rotation(angle, TimeWarp.deltaTime * 30f);
                    yield return(null);
                }
            }

            while (Anim.IsPlaying(hammerAnimation) && Anim[hammerAnimation].normalizedTime < 0.32f)
            {
                yield return(null);
            }

            DMUtils.DebugLog("Checking Distance To Terrain...");

            if (!useDistance)
            {
                //After the transform is rotated and pointing at the surface draw a ray from the extension transform; check for impacts on the terrain
                if (!rayImpact(values.OnAsteroid, ExtensionTransform, scale, 2.45f, out distance))
                {
                    //If no impact is detected within the distance limit stop the animation, reverse the rotation, and cancel the coroutine
                    DMUtils.DebugLog("Hammer Failed: Distance: {0:N3}", distance);
                    animator(-1f, 1f, Anim, hammerAnimation);

                    ScreenMessages.PostScreenMessage("Seismic Hammer can't impact the surface from here...", 6f, ScreenMessageStyle.UPPER_CENTER);

                    if (angle > 0)
                    {
                        while (Anim.IsPlaying(hammerAnimation) && RotationTransform.localEulerAngles.x > originalAngle)
                        {
                            rotation(originalAngle, TimeWarp.deltaTime * 30f);
                            yield return(null);
                        }
                    }
                    else if (angle < 0)
                    {
                        while (Anim.IsPlaying(hammerAnimation) && fixAngle(RotationTransform.localEulerAngles.x) < fixAngle(originalAngle))
                        {
                            rotation(originalAngle, TimeWarp.deltaTime * 30f);
                            yield return(null);
                        }
                    }
                    RotationTransform.localEulerAngles = originalRotation;

                    yield break;
                }
            }

            DMUtils.DebugLog("Hammer Hit: Distance: {0:N3}", distance);

            //We have to subtract the length of the impact hammer and the extensions transform position from the impact distance, leaving only the extension transform length
            distance = distance - (0.75f * scale) - (0.6f * scale);

            DMUtils.DebugLog("Hammer Hit: Second Distance: {0:N3}", distance);

            //Transform translation does not take the part scale into account, so we need to convert the distance back into the unscaled dimensions
            distance /= scale;

            DMUtils.DebugLog("Hammer Hit: Third Distance: {0:N3}", distance);

            //We obviously don't want negative distance movements
            distance = Math.Max(0, distance);

            DMUtils.DebugLog("New Distance: {0:N5}", distance);

            //Cache the original transform position and calculate the target position
            Vector3 originalPosition = ExtensionTransform.localPosition;

            float targetPosition = originalPosition.z - distance;

            DMUtils.DebugLog("Drill Original Position: {0:N5}", originalPosition.z);

            DMUtils.DebugLog("Drill Target Position: {0:N5}", targetPosition);

            //While the animation is playing translate the extension transform out
            if (distance > 0)
            {
                while (Anim.IsPlaying(hammerAnimation) && Anim[hammerAnimation].normalizedTime <0.65f && ExtensionTransform.localPosition.z> targetPosition)
                {
                    DMUtils.DebugLog("Drill Position: {0:N5}", ExtensionTransform.localPosition.z);
                    extension(Vector3.back, TimeWarp.deltaTime);
                    yield return(null);
                }
            }

            while (Anim[hammerAnimation].normalizedTime < 0.68f)
            {
                yield return(null);
            }

            //If this is a real run gather science data, then reset the flag
            if (!dry)
            {
                getScienceData(values.OnAsteroid, showData, s);
            }

            //After the experiment has been collected reverse the rotation and translation
            if (angle > 0)
            {
                while (Anim.IsPlaying(hammerAnimation) && (ExtensionTransform.localPosition.z < originalPosition.z || RotationTransform.localEulerAngles.x > originalAngle))
                {
                    if (distance > 0)
                    {
                        if (ExtensionTransform.localPosition.z < originalPosition.z)
                        {
                            extension(Vector3.forward, TimeWarp.deltaTime);
                        }
                    }
                    if (RotationTransform.localEulerAngles.x > originalAngle)
                    {
                        rotation(originalAngle, TimeWarp.deltaTime * 30f);
                    }
                    yield return(null);
                }
            }
            else
            {
                while (Anim.IsPlaying(hammerAnimation) && (ExtensionTransform.localPosition.z < originalPosition.z || fixAngle(RotationTransform.localEulerAngles.x) < fixAngle(originalAngle)))
                {
                    if (distance > 0)
                    {
                        if (ExtensionTransform.localPosition.z < originalPosition.z)
                        {
                            extension(Vector3.forward, TimeWarp.deltaTime);
                        }
                    }
                    if (fixAngle(RotationTransform.localEulerAngles.x) < fixAngle(originalAngle))
                    {
                        rotation(originalAngle, TimeWarp.deltaTime * 30f);
                    }
                    yield return(null);
                }
            }

            while (Anim.IsPlaying(hammerAnimation))
            {
                yield return(null);
            }

            //Reset the transform positions after the primary animation has completed; this corrects and timestep errors
            RotationTransform.localEulerAngles = originalRotation;
            ExtensionTransform.localPosition   = originalPosition;
        }
 private void runExperiment(float distance, ModuleAsteroid m)
 {
     ScienceData data = makeScience(distance, m);
     if (data == null)
         Debug.LogError("[DM] Something Went Wrong Here; Null Asteroid Science Data Returned; Please Report This On The KSP Forum With Output.log Data");
     else
     {
         GameEvents.OnExperimentDeployed.Fire(data);
         scienceReports.Add(data);
         Deployed = true;
         ReviewData();
     }
 }
        private ScienceData makeScience(float dist, ModuleAsteroid m)
        {
            if (dist <= 0)
            {
                DMUtils.Logging("Asteroid Not Scanned...  Distance Passed Through Asteroid: " + dist.ToString("N3"));
                if (asteroidInSight)
                    ScreenMessages.PostScreenMessage("No Asteroid Detected Between The Transmitting And Receiving Instruments...", 6f, ScreenMessageStyle.UPPER_CENTER);
                else if (receiverInRange)
                    ScreenMessages.PostScreenMessage("No Asteroid Detected In The Scanning Area...", 6f, ScreenMessageStyle.UPPER_CENTER);
                return null;
            }
            if (m == null)
            {
                DMUtils.Logging("Asteroid Not Scanned. Something Went Wrong Here; No Asteroid Was Detected; Distance Passed Through Asteroid: " + dist.ToString("N3"));
                return null;
            }
            ScienceData data = null;
            ScienceSubject sub = null;
            CelestialBody body = null;
            DMAsteroidScience ast = null;
            string biome = "";
            float multiplier = 1f;

            ast = new DMAsteroidScience(m);
            body = ast.Body;
            biome = ast.AType + ast.ASeed;
            multiplier = Math.Min(1f, dist / astWidth[aClassInt(ast.AClass)]);

            if (exp == null)
            {
                Debug.LogError("[DM] Something Went Wrong Here; Null Asteroid Experiment Returned; Please Report This On The KSP Forum With Output.log Data");
                return null;
            }

            sub = ResearchAndDevelopment.GetExperimentSubject(exp, ExperimentSituations.InSpaceLow, body, biome);

            if (sub == null)
            {
                Debug.LogError("[DM] Something Went Wrong Here; Null Asteroid Subject Returned; Please Report This On The KSP Forum With Output.log Data");
                return null;
            }

            DMUtils.OnAsteroidScience.Fire(ast.AClass, exp.id);
            sub.title = string.Format("{0} through a {1} asteroid", exp.experimentTitle, ast.AType);
            string dataTitle = string.Format("{0} through {1:P0} of a {2} asteroid", exp.experimentTitle, multiplier, ast.AType);
            registerDMScience(ast, sub);
            body.bodyName = asteroidBodyNameFixed;

            data = new ScienceData(multiplier * exp.baseValue * sub.dataScale, transmitValue, 0f, sub.id, dataTitle);

            return data;
        }
        //Determine if the signal passes through the asteroid, and what distance it travels if so
        private float asteroidScanLength(out ModuleAsteroid m)
        {
            m = null;
            float dist = 0f;
            if (dish != null && targetModule != null)
            {
                Vector3 tPos = dish.position;
                Vector3 targetPos = targetModule.part.transform.position;
                Vector3 direction = targetPos - tPos;
                Ray r = new Ray(tPos, direction);
                RaycastHit hit = new RaycastHit();
                Physics.Raycast(r, out hit, targetDistance, 1 << 28);
                DMUtils.DebugLog("Target Distance: {0:N3}", targetDistance);

                //The first ray determines whether or not the asteroid was hit and the distance from the dish
                //to that first encounter
                if (hit.collider != null)
                {
                    string obj = hit.collider.attachedRigidbody.gameObject.name;
                    if (obj.StartsWith(potato))
                    {
                        float firstDist = hit.distance;
                        DMUtils.DebugLog("First Ray Hit; Distance: {0:N3}", firstDist);
                        Vector3 reverseDirection = tPos - targetPos;
                        Ray targetRay = new Ray(targetPos, reverseDirection);
                        RaycastHit targetHit = new RaycastHit();
                        Physics.Raycast(targetRay, out targetHit, targetDistance, 1 << 28);

                        //The second ray determines the distance from the target vessel to the asteroid
                        if (targetHit.collider != null)
                        {
                            string targetObj = targetHit.collider.attachedRigidbody.gameObject.name;
                            if (targetObj.StartsWith(potato))
                            {
                                float secondDist = targetHit.distance;
                                DMUtils.DebugLog("Second Ray Hit; Distance: {0:N3}", secondDist);
                                Part p = Part.FromGO(hit.transform.gameObject) ?? hit.transform.gameObject.GetComponentInParent<Part>();

                                if (p != null)
                                {
                                    if (p.Modules.Contains("ModuleAsteroid"))
                                        m = p.FindModuleImplementing<ModuleAsteroid>();
                                }

                                //The two distances are subtracted from the total distance between vessels to
                                //give the distance the signal travels while inside the asteroid
                                dist = targetDistance - secondDist - firstDist;

                                DMUtils.DebugLog("Asteroid Scan Distance: {0:N3}", dist);
                            }
                        }
                    }
                }
            }

            return dist;
        }
Esempio n. 10
0
        private ScienceData makeScience(float dist, ModuleAsteroid m)
        {
            if (dist <= 0)
            {
                DMUtils.Logging("Asteroid Not Scanned...  Distance Passed Through Asteroid: " + dist.ToString("N3"));
                if (asteroidInSight)
                {
                    ScreenMessages.PostScreenMessage("No Asteroid Detected Between The Transmitting And Receiving Instruments...", 6f, ScreenMessageStyle.UPPER_CENTER);
                }
                else if (receiverInRange)
                {
                    ScreenMessages.PostScreenMessage("No Asteroid Detected In The Scanning Area...", 6f, ScreenMessageStyle.UPPER_CENTER);
                }
                return(null);
            }
            if (m == null)
            {
                DMUtils.Logging("Asteroid Not Scanned. Something Went Wrong Here; No Asteroid Was Detected; Distance Passed Through Asteroid: " + dist.ToString("N3"));
                return(null);
            }
            ScienceData       data       = null;
            ScienceSubject    sub        = null;
            CelestialBody     body       = null;
            DMAsteroidScience ast        = null;
            string            biome      = "";
            float             multiplier = 1f;

            ast        = new DMAsteroidScience(m);
            body       = ast.Body;
            biome      = ast.AType + ast.ASeed;
            multiplier = Math.Min(1f, dist / astWidth[aClassInt(ast.AClass)]);

            if (exp == null)
            {
                Debug.LogError("[DM] Something Went Wrong Here; Null Asteroid Experiment Returned; Please Report This On The KSP Forum With Output.log Data");
                return(null);
            }

            sub = ResearchAndDevelopment.GetExperimentSubject(exp, ExperimentSituations.InSpaceLow, body, biome, "");

            if (sub == null)
            {
                Debug.LogError("[DM] Something Went Wrong Here; Null Asteroid Subject Returned; Please Report This On The KSP Forum With Output.log Data");
                return(null);
            }

            DMUtils.OnAsteroidScience.Fire(ast.AClass, exp.id);

            string b = ast.AType;

            string a = "a";

            if (b == "Icy-Organic")
            {
                a = "an";
            }

            string c = " asteroid";

            if (b == "Comet")
            {
                c = "";
            }

            sub.title = string.Format("{0} through {1} {2}{3}", exp.experimentTitle, a, b, c);
            string dataTitle = string.Format("{0} through {1:P0} of {2} {3}{4}", exp.experimentTitle, multiplier, a, b, c);

            registerDMScience(ast, sub);
            body.bodyName = asteroidBodyNameFixed;

            data = new ScienceData(multiplier * exp.baseValue * sub.dataScale, transmitValue, 0, sub.id, dataTitle, false, part.flightID);

            return(data);
        }
Esempio n. 11
0
        public ProspectSituations GetProspectSituation(Vessel vessel, out GoldStrikeLode lode)
        {
            ModuleAsteroid asteroid = null;

            CBAttributeMapSO.MapAttribute biome = null;
            string biomeName = string.Empty;
            int    planetID  = int.MaxValue;
            bool   vesselSituationIsValid = false;
            double longitude = 0f;
            double latitude  = 0f;
            double altitude  = 0f;

            //If we're landed then we're ok to check prospect situation.
            if (vessel.situation == Vessel.Situations.LANDED || vessel.situation == Vessel.Situations.PRELAUNCH)
            {
                biome     = Utils.GetCurrentBiome(vessel);
                biomeName = biome.name;
                planetID  = vessel.mainBody.flightGlobalsIndex;
                longitude = vessel.longitude;
                latitude  = vessel.latitude;
                altitude  = vessel.altitude;
                vesselSituationIsValid = true;
                debugLog("Vessel is landed or prelaunch");
            }

            //If we have an asteroid, then we're ok to check prospect situation.
            asteroid = vessel.FindPartModuleImplementing <ModuleAsteroid>();
            if (asteroid != null)
            {
                biomeName = asteroid.AsteroidName;
                vesselSituationIsValid = true;
                debugLog("Vessel has an asteroid");
            }

            //Is there a lode in the area?
            if (asteroid != null)
            {
                lode = FindNearestLode(asteroid);
            }
            else
            {
                lode = FindNearestLode(planetID, biomeName, vessel.longitude, vessel.latitude);
            }
            if (lode != null)
            {
                return(ProspectSituations.LodeAlreadyExists);
            }

            //If the flight situation is bad then we're done.
            if (vesselSituationIsValid == false)
            {
                return(ProspectSituations.InvalidVesselSituation);
            }

            //Is the prospect site an asteroid, and has it been prospected?
            if (asteroid != null)
            {
                if (prospectedAsteroids.Contains(asteroid.AsteroidName))
                {
                    return(ProspectSituations.AsteroidProspected);
                }

                else //Record the fact that we prospected the asteroid.
                {
                    prospectedAsteroids.Add(asteroid.AsteroidName);
                }
            }

            //Have we traveled far enough?
            else
            {
                double travelDistance = GetDistanceFromLastLocation(vessel);
                if (travelDistance < GoldStrikeSettings.DistanceBetweenProspects)
                {
                    debugLog("Calculated distance between current location and last prospect location: " + travelDistance);
                    return(ProspectSituations.NotEnoughDistance);
                }
            }

            return(ProspectSituations.Valid);
        }
Esempio n. 12
0
        public void CheckGoldStrike()
        {
            string[]              strikeResourceKeys = null;
            int                   resourceIndex;
            GoldStrikeData        strikeData          = null;
            WBIPathfinderScenario scenario            = WBIPathfinderScenario.Instance;
            string                resourceName        = string.Empty;
            double                resourceAmount      = 0f;
            float                 analysisRoll        = 0f;
            float                 successTargetNumber = prospectChance;
            string                navigationID        = string.Empty;
            GoldStrikeLode        lode      = null;
            string                biomeName = string.Empty;
            int                   planetID  = -1;

            //Do we have gold strike resources?
            if (scenario.goldStrikeResources.Count() == 0)
            {
                ScreenMessages.PostScreenMessage("There are no Gold Strike resources to prospect!", kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER);
                debugLog("No resources to prospect");
                return;
            }

            //Do we have a valid situation?
            if (SituationIsValid() == false)
            {
                return;
            }

            //Update our location.
            asteroid = this.part.vessel.FindPartModuleImplementing <ModuleAsteroid>();
            GoldStrikeUtils.GetBiomeAndPlanet(out biomeName, out planetID, this.part.vessel, asteroid);
            vesselModule.UpdateLastProspectLocation();

            //Time to see if we find anything.
            //prospectChance: base chance to find a prospect. Some parts are better than others.
            //prospectBonus: Various situations contribute to the success of the attempt.
            successTargetNumber = 100 - (prospectChance + GetProspectBonus());
            debugLog("successTargetNumber: " + successTargetNumber);

            //Roll the chance and check it.
            analysisRoll = UnityEngine.Random.Range(1, 100);
            debugLog("analysisRoll: " + analysisRoll);

            //If we didn't succeed then we're done.
            if (analysisRoll < successTargetNumber && !WBIPathfinderScenario.debugProspectAlwaysSuccessful)
            {
                debugLog("Prospect failed; didn't roll high enough.");
                ScreenMessages.PostScreenMessage("Nothing of value here, try another location. ", kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER);
                return;
            }

            //Success! Get the resource name and strike data.
            //If we're near an anomaly then we need a roll table.
            if (anomalyBonus > 0)
            {
                SortedDictionary <int, GoldStrikeData> sortedResources = new SortedDictionary <int, GoldStrikeData>();
                strikeResourceKeys = scenario.goldStrikeResources.Keys.ToArray();

                //Add any resources that have an anomaly chance into the sorted resources
                for (int index = 0; index < strikeResourceKeys.Length; index++)
                {
                    resourceName = strikeResourceKeys[index];
                    strikeData   = scenario.goldStrikeResources[resourceName];
                    if (strikeData.anomalyChance > 0)
                    {
                        sortedResources.Add(strikeData.anomalyChance, strikeData);
                    }
                }

                //Roll a 1-100
                int pressenceRoll = UnityEngine.Random.Range(1, 100);

                //See if we have any strike data
                strikeData = null;
                foreach (KeyValuePair <int, GoldStrikeData> pair in sortedResources)
                {
                    if (pressenceRoll < pair.Key)
                    {
                        strikeData = pair.Value;
                        break;
                    }
                }

                //If we don't have any strike data then pick a random resource
                if (strikeData == null)
                {
                    resourceIndex = UnityEngine.Random.Range(0, strikeResourceKeys.Length - 1);
                    resourceName  = strikeResourceKeys[resourceIndex];
                    strikeData    = scenario.goldStrikeResources[resourceName];
                }
            }

            else
            {
                strikeResourceKeys = scenario.goldStrikeResources.Keys.ToArray();
                resourceIndex      = UnityEngine.Random.Range(0, strikeResourceKeys.Length - 1);
                resourceName       = strikeResourceKeys[resourceIndex];
                strikeData         = scenario.goldStrikeResources[resourceName];
                debugLog("strikeResourceKeys count: " + strikeResourceKeys.Length);
                debugLog("resourceIndex: " + resourceIndex);
            }
            debugLog("strikeData: " + strikeData.ToString());

            //Play the jingle
            playJingle();

            //Setup a planetary surface lode
            if (asteroid == null)
            {
                debugLog("Setting up surface lode");
                //Now, generate the resource amount to add to the map
                resourceAmount = UnityEngine.Random.Range(strikeData.minAmount, strikeData.maxAmount);
                debugLog("resourceAmount: " + resourceAmount);

                //If we hit the motherlode then factor that in.
                //The motherloade is 5% of the target number.
                if (analysisRoll <= (successTargetNumber * kMotherlodeFactor))
                {
                    resourceAmount *= strikeData.motherlodeMultiplier;
                    debugLog("resourceAmount after motherlode: " + resourceAmount);
                    ScreenMessages.PostScreenMessage(string.Format("Congratulations! You found a {0:s} motherlode with {1:f2} units available to mine!", resourceName, resourceAmount),
                                                     kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER);
                }

                else
                {
                    ScreenMessages.PostScreenMessage(string.Format("Congratulations! You found a {0:s} lode with {1:f2} units available to mine!", resourceName, resourceAmount),
                                                     kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER);
                }
                if (!string.IsNullOrEmpty(anomalyName))
                {
                    ScreenMessages.PostScreenMessage("Special cache found at " + anomalyName, kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER);
                }

                debugLog("Adding new lode entry to " + FlightGlobals.currentMainBody.name + " with flight global index " + FlightGlobals.currentMainBody.flightGlobalsIndex);
                debugLog("Biome: " + biomeName);
                debugLog("Lon/Lat: " + this.part.vessel.longitude + "/" + this.part.vessel.latitude);
                lode = scenario.AddLode(planetID, biomeName,
                                        this.part.vessel.longitude, this.part.vessel.latitude, resourceName, resourceAmount);
            }

            //Setup an asteroid lode
            else
            {
                debugLog("Setting up asteroid lode");
                float abundance = 0.01f;

                //Get the resource module for the lode.
                ModuleAsteroidResource   lodeResource    = null;
                ModuleAsteroidResource[] resourceModules = asteroid.part.FindModulesImplementing <ModuleAsteroidResource>().ToArray();
                for (int index = 0; index < resourceModules.Length; index++)
                {
                    if (resourceModules[index].resourceName == resourceName)
                    {
                        debugLog("ModuleAsteroidResource found for " + resourceName);
                        lodeResource = resourceModules[index];
                        break;
                    }
                }
                if (lodeResource == null)
                {
                    debugLog("ModuleAsteroidResource NOT found for " + resourceName);
                    return;
                }

                //Adjust abundance for motherlode
                if (analysisRoll <= (successTargetNumber * kMotherlodeFactor))
                {
                    abundance *= strikeData.motherlodeMultiplier;
                }
                debugLog("abundance increase: " + abundance);

                //Display appropriate message
                ScreenMessages.PostScreenMessage(string.Format("Congratulations! A careful scan of {0:s} has revealed an increased abundance of {1:s}", asteroid.AsteroidName, resourceName),
                                                 kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER);

                //Update resource module
                debugLog("Old abundance: " + lodeResource.abundance);
                lodeResource.abundance        += abundance;
                lodeResource.displayAbundance += abundance;
                debugLog("New abundance: " + lodeResource.abundance);

                debugLog("Adding new lode entry for asteroid: " + asteroid.AsteroidName);
                lode = scenario.AddLode(asteroid, resourceName, lodeResource.displayAbundance);
            }

            //Update any drills in the area.
            scenario.UpdateDrillLodes(asteroid);

            //Set waypoint
            if (lode != null && asteroid == null)
            {
                setWaypoint(resourceName, lode);
            }
        }