protected void findNearestLode() { int planetID; string biomeName; double longitude = 0f; double latitude = 0f; if (this.part.vessel.situation == Vessel.Situations.LANDED || this.part.vessel.situation == Vessel.Situations.PRELAUNCH) { longitude = this.part.vessel.longitude; latitude = this.part.vessel.latitude; //Find the nearest lode (if any) GoldStrikeUtils.GetBiomeAndPlanet(out biomeName, out planetID, this.part.vessel); nearestLode = WBIPathfinderScenario.Instance.FindNearestLode(planetID, biomeName, longitude, latitude, maxHarvestRange); if (nearestLode != null) { lodeStatus = Localizer.Format(statusOKName); lodeResourceName = nearestLode.resourceName; debugLog("nearestLode: " + nearestLode.ToString()); } else { lodeStatus = Localizer.Format(statusNoNearbyName); lodeResourceName = "N/A"; debugLog("No lode found nearby."); } } }
public void UpdateLastProspectLocation() { ModuleAsteroid asteroid = this.vessel.FindPartModuleImplementing <ModuleAsteroid>(); GoldStrikeUtils.GetBiomeAndPlanet(out lastProspectBiome, out lastProspectPlanet, this.vessel, asteroid); //If we don't have an asteroid then we care about where we are. if (asteroid == null) { lastProspectLongitude = this.vessel.longitude; lastProspectLatitude = this.vessel.latitude; lastProspectAltitude = this.vessel.altitude; } //If we have an asteroid then we don't care about our location because we'll be prospecting the asteroid. else { lastProspectLongitude = 0; lastProspectLatitude = 0; lastProspectAltitude = 0; } debugLog("Last lode location: " + lastProspectPlanet + " " + lastProspectBiome + " lon: " + lastProspectLongitude + " lat: " + lastProspectLatitude + " altitude: " + lastProspectAltitude); //Set last prospect location flag. hasLastProspectLocation = true; }
protected int updateChancesRemaining() { string biomeName = string.Empty; int planetID = int.MaxValue; int chancesRemaining = 0; GoldStrikeUtils.GetBiomeAndPlanet(out biomeName, out planetID, this.part.vessel, asteroid); chancesRemaining = WBIPathfinderScenario.Instance.DecrementProspectAttempts(planetID, biomeName); debugLog("chancesRemaining at " + planetID + " " + biomeName + " = " + chancesRemaining); return(chancesRemaining); }
public GoldStrikeLode FindNearestLode(int planetID, string biome, double longitude, double latitude, double searchDistance = kMaxProspectSearchDistance) { string planetBiomeKey = planetID.ToString() + biome; Dictionary <string, GoldStrikeLode> lodeMap = null; //Get the lode map. If there is none then we're done. if (goldStrikeLodes.ContainsKey(planetBiomeKey) == false) { debugLog("no lodeMap found for key: " + planetBiomeKey); return(null); } lodeMap = goldStrikeLodes[planetBiomeKey]; //Now iterate through the dictionary to find the nearest lode. //We have a minimum cutoff distance GoldStrikeLode[] lodes = lodeMap.Values.ToArray <GoldStrikeLode>(); GoldStrikeLode lode, closestProspect = null; double distance, prevDistance; debugLog("lodes length: " + lodes.Length); prevDistance = double.MaxValue; for (int index = 0; index < lodes.Length; index++) { lode = lodes[index]; debugLog("checking lode: " + lode.ToString()); distance = GoldStrikeUtils.HaversineDistance(longitude, latitude, lode.longitude, lode.lattitude, FlightGlobals.Bodies[lode.planetID]); debugLog("distance between current location and lode location: " + distance); if ((distance <= searchDistance) && (distance < prevDistance)) { debugLog("new closest lode: " + lode); closestProspect = lode; prevDistance = distance; } } if (closestProspect != null) { debugLog("closest lode found"); return(closestProspect); } else { debugLog("closest lode not found"); return(null); } }
public double GetDistanceFromLastLocation(double longitude, double latitude, double altitude) { //If the prospect was on an asteroid then we're done. if (IsAsteroid()) { return(0f); } //If we've never set a prospect location then we're automatically ok. if (lastProspectLocation == Vector2d.zero) { return(double.MaxValue); } double distance = GoldStrikeUtils.HaversineDistance(lastProspectLocation.x, lastProspectLocation.y, longitude, latitude, FlightGlobals.Bodies[planetID]); return(distance); }
protected double getDistanceFromLastLocation() { double distance = 0f; if (this.part.vessel.situation == Vessel.Situations.LANDED || this.part.vessel.situation == Vessel.Situations.PRELAUNCH) { //If we have no last prospect then the distance is zero. if (lastProspectLocation == Vector3d.zero) { return(0f); } //In kilometers distance = GoldStrikeUtils.HaversineDistance(lastProspectLocation.x, lastProspectLocation.y, this.part.vessel.longitude, this.part.vessel.latitude, this.part.vessel.mainBody); } return(distance); }
protected void updateNearestLode() { int planetID; string biomeName; double longitude = 0f; double latitude = 0f; if (this.part.vessel.situation == Vessel.Situations.LANDED || this.part.vessel.situation == Vessel.Situations.PRELAUNCH) { longitude = this.part.vessel.longitude; latitude = this.part.vessel.latitude; } //Find the nearest lode (if any) GoldStrikeUtils.GetBiomeAndPlanet(out biomeName, out planetID, this.part.vessel, asteroid); nearestLode = WBIPathfinderScenario.Instance.FindNearestLode(planetID, biomeName, longitude, latitude); if (nearestLode != null) { debugLog("nearestLode: " + nearestLode.ToString()); } }
public override void OnUpdate() { base.OnUpdate(); if (HighLogic.LoadedSceneIsFlight == false) { return; } //If we have an asteroid then we don't need to do anything. if (asteroid != null) { return; } //If we aren't landed then we're done. if (this.part.vessel.situation != Vessel.Situations.PRELAUNCH && this.part.vessel.situation != Vessel.Situations.LANDED) { return; } //Have we moved beyond our travel threshold? If so, look for the nearest node. double travelDistance = GoldStrikeUtils.HaversineDistance(this.part.vessel.longitude, this.part.vessel.latitude, lastLocation.x, lastLocation.y, this.part.vessel.mainBody); if (travelDistance > searchTriggerDistance) { updateNearestLode(); updateLastLocation(); } if (nearestLode != null) { lodeUnitsRemaining = nearestLode.amountRemaining; } else { lodeUnitsRemaining = double.NaN; } }
public void ResetProspects() { //Since it costs science, ask for confirmation. if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER || HighLogic.CurrentGame.Mode == Game.Modes.SCIENCE_SANDBOX) { float scienceCost = GoldStrikeSettings.ProspectResetCost; //Confirmed, pay the science cost. if (prospectResetConfirmed) { ResearchAndDevelopment.Instance.AddScience(-scienceCost, TransactionReasons.Any); } else { prospectResetConfirmed = true; string message = string.Format("It will cost {0:f2} Science to renew your prospecting chances in this biome. Click to confirm.", scienceCost); ScreenMessages.PostScreenMessage(message, kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER); return; } } //Reset the chances string biomeName = string.Empty; int planetID = -1; GoldStrikeUtils.GetBiomeAndPlanet(out biomeName, out planetID, this.part.vessel, asteroid); GoldStrikeChance chance = WBIPathfinderScenario.Instance.GetGoldStrikeChance(planetID, biomeName); chance.chancesRemaining = GoldStrikeSettings.ProspectsPerBiome; //Hide the reset button Events["ResetProspects"].guiActive = false; Events["ResetProspects"].guiActiveUnfocused = false; //Save the game GamePersistence.SaveGame("quicksave", HighLogic.SaveFolder, SaveMode.BACKUP); }
public GoldStrikeLode AddLode(ModuleAsteroid asteroid, string resourceName, float abundance) { int planetID; string biomeName; GoldStrikeUtils.GetBiomeAndPlanet(out biomeName, out planetID, null, asteroid); GoldStrikeLode lode = new GoldStrikeLode(); Dictionary <string, GoldStrikeLode> lodeMap = null; string planetBiomeKey = planetID.ToString() + biomeName; //Setup the new lode lode.resourceName = resourceName; lode.longitude = 0; lode.lattitude = 0; lode.biome = biomeName; lode.abundance = abundance; lode.planetID = planetID; //Get the lode map if (goldStrikeLodes.ContainsKey(planetBiomeKey) == false) { lodeMap = new Dictionary <string, GoldStrikeLode>(); goldStrikeLodes.Add(planetBiomeKey, lodeMap); debugLog("Added new goldStrikeLode with planetBiomeKey: " + planetBiomeKey); } lodeMap = goldStrikeLodes[planetBiomeKey]; //Add the new lode lodeMap.Add(asteroid.AsteroidName, lode); goldStrikeLodes[planetBiomeKey] = lodeMap; debugLog("Added new lode: " + lode.ToString()); //Save the game GamePersistence.SaveGame("quicksave", HighLogic.SaveFolder, SaveMode.BACKUP); return(lode); }
public GoldStrikeLode FindNearestLode(ModuleAsteroid asteroid) { int planetID; string biomeName; GoldStrikeUtils.GetBiomeAndPlanet(out biomeName, out planetID, null, asteroid); string planetBiomeKey = planetID.ToString() + biomeName; Dictionary <string, GoldStrikeLode> lodeMap = null; debugLog("planetBiomeKey: " + planetBiomeKey); //Get the lode map. If there is none then we're done. if (goldStrikeLodes.ContainsKey(planetBiomeKey) == false) { debugLog("goldStrikeLodes has no lodeMap for key: " + planetBiomeKey); return(null); } lodeMap = goldStrikeLodes[planetBiomeKey]; debugLog("lodeMap has " + lodeMap.Count + " entries"); if (showDebugLog) { foreach (string key in lodeMap.Keys) { debugLog("Key: " + key + "\r\n lode: " + lodeMap[key].ToString()); } } //Asteroids only have one lode if (lodeMap.ContainsKey(asteroid.AsteroidName) == false) { debugLog("No GoldStrikeLode found in lodeMap for " + asteroid.AsteroidName); return(null); } return(lodeMap[asteroid.AsteroidName]); }
public void CheckGoldStrike() { string[] strikeResourceKeys = null; int resourceIndex; GoldStrikeData strikeData = null; WBIGoldStrikeScenario scenario = WBIGoldStrikeScenario.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 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 && !WBIGoldStrikeScenario.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>(); int resourceCount = prospectResources.Count; //Add any resources that have an anomaly chance into the sorted resources for (int index = 0; index < resourceCount; index++) { strikeData = prospectResources[index]; 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, resourceCount - 1); strikeData = prospectResources[resourceIndex]; resourceName = strikeData.resourceName; } } else { resourceIndex = UnityEngine.Random.Range(0, prospectResources.Count - 1); strikeData = prospectResources[resourceIndex]; resourceName = strikeData.resourceName; debugLog("prospectResources count: " + prospectResources.Count); 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, this.part.vessel.altitude, 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); } }
protected bool situationIsValid() { //If we don't have input units and density, then we're in trouble. if (inputResourceDensity == 0f || inputResourceUnits == 0f) { ScreenMessages.PostScreenMessage("Converter stopped. No input resource density or input units found.", kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER); StopResourceConverter(); return(false); } //If we don't have a harvesting node then see if we can find one. if (nearestLode == null) { updateLastLocation(); updateNearestLode(); //If we don't have a nearby node then we're done. if (nearestLode == null) { debugLog("Converter stopped. Vessel isn't near a lode (null)."); ScreenMessages.PostScreenMessage("Converter stopped. This vessel isn't in range of a lode.", kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER); StopResourceConverter(); return(false); } else { lodeUnitsRemaining = nearestLode.amountRemaining; } } //If we're out of resource or are full then we're done. if (status.ToLower().Contains("missing") || status.ToLower().Contains("full")) { StopResourceConverter(); lodeUnitsRemaining = nearestLode.amountRemaining; return(false); } //If we aren't within harvesting range of the nearest lode, then we're done. double harvestDistance = GoldStrikeUtils.HaversineDistance(this.part.vessel.longitude, this.part.vessel.latitude, nearestLode.longitude, nearestLode.lattitude, this.part.vessel.mainBody); if (harvestDistance > maxHarvestRange) { debugLog("Converter stopped. Vessel isn't near a lode (out of range)."); ScreenMessages.PostScreenMessage("Converter stopped. This vessel isn't in range of a lode.", kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER); StopResourceConverter(); return(false); } //If we don't have any more resources to harvest then we're done. if (nearestLode.amountRemaining == 0f) { debugLog("Converter stopped. Lode is depleted."); ScreenMessages.PostScreenMessage("This vein of " + nearestLode.resourceName + " has been depleted. Time to move on...", kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER); StopResourceConverter(); return(false); } //Grab the drills if needed. We need at least one planetary or one asteroid drill. if (harvester == null) { harvester = this.part.FindModuleImplementing <ModuleResourceHarvester>(); } if (asteroidDrill == null) { asteroidDrill = this.part.FindModuleImplementing <ModuleAsteroidDrill>(); } if (harvester == null || asteroidDrill == null) { debugLog("No drill found!!!"); return(false); } //Situation is valid return(true); }
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; int chancesRemaining = 0; 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; } //Ok, we can prospect at this location. GoldStrikeUtils.GetBiomeAndPlanet(out biomeName, out planetID, this.part.vessel, asteroid); setLastLocation(); chancesRemaining = updateChancesRemaining(); //Time to see if we find anything. //Tally up the % chance we have to make a successful prospect. //prospectChance: base chance to find a prospect. Some parts are better than others. //prospectSkillBonus: multiplied by the EVA prospector's skill level. Default is 1.0. //labBonus: For each Pathfinder geology lab in the vicinity, give one point per crew member staffing the lab that has the prospectSkill. //For each non-Pathfinder geology lab in the vicinity, give half a point per crew member staffing the lab that has the prospectSkill. //Chance = prospectChance + prospectSkillBonus + labBonus. //Ex: A 3-star scientist on EVA makes a prospect check. skillBonus = 3; prospectSkillBonus = 1.0. Total skill bonus = 3.0. //Inside the Bison are two scientists staffing a geology lab (non-pathfinder). labBonus = 2 * 0.5 = 1 //Gold Digger has a base 10% chance of finding a prospect. //successTargetNumber = 10 + 3 + 1 = 14. successTargetNumber = prospectChance + GetProspectBonus(); debugLog("Base chance to succeed: " + prospectChance); debugLog("successTargetNumber: " + successTargetNumber); //Roll the chance and check it. analysisRoll = UnityEngine.Random.Range(1, 6); analysisRoll += UnityEngine.Random.Range(1, 6); analysisRoll += UnityEngine.Random.Range(1, 6); analysisRoll *= 5.5556f; debugLog("analysisRoll: " + analysisRoll); //If we didn't succeed then we're done. if (analysisRoll > successTargetNumber) { debugLog("Prospect failed; didn't roll low enough."); ScreenMessages.PostScreenMessage("Nothing of value here, try another location. " + chancesRemaining + " chances remain in the " + biomeName, kMessageDisplayTime, ScreenMessageStyle.UPPER_CENTER); return; } //Success! Get the resource name and strike data. 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()); //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); } ScreenMessages.PostScreenMessage(chancesRemaining + " chances remain to find another lode in the " + biomeName, kMessageDisplayTime, ScreenMessageStyle.UPPER_LEFT); //Play the jingle playJingle(); //Now set up the lode 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); //Set waypoint if (lode != null) { setWaypoint(resourceName, lode); } }