Release EDDI Scripts and EDDI enabled VA Commands Thread

Hi,

I created an app (better said: wired together lots of apps) called : Animgif Thingy.

I have a virtual dashboard on my secondary monitor, and there was an unused virtual display. So with a few free softwares, VA and EDDI I managed to make it alive.

It can play small animations, when an EDDI event happens. You can attach any number of animations to an event, it will pick one randomly. At this moment I have animgifs for 13 events. It can start the animation within one sec!

Description and downloads here:

http://voiceattack.com/smf/index.php?topic=1248.msg6122#msg6122

Or here:

https://forums.frontier.co.uk/showt...DIY-Playground-Tips-Tricks-and-Unicorns/page5

Screenshot of the virtual dash:

http://i.imgur.com/ZBPvLTe.jpg

Best regards!
 
Last edited:
'Nearest Neighbor' is the simplest but doesn't produce the most efficient route, so I will continue by modifying to utilize the 'Repetitive Nearest Neighbor' Algorithm. RNNA is actually not too bad for our limitation of 20 missions.

More work to do but wanted to share with you and folks in the community. Obviously, VA commands 'Update Mission Initialise' & 'Update Mission Store' would have to be modified and scenarios where missions are abandoned would need to be addressed.

I'll also need to build VA commands and support scripts to do automated plotting. I already have a VA command that will take a 'clipboarded' system name and plot it via the Galaxy Map, so that won't be too much of a feat. Can get fancy and auto-plot the next system as soon as you undock from the previous. :)

Hi Hoodathunk,

That's a great idea! I hadn't thought of using the mission system in that way, but it's an excellent example of what else can be achieved using my system as a base to work from. I'm eager to see what it becomes as you improve it.

I noticed that you have followed my 'style' of writing very closely, almost exactly in fact! ;) One could be forgiven for thinking I'd written it! The only thing I would do differently is move the five {set...} lines that are just before the {if len(systems) = 0: to the part of the IF block (the else part) where they are used. They are not needed until that part, so it would make the script slightly tidier and a little more efficient as they will not need to be set if you only have 0 or 1 valid system. But that's just personal preference.

I also see you've copied doing the annotations that I've done in my mission system. To be honest, I'd just left my pseudo-code lines & notes in, that's all they were for me, but as an unforeseen bonus, I guess they are a good help to those trying to understand what I've done and why I've done it. I may just start adding them in to my other scripts. :)

As for the 'repetitive nearest neighbour', that sound like a good plan. I'm not sure how to go about it though, but I imagine it would involve nested For or While loops. ;)

I look forward to seeing what you come up with.

Best regards,

-=] Darkcyde [=-
 
Hi,

I created an app (better said: wired together lots of apps) called : Animgif Thingy.

I have a virtual dashboard on my secondary monitor, and there was an unused virtual display. So with a few free softwares, VA and EDDI I managed to make it alive.

It can play small animations, when an EDDI event happens. You can attach any number of animations to an event, it will pick one randomly. At this moment I have animgifs for 13 events. It can start the animation within one sec!

Description and downloads here:

http://voiceattack.com/smf/index.php?topic=1248.msg6122#msg6122

Or here:

https://forums.frontier.co.uk/showt...DIY-Playground-Tips-Tricks-and-Unicorns/page5

Screenshot of the virtual dash:

http://i.imgur.com/ZBPvLTe.jpg

Best regards!

Hi Brigetiol1!

I was wondering where you were. ;) Now I see what you've been doing.

I like your idea, it looks good to have that as your second screen. I don't think it's something I would use though, as I use my second screen for other things while in Elite, but the whole reason for sharing on here is so that others may find it useful, and I'm sure many will. :) I see you're making good use of the 'Quote of the Day' too! ;)

Best regards,

-=] Darkcyde [=-
 
Hi Darkcyde,

I like to use everyday things in unusual contexts too, like you :)! And it is extremely funny to have an animgif running a the start of a fight, with Clint Eastwood, as Dirty Harry, "saying" Make my day! I have spent many months with EDDI lately, it is like having a holiday now making the Thingy.

I am very curious, what kind of new ideas will you guys realize regarding EDDI, because there are lots of new stuff cooking, as I see! And I'm watching and learning...

Rock 'n Roll!
 
Hi Hoodathunk,

As for the 'repetitive nearest neighbour', that sound like a good plan. I'm not sure how to go about it though, but I imagine it would involve nested For or While loops. ;)

I look forward to seeing what you come up with.

Best regards,

-=] Darkcyde [=-


Glad to hear you liked the 'Nearest Neighbor' solution. I've attached, below, my first pass at the 'Repetitive Nearest Neighbor' script...


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

{if state.eddi_context_missions_initialised != "yes": {F("MissionStoreInitialise")}}
{set mission_route to ""}
{set total_distance to 0}

{_ For VoiceAttack, convert TXT token into number value, as EDDI plugin can't export DEC to State variables }
{set missionstotal to cast(state.eddi_context_missions_accepted, "n")}

{if missionstotal > 0 && missionstotal != null:
    {set mission_system_array to split(state.eddi_context_mission_destinationsystem, "+=")}

    {_ Get all systems that have a destination, starting with the origin system }
    {set systems to []}
    {set origin to state.eddi_context_system_system}
    {set systems to cat(systems, [origin])}
    {set system_count to 1}
    {for system in mission_system_array:
        {if system != "":
            {if find(systems, system) = -1:
                {set systems to cat(systems, [system])}
                {set system_count to system_count + 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])}


    |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, depending on starting system }
        {while start < system_count:

            {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, find distance from current system }
                {if find(route_systems, systems[pos]) = -1:
                    {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 origin at end of missions string }
                {set temp to join(route_systems, "+=")}
                {set index to find(temp, origin) + len(origin) + 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_route', mission_route)}
{SetState('eddi_context_mission_route_distance', total_distance)}


I haven't tested it fully yet ( I have big plans for the weekend :) ) but wanted to get the code out so folks could play with it.

And, yes, your missions store system is a simple and flexible database, well suited for this application. I have several ideas for other scenarios... Parsing non-destination based missions, using mission sub-types, for example.
 
Last edited:
Morning folks, yeah another all night ED session :D

I just had an idea when doing some power play stuff is there a way to keep track of how many merits you have earned?

I've looked in the github for EDDI and the wiki and i don't see any variable for the merits.

I'd baseball like to be able to just ask EDDI though VA about how many merits I currently have and how many merits I have earned while killing enemy ships
 
Hey Darkcyde!

I've cleaned up both the 'MissionStoreAdd' and MissionStoreDelete' scripts. Please check and use as you see fit.


With 'MissionStoreAdd', I used the 'If' statement to set the separator as "" or "+=", depending on whether the addition was the first, or not.

Code:
{_ MissionStoreAdd }
{_ Add accepted missions to memory store. Max 20 missions }

{if state.eddi_context_missions_accepted < 20:
    {set missions to state.eddi_context_missions_accepted + 1}
    {SetState('eddi_context_missions_accepted', missions)}

    {if event.name = "Mission_AltruismCredits" || event.name = "Mission_Altruism":
        {set destinationsystem to system.name}
        {set destinationstation to station.name}
    |else:
        {set destinationsystem to event.destinationsystem}
        {set destinationstation to event.destinationstation}
    }

    {_ add += & data to end of string if not first mission }
    {if missions = 1: {set sep to ""} |else: {set sep to "+="}}

    {set Mission_MissionID to cat(state.eddi_context_mission_missionid, sep, event.missionid)}
    {set Mission_Name to cat(state.eddi_context_mission_name, sep, event.name)}
    {set Mission_DestinationSystem to cat(state.eddi_context_mission_destinationsystem, sep, destinationsystem)}
    {set Mission_DestinationStation to cat(state.eddi_context_mission_destinationstation, sep, destinationstation)}
    {set Mission_Commodity to cat(state.eddi_context_mission_commodity, sep, event.commodity)}
    {set Mission_PassengerType to cat(state.eddi_context_mission_passengertype, sep, event.passengertype)}
    {set Mission_TargetName to cat(state.eddi_context_mission_targetname, sep, event.targetname)}
    {set Mission_TargetType to cat(state.eddi_context_mission_targettype, sep, event.targettype)}
    {set Mission_Communal to cat(state.eddi_context_mission_communal, sep, event.communal)}
    {set Mission_Expiry to cat(state.eddi_context_mission_expiry, sep, event.expiry)}
    {set Mission_OriginSystem to cat(state.eddi_context_mission_originsystem, sep, system.name)}
    {set Mission_OriginStation to cat(state.eddi_context_mission_originstation, sep, station.name)}
    {set Mission_RoundTrip to cat(state.eddi_context_mission_roundtrip, sep, roundtrip)}

    {_ Rewrite State variable strings }
    {SetState('eddi_context_mission_missionid', Mission_MissionID)}
    {SetState('eddi_context_mission_name', Mission_Name)}
    {SetState('eddi_context_mission_destinationsystem', Mission_DestinationSystem)}
    {SetState('eddi_context_mission_destinationstation', Mission_DestinationStation)}
    {SetState('eddi_context_mission_commodity', Mission_Commodity)}
    {SetState('eddi_context_mission_passengertype', Mission_PassengerType)}
    {SetState('eddi_context_mission_targetname', Mission_TargetName)}
    {SetState('eddi_context_mission_targettype', Mission_TargetType)}
    {SetState('eddi_context_mission_communal', Mission_Communal)}
    {SetState('eddi_context_mission_expiry', Mission_Expiry)}
    {SetState('eddi_context_mission_originsystem', Mission_OriginSystem)}
    {SetState('eddi_context_mission_originstation', Mission_OriginStation)}
    {SetState('eddi_context_mission_roundtrip', Mission_RoundTrip)}

    {if missions = 20:
        You have now reached the maximum number of missions you can take.
        Please complete some, in order to accept more.
    |else:
        {OneOf("You {Occasionally(2,'now')} have {missions} mission{if missions > 1:s}",
            "{OneOf('That\\'s','That is','This is')} your
        {if missions = 1: 1st
        |elif missions = 2: 2nd
        |elif missions = 3: 3rd
        |else: {missions}th
        }
        mission")}.
    }
}


For 'MissionStoreDelete', I utilized the 'except' function to strip the abandoned/completed mission from the array.

Code:
{_ MissionStoreDelete }
{_ Remove completed/abandoned missions from the store }
{_ Finds the mission to delete and removes it from the array using the except() function }


{_ Convert missionid to a string so it can be compared }
{set mission to cast(event.missionid, "s")}

{set mission_missionid to split(state.eddi_context_mission_missionid, "+=")}

{_ find position of missionid in text array }
{set position to find(mission_missionid, mission)}

{if position > -1:

    {_ Create arrays from the strings, using += as the split marker }
    {set mission_name to split(state.eddi_context_mission_name, "+=")}
    {set mission_destinationsystem to split(state.eddi_context_mission_destinationsystem, "+=")}
    {set mission_destinationstation to split(state.eddi_context_mission_destinationstation, "+=")}
    {set mission_commodity to split(state.eddi_context_mission_commodity, "+=")}
    {set mission_passengertype to split(state.eddi_context_mission_passengertype, "+=")}
    {set mission_targetName to split(state.eddi_context_mission_targetname, "+=")}
    {set mission_targettype to split(state.eddi_context_mission_targettype, "+=")}
    {set mission_communal to split(state.eddi_context_mission_communal, "+=")}
    {set mission_expiry to split(state.eddi_context_mission_expiry, "+=")}
    {set mission_originsystem to split(state.eddi_context_mission_originsystem, "+=")}
    {set mission_originstation to split(state.eddi_context_mission_originstation, "+=")}
    {set mission_roundtrip to split(state.eddi_context_mission_roundtrip, "+=")}

    {_ Rebuild text string from modified arrays }
    {set mission_missionid to join(except(mission_missionid, [position:""]), "+=")}
    {set mission_name to join(except(mission_name, [position:""]), "+=")}
    {set mission_destinationsystem to join(except(mission_destinationsystem, [position:""]), "+=")}
    {set mission_destinationstation to join(except(mission_destinationstation, [position:""]), "+=")}
    {set mission_commodity to join(except(mission_commodity, [position:""]), "+=")}
    {set mission_passengertype to join(except(mission_passengertype, [position:""]), "+=")}
    {set mission_targetname to join(except(mission_targetname, [position:""]), "+=")}
    {set mission_targettype to join(except(mission_targettype, [position:""]), "+=")}
    {set mission_communal to join(except(mission_communal, [position:""]), "+=")}
    {set mission_expiry to join(except(mission_expiry, [position:""]), "+=")}
    {set mission_originsystem to join(except(mission_originsystem, [position:""]), "+=")}
    {set mission_originstation to join(except(mission_originstation, [position:""]), "+=")}
    {set mission_roundtrip to join(except(mission_roundtrip, [position:""]), "+=")}

    {_ Reset State variable ready for next use }
    {SetState('eddi_context_mission_missionid', mission_missionid)}
    {SetState('eddi_context_mission_name', mission_name)}
    {SetState('eddi_context_mission_destinationsystem', mission_destinationsystem)}
    {SetState('eddi_context_mission_destinationstation', mission_destinationstation)}
    {SetState('eddi_context_mission_commodity', mission_commodity)}
    {SetState('eddi_context_mission_passengertype', mission_passengertype)}
    {SetState('eddi_context_mission_targetname', mission_targetname)}
    {SetState('eddi_context_mission_targettype', mission_targettype)}
    {SetState('eddi_context_mission_communal', mission_communal)}
    {SetState('eddi_context_mission_expiry', mission_expiry)}
    {SetState('eddi_context_mission_originsystem', mission_originsystem)}
    {SetState('eddi_context_mission_originstation', mission_originstation)}
    {SetState('eddi_context_mission_roundtrip', mission_roundtrip)}

    {if state.eddi_context_missions_accepted > 0:
        {SetState('eddi_context_missions_accepted', state.eddi_context_missions_accepted - 1)}
    }
|else:
   Mission not found in database to delete.
}


Please note that I've included adding and deleting mission 'expiry' data to the MissionStore database. I'm playing with a script which will tell you when you have a mission that's about to expire.

It's still a bit rough but here's what I got thus far:

Code:
{_ MissionStoreCheckExpired }
{_ Check what missions are close to expiring }


{if state.eddi_context_missions_initialised != "yes": {F("MissionStoreInitialise")}}

{set missionstotal to state.eddi_context_missions_accepted}

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

    {set mission_expiry_array to split(state.eddi_context_mission_expiry, "+=")}
    {set mission_name_array to split(state.eddi_context_mission_name, "+=")}
    {set mission_system_array to split(state.eddi_context_mission_system, "+=")}


    {set month_to_days to [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]}

    {for expiry in mission_expiry_array:
        {if expiry != "":

            {_ Convert ISO 8601 to UNIX timestamp }
            {set date to split(slice(expiry, 0, 10),"-")}
            {set time to split(slice(expiry, 11, 8),":")}
            {set year to cast(date[0], "n") - 1970}
            {set month to cast(date[1], "n") - 1}
            {set day to cast(date[2], "n") + floor((year + 2) / 4) - 1}
            {set hour to cast(time[0], "n")}
            {set minute to cast(time[1], "n")}
            {set second to cast(time[2], "n")}
            {set timestamp to (year * 365 + month_to_days[month] + day) * 86400}
            {set timestamp to timestamp + hour * 3600 + minute * 60 + second}

            {_ Get expiration time in minutes }
            {set expiration to round(SecondsSince(timestamp) / 60, 0)}

            {if expiration > 0 && expiration < 120:

                {set pos to find(mission_expiry_array, expiry}
                {set type to mission_name_array[pos]}
                {F("MissionType")}

                Warning: {type} in the {mission_system_array[pos]} system, expiring in {expiration} minutes.

            }
        }
    }
}


As commented in the script, 'eddi_context_mission_timestamp' contains a timestamp of the number of seconds since midnight, 1/1/2017 UTC. This variable is updated by VoiceAttack (at a minimum) for 'Commander continued', 'Jumped', 'Entered supercruise' and 'Entered normal space' events.

Here is the Voice Attack code for ((Timestamp))

Code:
Adjust date/time for your timezone (Presently set for CST)
Set date [Jan-1-2017] value to 12/31/2016 17:00:00

Set integer [eddi_context_mission_timestamp] value to the converted value of {EXP: ({DATETICKS} - {DATETICKS:Jan-1-2017}) / 10000000}
Write '[Blue] EDDI Timestamp = {INT:eddi_context_mission_timestamp}' to log
Set Text [State variable] to 'eddi_context_mission_timestamp'
Execute external plugin, 'EDDI 2.3.0-b8'


As a result of all this fooling around, 'MissionStoreInitialised' and the associated Voice Attack 'Startup' and 'Update' commands must be modified to accommodate the new variables...

Code:
{_ MissionStoreInitialise }
{_ Set up Mission Store variables at start of game }

{SetState('eddi_context_mission_missionid', "")}
{SetState('eddi_context_mission_name', "")}
{SetState('eddi_context_mission_destinationsystem', "")}
{SetState('eddi_context_mission_destinationstation', "")}
{SetState('eddi_context_mission_commodity', "")}
{SetState('eddi_context_mission_passengertype', "")}
{SetState('eddi_context_mission_targetname', "")}
{SetState('eddi_context_mission_targettype', "")}
{SetState('eddi_context_mission_communal', "")}
{SetState('eddi_context_mission_expiry', "")}
{SetState('eddi_context_mission_originsystem', "")}
{SetState('eddi_context_mission_originstation', "")}
{SetState('eddi_context_mission_roundtrip', "")}
{SetState('eddi_context_mission_route', "")}

{SetState('eddi_context_missions_accepted', 0)}

{SetState('eddi_context_missions_initialised', "yes")}

Mission store initialisation complete.
Please check your transaction panel for any outstanding objectives not currently recorded.


Enjoy!
 
Last edited:
Hi Guys,

Regarding the mission manager tool:

-there is an EDDI variable set for nearest destination system.

-on the galaxy map screen in Elite you can enter a system's name in the input field.

-do you think, there is a way to make VA enter the nearest system into that field? Stepping left-right in the menus is no problemo, my question is, how to convert the nearest system variable to a txt, and how to make VA to "type" it into the input field. Maybe a copy-to-clipboard paste-from-clipboard stuff?

If it is possible, we would just need a voice command: "set destination to nearest mission", a macro opens the galaxy map, goes to the input field, sets target system, etc.

Thanks in advance!
 
Hey Darkcyde!

I've cleaned up both the 'MissionStoreAdd' and MissionStoreDelete' scripts. Please check and use as you see fit. [...]

Ooooh, nice! :) Thanks for taking a look over the code. Those changes will make a difference in code length and processing time, in a positive way! To be honest, I was always afraid that constant updating would do something like this, where I miss places that can be made more efficient when adding new stuff to it. Also, I must have read that 'except' command in the Cottle help like a dozen times, but always while looking for other things, so kinda skipped over it. I know there are probably other map processing commands that could probably help even more.

As for the timestamp of missions, I did try to include that with my first pass of the code, when I first wrote it all, but I could never figure out how to get SecondsSince() to work with the timestamp provided by Elite for a mission expiry. Although, I must admit, I didn't spend a lot of time on it as I was trying to get the whole thing working in the first place. I wanted to be able to check things like 'mission that will expire next', or list missions by expiry.

My Fines & Bounties functions are coming along, but slower now. I'm trying to navigate the minefield of 'Active', 'Dormant' & 'Legacy' conditions for fines and bounties against you. It's not easy trying to work out when they change, what causes a change, and how to handle it all. There doesn't seem to be any '100% definitive' information on this aspect. It's not helped by the fact that EDDI only supplies the amount paid when it comes to paying a fine, and considering that can change if you pay at a broker instead of at the factions station, this part has quickly become very difficult. Still, if I can implement your efficiency changes into this as well, it may make things a little easier for me to visualise. I'm hoping I can spend a bit of time on it today.

EDIT: Using a UNIX Timestamp converter, I found that the 01-01-2017 00:00 is 1483228800. You can use this as a base timestamp instead of converting. Also, if you want to get the current timestamp in EDDI, use {set tick to SecondsSince(0)}. This is how I'm using it in 'Fines & Bounties' to calculate expiry timers.

So, where you have VA calculating the time, you can simply do it all in EDDI. like so:-
Code:
{set now to SecondsSince(0)}
{set base_date to 1483228800}

Days elapsed since January 1st 2017 is {round((now - base_date) / 86400, 2)}
Unless I'm misunderstanding what you are doing. :p
This would be useful for those that do not want to (or can't) use VA. The functionality will still be available, albeit only during a play session.
 
Last edited:
Hi Guys,

Regarding the mission manager tool:

-there is an EDDI variable set for nearest destination system.

-on the galaxy map screen in Elite you can enter a system's name in the input field.

-do you think, there is a way to make VA enter the nearest system into that field? Stepping left-right in the menus is no problemo, my question is, how to convert the nearest system variable to a txt, and how to make VA to "type" it into the input field. Maybe a copy-to-clipboard paste-from-clipboard stuff?

If it is possible, we would just need a voice command: "set destination to nearest mission", a macro opens the galaxy map, goes to the input field, sets target system, etc.

Thanks in advance!

I think it should be possible. VA emulates key presses, so it shouldn't be too hard to produce the sequence needed to access the Galaxy Map, tab to the input field, paste the system name, and hit Enter. However, I can't find any key binding that would allow you to set a selected system as a nav point. So while you could make VA find the target system, I don't think you could make it plot a route.
 
Hi,

it starts to work!

First, I copy/pasted a part from the MissionStoreOtherSystems function (Darkcyde, you created a wonderful tool!), just to get the nearest mission destination system's name. Copied to a new script MissionNearestSystemDestination. Here I set a global variable with SetState at the end eddi_context_nearest_name to nearest_name. This goes to VA as a TXT variable.

In VA I have a voice command 'Set nearest mission target'.

First it calls the EDDI script MissionNearestSystemDestination, so the nearest name is for sure the actual one and the global variable is set.

Then start Begin text compare : [EDDI state eddi_context_nearest_name] does not equal '', to check, if the name/destination exists.

Inside the condition I use the set Windows clipboard to {TXT:EDDI state eddi_context_nearest_name}.

From this point, I just have to navigate in the menus to the Galaxy map's input field, send a keypress: CTRL+V, Enter, voila, nearest mission system is highlighted, select plot route, accept, exit :)!

I have to test it, to make sure, that the macro will work in any situation, but basically it does the job:)!

Best regards!
 
Last edited:
Hi,

it starts to work!

First, I copy/pasted a part from the MissionStoreOtherSystems function (Darkcyde, you created a wonderful tool!), just to get the nearest mission destination system's name. Copied to a new script MissionNearestSystemDestination. Here I set a global variable with SetState at the end eddi_context_nearest_name to nearest_name. This goes to VA as a TXT variable.

In VA I have a voice command 'Set nearest mission target'.

First it calls the EDDI script MissionNearestSystemDestination, so the nearest name is for sure the actual one and the global variable is set.

Then start Begin text compare : [EDDI state eddi_context_nearest_name] does not equal '', to check, if the name/destination exists.

Inside the condition I use the set Windows clipboard to {TXT:EDDI state eddi_context_nearest_name}.

From this point, I just have to navigate in the menus to the Galaxy map's input field, send a keypress: CTRL+V, Enter, voila, nearest mission system is highlighted, select plot route, accept, exit :)!

I have to test it, to make sure, that the macro will work in any situation, but basically it does the job:)!

Best regards!

Hi,

@Brigetiol1
I'm glad to hear you have almost done it already! I still don't know very much about VA, but you describe it exactly as I imagined it would work. When you have it perfect, I think I may add it to my EDDI/VA profiles, if that's ok with you?

@Hoodathunk
I've added your improvements to the Mission system, and to the work-in-progress of the Fines & Bounties system. They make a big difference to the 'readabiity' for me. Being half-blind it's not always easy for me to read code when there is a lot of it. Being able to remove great chunks of now redundant code has helped a lot. Thank you. I've also added in the 'expiry' variable too, ready for that functionality. ;)

Fingers-crossed, if things go smoothly (or at least well enough), I may just have a prototype version of F&B ready by next weekend. Or sooner, if things go really well. :D

Best Regards,

-=] Darkcyde [=-
 
Hi Darkcyde,

my EDDI profile's base is your profile. I am happy to be able to give something small in exchange :).

Now the script worked for 5 missions well. I just have to find out something for the delay, when the 'cursor' moves from current system to destination system on the gal-map. If it is a close one, it takes 1 sec (10 lys), for 40lys 3 sec. I think, based on the distance for the nearest mission system calculated in EDDI, it will be easy to set the delay properly, with a loop, for something like this:

[(distance in lys)/10] sec

Man, that will be smooth :)!

Believe me, I'm learning VA just now. But logic is logic, only the syntax is different :). That is why I try to find the 'Syntax for Real Life' eagerly, because I am sure, it is also based on simple logic.

As soon I'll have something acceptably stable, I'll upload it somewhere:)! (I mean, the automatic destination setting, but as soon I'll decode the 'Syntax for Real Life', I'll share that one too :))

Best regards!
 
Ooooh, nice! :) Thanks for taking a look over the code. Those changes will make a difference in code length and processing time, in a positive way! To be honest, I was always afraid that constant updating would do something like this, where I miss places that can be made more efficient when adding new stuff to it. Also, I must have read that 'except' command in the Cottle help like a dozen times, but always while looking for other things, so kinda skipped over it. I know there are probably other map processing commands that could probably help even more.

As for the timestamp of missions, I did try to include that with my first pass of the code, when I first wrote it all, but I could never figure out how to get SecondsSince() to work with the timestamp provided by Elite for a mission expiry. Although, I must admit, I didn't spend a lot of time on it as I was trying to get the whole thing working in the first place. I wanted to be able to check things like 'mission that will expire next', or list missions by expiry.

You're very welcome. I'm very excited about the direction this is going and I'm pleased to contribute.

Lol, As much as you 'forgot' about the 'except' function, I forgot about 'SecondsSince'!

I've fixed the code to build a full Unix timestamp from the ISO 8601 format...

Code:
{_ MissionStoreCheckExpired }
{_ Check what missions are close to expiring }


{if state.eddi_context_missions_initialised != "yes": {F("MissionStoreInitialise")}}

{set missionstotal to state.eddi_context_missions_accepted}

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

    {set mission_expiry_array to split(state.eddi_context_mission_expiry, "+=")}
    {set mission_name_array to split(state.eddi_context_mission_name, "+=")}
    {set mission_system_array to split(state.eddi_context_mission_system, "+=")}


    {set month_to_days to [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]}

    {for expiry in mission_expiry_array:
        {if expiry != "":

            {_ Convert ISO 8601 to UNIX timestamp }
            {set date to split(slice(expiry, 0, 10),"-")}
            {set time to split(slice(expiry, 11, 8),":")}
            {set year to cast(date[0], "n") - 1970}
            {set month to cast(date[1], "n") - 1}
            {set day to cast(date[2], "n") + floor((year + 2) / 4) - 1}
            {set hour to cast(time[0], "n")}
            {set minute to cast(time[1], "n")}
            {set second to cast(time[2], "n")}
            {set timestamp to (year * 365 + month_to_days[month] + day) * 86400}
            {set timestamp to timestamp + hour * 3600 + minute * 60 + second}

            {_ Get expiration time in minutes }
            {set expiration to round(SecondsSince(timestamp) / 60, 0)}

            {if expiration > 0 && expiration < 120:

                {set pos to find(mission_expiry_array, expiry}
                {set type to mission_name_array[pos]}
                {F("MissionType")}

                Warning: {type} in the {mission_system_array[pos]} system, expiring in {expiration} minutes.

            }
        }
    }
}


I've whipped up a script that will find the next expiring mission and populate 'eddi_context_mission_destination' with the system name...

Code:
{_ MissionStoreNextExpired }
{_ Find the mission closest to expiring }


{set missionstotal to state.eddi_context_missions_accepted}

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

    {set mission_expiry_array to split(state.eddi_context_mission_expiry, "+=")}
    {set mission_system_array to split(state.eddi_context_mission_system, "+=")}

    {set month_to_days to [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]}
    {set next_expired to 10000000}
    {set next_expired_system to ""}

    {for expiry in mission_expiry_array:
        {if expiry != "":

            {_ Convert ISO 8601 to UNIX timestamp }
            {set date to split(slice(expiry, 0, 10),"-")}
            {set time to split(slice(expiry, 11, 8),":")}
            {set year to cast(date[0], "n") - 1970}
            {set month to cast(date[1], "n") - 1}
            {set day to cast(date[2], "n") + floor((year + 2) / 4) - 1}
            {set hour to cast(time[0], "n")}
            {set minute to cast(time[1], "n")}
            {set second to cast(time[2], "n")}
            {set timestamp to (year * 365 + month_to_days[month] + day) * 86400}
            {set timestamp to timestamp + hour * 3600 + minute * 60 + second}

            {_ Get expiration time in seconds }
            {set expiration to SecondsSince(timestamp)}

            {if expiration < next_expired:

                {set next_expired to expiration}

                {set pos to find(mission_expiry_array, expiry}
                {set next_expired_system to mission_system_array[pos]}
            }
        }
    }
    {Setstate('eddi_context_mission_destination', next_expired_system}
    {Setstate('eddi_context_mission_next_expired', next_expired}
}


Also, I've had my course plotting automated for some time, this is an example of my VA command...

Code:
Begin Text Compare : [eddi_context_mission_destination] Does Not Equal ''
    Set Text [Destination] to [eddi_context_mission_destination]
    Set Windows clipboard to '{TXT:Destination}'
    Execute command, '((Get destination distance))' (by name) (and wait until it completes)
    
    Execute command, '((RS - Stand By))' (by name) (and wait until it completes)
    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)
    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-b8'
    
    Quick Input, '{CLIP}'
    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-b8'
    Set Text [Script] to 'Destination confirmed.'
    Execute external plugin, 'EDDI 2.3.0-b8'
    
    Pause 2 seconds
    Execute command, 'Close galaxy map' (by name) (and wait until it completes)
End Condition
 
Last edited:
Hi,

set destination for nearest mission, set destination to most missions, set destination to most urgent missions... do I have all components for xy blueprint? Find nearest engineer to upgrade my missiles, set as destination... I'm curious, if this will be possible to do with fines, bounties?
 
No leap years?

Good catch... originally a timestamp from 1/1/2017, so didn't need to account for leapyears.

Caught some other errors... Fixed, verified against a UNIX timestamp generator, and updated in previous post.

Thanks for keeping us honest! :)
 
Last edited:
Hello all. I'm interested in have the EDDI body report script read off the materials and percentages that are on scanned planets. I see that the materials and percents are listed in a body.materials array.

I am at a loss to figure out a way to read out this information. Does anyone have any ideas or examples that would have EDDI read out the materials and percentages on scanned planets?
 
Hello all. I'm interested in have the EDDI body report script read off the materials and percentages that are on scanned planets. I see that the materials and percents are listed in a body.materials array.

I am at a loss to figure out a way to read out this information. Does anyone have any ideas or examples that would have EDDI read out the materials and percentages on scanned planets?


Here you go!

Code:
{_ Fetch from context }
{set reportbody to BodyDetails(state.eddi_context_body_name, state.eddi_context_body_system)}

{if !reportbody.name || reportbody.name = "":
    I'm not sure which body you are asking about.
|else:
    {P(reportbody.name)} is a
    {if reportbody.gravity < 0.5:
        low-gravity
    |elif reportbody.gravity <2:
        medium-gravity
    |elif reportbody.gravity <4:
        high-gravity
    |else:
        extremely high-gravity
    }

    {if reportbody.tidallylocked:
        tidally-locked
    }

    {if reportbody.terraformstate = "Terraformable":
        terra-formable
    |elif reportbody.terraformstate = "Terraformed":
        terra-formed
    }

    {if len(reportbody.rings) > 0:
        ringed
    }

    {reportbody.planettype}

    {if reportbody.terraformstate = "Terraforming":
      in the process of being terra-formed
    }

    that is

    {if reportbody.landable:
        suitable
    |else:
        unsuitable
    }
    for landing.

    {_ Atmosphere? }

    {if reportbody.volcanism:
        This planet shows signs of volcanism, with
        {if reportbody.volcanism.type = 'Geysers':
            {if reportbody.volcanism.amount = 'Major':
                high numbers of
            |elif reportbody.volcanism.amount = 'Minor':
                low numbers of
            }
            active {reportbody.volcanism.composition} guy-sers
        |else:
            {if reportbody.volcanism.amount = 'Major':
                high levels of
            |elif reportbody.volcanism.amount = 'Minor':
                low levels  of
            }
            active {reportbody.volcanism.composition} magma flows
        }.
    }

    {if reportbody.landable :
        It has 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 Humanise(reportbody.rotationalperiod) != "1":s}.

        {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:
            .
        }
    }
}


You can 'grep' this version of 'Body report' against the default to see what I did.
 
Last edited:
Back
Top Bottom