cmdrmcdonald / EliteDangerousDataProvider

Apache License 2.0
133 stars 31 forks source link

Fixing the Fuel Scooping Problem #208

Open Darkcyde13 opened 7 years ago

Darkcyde13 commented 7 years ago

Hi,

As I mentioned before in issue #202, the Elite 2.3 update started putting multiple entries in the Journal for Fuel Scooping. I have made a bug report on the FD forums but as yet had no reply or acknowledgement.

So, I decided to investigate a fix from within EDDI and I seem to have succeeded. Below is my version of Ship Refuelled which corrects the multiple reporting during a scooping session. This reports the total only once, a couple of seconds after scooping is finished.

EDIT: It seems this will only work for the betas, not the stable release (as of 26-05-17).

{_ Context}
{SetState('eddi_context_last_subject', 'refuelling')}
{SetState('eddi_context_last_action', 'complete')}
{SetState('eddi_context_fuel_remaining', event.total)}

{set fuelscooped to state.eddi_fuel_scooped}
{set fueltotal to ship.fueltanktotalcapacity}

{if event.source = "Market":
   {Occasionally(2,"{OneOf('{ShipName()}','Ship')}")}
   {OneOf("re-fuelled","fuel tanks topped up","tanks re-filled")}
   {Occasionally(3,"by {Humanise(event.amount)} tonnes")}.
|else:
   {SetState('eddi_fuel_scooped',(state.eddi_fuel_scooped + event.amount))}

   {if event.amount <= 5.0000:
      {set total to (100/fueltotal)*event.total}

      {set trim to round((100/fueltotal)*state.eddi_fuel_scooped,1)}
      {F("ZeroTrim")}
      {set percent to trim}

      {set trim to round(state.eddi_fuel_scooped,1)}
      {F("ZeroTrim")}
      {set tonnes to trim}

      {SetState('eddi_fuel_scooped',0)}
      {Pause(3000)}

      {if tonnes = 1:
         {set tons to "tonne"}
      |else:
         {set tons to "tonnes"}
      }

      {OneOf("{percent}% refuelled",
             "Refuelled by {OneOf('{percent}%','{tonnes} {tons}')}",
             "{OneOf('{percent}%','{tonnes} {tons}')} taken on board")},

      {if total = 100:
         {Occasionally(2,"Main")}
         {Occasionally(2,"Fuel")}
         tanks at {OneOf("Maximum","100%")}
         {Occasionally(2,"capacity")}
      |else:
         {F("JumpFuel")}
      }
      {Occasionally(3,"{F('Honorific')}")}.
   }
}

The 5.0000 is important as the Journal (at least, in my case anyway) always puts the scooped amounts to a fraction over 5 tonnes. You will also note that I use a ZeroTrim function that removes trailing zeros from the numbers. I tried to use Humanise, but this kept removing the '.1' in numbers like '16.1' so it was only saying '16' when I wanted a number to one decimal place.

This is my ZeroTrim function. Set the variable you want trimmed to TRIM:-

{set x to "0"}

{while x = "0":
   {set x to slice(trim,len(trim)-1,1)}
   {if x = "0":
       {set trim to slice(trim,0,len(trim)-1)}
   }
}
{if slice(trim,len(trim)-1) = ".":
   {set trim to slice(trim,0,len(trim)-1)}
}

Finally, I also use a JumpFuel function to report number of jumps with available fuel reserves, for the occasions I don't fully refuel. I also call this function at the end of a jump, in the Jumped event.

{_ Report fuel level for max range jumps remaining}

{set fuelremaining to state.eddi_context_fuel_remaining}
{set class to ship.frameshiftdrive.class}
{set grade to ship.frameshiftdrive.grade}
{set fuellevel to round((fuelremaining/ship.fueltanktotalcapacity)*100,1)}

{if grade='E' || grade='D' || grade='C':
    {if class=2: {set maxfuel to 0.6}
    |elif class=3: {set maxfuel to 1.2}
    |elif class=4: {set maxfuel to 2.0}
    |elif class=5: {set maxfuel to 3.3}
    |elif class=6: {set maxfuel to 5.3}
    |elif class=7 || class=8: {set maxfuel to 8.5}
    }
|elif grade='B':
    {if class=2: {set maxfuel to 0.8}
    |elif class=3: {set maxfuel to 1.5}
    |elif class=4: {set maxfuel to 2.5}
    |elif class=5: {set maxfuel to 4.1}
    |elif class=6: {set maxfuel to 6.6}
    |elif class=7 || class=8: {set maxfuel to 10.6}
    }
|elif grade='A':
    {if class=2: {set maxfuel to 0.9}
    |elif class=3: {set maxfuel to 1.8}
    |elif class=4: {set maxfuel to 3.0}
    |elif class=5: {set maxfuel to 5.0}
    |elif class=6: {set maxfuel to 8.0}
    |elif class=7 || class=8: {set maxfuel to 12.8}
    }
}

{set maxjump to fuelremaining/maxfuel}

{if fuellevel < 25: Warning;
|elif fuellevel <50: Caution;
}

{set trim to fuellevel}
{F("ZeroTrim")}
{set fuellevel to trim}

Fuel {OneOf("level","tanks")} at {fuellevel}% {Occasionally("capacity")}

{if maxjump < 1:
   {OneOf("You do not have enough fuel for a max jump","Fuel reserves depleted")}.
   Refuel {OneOf("as soon as possible","at the {OneOf('earliest','soonest')} opportunity")}
|elif maxjump < 2: {OneOf("You have fuel for only one max jump","Fuel for only one max jump remains")}
|elif fuellevel < 75: {floor(maxjump)} max jumps remain
}

Of course, this uses a default FSD drive fuel consumption number, but it's close enough 90% of the time. I'm only including it here for completeness of my setup.

Feel free to use any, all or none of these. If you can make a built-in function for ZeroTrim, then that would be great too.

Keep up the great work Commander! :)

Kind regards,

Darkcyde.

Darkcyde13 commented 7 years ago

I just realised I can make ZeroTrim a bit more efficient. :)

{set x to slice(trim,len(trim)-1,1)}

{while x = "0":
   {set trim to slice(trim,0,len(trim)-1)}
   {set x to slice(trim,len(trim)-1,1)}
}

{if x = ".":
   {set trim to slice(trim,0,len(trim)-1)}
}
icextend commented 7 years ago

Cool /// waiting for implementation if anyone care. $Shipname refueled spam is ruining the experience.

Darkcyde13 commented 7 years ago

Just use what I have written above. It works perfectly. One single report of how much fuel was taken on board when scooping has finished. It doesn't matter if you fill your tank, or if you stop with half a tank, it will always tell you exactly how much, two seconds after finishing. Of course, you can edit what is said to your preference, but the mechanics of it are sound

MisteryMan commented 7 years ago

@Darkcyde13 I have attempted to use this script and it's functions. Sadly they keep resulting in 0% mentions across the board.

EDIT: Seems this only works on the current beta of EDDI. Not on the stable version due to complication in retrieving data from the companion API

Darkcyde13 commented 7 years ago

Ah, of course. My apologies, I always use the latest version of EDDI, and often forget that's not everyone runs the betas.

Thank you for clarifying that this fix only works in the latest beta versions though. :)

antrys commented 7 years ago

As long as we don't change the fact that the event triggers like it does, I'm fine I use the reporting of over/under 5 to decide weather to trigger my auto jump. If that gets implemented, it breaks a whole ton of code I've done in VA.

BeBumble commented 7 years ago

Can I just c&p this into the Ship refueled script in EDDI? Thought I could handle the 5T thing but its driving me nuts after all this time now

antrys commented 7 years ago

Yup, you should be able to paste darkcyde13's code into it. If you ever get it messed up, you can always click on revert to default.

He built EDDI pretty smart :)

Darkcyde13 commented 7 years ago

Yeah you should be able to just copy & paste into the ship refuelled script. The ZeroTrim function only cuts off trailing zeros from the number, makes it sound better. But not necessary to have if you don't want that part.

If you have trouble, let me know, and I'll see what I can do to help. Also, no one else has told me if it works for them or not, so I'd like to know how well (or not) it works for you.

antrys commented 7 years ago

Another approach (Advanced?) If you have Voice attack, you can disable the command within EDDI, and write your own command to handle it in voice attack. call this command: ((EDDI ship refuelled))

Here's my VA code, it's pretty specific to my VA setup, but it may give you an idea of how to do it.

**If we're fuel scooping.....
Begin Condition : ([QUIET MODE] Equals False AND [{TXT:EDDI ship refuelled source}] Equals 'Scoop')

    Set decimal [FUEL LEVEL] value to the converted value of {DEC:EDDI ship refuelled total} (round to 1 decimal place)

    **Send to custom ((Speak)) command. I set a TXT variable with want I want to say and send it there, so I can change one parameter in that script and change voices script-wide, instead of a thousand edits....
    Set Text [SPEECH] to '{DEC:FUEL LEVEL} tons'
    Execute command, '(((Speak))) [SPEECH] AI Voice' (and wait until it completes)

    Write '[Purple] {DEC:EDDI ship refuelled amount} Fuel Gained - this report' to log
    Write '[Purple] {DEC:EDDI ship refuelled total}}  - Total Fuel' to log
End Condition

**Trigger the auto-jump after fueling
**We know this because the last fueling trigger from the API was less than 5 tons, so we assume we're full, or left the sun's scoop area.
**[AUTO JUMP] is a BOOL set to decide weather my Auto Jump is enabled, triggered from another voice command.
**[OVERRIDE ENABLED] is an override BOOL set in another command .  If something goes wrong with this auto-jump, or I want to stay in-system a while, I want to be able to override and cancel this command.
Begin Condition : ([EDDI ship refuelled amount] Is Less Than 5.00000 AND [AUTO JUMP] Equals True AND [{TXT:EDDI ship refuelled source}] Equals 'Scoop' AND [OVERRIDE ENABLED] Equals False)
    Set Boolean [AUTO JUMP IN PROGRESS] to True
    DISABLED - Say, 'Take us out' or 'leave orbit' or 'ahead full' or 'ahead flank speed'  (and wait until it completes)
    Set Text [SPEECH] to 'Take us out.'
    Execute command, '(((Speak))) [SPEECH] AI Voice' (and wait until it completes)
    Execute command, 'Ahead Full;Flank speed'
    **Give time to escape orbit..... You'll know if you need to override or everything is going smooth in these 10 seconds.
    Pause 5 seconds
    Say, 'Jump in Five'
    Pause 1 second
    Say, 'Four'
    Pause 1 second
    Say, 'Three'
    Pause 1 second
    Say, 'Two'
    Pause 1 second
    Say, 'mark' or 'execute' or 'jump' or 'punch it'  (and wait until it completes)
    **My actual jump command...
    Execute command, 'Jump;cancel jump;jump cancel' (and wait until it completes)
End Condition

**If we purchased fuel from a market....
Begin Text Compare : [{TXT:EDDI ship refuelled source}] Equals 'Market'
    Set decimal [MARKET FUEL PURCHASED] value to the converted value of {DEC:EDDI ship refuelled amount} (round to 1 decimal place)
    Set Text [SPEECH] to '{DEC:MARKET FUEL PURCHASED} tons, for {DEC:EDDI ship refuelled price} credits.'
    Execute command, '(((Speak))) [SPEECH] AI Voice' (and wait until it completes)
End Condition