private void Update() { if (workerEnabled) { if (scenarioController == null) { foreach (ProtoScenarioModule psm in HighLogic.CurrentGame.scenarios) { if (psm != null) { if (psm.moduleName == "ScenarioDiscoverableObjects") { if (psm.moduleRef != null) { scenarioController = (ScenarioDiscoverableObjects)psm.moduleRef; scenarioController.spawnInterval = float.MaxValue; } } } } } if (scenarioController != null) { if ((Client.realtimeSinceStartup - lastAsteroidCheck) > ASTEROID_CHECK_INTERVAL) { lastAsteroidCheck = Client.realtimeSinceStartup; //Try to acquire the asteroid-spawning lock if nobody else has it. if (!LockSystem.fetch.LockExists("asteroid-spawning")) { LockSystem.fetch.AcquireLock("asteroid-spawning", false); } //We have the spawn lock, lets do stuff. if (LockSystem.fetch.LockIsOurs("asteroid-spawning")) { if ((HighLogic.CurrentGame.flightState.protoVessels != null) && (FlightGlobals.fetch.vessels != null)) { if ((HighLogic.CurrentGame.flightState.protoVessels.Count == 0) || (FlightGlobals.fetch.vessels.Count > 0)) { int beforeSpawn = GetAsteroidCount(); int asteroidsToSpawn = maxNumberOfUntrackedAsteroids - beforeSpawn; for (int asteroidsSpawned = 0; asteroidsSpawned < asteroidsToSpawn; asteroidsSpawned++) { DarkLog.Debug("Spawning asteroid, have " + (beforeSpawn + asteroidsSpawned) + ", need " + maxNumberOfUntrackedAsteroids); scenarioController.SpawnAsteroid(); } } } } //Check for changes to tracking foreach (Vessel asteroid in GetCurrentAsteroids()) { if (asteroid.state != Vessel.State.DEAD) { if (!serverAsteroidTrackStatus.ContainsKey(asteroid.id.ToString())) { serverAsteroidTrackStatus.Add(asteroid.id.ToString(), asteroid.DiscoveryInfo.trackingStatus.Value); } else { if (asteroid.DiscoveryInfo.trackingStatus.Value != serverAsteroidTrackStatus[asteroid.id.ToString()]) { ProtoVessel pv = asteroid.BackupVessel(); DarkLog.Debug("Sending changed asteroid, new state: " + asteroid.DiscoveryInfo.trackingStatus.Value + "!"); serverAsteroidTrackStatus[asteroid.id.ToString()] = asteroid.DiscoveryInfo.trackingStatus.Value; NetworkWorker.fetch.SendVesselProtoMessage(pv, false, false); } } } } } } } }
private void FixedUpdate() { if (workerEnabled) { if (scenarioController == null) { foreach (ProtoScenarioModule psm in HighLogic.CurrentGame.scenarios) { if (psm != null) { if (psm.moduleName == "ScenarioDiscoverableObjects") { if (psm.moduleRef != null) { DarkLog.Debug("Found reference to asteroid spawner"); scenarioController = (ScenarioDiscoverableObjects)psm.moduleRef; scenarioController.spawnInterval = float.MaxValue; } } } } } } if (workerEnabled && scenarioController != null) { if ((UnityEngine.Time.realtimeSinceStartup - lastAsteroidCheck) > ASTEROID_CHECK_INTERVAL) { List <Vessel> asteroidList = GetAsteroidList(); lastAsteroidCheck = UnityEngine.Time.realtimeSinceStartup; //Try to acquire the asteroid-spawning lock if nobody else has it. if (!LockSystem.fetch.LockExists("asteroid-spawning")) { LockSystem.fetch.AcquireLock("asteroid-spawning", false); } //We have the spawn lock, lets do stuff. if (LockSystem.fetch.LockIsOurs("asteroid-spawning")) { if (FlightGlobals.fetch.vessels != null ? FlightGlobals.fetch.vessels.Count > 0 : false) { lock (serverAsteroidListLock) { if (asteroidList.Count < maxNumberOfUntrackedAsteroids) { DarkLog.Debug("Spawning asteroid, have " + asteroidList.Count + ", need " + maxNumberOfUntrackedAsteroids); scenarioController.SpawnAsteroid(); } foreach (Vessel asteroid in asteroidList) { if (!serverAsteroids.Contains(asteroid.id.ToString())) { DarkLog.Debug("Spawned in new server asteroid!"); serverAsteroids.Add(asteroid.id.ToString()); VesselWorker.fetch.RegisterServerVessel(asteroid.id.ToString()); NetworkWorker.fetch.SendVesselProtoMessage(asteroid.protoVessel, false); } } } } } //Check for changes to tracking foreach (Vessel asteroid in asteroidList) { if (!serverAsteroidTrackStatus.ContainsKey(asteroid.id.ToString())) { serverAsteroidTrackStatus.Add(asteroid.id.ToString(), asteroid.DiscoveryInfo.trackingStatus.Value); } else { if (asteroid.DiscoveryInfo.trackingStatus.Value != serverAsteroidTrackStatus[asteroid.id.ToString()]) { DarkLog.Debug("Sending changed asteroid, new state: " + asteroid.DiscoveryInfo.trackingStatus.Value + "!"); serverAsteroidTrackStatus[asteroid.id.ToString()] = asteroid.DiscoveryInfo.trackingStatus.Value; NetworkWorker.fetch.SendVesselProtoMessage(asteroid.protoVessel, false); } } } } } }
protected bool CheckParameters(MonolithState paramState) { if (paramState < currentState) { return(true); } // StarJeb not active vessel if (starJeb != null && FlightGlobals.ActiveVessel != starJeb || candidate != null && FlightGlobals.ActiveVessel != candidate) { stepTime = Time.fixedTime; return(false); } // Create the velocity change handler if (velHdlr == null) { LoggingUtil.LogDebug(this, "Adding VelocityHandler"); velHdlr = MapView.MapCamera.gameObject.AddComponent <VelocityHandler>(); velHdlr.param = this; } switch (currentState) { case MonolithState.STARTED: // Look for an eva if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.vesselType == VesselType.EVA) { candidate = FlightGlobals.ActiveVessel; candidateName = candidate.vesselName; LoggingUtil.LogDebug(this, "Got an eva, starJeb = " + candidate.vesselName); nextState(); return(true); } return(false); case MonolithState.EVA: { Vessel discovery = ContractVesselTracker.Instance.GetAssociatedVessel("Discovery One"); float discoveryDistance = discovery == null ? 10000 : Vector3.Distance(discovery.transform.position, candidate.transform.position); if (distance < 10000 && discoveryDistance > distance && Time.fixedTime - stepTime > 10.0f || distance < MONOLITH_TOO_CLOSE) { // Store Star Jeb's name starJeb = candidate; starJebName = candidateName; PersistentDataStore.Instance.Store <string>("starJebName", starJebName); // Store Star Jeb's friend's name ProtoCrewMember protoStarJeb = candidate.GetVesselCrew().First(); if (discovery != null) { string trait = protoStarJeb.experienceTrait.TypeName == "Scientist" ? "Pilot" : "Scientist"; ProtoCrewMember notStarJeb = discovery.GetVesselCrew().Where(pcm => pcm.experienceTrait.TypeName == trait).FirstOrDefault(); if (notStarJeb != null) { PersistentDataStore.Instance.Store <string>("notStarJebName", notStarJeb.name); } } candidate = null; nextState(); // Set the right image (male vs. female) for the end sequence ConfiguredContract contract = Root as ConfiguredContract; DialogBox dialogBox = contract.Behaviours.Select(b => b as DialogBox).Where(b => b != null).FirstOrDefault(); if (dialogBox != null) { FieldInfo detailsField = typeof(DialogBox).GetFields(BindingFlags.Instance | BindingFlags.NonPublic). Where(fi => fi.FieldType == typeof(List <DialogBox.DialogDetail>)).First(); DialogBox.DialogDetail detail = ((List <DialogBox.DialogDetail>)detailsField.GetValue(dialogBox)).First(); DialogBox.ImageSection starJebImage = detail.sections.First() as DialogBox.ImageSection; starJebImage.imageURL = protoStarJeb.gender == ProtoCrewMember.Gender.Male ? "ContractPacks/AnomalySurveyor/Images/starjeb.dds.noload" : "ContractPacks/AnomalySurveyor/Images/starjeb_female.dds.noload"; } return(true); } } return(false); case MonolithState.FULL_OF_STARS1: { // Backup progress tracking progressTreeBackup = new ConfigNode("PROGRESS_TREE_BACKUP"); ProgressTracking.Instance.OnSave(progressTreeBackup); // Give the first kick away from Jool - this one using regular velocity change CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); // Find closest point on the jool-monolith line, and throw us away from that (so we don't hit either) Vector3 line = monolith.transform.position - jool.transform.position; float t = Vector3.Dot(line, (starJeb.transform.position - jool.transform.position)) / Vector3.Dot(line, line); Vector3 closest = jool.transform.position + line * t; velocity = (starJeb.transform.position - (t > 1.0 ? jool.transform.position : closest)).normalized; velocity += new Vector3(0.0f, 0.1f, 0.0f); velocity *= 15000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); // Camera to target jool FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition((starJeb.transform.position - jool.transform.position).normalized * 25.0f); } return(false); case MonolithState.FULL_OF_STARS2: if (Time.fixedTime - stepTime > 4.0f) { // Give the second kick away from Jool - these using anti-kraken velocity change CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); velocity = (starJeb.transform.position - jool.transform.position).normalized; velocity += new Vector3(0.0f, 0.1f, 0.0f); velocity *= 1500000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); } return(false); case MonolithState.FULL_OF_STARS3: if (Time.fixedTime - stepTime > 3.0f) { // Give the third kick away from Jool CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); velocity = (starJeb.transform.position - jool.transform.position).normalized; velocity *= 20000000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); } return(false); case MonolithState.FULL_OF_STARS4: if (Time.fixedTime - stepTime > 2.0f) { // Give the fourth and final kick away from Jool CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); velocity = (starJeb.transform.position - jool.transform.position).normalized; velocity *= 200000000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); } return(false); case MonolithState.FULL_OF_STARS5: if (Time.fixedTime - stepTime > 2.0f) { // Move along nextState(); } return(false); case MonolithState.FULL_OF_STARS_DRES1: { // Visit Dres CelestialBody dres = FlightGlobals.Bodies.Where(b => b.name == "Dres").First(); // Determine which side the sun is on - makes for a better show CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 sunnySide = sun.transform.position - dres.transform.position; sunnySide.x = 0.0f; sunnySide.y = 1; // Move across the top of the planet sunnySide.z = Math.Sign(sunnySide.z); // Set position for starjeb float distance = 4.0f * (float)dres.Radius; starJeb.SetPosition(dres.transform.position + new Vector3(distance, (float)dres.Radius, (float)dres.Radius * sunnySide.z)); velocity = (dres.transform.position - starJeb.transform.position + sunnySide * ((float)dres.Radius)).normalized; velocity *= distance / 3.0f; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); starJeb.SetWorldVelocity(dres.getRFrmVel(starJeb.transform.position)); nextState(); } return(false); case MonolithState.FULL_OF_STARS_DRES2: { // Camera to target Dres - do this on a seperate update to allow KSP to catch up CelestialBody dres = FlightGlobals.Bodies.Where(b => b.name == "Dres").First(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - dres.transform.position).normalized * 10.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_DRES3: if (Time.fixedTime - stepTime > 5.5f) { // Done with Dres nextState(); } return(false); case MonolithState.FULL_OF_STARS_DUNA1: { // Start between the sun and Duna CelestialBody duna = FlightGlobals.Bodies.Where(b => b.name == "Duna").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 sunnySide = sun.transform.position - duna.transform.position; sunnySide.Normalize(); // Set us up a nice 4 radiuses away... float distance = 4.0f * (float)duna.Radius; starJeb.SetPosition(duna.transform.position + sunnySide * distance); // Go straight at Duna velocity = (duna.transform.position - starJeb.transform.position).normalized; velocity *= distance / 3.0f; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); // Now offset him down so he doesn't actually hit Duna... starJeb.SetPosition(starJeb.transform.position + new Vector3(0.0f, -((float)duna.Radius + 55000), 0.0f)); starJeb.SetWorldVelocity(duna.getRFrmVel(starJeb.transform.position)); nextState(); } return(false); case MonolithState.FULL_OF_STARS_DUNA2: { // Camera to target Duna - do this on a seperate update to allow KSP to catch up CelestialBody duna = FlightGlobals.Bodies.Where(b => b.name == "Duna").First(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - duna.transform.position).normalized * 25.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_DUNA3: if (Time.fixedTime - stepTime > 5.5f) { // Done with Duna nextState(); } return(false); case MonolithState.FULL_OF_STARS_EELOO1: { // Start perpendicular to the sun and Eeloo CelestialBody eeloo = FlightGlobals.Bodies.Where(b => b.name == "Eeloo").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 perp = eeloo.transform.position - sun.transform.position; float tmp = perp.x; perp.x = -perp.z; perp.z = tmp; perp.Normalize(); // Set us up a nice 4 radiuses away... float distance = 4.0f * (float)eeloo.Radius; starJeb.SetPosition(eeloo.transform.position + perp * distance); // Determine which side the sun is on - makes for a better show Vector3 sunnySide = sun.transform.position - eeloo.transform.position; sunnySide.Normalize(); // Go straight at Eeloo velocity = (eeloo.transform.position - starJeb.transform.position).normalized; velocity *= distance / 3.0f; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); // Now offset him down so he doesn't actually hit Eeloo... starJeb.SetPosition(starJeb.transform.position + sunnySide * ((float)eeloo.Radius * 1.5f)); starJeb.SetWorldVelocity(eeloo.getRFrmVel(starJeb.transform.position)); nextState(); } return(false); case MonolithState.FULL_OF_STARS_EELOO2: { // This time won't target directly towards Eeloo, as the player will have some idea // what is up by now. CelestialBody eeloo = FlightGlobals.Bodies.Where(b => b.name == "Eeloo").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 awayFromSun = sun.transform.position - eeloo.transform.position; awayFromSun.Normalize(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + awayFromSun * 50.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_EELOO3: if (Time.fixedTime - stepTime > 5.5f) { velocity = null; // Done with Eeloo nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE1: { CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); Vector3 targetPosition = Destination.Value; Vector3 normal = eve.GetSurfaceNVector(eveLatitude, eveLongitude); startDistance = 10000000f; Vector3 start = targetPosition + normal * startDistance; starJeb.SetPosition(start); nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE2: { // Camera straight towards Eve - we're going in! CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); Vector3 awayFromEve = starJeb.transform.position - eve.transform.position; awayFromEve.Normalize(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + awayFromEve * 15.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_EVE3: // Wait until we've held the position for a split second if (Time.fixedTime - stepTime >= 9.3f) { nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE4: // Give the player a bit to get settled, then let the fun begins if (Time.fixedTime - stepTime >= 15.0f) { // Spawn some asteroids CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); ScenarioDiscoverableObjects asteroidSpawner = (ScenarioDiscoverableObjects)HighLogic.CurrentGame.scenarios.Find( s => s.moduleRef is ScenarioDiscoverableObjects).moduleRef; System.Random random = new System.Random(); // Spawn some more asteroids for (int i = 0; i < ASTEROID_COUNT; i++) { asteroidSpawner.SpawnAsteroid(); } nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE5: // Wait a full second after spawning the asteroids - we're not allowed to pull // them off rails until they've been active a bit if (Time.fixedTime - stepTime > 1.0f) { // Spawn some asteroids CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); System.Random random = new System.Random(); foreach (Vessel asteroid in FlightGlobals.Vessels.Where(v => v.vesselType == VesselType.SpaceObject).Reverse().Take(ASTEROID_COUNT)) { // Set the position double r = random.NextDouble() * 0.02 + 0.002; double theta = random.NextDouble() * 2.0 * Math.PI; double latitude = starJeb.latitude + r * Math.Sin(theta); double longitude = starJeb.longitude + r * Math.Cos(theta); double altitude = starJeb.altitude + 100 + random.NextDouble() * 200; asteroid.SetPosition(eve.GetWorldSurfacePosition(latitude, longitude, altitude)); asteroid.ChangeWorldVelocity(asteroid.GetSrfVelocity()); asteroid.Load(); asteroid.GoOffRails(); } nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE6: { // Determine if there's an asteroid about to kill us CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); bool killerAsteroid = FlightGlobals.Vessels.Where(v => v.mainBody == eve && v.vesselType == VesselType.SpaceObject && Vector3.Distance(starJeb.transform.position, v.transform.position) < 5.5 * ((int)v.DiscoveryInfo.objectSize + 1)).Any(); if (killerAsteroid || Time.fixedTime - stepTime > 20.0f) { foreach (Vessel asteroid in FlightGlobals.Vessels.Where(v => v.vesselType == VesselType.SpaceObject).Reverse().Take(ASTEROID_COUNT)) { asteroid.Die(); } nextState(); } } return(false); case MonolithState.FULL_OF_STARS_KERBIN1: { CheatOptions.NoCrashDamage = false; // Start between the sun and Kerbin CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 sunnySide = sun.transform.position - kerbin.transform.position; sunnySide.Normalize(); // Set us up a nice 4 radiuses away... float distance = 4.0f * (float)kerbin.Radius; starJeb.SetPosition(kerbin.transform.position + sunnySide * distance); // Orient him properly KerbalEVA keva = starJeb.FindPartModulesImplementing <KerbalEVA>().First(); MethodInfo rotationMethod = typeof(KerbalEVA).GetMethod("correctGroundedRotation", BindingFlags.Instance | BindingFlags.NonPublic); starJeb.packed = true; rotationMethod.Invoke(keva, new object[] { }); starJeb.packed = false; // Hardcode an orbital velocity, because it's late and I'm tired starJeb.SetWorldVelocity(kerbin.getRFrmVel(starJeb.transform.position).normalized * 1085); nextState(); } return(false); case MonolithState.FULL_OF_STARS_KERBIN2: { // Camera to target kerbin - do this on a seperate update to allow KSP to catch up CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized * 10.0f); starJeb.SetRotation(FlightCamera.fetch.transform.rotation * Quaternion.AngleAxis(180.0f, FlightCamera.fetch.transform.up)); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_KERBIN3: if (Time.fixedTime - stepTime > 2.0f) { // Turn into star jeb CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); starJeb.vesselName = "The Star Jeb"; Undress(starJeb.gameObject); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized * 1.5f); nextState(); } return(false); case MonolithState.FULL_OF_STARS_KERBIN4: if (Time.fixedTime - stepTime < 15.0f) { CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); Vector3 camDirection = starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized; } else { nextState(); monolith.Die(); monolith = null; starJeb.Die(); starJeb = null; Vessel discovery = ContractVesselTracker.Instance.GetAssociatedVessel("Discovery One"); FlightGlobals.ForceSetActiveVessel(discovery); } return(false); case MonolithState.FULL_OF_STARS_FINAL: nextState(); return(true); default: return(false); } }