-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
looking for a way to wait until science experiements are ready #125
Comments
The bindings to the science modules are still new, so I am still not entirely sure how everything behaves. |
Thank you for the responses. I will give this a try. |
I have been messing with this for a bit now and am becoming convinced that there's something missing that needs to be exposed. I've tried printing out all of the experiment variables and can't find anything that correlates to when the blue science light flashes. My setup:
I was expecting/hoping that a variable on the crew observation would flip as soon as I got into the atmosphere. Here's my script. The intent is just to run in a loop and execute science when available. Note that the 'can_run' function is just what I was using last. I've tried lots of combinations to no avail.
One thing I noticed is that in the game UI, the blinky science button in in the 'Vessel Actions' panel with the lights, gear, solar panels, etc. With the 0.2 update is science a new action group? It's not listed as an action group in the docs, but I'm not familiar with what's available from the game. |
... I did a bit of deeper digging and noticed that |
Short observation:
It looks like In the API I found a field to get the science/research_location the vessel currently is in, i.e. this will work with the next patch:
So I guess the logic would be:
This is a bit convoluted and I am still looking for a way to make the research inventory accessible as well. |
Thanks for taking a look. I agree that it's a bit convoluted, but.. early access. Is the 'research inventory' that you're looking into the list of science/research that you've already completed? I'll give this a whirl when the next patch comes out. |
After some testing I made
Additionally there is
|
version 0.5.2.8 (Ckan) As I was boring last night, I take a look to science. _gitreport::basicscience.to2 use { CONSOLE } from ksp::console
use { Vessel, ModuleScienceExperiment, VesselSituation } from ksp::vessel
use { ExperimentState, Experiment, ResearchLocation, ResearchReport, ScienceSituation } from ksp::science
use { wait_until, yield } from ksp::game
use { round } from core::math
/// Entry Point
pub fn main_flight(vessel: Vessel) -> Result<Unit, string> = {
CONSOLE.clear()
// https://kontrolsystem2.readthedocs.io/en/latest/reference/ksp/vessel.html#part
const science_modules = vessel.parts
.filter(fn(part) -> part.science_experiment.defined)
.map(fn(part) -> part.science_experiment.value)
// get parachutes
const parachutes = vessel.parts
.filter(fn(part) -> part.parachute.defined)
.map(fn(part) -> part.parachute.value)
check_science(vessel)
wait_until(fn() -> (!science_running(vessel)))
check_science(vessel)
// take off
vessel.set_throttle(0.55)
vessel.staging.next()
wait_until(fn() -> vessel.staging.ready)
// while going up
while(round( vessel.up.dot(vessel.surface_velocity) ) >= 0) {
if(vessel.engines.exists(fn(engine) -> engine.is_flameout)) { // drop engine
vessel.staging.next()
wait_until(fn() -> vessel.staging.ready)
}
check_science(vessel)
yield() // let Unity do things
}
// arm parachutes
for(parachute in parachutes)
parachute.armed = true
// while going down
while(vessel.situation != VesselSituation.Landed){
check_science(vessel)
yield() // let Unity do things
}
// just in case anything new could be catch
check_science(vessel)
wait_until(fn() -> (!science_running(vessel)))
check_science(vessel)
CONSOLE.print_line(vessel.name + ": end of mission")
}
fn check_science(vessel: Vessel, autoSend: bool = true, verbose: bool = true) -> Unit = {
const locationComparison = fn(locA: ResearchLocation, locB: ResearchLocation) -> {
(locA.body_name == locB.body_name || locA.body_name.length == 0 || locB.body_name.length == 0)
&& (locA.science_region == locB.science_region || (!locA.requires_region) || (!locB.requires_region))
&& (locA.science_situation == locB.science_situation || locA.science_situation == ScienceSituation.None || locB.science_situation == ScienceSituation.None)
}
const storedReports =
if(vessel.science_storage.defined)
vessel.science_storage.value.research_reports
else
<ResearchReport>[]
if(Some(shipLocation) = vessel.research_location) {
const newExperiments = vessel.parts
.filter(fn(p) -> p.science_experiment.defined)
.map(fn(p) -> p.science_experiment.value.experiments
.filter(fn(e) -> e.current_experiment_state == ExperimentState.READY
&& ((!e.experiment_location.defined) || (!locationComparison(e.experiment_location.value, shipLocation))))
).reduce(<Experiment>[], fn(flat, arr) -> flat + arr)
.filter(fn(e) -> !storedReports.exists(fn(r) -> r.definition.id == e.definition.id && (locationComparison(r.research_location, shipLocation))))
for(e in newExperiments) {
if(verbose)
CONSOLE.print_line("Starting " + e.definition.id + " at " + shipLocation.body_name + "/" + shipLocation.science_situation.to_string() + "/" + shipLocation.science_region)
e.run_experiment()
}
}
if(autoSend) {
for(r in storedReports.filter(fn(r) -> r.transmission_percentage == 0.0 && r.transmission_size > 0.0 && (!r.transmission_status))) {
if(verbose)
CONSOLE.print_line("Emitting " + r.definition.id + " from " + r.research_location.body_name + "/" + r.research_location.science_situation.to_string() + "/" + r.research_location.science_region)
r.start_transmit()
}
}
}
sync fn science_running(vessel: Vessel) -> bool = {
vessel.parts
.filter(fn(p) -> p.science_experiment.defined)
.map(fn(p) -> p.science_experiment.value)
.exists(fn(m) -> m.experiments.exists(fn(e) -> e.current_experiment_state == ExperimentState.RUNNING))
} It trigger research for any new compatible location. Edit : typo |
I guess the But first I have to do a bit more testing with the current pre-release (pretty much every file was touched by the refactoring session last weekend ;) ) |
Hi everyone! I'm going farther with the initial question: is it possible to know if an experiment was already conducted in a previous flight? KSP's latest version corrected that (the button doesn't blink anymore) when the experiment has been already done. Science Archive Mod also keeps track of the done experiment from one flight to an other. I assume something in KSP's API allows that. Thanks a lot for that mod. More complex than kOS but I'm having lot of fun to figure out how things work! |
To my knowledge, there is (still) no way to know what is already studied in KSC. As a candy, to wait, I can give you a well splited, slightly simpler version of the previous code : use { CONSOLE } from ksp::console
use { Vessel, ModuleScienceExperiment, VesselSituation } from ksp::vessel
use { ExperimentState, Experiment, ResearchLocation, ResearchReport, ScienceSituation } from ksp::science
use { ResourceData } from ksp::resource
use { wait_until, yield } from ksp::game
use { round } from core::math
pub type ResourceConst = int
pub const Resource: (MP: ResourceConst, SF: ResourceConst, Air: ResourceConst, H: ResourceConst, CH4: ResourceConst, Ox: ResourceConst, EC: ResourceConst, Xe: ResourceConst) = (
MP: 1,
SF: 2,
Air: 3,
H: 6,
CH4: 7,
Ox: 8,
EC: 12,
Xe: 13
)
pub fn check_science(vessel: Vessel, autoSend: bool = true, verbose: bool = true) -> Unit = {
const locationComparison = fn(locA: ResearchLocation, locB: ResearchLocation) -> {
(locA.body_name == locB.body_name || locA.body_name.length == 0 || locB.body_name.length == 0)
&& (locA.science_region == locB.science_region || (!locA.requires_region) || (!locB.requires_region))
&& (locA.science_situation == locB.science_situation || locA.science_situation == ScienceSituation.None || locB.science_situation == ScienceSituation.None)
}
const storedReports =
if(vessel.science_storage.defined)
vessel.science_storage.value.research_reports
else
<ResearchReport>[]
if(Some(shipLocation) = vessel.research_location) {
const newExperiments = vessel.parts
.filter(fn(p) -> p.science_experiment.defined)
.map(fn(p) -> p.science_experiment.value.experiments
.filter(fn(e) -> e.current_experiment_state == ExperimentState.READY
&& e.current_experiment_state != ExperimentState.ALREADYSTORED
&& ((!e.experiment_location.defined) || (!locationComparison(e.experiment_location.value, shipLocation))))
).reduce(<Experiment>[], fn(flat, arr) -> flat + arr)
run_science(vessel, newExperiments, verbose)
}
if(autoSend)
emmit_science(vessel, storedReports, verbose)
}
pub sync fn science_running(vessel: Vessel) -> bool = {
vessel.parts
.filter(fn(p) -> p.science_experiment.defined)
.map(fn(p) -> p.science_experiment.value)
.exists(fn(m) -> m.experiments.exists(fn(e) -> e.current_experiment_state == ExperimentState.RUNNING))
}
fn run_science(vessel: Vessel, experiments: Experiment[], verbose: bool = true) -> bool = {
if(Some(shipLocation) = vessel.research_location) {
if(verbose) {
for (e in experiments)
CONSOLE.print_line("Starting " + e.definition.id + " at " + shipLocation.body_name + "/" + shipLocation.science_situation.to_string() + "/" + shipLocation.science_region)
}
return experiments
.map(fn(e) -> e.run_experiment())
.exists(fn(done) -> done)
}
return false
}
fn emmit_science(vessel: Vessel, reports: ResearchReport[], verbose: bool = true) -> bool = {
const toSendReports = reports
.filter(fn(r) -> r.transmission_percentage == 0.0 && r.transmission_size > 0.0 && (!r.transmission_status))
.reduce((reports: <ResearchReport>[], consumption: 0.0), fn(agg, r) -> if(agg.consumption + r.ec_required < available_power(vessel)) (reports: agg.reports + r, consumption: agg.consumption + r.ec_required) else (reports: agg.reports, consumption: agg.consumption))
if(verbose) {
for (r in toSendReports.reports)
CONSOLE.print_line("Emitting " + r.definition.id + " from " + r.research_location.body_name + "/" + r.research_location.science_situation.to_string() + "/" + r.research_location.science_region)
}
return toSendReports.reports
.map(fn(r) -> r.start_transmit()) // ugly, but not sure if exists short the search at the first true
.exists(fn(done) -> done)
}
sync fn available_power(vessel: Vessel) -> float = {
vessel.parts
.reduce(<ResourceData>[], fn(flat, p) -> flat + p.resources.list.filter(fn(r) -> r.resource.id == Resource.EC))
.reduce(0.0, fn(sum, r) -> sum + r.stored_units)
} It consider to not emiting a report if EC resource are not enought. I'm not totaly confident with the |
THanks for your script @lefouvert |
The two only ways I found to wrote a file are
IMHO, none of thoses ways are usable. |
There are some (rough) guidelines what a KSP2 mod is allowed and not allowed to do, so reading and writing files has to be done with care. I guess the What probably would be within the allowed bounds would be some kind of persistent key-value store somewhere in the module directory ... just like the scripts themselves. I think I will add this to the todo-list. For the problem at hand though. For the next release I added a |
@untoldwind Out of curiosity, where thoses guidelines can be found ? |
In 0.5.3.2 this should work:
|
It works very well! Fantastic! Thanks |
It looks like you don't have access do the details (region, situation) of Research Location for the completed research report. So we can't ue the locationComparison from @lefouvert.
Then, I use this to compare an experiment with the experiment already reported:
Because experiments done during the actual flight are not in the completed research reports, I have the same kind of function for the actual flight:
and I finish with this to know if the exp is new:
All seem to work but I didn't try with multiple experiments in Exploration mode. |
@untoldwind Did |
Just realized that it accidentally dropped out during one of the refactoring. |
This issue is stale because it has been open for 60 days with no activity. |
This issue was closed because it has been inactive for 14 days since being marked as stale. |
I've searched through the docs and have yet to figure out how to determine when science experiments are available to run. Obviously the game knows this (the science icon flashes).
I'm hoping to write a script that will automatically start the experiments when the conditions have been met. This is probably not an issue in the code, per se, but in my inability to figure it out from the docs. Any help would be appreciated.
The text was updated successfully, but these errors were encountered: