Compare commits
174 commits
releases/4
...
release
Author | SHA1 | Date | |
---|---|---|---|
f034ae4220 | |||
d97499778c | |||
d78cf17b6b | |||
0d44828422 | |||
022c3ac25c | |||
fd0bbaa3a9 | |||
cc2694fc49 | |||
9db6785ef1 | |||
1135efd761 | |||
7c361e9bf7 | |||
54cd1e6fa2 | |||
3775d3f911 | |||
|
1357bde807 | ||
db85c2b793 | |||
4f9e4799bf | |||
5af0aff95c | |||
e2789623cd | |||
c615af5324 | |||
|
4e9a9b4517 | ||
|
38ea143ea7 | ||
|
0ee7701590 | ||
|
05a56d5d85 | ||
|
2ec9c2afbe | ||
|
3cbfe62ae1 | ||
|
9cc9965d7c | ||
acf43b42a0 | |||
55fa3579cf | |||
d1af3ebdcc | |||
b10e2bb2c4 | |||
91c47efbef | |||
1cdd9c98bd | |||
35c26e930f | |||
bb8d1067b5 | |||
6ec8d7c35e | |||
55f10a1117 | |||
35057b3f35 | |||
a2f6cc864c | |||
9beb6dfa41 | |||
2dae2abc4c | |||
99305cfb5d | |||
bc5addd22a | |||
64a096dae7 | |||
33a4fb8e3d | |||
3cbca1e542 | |||
55a031686c | |||
02a401a047 | |||
e36358be9f | |||
999d2b6883 | |||
e73b8c04f9 | |||
931ee4c4e7 | |||
751f80461f | |||
c9d39f6cc7 | |||
f8dd1ff464 | |||
f7328e31e2 | |||
2b0d2245e2 | |||
dc42912cbe | |||
b3ad1ae799 | |||
5421478d6e | |||
d771d0b403 | |||
b371523910 | |||
8572d0ec4c | |||
c00c1d9bbe | |||
0c0cf068c4 | |||
42faaa20d5 | |||
da9a6f6107 | |||
a5b22a8908 | |||
20599fef88 | |||
99438b4ed3 | |||
368b7ca771 | |||
5442738a21 | |||
d6cd7da11c | |||
2f4015001f | |||
81b83bba2d | |||
2544be701c | |||
9a8d7b646f | |||
999650e84f | |||
f69e3c03bd | |||
e81f3961ea | |||
8a3b17d674 | |||
d038c58595 | |||
08aaa3db8a | |||
7cad49a6c2 | |||
2997b8335c | |||
5bf21a48ba | |||
28854968fd | |||
00923f3da5 | |||
fa4e9535ba | |||
302fd9f512 | |||
0e757eaf76 | |||
7bc58f19ef | |||
4836273007 | |||
adcb01bead | |||
61e7f00c1f | |||
a57daf35a7 | |||
e12bb8a2ea | |||
f00fd22234 | |||
2715fa2a48 | |||
36abf8b53b | |||
bcbde1dd47 | |||
ec87397a92 | |||
4483945f6a | |||
3261c11d70 | |||
7c1c75ec98 | |||
f6b5621bb2 | |||
a1ddb987e0 | |||
3c46b20a23 | |||
b633d8791c | |||
a5a3740799 | |||
1d6ee3953e | |||
d47ea2597c | |||
42488b3bcf | |||
25a7440c7b | |||
254ada7318 | |||
aed4609ed8 | |||
1991e6b5f6 | |||
b30074317f | |||
3b9031ae59 | |||
2d8b923d0e | |||
c546c22bc4 | |||
387f17db1d | |||
ef86f0a517 | |||
2411514643 | |||
7aaf8d62b1 | |||
68716bb45b | |||
9705bba899 | |||
2cda77edda | |||
ffad1ffa28 | |||
0c592af8e2 | |||
9745e1ccb1 | |||
4fcca54ff0 | |||
71615e366c | |||
26dd98f050 | |||
fd0e07ecfa | |||
eda735a426 | |||
4495d9ead2 | |||
1904dd6d41 | |||
a5b0d175a2 | |||
b2f8ec96d6 | |||
7511d59641 | |||
e4ea1abb5e | |||
5e94677048 | |||
99dfc2cf09 | |||
9ce06804f4 | |||
4fba3ef79b | |||
2d6c96fce0 | |||
fdccb3a4ff | |||
5d429d463a | |||
b4f26f33c8 | |||
bc902310f8 | |||
eee768896b | |||
4c3b890120 | |||
d210779967 | |||
14092bf174 | |||
c47c26482c | |||
6cd7722db1 | |||
72633273e1 | |||
dc216dade8 | |||
62b94b000e | |||
4bd6ccc7a7 | |||
bd94f2e0f8 | |||
0d0fdc58a8 | |||
f2ca6dd0ad | |||
fa645fc369 | |||
f0a006a113 | |||
ec7f6798eb | |||
4affcb85ff | |||
27dbffbe79 | |||
205f90870b | |||
d512b5edbc | |||
9c1406c08b | |||
c7cbaec218 | |||
7c7a6b8718 | |||
0e350ccc3d | |||
32f43660fd |
14
.editorconfig
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[*]
|
||||||
|
guidelines = 80
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
charset = utf-8-bom
|
||||||
|
|
||||||
|
[*.cs]
|
||||||
|
guidelines = 80, 120
|
||||||
|
|
||||||
|
# IDE0021: Use block body for constructors
|
||||||
|
csharp_style_expression_bodied_constructors = when_on_single_line
|
||||||
|
|
||||||
|
# IDE0024: Use block body for operators
|
||||||
|
csharp_style_expression_bodied_operators = when_on_single_line
|
2
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
github: alterNERDtive
|
||||||
|
ko_fi: alterNERDtive
|
12
.github/dependabot.yaml
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "nuget"
|
||||||
|
directory: "/"
|
||||||
|
target-branch: "develop"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
target-branch: "develop"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
20
.github/workflows/auto-pull-request.yaml
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
name: Pull Request on Branch Push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches-ignore:
|
||||||
|
- devel
|
||||||
|
- release
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
auto-pull-request:
|
||||||
|
name: Open pull request
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: pull-request-action
|
||||||
|
uses: vsoch/pull-request-action@1.0.19
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
PULL_REQUEST_BRANCH: "devel"
|
||||||
|
PULL_REQUEST_DRAFT: true
|
||||||
|
PASS_IF_EXISTS: true
|
23
.github/workflows/create-release.yaml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
name: Create release on tag push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'releases/*.*'
|
||||||
|
- 'releases/*.*.*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Create draft release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Draft release
|
||||||
|
uses: ncipollo/release-action@v1
|
||||||
|
with:
|
||||||
|
bodyFile: "CHANGELOG.md"
|
||||||
|
draft: true
|
||||||
|
token: ${{ secrets.RELEASE_TOKEN }}
|
22
.github/workflows/gh-pages.yaml
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
name: Deploy github pages on tag push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'release/*.*'
|
||||||
|
- 'release/*.*.*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Deploy documentation
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Deploy docs
|
||||||
|
uses: mhausenblas/mkdocs-deploy-gh-pages@nomaterial
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
REQUIREMENTS: requirements.txt
|
1
.gitignore
vendored
|
@ -358,3 +358,4 @@ MigrationBackup/
|
||||||
/Makefile
|
/Makefile
|
||||||
/site
|
/site
|
||||||
/src
|
/src
|
||||||
|
/build.csproj
|
||||||
|
|
379
CHANGELOG.md
|
@ -1,3 +1,359 @@
|
||||||
|
# 4.5 (2022-09-19)
|
||||||
|
|
||||||
|
This might very well be the last release of this. With how the “Horizons 4.0”
|
||||||
|
launch went, Frontier’s communication around it, and just _how_ horrible 4.0 is,
|
||||||
|
I currently do not see me being motivated to actually port stuff to 4.0. And,
|
||||||
|
let’s face it, 3.8 will go EoL eventually.
|
||||||
|
|
||||||
|
Anyway, I still have some programming pet projects around this stuff that I
|
||||||
|
might continue with and adapt this for, so I might sneak some fixes / updates
|
||||||
|
in, and I’m not going to say never because who knows how I’ll feel about this in
|
||||||
|
the future. Obviously there’s also still the option to _pay_ me to do stuff =p
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Race condition in all plugins that might lead to commands using command-scoped
|
||||||
|
variables (`~<name>`) not working as intended. This was introduced in
|
||||||
|
refactoring work that was done for 4.4.
|
||||||
|
* Documentation proof read and fixed by @ACyprus. Thanks!
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Some behind the scenes things regarding how builds work. This will make it
|
||||||
|
possible to build this entirely on Github (= less potential for human error)
|
||||||
|
once I have dealt with #62 (see #143 as well).
|
||||||
|
|
||||||
|
## EliteAttack 8.5
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* `target nearest […]` commands now log the result (with log level “INFO”).
|
||||||
|
* `include outdated settlements` option: Include Odyssey settlements in the
|
||||||
|
outdated stations list. Default: true.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* `Docked` event now handles Odyssey settlements properly (they have no hangar).
|
||||||
|
(#145)
|
||||||
|
* Fixed potential race condition with the discovery scan event command queue.
|
||||||
|
Might have an impact on #64.
|
||||||
|
|
||||||
|
## RatAttack 6.4
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Support for new Horizons 3 / Horizons 4 / Odyssey RATSIGNALs. (#159)
|
||||||
|
* Made case list thread safe. Probably only ever impacted my own specific setup,
|
||||||
|
but still a huge 🤦.
|
||||||
|
* Apparently `^` can be part of both CMDR names and IRC nicks (fixed RATSIGNAL
|
||||||
|
regex).
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# 4.4 (2022-05-31)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* The Configuration GUI now has an “Apply” button.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Configuration GUI now `.Activate()`s immediately to prevent it from hiding
|
||||||
|
behind other windows.
|
||||||
|
|
||||||
|
## EliteAttack 8.4
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* `auto retract landing gear` setting: Automatically retract landing gear when
|
||||||
|
lifting off a planet / undocking from a station. Default: true. (#133)
|
||||||
|
* `auto disable s r v lights` setting: Automatically turn SRV lights off when
|
||||||
|
deploying one. Default: true. (#133)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* `auto enter station services` option. (#142)
|
||||||
|
|
||||||
|
## RatAttack 6.3.1
|
||||||
|
|
||||||
|
* Added error message to the CLI tool for running VoiceAttack with elevated
|
||||||
|
privileges which will cause an `UnAuthorizedAccessException` trying to
|
||||||
|
communicate with the plugin. (#138)
|
||||||
|
* Added warning to VoiceAttack when running it with elevated privileges. (#138)
|
||||||
|
|
||||||
|
## SpashAttack 7.2.2
|
||||||
|
|
||||||
|
* Fixed getting current jump range from EDDI; no longer fails on the first try,
|
||||||
|
no longer sometimes reports the last requested range instead of current.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# 4.3 (2022-05-19)
|
||||||
|
|
||||||
|
**NOTE**: Further development is on hold and Odyssey compatibility will not be
|
||||||
|
worked on for the time being. See [the corresponding issue on
|
||||||
|
Github](https://github.com/alterNERDtive/VoiceAttack-profiles/issues/113). Feel
|
||||||
|
free to file issues for anything that is broken on Odyssey and it will be worked
|
||||||
|
on when it is worked on.
|
||||||
|
|
||||||
|
That said, there is now a settings UI! It’s not pretty, it’s basic, but it does
|
||||||
|
the job.
|
||||||
|
|
||||||
|
* Updated documentation for the switch to 64-bit as the standard VoiceAttack
|
||||||
|
distribution format.
|
||||||
|
* Updated included `bindED` plugin.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* `customize settings` command: Brings up a rudimentary settings UI. (#80)
|
||||||
|
* `open documentation` command: Opens the profile’s documentatin in your
|
||||||
|
default browser.
|
||||||
|
* Section about HCS compatibility in “Troubleshooting” documentation (#130).
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Log level settings description no longer contains literal `\n`s.
|
||||||
|
* Documentation now mentions that you have to reload your custom profile after
|
||||||
|
creating the `startup` command for the first time. (#129)
|
||||||
|
* Clarified not having to install bundled dependencies manually. (#127)
|
||||||
|
* Reordered setup instructions to clarify that the profile example already comes
|
||||||
|
with a `startup` command. (#126)
|
||||||
|
* No longer cuts off EDDI’s “update available” TTS on VoiceAttack start. (#120)
|
||||||
|
* Implemented workaround for EDDI’s `Body scanned` event sometimes not setting
|
||||||
|
variables correctly. Might drop some events, will log to `DEBUG`. (#121)
|
||||||
|
|
||||||
|
## EliteAttack 8.3
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* `INFO` logging for carrier events.
|
||||||
|
* `auto refuel` setting: Automatically refuel after docking at a station.
|
||||||
|
Default: true. (#133)
|
||||||
|
* `auto repair` setting: Automatically repair after docking at a station.
|
||||||
|
Default: true. (#133)
|
||||||
|
* `auto move to hangar` setting: Automatically move the ship to the hanger after
|
||||||
|
docking at a station. Default: true. (#133)
|
||||||
|
* `auto enter station services`: Automatically enter the Station Services menu
|
||||||
|
after docking at a station. Default: true. (#133)
|
||||||
|
* `find nearest […]` command now logs the result to the VoiceAttack log (log
|
||||||
|
level `INFO`). (#96)
|
||||||
|
|
||||||
|
## RatAttack 6.3
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Now gives feedback after asking for call confirmation: “Call aborted.” /
|
||||||
|
“Calling <…>.”.
|
||||||
|
* `auto copy rat case system` setting: Automatically copy the client’s system to
|
||||||
|
the clipboard when you open a rat case. Default: true.
|
||||||
|
* Now asks for call confirmation more clearly: “send call \<call\> to fuel
|
||||||
|
rats?” instead of an easily misinterpreted “call \<call\>?”. The question
|
||||||
|
inflection is more or less pronounced depending on the TTS voice used and has
|
||||||
|
led to confusion. (#101)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* No longer trying to get nearest CMDR for the new “Unconfirmed” system info.
|
||||||
|
* Fixed RATSIGNAL parsing for locales containing `&`.
|
||||||
|
* Fixed RATSIGNAL parsing for system information containing `/` (e.g. “Herbig
|
||||||
|
AE/BE star”).
|
||||||
|
* “Not Set” case number when asking for details about an invalid case.
|
||||||
|
* Fixed RATSIGNAL parsing for locales containing `,`.
|
||||||
|
* No longer determines (nor logs) nearest CMDR if announcing nearest CMDR is
|
||||||
|
turned off while also being off duty.
|
||||||
|
* No longer silently swallows calls if call confirmation is disabled. (#128)
|
||||||
|
|
||||||
|
## SpanshAttack 7.2.1
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* OBOE on last jump.
|
||||||
|
* Moved jumps left announcement from getting the next waypoint (now happens at
|
||||||
|
the start of a jump) to the `Jumped` event (happens after a jump). (#124)
|
||||||
|
* Will no longer go to neutron jump mode if no route has been found (= there is
|
||||||
|
only a single waypoint). (#104)
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# 4.2.3 (2021-05-23)
|
||||||
|
|
||||||
|
Updated included bindED plugin to version 4.1 that fixes Odyssey compatibility.
|
||||||
|
|
||||||
|
No actual code / profile changes.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# 4.2.2 (2021-05-19)
|
||||||
|
|
||||||
|
Now comes with Odyssey-compatible bindED.
|
||||||
|
|
||||||
|
**DO read [the release notes on
|
||||||
|
that](https://github.com/alterNERDtive/bindED/releases/tag/release/4.0) before
|
||||||
|
upgrading!**
|
||||||
|
|
||||||
|
## RatAttack 6.2.2
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Added handling for Odyssey clients. (#114)
|
||||||
|
* Correctly setting system for manual Ratsignals (`""`) to `None` now. IMO a
|
||||||
|
Mecha bug, but whatever.
|
||||||
|
* Code reds are now correctly detected again with the new case announcement
|
||||||
|
format. (#115)
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# 4.2.1 (2021-05-03)
|
||||||
|
|
||||||
|
This will probably be the last pre-Odyssey release. I am not in the Odyssey
|
||||||
|
alpha, and I have no ETA on a compatibility release. Please do file issues you
|
||||||
|
encounter regardless.
|
||||||
|
|
||||||
|
Changes to the RATSIGNAL produced by Swiftsqueak broke not only the parsing, but
|
||||||
|
also the default string used to detect them in AdiIRC. You’ll need to listen to
|
||||||
|
`on *:TEXT:*RATSIGNAL*(??_SIGNAL):#fuelrats:` instead.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
* Reworded the 32- vs. 64-bit part of the VoiceAttack installation instructions.
|
||||||
|
Some scenarios require one or the other, otherwise it probably doesn’t matter
|
||||||
|
which you pick.
|
||||||
|
|
||||||
|
## EliteAttack 8.2.1
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* ~~No longer tries to auto-honk after a hyperdiction event. (#105)~~ Sadly
|
||||||
|
doesn’t quite work, yet.
|
||||||
|
* On-demand outdated station check works again. (#108)
|
||||||
|
|
||||||
|
## RatAttack 6.2.1
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fixed RATSIGNAL parsing for new format. Needs adjusting your IRC client, see
|
||||||
|
above. IRC formatting will now be stripped before sending to VoiceAttack.
|
||||||
|
(#111)
|
||||||
|
* Fixed RATSIGNAL parsing for language strings that contain numbers (e.g.
|
||||||
|
“es-419”).
|
||||||
|
* Fixed RATSIGNAL parsing for “unknown system” (which contains a zero-width
|
||||||
|
space …)
|
||||||
|
* Fixed RATSIGNAL parsing for procedually generated landmark systems.
|
||||||
|
* Fixed RATSIGNAL parsing landmark systems with alternate names.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Removed the TTS prompt and logging from incoming invalid RATSIGNALs by
|
||||||
|
default, for real this time. See the `((RatAttack.invalidRatsignal))` command
|
||||||
|
for info on how to re-enable for yourself.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# 4.2 (2021-03-09)
|
||||||
|
|
||||||
|
## EliteAttack 8.2
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* "limpet check" configuration option: Do a limpet check when undocking,
|
||||||
|
reminding you if you forgot to buy some. Default: true. (see discussion on
|
||||||
|
#86)
|
||||||
|
|
||||||
|
## RatAttack 6.2
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* `distance to latest rat case` command: gives you you current distance to the
|
||||||
|
latest rat case.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fixed RATSIGNAL parsing for “Sagittarius A*” landmark.
|
||||||
|
* Fixed RATSIGNAL parsing for new wording of injected cases with no system
|
||||||
|
given.
|
||||||
|
* Fixed RATSIGNAL parsing for “cardinal direction” addition to distance
|
||||||
|
estimates for proc gen systems.
|
||||||
|
|
||||||
|
## SpanshAttack 7.2
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Moved EDTS system coordinate estimation code from Python script to the
|
||||||
|
VoiceAttack plugin.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
* `edts.exe` Python script.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# 4.1 (2021-02-19)
|
||||||
|
|
||||||
|
## EliteAttack 8.1
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* `how many jumps left` command: Announces the jumps left on a neutron trip
|
||||||
|
(requires SpanshAttack) or a course plotted via the galaxy map.
|
||||||
|
* `route jump count` configuration option: Give a jump count on plotting a
|
||||||
|
route. Default: true.
|
||||||
|
* Now reports on AFMU repairs.
|
||||||
|
* `repair reports` configuration option: Report on AFMU repairs. Default: true.
|
||||||
|
* Now reports on Synthesis.
|
||||||
|
* `synthesis reports` configuration option: Report on synthesis. Default: true.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Restricted outdated stations check to systems with stations again.
|
||||||
|
* `Material Threshold` event should no longer cause logging errors.
|
||||||
|
|
||||||
|
## RatAttack 6.1
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* `call jumps [left;]` command: Calls jumps for the currently open case based on
|
||||||
|
a neutron trip (requires Spanshattack) or a plotted ingame route.
|
||||||
|
* Now uses Mecha’s system information in the RATSIGNAL in case announcements.
|
||||||
|
* `system information for fuel rat case` configuration option: System
|
||||||
|
information provided by Mecha. Default: true.
|
||||||
|
* `latest rat case details` command: Will give you the case data for the
|
||||||
|
latest incoming case.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Removed TTS prompt from the invalid RATSIGNAL trigger. It’s still in the log,
|
||||||
|
but you won’t get spammed in voice every time the format changes before an
|
||||||
|
update to the profiles is out.
|
||||||
|
* No longer looks up your nearest CMDR to a rat case if the system is neither in
|
||||||
|
Mecha’s galaxy database nor a potentially valid system name. (#89)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Updated RATSIGNAL parsing to correctly handle new format for landmark systems.
|
||||||
|
* Updated RATSIGNAL parsing to accomodate new “Invalid system name” info and
|
||||||
|
colouration.
|
||||||
|
* Updated RATSIGNAL parsing for new nick announcement (if different than CMDR name)
|
||||||
|
|
||||||
|
## SpanshAttack 7.1
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* `skip [this;current] neutron waypoint` command: Skips the next neutron
|
||||||
|
waypoint. (#94)
|
||||||
|
* Now also announces the actual jump count with the trip time.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# 4.0.2 (2021-02-04)
|
||||||
|
|
||||||
|
## RatAttack 6.0.1
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* RATSIGNAL parsing updated for latest Mecha3 changes.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# 4.0.1 (2021-01-30)
|
# 4.0.1 (2021-01-30)
|
||||||
|
|
||||||
## SpanshAttack 7.0.1
|
## SpanshAttack 7.0.1
|
||||||
|
@ -705,6 +1061,8 @@ a station with data in EDDN >1 year old. Apologies.
|
||||||
* Added new “Navigation” section. This includes the aforementioned new commands
|
* Added new “Navigation” section. This includes the aforementioned new commands
|
||||||
and a bunch of old ones that fit there better than into “Misc”.
|
and a bunch of old ones that fit there better than into “Misc”.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# v1.3 (2020-06-14)
|
# v1.3 (2020-06-14)
|
||||||
|
|
||||||
## EliteDangerous v5.0
|
## EliteDangerous v5.0
|
||||||
|
@ -745,6 +1103,8 @@ bindings before even though it needs them …
|
||||||
* Now updates your location when dropping from SC.
|
* Now updates your location when dropping from SC.
|
||||||
* Fixed some copypasta errors in the documentation.
|
* Fixed some copypasta errors in the documentation.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# v1.2 (2020-03-09)
|
# v1.2 (2020-03-09)
|
||||||
|
|
||||||
## EliteDangerous v4.0
|
## EliteDangerous v4.0
|
||||||
|
@ -775,8 +1135,7 @@ up to date in EDDN.
|
||||||
* Added `open [rat;] dispatch board` command. Opens the web dispatch board in
|
* Added `open [rat;] dispatch board` command. Opens the web dispatch board in
|
||||||
your default browser.
|
your default browser.
|
||||||
* Added proper handling for multiple ratsignals hitting at once. That’s mainly
|
* Added proper handling for multiple ratsignals hitting at once. That’s mainly
|
||||||
an IRC client config thing,
|
an IRC client config thing, [see the docs](docs/configuration/RatAttack.md).
|
||||||
[see the docs](docs/RatAttack.md#getting-case-data-from-irc).
|
|
||||||
* Renamed `RatAttack.getInfoFromRatsignal` to
|
* Renamed `RatAttack.getInfoFromRatsignal` to
|
||||||
`RatAttack.announceCaseFromRatsignal`. Removed the “open case?” voice input
|
`RatAttack.announceCaseFromRatsignal`. Removed the “open case?” voice input
|
||||||
prompt.
|
prompt.
|
||||||
|
@ -811,6 +1170,8 @@ mine ;)
|
||||||
|
|
||||||
[See the docs](docs/StreamAttack.md).
|
[See the docs](docs/StreamAttack.md).
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# v1.1 (2020-01-30)
|
# v1.1 (2020-01-30)
|
||||||
|
|
||||||
The compiled Python scripts are now distributed as two single .exe files. You
|
The compiled Python scripts are now distributed as two single .exe files. You
|
||||||
|
@ -880,6 +1241,8 @@ fixes:
|
||||||
* updated for new controls setup: the HOTAS buttons have changed because my
|
* updated for new controls setup: the HOTAS buttons have changed because my
|
||||||
setup has changed. Probably not really relevant for you.
|
setup has changed. Probably not really relevant for you.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# v1.0 (2019-12-04)
|
# v1.0 (2019-12-04)
|
||||||
|
|
||||||
### single-file profile package
|
### single-file profile package
|
||||||
|
@ -924,6 +1287,8 @@ open a bug if it does.
|
||||||
|
|
||||||
* fixed bug with wonky system names (including e.g. `+` or `[]`)
|
* fixed bug with wonky system names (including e.g. `+` or `[]`)
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# v0.5 (2019-11-09)
|
# v0.5 (2019-11-09)
|
||||||
|
|
||||||
## RatAttack v0.1
|
## RatAttack v0.1
|
||||||
|
@ -957,6 +1322,8 @@ RatAttack is now a thing! :D
|
||||||
when EDSM knows _fewer_ bodies (there are some issues with duplicate entries
|
when EDSM knows _fewer_ bodies (there are some issues with duplicate entries
|
||||||
in EDSM, e.g. in Dromi)
|
in EDSM, e.g. in Dromi)
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# v0.4.1 (2019-10-14)
|
# v0.4.1 (2019-10-14)
|
||||||
|
|
||||||
This is a bug fix release (as the version number indicates). Mainly for changes
|
This is a bug fix release (as the version number indicates). Mainly for changes
|
||||||
|
@ -976,6 +1343,8 @@ yet, so you do not have to download the new archive.
|
||||||
* fixed discovery scan event for new EDDI variable naming
|
* fixed discovery scan event for new EDDI variable naming
|
||||||
* fixed srv lauched event to properly turn off the lights
|
* fixed srv lauched event to properly turn off the lights
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# v0.4 (2019-10-12)
|
# v0.4 (2019-10-12)
|
||||||
|
|
||||||
## SpanshAttack v1.3
|
## SpanshAttack v1.3
|
||||||
|
@ -999,6 +1368,8 @@ yet, so you do not have to download the new archive.
|
||||||
update EDSM) (requires python scripts, see doc)
|
update EDSM) (requires python scripts, see doc)
|
||||||
* added compatibility for SpanshAttack’s clear on shutdown
|
* added compatibility for SpanshAttack’s clear on shutdown
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# v0.3 (2019-09-22)
|
# v0.3 (2019-09-22)
|
||||||
|
|
||||||
## SpanshAttack v1.2
|
## SpanshAttack v1.2
|
||||||
|
@ -1012,6 +1383,8 @@ Should be usable by other people now without too much hassle. If you run into
|
||||||
problems, please hit me up on [Discord](https://discord.gg/mD6dAb) or file an
|
problems, please hit me up on [Discord](https://discord.gg/mD6dAb) or file an
|
||||||
issue here.
|
issue here.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# v0.2 (2019-08-28)
|
# v0.2 (2019-08-28)
|
||||||
|
|
||||||
## SpanshAttack v1.1
|
## SpanshAttack v1.1
|
||||||
|
@ -1030,6 +1403,8 @@ advised for general use, but feel free to dig around and draw inspiration from
|
||||||
it. Soon™ it will be published in a more usable state, but I wanted to get it
|
it. Soon™ it will be published in a more usable state, but I wanted to get it
|
||||||
out there for reference.
|
out there for reference.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
# v0.1 (2019-08-06)
|
# v0.1 (2019-08-06)
|
||||||
|
|
||||||
## SpanshAttack v1.0
|
## SpanshAttack v1.0
|
||||||
|
|
25
Directory.build.props
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<LangVersion>10.0</LangVersion>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<!-- StyleCop Analyzers configuration -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<CodeAnalysisRuleSet>$(SolutionDir)StyleCop.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="StyleCop.Analyzers.Error" Version="1.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="StyleCop.CSharp.Async.Rules" Version="6.1.41">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<AdditionalFiles Include="$(SolutionDir)stylecop.json" Link="stylecop.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
14
README.md
|
@ -1,10 +1,17 @@
|
||||||
# Elite Dangerous VoiceAttack Profiles #
|
# Elite Dangerous VoiceAttack Profiles #
|
||||||
|
|
||||||
These are various profiles for [VoiceAttack](https://voiceattack.com) (VA) I use
|
These are various profiles for [VoiceAttack](https://voiceattack.com) (VA) I use
|
||||||
to enhance my Elite experience. They give me important info, facilitate
|
to enhance my Elite experience. They give me important info, facilitate
|
||||||
day-to-day gaming and do some special things for [Fuel
|
day-to-day gaming and do some special things for [Fuel
|
||||||
Rats](https://fuelrats.com) and [Hull Seals](https://hullseals.space) work.
|
Rats](https://fuelrats.com) and [Hull Seals](https://hullseals.space) work.
|
||||||
|
|
||||||
|
**NOTE**: Further development is on hold and Odyssey compatibility will not be
|
||||||
|
worked on for the time being. See [the corresponding issue on
|
||||||
|
Github](https://github.com/alterNERDtive/VoiceAttack-profiles/issues/113). This
|
||||||
|
might or might not change after the Horizons/Odyssey merge when console release
|
||||||
|
is upon us. Feel free to file issues for anything that is broken on Odyssey and
|
||||||
|
it will be worked on when it is worked on.
|
||||||
|
|
||||||
## Available Profiles ##
|
## Available Profiles ##
|
||||||
|
|
||||||
* EliteAttack: The main Elite VA profile. Anything related to “just” playing the
|
* EliteAttack: The main Elite VA profile. Anything related to “just” playing the
|
||||||
|
@ -15,7 +22,7 @@ Rats](https://fuelrats.com) and [Hull Seals](https://hullseals.space) work.
|
||||||
* StreamAttack: Writes various status things to files that can then be read by
|
* StreamAttack: Writes various status things to files that can then be read by
|
||||||
streaming software like OBS.
|
streaming software like OBS.
|
||||||
|
|
||||||
## Documentation
|
## Documentation & Installation Guide
|
||||||
|
|
||||||
You can find [comprehensive documentation on Github
|
You can find [comprehensive documentation on Github
|
||||||
Pages](https://alternerdtive.github.io/VoiceAttack-profiles).
|
Pages](https://alternerdtive.github.io/VoiceAttack-profiles).
|
||||||
|
@ -30,3 +37,6 @@ issue](https://github.com/alterNERDtive/VoiceAttack-profiles/issues). Thanks! :)
|
||||||
|
|
||||||
You can also [say “Hi” on Discord](https://discord.gg/kXtXm54) if that is your
|
You can also [say “Hi” on Discord](https://discord.gg/kXtXm54) if that is your
|
||||||
thing.
|
thing.
|
||||||
|
|
||||||
|
[![GitHub Sponsors](https://img.shields.io/github/sponsors/alterNERDtive?style=for-the-badge)](https://github.com/sponsors/alterNERDtive)
|
||||||
|
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/S6S1DLYBS)
|
||||||
|
|
2
StyleCop.ruleset
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RuleSet Name="StyleCop.Analyzers rules with default action" Description="StyleCop.Analyzers with default action. Rules with IsEnabledByDefault = false are disabled." ToolsVersion="17.0" />
|
2
VERSION
|
@ -1 +1 @@
|
||||||
4.0.1
|
4.5
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# EliteAttack
|
# EliteAttack
|
||||||
|
|
||||||
This is my personal VoiceAttack profile for Elite: Dangerous. It started out
|
This is my personal VoiceAttack profile for Elite: Dangerous. It started out
|
||||||
ages ago as a modification of [MalicVR’s public
|
ages ago as a modification of [MalicVR’s public
|
||||||
|
@ -35,7 +35,7 @@ the edit window ready to send. They will _not_ hit Enter on their own.
|
||||||
|
|
||||||
## Navigation
|
## Navigation
|
||||||
|
|
||||||
There are so many navigation-focused commands now, they deserve there own
|
There are so many navigation-focused commands now, they deserve their own
|
||||||
category. Basically anything that helps you plot anywhere. A lot of those are
|
category. Basically anything that helps you plot anywhere. A lot of those are
|
||||||
powered by awesome EDDI so I don’t have to do the work myself!
|
powered by awesome EDDI so I don’t have to do the work myself!
|
||||||
|
|
||||||
|
@ -51,6 +51,8 @@ powered by awesome EDDI so I don’t have to do the work myself!
|
||||||
Well, you know the drill by now.
|
Well, you know the drill by now.
|
||||||
* `[find;target] nearest mission system`: Targets the nearest system that has a
|
* `[find;target] nearest mission system`: Targets the nearest system that has a
|
||||||
mission target.
|
mission target.
|
||||||
|
* `how many jumps left`: Announces the jumps left on a neutron trip (requires
|
||||||
|
SpanshAttack) or a course plotted via the galaxy map.
|
||||||
* `plot course;[target;] next [waypoint;way point]`: Plots a course to the text
|
* `plot course;[target;] next [waypoint;way point]`: Plots a course to the text
|
||||||
in your clipboard.
|
in your clipboard.
|
||||||
* `target [bug killer;colonia;dav’s hope;explorer’s anchorage;jackson's lighthouse;jameson’s cobra;robigo;shinrarta dezhra;sagittarius a*;shinrarta;sothis]`:
|
* `target [bug killer;colonia;dav’s hope;explorer’s anchorage;jackson's lighthouse;jameson’s cobra;robigo;shinrarta dezhra;sagittarius a*;shinrarta;sothis]`:
|
||||||
|
@ -70,10 +72,9 @@ Basically anything that is related to directly doing something with your ship.
|
||||||
* `[close;deploy;extend;open;retract;] [cargo scoop;hard points; landing gear] [up;down;]`:
|
* `[close;deploy;extend;open;retract;] [cargo scoop;hard points; landing gear] [up;down;]`:
|
||||||
Overly complicated command to handle everything related to Cargo Scoop, Hard
|
Overly complicated command to handle everything related to Cargo Scoop, Hard
|
||||||
Points, Landing Gear. You get the gist, I guess. Works in SRV too.
|
Points, Landing Gear. You get the gist, I guess. Works in SRV too.
|
||||||
* `[dis;]engage silent running`: Handles silent running.
|
|
||||||
* `[disco;discovery scan]`: Executes a discovery scan. Expects the Discovery
|
* `[disco;discovery scan]`: Executes a discovery scan. Expects the Discovery
|
||||||
Scanner in your first fire group, secondary fire. [You can change
|
Scanner in your first fire group, secondary fire. [You can change
|
||||||
that](/configuration/EliteAttack/#settings).
|
that](configuration/EliteAttack.md#settings).
|
||||||
* `[dis;]engage silent running`: Turns silent running on and off.
|
* `[dis;]engage silent running`: Turns silent running on and off.
|
||||||
* `[head;spot;] lights [on;off]`: Turns your lights on and off. Works in SRV
|
* `[head;spot;] lights [on;off]`: Turns your lights on and off. Works in SRV
|
||||||
too, kinda; turning lights off there relies on the state updating fast enough,
|
too, kinda; turning lights off there relies on the state updating fast enough,
|
||||||
|
@ -94,7 +95,7 @@ Basically anything that is related to directly doing something with your ship.
|
||||||
given “when ready” will wait for mass lock to clear and your FSD to cool down
|
given “when ready” will wait for mass lock to clear and your FSD to cool down
|
||||||
first.
|
first.
|
||||||
|
|
||||||
## SRV controls
|
## SRV Controls
|
||||||
|
|
||||||
Things relevant to your SRV, but not your ship.
|
Things relevant to your SRV, but not your ship.
|
||||||
|
|
||||||
|
@ -105,13 +106,12 @@ Things relevant to your SRV, but not your ship.
|
||||||
|
|
||||||
## Targeting
|
## Targeting
|
||||||
|
|
||||||
Well … targeting stuff, I guess. Not really sure why I made that it’s own
|
Well … targeting stuff, I guess. Not really sure why I made that its own
|
||||||
category, but oh well :)
|
category, but oh well :)
|
||||||
|
|
||||||
* `target the [drive;drives;power plant;frame shift drive;f s d;shield
|
* `target the [drive;drives;power plant;frame shift drive;f s d;shield
|
||||||
generator]`:*
|
generator]`: Targets the given submodule on your current target, or your next
|
||||||
Targets the given submodule on your current target, or your next target if you
|
target if you don’t have one currently. Does not persist between targets.
|
||||||
don’t have one currently. Does not persist between targets.
|
|
||||||
* `clear sub [module;system] target`: Clears the current submodule target.
|
* `clear sub [module;system] target`: Clears the current submodule target.
|
||||||
* `target next system`: Selects the next system on your route.
|
* `target next system`: Selects the next system on your route.
|
||||||
* `target wing man [1;2;3]`: Targets your wingmen.
|
* `target wing man [1;2;3]`: Targets your wingmen.
|
||||||
|
@ -165,6 +165,15 @@ The commands in here do random more or less useful things.
|
||||||
|
|
||||||
## Events
|
## Events
|
||||||
|
|
||||||
|
This is a list of ingame Events, [provided by
|
||||||
|
EDDI](https://github.com/EDCD/EDDI/wiki/VoiceAttack-Integration), that the
|
||||||
|
profile will act on.
|
||||||
|
|
||||||
|
### AFMU Repairs
|
||||||
|
|
||||||
|
Reports on the module that has been repaired, and if it has been fully or
|
||||||
|
partially repaired.
|
||||||
|
|
||||||
### Body Mapped
|
### Body Mapped
|
||||||
|
|
||||||
Announces an estimate for high-value bodies’ payouts and the remaining mapping
|
Announces an estimate for high-value bodies’ payouts and the remaining mapping
|
||||||
|
@ -219,8 +228,8 @@ scripts).
|
||||||
|
|
||||||
### Docked
|
### Docked
|
||||||
|
|
||||||
Automatically refuels, repairs, optionally rearms, then gets your ship into the
|
Automatically refuels, repairs, rearms, then gets your ship into the hangar and
|
||||||
hangar and opens station services.
|
opens station services. Can be individually disabled.
|
||||||
|
|
||||||
### Docking Denied
|
### Docking Denied
|
||||||
|
|
||||||
|
@ -261,12 +270,16 @@ the (rough) range you still have on the fumes left in your tank.
|
||||||
|
|
||||||
### Material Threshold
|
### Material Threshold
|
||||||
|
|
||||||
Warns you when a monitored material falls below it’s minimum stock level and
|
Warns you when a monitored material falls below its minimum stock level and
|
||||||
tells you when you reach your desired level or fill up.
|
tells you when you reach your desired level or fill up.
|
||||||
|
|
||||||
You will have to set minimum and desired amounts in EDDI’s material monitor
|
You will have to set minimum and desired amounts in EDDI’s material monitor
|
||||||
options first for all materials you wish to be monitored.
|
options first for all materials you wish to be monitored.
|
||||||
|
|
||||||
|
### Next Jump
|
||||||
|
|
||||||
|
Gives you a jump count upon plotting a route using the galaxy map.
|
||||||
|
|
||||||
### Ship FSD
|
### Ship FSD
|
||||||
|
|
||||||
This event actually is several different events in one. Currently the following
|
This event actually is several different events in one. Currently the following
|
||||||
|
@ -276,7 +289,7 @@ are handled:
|
||||||
* Cooldown complete: Announces FSD cooldown if you are currently in normal
|
* Cooldown complete: Announces FSD cooldown if you are currently in normal
|
||||||
space.
|
space.
|
||||||
|
|
||||||
### Ship interdicted
|
### Ship Interdicted
|
||||||
|
|
||||||
Tells you when you have been interdicted by a player. Is also supposed to target
|
Tells you when you have been interdicted by a player. Is also supposed to target
|
||||||
the interdictor automatically, but randomly sometimes just doesn’t work. Yay!
|
the interdictor automatically, but randomly sometimes just doesn’t work. Yay!
|
||||||
|
@ -287,11 +300,15 @@ Toggles SRV lights off after launching. Might not work if you drop particularly
|
||||||
far after deployment because it works off a timer. Conversely might take a
|
far after deployment because it works off a timer. Conversely might take a
|
||||||
second to turn your lights off on a short drop and/or in high gravity.
|
second to turn your lights off on a short drop and/or in high gravity.
|
||||||
|
|
||||||
|
### Synthesis
|
||||||
|
|
||||||
|
Reports on the synthesis type and quality.
|
||||||
|
|
||||||
### System Scan Complete
|
### System Scan Complete
|
||||||
|
|
||||||
Lists you all bodies EDDI considers worth mapping in the current system.
|
Lists all bodies EDDI considers worth mapping in the current system.
|
||||||
|
|
||||||
### Undocked
|
### Undocked
|
||||||
|
|
||||||
Retracts landing gear for you. Seriously, is there any occasion in which you
|
Retracts landing gear for you. Seriously, is there any occasion in which you
|
||||||
_don’t_ immediately want to retract it after takeoff?
|
_don’t_ immediately want to retract it after takeoff?
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RatAttack
|
# RatAttack
|
||||||
|
|
||||||
This profile facilitates [Fuel Ratting](https://www.fuelrats.com). It aims to
|
This profile facilitates [Fuel Ratting](https://www.fuelrats.com). It aims to
|
||||||
eliminate as much of the required manual task and attention switching as
|
eliminate as much of the required manual task and attention switching as
|
||||||
|
@ -16,10 +16,11 @@ through IRC. When off duty, it won’t.
|
||||||
|
|
||||||
## Case Handling
|
## Case Handling
|
||||||
|
|
||||||
If you have your IRC client setup properly, VoiceAttack will hold a list with
|
[If you have your IRC client setup
|
||||||
all rat cases that have come in while you had it running. It will save the case
|
properly](../configuration/RatAttack/#getting-case-data-from-irc), VoiceAttack
|
||||||
number, CMDR name, system, O₂ status and platform. There are several commands
|
will hold a list with all rat cases that have come in while you had it running.
|
||||||
you can run on this list, giving it a case number:
|
It will save the case number, CMDR name, system, O₂ status and platform. There
|
||||||
|
are several commands you can run on this list, giving it a case number:
|
||||||
|
|
||||||
### Getting Case Information
|
### Getting Case Information
|
||||||
|
|
||||||
|
@ -30,6 +31,8 @@ you can run on this list, giving it a case number:
|
||||||
location to the currently opened rat case.
|
location to the currently opened rat case.
|
||||||
* `distance to rat case number [0..30]`: Will give you the distance from your
|
* `distance to rat case number [0..30]`: Will give you the distance from your
|
||||||
current system to a case’s system.
|
current system to a case’s system.
|
||||||
|
* `latest rat case details`: Will give you the case data for the latest incoming
|
||||||
|
case.
|
||||||
* `nearest commander to rat case number [0..30]`: Will give you the nearest of
|
* `nearest commander to rat case number [0..30]`: Will give you the nearest of
|
||||||
your CMDRs with their distance to a case’s system. [Requires some
|
your CMDRs with their distance to a case’s system. [Requires some
|
||||||
setup](../configuration/RatAttack/#announcing-your-nearest-cmdr).
|
setup](../configuration/RatAttack/#announcing-your-nearest-cmdr).
|
||||||
|
@ -47,6 +50,9 @@ you can run on this list, giving it a case number:
|
||||||
announcements to
|
announcements to
|
||||||
VoiceAttack](../configuration/RatAttack/#getting-case-data-from-irc).
|
VoiceAttack](../configuration/RatAttack/#getting-case-data-from-irc).
|
||||||
|
|
||||||
|
Opening a case will automatically copy the client’s system to the clipboard for
|
||||||
|
easy route plotting. This can be disabled.
|
||||||
|
|
||||||
### Making Calls ###
|
### Making Calls ###
|
||||||
|
|
||||||
There are a bunch of calls you can make for a case, the most common are modelled
|
There are a bunch of calls you can make for a case, the most common are modelled
|
||||||
|
@ -55,10 +61,12 @@ will be shortened to the usual IRC short hands (e.g. “sysconf”). If you need
|
||||||
something more unusual you can either still manually type it into your IRC
|
something more unusual you can either still manually type it into your IRC
|
||||||
client or use the “General IRC Integration”, see below.
|
client or use the “General IRC Integration”, see below.
|
||||||
|
|
||||||
* `call [1..20] jumps [and login;and takeoff;left;]`: Calls jump for the
|
* `call [1..20] jumps [and login;and takeoff;left;]`: Calls jumps for the
|
||||||
currently open case. You can optionally include that you will still have to
|
currently open case. You can optionally include that you will still have to
|
||||||
login to the game or have to take off from your current
|
login to the game or have to take off from your current
|
||||||
station/port/outpost/planet.
|
station/port/outpost/planet.
|
||||||
|
* `call jumps [left;]`: Calls jumps for the currently open case based on a
|
||||||
|
neutron trip (requires SpanshAttack) or a plotted ingame route.
|
||||||
* `call friend [positive;negative] [in pg;in private group;in solo;in main menu;sysconf;system confirmed;]`:
|
* `call friend [positive;negative] [in pg;in private group;in solo;in main menu;sysconf;system confirmed;]`:
|
||||||
Friend request confirmations, with all the
|
Friend request confirmations, with all the
|
||||||
things you might want to / should call with it.
|
things you might want to / should call with it.
|
||||||
|
@ -73,6 +81,9 @@ client or use the “General IRC Integration”, see below.
|
||||||
calls, and make sure you will never have to call “client destroyed”, would
|
calls, and make sure you will never have to call “client destroyed”, would
|
||||||
you?
|
you?
|
||||||
|
|
||||||
|
By default, VoiceAttack will ask for confirmation before sending calls to the
|
||||||
|
`#fuelrats` channel.
|
||||||
|
|
||||||
### Closing a Case
|
### Closing a Case
|
||||||
|
|
||||||
* `[close;clear] rat case`: Closes the currently open rat case.
|
* `[close;clear] rat case`: Closes the currently open rat case.
|
||||||
|
@ -96,4 +107,4 @@ client or in SC in some remote system out in the black on a long range rescue).
|
||||||
\#ratchat.
|
\#ratchat.
|
||||||
|
|
||||||
Make sure [that your IRC client is setup
|
Make sure [that your IRC client is setup
|
||||||
properly](../configuration/RatAttack/#sending-text-to-fuelrats-irc).
|
properly](../configuration/RatAttack/#sending-text-to-fuelrats-irc).
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
# SpanshAttack
|
# SpanshAttack
|
||||||
|
|
||||||
This profile uses the
|
This profile uses the
|
||||||
[ED-NeutronRouter](https://github.com/sc-pulgan/ED-NeutronRouter) plugin to plot
|
[ED-NeutronRouter](https://github.com/sc-pulgan/ED-NeutronRouter) plugin to
|
||||||
neutron jumps using [spansh](https://spansh.co.uk/plotter). It fully does
|
plot neutron jumps using [Spansh](https://spansh.co.uk/plotter). It does
|
||||||
everything you need from within the game and VoiceAttack, you won’t have to
|
everything you need fully from within the game and VoiceAttack, you won’t have
|
||||||
visit the site at any point.
|
to visit the site at any point.
|
||||||
|
|
||||||
## Plotting a Route
|
## Plotting a Route
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ visit the site at any point.
|
||||||
### Plotting to a System Unknown to the Neutron Router
|
### Plotting to a System Unknown to the Neutron Router
|
||||||
|
|
||||||
The router can only plot a route to a system that is in its database (obviously
|
The router can only plot a route to a system that is in its database (obviously
|
||||||
can also only give you way points that are). If your target system is not, there
|
can also only give you waypoints that are). If your target system is not, there
|
||||||
are several levels of fallback handling to find a system that is.
|
are several levels of fallback handling to find a system that is.
|
||||||
|
|
||||||
1. Check `Next system` coordinates provided by EDDI. If the system is in EDSM,
|
1. Check `Next system` coordinates provided by EDDI. If the system is in EDSM,
|
||||||
|
@ -55,6 +55,16 @@ Additionally, you can use the `SpanshAttack.copyNextNeutronWaypoint`
|
||||||
/ `[get;copy] next neutron [waypoint;way point]` command to copy the next
|
/ `[get;copy] next neutron [waypoint;way point]` command to copy the next
|
||||||
neutron waypoint to the clipboard.
|
neutron waypoint to the clipboard.
|
||||||
|
|
||||||
|
### Skipping a Waypoint
|
||||||
|
|
||||||
|
Sometimes, especially in very neutron-sparse areas of the galaxy, the plotter
|
||||||
|
will give you weird jumps. E.g. I recently got neutron → 37 ly → neutron → 440
|
||||||
|
ly.
|
||||||
|
|
||||||
|
In these cases you can use the `SpanshAttack.skipNeutronWaypoint` / `skip
|
||||||
|
[this;current] neutron waypoint` command to move on to the next one in the
|
||||||
|
list.
|
||||||
|
|
||||||
### Manual Re-Plot
|
### Manual Re-Plot
|
||||||
|
|
||||||
Trigger the `SpanshAttack.replotRoute` command either by voice
|
Trigger the `SpanshAttack.replotRoute` command either by voice
|
||||||
|
@ -92,4 +102,4 @@ neutron waypoint_.
|
||||||
SpanshAttack keeps track of your start time, even if you have the option to time
|
SpanshAttack keeps track of your start time, even if you have the option to time
|
||||||
your trip turned off. This way you can get the time you’ve been jumping with the
|
your trip turned off. This way you can get the time you’ve been jumping with the
|
||||||
`SpanshAttack.announceTripTime` or
|
`SpanshAttack.announceTripTime` or
|
||||||
`how long have i been [jumping;on this trip;on this neutron trip]?` commands.
|
`how long have i been [jumping;on this trip;on this neutron trip]?` commands.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# StreamAttack
|
# StreamAttack
|
||||||
|
|
||||||
This profile uses the [EDDI](https://github.com/EDCD/EDDI) plugin to write
|
This profile uses the [EDDI](https://github.com/EDCD/EDDI) plugin to write
|
||||||
a bunch of information about your commander, your current location and your ship
|
a bunch of information about your commander, your current location and your ship
|
||||||
|
@ -23,6 +23,10 @@ Default folder is `%appdata%\StreamAttack\`.
|
||||||
|
|
||||||
### Elite
|
### Elite
|
||||||
|
|
||||||
|
Please do note that information in the output files is only updated when a
|
||||||
|
journal event that contains the information is detected. E.g. the distance to
|
||||||
|
your jump target is not constantly calculated, but only updated after a jump.
|
||||||
|
|
||||||
#### Commander
|
#### Commander
|
||||||
|
|
||||||
* `Elite\cmdr\name`: The current commander’s name.
|
* `Elite\cmdr\name`: The current commander’s name.
|
||||||
|
@ -45,4 +49,4 @@ Default folder is `%appdata%\StreamAttack\`.
|
||||||
* `Elite\ship\build`: Your current ship’s loadout (link to coriolis).
|
* `Elite\ship\build`: Your current ship’s loadout (link to coriolis).
|
||||||
* `Elite\ship\full`: `“<name>” | <model> | <build>`.
|
* `Elite\ship\full`: `“<name>” | <model> | <build>`.
|
||||||
* `Elite\ship\model`: Your current ship’s model.
|
* `Elite\ship\model`: Your current ship’s model.
|
||||||
* `Elite\ship\name`: Your current ship’s name.
|
* `Elite\ship\name`: Your current ship’s name.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# EliteAttack
|
# EliteAttack
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
|
@ -8,8 +8,20 @@ Toggles:
|
||||||
without constraints. Default: false.
|
without constraints. Default: false.
|
||||||
* `auto honk new systems`: Automatically honk upon entering a system if it is
|
* `auto honk new systems`: Automatically honk upon entering a system if it is
|
||||||
your first visit. Default: true.
|
your first visit. Default: true.
|
||||||
* `auto restock`: Automatically restock after docking at a station. You will
|
* `auto refuel`: Automatically refuel after docking at a station. Default:
|
||||||
always refuel, repair and enter the Station Services menu. Default: true.
|
true.
|
||||||
|
* `auto repair`: Automatically repair after docking at a station. Default:
|
||||||
|
true.
|
||||||
|
* `auto restock`: Automatically restock after docking at a station. Default:
|
||||||
|
true.
|
||||||
|
* `auto move to hangar`: Automatically move the ship to the hangar after docking
|
||||||
|
at a station. Default: true.
|
||||||
|
* `auto enter station services`: Automatically enter the Station Services menu
|
||||||
|
after docking at a station. Default: true.
|
||||||
|
* `auto retract landing gear`: Automatically retract landing gear when lifting
|
||||||
|
off a planet / undocking from a station. Default: true. (#133)
|
||||||
|
* `auto disable s r v lights`: Automatically turn SRV lights off when deploying
|
||||||
|
one. Default: true. (#133)
|
||||||
* `edsm system status`: Pull system data from EDSM and compare it
|
* `edsm system status`: Pull system data from EDSM and compare it
|
||||||
against your discovery scan. Default: true.
|
against your discovery scan. Default: true.
|
||||||
* `discovery scan on primary fire`: Use primary fire for honking instead of
|
* `discovery scan on primary fire`: Use primary fire for honking instead of
|
||||||
|
@ -18,17 +30,24 @@ Toggles:
|
||||||
that, it’s great. Default: false.
|
that, it’s great. Default: false.
|
||||||
* `hyper space dethrottle`: Throttle down after a jump and when dropping from
|
* `hyper space dethrottle`: Throttle down after a jump and when dropping from
|
||||||
SC. Like the SC Assist module does. Default: true.
|
SC. Like the SC Assist module does. Default: true.
|
||||||
|
* `limpet check`: Do a limpet check when undocking, reminding you if you forgot
|
||||||
|
to buy some. Default: true.
|
||||||
* `mapping candidates`: Announce bodies worth mapping when you have finished
|
* `mapping candidates`: Announce bodies worth mapping when you have finished
|
||||||
scanning a system. (Terraformables, Water Worlds, Earth-Like Worlds and
|
scanning a system. (Terraformables, Water Worlds, Earth-Like Worlds and
|
||||||
Ammonia Worlds that have not been mapped yet.) Default: true.
|
Ammonia Worlds that have not been mapped yet.) Default: true.
|
||||||
* `outdated stations`: Announce stations with outdated data in the online
|
* `outdated stations`: Announce stations with outdated data in the online
|
||||||
databases. Default: true.
|
databases. Default: true.
|
||||||
|
* `include outdated settlements` option: Include Odyssey settlements in the
|
||||||
|
outdated stations list. Default: true.
|
||||||
|
* `repair reports`: Report on AFMU repairs. Default: true.
|
||||||
* `road to riches`: Announce bodies worth scanning if you are looking for some
|
* `road to riches`: Announce bodies worth scanning if you are looking for some
|
||||||
starting cash on the Road to Riches. Default: false.
|
starting cash on the Road to Riches. Default: false.
|
||||||
|
* `route jump count`: Give a jump count on plotting a route. Default: true.
|
||||||
|
* `synthesis reports`: Report on synthesis. Default: true.
|
||||||
|
|
||||||
Other settings:
|
Other settings:
|
||||||
|
|
||||||
* `outdated station threshold`: The threshold for station data to count as
|
* `outdated station threshold`: The threshold for station data to count as
|
||||||
“outdated”, in days. Default: 365.
|
“outdated”, in days. Default: 365.
|
||||||
* `scanner fire group`: The fire group your discovery scanner is assigned to.
|
* `scanner fire group`: The fire group your discovery scanner is assigned to.
|
||||||
Default: 0 (the first one).
|
Default: 0 (the first one).
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RatAttack
|
# RatAttack
|
||||||
|
|
||||||
## Getting Case Data From IRC
|
## Getting Case Data From IRC
|
||||||
|
|
||||||
|
@ -8,6 +8,10 @@ and an optional boolean as second argument that triggers a TTS case
|
||||||
announcement. You can find it under your VoiceAttack “Apps” folder,
|
announcement. You can find it under your VoiceAttack “Apps” folder,
|
||||||
`\alterNERDtive\RatAttack-cli.exe`.
|
`\alterNERDtive\RatAttack-cli.exe`.
|
||||||
|
|
||||||
|
**Note**: If you are running VoiceAttack as admin, you need to run your IRC
|
||||||
|
client as admin, too! Otherwise they cannot communicate. In general you want to
|
||||||
|
run both with normal privileges.
|
||||||
|
|
||||||
This has two purposes:
|
This has two purposes:
|
||||||
|
|
||||||
1. Announcing a new incoming case (if passing `true` as second argument).
|
1. Announcing a new incoming case (if passing `true` as second argument).
|
||||||
|
@ -17,7 +21,7 @@ This has two purposes:
|
||||||
For my AdiIRC, it looks like this (obviously change the path, please):
|
For my AdiIRC, it looks like this (obviously change the path, please):
|
||||||
|
|
||||||
```adiirc
|
```adiirc
|
||||||
on *:TEXT:RATSIGNAL - CMDR*(??_SIGNAL):#fuelrats:{
|
on *:TEXT:*RATSIGNAL*(??_SIGNAL):#fuelrats:{
|
||||||
if ( $away ) {
|
if ( $away ) {
|
||||||
/run -h "X:\path\to\VoiceAttack\Apps\alterNERDtive\RatAttack-cli.exe" " $+ $replace($1-,","") $+ " false
|
/run -h "X:\path\to\VoiceAttack\Apps\alterNERDtive\RatAttack-cli.exe" " $+ $replace($1-,","") $+ " false
|
||||||
}
|
}
|
||||||
|
@ -37,7 +41,15 @@ command invocation.
|
||||||
You get the gist; if not and you don’t know how to do the same thing for your
|
You get the gist; if not and you don’t know how to do the same thing for your
|
||||||
IRC client, either switch to AdiIRC or bribe me to make an example for yours.
|
IRC client, either switch to AdiIRC or bribe me to make an example for yours.
|
||||||
|
|
||||||
Note: If you are not on duty (see below) you will _not_ get case announcements.
|
mIRC is a straight forward copy & paste job from Adi to mIRC (“Tools” → “Script
|
||||||
|
Editor” → “Remote”). Make sure you do not strip colour codes from incoming
|
||||||
|
messages!
|
||||||
|
|
||||||
|
Note for Hexchat users: Hexchat doesn’t seem to have a simple way of doing this.
|
||||||
|
If you figure it out, I’ll gladly add instructions here.
|
||||||
|
|
||||||
|
Keep in mind that if you are not on duty (see below) you will _not_ get case
|
||||||
|
announcements.
|
||||||
|
|
||||||
## Announcing Your Nearest CMDR
|
## Announcing Your Nearest CMDR
|
||||||
|
|
||||||
|
@ -57,7 +69,7 @@ You can use this for a single CMDR, too. A less convoluted setup for announcing
|
||||||
the distance to your location in that case is on the list™ but does not have an
|
the distance to your location in that case is on the list™ but does not have an
|
||||||
ETA yet.
|
ETA yet.
|
||||||
|
|
||||||
Currently there is no way to specify a platform for each CMDR.
|
Currently there is no way to specify a platform for each CMDR separately.
|
||||||
|
|
||||||
## Sending Text to FuelRats IRC
|
## Sending Text to FuelRats IRC
|
||||||
|
|
||||||
|
@ -76,6 +88,8 @@ Toggles:
|
||||||
|
|
||||||
* `auto close fuel rat case`: Automatically close a rat case when sending
|
* `auto close fuel rat case`: Automatically close a rat case when sending
|
||||||
“fuel+” via voice command or ingame chat. Default: false.
|
“fuel+” via voice command or ingame chat. Default: false.
|
||||||
|
* `auto copy rat case system` : Automatically copy the client’s system to the
|
||||||
|
clipboard when you open a rat case. Default: true.
|
||||||
* `fuel rat call confirmation`: Only make calls in #fuelrats after vocal
|
* `fuel rat call confirmation`: Only make calls in #fuelrats after vocal
|
||||||
confirmation to prevent mistakes. Default: true.
|
confirmation to prevent mistakes. Default: true.
|
||||||
* `fuel rat duty`: On duty, receiving case announcements via TTS. Default: true.
|
* `fuel rat duty`: On duty, receiving case announcements via TTS. Default: true.
|
||||||
|
@ -83,10 +97,12 @@ Toggles:
|
||||||
incoming rat cases. Default: false.
|
incoming rat cases. Default: false.
|
||||||
* `platform for fuel rat case`: Announce the platform for incoming rat cases.
|
* `platform for fuel rat case`: Announce the platform for incoming rat cases.
|
||||||
Default: false.
|
Default: false.
|
||||||
|
* `system information for fuel rat case`: System information provided by Mecha.
|
||||||
|
Default: true.
|
||||||
|
|
||||||
Other Settings:
|
Other Settings:
|
||||||
|
|
||||||
* `fuel rat commanders`: All your CMDRs that are ready to take rat cases. Use
|
* `fuel rat commanders`: All your CMDRs that are ready to take rat cases. Use
|
||||||
‘;’ as separator, e.g. “Bud Spencer;Terrence Hill”. Default: "".
|
‘;’ as separator, e.g. “Bud Spencer;Terrence Hill”. Default: "".
|
||||||
* `fuel rat platforms`: The platform(s) you want to get case announcements for
|
* `fuel rat platforms`: The platform(s) you want to get case announcements for
|
||||||
(PC, Xbox, Playstation). Use ‘;’ as separator, e.g. “PC;Xbox”. Default: "PC".
|
(PC, Xbox, Playstation). Use ‘;’ as separator, e.g. “PC;Xbox”. Default: "PC".
|
||||||
|
|
|
@ -13,7 +13,7 @@ For any ships that you regularly use for neutron jumping, e.g. long range Fuel
|
||||||
Rat ships, I recommend telling SpanshAttack about the range they are supposed to
|
Rat ships, I recommend telling SpanshAttack about the range they are supposed to
|
||||||
have with full fuel and your preferred amount of cargo/limpets.
|
have with full fuel and your preferred amount of cargo/limpets.
|
||||||
|
|
||||||
In oder to do that, copy the `SpanshAttack.getShipRange` command from
|
In order to do that, copy the `SpanshAttack.getShipRange` command from
|
||||||
SpanshAttack or the example profile to your custom profile and add your ships.
|
SpanshAttack or the example profile to your custom profile and add your ships.
|
||||||
Any ship listed in there will automatically have its jump range used instead of
|
Any ship listed in there will automatically have its jump range used instead of
|
||||||
EDDI’s reported laden range or VoiceAttack prompting you to manually supply it.
|
EDDI’s reported laden range or VoiceAttack prompting you to manually supply it.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# General Configuration
|
# General Configuration
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
|
@ -7,12 +7,15 @@ configuration is stored in a bunch of VoiceAttack variables which in turn are
|
||||||
stored in your custom profile. You could even have different custom profiles
|
stored in your custom profile. You could even have different custom profiles
|
||||||
with their own distinct settings.
|
with their own distinct settings.
|
||||||
|
|
||||||
You change the configuration via voice commands:
|
The easiest way to change settings is to say `customize settings`. That will
|
||||||
|
bring up a rudimentary settings UI.
|
||||||
|
|
||||||
|
You change also change the configuration directly via voice commands:
|
||||||
|
|
||||||
* For toggles (booleans): `customize setting [enable;disable] <trigger phrase>`
|
* For toggles (booleans): `customize setting [enable;disable] <trigger phrase>`
|
||||||
* For everything else: `customize setting set <trigger phrase>`
|
* For everything else: `customize setting set <trigger phrase>`
|
||||||
|
|
||||||
You can find a list of trigger phrases here, or you can say
|
You can find a list of trigger phrases on this page, or you can say
|
||||||
`customize setting list [options;settings]` for a list of voice triggers and
|
`customize setting list [options;settings]` for a list of voice triggers and
|
||||||
what they do. If you don’t remember your settings or just want a nice list,
|
what they do. If you don’t remember your settings or just want a nice list,
|
||||||
`customize setting report [options;settings]` will print that to the
|
`customize setting report [options;settings]` will print that to the
|
||||||
|
@ -22,9 +25,9 @@ VoiceAttack log. If you want to reset everything back to default state, say
|
||||||
The “customize setting” prefix is kind of a leftover from times long gone and
|
The “customize setting” prefix is kind of a leftover from times long gone and
|
||||||
does not quite fit anymore. Might change in a future version.
|
does not quite fit anymore. Might change in a future version.
|
||||||
|
|
||||||
Since the settings are saved to your custom profile they will not be preserved
|
Since the settings are saved to your custom profile they will not necessarily be
|
||||||
when you switch profiles. Once you switch back, the correct settings for the
|
preserved when you switch profiles. Once you switch back, the correct settings
|
||||||
profile are re-loaded.
|
for the profile are re-loaded.
|
||||||
|
|
||||||
### General Settings for All Profiles
|
### General Settings for All Profiles
|
||||||
|
|
||||||
|
@ -48,9 +51,10 @@ Other settings:
|
||||||
## Note on Non-Standard Keyboard Layouts
|
## Note on Non-Standard Keyboard Layouts
|
||||||
|
|
||||||
Because Elite’s keyboard handling is … weird you’ll have to set the key to use
|
Because Elite’s keyboard handling is … weird you’ll have to set the key to use
|
||||||
for pasting text into Elite:Dangerous if you are not using a “standard”QWERT[YZ]
|
for pasting text into Elite Dangerous if you are not using a keyboard layout
|
||||||
layout. You will have to change it to the key that is physically in the place
|
that the game supports by default. You will have to change it to the key that
|
||||||
where `V` would be on QWERTY, e.g. `P` for [Neo2](https://neo-layout.org).
|
is physically in the place where `V` would be on QWERTY, e.g. `P` for
|
||||||
|
[Neo2](https://neo-layout.org).
|
||||||
|
|
||||||
To set the key, say “customize setting set elite paste key”.
|
To set the key, say “customize setting set elite paste key”.
|
||||||
|
|
||||||
|
@ -70,4 +74,4 @@ appropriate handlers in my profiles are called, too. That is done by invoking
|
||||||
the `eddi.Event` plugin context of the `alterNERDtive-base` plugin. Otherwise
|
the `eddi.Event` plugin context of the `alterNERDtive-base` plugin. Otherwise
|
||||||
stuff _will_ break.
|
stuff _will_ break.
|
||||||
|
|
||||||
![[EDDI-event.png]]
|
![[EDDI-event.png]]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
The base profile provides voice commands for changing the profiles settings.
|
The base profile provides voice commands for changing the profiles’ settings.
|
||||||
See [the configuration section](../configuration/general#settings).
|
See [the configuration section](../configuration/general#settings).
|
||||||
|
|
||||||
## Chat
|
## Chat
|
||||||
|
@ -10,7 +10,7 @@ See [the configuration section](../configuration/general#settings).
|
||||||
* `paste text`: Pastes the contents of your current clipboard. Note that this
|
* `paste text`: Pastes the contents of your current clipboard. Note that this
|
||||||
command is supposed to be used for pasting _into Elite_ and hence uses the
|
command is supposed to be used for pasting _into Elite_ and hence uses the
|
||||||
configured paste key. If you’re using a non-standard layout that means that
|
configured paste key. If you’re using a non-standard layout that means that
|
||||||
you can _not_ use this command to paste text into other applications.
|
you _cannot_ use this command to paste text into other applications.
|
||||||
|
|
||||||
## Updating
|
## Updating
|
||||||
|
|
||||||
|
@ -31,10 +31,11 @@ See [the configuration section](../configuration/general#settings).
|
||||||
and places it on your Desktop. Note that this currently uses bindED’s built-in
|
and places it on your Desktop. Note that this currently uses bindED’s built-in
|
||||||
report which will output _any_ bind that does not have a keyboard key set,
|
report which will output _any_ bind that does not have a keyboard key set,
|
||||||
including axis binds and binds that are not actually used by the profiles.
|
including axis binds and binds that are not actually used by the profiles.
|
||||||
|
* `open documentation`: Opens the documentation in your default browser.
|
||||||
* `open EDDI options;configure EDDI`: Displays EDDI’s configuration window.
|
* `open EDDI options;configure EDDI`: Displays EDDI’s configuration window.
|
||||||
* `open elite bindings folder`: Opens Elite’s bindings folder
|
* `open elite bindings folder`: Opens Elite’s bindings folder
|
||||||
(`%localappdata%\Frontier Developments\Elite Dangerous\Options\Bindings`)
|
(`%localappdata%\Frontier Developments\Elite Dangerous\Options\Bindings`)
|
||||||
* `reload elite key binds`: Forces a reload of your Elite binds. Should not be
|
* `reload elite key binds`: Forces a reload of your Elite binds. Should not be
|
||||||
necessary.
|
necessary.
|
||||||
* `shut up EDDI`: Immediately interrupts any current and pending speech on
|
* `shut up EDDI`: Immediately interrupts any current and pending speech on
|
||||||
EDDI’s end.
|
EDDI’s end.
|
||||||
|
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 40 KiB |
BIN
docs/images/Elite-COVAS.png
Normal file
After Width: | Height: | Size: 184 KiB |
BIN
docs/images/Elite-binds-galmap.png
Normal file
After Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 134 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 30 KiB |
|
@ -1,10 +1,17 @@
|
||||||
# Elite Dangerous VoiceAttack Profiles
|
# Elite Dangerous VoiceAttack Profiles
|
||||||
|
|
||||||
These are various profiles for [VoiceAttack](https://voiceattack.com) (VA) I use
|
These are various profiles for [VoiceAttack](https://voiceattack.com) (VA) I use
|
||||||
to enhance my Elite experience. They give me important info, facilitate
|
to enhance my Elite experience. They give me important info, facilitate
|
||||||
day-to-day gaming and do some special things for [Fuel
|
day-to-day gaming and do some special things for [Fuel
|
||||||
Rats](https://fuelrats.com) and [Hull Seals](https://hullseals.space) work.
|
Rats](https://fuelrats.com) and [Hull Seals](https://hullseals.space) work.
|
||||||
|
|
||||||
|
**NOTE**: Further development is on hold and Odyssey compatibility will not be
|
||||||
|
worked on for the time being. See [the corresponding issue on
|
||||||
|
Github](https://github.com/alterNERDtive/VoiceAttack-profiles/issues/113). This
|
||||||
|
might or might not change after the Horizons/Odyssey merge. Feel free to file
|
||||||
|
issues for anything that is broken on Odyssey and it will be worked on when it
|
||||||
|
is worked on.
|
||||||
|
|
||||||
## Available Profiles
|
## Available Profiles
|
||||||
|
|
||||||
* [EliteAttack](EliteAttack): The main Elite VA profile. Anything related to
|
* [EliteAttack](EliteAttack): The main Elite VA profile. Anything related to
|
||||||
|
@ -24,10 +31,13 @@ Well, you are in the right place. You can find comprehensive documentation right
|
||||||
here.
|
here.
|
||||||
|
|
||||||
If you run into any errors, please make sure you are running the latest version
|
If you run into any errors, please make sure you are running the latest version
|
||||||
of the profiles and all requirements.
|
of the profiles and all [requirements](requirements.md).
|
||||||
|
|
||||||
If your problem persists, please [file an
|
If your problem persists, please [file an
|
||||||
issue](https://github.com/alterNERDtive/VoiceAttack-profiles/issues). Thanks! :)
|
issue](https://github.com/alterNERDtive/VoiceAttack-profiles/issues). Thanks! :)
|
||||||
|
|
||||||
You can also [say “Hi” on Discord](https://discord.gg/kXtXm54) if that is your
|
You can also [say “Hi” on Discord](https://discord.gg/kXtXm54) if that is your
|
||||||
thing.
|
thing.
|
||||||
|
|
||||||
|
[![GitHub Sponsors](https://img.shields.io/github/sponsors/alterNERDtive?style=for-the-badge)](https://github.com/sponsors/alterNERDtive)
|
||||||
|
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/S6S1DLYBS)
|
||||||
|
|
|
@ -4,44 +4,48 @@
|
||||||
|
|
||||||
Grab the [most recent VoiceAttack beta
|
Grab the [most recent VoiceAttack beta
|
||||||
version](https://voiceattack.com/#download-1) off the official site and install
|
version](https://voiceattack.com/#download-1) off the official site and install
|
||||||
it. Right now 32bit vs. 64bit does not make any difference, but there is no
|
it.
|
||||||
reason not to choose 64bit unless you are running a 32bit version of Windows (is
|
|
||||||
that even still a thing?).
|
|
||||||
|
|
||||||
If you are using the standalone version you should probably download the
|
If you are using the standalone version you should probably download the
|
||||||
executable installer. If you are using the Steam version of VoiceAttack, you
|
executable installer.
|
||||||
will have to download the zipped folder and replace your installed version with
|
|
||||||
its contents.
|
|
||||||
|
|
||||||
![[VoiceAttack-download.png]]
|
![[VoiceAttack-download.png]]
|
||||||
|
|
||||||
|
If you are using the Steam version of VoiceAttack, you will have to download the
|
||||||
|
zipped folder and replace your installed version with its contents.
|
||||||
|
|
||||||
[Here is the first hit on a Google search for finding the installation
|
[Here is the first hit on a Google search for finding the installation
|
||||||
folder](https://steamcommunity.com/sharedfiles/filedetails/?id=760447682). It is
|
folder](https://steamcommunity.com/sharedfiles/filedetails/?id=760447682). It is
|
||||||
for a completely unrelated game, but the steps are the same.
|
for a completely unrelated game, but the steps are the same.
|
||||||
|
|
||||||
You can potentially also install the latest non-beta version; but I often use
|
You can potentially also install the latest non-beta version; but I often use
|
||||||
features that have only just been added to the beta, so some things might break
|
features that have only just been added to the beta, so some things might break
|
||||||
for you if you are not using that.
|
for you if you are not using that. There might not be a beta version at the time
|
||||||
|
you’re reading this, just get the full release then.
|
||||||
|
|
||||||
|
### Enable Plugin Support
|
||||||
|
|
||||||
Make sure you have plugin support enabled:
|
Make sure you have plugin support enabled:
|
||||||
|
|
||||||
1. Go to VoiceAttack settings. ![[VoiceAttack-settings.png]]
|
1. Go to VoiceAttack settings. ![[VoiceAttack-settings.png]]
|
||||||
1. Check “enable plugin support”. ![[VoiceAttack-settings-plugin-support.png]]
|
1. Check “enable plugin support”. ![[VoiceAttack-settings-plugin-support.png]]
|
||||||
|
|
||||||
While you are there, you might also want to enable the automatic update checks.
|
While you are there, you might also want to enable the automatic update checks
|
||||||
|
(Note: those settings do not exist in the Steam version).
|
||||||
|
|
||||||
![[VoiceAttack-settings-updates.png]]
|
![[VoiceAttack-settings-updates.png]]
|
||||||
|
|
||||||
## Install EDDI
|
## Install EDDI
|
||||||
|
|
||||||
Install [the latest release](https://github.com/EDCD/EDDI/releases/latest) from
|
Install [the latest release](https://github.com/EDCD/EDDI/releases/latest) from
|
||||||
Github (The `EDDI-X.Y.Z.exe` under “Assets”). You will need to [install it as a
|
Github (The `EDDI-X.Y.Z.exe` file under “Assets”). You will need to [install it
|
||||||
VoiceAttack
|
as a VoiceAttack
|
||||||
plugin](https://github.com/EDCD/EDDI/wiki/VoiceAttack-Integration#using-eddi-with-voiceattack).
|
plugin](https://github.com/EDCD/EDDI/wiki/VoiceAttack-Integration#using-eddi-with-voiceattack).
|
||||||
|
|
||||||
If you do not want to install it into the VoiceAttack installation folder (or
|
If you do not want to install it into the VoiceAttack installation folder (or
|
||||||
already have it installed somewhere else) you can also just create a symbolic
|
already have it installed somewhere else) you can instead put it elsewhere and
|
||||||
link. Open a CMD prompt (Windows key + `R`, enter “cmd”, hit `Enter`) and do
|
create a symbolic link. Open a command prompt (Windows key + `R`, enter “cmd”,
|
||||||
|
hit `Enter`) and do
|
||||||
|
|
||||||
```cmd
|
```cmd
|
||||||
>cd x:\path\to\VoiceAttack\Apps
|
>cd x:\path\to\VoiceAttack\Apps
|
||||||
|
@ -49,18 +53,15 @@ link. Open a CMD prompt (Windows key + `R`, enter “cmd”, hit `Enter`) and do
|
||||||
```
|
```
|
||||||
|
|
||||||
If you have installed the non-Steam version of VoiceAttack to the default folder
|
If you have installed the non-Steam version of VoiceAttack to the default folder
|
||||||
within “ProgramFiles” you will have to run the CMD prompt as admin (Windows key
|
within “Program Files” you will have to run the command prompt as admin (Windows
|
||||||
+ `R`, enter “cmd”, hit `Control` + `Shift` + `Enter`).
|
key + `R`, enter “cmd”, hit `Control` + `Shift` + `Enter`).
|
||||||
|
|
||||||
## Install ED-NeutronRouter
|
## Install ED-NeutronRouter
|
||||||
|
|
||||||
**Make sure to [grab the pre-release
|
Grab [the latest release release from
|
||||||
1.02](https://github.com/sc-pulgan/ED-NeutronRouter/releases/tag/1.02)** since
|
Github](https://github.com/sc-pulgan/ED-NeutronRouter/releases/latest) (The
|
||||||
1.01 has a bug with a hardcoded 50 ly jump range (the
|
`EDNeutronRouter.vX.YZ.zip` under “Assets”). You will have to extract the
|
||||||
`EDNeutronRouter.vX.YZ.zip` under “Assets”).
|
contents of the release .zip file to your VoiceAttack Apps folder:
|
||||||
|
|
||||||
You will have to extract the contents of the release .zip file to your
|
|
||||||
VoiceAttack Apps folder:
|
|
||||||
|
|
||||||
1. Go into VoiceAttack settings. ![[VoiceAttack-settings.png]]
|
1. Go into VoiceAttack settings. ![[VoiceAttack-settings.png]]
|
||||||
1. Click the folder set as “Apps Folder”. ![[VoiceAttack-apps.png]]
|
1. Click the folder set as “Apps Folder”. ![[VoiceAttack-apps.png]]
|
||||||
|
@ -79,6 +80,7 @@ Leave the “Apps” folder open in Windows Explorer, you will need it for the n
|
||||||
Acquire [the latest
|
Acquire [the latest
|
||||||
release](https://github.com/alterNERDtive/VoiceAttack-profiles/releases/latest)
|
release](https://github.com/alterNERDtive/VoiceAttack-profiles/releases/latest)
|
||||||
from Github (the `alterNERDtive-voiceattack-profiles.vax` file under “Assets”).
|
from Github (the `alterNERDtive-voiceattack-profiles.vax` file under “Assets”).
|
||||||
|
Put it into VoiceAttack’s “Import” folder:
|
||||||
|
|
||||||
1. Go into VoiceAttack settings. ![[VoiceAttack-settings.png]]
|
1. Go into VoiceAttack settings. ![[VoiceAttack-settings.png]]
|
||||||
1. Click the folder set as “Apps Folder”. ![[VoiceAttack-apps.png]]
|
1. Click the folder set as “Apps Folder”. ![[VoiceAttack-apps.png]]
|
||||||
|
@ -95,37 +97,17 @@ the profiles that you want to change and add voice triggers or hotkeys.
|
||||||
|
|
||||||
You can either use an existing profile, create a new one or use the provided
|
You can either use an existing profile, create a new one or use the provided
|
||||||
profile example as a basis. Regardless of which way you choose, make sure to
|
profile example as a basis. Regardless of which way you choose, make sure to
|
||||||
read the [[#Import Profiles]] section and follow the instructions there!
|
read the [Include Profiles](#include-profiles) section and follow the instructions there!
|
||||||
|
|
||||||
### Create a New Profile
|
### Option 1: Create a New Profile Or Use an Existing One
|
||||||
|
|
||||||
1. Click the “Profile Actions” button, then “Create New Profile”.
|
1. Click the “Profile Actions” button, then “Create New Profile”.
|
||||||
![[VoiceAttack-new-profile.png]]
|
![[VoiceAttack-new-profile.png]]
|
||||||
1. Give it a name and add some commands if you want to.
|
1. Give it a name and add some commands if you want to.
|
||||||
1. Hit “Done” to create the new profile.
|
1. Hit “Done” to create the new profile.
|
||||||
|
|
||||||
### Use the Profile Example
|
Alternatively you can keep using your existing profile. You will still have to
|
||||||
|
follow the rest of the instructions in this case.
|
||||||
1. Click the “Profile Actions” button, then “Import Profile”.
|
|
||||||
![[VoiceAttack-import-profile.png]]
|
|
||||||
1. Navigate to your VoiceAttack Apps folder (see above), go into the
|
|
||||||
“alterNERDtive” subfolder, choose the profile example and hit “Open”.
|
|
||||||
![[VoiceAttack-import-profile-open.png]]
|
|
||||||
|
|
||||||
Once you are done with the setup and configuration process, you can find a bunch
|
|
||||||
of example commands with comments on how to do things in this profile. Make sure
|
|
||||||
to also rename it to something more exciting than “Custom Profile Example”!
|
|
||||||
|
|
||||||
### Include Profiles
|
|
||||||
|
|
||||||
In order to use my profiles with your custom profile, you will need to take two
|
|
||||||
additional steps:
|
|
||||||
|
|
||||||
1. Include the profiles in your custom profiles. That will make all commands
|
|
||||||
available when your custom profile is active.
|
|
||||||
1. Create a startup command for your custom profile. You can use it to do
|
|
||||||
anything you want when your profile loads, but it will also have to run the
|
|
||||||
startup command for my profiles.
|
|
||||||
|
|
||||||
#### Create a Startup Command
|
#### Create a Startup Command
|
||||||
|
|
||||||
|
@ -139,7 +121,7 @@ will now have to create the startup command. Hit the “New Command” button.
|
||||||
![[VoiceAttack-edit-new-command.png]]
|
![[VoiceAttack-edit-new-command.png]]
|
||||||
|
|
||||||
You can name it anything you want but I recommend calling it “startup” or
|
You can name it anything you want but I recommend calling it “startup” or
|
||||||
similar, and to deactivate the “when i say”checkbox in the command options to
|
similar, and to deactivate the “when I say” checkbox in the command options to
|
||||||
make sure you do not accidentally run it via voice.
|
make sure you do not accidentally run it via voice.
|
||||||
|
|
||||||
![[VoiceAttack-edit-startup.png]]
|
![[VoiceAttack-edit-startup.png]]
|
||||||
|
@ -163,6 +145,33 @@ You can add anything else you want your profile to do when it loads below this
|
||||||
action. You do not have to set any configuration options, this can be done way
|
action. You do not have to set any configuration options, this can be done way
|
||||||
more elegantly! More on this [later on](general.md#settings).
|
more elegantly! More on this [later on](general.md#settings).
|
||||||
|
|
||||||
|
After adding the startup command you will have to right click VoiceAttack’s
|
||||||
|
title bar and choose “Reload Active Profile” or restart VoiceAttack to see it
|
||||||
|
executed for the first time.
|
||||||
|
|
||||||
|
### Option 2: Use the Profile Example
|
||||||
|
|
||||||
|
1. Click the “Profile Actions” button, then “Import Profile”.
|
||||||
|
![[VoiceAttack-import-profile.png]]
|
||||||
|
1. Navigate to your VoiceAttack Apps folder (see above), go into the
|
||||||
|
“alterNERDtive” subfolder, choose the profile example and hit “Open”.
|
||||||
|
![[VoiceAttack-import-profile-open.png]]
|
||||||
|
|
||||||
|
Once you are done with the setup and configuration process, you can find a bunch
|
||||||
|
of example commands with comments on how to do things in this profile. Make sure
|
||||||
|
to also rename it to something more exciting than “Custom Profile Example”!
|
||||||
|
|
||||||
|
## Include Profiles
|
||||||
|
|
||||||
|
In order to use my profiles with your custom profile, you will need to take two
|
||||||
|
additional steps:
|
||||||
|
|
||||||
|
1. Include the profiles in your custom profile. That will make all commands
|
||||||
|
available when your custom profile is active.
|
||||||
|
1. Create a startup command for your custom profile. You can use it to do
|
||||||
|
anything you want when your profile loads, but it will also have to run the
|
||||||
|
startup command for my profiles.
|
||||||
|
|
||||||
#### Set Profile Options
|
#### Set Profile Options
|
||||||
|
|
||||||
While editing the profile, hit the “Options” button.
|
While editing the profile, hit the “Options” button.
|
||||||
|
@ -174,23 +183,31 @@ button.
|
||||||
|
|
||||||
![[VoiceAttack-profile-options-include.png]]
|
![[VoiceAttack-profile-options-include.png]]
|
||||||
|
|
||||||
Add all my profiles (“alterNERDtive-base”, “EliteDangerous”, “RatAttack”,
|
Add all my profiles (“alterNERDtive-base”, “EliteAttack”, “RatAttack”,
|
||||||
“SpanshAttack”,“StreamAttack”).
|
“SpanshAttack”, “StreamAttack”).
|
||||||
|
|
||||||
![[VoiceAttack-profile-options-includelist.png]]
|
![[VoiceAttack-profile-options-includelist.png]]
|
||||||
|
|
||||||
Technically you can leave out anything you are not planning on using.
|
Make sure that “alterNERDtive-base” is on top of the list, the order of the
|
||||||
Practically it probably will not hurt you to just include everything, and it
|
others does not matter. But I like it nice and alphabetical. Technically you can
|
||||||
will then available for you in the future if you choose to check it out! Make
|
leave out any profile you are not planning to use. Practically it probably will
|
||||||
sure that “alterNERDtive-base” is on top of the list, the order of the others
|
not hurt you to just include everything, and it will then be available for you
|
||||||
does not matter. But I like it nice and alphabetical …
|
in the future should you choose to check it out!
|
||||||
|
|
||||||
Now switch to the “Profile Exec” tab. Tick the “Execute a command each time this
|
Now switch to the “Profile Exec” tab. Tick the “Execute a command each time this
|
||||||
profile is loaded” checkbox, and select the “startup” command you have created
|
profile is loaded” checkbox, and select the “startup” command you have created
|
||||||
earlier.
|
earlier.
|
||||||
|
|
||||||
![[VoiceAttack-profile-options-startup.png]]
|
![[VoiceAttack-profile-options-startup.png]]
|
||||||
|
|
||||||
|
## Reload the Profile
|
||||||
|
|
||||||
|
To make sure everything is loaded correctly, you now need to either reload the
|
||||||
|
profile by right clicking on VoiceAttack’s title bar → “Reset Active Profile” or
|
||||||
|
by simply restarting VoiceAttack.
|
||||||
|
|
||||||
|
You should see a bunch of initialization messages pop up in the VoiceAttack log.
|
||||||
|
|
||||||
## Set Elite Keyboard Binds
|
## Set Elite Keyboard Binds
|
||||||
|
|
||||||
You need to have keyboard binds setup at least as secondary bindings in Elite’s
|
You need to have keyboard binds setup at least as secondary bindings in Elite’s
|
||||||
|
@ -201,13 +218,21 @@ HOTAS. Or racing wheel. Or Rock Band set. Or bananas.
|
||||||
|
|
||||||
![[Elite-binds.png]]
|
![[Elite-binds.png]]
|
||||||
|
|
||||||
|
For the “Galaxy Map” section, make sure that the bindings do not conflict with
|
||||||
|
the ones in the “Interface Mode” section. The map bindings take precedence and a
|
||||||
|
conflict leads to VoiceAttack being unable to target systems for you. In that
|
||||||
|
case you would see it open the map for you and then wiggle the view for a split
|
||||||
|
second instead of switching tabs over to the system search.
|
||||||
|
|
||||||
|
![[Elite-binds-galmap.png]]
|
||||||
|
|
||||||
Should you use a keyboard layout that is _not_ en-US QWERTY, some keys might not
|
Should you use a keyboard layout that is _not_ en-US QWERTY, some keys might not
|
||||||
work out of the box. You can try telling bindED about your keyboard layout by
|
work out of the box. You can try telling bindED about your keyboard layout by
|
||||||
setting the `bindED.layout#` variable (including the \#!) to something more
|
setting the `bindED.layout#` variable (including the `#`!) to something more
|
||||||
appropriate in your startup command.
|
appropriate in your startup command.
|
||||||
|
|
||||||
![[bindED-layout.png]]
|
![[bindED-layout.png]]
|
||||||
|
|
||||||
Currently bindED supports the `en-US`, `en-GB` and `de-Neo2` layouts. [You can
|
Currently bindED supports the `en-US`, `en-GB` and `de-Neo2` layouts. [You can
|
||||||
find instructions on how to add your own on
|
find instructions on how to add your own
|
||||||
Github](https://github.com/alterNERDtive/bindED/wiki/Keyboard-Layouts).
|
here](https://alternerdtive.github.io/bindED/troubleshooting/#adding-a-keyboard-layout).
|
||||||
|
|
|
@ -1,60 +1,69 @@
|
||||||
# Requirements
|
# Requirements
|
||||||
|
|
||||||
## VoiceAttack
|
## VoiceAttack
|
||||||
|
|
||||||
Obviously you will need to install [VoiceAttack](https://voiceattack.com). There
|
Obviously you will need to install [VoiceAttack](https://voiceattack.com). There
|
||||||
is a free trial version available, but that one is limited to a single profile
|
is a free trial version available, but that one is limited to a single profile
|
||||||
and a few commands. This is 4 profiles and … a lot of commands. You will need the
|
and a few commands. This is 5 profiles and … a lot of commands. You will need the
|
||||||
full version, available for $10 (official site) or €11.99 (Steam, IIRC $14.99
|
full version, available for $10 (official site) or €11.99 (Steam, IIRC $14.99
|
||||||
for our US-based friends).
|
for our US-based friends).
|
||||||
|
|
||||||
I recommend buying on the site. Why? Because on Steam, Valve gets a 30% cut.
|
I recommend buying on the site. Why? Because on Steam, Valve gets a 30% cut.
|
||||||
Unlike many other developers Gary (the developer of VoiceAttack) remedies that
|
Unlike many other developers Gary (the developer of VoiceAttack) remedies that
|
||||||
by having a price on Steam that ends up paying $10 to him. So basically, you are
|
by having a price on Steam that ends up paying $10 to him. So basically, you are
|
||||||
paying Valve out of your own pocket. Many other developers do not do that, and
|
paying Valve out of your own pocket. Many other developers do not do that, and
|
||||||
by buying from them directly instead of on Steam you are literally giving them
|
by buying from them directly instead of on Steam you are literally giving them
|
||||||
extra money. Please do keep that in mind in the future!
|
extra money. Please do keep that in mind in the future!
|
||||||
|
|
||||||
You also will generally need to opt into the beta version. I am usually at the
|
You also will generally need to opt into the beta version. I am usually at the
|
||||||
forefront of bug reports and feature requests, and I do rely on the
|
forefront of bug reports and feature requests, and I do rely on the
|
||||||
fixes/additions in beta versions quite often.
|
fixes/additions in beta versions quite often.
|
||||||
|
|
||||||
## EDDI
|
## EDDI
|
||||||
|
|
||||||
[EDDI](https://github.com/EDCD/EDDI) is a companion application for Elite:
|
[EDDI](https://github.com/EDCD/EDDI) is a companion application for Elite:
|
||||||
Dangerous, providing responses to events that occur in-game using data from the
|
Dangerous, providing responses to events that occur in-game using data from the
|
||||||
game as well as various third-party tools. In this case, you will need to run it
|
game as well as various third-party tools. In this case, you will need to run it
|
||||||
as a VoiceAttack plugin.
|
as a VoiceAttack plugin.
|
||||||
|
|
||||||
EDDI also regularly publishes beta versions. Unless a profiles release
|
EDDI also regularly publishes beta versions. Unless a profiles release
|
||||||
explicitly states it you will _not_ have to run EDDI beta.
|
explicitly states it you will _not_ have to run EDDI beta.
|
||||||
|
|
||||||
## bindED
|
Do note that the profiles put EDDI into quiet mode by default, disabling the
|
||||||
|
built-in speech responders. This can be changed
|
||||||
[bindED](https://github.com/alterNERDtive/bindED) reads your Elite Dangerous
|
[via the `EDDI quiet mode` setting](configuration/general.md#general-settings-for-all-profiles).
|
||||||
binding files and makes them available to VoiceAttack as variables. That way
|
|
||||||
commands can be portable and you do not have to manually go through them and
|
## bindED
|
||||||
change any actions that you happen to not have the standard binds for.
|
|
||||||
|
[bindED](https://alterNERDtive.github.io/bindED) reads your Elite Dangerous
|
||||||
This plugin is _included_ in the release package.
|
binding files and makes them available to VoiceAttack as variables. That way
|
||||||
|
commands can be portable and you do not have to manually go through them and
|
||||||
## Elite Scripts
|
change any actions that you happen to not have the standard binds for.
|
||||||
|
|
||||||
I have written a [collection of Python
|
This plugin is _included_ in the release package. You do _not_ have to download
|
||||||
scripts](https://github.com/alterNERDtive/elite-scripts) to interface with
|
and install it manually, but you _can_ independently update it if a newer
|
||||||
various 3ʳᵈ party services like EDSM or Spansh. Those are called by the profiles
|
version is available.
|
||||||
for various tasks, like checking a system’s body count.
|
|
||||||
|
## Elite Scripts
|
||||||
In the future they will be replaced by VoiceAttack plugin code.
|
|
||||||
|
I have written a [collection of Python
|
||||||
The scripts are _included_ in the release package.
|
scripts](https://github.com/alterNERDtive/elite-scripts) to interface with
|
||||||
|
various 3ʳᵈ party services like EDSM or Spansh. Those are called by the profiles
|
||||||
## ED-NeutronRouter
|
for various tasks, like checking a system’s body count.
|
||||||
|
|
||||||
(required for SpanshAttack)
|
In the future they will be replaced by VoiceAttack plugin code.
|
||||||
|
|
||||||
[ED-NeutronRouter](https://github.com/sc-pulgan/ED-NeutronRouter) interfaces
|
The scripts are _included_ in the release package. You do _not_ have to download
|
||||||
with [Spansh’s neutron plotter](https://spansh.uk/plotter) and makes the result
|
and install them manually, but you _can_ independently update them if a newer
|
||||||
|
version is available.
|
||||||
|
|
||||||
|
## ED-NeutronRouter
|
||||||
|
|
||||||
|
[ED-NeutronRouter](https://github.com/sc-pulgan/ED-NeutronRouter) interfaces
|
||||||
|
with [Spansh’s neutron plotter](https://spansh.uk/plotter) and makes the result
|
||||||
available to VoiceAttack.
|
available to VoiceAttack.
|
||||||
|
|
||||||
This will also eventually replaced by my own plugins.
|
This plugin is _only_ required if you intend to use the SpanshAttack profile for
|
||||||
|
neutron routing. Otherwise you do not have to install it.
|
||||||
|
|
||||||
|
This will also eventually be replaced by my own plugins.
|
||||||
|
|
|
@ -1,33 +1,100 @@
|
||||||
# Troubleshooting
|
# Troubleshooting
|
||||||
|
|
||||||
This will fill up gradually with Troubleshooting tips as people run into common
|
This will fill up gradually with Troubleshooting tips as people run into common
|
||||||
ones.
|
ones.
|
||||||
|
|
||||||
# VoiceAttack does not understand me / mishears me / fires random commands
|
## VoiceAttack does not understand me / mishears me / fires random commands
|
||||||
|
|
||||||
There is [a thread on the VoiceAttack
|
There is [a thread on the VoiceAttack
|
||||||
forums](https://forum.voiceattack.com/smf/index.php?topic=2667.msg12197#msg12197)
|
forums](https://forum.voiceattack.com/smf/index.php?topic=2667.msg12197#msg12197)
|
||||||
on how to set up your microphone and the speech recognition engine to work best.
|
on how to set up your microphone and the speech recognition engine to work best.
|
||||||
|
|
||||||
If your microphone is bad and you still get erroneous recognitions when you are
|
If your microphone is bad and you still get erroneous recognitions when you are
|
||||||
not speaking it is probably going to recognize the same command every time. You
|
not speaking it is probably going to recognize the same command every time. You
|
||||||
can remedy that by blocking the voice trigger.
|
can remedy that by blocking the voice trigger. One-syllable triggers are
|
||||||
|
especially prone to misrecognition.
|
||||||
1. Create a new command in your custom profile.
|
|
||||||
1. Set the “when I say” field to the trigger that gets misrecognized.
|
1. Create a new command in your custom profile.
|
||||||
|
1. Set the “when I say” field to the trigger that gets misrecognized.
|
||||||
Adding the “Other” → “VoiceAttack Action” → “Ignore an Unrecognized Word or
|
|
||||||
Phrase” action will also hide it from the VoiceAttack log when it is (wrongly)
|
Adding the “Other” → “VoiceAttack Action” → “Ignore an Unrecognized Word or
|
||||||
recognized. You might or might not want that.
|
Phrase” action will also hide it from the VoiceAttack log when it is (wrongly)
|
||||||
|
recognized. You might or might not want that.
|
||||||
Example for the “cruise” voice trigger of the Supercruise command:
|
|
||||||
|
Example for the “cruise” voice trigger of the Supercruise command:
|
||||||
![[troubleshooting-remove-trigger.png]]
|
|
||||||
|
![[troubleshooting-remove-trigger.png]]
|
||||||
Alternatively you can raise the minimum confidence level and call the underlying
|
|
||||||
command to make misfires less likely:
|
Alternatively you can raise the minimum confidence level and call the underlying
|
||||||
|
command to make misfires less likely:
|
||||||
![[troubleshooting-raise-min-confidence.png]]
|
|
||||||
|
![[troubleshooting-raise-min-confidence.png]]
|
||||||
There are a few examples in the [Custom Profile
|
|
||||||
Example](../installing#use-the-profile-example).
|
There are a few examples in the [Custom Profile
|
||||||
|
Example](../installing#use-the-profile-example).
|
||||||
|
|
||||||
|
## VoiceAttack recognizes a command, but doesn’t do anything in game
|
||||||
|
|
||||||
|
Make sure you have a keyboard bind for whatever the command is supposed to do as
|
||||||
|
outlined in [[Installing#Set Elite Keyboard Binds]].
|
||||||
|
|
||||||
|
## VoiceAttack talks over the COVAS voice
|
||||||
|
|
||||||
|
There is no way to know for sure when the ingame COVAS is talking to you, so
|
||||||
|
there is no way to always prevent the two from speaking over each other.
|
||||||
|
|
||||||
|
You can however either disable TTS responses for events that you know will clash
|
||||||
|
(or [file a feature
|
||||||
|
request](https://github.com/alterNERDtive/VoiceAttack-profiles/issues/) if one
|
||||||
|
is not optional yet). Alternatively, if you prefer the info given by VoiceAttack
|
||||||
|
over the ingame COVAS, you can deactivate its response to these events in the
|
||||||
|
ingame Audo settings:
|
||||||
|
|
||||||
|
![[Elite-COVAS.png]]
|
||||||
|
|
||||||
|
While you’re in there you might as well get rid of the spoken FSD countdown that
|
||||||
|
is off by one second …
|
||||||
|
|
||||||
|
## This doesn’t work (well) with my HCS pack
|
||||||
|
|
||||||
|
My profiles are designed from the ground up to work with whatever else you are
|
||||||
|
doing with VoiceAttack; that is the reason for importing them into your own
|
||||||
|
custom profile instead of selecting e.g. `EliteAttack` as your active profile.
|
||||||
|
|
||||||
|
HCS on the contrary explicitly expects you do exclusively use HCS with
|
||||||
|
VoiceAttack. There is the rudimentary way of including simple profiles into
|
||||||
|
theirs, but the mechanism falls flat in many places. For example you cannot tell
|
||||||
|
HCS to run an included profile’s startup command.
|
||||||
|
|
||||||
|
So, in order to mostly make stuff work, you need to treat the HCS profile as
|
||||||
|
your “custom” profile as per this documentation.
|
||||||
|
|
||||||
|
1. Include `alterNERDtive-base` and all profiles you want to use into the active
|
||||||
|
HCS profile.
|
||||||
|
1. Include a custom profile that has a startup command with a voice trigger of
|
||||||
|
your choosing, e.g. “load included profiles”.
|
||||||
|
1. Set up said startup command as you would normally.
|
||||||
|
1. Every time you start VA or change profiles, you will have to manually say
|
||||||
|
“load included profiles”.
|
||||||
|
|
||||||
|
That will make most things work. Conflicts may arise if HCS happens to have
|
||||||
|
voice triggers that are the same as mine, in which case their command will take
|
||||||
|
priority.
|
||||||
|
|
||||||
|
**Note on TTS**: EDDI’s TTS (used by my profiles) and HCS’ TTS / recorded voice
|
||||||
|
lines act 100% independently. That means they will frequently “speak over each
|
||||||
|
other”. There is no way to alleviate this.
|
||||||
|
|
||||||
|
EDDI does have a mechanism to detect if it is currently speaking – it sets a
|
||||||
|
corresponding VoiceAttack variable. HCS neither does anything similar nor checks
|
||||||
|
if EDDI is speaking to prevent conflicts. Refer to them if you want that
|
||||||
|
changed.
|
||||||
|
|
||||||
|
## This does not work with Geforce Now
|
||||||
|
|
||||||
|
Nope. Just won’t. Geforce Now obviously has Elite’s files, journals and keybinds
|
||||||
|
stored on some random PC in the cloud. Your local VoiceAttack has no way of
|
||||||
|
accessing those.
|
||||||
|
|
||||||
|
If you can get VoiceAttack to run _on Geforce Now_ in parallel to Elite, I don’t
|
||||||
|
see why it wouldn’t work.
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
# Upgrading
|
# Upgrading
|
||||||
|
|
||||||
To upgrade to the latest version, follow these simple steps:
|
To upgrade to the latest version, follow these simple steps:
|
||||||
|
|
||||||
1. Say “download profiles update”.
|
1. Say “download profiles update”.
|
||||||
1. Put the `alterNERDtive-voiceattack-profiles.vax` file from Github into the
|
1. Put the `alterNERDtive-voiceattack-profiles.vax` file from Github into
|
||||||
“Import” folder.
|
VoiceAttack’s “Import” folder.
|
||||||
1. Restart VoiceAttack.
|
1. Restart VoiceAttack.
|
||||||
|
|
||||||
In general, migration from old versions will be handled automatically. If there
|
In general, migration from old versions will be handled automatically. If there
|
||||||
|
@ -14,7 +14,7 @@ You can find the full
|
||||||
[Changelog](https://github.com/alterNERDtive/VoiceAttack-profiles/blob/release/CHANGELOG.md)
|
[Changelog](https://github.com/alterNERDtive/VoiceAttack-profiles/blob/release/CHANGELOG.md)
|
||||||
on Github.
|
on Github.
|
||||||
|
|
||||||
## 3.x.x to 4.0
|
## 3.x.x to 4.x.x
|
||||||
|
|
||||||
If you have been using a custom profile as outlined in [[Installing#Create a
|
If you have been using a custom profile as outlined in [[Installing#Create a
|
||||||
Custom Profile]] your settings will be migrated to the new variables
|
Custom Profile]] your settings will be migrated to the new variables
|
||||||
|
@ -29,6 +29,13 @@ Please do not fiddle with the configuration variables from your startup command
|
||||||
entirely unnecessary since configuration will be saved to and loaded from the
|
entirely unnecessary since configuration will be saved to and loaded from the
|
||||||
profile anyway.
|
profile anyway.
|
||||||
|
|
||||||
|
### EDDI Events
|
||||||
|
|
||||||
|
The process for adding your own handlers for EDDI events has changed. You no
|
||||||
|
longer have to check which of my profiles handle them and add the commands for
|
||||||
|
those manually; instead you need to [run the `eddi.event` context of the
|
||||||
|
`alterNERDtive-base` plugin](../configuration/general#eddi-events).
|
||||||
|
|
||||||
### bindED
|
### bindED
|
||||||
|
|
||||||
If you have done anything non-standard with bindED before, it might break. The
|
If you have done anything non-standard with bindED before, it might break. The
|
||||||
|
@ -70,7 +77,7 @@ list.
|
||||||
For my AdiIRC, it looks like this (obviously change the path, please):
|
For my AdiIRC, it looks like this (obviously change the path, please):
|
||||||
|
|
||||||
```adiirc
|
```adiirc
|
||||||
on *:TEXT:RATSIGNAL - CMDR*(??_SIGNAL):#fuelrats:{
|
on *:TEXT:*RATSIGNAL*(??_SIGNAL):#fuelrats:{
|
||||||
if ( $away ) {
|
if ( $away ) {
|
||||||
/run -h "X:\path\to\VoiceAttack\Apps\alterNERDtive\RatAttack-cli.exe" " $+ $replace($1-,","") $+ " false
|
/run -h "X:\path\to\VoiceAttack\Apps\alterNERDtive\RatAttack-cli.exe" " $+ $replace($1-,","") $+ " false
|
||||||
}
|
}
|
||||||
|
@ -83,8 +90,8 @@ on *:TEXT:RATSIGNAL - CMDR*(??_SIGNAL):#fuelrats:{
|
||||||
If I am away it will just add the new case to the list. If I am not away, it
|
If I am away it will just add the new case to the list. If I am not away, it
|
||||||
will announce it using TTS.
|
will announce it using TTS.
|
||||||
|
|
||||||
The “replace” part handles the fact that announcements now put the system in
|
The `$replace` part handles the fact that case announcements now put the system
|
||||||
quotes. They have to be escaped as double quotes (`""`) to create a correct
|
in quotes. They have to be escaped as double quotes (`""`) to create a correct
|
||||||
command line invocation.
|
command line invocation.
|
||||||
|
|
||||||
#### Nearest CMDR Announcements
|
#### Nearest CMDR Announcements
|
||||||
|
@ -93,4 +100,4 @@ If you have RatAttack set up to announce your nearest commander to a case,
|
||||||
you’ll have to change the setting to the new format, separated by `;` instead of
|
you’ll have to change the setting to the new format, separated by `;` instead of
|
||||||
whitespace.
|
whitespace.
|
||||||
|
|
||||||
Say “customize setting set fuel rat commanders” to update it.
|
Say “customize setting set fuel rat commanders” to update it.
|
||||||
|
|
19
mkdocs.yml
|
@ -1,10 +1,10 @@
|
||||||
site_name: "alterNERDtive VA profiles"
|
site_name: "alterNERDtive VA profiles"
|
||||||
site_url: https://alterNERDtive.github.io/VoiceAttack-profiles
|
site_url: https://alterNERDtive.github.io/VoiceAttack-profiles
|
||||||
repo_url: https://github.com/alterNERDtive/VoiceAttack-profiles
|
repo_url: https://github.com/alterNERDtive/VoiceAttack-profiles
|
||||||
edit_uri: "edit/devel/docs/"
|
edit_uri: "edit/devel/docs/"
|
||||||
site_description: "alterNERDtive VoiceAttack profiles for Elite: Dangerous"
|
site_description: "alterNERDtive VoiceAttack profiles for Elite: Dangerous"
|
||||||
site_author: "alterNERDtive"
|
site_author: "alterNERDtive"
|
||||||
remote_name: "ssh-origin"
|
remote_name: "origin"
|
||||||
|
|
||||||
theme:
|
theme:
|
||||||
name: readthedocs
|
name: readthedocs
|
||||||
|
@ -13,9 +13,9 @@ theme:
|
||||||
plugins:
|
plugins:
|
||||||
- search
|
- search
|
||||||
- roamlinks
|
- roamlinks
|
||||||
- mkpdfs:
|
# - mkpdfs:
|
||||||
author: 'alterNERDtive'
|
# author: 'alterNERDtive'
|
||||||
output_path: 'pdf/Profiles Documentation.pdf'
|
# output_path: 'pdf/Profiles Documentation.pdf'
|
||||||
|
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
- toc:
|
- toc:
|
||||||
|
@ -41,9 +41,10 @@ nav:
|
||||||
- 'SpanshAttack.md'
|
- 'SpanshAttack.md'
|
||||||
- 'StreamAttack.md'
|
- 'StreamAttack.md'
|
||||||
- 'Issues':
|
- 'Issues':
|
||||||
- 'VoiceAttack Tips': 'VoiceAttack.md'
|
#- 'VoiceAttack Tips': 'VoiceAttack.md'
|
||||||
- 'troubleshooting.md'
|
- 'troubleshooting.md'
|
||||||
- 'Report a Bug': 'https://github.com/alterNERDtive/VoiceAttack-profiles/issues/new'
|
- '⎋ Changelog': 'https://github.com/alterNERDtive/VoiceAttack-profiles/blob/release/CHANGELOG.md'
|
||||||
|
- '⎋ Report a Bug': 'https://github.com/alterNERDtive/VoiceAttack-profiles/issues/'
|
||||||
- 'Watch in Action':
|
- 'Watch in Action':
|
||||||
- 'Twitch': 'https://twitch.tv/alterNERDtive'
|
- '⎋ Twitch': 'https://twitch.tv/alterNERDtive'
|
||||||
- 'Youtube': 'https://www.youtube.com/channel/UC3XNZA7xWed1zM1AWOOdmog'
|
- '⎋ Youtube': 'https://www.youtube.com/channel/UC3XNZA7xWed1zM1AWOOdmog'
|
||||||
|
|
58
plugins.sln
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 16.0.30413.136
|
VisualStudioVersion = 17.3.32519.111
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VoiceAttack-base", "plugins\VoiceAttack-base\VoiceAttack-base.csproj", "{1C05DB3F-3449-4664-B363-A379892995E5}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VoiceAttack-base", "plugins\VoiceAttack-base\VoiceAttack-base.csproj", "{1C05DB3F-3449-4664-B363-A379892995E5}"
|
||||||
EndProject
|
EndProject
|
||||||
|
@ -13,6 +13,54 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EliteAttack", "plugins\Elit
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpanshAttack", "plugins\SpanshAttack\SpanshAttack.csproj", "{D2047704-696B-4665-8D37-3AD298A8B9F9}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpanshAttack", "plugins\SpanshAttack\SpanshAttack.csproj", "{D2047704-696B-4665-8D37-3AD298A8B9F9}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C2B4D94B-8D73-431A-880B-B1E7ADF064B2}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
.editorconfig = .editorconfig
|
||||||
|
CHANGELOG.md = CHANGELOG.md
|
||||||
|
.github\workflows\create-release.yaml = .github\workflows\create-release.yaml
|
||||||
|
Directory.build.props = Directory.build.props
|
||||||
|
mkdocs.yml = mkdocs.yml
|
||||||
|
README.md = README.md
|
||||||
|
stylecop.json = stylecop.json
|
||||||
|
VERSION = VERSION
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{5401ADF7-CB6D-448B-A4AC-D8A17B2D841F}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
docs\EliteAttack.md = docs\EliteAttack.md
|
||||||
|
docs\general.md = docs\general.md
|
||||||
|
docs\index.md = docs\index.md
|
||||||
|
docs\installing.md = docs\installing.md
|
||||||
|
docs\RatAttack.md = docs\RatAttack.md
|
||||||
|
docs\requirements.md = docs\requirements.md
|
||||||
|
docs\SpanshAttack.md = docs\SpanshAttack.md
|
||||||
|
docs\StreamAttack.md = docs\StreamAttack.md
|
||||||
|
docs\troubleshooting.md = docs\troubleshooting.md
|
||||||
|
docs\upgrading.md = docs\upgrading.md
|
||||||
|
docs\VoiceAttack.md = docs\VoiceAttack.md
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "configuration", "configuration", "{1AFD9AE6-7D22-4EF4-B0DE-51C9E91370FB}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
docs\configuration\EliteAttack.md = docs\configuration\EliteAttack.md
|
||||||
|
docs\configuration\general.md = docs\configuration\general.md
|
||||||
|
docs\configuration\RatAttack.md = docs\configuration\RatAttack.md
|
||||||
|
docs\configuration\SpanshAttack.md = docs\configuration\SpanshAttack.md
|
||||||
|
docs\configuration\StreamAttack.md = docs\configuration\StreamAttack.md
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{A68BA76B-47FA-4D25-805E-66EBDD8C5223}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
.github\dependabot.yaml = .github\dependabot.yaml
|
||||||
|
.github\FUNDING.yml = .github\FUNDING.yml
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{0147AF7E-BB7F-4D5F-96EC-8734393DFF56}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
.github\workflows\create-release.yaml = .github\workflows\create-release.yaml
|
||||||
|
.github\workflows\gh-pages.yaml = .github\workflows\gh-pages.yaml
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -43,6 +91,12 @@ Global
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{5401ADF7-CB6D-448B-A4AC-D8A17B2D841F} = {C2B4D94B-8D73-431A-880B-B1E7ADF064B2}
|
||||||
|
{1AFD9AE6-7D22-4EF4-B0DE-51C9E91370FB} = {5401ADF7-CB6D-448B-A4AC-D8A17B2D841F}
|
||||||
|
{A68BA76B-47FA-4D25-805E-66EBDD8C5223} = {C2B4D94B-8D73-431A-880B-B1E7ADF064B2}
|
||||||
|
{0147AF7E-BB7F-4D5F-96EC-8734393DFF56} = {A68BA76B-47FA-4D25-805E-66EBDD8C5223}
|
||||||
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {339E6747-C7BF-43C3-99C6-9249C9849A84}
|
SolutionGuid = {339E6747-C7BF-43C3-99C6-9249C9849A84}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
|
|
@ -1,113 +1,175 @@
|
||||||
#nullable enable
|
// <copyright file="EliteAttack.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
using alterNERDtive.util;
|
//
|
||||||
using System;
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
using System.Collections.Generic;
|
//
|
||||||
using System.Linq;
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
using System.Text;
|
// it under the terms of the GNU General Public License as published by
|
||||||
using System.Threading.Tasks;
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
namespace EliteAttack
|
//
|
||||||
{
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
public class EliteAttack {
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
private static dynamic? VA { get; set; }
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
private static VoiceAttackLog Log
|
//
|
||||||
=> log ??= new VoiceAttackLog(VA, "EliteAttack");
|
// You should have received a copy of the GNU General Public License
|
||||||
private static VoiceAttackLog? log;
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
private static VoiceAttackCommands Commands
|
|
||||||
=> commands ??= new VoiceAttackCommands(VA, Log);
|
#nullable enable
|
||||||
private static VoiceAttackCommands? commands;
|
|
||||||
|
using System;
|
||||||
/*================\
|
|
||||||
| plugin contexts |
|
using alterNERDtive.util;
|
||||||
\================*/
|
|
||||||
|
namespace EliteAttack
|
||||||
private static void Context_Log(dynamic vaProxy)
|
{
|
||||||
{
|
/// <summary>
|
||||||
string message = vaProxy.GetText("~message");
|
/// VoiceAttack plugin for the EliteAttack profile.
|
||||||
string level = vaProxy.GetText("~level");
|
/// </summary>
|
||||||
|
public class EliteAttack
|
||||||
if (level == null)
|
{
|
||||||
{
|
private static readonly Version VERSION = new ("8.5");
|
||||||
Log.Log(message);
|
|
||||||
}
|
private static VoiceAttackLog? log;
|
||||||
else
|
private static VoiceAttackCommands? commands;
|
||||||
{
|
|
||||||
try
|
private static dynamic? VA { get; set; }
|
||||||
{
|
|
||||||
Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper()));
|
private static VoiceAttackLog Log => log ??= new (VA, "EliteAttack");
|
||||||
}
|
|
||||||
catch (ArgumentNullException) { throw; }
|
private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
|
||||||
catch (ArgumentException)
|
|
||||||
{
|
/*========================================\
|
||||||
Log.Error($"Invalid log level '{level}'.");
|
| required VoiceAttack plugin shenanigans |
|
||||||
}
|
\========================================*/
|
||||||
}
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// The plugin’s GUID, as required by the VoiceAttack plugin API.
|
||||||
private static void Context_Startup(dynamic vaProxy)
|
/// </summary>
|
||||||
{
|
/// <returns>The GUID.</returns>
|
||||||
Log.Notice("Starting up …");
|
public static Guid VA_Id()
|
||||||
VA = vaProxy;
|
=> new ("{5B46321D-2935-4550-BEEA-36C2145547B8}");
|
||||||
Log.Notice("Finished startup.");
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// The plugin’s display name, as required by the VoiceAttack plugin API.
|
||||||
/*========================================\
|
/// </summary>
|
||||||
| required VoiceAttack plugin shenanigans |
|
/// <returns>The display name.</returns>
|
||||||
\========================================*/
|
public static string VA_DisplayName()
|
||||||
|
=> $"EliteAttack {VERSION}";
|
||||||
static readonly Version VERSION = new Version("8.0.0");
|
|
||||||
|
/// <summary>
|
||||||
public static Guid VA_Id()
|
/// The plugin’s description, as required by the VoiceAttack plugin API.
|
||||||
=> new Guid("{5B46321D-2935-4550-BEEA-36C2145547B8}");
|
/// </summary>
|
||||||
public static string VA_DisplayName()
|
/// <returns>The description.</returns>
|
||||||
=> $"EliteAttack {VERSION}";
|
public static string VA_DisplayInfo()
|
||||||
public static string VA_DisplayInfo()
|
=> "EliteAttack: a plugin for doing Elite-y things.";
|
||||||
=> "EliteAttack: a plugin for doing Elite-y things.";
|
|
||||||
|
/// <summary>
|
||||||
public static void VA_Init1(dynamic vaProxy)
|
/// The Init method, as required by the VoiceAttack plugin API.
|
||||||
{
|
/// Runs when the plugin is initially loaded.
|
||||||
VA = vaProxy;
|
/// </summary>
|
||||||
Log.Notice("Initializing …");
|
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
|
||||||
VA.SetText("EliteAttack.version", VERSION.ToString());
|
public static void VA_Init1(dynamic vaProxy)
|
||||||
Log.Notice("Init successful.");
|
{
|
||||||
}
|
VA = vaProxy;
|
||||||
|
Log.Notice("Initializing …");
|
||||||
public static void VA_Invoke1(dynamic vaProxy)
|
VA.SetText("EliteAttack.version", VERSION.ToString());
|
||||||
{
|
Log.Notice("Init successful.");
|
||||||
string context = vaProxy.Context.ToLower();
|
}
|
||||||
Log.Debug($"Running context '{context}' …");
|
|
||||||
try
|
/// <summary>
|
||||||
{
|
/// The Invoke method, as required by the VoiceAttack plugin API.
|
||||||
switch (context)
|
/// Runs whenever a plugin context is invoked.
|
||||||
{
|
/// </summary>
|
||||||
case "startup":
|
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
|
||||||
Context_Startup(vaProxy);
|
public static void VA_Invoke1(dynamic vaProxy)
|
||||||
break;
|
{
|
||||||
// log
|
string context = vaProxy.Context.ToLower();
|
||||||
case "log.log":
|
Log.Debug($"Running context '{context}' …");
|
||||||
Context_Log(vaProxy);
|
try
|
||||||
break;
|
{
|
||||||
// invalid
|
switch (context)
|
||||||
default:
|
{
|
||||||
Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
|
case "startup":
|
||||||
break;
|
Context_Startup(vaProxy);
|
||||||
}
|
break;
|
||||||
}
|
case "log.log":
|
||||||
catch (ArgumentNullException e)
|
// log
|
||||||
{
|
Context_Log(vaProxy);
|
||||||
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
|
break;
|
||||||
}
|
default:
|
||||||
catch (Exception e)
|
// invalid
|
||||||
{
|
Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
|
||||||
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (ArgumentNullException e)
|
||||||
public static void VA_Exit1(dynamic vaProxy) { }
|
{
|
||||||
|
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
|
||||||
public static void VA_StopCommand() { }
|
}
|
||||||
}
|
catch (Exception e)
|
||||||
}
|
{
|
||||||
|
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Exit method, as required by the VoiceAttack plugin API.
|
||||||
|
/// Runs when VoiceAttack is shut down.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "required by VoiceAttack plugin API")]
|
||||||
|
public static void VA_Exit1(dynamic vaProxy)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The StopCommand method, as required by the VoiceAttack plugin API.
|
||||||
|
/// Runs whenever all commands are stopped using the “Stop All Commands”
|
||||||
|
/// button or action.
|
||||||
|
/// </summary>
|
||||||
|
public static void VA_StopCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*================\
|
||||||
|
| plugin contexts |
|
||||||
|
\================*/
|
||||||
|
|
||||||
|
#pragma warning disable IDE0060 // Remove unused parameter
|
||||||
|
private static void Context_Log(dynamic vaProxy)
|
||||||
|
{
|
||||||
|
string message = vaProxy.GetText("~message");
|
||||||
|
string level = vaProxy.GetText("~level");
|
||||||
|
|
||||||
|
if (level == null)
|
||||||
|
{
|
||||||
|
Log.Log(message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper()));
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
Log.Error($"Invalid log level '{level}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Context_Startup(dynamic vaProxy)
|
||||||
|
{
|
||||||
|
Log.Notice("Starting up …");
|
||||||
|
Log.Notice("Finished startup.");
|
||||||
|
}
|
||||||
|
#pragma warning restore IDE0060 // Remove unused parameter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<LangVersion>8.0</LangVersion>
|
<DocumentationFile>..\build\alterNERDtive\EliteAttack.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<LangVersion>8.0</LangVersion>
|
<DocumentationFile>..\build\alterNERDtive\EliteAttack.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
|
|
@ -1,4 +1,23 @@
|
||||||
using System.Reflection;
|
// <copyright file="AssemblyInfo.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,23 @@
|
||||||
using System.Reflection;
|
// <copyright file="AssemblyInfo.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.IO.Pipes;
|
|
||||||
|
|
||||||
namespace RatAttack
|
|
||||||
{
|
|
||||||
class RatAttack_cli
|
|
||||||
{
|
|
||||||
static void Main(string[] args)
|
|
||||||
{
|
|
||||||
RatAttack.Ratsignal ratsignal = new RatAttack.Ratsignal(args[0], args.Length > 1 && args[1].ToLower() == "true");
|
|
||||||
|
|
||||||
using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "RatAttack", PipeDirection.Out))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// try connecting for up to 2 minutes; then we’ll assume VoiceAttack just isn’t up and won’t come up
|
|
||||||
pipeClient.Connect(120000);
|
|
||||||
using (StreamWriter writer = new StreamWriter(pipeClient))
|
|
||||||
{
|
|
||||||
writer.WriteLine(ratsignal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (TimeoutException)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine("Connection to RatAttack pipe has timed out.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,7 +25,7 @@
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<LangVersion>8.0</LangVersion>
|
<DocumentationFile>..\build\alterNERDtive\RatAttack-cli.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<LangVersion>8.0</LangVersion>
|
<DocumentationFile>..\build\alterNERDtive\RatAttack-cli.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
@ -50,8 +50,8 @@
|
||||||
<Reference Include="System.Xml.Serialization" />
|
<Reference Include="System.Xml.Serialization" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="RatAttack-cli.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="RatAttack_cli.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\RatAttack\RatAttack.csproj">
|
<ProjectReference Include="..\RatAttack\RatAttack.csproj">
|
||||||
|
|
68
plugins/RatAttack-cli/RatAttack_cli.cs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
// <copyright file="RatAttack_cli.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Pipes;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace RatAttack
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// CLI helper tool for the RatAttack VoiceAttack plugin. Accepts RATSIGNALs
|
||||||
|
/// e.g. from an IRC client and passes them to the plugin via named pipe.
|
||||||
|
/// </summary>
|
||||||
|
public class RatAttack_cli
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Main entry point.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The command line arguments.</param>
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
RatAttack.Ratsignal ratsignal = new (StripIrcCodes(args[0]), args.Length > 1 && args[1].ToLower() == "true");
|
||||||
|
|
||||||
|
using (NamedPipeClientStream pipeClient = new (".", "RatAttack", PipeDirection.Out))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// try connecting for up to 2 minutes; then we’ll assume VoiceAttack just isn’t up and won’t come up
|
||||||
|
pipeClient.Connect(120000);
|
||||||
|
using StreamWriter writer = new (pipeClient);
|
||||||
|
writer.WriteLine(ratsignal);
|
||||||
|
}
|
||||||
|
catch (TimeoutException)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Connection to RatAttack pipe has timed out.");
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Cannot connect to RatAttack pipe. Are you running VoiceAttack as Admin?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string StripIrcCodes(string message)
|
||||||
|
{
|
||||||
|
return Regex.Replace(message, @"[\x02\x11\x0F\x1D\x1E\x1F\x16]|\x03(\d\d?(,\d\d?)?)?", string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,23 @@
|
||||||
using System.Reflection;
|
// <copyright file="AssemblyInfo.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
|
@ -1,321 +1,445 @@
|
||||||
#nullable enable
|
// <copyright file="RatAttack.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
using System;
|
//
|
||||||
using System.Collections.Generic;
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
using System.Diagnostics;
|
//
|
||||||
using System.Text.RegularExpressions;
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
using alterNERDtive.util;
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
namespace RatAttack
|
// (at your option) any later version.
|
||||||
{
|
//
|
||||||
public class RatAttack
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
{
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
private static Dictionary<int,RatCase> CaseList { get; } = new Dictionary<int, RatCase>();
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
private static dynamic? VA { get; set; }
|
// GNU General Public License for more details.
|
||||||
private static alterNERDtive.util.PipeServer<Ratsignal> RatsignalPipe
|
//
|
||||||
=> ratsignalPipe ??= new alterNERDtive.util.PipeServer<Ratsignal>(Log, "RatAttack",
|
// You should have received a copy of the GNU General Public License
|
||||||
new alterNERDtive.util.PipeServer<Ratsignal>.SignalHandler(On_Ratsignal));
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
private static alterNERDtive.util.PipeServer<Ratsignal>? ratsignalPipe;
|
// </copyright>
|
||||||
|
|
||||||
private static readonly Regex RatsignalRegex = new Regex(
|
#nullable enable
|
||||||
@"^RATSIGNAL - CMDR (?<cmdr>.+) - Reported System: (None|""(?<system>.+)""( \(((?<systemInfo>[0-9,\.]+ LY from .*|landmark|Not found in galaxy database|Valid system name))\))?(?<permit> \x037\(((?<permitName>.*) )?Permit Required\)\x03)?) - Platform: \x03(6|3|12)(?<platform>(PC|Xbox|Playstation))\x03 - O2: (\x034)?(?<oxygen>(NOT )?OK)\x03? - Language: .+ \(\x02Case #(?<number>\d+)\x02\) \((PC|XB|PS)_SIGNAL\)\v*$"
|
|
||||||
);
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
private static VoiceAttackLog Log
|
using System.Diagnostics;
|
||||||
=> log ??= new VoiceAttackLog(VA, "RatAttack");
|
using System.Text.RegularExpressions;
|
||||||
private static VoiceAttackLog? log;
|
|
||||||
|
using alterNERDtive.util;
|
||||||
private static VoiceAttackCommands Commands
|
|
||||||
=> commands ??= new VoiceAttackCommands(VA, Log);
|
namespace RatAttack
|
||||||
private static VoiceAttackCommands? commands;
|
{
|
||||||
|
/// <summary>
|
||||||
private class RatCase
|
/// VoiceAttack plugin for the RatAttack profile.
|
||||||
{
|
/// </summary>
|
||||||
public string Cmdr;
|
public class RatAttack
|
||||||
public string? System;
|
{
|
||||||
public string? SystemInfo;
|
private static readonly Version VERSION = new ("6.4");
|
||||||
public bool PermitLocked;
|
|
||||||
public string? PermitName;
|
private static readonly Regex RatsignalRegex = new (
|
||||||
public string Platform;
|
@"^RATSIGNAL Case #(?<number>\d+) (?<platform>(PC|Xbox|Playstation))( )?(?<mode>H3.8|H4.0|ODY)?(?<oxygen> \(Code Red\))? – CMDR (?<cmdr>.+) – System: (None|u\u200bnknown system|""(?<system>.+)"" \((?<systemInfo>([a-zA-Z0-9\s\(\)\-/]*(~?[0-9,\.]+ LY (""[a-zA-Z\-]+"" of|from) [a-zA-Z0-9\s\*\-]+)?( \([a-zA-Z\s]+\))?|Not found in galaxy database|Invalid system name))\)(?<permit> \(((?<permitName>.*) )?Permit Required\))?) – Language: (?<language>[a-zA-z0-9\x7f-\xff\-\(\)&,\s\.]+)( – Nick: (?<nick>[a-zA-Z0-9_\[\]\-\^]+))? \((H3|H4|ODY|XB|PS)_SIGNAL\)\v*$");
|
||||||
public bool CodeRed;
|
|
||||||
public int Number;
|
private static PipeServer<Ratsignal>? ratsignalPipe;
|
||||||
|
private static VoiceAttackLog? log;
|
||||||
public RatCase(string cmdr, string? system, string? systemInfo, bool permitLocked, string? permitName, string platform, bool codeRed, int number)
|
private static VoiceAttackCommands? commands;
|
||||||
=> (Cmdr, System, SystemInfo, PermitLocked, PermitName, Platform, CodeRed, Number) = (cmdr, system, systemInfo, permitLocked, permitName, platform, codeRed, number);
|
|
||||||
|
private static ConcurrentDictionary<int, RatCase> CaseList { get; } = new ();
|
||||||
public string ShortInfo
|
|
||||||
{
|
private static dynamic? VA { get; set; }
|
||||||
get => $"#{Number}, {Platform}{(CodeRed ? ", code red" : "")}, {System ?? "None"}{(SystemInfo != null ? $" ({SystemInfo}{(PermitLocked ? ", permit required" : "")})" : "")}";
|
|
||||||
}
|
private static PipeServer<Ratsignal> RatsignalPipe
|
||||||
|
=> ratsignalPipe ??= new (
|
||||||
public override string ToString()
|
Log,
|
||||||
=> ShortInfo;
|
"RatAttack",
|
||||||
}
|
new PipeServer<Ratsignal>.SignalHandler(On_Ratsignal));
|
||||||
|
|
||||||
public class Ratsignal : IPipable
|
private static VoiceAttackLog Log => log ??= new (VA, "RatAttack");
|
||||||
{
|
|
||||||
public string Signal { get; set; }
|
private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
|
||||||
public bool Announce { get; set; }
|
|
||||||
private readonly char separator = '\x1F';
|
/*========================================\
|
||||||
|
| required VoiceAttack plugin shenanigans |
|
||||||
public Ratsignal()
|
\========================================*/
|
||||||
=> (Signal, Announce) = ("", false);
|
|
||||||
|
/// <summary>
|
||||||
public Ratsignal(string signal, bool announce)
|
/// The plugin’s GUID, as required by the VoiceAttack plugin API.
|
||||||
=> (Signal, Announce) = (signal, announce);
|
/// </summary>
|
||||||
|
/// <returns>The GUID.</returns>
|
||||||
public void ParseString(string serialization)
|
public static Guid VA_Id()
|
||||||
{
|
=> new ("{F2ADF0AE-4837-4E4A-9C87-8A7E2FA63E5F}");
|
||||||
try
|
|
||||||
{
|
/// <summary>
|
||||||
string[] parts = serialization.Split(separator);
|
/// The plugin’s display name, as required by the VoiceAttack plugin API.
|
||||||
Signal = parts[0];
|
/// </summary>
|
||||||
Announce = Boolean.Parse(parts[1]);
|
/// <returns>The display name.</returns>
|
||||||
}
|
public static string VA_DisplayName()
|
||||||
catch (Exception e)
|
=> $"RatAttack {VERSION}";
|
||||||
{
|
|
||||||
throw new ArgumentException($"Invalid serialized RATSIGNAL: '{serialization}'", e);
|
/// <summary>
|
||||||
}
|
/// The plugin’s description, as required by the VoiceAttack plugin API.
|
||||||
}
|
/// </summary>
|
||||||
|
/// <returns>The description.</returns>
|
||||||
public override string ToString()
|
public static string VA_DisplayInfo()
|
||||||
=> $"{Signal}{separator}{Announce}";
|
=> "RatAttack: a plugin to handle FuelRats cases.";
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
private static int ParseRatsignal(string ratsignal)
|
/// The Init method, as required by the VoiceAttack plugin API.
|
||||||
{
|
/// Runs when the plugin is initially loaded.
|
||||||
if (!RatsignalRegex.IsMatch(ratsignal))
|
/// </summary>
|
||||||
throw new ArgumentException($"Invalid RATSIGNAL format: '{ratsignal}'.", "ratsignal");
|
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
|
||||||
|
public static void VA_Init1(dynamic vaProxy)
|
||||||
Match match = RatsignalRegex.Match(ratsignal);
|
{
|
||||||
|
VA = vaProxy;
|
||||||
string cmdr = match.Groups["cmdr"].Value;
|
Log.Notice("Initializing …");
|
||||||
string? system = match.Groups["system"].Value;
|
VA.SetText("RatAttack.version", VERSION.ToString());
|
||||||
string? systemInfo = match.Groups["systemInfo"].Value;
|
vaProxy.ProfileChanged += new Action<Guid?, Guid?, string, string>(On_ProfileChanged);
|
||||||
bool permitLocked = match.Groups["permit"].Success;
|
Log.Notice("Init successful.");
|
||||||
string? permitName = match.Groups["permitName"].Value;
|
}
|
||||||
string platform = match.Groups["platform"].Value;
|
|
||||||
bool codeRed = match.Groups["oxygen"].Value == "NOT OK";
|
/// <summary>
|
||||||
|
/// The Invoke method, as required by the VoiceAttack plugin API.
|
||||||
int number = int.Parse(match.Groups["number"].Value);
|
/// Runs whenever a plugin context is invoked.
|
||||||
|
/// </summary>
|
||||||
Log.Debug($"New rat case: CMDR “{cmdr}” in “{system}”{(systemInfo != null ? $" ({systemInfo})" : "")} on {platform}, permit locked: {permitLocked}{(permitLocked && permitName != null ? $" (permit name: {permitName})" : "")}, code red: {codeRed} (#{number}).");
|
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
|
||||||
|
public static void VA_Invoke1(dynamic vaProxy)
|
||||||
CaseList[number] = new RatCase(cmdr, system, systemInfo, permitLocked, permitName, platform, codeRed, number);
|
{
|
||||||
|
string context = vaProxy.Context.ToLower();
|
||||||
return number;
|
Log.Debug($"Running context '{context}' …");
|
||||||
}
|
try
|
||||||
|
{
|
||||||
private static void On_Ratsignal(Ratsignal ratsignal)
|
switch (context)
|
||||||
{
|
{
|
||||||
try
|
case "getcasedata":
|
||||||
{
|
// plugin methods
|
||||||
int number = ParseRatsignal(ratsignal.Signal);
|
Context_GetCaseData(vaProxy);
|
||||||
Log.Notice($"New rat case: {CaseList[number]}.");
|
break;
|
||||||
Commands.TriggerEvent("RatAttack.incomingCase", parameters: new dynamic[] { new int[] { number }, new bool[] { ratsignal.Announce } });
|
case "parseratsignal":
|
||||||
}
|
Context_ParseRatsignal(vaProxy);
|
||||||
catch (ArgumentException e)
|
break;
|
||||||
{
|
case "startup":
|
||||||
Log.Error(e.Message);
|
Context_Startup(vaProxy);
|
||||||
Commands.TriggerEvent("RatAttack.invalidRatsignal", parameters: new dynamic[] { new string[] { ratsignal.Signal } });
|
break;
|
||||||
}
|
case "edsm.getnearestcmdr":
|
||||||
catch (Exception e)
|
// EDSM
|
||||||
{
|
Context_EDSM_GetNearestCMDR(vaProxy);
|
||||||
Log.Error($"Unhandled exception while parsing RATSIGNAL: '{e.Message}'.");
|
break;
|
||||||
}
|
case "log.log":
|
||||||
}
|
// log
|
||||||
|
Context_Log(vaProxy);
|
||||||
private static void On_ProfileChanged(Guid? from, Guid? to, string fromName, string toName)
|
break;
|
||||||
=> VA_Exit1(VA);
|
default:
|
||||||
|
// invalid
|
||||||
/*================\
|
Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
|
||||||
| plugin contexts |
|
break;
|
||||||
\================*/
|
}
|
||||||
|
}
|
||||||
private static void Context_EDSM_GetNearestCMDR(dynamic vaProxy)
|
catch (ArgumentNullException e)
|
||||||
{
|
{
|
||||||
int caseNo = vaProxy.GetInt("~caseNo") ?? throw new ArgumentNullException("~caseNo");
|
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
|
||||||
string cmdrList = vaProxy.GetText("~cmdrs") ?? throw new ArgumentNullException("~cmdrs");
|
}
|
||||||
string[] cmdrs = cmdrList.Split(';');
|
catch (Exception e)
|
||||||
if (cmdrs.Length == 0)
|
{
|
||||||
{
|
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
|
||||||
throw new ArgumentNullException("~cmdrs");
|
}
|
||||||
}
|
}
|
||||||
string system = CaseList[caseNo]?.System ?? throw new ArgumentException($"Case #{caseNo} has no system information", "~caseNo");
|
|
||||||
|
/// <summary>
|
||||||
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\Scripts\edsm-getnearest.exe";
|
/// The Exit method, as required by the VoiceAttack plugin API.
|
||||||
string arguments = $@"--short --text --system ""{system}"" ""{string.Join(@""" """, cmdrs)}""";
|
/// Runs when VoiceAttack is shut down.
|
||||||
|
/// </summary>
|
||||||
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "required by VoiceAttack plugin API")]
|
||||||
p.Start();
|
public static void VA_Exit1(dynamic vaProxy)
|
||||||
string stdout = p.StandardOutput.ReadToEnd();
|
{
|
||||||
string stderr = p.StandardError.ReadToEnd();
|
Log.Debug("Starting teardown …");
|
||||||
p.WaitForExit();
|
Log.Debug("Closing RATSIGNAL pipe …");
|
||||||
|
RatsignalPipe.Stop();
|
||||||
string message = stdout;
|
Log.Debug("Teardown finished.");
|
||||||
string? errorMessage = null;
|
}
|
||||||
bool error = true;
|
|
||||||
|
/// <summary>
|
||||||
switch (p.ExitCode)
|
/// The StopCommand method, as required by the VoiceAttack plugin API.
|
||||||
{
|
/// Runs whenever all commands are stopped using the “Stop All Commands”
|
||||||
case 0:
|
/// button or action.
|
||||||
error = false;
|
/// </summary>
|
||||||
Log.Info(message);
|
public static void VA_StopCommand()
|
||||||
break;
|
{
|
||||||
case 1: // CMDR not found, Server Error, Api Exception (jeez, what a mess did I make there?)
|
}
|
||||||
error = true;
|
|
||||||
Log.Error(message);
|
/// <summary>
|
||||||
break;
|
/// Parses a RATSIGNAL and extracts case data for storage.
|
||||||
case 2: // System not found
|
/// </summary>
|
||||||
error = true;
|
/// <param name="ratsignal">The incoming RATSIGNAL.</param>
|
||||||
Log.Warn(message);
|
/// <returns>The case number.</returns>
|
||||||
break;
|
/// <exception cref="ArgumentException">Thrown on invalid RATSIGNAL.</exception>
|
||||||
default:
|
private static int ParseRatsignal(string ratsignal)
|
||||||
error = true;
|
{
|
||||||
Log.Error(stderr);
|
if (!RatsignalRegex.IsMatch(ratsignal))
|
||||||
errorMessage = "Unrecoverable error in plugin.";
|
{
|
||||||
break;
|
throw new ArgumentException($"Invalid RATSIGNAL format: '{ratsignal}'.", "ratsignal");
|
||||||
|
}
|
||||||
}
|
|
||||||
|
Match match = RatsignalRegex.Match(ratsignal);
|
||||||
vaProxy.SetText("~message", message);
|
|
||||||
vaProxy.SetBoolean("~error", error);
|
string cmdr = match.Groups["cmdr"].Value;
|
||||||
vaProxy.SetText("~errorMessage", errorMessage);
|
string? language = match.Groups["language"].Value;
|
||||||
vaProxy.SetInt("~exitCode", p.ExitCode);
|
string? system = match.Groups["system"].Value;
|
||||||
}
|
string? systemInfo = match.Groups["systemInfo"].Value;
|
||||||
|
bool permitLocked = match.Groups["permit"].Success;
|
||||||
private static void Context_GetCaseData(dynamic vaProxy)
|
string? permitName = match.Groups["permitName"].Value;
|
||||||
{
|
string platform = match.Groups["platform"].Value;
|
||||||
int cn = vaProxy.GetInt("~caseNumber");
|
bool codeRed = match.Groups["oxygen"].Success;
|
||||||
|
string? mode = match.Groups["mode"].Value;
|
||||||
if (CaseList.ContainsKey(cn))
|
|
||||||
{
|
int number = int.Parse(match.Groups["number"].Value);
|
||||||
RatCase rc = CaseList[cn];
|
|
||||||
|
if (string.IsNullOrEmpty(system))
|
||||||
vaProxy.SetInt("~~caseNumber", rc.Number);
|
{
|
||||||
vaProxy.SetText("~~cmdr", rc.Cmdr);
|
system = "None";
|
||||||
vaProxy.SetText("~~system", rc?.System?.ToLower());
|
}
|
||||||
vaProxy.SetBoolean("~~permitLocked", rc?.PermitLocked);
|
|
||||||
vaProxy.SetText("~~permitName", rc?.PermitName);
|
Log.Debug($"New rat case: CMDR “{cmdr}” in “{system}”{(!string.IsNullOrEmpty(systemInfo) ? $" ({systemInfo})" : string.Empty)} on {platform}{(!string.IsNullOrEmpty(mode) ? $" ({mode})" : string.Empty)}, permit locked: {permitLocked}{(permitLocked && !string.IsNullOrEmpty(permitName) ? $" (permit name: {permitName})" : string.Empty)}, code red: {codeRed} (#{number}).");
|
||||||
vaProxy.SetText("~~platform", rc?.Platform);
|
|
||||||
vaProxy.SetBoolean("~~codeRed", rc?.CodeRed);
|
CaseList[number] = new RatCase(cmdr, language, system, systemInfo, permitLocked, permitName, platform, mode, codeRed, number);
|
||||||
}
|
|
||||||
else
|
return number;
|
||||||
{
|
}
|
||||||
Log.Warn($"Case #{cn} not found in the case list");
|
|
||||||
}
|
private static void On_Ratsignal(Ratsignal ratsignal)
|
||||||
}
|
{
|
||||||
|
try
|
||||||
private static void Context_Log(dynamic vaProxy)
|
{
|
||||||
{
|
int number = ParseRatsignal(ratsignal.Signal);
|
||||||
string message = vaProxy.GetText("~message");
|
Log.Notice($"New rat case: {CaseList[number]}.");
|
||||||
string level = vaProxy.GetText("~level");
|
Commands.TriggerEvent("RatAttack.incomingCase", parameters: new dynamic[] { new int[] { number }, new bool[] { ratsignal.Announce } });
|
||||||
|
}
|
||||||
if (level == null)
|
catch (ArgumentException e)
|
||||||
{
|
{
|
||||||
Log.Log(message);
|
Log.Error(e.Message);
|
||||||
}
|
Commands.TriggerEvent("RatAttack.invalidRatsignal", parameters: new dynamic[] { new string[] { ratsignal.Signal } });
|
||||||
else
|
}
|
||||||
{
|
catch (Exception e)
|
||||||
try
|
{
|
||||||
{
|
Log.Error($"Unhandled exception while parsing RATSIGNAL: '{e.Message}'.");
|
||||||
Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper()));
|
}
|
||||||
}
|
}
|
||||||
catch (ArgumentNullException) { throw; }
|
|
||||||
catch (ArgumentException)
|
private static void On_ProfileChanged(Guid? from, Guid? to, string fromName, string toName)
|
||||||
{
|
=> VA_Exit1(VA);
|
||||||
Log.Error($"Invalid log level '{level}'.");
|
|
||||||
}
|
/*================\
|
||||||
}
|
| plugin contexts |
|
||||||
}
|
\================*/
|
||||||
|
|
||||||
private static void Context_Startup(dynamic vaProxy)
|
#pragma warning disable IDE0060 // Remove unused parameter
|
||||||
{
|
private static void Context_EDSM_GetNearestCMDR(dynamic vaProxy)
|
||||||
Log.Notice("Starting up …");
|
{
|
||||||
VA = vaProxy;
|
int caseNo = vaProxy.GetInt("~caseNo") ?? throw new ArgumentNullException("~caseNo");
|
||||||
_ = RatsignalPipe.Run();
|
string cmdrList = vaProxy.GetText("~cmdrs") ?? throw new ArgumentNullException("~cmdrs");
|
||||||
Log.Notice("Finished startup.");
|
string[] cmdrs = cmdrList.Split(';');
|
||||||
}
|
if (cmdrs.Length == 0)
|
||||||
|
{
|
||||||
private static void Context_ParseRatsignal(dynamic vaProxy)
|
throw new ArgumentNullException("~cmdrs");
|
||||||
{
|
}
|
||||||
Log.Warn("Passing a RATSIGNAL from VoiceAttack (through the clipboard or a file) is DEPRECATED and will no longer be supported in the future.");
|
|
||||||
On_Ratsignal(new Ratsignal(vaProxy.GetText("~ratsignal"), vaProxy.GetBoolean("~announceRatsignal")));
|
string system = CaseList[caseNo]?.System ?? throw new ArgumentException($"Case #{caseNo} has no system information", "~caseNo");
|
||||||
}
|
|
||||||
|
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\Scripts\edsm-getnearest.exe";
|
||||||
/*========================================\
|
string arguments = $@"--short --text --system ""{system}"" ""{string.Join(@""" """, cmdrs)}""";
|
||||||
| required VoiceAttack plugin shenanigans |
|
|
||||||
\========================================*/
|
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
||||||
|
|
||||||
static readonly Version VERSION = new Version("6.0.0");
|
p.Start();
|
||||||
|
string stdout = p.StandardOutput.ReadToEnd();
|
||||||
public static Guid VA_Id()
|
string stderr = p.StandardError.ReadToEnd();
|
||||||
=> new Guid("{F2ADF0AE-4837-4E4A-9C87-8A7E2FA63E5F}");
|
p.WaitForExit();
|
||||||
public static string VA_DisplayName()
|
|
||||||
=> $"RatAttack {VERSION}";
|
string message = stdout;
|
||||||
public static string VA_DisplayInfo()
|
string? errorMessage = null;
|
||||||
=> "RatAttack: a plugin to handle FuelRats cases.";
|
bool error;
|
||||||
|
|
||||||
public static void VA_Init1(dynamic vaProxy)
|
switch (p.ExitCode)
|
||||||
{
|
{
|
||||||
VA = vaProxy;
|
case 0:
|
||||||
Log.Notice("Initializing …");
|
error = false;
|
||||||
VA.SetText("RatAttack.version", VERSION.ToString());
|
Log.Info(message);
|
||||||
vaProxy.ProfileChanged += new Action<Guid?, Guid?, String, String>(On_ProfileChanged);
|
break;
|
||||||
Log.Notice("Init successful.");
|
case 1: // CMDR not found, Server Error, Api Exception (jeez, what a mess did I make there?)
|
||||||
}
|
error = true;
|
||||||
|
Log.Error(message);
|
||||||
public static void VA_Invoke1(dynamic vaProxy)
|
break;
|
||||||
{
|
case 2: // System not found
|
||||||
string context = vaProxy.Context.ToLower();
|
error = true;
|
||||||
Log.Debug($"Running context '{context}' …");
|
Log.Warn(message);
|
||||||
try
|
break;
|
||||||
{
|
default:
|
||||||
switch (context)
|
error = true;
|
||||||
{
|
Log.Error(stderr);
|
||||||
// plugin methods
|
errorMessage = "Unrecoverable error in plugin.";
|
||||||
case "getcasedata":
|
break;
|
||||||
Context_GetCaseData(vaProxy);
|
}
|
||||||
break;
|
|
||||||
case "parseratsignal":
|
vaProxy.SetText("~message", message);
|
||||||
Context_ParseRatsignal(vaProxy);
|
vaProxy.SetBoolean("~error", error);
|
||||||
break;
|
vaProxy.SetText("~errorMessage", errorMessage);
|
||||||
case "startup":
|
vaProxy.SetInt("~exitCode", p.ExitCode);
|
||||||
Context_Startup(vaProxy);
|
}
|
||||||
break;
|
|
||||||
// EDSM
|
private static void Context_GetCaseData(dynamic vaProxy)
|
||||||
case "edsm.getnearestcmdr":
|
{
|
||||||
Context_EDSM_GetNearestCMDR(vaProxy);
|
int cn = vaProxy.GetInt("~caseNumber");
|
||||||
break;
|
|
||||||
// log
|
if (CaseList.ContainsKey(cn))
|
||||||
case "log.log":
|
{
|
||||||
Context_Log(vaProxy);
|
RatCase rc = CaseList[cn];
|
||||||
break;
|
|
||||||
// invalid
|
vaProxy.SetInt("~~caseNumber", rc.Number);
|
||||||
default:
|
vaProxy.SetText("~~cmdr", rc.Cmdr);
|
||||||
Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
|
vaProxy.SetText("~~system", rc?.System?.ToLower());
|
||||||
break;
|
vaProxy.SetText("~~systemInfo", rc?.SystemInfo);
|
||||||
}
|
vaProxy.SetBoolean("~~permitLocked", rc?.PermitLocked);
|
||||||
}
|
vaProxy.SetText("~~permitName", rc?.PermitName);
|
||||||
catch (ArgumentNullException e)
|
vaProxy.SetText("~~platform", rc?.Platform);
|
||||||
{
|
vaProxy.SetText("~~mode", rc?.Mode);
|
||||||
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
|
vaProxy.SetBoolean("~~codeRed", rc?.CodeRed);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
else
|
||||||
{
|
{
|
||||||
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
|
Log.Warn($"Case #{cn} not found in the case list");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void VA_Exit1(dynamic vaProxy)
|
private static void Context_Log(dynamic vaProxy)
|
||||||
{
|
{
|
||||||
Log.Debug("Starting teardown …");
|
string message = vaProxy.GetText("~message");
|
||||||
Log.Debug("Closing RATSIGNAL pipe …");
|
string level = vaProxy.GetText("~level");
|
||||||
RatsignalPipe.Stop();
|
|
||||||
Log.Debug("Teardown finished.");
|
if (level == null)
|
||||||
}
|
{
|
||||||
|
Log.Log(message);
|
||||||
public static void VA_StopCommand() { }
|
}
|
||||||
}
|
else
|
||||||
}
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper()));
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
Log.Error($"Invalid log level '{level}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Context_Startup(dynamic vaProxy)
|
||||||
|
{
|
||||||
|
Log.Notice("Starting up …");
|
||||||
|
_ = RatsignalPipe.Run();
|
||||||
|
Log.Notice("Finished startup.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Context_ParseRatsignal(dynamic vaProxy)
|
||||||
|
{
|
||||||
|
Log.Warn("Passing a RATSIGNAL to VoiceAttack through the clipboard or a file is DEPRECATED and will no longer be supported in the future.");
|
||||||
|
On_Ratsignal(new Ratsignal(vaProxy.GetText("~ratsignal"), vaProxy.GetBoolean("~announceRatsignal") ?? false));
|
||||||
|
}
|
||||||
|
#pragma warning restore IDE0060 // Remove unused parameter
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encapsulates a RATSIGNAL for sending between the CLI helper tool and
|
||||||
|
/// the plugin via named pipe.
|
||||||
|
/// </summary>
|
||||||
|
public class Ratsignal : IPipable
|
||||||
|
{
|
||||||
|
private readonly char separator = '\x1F';
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Ratsignal"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public Ratsignal()
|
||||||
|
=> (this.Signal, this.Announce) = (string.Empty, false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Ratsignal"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="signal">The RATSIGNAL.</param>
|
||||||
|
/// <param name="announce">Whether or not to announce the new case.</param>
|
||||||
|
public Ratsignal(string signal, bool announce)
|
||||||
|
=> (this.Signal, this.Announce) = (signal, announce);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the RATSIGNAL.
|
||||||
|
/// </summary>
|
||||||
|
public string Signal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or Sets a value indicating whether to announce the incoming
|
||||||
|
/// case.
|
||||||
|
/// </summary>
|
||||||
|
public bool Announce { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the <see cref="Ratsignal"/> instance from a
|
||||||
|
/// serialized representation.
|
||||||
|
/// FIXXME: should probably make this a static factory method.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serialization">The serialized <see cref="Ratsignal"/>.</param>
|
||||||
|
/// <exception cref="ArgumentException">Thrown on receiving an invalid signal.</exception>
|
||||||
|
public void ParseString(string serialization)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] parts = serialization.Split(this.separator);
|
||||||
|
this.Signal = parts[0];
|
||||||
|
this.Announce = bool.Parse(parts[1]);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Invalid serialized RATSIGNAL: '{serialization}'", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override string ToString()
|
||||||
|
=> $"{this.Signal}{this.separator}{this.Announce}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RatCase
|
||||||
|
{
|
||||||
|
public RatCase(string cmdr, string? language, string? system, string? systemInfo, bool permitLocked, string? permitName, string platform, string mode, bool codeRed, int number)
|
||||||
|
=> (this.Cmdr, this.Language, this.System, this.SystemInfo, this.PermitLocked, this.PermitName, this.Platform, this.Mode, this.CodeRed, this.Number)
|
||||||
|
= (cmdr, language, system, systemInfo, permitLocked, permitName, platform, mode, codeRed, number);
|
||||||
|
|
||||||
|
public string Cmdr { get; }
|
||||||
|
|
||||||
|
public string? Language { get; }
|
||||||
|
|
||||||
|
public string? System { get; }
|
||||||
|
|
||||||
|
public string? SystemInfo { get; }
|
||||||
|
|
||||||
|
public bool PermitLocked { get; }
|
||||||
|
|
||||||
|
public string? PermitName { get; }
|
||||||
|
|
||||||
|
public string Platform { get; }
|
||||||
|
|
||||||
|
public string? Mode { get; }
|
||||||
|
|
||||||
|
public bool CodeRed { get; }
|
||||||
|
|
||||||
|
public int Number { get; }
|
||||||
|
|
||||||
|
public string ShortInfo
|
||||||
|
{
|
||||||
|
get => $"#{this.Number}, {this.Platform}{(!string.IsNullOrEmpty(this.Mode) ? $" ({this.Mode})" : string.Empty)}{(this.CodeRed ? ", code red" : string.Empty)}, {this.System ?? "None"}{(!string.IsNullOrEmpty(this.SystemInfo) ? $" ({this.SystemInfo}{(this.PermitLocked ? ", permit required" : string.Empty)})" : string.Empty)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
=> this.ShortInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<LangVersion>8.0</LangVersion>
|
<DocumentationFile>..\build\alterNERDtive\RatAttack.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<LangVersion>8.0</LangVersion>
|
<DocumentationFile>..\build\alterNERDtive\RatAttack.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
|
|
@ -1,4 +1,23 @@
|
||||||
using System.Reflection;
|
// <copyright file="AssemblyInfo.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
|
@ -1,84 +1,204 @@
|
||||||
#nullable enable
|
// <copyright file="SpanshAttack.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
using alterNERDtive.util;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
using alterNERDtive.edts;
|
||||||
|
using alterNERDtive.util;
|
||||||
|
|
||||||
namespace SpanshAttack
|
namespace SpanshAttack
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// VoiceAttack plugin for the SpanshAttack profile.
|
||||||
|
/// </summary>
|
||||||
public class SpanshAttack
|
public class SpanshAttack
|
||||||
{
|
{
|
||||||
|
private static readonly Version VERSION = new ("7.2.2");
|
||||||
|
|
||||||
|
private static VoiceAttackLog? log;
|
||||||
|
private static VoiceAttackCommands? commands;
|
||||||
|
|
||||||
private static dynamic? VA { get; set; }
|
private static dynamic? VA { get; set; }
|
||||||
|
|
||||||
private static VoiceAttackLog Log
|
private static VoiceAttackLog Log => log ??= new (VA, "SpanshAttack");
|
||||||
=> log ??= new VoiceAttackLog(VA, "SpanshAttack");
|
|
||||||
private static VoiceAttackLog? log;
|
|
||||||
|
|
||||||
private static VoiceAttackCommands Commands
|
private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
|
||||||
=> commands ??= new VoiceAttackCommands(VA, Log);
|
|
||||||
private static VoiceAttackCommands? commands;
|
/*========================================\
|
||||||
|
| required VoiceAttack plugin shenanigans |
|
||||||
|
\========================================*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The plugin’s GUID, as required by the VoiceAttack plugin API.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The GUID.</returns>
|
||||||
|
public static Guid VA_Id()
|
||||||
|
=> new ("{e722b29d-898e-47dd-a843-a409c87e0bd8}");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The plugin’s display name, as required by the VoiceAttack plugin API.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The display name.</returns>
|
||||||
|
public static string VA_DisplayName()
|
||||||
|
=> $"SpanshAttack {VERSION}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The plugin’s description, as required by the VoiceAttack plugin API.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The description.</returns>
|
||||||
|
public static string VA_DisplayInfo()
|
||||||
|
=> "SpanshAttack: a plugin for doing routing with spansh.co.uk for Elite: Dangerous.";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Init method, as required by the VoiceAttack plugin API.
|
||||||
|
/// Runs when the plugin is initially loaded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
|
||||||
|
public static void VA_Init1(dynamic vaProxy)
|
||||||
|
{
|
||||||
|
VA = vaProxy;
|
||||||
|
Log.Notice("Initializing …");
|
||||||
|
VA.SetText("SpanshAttack.version", VERSION.ToString());
|
||||||
|
Log.Notice("Init successful.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Invoke method, as required by the VoiceAttack plugin API.
|
||||||
|
/// Runs whenever a plugin context is invoked.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
|
||||||
|
public static void VA_Invoke1(dynamic vaProxy)
|
||||||
|
{
|
||||||
|
string context = vaProxy.Context.ToLower();
|
||||||
|
Log.Debug($"Running context '{context}' …");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (context)
|
||||||
|
{
|
||||||
|
case "startup":
|
||||||
|
Context_Startup(vaProxy);
|
||||||
|
break;
|
||||||
|
case "edts.getcoordinates":
|
||||||
|
// EDTS
|
||||||
|
Context_EDTS_GetCoordinates(vaProxy);
|
||||||
|
break;
|
||||||
|
case "log.log":
|
||||||
|
// log
|
||||||
|
Context_Log(vaProxy);
|
||||||
|
break;
|
||||||
|
case "spansh.systemexists":
|
||||||
|
// Spansh
|
||||||
|
Context_Spansh_SytemExists(vaProxy);
|
||||||
|
break;
|
||||||
|
case "spansh.nearestsystem":
|
||||||
|
Context_Spansh_Nearestsystem(vaProxy);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// invalid
|
||||||
|
Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException e)
|
||||||
|
{
|
||||||
|
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Exit method, as required by the VoiceAttack plugin API.
|
||||||
|
/// Runs when VoiceAttack is shut down.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "required by VoiceAttack plugin API")]
|
||||||
|
public static void VA_Exit1(dynamic vaProxy)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The StopCommand method, as required by the VoiceAttack plugin API.
|
||||||
|
/// Runs whenever all commands are stopped using the “Stop All Commands”
|
||||||
|
/// button or action.
|
||||||
|
/// </summary>
|
||||||
|
public static void VA_StopCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/*================\
|
/*================\
|
||||||
| plugin contexts |
|
| plugin contexts |
|
||||||
\================*/
|
\================*/
|
||||||
|
|
||||||
|
#pragma warning disable IDE0060 // Remove unused parameter
|
||||||
private static void Context_EDTS_GetCoordinates(dynamic vaProxy)
|
private static void Context_EDTS_GetCoordinates(dynamic vaProxy)
|
||||||
{
|
{
|
||||||
string system = vaProxy.GetText("~system") ?? throw new ArgumentNullException("~system");
|
string name = vaProxy.GetText("~system") ?? throw new ArgumentNullException("~system");
|
||||||
|
|
||||||
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\Scripts\edts.exe";
|
bool success = false;
|
||||||
string arguments = $@"coords ""{system}""";
|
string? errorType = null;
|
||||||
|
string? errorMessage = null;
|
||||||
|
|
||||||
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
try
|
||||||
|
|
||||||
Dictionary<char, int> coords = new Dictionary<char, int> { { 'x', 0 }, { 'y', 0 }, { 'z', 0 } };
|
|
||||||
int precision = 0;
|
|
||||||
bool error = false;
|
|
||||||
string errorMessage = "";
|
|
||||||
|
|
||||||
p.Start();
|
|
||||||
string stdout = p.StandardOutput.ReadToEnd();
|
|
||||||
string stderr = p.StandardError.ReadToEnd();
|
|
||||||
p.WaitForExit();
|
|
||||||
switch (p.ExitCode)
|
|
||||||
{
|
{
|
||||||
case 0:
|
StarSystem system = EdtsApi.GetCoordinates(name);
|
||||||
string[] stdoutExploded = stdout.Split('|');
|
|
||||||
precision = int.Parse(stdoutExploded[1]);
|
|
||||||
string[] stdoutCoords = stdoutExploded[0].Split(',');
|
|
||||||
coords['x'] = int.Parse(stdoutCoords[0]);
|
|
||||||
coords['y'] = int.Parse(stdoutCoords[1]);
|
|
||||||
coords['z'] = int.Parse(stdoutCoords[2]);
|
|
||||||
if (precision < 100)
|
|
||||||
{
|
|
||||||
Log.Info($"Coordinates for {system}: ({coords['x']}, {coords['y']}, {coords['z']}), precision: {precision} ly");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Warn($"Coordinates with low precision for {system}: ({coords['x']}, {coords['y']}, {coords['z']}), precision: {precision} ly");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
errorMessage = $@"No coordinates could be determined for ""{system}"" with acceptable precision";
|
|
||||||
Log.Error(errorMessage);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
errorMessage = $@"""{system}"" is not a valied proc gen system name";
|
|
||||||
Log.Error(errorMessage);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
if (system.Coords.Precision < 100)
|
||||||
|
{
|
||||||
|
Log.Info($@"Coordinates for ""{name}"": ({system.Coords.X}, {system.Coords.Y}, {system.Coords.Z}), precision: {system.Coords.Precision} ly");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Warn($@"Coordinates with low precision for ""{name}"": ({system.Coords.X}, {system.Coords.Y}, {system.Coords.Z}), precision: {system.Coords.Precision} ly");
|
||||||
|
}
|
||||||
|
|
||||||
|
vaProxy.SetInt("~x", system.Coords.X);
|
||||||
|
vaProxy.SetInt("~y", system.Coords.Y);
|
||||||
|
vaProxy.SetInt("~z", system.Coords.Z);
|
||||||
|
vaProxy.SetInt("~precision", system.Coords.Precision);
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
catch (ArgumentException e)
|
||||||
|
{
|
||||||
|
errorType = "invalid name";
|
||||||
|
errorMessage = e.Message;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
errorType = "connection error";
|
||||||
|
errorMessage = e.Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
vaProxy.SetInt("~x", coords['x']);
|
vaProxy.SetBoolean("~success", success);
|
||||||
vaProxy.SetInt("~y", coords['y']);
|
if (!string.IsNullOrWhiteSpace(errorType))
|
||||||
vaProxy.SetInt("~z", coords['z']);
|
{
|
||||||
vaProxy.SetInt("~precision", precision);
|
Log.Error(errorMessage!);
|
||||||
vaProxy.SetBoolean("~error", error);
|
vaProxy.SetText("~errorType", errorType);
|
||||||
vaProxy.SetText("~errorMessage", errorMessage);
|
vaProxy.SetText("~errorMessage", errorMessage);
|
||||||
vaProxy.SetInt("~exitCode", p.ExitCode);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Context_Log(dynamic vaProxy)
|
private static void Context_Log(dynamic vaProxy)
|
||||||
|
@ -96,7 +216,10 @@ namespace SpanshAttack
|
||||||
{
|
{
|
||||||
Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper()));
|
Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper()));
|
||||||
}
|
}
|
||||||
catch (ArgumentNullException) { throw; }
|
catch (ArgumentNullException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
catch (ArgumentException)
|
catch (ArgumentException)
|
||||||
{
|
{
|
||||||
Log.Error($"Invalid log level '{level}'.");
|
Log.Error($"Invalid log level '{level}'.");
|
||||||
|
@ -115,11 +238,11 @@ namespace SpanshAttack
|
||||||
|
|
||||||
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
||||||
|
|
||||||
Dictionary<char, decimal> coords = new Dictionary<char, decimal> { { 'x', 0 }, { 'y', 0 }, { 'z', 0 } };
|
Dictionary<char, decimal> coords = new () { { 'x', 0 }, { 'y', 0 }, { 'z', 0 } };
|
||||||
string system = "";
|
string system = string.Empty;
|
||||||
decimal distance = 0;
|
decimal distance = 0;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
string errorMessage = "";
|
string errorMessage = string.Empty;
|
||||||
|
|
||||||
p.Start();
|
p.Start();
|
||||||
string stdout = p.StandardOutput.ReadToEnd();
|
string stdout = p.StandardOutput.ReadToEnd();
|
||||||
|
@ -170,7 +293,7 @@ namespace SpanshAttack
|
||||||
|
|
||||||
bool exists = true;
|
bool exists = true;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
string errorMessage = "";
|
string errorMessage = string.Empty;
|
||||||
|
|
||||||
p.Start();
|
p.Start();
|
||||||
string stdout = p.StandardOutput.ReadToEnd();
|
string stdout = p.StandardOutput.ReadToEnd();
|
||||||
|
@ -206,75 +329,8 @@ namespace SpanshAttack
|
||||||
private static void Context_Startup(dynamic vaProxy)
|
private static void Context_Startup(dynamic vaProxy)
|
||||||
{
|
{
|
||||||
Log.Notice("Starting up …");
|
Log.Notice("Starting up …");
|
||||||
VA = vaProxy;
|
|
||||||
Log.Notice("Finished startup.");
|
Log.Notice("Finished startup.");
|
||||||
}
|
}
|
||||||
|
#pragma warning restore IDE0060 // Remove unused parameter
|
||||||
/*========================================\
|
|
||||||
| required VoiceAttack plugin shenanigans |
|
|
||||||
\========================================*/
|
|
||||||
|
|
||||||
static readonly Version VERSION = new Version("7.0.1");
|
|
||||||
|
|
||||||
public static Guid VA_Id()
|
|
||||||
=> new Guid("{e722b29d-898e-47dd-a843-a409c87e0bd8}");
|
|
||||||
public static string VA_DisplayName()
|
|
||||||
=> $"SpanshAttack {VERSION}";
|
|
||||||
public static string VA_DisplayInfo()
|
|
||||||
=> "SpanshAttack: a plugin for doing routing with spansh.co.uk for Elite: Dangerous.";
|
|
||||||
|
|
||||||
public static void VA_Init1(dynamic vaProxy)
|
|
||||||
{
|
|
||||||
VA = vaProxy;
|
|
||||||
Log.Notice("Initializing …");
|
|
||||||
VA.SetText("SpanshAttack.version", VERSION.ToString());
|
|
||||||
Log.Notice("Init successful.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void VA_Invoke1(dynamic vaProxy)
|
|
||||||
{
|
|
||||||
string context = vaProxy.Context.ToLower();
|
|
||||||
Log.Debug($"Running context '{context}' …");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (context)
|
|
||||||
{
|
|
||||||
case "startup":
|
|
||||||
Context_Startup(vaProxy);
|
|
||||||
break;
|
|
||||||
// EDTS
|
|
||||||
case "edts.getcoordinates":
|
|
||||||
Context_EDTS_GetCoordinates(vaProxy);
|
|
||||||
break;
|
|
||||||
// log
|
|
||||||
case "log.log":
|
|
||||||
Context_Log(vaProxy);
|
|
||||||
break;
|
|
||||||
// Spansh
|
|
||||||
case "spansh.systemexists":
|
|
||||||
Context_Spansh_SytemExists(vaProxy);
|
|
||||||
break;
|
|
||||||
case "spansh.nearestsystem":
|
|
||||||
Context_Spansh_Nearestsystem(vaProxy);
|
|
||||||
break;
|
|
||||||
// invalid
|
|
||||||
default:
|
|
||||||
Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (ArgumentNullException e)
|
|
||||||
{
|
|
||||||
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void VA_Exit1(dynamic vaProxy) { }
|
|
||||||
|
|
||||||
public static void VA_StopCommand() { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<LangVersion>8.0</LangVersion>
|
<DocumentationFile>..\build\alterNERDtive\SpanshAttack.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<LangVersion>8.0</LangVersion>
|
<DocumentationFile>..\build\alterNERDtive\SpanshAttack.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
|
28
plugins/VoiceAttack-base/GlobalSuppressions.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// <copyright file="GlobalSuppressions.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
// This file is used by Code Analysis to maintain SuppressMessage
|
||||||
|
// attributes that are applied to this project.
|
||||||
|
// Project-level suppressions either have no target or are given
|
||||||
|
// a specific target and scoped to a namespace, type, member, etc.
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "just cause", Scope = "namespace", Target = "~N:alterNERDtive")]
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "just cause", Scope = "namespace", Target = "~N:alterNERDtive.edts")]
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "just cause", Scope = "namespace", Target = "~N:alterNERDtive.util")]
|
|
@ -1,4 +1,23 @@
|
||||||
using System.Reflection;
|
// <copyright file="AssemblyInfo.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
@ -10,7 +29,7 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("VoiceAttack-base")]
|
[assembly: AssemblyProduct("VoiceAttack-base")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
[assembly: AssemblyCopyright("Copyright © 2020–2022")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
|
25
plugins/VoiceAttack-base/SettingsDialog.xaml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<UserControl x:Class="alterNERDtive.SettingsDialog"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="clr-namespace:alterNERDtive"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<Grid>
|
||||||
|
<StackPanel>
|
||||||
|
<TabControl Name="tabs">
|
||||||
|
<TabItem Name="general" Header="general"></TabItem>
|
||||||
|
<TabItem Name="EliteAttack" Header="EliteAttack"></TabItem>
|
||||||
|
<TabItem Name="RatAttack" Header="RatAttack"></TabItem>
|
||||||
|
<TabItem Name="SpanshAttack" Header="SpanshAttack"></TabItem>
|
||||||
|
<TabItem Name="StreamAttack" Header="StreamAttack"></TabItem>
|
||||||
|
</TabControl>
|
||||||
|
<WrapPanel VerticalAlignment="Bottom" HorizontalAlignment="Right">
|
||||||
|
<Button Name="applyButton" Click="ApplyButton_Click" Padding="5" Margin="5" Width="100">Apply</Button>
|
||||||
|
<Button Name="okButton" Click="OkButton_Click" Padding="5" Margin="5" Width="100">Done</Button>
|
||||||
|
<Button Name="cancelButton" Click="CancelButton_Click" Padding="5" Margin="5" Width="100">Cancel</Button>
|
||||||
|
</WrapPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
188
plugins/VoiceAttack-base/SettingsDialog.xaml.cs
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
// <copyright file="SettingsDialog.xaml.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
namespace alterNERDtive
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for SettingsDialog.xaml.
|
||||||
|
/// </summary>
|
||||||
|
public partial class SettingsDialog : UserControl
|
||||||
|
{
|
||||||
|
private readonly List<Setting> values = new List<Setting>();
|
||||||
|
private util.Configuration config;
|
||||||
|
private util.VoiceAttackLog log;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SettingsDialog"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config">The plugin Configuration.</param>
|
||||||
|
/// <param name="log">The plugin Log.</param>
|
||||||
|
public SettingsDialog(util.Configuration config, util.VoiceAttackLog log)
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
|
||||||
|
this.config = config;
|
||||||
|
this.log = log;
|
||||||
|
|
||||||
|
foreach (TabItem tab in this.tabs.Items)
|
||||||
|
{
|
||||||
|
string profile = tab.Name;
|
||||||
|
if (profile == "general")
|
||||||
|
{
|
||||||
|
profile = "alterNERDtive-base";
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.IsEnabled = BasePlugin.IsProfileActive(profile);
|
||||||
|
|
||||||
|
StackPanel panel = new StackPanel();
|
||||||
|
util.Configuration.OptDict<string, util.Configuration.Option> options = util.Configuration.GetOptions(profile);
|
||||||
|
|
||||||
|
foreach (dynamic option in options.Values)
|
||||||
|
{
|
||||||
|
dynamic value = config.GetConfig(profile, option.Name);
|
||||||
|
|
||||||
|
if (option is util.Configuration.Option<bool>)
|
||||||
|
{
|
||||||
|
WrapPanel row = new WrapPanel();
|
||||||
|
|
||||||
|
CheckBox checkBox = new CheckBox();
|
||||||
|
checkBox.IsChecked = value;
|
||||||
|
checkBox.VerticalAlignment = VerticalAlignment.Center;
|
||||||
|
row.Children.Add(checkBox);
|
||||||
|
this.values.Add(new Setting(profile, option, value, checkBox));
|
||||||
|
|
||||||
|
Label label = new Label();
|
||||||
|
label.Content = option.Description;
|
||||||
|
row.Children.Add(label);
|
||||||
|
|
||||||
|
panel.Children.Add(row);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StackPanel row = new StackPanel();
|
||||||
|
|
||||||
|
Label label = new Label();
|
||||||
|
label.Content = option.Description;
|
||||||
|
row.Children.Add(label);
|
||||||
|
|
||||||
|
TextBox input = new TextBox();
|
||||||
|
input.Text = value.ToString();
|
||||||
|
row.Children.Add(input);
|
||||||
|
this.values.Add(new Setting(profile, option, value, input));
|
||||||
|
|
||||||
|
panel.Children.Add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.Content = panel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ApplySettings()
|
||||||
|
{
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
foreach (Setting setting in this.values)
|
||||||
|
{
|
||||||
|
dynamic? state = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (setting.Option is util.Configuration.Option<bool>)
|
||||||
|
{
|
||||||
|
state = ((CheckBox)setting.UiElement).IsChecked ?? false;
|
||||||
|
}
|
||||||
|
else if (setting.Option is util.Configuration.Option<DateTime>)
|
||||||
|
{
|
||||||
|
state = DateTime.Parse(((TextBox)setting.UiElement).Text);
|
||||||
|
}
|
||||||
|
else if (setting.Option is util.Configuration.Option<decimal>)
|
||||||
|
{
|
||||||
|
state = decimal.Parse(((TextBox)setting.UiElement).Text);
|
||||||
|
}
|
||||||
|
else if (setting.Option is util.Configuration.Option<int>)
|
||||||
|
{
|
||||||
|
state = int.Parse(((TextBox)setting.UiElement).Text);
|
||||||
|
}
|
||||||
|
else if (setting.Option is util.Configuration.Option<short>)
|
||||||
|
{
|
||||||
|
state = short.Parse(((TextBox)setting.UiElement).Text);
|
||||||
|
}
|
||||||
|
else if (setting.Option is util.Configuration.Option<string>)
|
||||||
|
{
|
||||||
|
state = ((TextBox)setting.UiElement).Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state != setting.Value)
|
||||||
|
{
|
||||||
|
this.log.Log($@"Configuration changed via settings dialog: ""{setting.Profile}.{setting.Option.Name}"" → ""{state}""", util.LogLevel.DEBUG);
|
||||||
|
this.config.SetConfig(setting.Profile, setting.Option.Name, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) when (e is ArgumentNullException || e is FormatException || e is OverflowException)
|
||||||
|
{
|
||||||
|
this.log.Log($@"Invalid value for ""{setting.Profile}.{setting.Option.Name}"": ""{((TextBox)setting.UiElement).Text}""", util.LogLevel.ERROR);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Window.GetWindow(this).Close();
|
||||||
|
this.log.Log("Settings dialog cancelled.", util.LogLevel.DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OkButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (this.ApplySettings())
|
||||||
|
{
|
||||||
|
Window.GetWindow(this).Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyButton_Click(object sender, RoutedEventArgs reeargs)
|
||||||
|
{
|
||||||
|
this.ApplySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct Setting
|
||||||
|
{
|
||||||
|
public Setting(string profile, dynamic option, dynamic value, dynamic uiElement)
|
||||||
|
=> (this.Profile, this.Option, this.Value, this.UiElement) = (profile, option, value, uiElement);
|
||||||
|
|
||||||
|
public string Profile { get; }
|
||||||
|
|
||||||
|
public dynamic Option { get; }
|
||||||
|
|
||||||
|
public dynamic Value { get; }
|
||||||
|
|
||||||
|
public dynamic UiElement { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,7 @@
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<LangVersion>8.0</LangVersion>
|
<DocumentationFile>..\build\alterNERDtive\base.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
|
@ -33,22 +33,50 @@
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<LangVersion>8.0</LangVersion>
|
<DocumentationFile>..\build\alterNERDtive\base.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="PresentationCore" />
|
||||||
|
<Reference Include="PresentationFramework" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Numerics" />
|
||||||
|
<Reference Include="System.Xaml" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="WindowsBase" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="base.cs" />
|
<Compile Include="base.cs" />
|
||||||
|
<Compile Include="edts.cs">
|
||||||
|
<ExcludeFromStyleCop>true</ExcludeFromStyleCop>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="GlobalSuppressions.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="SettingsDialog.xaml.cs">
|
||||||
|
<DependentUpon>SettingsDialog.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="util.cs" />
|
<Compile Include="util.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Include="SettingsDialog.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNet.WebApi.Client">
|
||||||
|
<Version>5.2.9</Version>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Newtonsoft.Json">
|
||||||
|
<Version>13.0.1</Version>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="System.Net.Http">
|
||||||
|
<Version>4.3.4</Version>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
81
plugins/VoiceAttack-base/edts.cs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
// <auto-generated/>
|
||||||
|
// Not really, but this file will not bow to StyleCop tyranny.
|
||||||
|
// Why? Because it will be obsolete mid term anyway ;)
|
||||||
|
|
||||||
|
// <copyright file="edts.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2019–2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
|
||||||
|
namespace alterNERDtive.edts
|
||||||
|
{
|
||||||
|
|
||||||
|
public struct StarSystem
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public Position Coords { get; set; }
|
||||||
|
}
|
||||||
|
public struct Position
|
||||||
|
{
|
||||||
|
public int X { get; set; }
|
||||||
|
public int Y { get; set; }
|
||||||
|
public int Z { get; set; }
|
||||||
|
public int Precision { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EdtsApi
|
||||||
|
{
|
||||||
|
private static readonly string APIURL = "http://edts.thargoid.space/api/v1/";
|
||||||
|
private static HttpClient ApiClient;
|
||||||
|
|
||||||
|
static EdtsApi()
|
||||||
|
{
|
||||||
|
ApiClient = new HttpClient
|
||||||
|
{
|
||||||
|
BaseAddress = new Uri(APIURL)
|
||||||
|
};
|
||||||
|
ApiClient.DefaultRequestHeaders.Accept.Clear();
|
||||||
|
ApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StarSystem GetCoordinates(string name)
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = ApiClient.GetAsync($"system_position/{name}").Result;
|
||||||
|
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.BadRequest) // 400
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"“{name}” is not a valid proc gen system name.", "~system");
|
||||||
|
}
|
||||||
|
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
dynamic json = response.Content.ReadAsAsync<dynamic>().Result["result"];
|
||||||
|
|
||||||
|
int x = json["position"]["x"];
|
||||||
|
int y = json["position"]["y"];
|
||||||
|
int z = json["position"]["z"];
|
||||||
|
int uncertainty = json["uncertainty"];
|
||||||
|
|
||||||
|
return new StarSystem { Name=name, Coords=new Position { X=x, Y=y, Z=z, Precision=uncertainty } };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
mkdocs-roamlinks-plugin
|
16
stylecop.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
|
||||||
|
"settings": {
|
||||||
|
"orderingRules": {
|
||||||
|
"usingDirectivesPlacement": "outsideNamespace"
|
||||||
|
},
|
||||||
|
"documentationRules": {
|
||||||
|
"companyName": "alterNERDtive",
|
||||||
|
"copyrightText": "Copyright {year} {companyName}.\n\nThis file is part of {application}.\n\n{application} is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\n{application} is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with {application}. If not, see <https://www.gnu.org/licenses/>.",
|
||||||
|
"variables": {
|
||||||
|
"application": "alterNERDtive VoiceAttack profiles for Elite Dangerous",
|
||||||
|
"year": "2019–2022"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|