Release EDDI Scripts and EDDI enabled VA Commands Thread

Hi VerticalBlank!

Welcome to the thread!

That's an interesting way to deal with the problem, and looks quite useful. I was also bugged by the fact the body name was repeated by the report right after a scan. So I have something similar in my profile. That's available in this thread too, if you want to take a look at it.

With suggestions like yours, I think you'll be a valuable contributor to this thread! :) Hope you stick around!

Regards,

-=] Darkcyde [=-

Thanks Darkcyde. I hope to be able to contribute further as I become more familiar with Cottle and the APIs we are dealing with. I'm most familiar with Obj-C, C++ and Python but can bend my will to any language given docs.
 
Body Scanned Script

I think I've finally gotten my Body Scanned script to where I want it. I'm an information junkie, I like hearing all the scan info about a body that is available, so my scanned script is very detailed. I've had mixed results using the BodyDetails function (values being not set when they are in the journal) so I settled on using a mix of bodydetails and eventdetails. Some of the units of measurement are different if called from bodydetails vs the event. I've tried to make the script work well with a Surface Scanner, and with out a surface scanner.

I am absoulty not a programmer; code makes my head hurt. I've copied liberaly from this thread and the EDDI thread to piece togeter the pieces.

It's broken down into sections:

Mass & Surface Temperture:
I convert the meters stored in event.radius to kilometers, and convert kelvin to Fahrenheit (USA here).
Code:
{OneOf("{P(reportbody.name)} is", "It is", "This body is")}

{if event.earthmass <= 0.0200:
       a miniscule, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 4)} earthmass,
   |elif event.earthmass <= 0.1000:
       a tiny, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 4)} earthmass,
      |elif event.earthmass <= 3.0:
       a medium sized, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 2)} earthmass,
   |elif event.earthmass <= 10.0:
       a large, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 2)} earthmass,
   |elif event.earthmass <= 20.0:
       a huge, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 2)} earthmass,
   |elif event.earthmass <= 50.0:
       an incredibly large, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 2)} earthmass,
   |else:
       a gigantic, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 2)} earthmass,
   }

{if reportbody.temperature:
{set temp to (reportbody.temperature * 1.8 - 459.67)}

{if reportbody.temperature <=0:
    frozen {round(temp, 0)} degree, 
|elif reportbody.temperature < 173:
    frigid {round(temp, 0)} degree,
|elif reportbody.temperature < 213:
    cold {round(temp, 0)} degree,
|elif reportbody.temperature < 243:
    arctic {round(temp, 0)} degree,
|elif reportbody.temperature < 258:
    cool {round(temp, 0)} degree,
|elif reportbody.temperature < 273:
    chilly {round(temp, 0)} degree,
|elif reportbody.temperature < 300:
    temperate {round(temp, 0)} degree,
|elif reportbody.temperature < 315:
    warm {round(temp, 0)} degree,
|elif reportbody.temperature < 375:
    heated {round(temp, 0)} degree,
|elif reportbody.temperature < 500:
    hot {round(temp, 0)} degree,
|elif reportbody.temperature < 700:
    sweltering {round(temp, 0)} degree,
|elif reportbody.temperature < 1000:
    scorchingly hot {round(temp, 0)} degree,
|elif reportbody.temperature < 1500:
    melting {round(temp, 0)} degree,
|elif reportbody.temperature < 2300:
    molten {round(temp, 0)} degree,
|elif reportbody.temperature < 3300:
    boiling {round(temp, 0)} degree,
|elif reportbody.temperature < 10000:
    blazingly hot {round(temp, 0)} degree,
|else:
    incredibly hot {round(temp, 0)} degree,
}
|else:
with an undetected surface tempature,
}

Body Type, Misc details, orbital info and landable status:
Code:
{if reportbody.tidallylocked:
     tidally-locked,
}

{if reportbody.terraformstate = "Terraformable":
    terraformable, 
|elif reportbody.terraformstate = "Terraformed":
    terraformed, 
}
    
{if len(reportbody.rings) > 0:
  {len(reportbody.rings)} ringed, 
    {if reportbody.reserves:
        with {reportbody.reserves},
    }
}

{if event.bodyclass= "Sudarsky class I gas giant":
   Class one gas giant. 
|elif event.bodyclass= "Sudarsky class II gas giant":
   Class two gas giant. 
|elif event.bodyclass= "Sudarsky class III gas giant":
   Class three gas giant. 
|elif event.bodyclass= "Sudarsky class IV gas giant":
   Class four gas giant. 
|elif event.bodyclass= "Sudarsky class V gas giant":
   Class five gas giant. 
|else:
   {event.bodyclass}. 
}

{if reportbody.terraformstate = "Terraforming":
  In the process of being terraformed. 
}

{OneOf("{P(reportbody.name)} has", "It has", "This body has","This {event.bodyclass} has")}
a gravity of {round(reportbody.gravity, 2)} G's with a

{if reportbody.rotationalperiod < -20.0:
            slow retrograde
        |elif reportbody.rotationalperiod < -0.5:
            retrograde
        |elif reportbody.rotationalperiod < 0:
            fast retrograde
        |elif reportbody.rotationalperiod <= 0.5:
            fast
        |elif reportbody.rotationalperiod > 20.0:
            slow
}

rotational period of {Humanise(reportbody.rotationalperiod)} day{if reportbody.rotationalperiod != "1":s}, and an orbital period of {Humanise(reportbody.orbitalperiod)} day{if reportbody.orbitalperiod != "1":s}.

 
{if reportbody.landable = true || event.landable = true:
  {OneOf("This body is", "It is", "This planet is")} suitable for landing.

|elif !reportbody.landable || !event.landable:
  {if event.bodyclass = "Sudarsky class I gas giant" || event.bodyclass = "Sudarsky class II gas giant" || event.bodyclass = "Sudarsky class III gas giant" || event.bodyclass = "Sudarsky class IV gas giant" || event.bodyclass = "Sudarsky class V gas giant" || event.bodyclass = "Water world" || event.bodyclass = "Earth-like world" || event.bodyclass = "Ammonia world" || event.bodyclass = "Water Giant" || event.bodyclass = "Helium-rich" || event.bodyclass = "Gas giant with ammonia based life" || event.bodyclass = "Gas giant with water based life"  || reportbody.atmosphere  || event.bodyclass ="Earthlike body": 
    {OneOf("This body is", "It is", "This planet is")} unsuitable for landing.
  |else:
    The landable status of this body is unable to be detected.
  }
|elif reportbody.landable = false || event.landable = false:
{OneOf("This body is", "It is", "This planet is")} unsuitable for landing.
}

Atmosphere and Volcanism:
I borrowed heavily from Estelyen's atmosphere script:
https://forums.frontier.co.uk/showt...ion-and-more?p=5431518&viewfull=1#post5431518
Code:
{_Atmosphere }

{SetState("eddi_atmosphere_type", 0)}
{if event.bodyclass= "Sudarsky class I gas giant":
   Class one or Jovian gas giants have primarily hydrogen and helium atmospheres. Coloration comes from clouds in the upper atmosphere of ammonia, water vapor, hydrogen sulphide, phosphine and sulphur.
      {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass= "Sudarsky class II gas giant":
   Class two gas giants have primarily hydrogen and helium atmospheres. Water vapor in the upper cloud layers creates high reflected light levels.
      {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass= "Sudarsky class III gas giant":
   Class three gas giants have primarily hydrogen and helium atmospheres without distinctive cloud layers.  They are primarily blue in color.
      {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass= "Sudarsky class IV gas giant":
   Class four gas giants have primarily hydrogen and helium atmospheres with carbon monoxide and upper clouds of alkali metals above lower cloud layers of silicates and iron compounds. This causes bright colours.
      {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass= "Sudarsky class V gas giant":
   Class five gas giants have primarily hydrogen and helium atmospheres, with thick clouds of silicates and iron compounds, even metallic iron. They often emit a dull glow from the internal heat within the clouds.
      {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass= "Gas giant with water based life":
   Gas giant's with water based life have primarily a hydrogen and helium based atmosphere, but not far below the surface exists life based in the water cloud layer.
      {SetState("eddi_atmosphere_type", 1)}
|elif find(event.bodyclass, "Water Giant") >= 0:
   This gas giant is mainly composed of Water vapor.
   {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass="Earthlike body":
   This outdoor world has a human breathable atmosphere and  indigenious life.
   {SetState("eddi_atmosphere_type", 1)} 
|elif event.bodyclass = "Ammonia World" || event.bodyclass ="Ammonia world":
   This terrestrial ammonia world has an active ammonia based chemistry and carbon ammonia based life.
   {SetState("eddi_atmosphere_type", 2)}
|elif event.bodyclass = "Gas giant with ammonia based life":
   This gas giant with ammonia-based life is a primary hydrogen and helium based atmospheric gas gieant, but a little below the surface cloud layers, life exists based in the ammonia cloud layer.
   {SetState("eddi_atmosphere_type", 1)}

|else: 
   {if reportbody.atmosphere = "ammonia atmosphere" || reportbody.atmosphere = "argon atmosphere" || reportbody.atmosphere = "carbon dioxide atmosphere" || reportbody.atmosphere = "helium atmosphere" || reportbody.atmosphere = "methane atmosphere" || reportbody.atmosphere = "neon atmosphere" || reportbody.atmosphere = "nitrogen atmosphere" || reportbody.atmosphere = "silicate vapour atmosphere" || reportbody.atmosphere = "sulfur dioxide atmosphere" || reportbody.atmosphere = "sulphur dioxide atmosphere" || reportbody.atmosphere = "water atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 0, find(reportbody.atmosphere, " atmosphere", 0)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "ammonia rich atmosphere" || reportbody.atmosphere = "argon rich atmosphere" || reportbody.atmosphere = "carbon dioxide rich atmosphere" || reportbody.atmosphere = "helium rich atmosphere" || reportbody.atmosphere = "methane rich atmosphere" || reportbody.atmosphere = "neon rich atmosphere" || reportbody.atmosphere = "nitrogen rich atmosphere" || reportbody.atmosphere = "silicate vapour rich atmosphere" || reportbody.atmosphere = "sulfur dioxide rich atmosphere" || reportbody.atmosphere = "sulphur dioxide rich atmosphere" || reportbody.atmosphere = "water rich atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 0, find(reportbody.atmosphere, " rich", 0)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "hot thick ammonia atmosphere" || reportbody.atmosphere = "hot thick argon atmosphere" || reportbody.atmosphere = "hot thick carbon dioxide atmosphere" || reportbody.atmosphere = "hot thick helium atmosphere" || reportbody.atmosphere = "hot thick methane atmosphere" || reportbody.atmosphere = "hot thick neon atmosphere" || reportbody.atmosphere = "hot thick nitrogen atmosphere" || reportbody.atmosphere = "hot thick silicate vapour atmosphere" || reportbody.atmosphere = "hot thick sulfur dioxide atmosphere" || reportbody.atmosphere = "hot thick sulphur dioxide atmosphere" || reportbody.atmosphere = "hot thick water atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 10, (find(reportbody.atmosphere, " atmosphere", 0)-10)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "hot thick ammonia rich atmosphere" || reportbody.reportbody = "hot thick argon rich atmosphere" || reportbody.atmosphere = "hot thick carbon dioxide rich atmosphere" || reportbody.atmosphere = "hot thick helium rich atmosphere" || reportbody.atmosphere = "hot thick methane rich atmosphere" || reportbody.atmosphere = "hot thick neon rich atmosphere" || reportbody.atmosphere = "hot thick nitrogen rich atmosphere" || reportbody.atmosphere = "hot thick silicate vapour rich atmosphere" || reportbody.atmosphere = "hot thick sulfur dioxide rich atmosphere" || reportbody.atmosphere = "hot thick sulphur dioxide rich atmosphere" || reportbody.atmosphere = "hot thick water rich atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 10, (find(reportbody.atmosphere, " rich", 0)-10)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "thick ammonia atmosphere" || reportbody.atmosphere = "thick argon atmosphere" || reportbody.atmosphere = "thick carbon dioxide atmosphere" || reportbody.atmosphere = "thick helium atmosphere" || reportbody.atmosphere = "thick methane atmosphere" || reportbody.atmosphere = "thick neon atmosphere" || reportbody.atmosphere = "thick nitrogen atmosphere" || reportbody.atmosphere = "thick silicate vapour atmosphere" || reportbody.atmosphere = "thick sulfur dioxide atmosphere" || reportbody.atmosphere = "thick sulphur dioxide atmosphere" || reportbody.atmosphere = "thick water atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 6, (find(reportbody.atmosphere, " atmosphere", 0)-6)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "thick ammonia rich atmosphere" || reportbody.atmosphere = "thick argon rich atmosphere" || reportbody.atmosphere = "thick carbon dioxide rich atmosphere" || reportbody.atmosphere = "thick helium rich atmosphere" || reportbody.atmosphere = "thick methane rich atmosphere" || reportbody.atmosphere = "thick neon rich atmosphere" || reportbody.atmosphere = "thick nitrogen rich atmosphere" || reportbody.atmosphere = "thick silicate vapour rich atmosphere" || reportbody.atmosphere = "thick sulfur dioxide rich atmosphere" || reportbody.atmosphere = "thick sulphur dioxide rich atmosphere" || reportbody.atmosphere = "thick water rich atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 6, (find(reportbody.atmosphere, " rich", 0)-6)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "thin ammonia atmosphere" || reportbody.atmosphere = "thin argon atmosphere" || reportbody.atmosphere = "thin carbon dioxide atmosphere" || reportbody.atmosphere = "thin helium atmosphere" || reportbody.atmosphere = "thin methane atmosphere" || reportbody.atmosphere = "thin neon atmosphere" || reportbody.atmosphere = "thin nitrogen atmosphere" || reportbody.atmosphere = "thin silicate vapour atmosphere" || reportbody.atmosphere = "thin sulfur dioxide atmosphere" || reportbody.atmosphere = "thin sulphur dioxide atmosphere" || reportbody.atmosphere = "thin water atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 5, (find(reportbody.atmosphere, " atmosphere", 0)-5)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "thin ammonia rich atmosphere" || reportbody.atmosphere = "thin argon rich atmosphere" || reportbody.atmosphere = "thin carbon dioxide rich atmosphere" || reportbody.atmosphere = "thin helium rich atmosphere" || reportbody.atmosphere = "thin methane rich atmosphere" || reportbody.atmosphere = "thin neon rich atmosphere" || reportbody.atmosphere = "thin nitrogen rich atmosphere" || reportbody.atmosphere = "thin silicate vapour rich atmosphere" || reportbody.atmosphere = "thin sulfur dioxide rich atmosphere" || reportbody.atmosphere = "thin sulphur dioxide rich atmosphere" || reportbody.atmosphere = "thin water rich atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 5, (find(reportbody.atmosphere, " rich", 0)-5)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere ="No atmosphere" || reportbody.atmosphere = "" || event.landable:
          {SetState("eddi_atmosphere_type", 1)}
          {OneOf("{reportbody.name} has no atmosphere ","There is no atmosphere on this {event.bodyclass}","This body has no atmosphere")}.
   |elif !reportbody.atmosphere:
         {OneOf("{reportbody.name} has an undetected atmosphere composition","This {event.bodyclass}'s atmosphere composition is undetected","This body's atmosphere composition is undetected")}.
         {SetState("eddi_atmosphere_type", 1)}

   |else:
      {OneOf("{reportbody.name} has a {reportbody.atmosphere}","There is a {reportbody.atmosphere} on this {event.bodyclass}","This body has a {reportbody.atmosphere}")}.
      {SetState("eddi_atmosphere_type", 1)}
   }
}
{if state.eddi_atmosphere_type = 0:
   {OneOf("{reportbody.name} has ","There is ","This {event.bodyclass} has ","This body has ")}
   {if reportbody.pressure < 35000:
      a trace
   |elif reportbody.pressure < 60000:
      a very thin
   |elif reportbody.pressure < 80000:
      a thin
   |elif reportbody.pressure < 120000:
      an average
   |elif reportbody.pressure < 500000:
      a thick
   |elif reportbody.pressure < 10000000:
      a dense
   |elif reportbody.pressure < 100000000:
      a very dense
   |else:
      a crushing
   }
   atmosphere composed mainly of {state.eddi_atmosphere_element}.
|elif state.eddi_atmosphere_type = 2:
   {OneOf("{reportbody.name} has ","There is ","This {event.bodyclass} has ","This body has ")}
   {if reportbody.pressure < 35000:
      a trace
   |elif reportbody.pressure < 60000:
      a very thin
   |elif reportbody.pressure < 80000:
      a thin
   |elif reportbody.pressure < 120000:
      an average
   |elif reportbody.pressure < 500000:
      a thick
   |elif reportbody.pressure < 10000000:
      a dense
   |elif reportbody.pressure < 100000000:
      a very dense
   |else:
      a crushing
   }
   atmosphere composed mainly of toxic gases like methane and ammonia.
}
{SetState("eddi_atmosphere_type", 0)}
{_ Volcanism}
{if reportbody.volcanism.type = "Magma":
   There are 
   {if reportbody.volcanism.amount = "Major":
      {OneOf("numerous", "many", "lots of")} 
   |elif reportbody.volcanism.amount = "Minor":
      {OneOf("some", "a few", "a small amount of")} 
   } 
   lava flows consisting mostly of {reportbody.volcanism.composition} on the surface.
|elif reportbody.volcanism.type = "Geysers":
   There are
   {if reportbody.volcanism.amount = "Major":
      {OneOf("numerous", "many", "lots of")} 
   |elif reportbody.volcanism.amount = "Minor":
      {OneOf("some", "a few", "a small number of")} 
   } geysers of volcanic origin that are ejecting mostly {reportbody.volcanism.composition} {OneOf("detected", "present")} on the surface.
    
      
}

Materials Available:
I have two versions, the standard version that just reports high percents. (I'm still trying to figure out how to adjust the percent threshold that are reported), and a detailed report that Hoodathunk very helpfully provided. I use voiceattack to set a state variable in EDDI to determine what version I want.
Code:
{_ Body materials report }

{if !state.detailedmat: 

   {if !reportbody.landable || !event.landable:

   |else:
      {if reportbody.landable = true || event.landable = true:
        {set goodmaterials to []}
        {set greatmaterials to []}
        {for material in reportbody.materials:
            {if material.percentage >= MaterialDetails(material.material).greatpctbody:
                {set greatmaterials to cat(greatmaterials, [material])}
            |elif material.percentage >= MaterialDetails(material.material).goodpctbody:
                {set goodmaterials to cat(goodmaterials, [material])}
            }
        }

        {if len(greatmaterials) > 0:
            This body contains very high levels of
            {if len(greatmaterials) = 1:
                {greatmaterials[0].material} at {round(greatmaterials[0].percentage, 1)} percent
            |elif len(greatmaterials) = 2:
                {greatmaterials[0].material} at {round(greatmaterials[0].percentage, 1)} percent and {greatmaterials[1].material} at {round(greatmaterials[1].percentage,1)} percent
            |else:
                {set cur to 0}
                {while cur < len(greatmaterials):
                    {if cur = 0:
                        {greatmaterials[cur].material} at {round(greatmaterials[cur].percentage, 1)} percent
                    |elif cur < len(greatmaterials) - 1:
                        , {greatmaterials[cur].material} at {round(greatmaterials[cur].percentage, 1)} percent
                    |else:
                        , and {greatmaterials[cur].material} at {round(greatmaterials[cur].percentage, 1)} percent
                    }
                    {set cur to cur + 1}
                }
            }
        }
        {if len(goodmaterials) > 0:
            {if len(greatmaterials) > 0:
                and high levels of
            |else:
                This body contains high levels of
            }
            {if len(goodmaterials) = 1:
                {goodmaterials[0].material} at {round(goodmaterials[0].percentage, 1)} percent
            |elif len(goodmaterials) = 2:
                {goodmaterials[0].material} at {round(goodmaterials[0].percentage, 1)} percent and {goodmaterials[1].material} at {round(goodmaterials[1].percentage, 1)} percent
            |else:
                {set cur to 0}
                {while cur < len(goodmaterials):
                    {if cur = 0:
                        {goodmaterials[cur].material} at {round(goodmaterials[cur].percentage, 1)} percent
                    |elif cur < len(goodmaterials) - 1:
                        , {goodmaterials[cur].material} at {round(goodmaterials[cur].percentage, 1)} percent
                    |else:
                        , and {goodmaterials[cur].material} at {round(goodmaterials[cur].percentage, 1)} percent
                    }
                    {set cur to cur + 1}
                }
            }
        }
        {if len(greatmaterials) > 0 || len(goodmaterials) > 0:
            .
        |else:
        No particular abundant minerals detected.         
        }
            
}
}

|else:

{if reportbody.landable = true || event.landable = true && len(reportbody.materials) > 0:

        {OneOf("This body contains measureable levels of", "There is measurable levels of", "The following materials are detected on the surface","This {event.bodyclass} contains measurable levels of")}
        {if len(reportbody.materials) = 1:
            {reportbody.materials[0].material} at {round(reportbody.materials[0].percentage, 1)} percent
        |elif len(material) = 2:
            {reportbody.materials[0].material} at {round(reportbody.materials[0].percentage, 1)} percent,
            and {reportbody.materials[1].material} at {round(reportbody.materials[1].percentage, 1)} percent
        |else:
            {set cur to 0}
            {while cur < len(reportbody.materials):
                {if cur = 0:
                    {reportbody.materials[cur].material} at {round(reportbody.materials[cur].percentage, 1)} percent
                |elif cur < len(reportbody.materials) - 1:
                    , {reportbody.materials[cur].material} at {round(reportbody.materials[cur].percentage, 1)} percent
                |else:
                        , and {reportbody.materials[cur].material} at {round(reportbody.materials[cur].percentage, 1)} percent
                }
                {set cur to cur + 1}
            }
        }
        {if len(reportbody.materials) > 0:
            .
        }
}
}

I use a state variable that is set at starting the game and refreshed when doing my preflight check that set's if a surface scanner is equpped. The script then reads out if it's a Detailed surface scan, or a normal scan.

Here is the entire script in all it's messy glory:
Code:
{_ Context }
{SetState('eddi_context_last_subject', 'body')}
{SetState('eddi_context_last_action', 'scan')}
{SetState('eddi_context_body_system', system.name)}
{SetState('eddi_context_body_name', event.name)}

{set reportbody to BodyDetails(state.eddi_context_body_name, state.eddi_context_body_system)}
{if !reportbody:
   {set reportbody to event}
   {set planettype to bodyclass}
}

{if state.surface_scanner = 1:
    Detailed surface Scan of {P(reportbody.name)} complete.
|else:
    Scan of {P(reportbody.name)} complete.
}


{OneOf("{P(reportbody.name)} is", "It is", "This body is")}

{if event.earthmass <= 0.0200:
       a miniscule, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 4)} earthmass,
   |elif event.earthmass <= 0.1000:
       a tiny, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 4)} earthmass,
      |elif event.earthmass <= 3.0:
       a medium sized, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 2)} earthmass,
   |elif event.earthmass <= 10.0:
       a large, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 2)} earthmass,
   |elif event.earthmass <= 20.0:
       a huge, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 2)} earthmass,
   |elif event.earthmass <= 50.0:
       an incredibly large, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 2)} earthmass,
   |else:
       a gigantic, {round(event.radius / 1000, 0)} kilometer radius, {round(event.earthmass, 2)} earthmass,
   }

{if reportbody.temperature:
{set temp to (reportbody.temperature * 1.8 - 459.67)}

{if reportbody.temperature <=0:
    frozen {round(temp, 0)} degree, 
|elif reportbody.temperature < 173:
    frigid {round(temp, 0)} degree,
|elif reportbody.temperature < 213:
    cold {round(temp, 0)} degree,
|elif reportbody.temperature < 243:
    arctic {round(temp, 0)} degree,
|elif reportbody.temperature < 258:
    cool {round(temp, 0)} degree,
|elif reportbody.temperature < 273:
    chilly {round(temp, 0)} degree,
|elif reportbody.temperature < 300:
    temperate {round(temp, 0)} degree,
|elif reportbody.temperature < 315:
    warm {round(temp, 0)} degree,
|elif reportbody.temperature < 375:
    heated {round(temp, 0)} degree,
|elif reportbody.temperature < 500:
    hot {round(temp, 0)} degree,
|elif reportbody.temperature < 700:
    sweltering {round(temp, 0)} degree,
|elif reportbody.temperature < 1000:
    scorchingly hot {round(temp, 0)} degree,
|elif reportbody.temperature < 1500:
    melting {round(temp, 0)} degree,
|elif reportbody.temperature < 2300:
    molten {round(temp, 0)} degree,
|elif reportbody.temperature < 3300:
    boiling {round(temp, 0)} degree,
|elif reportbody.temperature < 10000:
    blazingly hot {round(temp, 0)} degree,
|else:
    incredibly hot {round(temp, 0)} degree,
}
|else:
with an undetected surface tempature,
}


{if reportbody.tidallylocked:
     tidally-locked,
}

{if reportbody.terraformstate = "Terraformable":
    terraformable, 
|elif reportbody.terraformstate = "Terraformed":
    terraformed, 
}
    
{if len(reportbody.rings) > 0:
  {len(reportbody.rings)} ringed, 
    {if reportbody.reserves:
        with {reportbody.reserves},
    }
}

{if event.bodyclass= "Sudarsky class I gas giant":
   Class one gas giant. 
|elif event.bodyclass= "Sudarsky class II gas giant":
   Class two gas giant. 
|elif event.bodyclass= "Sudarsky class III gas giant":
   Class three gas giant. 
|elif event.bodyclass= "Sudarsky class IV gas giant":
   Class four gas giant. 
|elif event.bodyclass= "Sudarsky class V gas giant":
   Class five gas giant. 
|else:
   {event.bodyclass}. 
}

{if reportbody.terraformstate = "Terraforming":
  In the process of being terraformed. 
}

{OneOf("{P(reportbody.name)} has", "It has", "This body has","This {event.bodyclass} has")}
a gravity of {round(reportbody.gravity, 2)} G's with a

{if reportbody.rotationalperiod < -20.0:
            slow retrograde
        |elif reportbody.rotationalperiod < -0.5:
            retrograde
        |elif reportbody.rotationalperiod < 0:
            fast retrograde
        |elif reportbody.rotationalperiod <= 0.5:
            fast
        |elif reportbody.rotationalperiod > 20.0:
            slow
}

rotational period of {Humanise(reportbody.rotationalperiod)} day{if reportbody.rotationalperiod != "1":s}, and an orbital period of {Humanise(reportbody.orbitalperiod)} day{if reportbody.orbitalperiod != "1":s}.

 
{if reportbody.landable = true || event.landable = true:
  {OneOf("This body is", "It is", "This planet is")} suitable for landing.

|elif !reportbody.landable || !event.landable:
  {if event.bodyclass = "Sudarsky class I gas giant" || event.bodyclass = "Sudarsky class II gas giant" || event.bodyclass = "Sudarsky class III gas giant" || event.bodyclass = "Sudarsky class IV gas giant" || event.bodyclass = "Sudarsky class V gas giant" || event.bodyclass = "Water world" || event.bodyclass = "Earth-like world" || event.bodyclass = "Ammonia world" || event.bodyclass = "Water Giant" || event.bodyclass = "Helium-rich" || event.bodyclass = "Gas giant with ammonia based life" || event.bodyclass = "Gas giant with water based life"  || reportbody.atmosphere  || event.bodyclass ="Earthlike body": 
    {OneOf("This body is", "It is", "This planet is")} unsuitable for landing.
  |else:
    The landable status of this body is unable to be detected.
  }
|elif reportbody.landable = false || event.landable = false:
{OneOf("This body is", "It is", "This planet is")} unsuitable for landing.
}


{_Atmosphere }

{SetState("eddi_atmosphere_type", 0)}
{if event.bodyclass= "Sudarsky class I gas giant":
   Class one or Jovian gas giants have primarily hydrogen and helium atmospheres. Coloration comes from clouds in the upper atmosphere of ammonia, water vapor, hydrogen sulphide, phosphine and sulphur.
      {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass= "Sudarsky class II gas giant":
   Class two gas giants have primarily hydrogen and helium atmospheres. Water vapor in the upper cloud layers creates high reflected light levels.
      {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass= "Sudarsky class III gas giant":
   Class three gas giants have primarily hydrogen and helium atmospheres without distinctive cloud layers.  They are primarily blue in color.
      {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass= "Sudarsky class IV gas giant":
   Class four gas giants have primarily hydrogen and helium atmospheres with carbon monoxide and upper clouds of alkali metals above lower cloud layers of silicates and iron compounds. This causes bright colours.
      {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass= "Sudarsky class V gas giant":
   Class five gas giants have primarily hydrogen and helium atmospheres, with thick clouds of silicates and iron compounds, even metallic iron. They often emit a dull glow from the internal heat within the clouds.
      {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass= "Gas giant with water based life":
   Gas giant's with water based life have primarily a hydrogen and helium based atmosphere, but not far below the surface exists life based in the water cloud layer.
      {SetState("eddi_atmosphere_type", 1)}
|elif find(event.bodyclass, "Water Giant") >= 0:
   This gas giant is mainly composed of Water vapor.
   {SetState("eddi_atmosphere_type", 1)}
|elif event.bodyclass="Earthlike body":
   This outdoor world has a human breathable atmosphere and  indigenious life.
   {SetState("eddi_atmosphere_type", 1)} 
|elif event.bodyclass = "Ammonia World" || event.bodyclass ="Ammonia world":
   This terrestrial ammonia world has an active ammonia based chemistry and carbon ammonia based life.
   {SetState("eddi_atmosphere_type", 2)}
|elif event.bodyclass = "Gas giant with ammonia based life":
   This gas giant with ammonia-based life is a primary hydrogen and helium based atmospheric gas gieant, but a little below the surface cloud layers, life exists based in the ammonia cloud layer.
   {SetState("eddi_atmosphere_type", 1)}

|else: 
   {if reportbody.atmosphere = "ammonia atmosphere" || reportbody.atmosphere = "argon atmosphere" || reportbody.atmosphere = "carbon dioxide atmosphere" || reportbody.atmosphere = "helium atmosphere" || reportbody.atmosphere = "methane atmosphere" || reportbody.atmosphere = "neon atmosphere" || reportbody.atmosphere = "nitrogen atmosphere" || reportbody.atmosphere = "silicate vapour atmosphere" || reportbody.atmosphere = "sulfur dioxide atmosphere" || reportbody.atmosphere = "sulphur dioxide atmosphere" || reportbody.atmosphere = "water atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 0, find(reportbody.atmosphere, " atmosphere", 0)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "ammonia rich atmosphere" || reportbody.atmosphere = "argon rich atmosphere" || reportbody.atmosphere = "carbon dioxide rich atmosphere" || reportbody.atmosphere = "helium rich atmosphere" || reportbody.atmosphere = "methane rich atmosphere" || reportbody.atmosphere = "neon rich atmosphere" || reportbody.atmosphere = "nitrogen rich atmosphere" || reportbody.atmosphere = "silicate vapour rich atmosphere" || reportbody.atmosphere = "sulfur dioxide rich atmosphere" || reportbody.atmosphere = "sulphur dioxide rich atmosphere" || reportbody.atmosphere = "water rich atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 0, find(reportbody.atmosphere, " rich", 0)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "hot thick ammonia atmosphere" || reportbody.atmosphere = "hot thick argon atmosphere" || reportbody.atmosphere = "hot thick carbon dioxide atmosphere" || reportbody.atmosphere = "hot thick helium atmosphere" || reportbody.atmosphere = "hot thick methane atmosphere" || reportbody.atmosphere = "hot thick neon atmosphere" || reportbody.atmosphere = "hot thick nitrogen atmosphere" || reportbody.atmosphere = "hot thick silicate vapour atmosphere" || reportbody.atmosphere = "hot thick sulfur dioxide atmosphere" || reportbody.atmosphere = "hot thick sulphur dioxide atmosphere" || reportbody.atmosphere = "hot thick water atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 10, (find(reportbody.atmosphere, " atmosphere", 0)-10)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "hot thick ammonia rich atmosphere" || reportbody.reportbody = "hot thick argon rich atmosphere" || reportbody.atmosphere = "hot thick carbon dioxide rich atmosphere" || reportbody.atmosphere = "hot thick helium rich atmosphere" || reportbody.atmosphere = "hot thick methane rich atmosphere" || reportbody.atmosphere = "hot thick neon rich atmosphere" || reportbody.atmosphere = "hot thick nitrogen rich atmosphere" || reportbody.atmosphere = "hot thick silicate vapour rich atmosphere" || reportbody.atmosphere = "hot thick sulfur dioxide rich atmosphere" || reportbody.atmosphere = "hot thick sulphur dioxide rich atmosphere" || reportbody.atmosphere = "hot thick water rich atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 10, (find(reportbody.atmosphere, " rich", 0)-10)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "thick ammonia atmosphere" || reportbody.atmosphere = "thick argon atmosphere" || reportbody.atmosphere = "thick carbon dioxide atmosphere" || reportbody.atmosphere = "thick helium atmosphere" || reportbody.atmosphere = "thick methane atmosphere" || reportbody.atmosphere = "thick neon atmosphere" || reportbody.atmosphere = "thick nitrogen atmosphere" || reportbody.atmosphere = "thick silicate vapour atmosphere" || reportbody.atmosphere = "thick sulfur dioxide atmosphere" || reportbody.atmosphere = "thick sulphur dioxide atmosphere" || reportbody.atmosphere = "thick water atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 6, (find(reportbody.atmosphere, " atmosphere", 0)-6)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "thick ammonia rich atmosphere" || reportbody.atmosphere = "thick argon rich atmosphere" || reportbody.atmosphere = "thick carbon dioxide rich atmosphere" || reportbody.atmosphere = "thick helium rich atmosphere" || reportbody.atmosphere = "thick methane rich atmosphere" || reportbody.atmosphere = "thick neon rich atmosphere" || reportbody.atmosphere = "thick nitrogen rich atmosphere" || reportbody.atmosphere = "thick silicate vapour rich atmosphere" || reportbody.atmosphere = "thick sulfur dioxide rich atmosphere" || reportbody.atmosphere = "thick sulphur dioxide rich atmosphere" || reportbody.atmosphere = "thick water rich atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 6, (find(reportbody.atmosphere, " rich", 0)-6)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "thin ammonia atmosphere" || reportbody.atmosphere = "thin argon atmosphere" || reportbody.atmosphere = "thin carbon dioxide atmosphere" || reportbody.atmosphere = "thin helium atmosphere" || reportbody.atmosphere = "thin methane atmosphere" || reportbody.atmosphere = "thin neon atmosphere" || reportbody.atmosphere = "thin nitrogen atmosphere" || reportbody.atmosphere = "thin silicate vapour atmosphere" || reportbody.atmosphere = "thin sulfur dioxide atmosphere" || reportbody.atmosphere = "thin sulphur dioxide atmosphere" || reportbody.atmosphere = "thin water atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 5, (find(reportbody.atmosphere, " atmosphere", 0)-5)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere = "thin ammonia rich atmosphere" || reportbody.atmosphere = "thin argon rich atmosphere" || reportbody.atmosphere = "thin carbon dioxide rich atmosphere" || reportbody.atmosphere = "thin helium rich atmosphere" || reportbody.atmosphere = "thin methane rich atmosphere" || reportbody.atmosphere = "thin neon rich atmosphere" || reportbody.atmosphere = "thin nitrogen rich atmosphere" || reportbody.atmosphere = "thin silicate vapour rich atmosphere" || reportbody.atmosphere = "thin sulfur dioxide rich atmosphere" || reportbody.atmosphere = "thin sulphur dioxide rich atmosphere" || reportbody.atmosphere = "thin water rich atmosphere":
      {SetState("eddi_atmosphere_element", slice(reportbody.atmosphere, 5, (find(reportbody.atmosphere, " rich", 0)-5)))}
      {SetState("eddi_atmosphere_type", 0)}
   |elif reportbody.atmosphere ="No atmosphere" || reportbody.atmosphere = "" || event.landable:
          {SetState("eddi_atmosphere_type", 1)}
          {OneOf("{reportbody.name} has no atmosphere ","There is no atmosphere on this {event.bodyclass}","This body has no atmosphere")}.
   |elif !reportbody.atmosphere:
         {OneOf("{reportbody.name} has an undetected atmosphere composition","This {event.bodyclass}'s atmosphere composition is undetected","This body's atmosphere composition is undetected")}.
         {SetState("eddi_atmosphere_type", 1)}

   |else:
      {OneOf("{reportbody.name} has a {reportbody.atmosphere}","There is a {reportbody.atmosphere} on this {event.bodyclass}","This body has a {reportbody.atmosphere}")}.
      {SetState("eddi_atmosphere_type", 1)}
   }
}
{if state.eddi_atmosphere_type = 0:
   {OneOf("{reportbody.name} has ","There is ","This {event.bodyclass} has ","This body has ")}
   {if reportbody.pressure < 35000:
      a trace
   |elif reportbody.pressure < 60000:
      a very thin
   |elif reportbody.pressure < 80000:
      a thin
   |elif reportbody.pressure < 120000:
      an average
   |elif reportbody.pressure < 500000:
      a thick
   |elif reportbody.pressure < 10000000:
      a dense
   |elif reportbody.pressure < 100000000:
      a very dense
   |else:
      a crushing
   }
   atmosphere composed mainly of {state.eddi_atmosphere_element}.
|elif state.eddi_atmosphere_type = 2:
   {OneOf("{reportbody.name} has ","There is ","This {event.bodyclass} has ","This body has ")}
   {if reportbody.pressure < 35000:
      a trace
   |elif reportbody.pressure < 60000:
      a very thin
   |elif reportbody.pressure < 80000:
      a thin
   |elif reportbody.pressure < 120000:
      an average
   |elif reportbody.pressure < 500000:
      a thick
   |elif reportbody.pressure < 10000000:
      a dense
   |elif reportbody.pressure < 100000000:
      a very dense
   |else:
      a crushing
   }
   atmosphere composed mainly of toxic gases like methane and ammonia.
}
{SetState("eddi_atmosphere_type", 0)}
{_ Volcanism}
{if reportbody.volcanism.type = "Magma":
   There are 
   {if reportbody.volcanism.amount = "Major":
      {OneOf("numerous", "many", "lots of")} 
   |elif reportbody.volcanism.amount = "Minor":
      {OneOf("some", "a few", "a small amount of")} 
   } 
   lava flows consisting mostly of {reportbody.volcanism.composition} on the surface.
|elif reportbody.volcanism.type = "Geysers":
   There are
   {if reportbody.volcanism.amount = "Major":
      {OneOf("numerous", "many", "lots of")} 
   |elif reportbody.volcanism.amount = "Minor":
      {OneOf("some", "a few", "a small number of")} 
   } geysers of volcanic origin that are ejecting mostly {reportbody.volcanism.composition} {OneOf("detected", "present")} on the surface.
    
      
}

{_ Body materials report }

{if !state.detailedmat: 

   {if !reportbody.landable || !event.landable:

   |else:
      {if reportbody.landable = true || event.landable = true:
        {set goodmaterials to []}
        {set greatmaterials to []}
        {for material in reportbody.materials:
            {if material.percentage >= MaterialDetails(material.material).greatpctbody:
                {set greatmaterials to cat(greatmaterials, [material])}
            |elif material.percentage >= MaterialDetails(material.material).goodpctbody:
                {set goodmaterials to cat(goodmaterials, [material])}
            }
        }

        {if len(greatmaterials) > 0:
            This body contains very high levels of
            {if len(greatmaterials) = 1:
                {greatmaterials[0].material} at {round(greatmaterials[0].percentage, 1)} percent
            |elif len(greatmaterials) = 2:
                {greatmaterials[0].material} at {round(greatmaterials[0].percentage, 1)} percent and {greatmaterials[1].material} at {round(greatmaterials[1].percentage,1)} percent
            |else:
                {set cur to 0}
                {while cur < len(greatmaterials):
                    {if cur = 0:
                        {greatmaterials[cur].material} at {round(greatmaterials[cur].percentage, 1)} percent
                    |elif cur < len(greatmaterials) - 1:
                        , {greatmaterials[cur].material} at {round(greatmaterials[cur].percentage, 1)} percent
                    |else:
                        , and {greatmaterials[cur].material} at {round(greatmaterials[cur].percentage, 1)} percent
                    }
                    {set cur to cur + 1}
                }
            }
        }
        {if len(goodmaterials) > 0:
            {if len(greatmaterials) > 0:
                and high levels of
            |else:
                This body contains high levels of
            }
            {if len(goodmaterials) = 1:
                {goodmaterials[0].material} at {round(goodmaterials[0].percentage, 1)} percent
            |elif len(goodmaterials) = 2:
                {goodmaterials[0].material} at {round(goodmaterials[0].percentage, 1)} percent and {goodmaterials[1].material} at {round(goodmaterials[1].percentage, 1)} percent
            |else:
                {set cur to 0}
                {while cur < len(goodmaterials):
                    {if cur = 0:
                        {goodmaterials[cur].material} at {round(goodmaterials[cur].percentage, 1)} percent
                    |elif cur < len(goodmaterials) - 1:
                        , {goodmaterials[cur].material} at {round(goodmaterials[cur].percentage, 1)} percent
                    |else:
                        , and {goodmaterials[cur].material} at {round(goodmaterials[cur].percentage, 1)} percent
                    }
                    {set cur to cur + 1}
                }
            }
        }
        {if len(greatmaterials) > 0 || len(goodmaterials) > 0:
            .
        |else:
        No particular abundant minerals detected.         
        }
            
}
}

|else:

{if reportbody.landable = true || event.landable = true && len(reportbody.materials) > 0:

        {OneOf("This body contains measureable levels of", "There is measurable levels of", "The following materials are detected on the surface","This {event.bodyclass} contains measurable levels of")}
        {if len(reportbody.materials) = 1:
            {reportbody.materials[0].material} at {round(reportbody.materials[0].percentage, 1)} percent
        |elif len(material) = 2:
            {reportbody.materials[0].material} at {round(reportbody.materials[0].percentage, 1)} percent,
            and {reportbody.materials[1].material} at {round(reportbody.materials[1].percentage, 1)} percent
        |else:
            {set cur to 0}
            {while cur < len(reportbody.materials):
                {if cur = 0:
                    {reportbody.materials[cur].material} at {round(reportbody.materials[cur].percentage, 1)} percent
                |elif cur < len(reportbody.materials) - 1:
                    , {reportbody.materials[cur].material} at {round(reportbody.materials[cur].percentage, 1)} percent
                |else:
                        , and {reportbody.materials[cur].material} at {round(reportbody.materials[cur].percentage, 1)} percent
                }
                {set cur to cur + 1}
            }
        }
        {if len(reportbody.materials) > 0:
            .
        }
}
}

I'm still adjusting atmosphere types that don't read out correctly, and trying to make the landable section fool proof. I still encounter strangeness when the info is in the journal, but EDDI doesn't report it.

I hope this is useful for someone. :)

I'm open to ideas on how to make my body scanned script better. Enjoy!
 
Hey Darkcyde,

Trying to wrap my head around the changes to the "Add' script... could you provide an example of a 'multi-destination' destinationsystem string that the 'Add' script now parses? I need to incorporate multi-destination mission IDs into my 'Traveling Salesman' route finder and it would aid greatly to my understanding.

Thanks!

Hi Hoodathunk,

I sure can, and with a little background info.

A few days ago JRohrer sent me a PM about some odd speech they had heard. Here's the relevant part of the message:

Your nearest mission target is in the Phracani$MISSIONUTIL_MULTIPLE_INNER_SEPARATOR;LP 244-47$MISSIONUTIL_MULTIPLE_FINAL_SEPARATOR;Cartoi system, 37.54 lightyears away. You have 1 mission in each of the Phracani$MISSIONUTIL_MULTIPLE_INNER_SEPARATOR;LP 244-47$MISSIONUTIL_MULTIPLE_FINAL_SEPARATOR;Cartoi and the Akualanu$MISSIONUTIL_MULTIPLE_INNER_SEPARATOR;LHS 2265$MISSIONUTIL_MULTIPLE_INNER_SEPARATOR;Col 285 Sector VU-M c8-1$MISSIONUTIL_MULTIPLE_FINAL_SEPARATOR;Gooheimar systems.

The two missions I have are multistop passenger missions:
1st mission stops:
Pharacani, LP 244-47 and Cartoi
2nd mission stops:
Akualanu, LHS 2265, and Gooheimar.

I used the destination string exactly as it's presented here, beginning with Phracani, and ending with Cartoi. It's a three stop multi-destination mission (MDM), so I wrote the upgrades using that as test data. When I was done, I ran a two-stop MDM in game and it all went fine, all four reports working just as I'd expected them to. I have yet to try a four stop MDM, but I don't think there will be any problems with one of those.

It looks like FDev have implemented these 'separators' in preparation for more MDMs in future.

Having had some time to think a bit more about MDMs, I think I am going to go with giving people options for how the reports work. My current idea is to set a state variable, something like 'state.eddi_context_mission_visited', and set it to None, MDM, or All, where the value determines what is blocked from reporting once visited. So if None is selected, then the reports will work as they do now. If All is selected then all visited systems will not be reported, and (you guessed it) if MDM is selected, any MDM destination visited will not report, but normal mission ones will.

I think this approach will give the system the greatest flexibility for users, as the option can be changed at any time, giving more or less information as needed, on-the-fly.

Just got to get around to writing it now. :)

Best regards,

-=] Darkcyde [=-
 
Hi Hoodathunk,

I sure can, and with a little background info.

A few days ago JRohrer sent me a PM about some odd speech they had heard. Here's the relevant part of the message:



I used the destination string exactly as it's presented here, beginning with Phracani, and ending with Cartoi. It's a three stop multi-destination mission (MDM), so I wrote the upgrades using that as test data. When I was done, I ran a two-stop MDM in game and it all went fine, all four reports working just as I'd expected them to. I have yet to try a four stop MDM, but I don't think there will be any problems with one of those.

It looks like FDev have implemented these 'separators' in preparation for more MDMs in future.

Having had some time to think a bit more about MDMs, I think I am going to go with giving people options for how the reports work. My current idea is to set a state variable, something like 'state.eddi_context_mission_visited', and set it to None, MDM, or All, where the value determines what is blocked from reporting once visited. So if None is selected, then the reports will work as they do now. If All is selected then all visited systems will not be reported, and (you guessed it) if MDM is selected, any MDM destination visited will not report, but normal mission ones will.

I think this approach will give the system the greatest flexibility for users, as the option can be changed at any time, giving more or less information as needed, on-the-fly.

Just got to get around to writing it now. :)

Best regards,

-=] Darkcyde [=-


Thanks for the info and update.

My take... As long as MDMs are limited to passenger missions, I don't think breaking MDMs into indiviual entries with redundant MissionIDs is necessary and your current implementation is fine. I modified my RRNA route finder script, using your methodology, with minimal work. IF FDEV extends MDMs with multiple destination stations or expiry times, then individual entries would be a necessity.

Thoughts?
 
Thanks for the info and update.

My take... As long as MDMs are limited to passenger missions, I don't think breaking MDMs into indiviual entries with redundant MissionIDs is necessary and your current implementation is fine. I modified my RRNA route finder script, using your methodology, with minimal work. IF FDEV extends MDMs with multiple destination stations or expiry times, then individual entries would be a necessity.

Thoughts?

A large part of me would agree with what you have said. If MDMs are limited to passenger only missions (which they seem to be currently), it would be inefficient to expend resources coding it in detail into the system when they are such a minor part of the overall range of missions.

It's worth noting that I don't actually split MDMs into individual entries, they are stored as a single mission just as with any other one. The destination systems are stored as a single string within the database, and are only split up for reporting purposes. I plan on keeping it this way, even if I add any further functionality.

I agree that, as I have it now, the anomaly experienced by JRohrer is fixed, and MDMs being treated as separate destinations only when reporting, is perfectly adequate for 95% of most users. You're probably right about leaving MDMs and normal mission together rather than as separate parts of a report too.

However, that being said, I'm a bit of a completionist, and I feel that the system is incomplete without 'something more' with regards to MDMs. I love the challenge of being able to write something, and successfully solving the problem at hand, even such a minor one as this, gives me a great sense of personal achievement, even if others think it's a waste of time. Of course, no one is stopping me writing it for my own use anyway, I would just feel better about it if I thought a few others could find it useful too.

This is kinda why I thought about making the 'extra' stuff optional. I could do the programming I enjoy, and then people have the option of if they want to use it or not. I don't really see it taking much more to code it, as most of what I need is already in place. If the system skips entries because they have been visited, it will only speed up the execution, and shorten some of the reports.

I had thought about marking the visited destinations by adding a character to the beginning of a destination system name (like a # maybe), but on reflection, if I add a new state variable for the purpose, then you would not need to make any amendments to your code for the RRNA functionality, you could just ignore the new variable.

I really feel I'd like to do this, but if most people don't like the idea, I may make it for myself and only distribute it as a secondary option.

Well, opinions are welcome.

-=] Darkcyde [=-


P.S. Do I over-explain things too much? :x
 
A large part of me would agree with what you have said. If MDMs are limited to passenger only missions (which they seem to be currently), it would be inefficient to expend resources coding it in detail into the system when they are such a minor part of the overall range of missions.

It's worth noting that I don't actually split MDMs into individual entries, they are stored as a single mission just as with any other one. The destination systems are stored as a single string within the database, and are only split up for reporting purposes. I plan on keeping it this way, even if I add any further functionality.

I agree that, as I have it now, the anomaly experienced by JRohrer is fixed, and MDMs being treated as separate destinations only when reporting, is perfectly adequate for 95% of most users. You're probably right about leaving MDMs and normal mission together rather than as separate parts of a report too.

However, that being said, I'm a bit of a completionist, and I feel that the system is incomplete without 'something more' with regards to MDMs. I love the challenge of being able to write something, and successfully solving the problem at hand, even such a minor one as this, gives me a great sense of personal achievement, even if others think it's a waste of time. Of course, no one is stopping me writing it for my own use anyway, I would just feel better about it if I thought a few others could find it useful too.

This is kinda why I thought about making the 'extra' stuff optional. I could do the programming I enjoy, and then people have the option of if they want to use it or not. I don't really see it taking much more to code it, as most of what I need is already in place. If the system skips entries because they have been visited, it will only speed up the execution, and shorten some of the reports.

I had thought about marking the visited destinations by adding a character to the beginning of a destination system name (like a # maybe), but on reflection, if I add a new state variable for the purpose, then you would not need to make any amendments to your code for the RRNA functionality, you could just ignore the new variable.

I really feel I'd like to do this, but if most people don't like the idea, I may make it for myself and only distribute it as a secondary option.

Well, opinions are welcome.

-=] Darkcyde [=-


P.S. Do I over-explain things too much? :x

Naw, you're good... I'm an engineer and I know exactly where you feel the need to be complete and concise.

And for the record, I'm also all about maximizing functionality, while maintaining simplicity. Don't worry about me and my 'Traveling Salesman' route planning script... I'll adjust as necessary.

In fact, I've been giving some thought to taking it to the next level by parsing the mission types as to whether you need to return to your destination (scan, salvage, and assassination missions, for example). This can be implemented in one of two ways... either only populating the 'originsystem' and 'originstaion' variables if you need to return to collect on the mission, or creating another variable, 'eddi_context_mission_return' for example, which would be "yes" or "no" for each mission entry (similar to the 'failed' mission variable) depending on whether a return was required.

How would this be helpful? Returning to the origin system in your shortest distance calculation is a necessity if you're grinding Fed or Empire rep, but what if you're picking up new missions in systems that were destinations for a previously accepted mission? How do you fold multiple 'returning systems' into the route re-calculation? For example, you need to ensure you don't pick a 'shortest path' that has you returning to an origin system before you completed the mission in the destination system... that would be an algorithm failure.

I have some thoughts on how to implement 'multiple origin' functionality... will keep you posted
 
Last edited:
Darkcyde where is the best place to get the latest complete personality? not sure if http://snafets.de/elite/eddi_scripts/index.php has the latests as there doesnt seem to be an "last updated" time and date field. Well I cant find it but then again thats nothing new :D

Interested in incorporating some of the scripts you have been talking about in this thread into my own personality if you dont mind that is

Thanks to you and everyone for the awesomeness of the scripting and helping me out when Ive posted problems in the past, present and future
 
Naw, you're good... I'm an engineer and I know exactly where you feel the need to be complete and concise.

And for the record, I'm also all about maximizing functionality, while maintaining simplicity. Don't worry about me and my 'Traveling Salesman' route planning script... I'll adjust as necessary.

In fact, I've been giving some thought to taking it to the next level by parsing the mission types as to whether you need to return to your destination (scan, salvage, and assassination missions, for example). This can be implemented in one of two ways... either only populating the 'originsystem' and 'originstaion' variables if you need to return to collect on the mission, or creating another variable, 'eddi_context_mission_return' for example, which would be "yes" or "no" for each mission entry (similar to the 'failed' mission variable) depending on whether a return was required.

How would this be helpful? Returning to the origin system in your shortest distance calculation is a necessity if you're grinding Fed or Empire rep, but what if you're picking up new missions in systems that were destinations for a previously accepted mission? How do you fold multiple 'returning systems' into the route re-calculation? For example, you need to ensure you don't pick a 'shortest path' that has you returning to an origin system before you completed the mission in the destination system... that would be an algorithm failure.

I have some thoughts on how to implement 'multiple origin' functionality... will keep you posted

Now you mention it, I do actually have a variable already in place for just this purpose, I just never got around to actually doing anything with it (yet!). The variable is 'state.eddi_context_mission_roundtrip' and I put it in to store a yes/no value to say if you needed to return to the origin system/station to hand in. As I've not got around to coding that functionality (other things dragged me away), I've also not checked to see if the origin system/station was being stored properly. It should be, in theory, I just don't remember if I checked it or not. (Side note: I tend to forget stuff sometimes, it's a side effect of a stroke I had a few years ago. That, and being half blind from it too).

I also parse the mission types already, mainly for the speech of accepting or handing in missions, and giving slight variations on the speech for the different types. I had intended to use the same function to set the 'roundtrip' variable, depending on the mission type. So it looks like we've been thinking along the same lines with this. On the plus side, half of what we need is already done: the variable and the mission parsing. :D It's my birthday tomorrow (yay I'm older :p ) and my company has given everyone their birthday off this year, so I'll see about going through the missions and making them set that variable. It should be all set for you to do your stuff then. :) Plus 'Return' sounds better than 'RoundTrip' so I think I'll change it to that while I'm at it. :D

I must admit, what you are proposing, and have done already, sounds great, and I'd like to incorporate it all into my EDDI personality, if that's ok? When you have it done, just let me know. :)

As I now have a four day weekend (I took Friday off work too) I may see about adding the other functionality to the missions system, and the options to enable/disable it on the fly too.

Best regards,

-=] Darkcyde [=-


EDIT: I've made the change of the variable name to '..._return' now. I've also updated my 'MissionType' function to set it to yes or no depending on if the mission type requires it. I think I have them all correct, hopefully anyway!
 
Last edited:
Darkcyde where is the best place to get the latest complete personality? not sure if http://snafets.de/elite/eddi_scripts/index.php has the latests as there doesnt seem to be an "last updated" time and date field. Well I cant find it but then again thats nothing new :D

Interested in incorporating some of the scripts you have been talking about in this thread into my own personality if you dont mind that is

Thanks to you and everyone for the awesomeness of the scripting and helping me out when Ive posted problems in the past, present and future

Hiya,

Yeah, sorry about that. I keep forgetting about snafets. :( Well, I've decided to just update my sig below, with a link to my dropbox for the latest file. I'm more likely to remember to update this, as and when needed. I hope that's ok for you?

Best regards

-=] Darkcyde [=-
 
Hello cmdrs! I made my first EDDI script today! It's a simple "undocking" with more informations...!

{Pause(3350)}

{OneOf("Full control re-established", "Docking clamps free", "Disengaged from local networks","undocking event completed")}.

{event.station} {OneOf("bids us farewell!","has set our ship logs to departured","cleared all our ship records for the time being","Sent a message, thank you for your visit commander!")}.

the {P(ShipName())} {P(ship.model)} {OneOf("is ready for duty","stands ready","is on it's way to a new adventure","is airborne, let's conquer the stars")}

{Pause(1000)}

{OneOf("updating credits amount of","you have","total assets in bank")} {Humanise(cmdr.credits)}

{Occasionally(2,"{OneOf("it's good to have credits",Don't forget the rebuy","fly safe commander")}")}



{set limpetcheck to F("Limpet check")}

{if limpetcheck:
{Pause(5000)}
{limpetcheck}
}

Wish i could wrap my head on creating more complex scripts but i'm studying! It's fun to see it "live" in the game! EDDI is AWEEEEESOME!
One day maybe i can come up with incredible scripts like yours! Fly safe cmdrs!
 
Hi Tulextreme,

Congrats for the first working script!

Great idea to follow your account at undocking! I am wondering, how it would sound, if we'd check the relative increment/decrease compared to the account state at docking, and making some comments based on that, like "Man, are you burning money?" if credits are less at undocking than docking, and "Business is running well, commander!" at the opposite state, or something like this. You could use SetState to store the account state when entering a station (if cmdr.credits is available there too). Darkcyde made a very good description about the usage of SetState earlier in this thread somewhere.

Best regards!
 
Help with script idea?

Hiya, I hope this is the right place (or at least a good place) to post this. I'm pretty new to EDDI and VA but in the messing around I've done along with looking at other publicly available profiles/scripts I can see how easy it'd be to do just lots of cool and insane things... If you have the coding knowledge. This in lies my problem in that while I have some, I lack some of the more in-depth stuff and proper syntax usage for VA and EDDI currently. Besides this I also fear that to fully work my idea is going to need a separate plugin, which just makes things so much more ugh.

Anyways all that said I feel like my idea is semi-simple. Basically a way to use EDDI's ability to know your current system to iterate through a list of systems you have stored locally somewhere (probably as plain text file, or at least an easy to edit file) and setting the next system on that list as some variable to be used later (for example set as destination in galaxy map through copy/paste or something). Ignoring the utterly wrong syntax/formatting, I imagine it could be something like...


Make Array from text file
set var target system = Array item 1
set var current system = EDDI Completed Jump System

On completed jump run
if target system == current system set target system = Array item 2

From there I imagine a separate command could be run to do whatever with the target system variable, such as typing it out on demand or similar.


To be honest I probably could do most of this myself by looking at other scripts, I mean the first post here contains a nice script including a lot of what I'd need, but that thing about the array has me at a loss and right now googling isn't helping any. But if this was possible this would be super useful for something like the neutron router or a list of systems you want to visit (like the Ancient Ruins or Thargoid ships).

Thanks for any help/input.
 
Hiya,

Yeah, sorry about that. I keep forgetting about snafets. :( Well, I've decided to just update my sig below, with a link to my dropbox for the latest file. I'm more likely to remember to update this, as and when needed. I hope that's ok for you?

Best regards

-=] Darkcyde [=-

Thats cool with me, even better just one place to check the latest updates :D
 
Now you mention it, I do actually have a variable already in place for just this purpose, I just never got around to actually doing anything with it (yet!). The variable is 'state.eddi_context_mission_roundtrip' and I put it in to store a yes/no value to say if you needed to return to the origin system/station to hand in. As I've not got around to coding that functionality (other things dragged me away), I've also not checked to see if the origin system/station was being stored properly. It should be, in theory, I just don't remember if I checked it or not. (Side note: I tend to forget stuff sometimes, it's a side effect of a stroke I had a few years ago. That, and being half blind from it too).

I also parse the mission types already, mainly for the speech of accepting or handing in missions, and giving slight variations on the speech for the different types. I had intended to use the same function to set the 'roundtrip' variable, depending on the mission type. So it looks like we've been thinking along the same lines with this. On the plus side, half of what we need is already done: the variable and the mission parsing. :D It's my birthday tomorrow (yay I'm older :p ) and my company has given everyone their birthday off this year, so I'll see about going through the missions and making them set that variable. It should be all set for you to do your stuff then. :) Plus 'Return' sounds better than 'RoundTrip' so I think I'll change it to that while I'm at it. :D

I must admit, what you are proposing, and have done already, sounds great, and I'd like to incorporate it all into my EDDI personality, if that's ok? When you have it done, just let me know. :)

As I now have a four day weekend (I took Friday off work too) I may see about adding the other functionality to the missions system, and the options to enable/disable it on the fly too.

Best regards,

-=] Darkcyde [=-


EDIT: I've made the change of the variable name to '..._return' now. I've also updated my 'MissionType' function to set it to yes or no depending on if the mission type requires it. I think I have them all correct, hopefully anyway!

With the new functionality I'm intending, the 'Route Finder' script is now/still a work in progress, but yes, absolutely add it to your package if you think it brings value.

I've updated my scripts to reflect your 'return' and 'MissionType' changes. Due to necessities of making the RNNA Route Finder more robust, I've also added some new variables to the Mission System.

First, 'eddi_context_missions_home' allows the user to set a 'home base' to always finish the loop... very handy for rep grinding. This could be changed by the user via VA commands.

Additionally, I found the need (as you previously mentioned) to add an 'eddi_context_mission_visited' variable for tracking 'destination systems' which have been visited. 'MissionStoreAdd', 'MissionStoreDelete, and 'MissionStoreInitialise', etc, along with the associated VA commands have been modified to reflect the addition.


Again, a work in progress and has not been tested, but this is the current snapshot of 'MissionStoreVisited', which would be called following a jump.

Code:
{_ MissionStoreVisited }
{_ Change status of 'visited' missions }


{set destination to state.eddi_context_mission_destination}
{set current_system to state.eddi_context_system_name}


{if destination != "" && destination = current_system:

    {set destinations to split(state.eddi_context_mission_destinationsystems, "+=")}
    {set visited to split(state.eddi_context_mission_visited, "+=")}

    {set cur to 0}
    {while cur < len(destinations):
        {if find(destinations[cur], "::") > -1:
            {set dest_array to split(destinations, "::")}
            {set pos to find(dest_array, current_system)}
            {if pos > -1: set visited[cur] to token(visited[cur], "::", pos, "yes")}}
        |else:
            {if destinations[cur] = current_system: {set visited[cur] to "yes"}}
        }
        {set cur to cur + 1}
    }
    {SetState('eddi_context_mission_visited', join(visited, "+="))}
}

Note that 'visited' is changed from "no" to "yes" only if the RNNA Route Finder has populated 'eddi_context_mission_destination'. This prevents the 'visited' status being changed if system is not a deliberate destination.

Another option would be to call 'MissionStoreVisited' for delivery type missions when the mission has been completed in the destination system.

Additionally, note that the 'visited' elements support Multiple Destination functionality. For example, "no::no::yes". Well, at least in theory until I've fully tested it ;)


EDIT: and Happy Birthday!!
 
Last edited:
Hi Tulextreme,

Congrats for the first working script!

Great idea to follow your account at undocking! I am wondering, how it would sound, if we'd check the relative increment/decrease compared to the account state at docking, and making some comments based on that, like "Man, are you burning money?" if credits are less at undocking than docking, and "Business is running well, commander!" at the opposite state, or something like this. You could use SetState to store the account state when entering a station (if cmdr.credits is available there too). Darkcyde made a very good description about the usage of SetState earlier in this thread somewhere.

Best regards!

Thank you Brigetiol1 ! Glad you liked my idea! It would be awesome to improve on it but sadly i lack the knowledge to do so! I'm reading all the thread in here but some things are hard to understand! :D
 
Thank you Brigetiol1 ! Glad you liked my idea! It would be awesome to improve on it but sadly i lack the knowledge to do so! I'm reading all the thread in here but some things are hard to understand! :D

Hi,

I think, here are great guys around with lots of knowledge, I'm sure, somebody can answer your questions, just feel free to ask :) !

Best regards!
 
With the new functionality I'm intending, the 'Route Finder' script is now/still a work in progress, but yes, absolutely add it to your package if you think it brings value.

I've updated my scripts to reflect your 'return' and 'MissionType' changes. Due to necessities of making the RNNA Route Finder more robust, I've also added some new variables to the Mission System.

First, 'eddi_context_missions_home' allows the user to set a 'home base' to always finish the loop... very handy for rep grinding. This could be changed by the user via VA commands.

Additionally, I found the need (as you previously mentioned) to add an 'eddi_context_mission_visited' variable for tracking 'destination systems' which have been visited. 'MissionStoreAdd', 'MissionStoreDelete, and 'MissionStoreInitialise', etc, along with the associated VA commands have been modified to reflect the addition.


Again, a work in progress and has not been tested, but this is the current snapshot of 'MissionStoreVisited', which would be called following a jump.

Code:
{_ MissionStoreVisited }
{_ Change status of 'visited' missions }


{set destination to state.eddi_context_mission_destination}
{set current_system to state.eddi_context_system_name}


{if destination != "" && destination = current_system:

    {set destinations to split(state.eddi_context_mission_destinationsystems, "+=")}
    {set visited to split(state.eddi_context_mission_visited, "+=")}

    {set cur to 0}
    {while cur < len(destinations):
        {if find(destinations[cur], "::") > -1:
            {set dest_array to split(destinations, "::")}
            {set pos to find(dest_array, current_system)}
            {if pos > -1: set visited[cur] to token(visited[cur], "::", pos, "yes")}}
        |else:
            {if destinations[cur] = current_system: {set visited[cur] to "yes"}}
        }
        {set cur to cur + 1}
    }
    {SetState('eddi_context_mission_visited', join(visited, "+="))}
}

Note that 'visited' is changed from "no" to "yes" only if the RNNA Route Finder has populated 'eddi_context_mission_destination'. This prevents the 'visited' status being changed if system is not a deliberate destination.

Another option would be to call 'MissionStoreVisited' for delivery type missions when the mission has been completed in the destination system.

Additionally, note that the 'visited' elements support Multiple Destination functionality. For example, "no::no::yes". Well, at least in theory until I've fully tested it ;)

At first, when I read the part about adding a home variable, I thought that EDDI does that already. Then I realised that EDDI probably doesn't allow you to change that variable, outside of the tab in the EDDI config. This makes your solution much better as you can change it as necessary with VA.

I like your 'visited' script, I had something along those lines planned when I first thought about adding that info. It occurred to me though, that there could be problems(?) depending when it's called. If it's called when you arrive in system, it will move on to your next destination and won't be able to tell you the station or planet you need in this system. Also, what if you jumped out again (for whatever reason) without completing the task in this system? I had thought of a couple of other things, but I can't remember them now. :/ I had to refine things in an attempt to be more accurate, from my point of view at least.

Actually, rather than try to explain it, here's a copy of my notes I made last week. This was just for the marking of the visited destinations.
Code:
Use State.eddi_context_mission_visited = No/MDM/All
 - Use VA commands to switch between.
 - Use VA to store along with all other mission variables.

Mark visited systems in database.
 - When dropping to normal space from supercruise
   - only if manually done, not pulled out by Pirate/Police/etc.
   - missions gained in-system should still work
   - reporting will still work when you arrive and up until you drop
   - allows you to query next destination before leaving system
   - only mark those missions with a destination in the current system.

When reporting:
if 'Visited'
 = No, report all as originally.
    Ignore 'visited' for all missions.
 = MDM, block reporting of MDM systems only.
    Allows for reporting next stop in mission chain.
    Ignore 'visited' for normal missions only.
 = All, block all visited systems from reporting.
    Use 'visited' fully.

Allow for Visited changing on-the-fly.
 - One report may say all missions, change setting, repeat report now ignores MDMs.


If mission has a 'Destination Station' & dropped near to a it, mark mission as visited
If no destination station (MDMs, seek missions, etc) then mark visited when manually drop to normal space. need more research.

manual drop out
check missions & report THEN
  find system in array
  while position > -1
     if system has a matching station
        if station is where we are, mark visited (for space stations, not for ground stations)
        if dropped near a planet
           if body().distance = missionstation().distance, mark visited (check if viable)
     else
        if no station, mark visited
     }
goto next position
}

surface scan missions won't work like this?
visitor beacons/sites have no destination station. check drop near planet?

Ignore the first line, I can easily change the _visited variable to something more appropriate as it would be better used for the yes/no as you have it. The ideas I have in my notes are far from perfect solutions. I've also considered doing the checks when departing a station, which would be much more accurate, but then you have the problem that most people would like to know their next destination before leaving. Hmmm, how about if it's called when docking is complete? The destination would remain pointing you to what you need to do in system right up until you actually dock, and only then would switch to the next destination. What do you think? Ahh, but then visitor beacons wouldn't work. Maybe a combination of ideas instead? Any thoughts?
 
Hiya, I hope this is the right place (or at least a good place) to post this. I'm pretty new to EDDI and VA but in the messing around I've done along with looking at other publicly available profiles/scripts I can see how easy it'd be to do just lots of cool and insane things... If you have the coding knowledge. This in lies my problem in that while I have some, I lack some of the more in-depth stuff and proper syntax usage for VA and EDDI currently. Besides this I also fear that to fully work my idea is going to need a separate plugin, which just makes things so much more ugh.

Anyways all that said I feel like my idea is semi-simple. Basically a way to use EDDI's ability to know your current system to iterate through a list of systems you have stored locally somewhere (probably as plain text file, or at least an easy to edit file) and setting the next system on that list as some variable to be used later (for example set as destination in galaxy map through copy/paste or something). Ignoring the utterly wrong syntax/formatting, I imagine it could be something like...


Make Array from text file
set var target system = Array item 1
set var current system = EDDI Completed Jump System

On completed jump run
if target system == current system set target system = Array item 2

From there I imagine a separate command could be run to do whatever with the target system variable, such as typing it out on demand or similar.


To be honest I probably could do most of this myself by looking at other scripts, I mean the first post here contains a nice script including a lot of what I'd need, but that thing about the array has me at a loss and right now googling isn't helping any. But if this was possible this would be super useful for something like the neutron router or a list of systems you want to visit (like the Ancient Ruins or Thargoid ships).

Thanks for any help/input.

Hi Cynor,

Welcome to this thread. :)

The problem with EDDI and arrays is that they cannot be stored between events. EDDI has State variables for storing between events, but due to the way EDDI handles these, they cannot be arrays, only single variables. With the syntax, I believe they are already an array of 'State' objects.

To get around this, myself and others have been using strings with particular separators to store in the State variable, then use the functions of split() and join() to create an array from the string, and then rebuild the string from the array ready to store in a State variable again.

So, very basically:-

Say your array is called 'your_array'.

{set your_variable to join(your_array. "+=")}
This will create a string called your_variable, made up from the elements of your_array, with each element separated by the characters +=.
Something like this "Fine+=Bounty+=Bounty+=BountyInc+=Bond+=Bond+=Bond".

{SetState('your_variable_here', your_variable}
This will create a State variable of the string, to be stored between EDDI events.
This variable will be available to all other scripts as 'state.your_variable_here'

{set your_array to split(state.your_variable_here, "+=")}
In any other script, you can use this line to recreate your array, using the += as the separation markers.
You can use anything as separators, I simply chose += as they are unlikely to occur together in most situations.


In your example you could go like this:-

Use VoiceAttack to load the string from a text file into 'state.system_list':-
Code:
Set Text [system_list] to [C:\\Elite\systems_list.txt]
Set Text [State variable] to 'system_list'
Execute external plugin 'EDDI..<version>' and wait for return   (EDDI plugin will have the version as part of it's name)

Then in your script (probably the Jumped script or make your own script and call it from Jumped):-
Code:
{set position to 0}
{set systems to split(state.system_list, "+=")}
{set system to systems[position]}
{set current to state.eddi_context_system_system}    (EDDI already has this state variable stored for the current system)

{if system = current:
   {set system to systems[position + 1]}
}

This is simply an example of the syntax and commands. Each time it's called, it will always look at position 0. If I understand what you intend for this, you will also need to mark each system in the array as 'visited', so that on the next jump it will skip all the visited ones and go straight to the next in the list. This is very similar to the things Hoodathunk and myself have been discussing above. You could, for example, have another State variable to store 'position'.

I believe you can also use VoiceAttack to do a copy/paste into the Galaxy map to look for a destination, but I don't know a lot about VA to be able to tell you how to do that. Sorry. :(

Well, I hope that helps a little at least! :)

Best regards,

-=] Darkcyde [=-
 
Here's my latest on a 'Shortest Path Missions Route Finder', to work in conjunction with Darkcyde's Mission Store System!

This script is based on a modified 'Repetitive Nearest Neighbor Algorithm'.

Modified in the sense that the calculated route ensures that no 'return system' (system which must be returned to in order to collect your reward) is visited before before all its destination systems have been visited.


Code:
{_ Missions_RouteFind }
{_ Plot a RNNA route for defined systems in the mission store }


{_ Setup 'destination array builder' function }
{set systems_builder(system) to:
    {if find(systems, system) = -1:
        {set systems to cat(systems, [system])}
        {set system_count to system_count + 1}
    }
}

{_ Test whether mission origin is a 'return' system. }
{_ If so, check whether mission destination has been visited yet }
{set test_visited(system) to:
    {set test to find(origins, system)}
    {while test > -1:
        {set dest to token(state.eddi_context_mission_destinationsystem, "+=", test)}
        {if returns[test] = "yes" && find(route_systems, dest) = -1: {return false}}
        {set test to find(origins, system, test + 1)}

    }
    {return true}
}

{_ Test 'starting system' is a destination for a 'return' mission. }
{_ If so, then any route with this 'starting system' is not viable.}
{set test_dest(system) to:
    {set test to find(returns, "yes")}
    {while test > -1:
        {set dest to token(state.eddi_context_mission_destinationsystem, "+=", test)}
        {if system = dest: {return true}}
        {set test to find(returns, "yes", test + 1)}

    }
    {return false}
}

{set mission_route to ""}
{set total_distance to -1}
{set missionstotal to state.eddi_context_missions_accepted}

{if missionstotal != null && missionstotal > 0:

    {set origins to split(state.eddi_context_mission_originsystem, "+=")}
    {set returns to split(state.eddi_context_mission_return, "+=")}

    {_ Start by adding the 'current' & 'home' systems to the destination list }
    {set current_system to state.eddi_context_system_name}
    {set systems to []}
    {set systems to cat(systems, [current_system])}
    {set system_count to 1}

    {set home_system to state.eddi_context_missions_home}
    {if home_system = "":
        {set home_system to current_system}
    |else:
        {systems_builder(home_system)}        
    }

    {_ Add all mission systems that have a 'return to origin' to the destination list }
    {set pos to find(returns, "yes")}
    {while pos > -1:
        {systems_builder(origins[pos])}
        {set pos to find(returns, "yes", pos + 1)}
    }

    {_ Add all destination systems to the destination list }
    {set cur to 0}
    {while cur < missionstotal
        {set destination to token(state.eddi_context_mission_destinationsystem, "+=", cur)}
        {set failed to token(state.eddi_context_mission_failed, "+=", cur)}

        {if destination != "" && failed = "no":
            {if find(destination, "::") > -1:
                {set dest_array to split(destination, "::")}
                {for destination in dest_array: {systems_builder(destination)}}
            |else:
                {systems_builder(destination)}
            }
        }
        {set cur to cur + 1}
    }

    {if len(systems) = 2:
        {set curr to SystemDetails(systems[0])}
        {set dest to SystemDetails(systems[1])}
        {set total_distance to round(Distance(curr.x, curr.y, curr.z, dest.x, dest.y, dest.z) * 2,2)}
        {set mission_route to cat(systems[1], "+=", systems[0])}
        {SetState('eddi_context_mission_destination', systems[1])}

    |elif len(systems) > 2:
        {set cur to 1}
        {set start to 0}
        {set nearest_distance to 10000}
        {set total_distance to 1000000}

        {_ Iterate all possible routes, differing the starting system }
        {while start < system_count:

            {while test_dest(systems[start]):
                {set start to start + 1}
            }
            {set starting_system to systems[start]}

            {set curr to SystemDetails(starting_system)}
            {set route_count to 1}
            {set route_systems to []}
            {set td to 0}
        
            {_ Repeat until all systems have been visited }
            {while route_count < system_count:

                {set pos to start + cur}
                {if pos >= system_count: {set pos to pos - system_count}}

                {_ If system hasn't already been visited and it's not a 'return' system }
                {_ with an unvisited destination, find its distance from current system }
                {if find(route_systems, systems[pos]) = -1 && test_visited(systems[pos]):
                    {set dest to SystemDetails(systems[pos])}
                    {set distance to round(Distance(curr.x, curr.y, curr.z, dest.x, dest.y, dest.z), 2)}

                    {_ Save if nearest to current system } 
                    {if distance < nearest_distance:
                        {set nearest_distance to distance}
                        {set nearest_name to dest.name}

                    }
                }
                {set cur to cur + 1}

                {_ Once nearest found, 'visit it' and then find the 'next nearest' }
                {if cur = system_count:
                    {set route_systems to cat(route_systems, [nearest_name])}

                    {_ 'Nearest' becomes current system for next iteration }
                    {set curr to SystemDetails(nearest_name)}

                    {set route_count to route_count + 1}
                    {set td to td + nearest_distance}
                    {set nearest_distance to 10000}
                    {set cur to 1}
                }
            }

            {_ Add 'starting system' to complete route &  to total distance traveled }
            {set route_systems to cat(route_systems, [starting_system])}
            {set dest to SystemDetails(starting_system)}
            {set distance to round(Distance(curr.x, curr.y, curr.z, dest.x, dest.y, dest.z),2)}
            {set td to td + distance}

            {_ If new route total distance less than previous best, then keep it }
            {if td < total_distance:
                {set total_distance to td}

                {_ Rotate to place 'home system' at end of missions array }
                {set temp to join(route_systems, "+=")}
                {set index to find(temp, home_system) + len(home_system) + 2}
                {if index < len(temp):
                    {set mission_route to cat(slice(temp, index), "+=", slice(temp, 0, index - 2))}
                |else:
                    {set mission_route to temp}
                }
            }
            {set start to start + 1}
        }
        {SetState('eddi_context_mission_destination', token(mission_route, "+=", 0))}
    }
    {SetState('eddi_context_mission_route', mission_route)}
    {SetState('eddi_context_mission_route_distance', total_distance)}

    Missions route calculated for {system_count} systems.
    {Pause(400)}
    Total distance is {round(total_distance, 1)} lightyears.
    {Pause(400)}
    First destination is {state.eddi_context_mission_destination}. Awaiting orders.
}


I've tested the script enough that I feel comfortable it's generating good routes, but I'll throw in the disclaimer that it's fairly arduous to test all the possible permutations, so please let me know if you run into any problems with it when you're out in the black.


The script 'MissionStoreNextInRoute' iterates through the systems in the Missions Route List. You could call this manually using a VA Command, or you could automate it following each jump as I've described below.

Code:
{_ Missions_RouteNext }
{_ Set the next mission system destination }


{if state.eddi_context_mission_route = "":
    {SetState('eddi_context_mission_destination', "")}

|else:
    {set mission_route to split(state.eddi_context_mission_route, "+=")}
    {set mission_route to join(except(mission_route, [0:""]), "+=")}
    {SetState('eddi_context_mission_route', mission_route)}
    {set destination to token(mission_route, "+=", 0)}
    {SetState('eddi_context_mission_destination', destination)}
}


Additionally, also related to Darkcyde's excellent response to Cynor's question, here is an example VA command for automating course selection via the Galaxy Map.


Code:
Begin Text Compare : [EDDI state eddi_context_mission_destination] Does Not Equal ''
    Set Text [destination] to [EDDI state eddi_context_mission_destination]
 
    Set Text [from_system] to [System name]
    Set Text [State variable] to 'from_system'
    Execute external plugin, 'EDDI 2.3.0' and wait for return

    Set Text [to_system] to [destination]
    Set Text [State variable] to 'to_system'
    Execute external plugin, 'EDDI 2.3.0' and wait for return

    Set Text [Script] to 'Get distance'
    Execute external plugin, 'EDDI 2.3.0' and wait for return

    Set Text [Script] to 'Stand by.'
    Execute external plugin, 'EDDI 2.3.0'
    Execute command, '((Galaxy map))' (by name) (and wait until it completes)
    Pause 2 seconds
    
    Execute command, '((UI Next))' (by name) (and wait until it completes)
    Pause 0.3 seconds
    Execute command, '((UI Accept))' (by name) (and wait until it completes)
    Execute command, '((UI Cancel))' (by name) (and wait until it completes)
    
    Set Text [Script] to '[Setting course for;Plotting course to;Plotting route to] the {TXT:destination} system.'
    Execute external plugin, 'EDDI 2.3.0'
    
    Quick Input, '{TXT:destination}'
    Press Enter key and hold for 0.03 seconds and release
    Set decimal [pause-time] value to the value of [EDDI state distance]
    Set decimal [pause-time] to [pause-time] divided by 250 (round to 0 decimal places)
    Set decimal [pause-time] to [pause-time] plus 3 (round to 0 decimal places)
    Pause a variable number of seconds [pause-time]
    
    Execute command, '((UI Right))' (by name) (and wait until it completes)
    Execute command, '((UI Accept))' (by name) (and wait until it completes)
    
    Pause 1 second
    Set Text [State variable] to 'destination'
    Execute external plugin, 'EDDI 2.3.0'
    Set Text [Script] to 'Destination confirmed.'
    Execute external plugin, 'EDDI 2.3.0'
    
    Pause 2 seconds
    Execute command, '((Galaxy map))' (by name) (and wait until it completes)
End Condition


((Galaxy map)), ((UI Right)), ((UI Previous)), etc are VA commands for key-presses and are unique to your controls setup... Adjust accordingly.


This the Speech Responder script for 'Get distance'...


Code:
{set dist to -1}
{if state.from_system && state.to_system:
    {if state.from_system = "":
        Origin system not designated.
    |elif state.to_system = "":
        Destination system not designated.
    |else:
        {set fs to SystemDetails(state.from_system)}
        {set ts to SystemDetails(state.to_system)}

        {if !fs.name:
            Your origin is not in the Pilot's Federation star charts.
        |elif !ts.name:
            Your destination is not in the Pilot's Federation star charts.
        |else:
            {set dist to round(Distance(fs.x, fs.y, fs.z, ts.x, ts.y, ts.z),1)}
        }
    }
}
{SetState('distance', dist)}


Lastly, if you wish to automate iterating through the Missions Route List, insert this code onto the end of your 'Jumped' script.


Code:
{if mission_destination && mission_destination != "":
    {if mission_destination = system.name:
        {F("Missions_NextInRoute")}
    }
}


Now, if you're looking for the 'full monty', where you get 'Arrival Notification' and status updates after each jump, insert this code onto the end of your 'Jumped' script!


Code:
{set dist to -1}
{set mission_destination to state.eddi_context_mission_destination}

{if mission_destination && mission_destination != "":
    {if mission_destination = system.name:
        {F("Missions_NextInRoute")}
    }

|elif state.destination && state.destination != "":
    {set ds to SystemDetails(state.destination)}
    {if !ds.name:
        Your destination is not in the Pilot's Federation star charts.
    |else:
        {set dist to round(Distance(ds.x, ds.y, ds.z, system.x, system.y, system.z),1)}
        {if dist = 0:
            {ShipName()} has arrived at the {P(ds.name)} system.
            {SetState('destination', '')}
        |else:
            Distance to {P(ds.name)} is {dist} light years.
        }
    }
    {SetState('distance', dist)}
}


Enjoy!
 
Last edited:
Back
Top Bottom