Compare commits
306 commits
releases/3
...
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 | |||
e1b42b8c0c | |||
dcd58e1d23 | |||
1106aafffe | |||
fe3c84b4f2 | |||
7669290a65 | |||
94a5429818 | |||
9495117a4a | |||
78f6f955e3 | |||
788b8a9d7b | |||
13e812e310 | |||
c0875cde48 | |||
c2e30eb9da | |||
8c80a4389c | |||
58b4860a58 | |||
a355af016d | |||
ddc5bd9bcb | |||
53d6472e01 | |||
e6766e67a8 | |||
6731dfd44e | |||
8330e181db | |||
d3d668f65b | |||
b8d811bca3 | |||
cc9b382d72 | |||
4befa49fe2 | |||
580abc8300 | |||
da81ae5985 | |||
2bdab1a4c7 | |||
a3cef9d365 | |||
6f6fb9219b | |||
a3bd10f4ae | |||
abd3b07e60 | |||
f153d3aa75 | |||
526730902f | |||
2306beb801 | |||
4bab6a13e8 | |||
1fb6d57cce | |||
327be7a5c4 | |||
8d7ff42a48 | |||
1a3846896a | |||
08ea88fbb9 | |||
22505515d3 | |||
525e777913 | |||
ffa7ebcf5d | |||
21a7e8cf50 | |||
2586d438b3 | |||
44806fee9a | |||
faa38b194b | |||
7cb429455c | |||
49ed63b421 | |||
55e008108a | |||
49ca50589a | |||
55b2ce9f6b | |||
0e199f88dc | |||
ad55954f65 | |||
3e5430431f | |||
4c75dbd236 | |||
6186d24096 | |||
afc49ed7e5 | |||
4d4f22e216 | |||
7d104a2be2 | |||
87610b1bbd | |||
6f51333bd4 | |||
a9a1a84aa7 | |||
0569a90aa3 | |||
dc71f21fe4 | |||
aea70224da | |||
c1dcbb0817 | |||
82c1cc065e | |||
03bfc512fc | |||
9d8eedd581 | |||
69b097d7c3 | |||
c5eb93dd0e | |||
9637975bdb | |||
afee22cf62 | |||
e8134e240d | |||
e9ea4a2576 | |||
cd4390c9ef | |||
d15fae9197 | |||
4bb10e28f5 | |||
dac75b7af3 | |||
e179fef0d1 | |||
f6a4861a06 | |||
58435a350e | |||
9baa3a1be4 | |||
ed0c9449c7 | |||
146653bdeb | |||
c2d5655703 | |||
977b0c74d7 | |||
c17355229f | |||
e5183a6d5f | |||
8bf6135482 | |||
1a5ae485b6 | |||
ba0021c3bd | |||
7f79af826f | |||
606f651eb6 | |||
ca52c39da3 | |||
22f6365f60 | |||
c7c99995d4 | |||
0a3cc4cf3e | |||
10cd0c8811 | |||
c7404c2563 | |||
01c162c459 | |||
d9199d0dee | |||
72af5a3683 | |||
b09dc47f5c | |||
2585a5a4b3 | |||
77ecc1a2d9 | |||
9f326c88ad | |||
957caa9780 | |||
caa432859c | |||
3419aeb44b | |||
288f3f3678 | |||
a96a3c9d87 | |||
12d946f036 | |||
a63b6f7a87 | |||
1d63f58097 | |||
006bbcac3b | |||
cd9437c59d | |||
92eee3f1e7 | |||
a23dd5816f | |||
6633af6060 | |||
e14512f076 | |||
d9f940c7bc | |||
5623d47aa9 | |||
f1f78e69ce | |||
77e727bb9c | |||
67d4c45102 | |||
adcec42dbd | |||
48593fce9d | |||
e0b7631eac | |||
0196a2aaf2 | |||
c955fe05d6 |
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
|
361
.gitignore
vendored
Normal file
|
@ -0,0 +1,361 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
|
||||
|
||||
|
||||
/plugins/build
|
||||
/build
|
||||
/alterNERDtive-VoiceAttack-profiles.vax
|
||||
/Makefile
|
||||
/site
|
||||
/src
|
||||
/build.csproj
|
591
CHANGELOG.md
|
@ -1,3 +1,571 @@
|
|||
# 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)
|
||||
|
||||
## SpanshAttack 7.0.1
|
||||
|
||||
### Fixed
|
||||
|
||||
* Now correctly getting the next neutron waypoint again after reaching the
|
||||
current one.
|
||||
|
||||
-----
|
||||
|
||||
# 4.0 (2021-01-29)
|
||||
|
||||
This version introduces huge (and _breaking_) changes. **Make sure to refer to
|
||||
[the “Upgrading”
|
||||
section](https://alternerdtive.github.io/VoiceAttack-profiles/upgrading/) in the
|
||||
documentation if you are upgrading from an older version!**
|
||||
|
||||
Oh yes, there is [an all new and improved documentation
|
||||
now](https://alternerdtive.github.io/VoiceAttack-profiles)!
|
||||
|
||||
The biggest change is the addition of plugins to supplement the profiles, and
|
||||
the new `alterNERDtive-base` profile that handles a lot of the plugin-related
|
||||
tasks including configuration.
|
||||
|
||||
Long-term goal is to re-implement the Python scripts in the plugins, too, to
|
||||
reduce the complexity (= probability of silly errors) and the download size.
|
||||
|
||||
The profile package now also includes [my fork of the `bindED`
|
||||
plugin](https://github.com/alterNERDtive/bindED). If you use other profiles that
|
||||
expect the old version, you will see error messages in the log about not being
|
||||
able to invoke that plugin. [You can safely ignore that](https://github.com/alterNERDtive/bindED#migrating-from-the-old-plugin).
|
||||
|
||||
## alterNERDtive-base 4.0
|
||||
|
||||
### Added
|
||||
|
||||
* `alterNERDtive-base` plugin. Provides functionality common to all profiles.
|
||||
* Proper logging to the VoiceAttack log. You will notice a lot of useful
|
||||
information, more is available if you change the log level configuration
|
||||
option. Logging to a file for troubleshooting will be added at a later date.
|
||||
* `generate missing key binds report` command: Will place a list of missing key
|
||||
binds (provided by bindED) on your Desktop for troubleshooting.
|
||||
* Lots of new configuration options, see [the
|
||||
documentation](https://alternerdtive.github.io/VoiceAttack-profiles/configuration/general).
|
||||
* You can now have a list of configuration voice commands as well as a list
|
||||
of all configuration options and their current settings printed to the
|
||||
VoiceAttack log.
|
||||
* `open [docs;documentation;help] [site;]` command: Opens the new documentation site.
|
||||
* `open [docs;documentation;help] file` command: Opens the PDF version of the
|
||||
new documentation site distributed with the profiles for offline use.
|
||||
|
||||
### Removed
|
||||
|
||||
* `Python.scriptPath` configuration option: The scripts are basically already
|
||||
deprecated, and I’m from now on assuming that you use the profile package for
|
||||
installation/upgrades, so I expect the scripts where they are supposed to be.
|
||||
|
||||
### Changed
|
||||
|
||||
* Completely reworked how the configuration works. It will be trivial to add new
|
||||
options in the future including voice commands to set them. Adding a GUI is
|
||||
also possible, but not on the roadmap yet.
|
||||
* EDDI events (and some other more administrative commands) are now hidden from
|
||||
the VoiceAttack log.
|
||||
* The command beep sound used by some commands as acknowledgment has been
|
||||
changed to a builtin sound effect in VoiceAttack to avoid having to ship a
|
||||
.wav file of unknown origin.
|
||||
|
||||
### EliteAttack 8.0
|
||||
|
||||
The `EliteDangerous` profile has been renamed to `EliteAttack` to be consistent
|
||||
with the other profiles. If you are upgrading instead of installing fresh, your
|
||||
profile will keep the old name. Feel free to manually rename it.
|
||||
|
||||
### Added
|
||||
|
||||
* `EliteAttack` plugin. Doesn’t do a lot yet.
|
||||
* Submodule targeting! Say
|
||||
`target the [drive;drives;power plant;frame shift drive;f s d;shield generator]`
|
||||
to target submodules on your current target, and `clear sub [module;system]
|
||||
target` to clear your target.
|
||||
* `distance [from;to] [Sol;home;the center;Beagle Point;Colonia]` command: Gives
|
||||
you your current distance to the given POI.
|
||||
* `[where’s;where is] my landing pad` command: Will tell you the location of
|
||||
your assigned landing pad on a starport.
|
||||
* `[dis;]engage silent running` command: Handles silent running.
|
||||
* `[are there any;] outdated stations [in this system;]` command: Runs an
|
||||
on-demand check for outdated stations in the current system.
|
||||
* `open spansh` command: Opens https://spansh.uk in your default browser.
|
||||
|
||||
### Changed
|
||||
|
||||
* `power to` command now supports of lot more options. `power to X and Y` sets
|
||||
8/4/0, `balanced power to X and Y` sets 6/6/0, `half power to X` sets 6/3/3,
|
||||
`half power to X and Y` sets 5/5/2.
|
||||
* Moved the EDSM body count and outdated station checks from the `Jumped` event
|
||||
to the pre-jump `FSD engaged` event to work around increased EDSM response
|
||||
times. (#85)
|
||||
|
||||
### Removed
|
||||
|
||||
* `[buggy;exploration] power` command.
|
||||
|
||||
### Fixed
|
||||
|
||||
* `EDDI Material threshold` event now uses the correct variable names. It will
|
||||
automatically start working properly in a future version of EDDI that fixes
|
||||
some bugs with setting event variables. (#32)
|
||||
|
||||
### RatAttack 6.0
|
||||
|
||||
### Added
|
||||
|
||||
* `RatAttack` plugin. Responsible for handling case data instead of having a way
|
||||
too long and convoluted list of VoiceAttack variables. Also provides a way to
|
||||
send RATSIGNALs to VoiceAttack via IPC.
|
||||
* `RatAttack-cli.exe` helper tool. Used to send RATSIGNALs to the plugin via IPC.
|
||||
* Will now announce permit locks, including the name of the permit if available.
|
||||
* Now supports manually injected cases that might not provide a system. You will
|
||||
still have to manually copy the system from \#fuelrats or the dispatch board
|
||||
after it has been set. (#76)
|
||||
|
||||
### Changed
|
||||
|
||||
* RATSIGNAL handling is no longer done through a file, there is now a helper
|
||||
tool that communicates with the plugin directly. See “Upgrading” in the
|
||||
documentation.
|
||||
* Now supports up to 31 cases (0–30). Thanks, Epicalypse!
|
||||
|
||||
### Fixed
|
||||
|
||||
* Updated RATSIGNAL parsing for Mecha3.
|
||||
|
||||
### SpanshAttack 7.0
|
||||
|
||||
### Added
|
||||
|
||||
* `SpanshAttack` plugin. Does miscellaneous things for now, will at some point
|
||||
replace the dependency on the ED-NeutronRouter plugin.
|
||||
* Will now log the jumps calculated for a trip to the VoiceAttack log.
|
||||
|
||||
### Changed
|
||||
|
||||
* Now pulls/announces next neutron waypoint on `FSD engaged` (starting a jump)
|
||||
instead of `Jumped` (finishing a jump). (#85)
|
||||
|
||||
### StreamAttack 2.0
|
||||
|
||||
### Added
|
||||
|
||||
* `distance [to;from] jump target` command: Tells you the current distance to
|
||||
the jump target.
|
||||
|
||||
### Changed
|
||||
|
||||
* Jump target will now be set to SpanshAttack’s plot target if the actual target
|
||||
system is not in the database.
|
||||
|
||||
-----
|
||||
|
||||
# 3.2.1 (2021-01-02)
|
||||
|
||||
## RatAttack 5.0.5
|
||||
|
||||
### Fixed
|
||||
|
||||
* RATSIGNAL parsing had to be updated _again_. -.-
|
||||
|
||||
-----
|
||||
|
||||
# 3.2.0 (2020-12-31)
|
||||
|
||||
The update mechanism has been changed to manual update in preparation of the
|
||||
4.0 release that will come with the need to manually change some things around.
|
||||
So in order to not automatically leave people with a broken state, they will
|
||||
have to manually go through the update steps for 4.0. To reflect that, 3.2.0
|
||||
will no longer auto-download a new release and instead send you to the release
|
||||
page on Github.
|
||||
|
||||
## RatAttack 5.0.4
|
||||
|
||||
### Fixed
|
||||
|
||||
* RATSIGNAL parsing updated for the latest Mecha3 changes. Permits are now
|
||||
orange instead of red.
|
||||
|
||||
## EliteDangerous 7.3
|
||||
|
||||
### Changed
|
||||
|
||||
* Updates are no longer automatic, instead you will be sent to the release page
|
||||
on Github.
|
||||
|
||||
-----
|
||||
|
||||
# 3.1.3 (2020-11-06)
|
||||
|
||||
Hopefully last Mecha3 compatibility release.
|
||||
|
||||
## RatAttack 5.0.3
|
||||
|
||||
### Fixed
|
||||
|
||||
* System names will now be `ToLower()`ed since Mecha3 capitalizes them and EDDI
|
||||
likes spelling those out instead of saying the names. Makes them a little
|
||||
messy in other ways, but less annoying overall.
|
||||
* Permit detection part of the RATSIGNAL RegEx fixed for named permits.
|
||||
* `XB` platform changed to `Xbox` to match Mecha3.
|
||||
|
||||
-----
|
||||
|
||||
# 3.1.2 (2020-10-22)
|
||||
|
||||
Bugfix to the bugfix, anyone?
|
||||
|
@ -493,6 +1061,8 @@ a station with data in EDDN >1 year old. Apologies.
|
|||
* Added new “Navigation” section. This includes the aforementioned new commands
|
||||
and a bunch of old ones that fit there better than into “Misc”.
|
||||
|
||||
-----
|
||||
|
||||
# v1.3 (2020-06-14)
|
||||
|
||||
## EliteDangerous v5.0
|
||||
|
@ -533,6 +1103,8 @@ bindings before even though it needs them …
|
|||
* Now updates your location when dropping from SC.
|
||||
* Fixed some copypasta errors in the documentation.
|
||||
|
||||
-----
|
||||
|
||||
# v1.2 (2020-03-09)
|
||||
|
||||
## EliteDangerous v4.0
|
||||
|
@ -563,8 +1135,7 @@ up to date in EDDN.
|
|||
* Added `open [rat;] dispatch board` command. Opens the web dispatch board in
|
||||
your default browser.
|
||||
* Added proper handling for multiple ratsignals hitting at once. That’s mainly
|
||||
an IRC client config thing,
|
||||
[see the docs](docs/RatAttack.md#getting-case-data-from-irc).
|
||||
an IRC client config thing, [see the docs](docs/configuration/RatAttack.md).
|
||||
* Renamed `RatAttack.getInfoFromRatsignal` to
|
||||
`RatAttack.announceCaseFromRatsignal`. Removed the “open case?” voice input
|
||||
prompt.
|
||||
|
@ -599,6 +1170,8 @@ mine ;)
|
|||
|
||||
[See the docs](docs/StreamAttack.md).
|
||||
|
||||
-----
|
||||
|
||||
# v1.1 (2020-01-30)
|
||||
|
||||
The compiled Python scripts are now distributed as two single .exe files. You
|
||||
|
@ -668,6 +1241,8 @@ fixes:
|
|||
* updated for new controls setup: the HOTAS buttons have changed because my
|
||||
setup has changed. Probably not really relevant for you.
|
||||
|
||||
-----
|
||||
|
||||
# v1.0 (2019-12-04)
|
||||
|
||||
### single-file profile package
|
||||
|
@ -712,6 +1287,8 @@ open a bug if it does.
|
|||
|
||||
* fixed bug with wonky system names (including e.g. `+` or `[]`)
|
||||
|
||||
-----
|
||||
|
||||
# v0.5 (2019-11-09)
|
||||
|
||||
## RatAttack v0.1
|
||||
|
@ -745,6 +1322,8 @@ RatAttack is now a thing! :D
|
|||
when EDSM knows _fewer_ bodies (there are some issues with duplicate entries
|
||||
in EDSM, e.g. in Dromi)
|
||||
|
||||
-----
|
||||
|
||||
# v0.4.1 (2019-10-14)
|
||||
|
||||
This is a bug fix release (as the version number indicates). Mainly for changes
|
||||
|
@ -764,6 +1343,8 @@ yet, so you do not have to download the new archive.
|
|||
* fixed discovery scan event for new EDDI variable naming
|
||||
* fixed srv lauched event to properly turn off the lights
|
||||
|
||||
-----
|
||||
|
||||
# v0.4 (2019-10-12)
|
||||
|
||||
## SpanshAttack v1.3
|
||||
|
@ -787,6 +1368,8 @@ yet, so you do not have to download the new archive.
|
|||
update EDSM) (requires python scripts, see doc)
|
||||
* added compatibility for SpanshAttack’s clear on shutdown
|
||||
|
||||
-----
|
||||
|
||||
# v0.3 (2019-09-22)
|
||||
|
||||
## SpanshAttack v1.2
|
||||
|
@ -800,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
|
||||
issue here.
|
||||
|
||||
-----
|
||||
|
||||
# v0.2 (2019-08-28)
|
||||
|
||||
## SpanshAttack v1.1
|
||||
|
@ -818,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
|
||||
out there for reference.
|
||||
|
||||
-----
|
||||
|
||||
# v0.1 (2019-08-06)
|
||||
|
||||
## SpanshAttack v1.0
|
||||
|
|
BIN
Custom Profile Example.vap
Normal file
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>
|
674
LICENSE
Normal file
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
188
README.md
|
@ -1,184 +1,42 @@
|
|||
# Elite Dangerous VoiceAttack Profiles #
|
||||
# Elite Dangerous VoiceAttack Profiles #
|
||||
|
||||
These are various profiles for [VoiceAttack](https://voiceattack.com) (VA) I use
|
||||
to enhance my Elite experience. They give me important info, facilitate
|
||||
day-to-day gaming and do some special things for [Fuel
|
||||
Rats](https://fuelrats.com) and [Hull Seals](https://hullseals.space) work.
|
||||
|
||||
Each of the profiles is documented in `docs/`.
|
||||
**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 ##
|
||||
|
||||
* [EliteDangerous](docs/EliteDangerous.md): My main Elite VA profile. Here be
|
||||
dragons; things may be heavily tailored towards how _I_ play the game and may
|
||||
not apply to how you play it. Included for reference and as a baseline or
|
||||
inspiration to create your own stuff.
|
||||
* [RatAttack](docs/RatAttack.md): profile for interactions with the Fuel Rats’
|
||||
IRC server.
|
||||
* [SpanshAttack](docs/SpanshAttack.md): profile to plot and follow trips along
|
||||
the neutron highway using [spansh](https://spansh.co.uk/plotter).
|
||||
* [StreamAttack](docs/StreamAttack.md): profile for writing various things to
|
||||
files that can then be read by streaming software like OBS.
|
||||
* EliteAttack: The main Elite VA profile. Anything related to “just” playing the
|
||||
game.
|
||||
* RatAttack: Manages interactions with the FuelRats IRC server.
|
||||
* SpanshAttack: Plots and follows trips along the neutron highway using
|
||||
[Spansh’s neutron plotter](https://spansh.co.uk/plotter).
|
||||
* StreamAttack: Writes various status things to files that can then be read by
|
||||
streaming software like OBS.
|
||||
|
||||
## Requirements ##
|
||||
## Documentation & Installation Guide
|
||||
|
||||
* [VoiceAttack](https://voiceattack.com): absolutely required (duh).
|
||||
* [bindED](https://forum.voiceattack.com/smf/index.php?topic=564.0): required
|
||||
for EliteDangerous and SpanshAttack; makes anything involving hitting E:D key
|
||||
binds portable.
|
||||
* [EDDI](https://github.com/EDCD/EDDI) installed as a VoiceAttack plugin:
|
||||
required for EliteDangerous, SpanshAttack and Streamattack, optional for
|
||||
RatAttack.
|
||||
* [ED-NeutronRouter](https://github.com/sc-pulgan/ED-NeutronRouter): required
|
||||
for SpanshAttack. **Make sure to [grab the pre-release
|
||||
1.02](https://github.com/sc-pulgan/ED-NeutronRouter/releases/tag/1.02)** since
|
||||
1.01 has a bug with a hardcoded 50 ly jump range.
|
||||
* [elite-scripts](https://github.com/alterNERDtive/elite-scripts): required for
|
||||
EliteDangerous, SpanshAttack and StreamAttack, recommended for RatAttack
|
||||
(included).
|
||||
|
||||
Additionally, you need to have keyboard binds setup at least as secondary
|
||||
bindings in Elite’s controls options. VA _cannot_ “push” joystick buttons for
|
||||
you, it can only do keyboard inputs. Hence its only way to interact with Elite
|
||||
is through keyboard emulation, even if you otherwise play the game with
|
||||
a controller or HOTAS. Or racing wheel. Or Rock Band set. Or bananas.
|
||||
|
||||
## Installing ##
|
||||
|
||||
1. Install [VoiceAttack](https://voiceattack.com).
|
||||
1. Install the plugins listed in [Requirements](#Requirements).
|
||||
1. Download the profile package (`alterNERDtive-voiceattack-profiles.vax`) from
|
||||
the [release
|
||||
page](https://github.com/alterNERDtive/VoiceAttack-profiles/releases/latest)
|
||||
and import it as a profile into VoiceAttack. This will install all included
|
||||
profiles, the referenced sound files and the Python scripts.
|
||||
|
||||
(You can also download the profiles individually from the `profiles/` folder on
|
||||
github.)
|
||||
|
||||
## Getting Started ##
|
||||
|
||||
You will want to create your own profile and then import the downloaded ones
|
||||
into your custom profile. This way you can easily add commands (to your custom
|
||||
profile), change commands (by copying them into your custom profile and editing
|
||||
them) and change settings (by overriding them in your custom profile). Note that
|
||||
most settings can be changed with voice commands. If you find any that cannot
|
||||
but you feel should, please file an issue or report it on Discord.
|
||||
|
||||
### Creating a Custom Profile ###
|
||||
|
||||
Hit the second button next to the profile dropdown menu and choose “Create new
|
||||
Profile”. Give it a name and add some commands if you want to.
|
||||
|
||||
You can also just keep using a profile you have already created.
|
||||
|
||||
### Importing profiles ###
|
||||
|
||||
First off, create a startup command. 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 make sure you don’t accidentally run it via
|
||||
voice. We will need this command later.
|
||||
|
||||
While editing the profile, hit the “Options” button. On the section labeled
|
||||
“Include commands from other profiles”, hit the “…” button and add all profiles
|
||||
(`EliteDangerous`, `RatAttack`, `SpanshAttack`, `StreamAttack`). All commands
|
||||
defined in these profiles will be available to you. Make sure that
|
||||
“EliteDangerous” is on top of the list.
|
||||
|
||||
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
|
||||
earlier.
|
||||
|
||||
Edit your startup command. Add a new action using “Other” → “VoiceAttack Action”
|
||||
→ “Execute Another Command”. Choose “Execute by name (Advanced)” and enter
|
||||
“EliteDangerous.startup”.
|
||||
|
||||
### Settings ###
|
||||
|
||||
All profiles will load sane defaults if you haven’t changed anything. You no
|
||||
longer need to fiddle with the `startup` commands of each profile, instead you
|
||||
can use voice commands to change settings! See the `docs/` and the
|
||||
`_configuration` commands section of each profile.
|
||||
|
||||
Basically all the settings are available using the `customize settings` prefix,
|
||||
then saying `[enable;disable] <setting>` for on/off switches and `set <setting>`
|
||||
for text variables.
|
||||
|
||||
One caveat applies: settings will only be saved in the profile you have
|
||||
selected, but be preserved if you switch around.
|
||||
|
||||
### Making changes ###
|
||||
|
||||
If you want to edit a command or add your own, _do not edit the profiles
|
||||
directly_. Instead create commands in your custom profile, and copy commands you
|
||||
want to change over to that before editing them. This will make sure no changes
|
||||
are lost if you update the profiles.
|
||||
|
||||
Because of limitations of VoiceAttack itself, only the first matching command
|
||||
found will be executed, _including EDDI events_. That means that if you create
|
||||
commands to handle EDDI events, you are going to have to check the imported
|
||||
profiles if they rely on these event handlers as well, and call them manually if
|
||||
they do.
|
||||
|
||||
E.g. if you want to create a custom `((EDDI Message sent))` handler in your
|
||||
profile, you will have to make it excute the `EliteDangerous.EDDI Message sent`
|
||||
and `RatAttack.EDDI Message sent` commands. Otherwise stuff _will_ break.
|
||||
|
||||
If you have no idea what the previous two paragraphs were about, you can most
|
||||
likely just ignore them.
|
||||
|
||||
## Updating ##
|
||||
|
||||
### The Best™ Way ###
|
||||
|
||||
Say “check for profiles update”. If it finds one, say “download profiles
|
||||
update”. Restart VoiceAttack.
|
||||
|
||||
There will also be an update check every time `EliteDangerous.startup` is run.
|
||||
|
||||
### The Manual Way ###
|
||||
|
||||
If you don’t like automation or do not use all provided profiles, you’ll have to
|
||||
update semi-manually.
|
||||
|
||||
Say “open VoiceAttack import folder”. Download the current release profile
|
||||
package, drop it in there. Restart VoiceAttack.
|
||||
|
||||
### Note about Admin Privileges ###
|
||||
|
||||
The update process will run VoiceAttack with admin privileges. If you do not
|
||||
usually run VoiceAttack with admin privileges, do _not_ have it start
|
||||
VoiceAttack for you after importing the profiles update. It will keep running
|
||||
with elevated privileges. Instead restart it manually. If you are not sure if
|
||||
you are running with elevated privileges check the “VoiceAttack Information”
|
||||
dialog in VoiceAttack General settings → “System Info >”. It will include a line
|
||||
about running with admin prvileges if it does.
|
||||
|
||||
### Major Version Changes ###
|
||||
|
||||
If a profile’s major version number changes (e.g. SpanshAttack 1.x.x to 2.0.0)
|
||||
there _will_ be changes to the profile that include one or any amount of the
|
||||
following changes:
|
||||
|
||||
* command names / command invocation have changed
|
||||
* configuration variable name or format have changed
|
||||
* features removed
|
||||
* _major_ features added
|
||||
|
||||
**If you see a major version number change in the release notes, please pay
|
||||
attention to said notes to know what you might have to change to get it to
|
||||
work!**
|
||||
You can find [comprehensive documentation on Github
|
||||
Pages](https://alternerdtive.github.io/VoiceAttack-profiles).
|
||||
|
||||
## Need Help / Want to Contribute? ##
|
||||
|
||||
If you run into any errors, please try running the profile in question on its
|
||||
own / get a fresh version. If that doesn’t fix the error, look at the
|
||||
[devel](https://github.com/alterNERDtive/VoiceAttack-profiles/tree/devel) branch
|
||||
and see if it’s fixed there already.
|
||||
If you run into any errors, please make sure you are running the latest version
|
||||
of the profiles and all requirements.
|
||||
|
||||
If you have no idea what I was saying in that last parargraph and / or the
|
||||
things mentioned there don’t fix your problem, please [file an
|
||||
If your problem persists, please [file an
|
||||
issue](https://github.com/alterNERDtive/VoiceAttack-profiles/issues). Thanks! :)
|
||||
|
||||
You can also [say “Hi” on Discord](https://discord.gg/kXtXm54) if that is your
|
||||
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 @@
|
|||
3.1.2
|
||||
4.5
|
||||
|
|
314
docs/EliteAttack.md
Normal file
|
@ -0,0 +1,314 @@
|
|||
# EliteAttack
|
||||
|
||||
This is my personal VoiceAttack profile for Elite: Dangerous. It started out
|
||||
ages ago as a modification of [MalicVR’s public
|
||||
profile](https://forums.frontier.co.uk/threads/malics-voice-attack-profile-for-vr.351050/),
|
||||
then looked less and less and less like that and I added and cleaned up a lot of
|
||||
things while removing the stuff I didn’t use anyway. By now it would have
|
||||
probably been simpler to start from scratch.
|
||||
|
||||
Funnily enough it has grown to rely way more on events provided by
|
||||
[EDDI](https://github.com/EDCD/EDDI) than actual voice commands.
|
||||
|
||||
## Chat Commands
|
||||
|
||||
These commands will only work with the comms panel active, and you should be in
|
||||
the edit window ready to send. They will _not_ hit Enter on their own.
|
||||
|
||||
* `clear [chat;text]`: Clears the chat window. Use from outside the comms panel.
|
||||
* `[local;squad;system;wing] chat`: Puts you into the chosen chat channel.
|
||||
* `salute; oh seven`: Will put “o7” into the chat.
|
||||
|
||||
## Engineering/Materials
|
||||
|
||||
* `how many [<g5 manufactured materials list>] do i have`: Tells you how many of
|
||||
the given g5 manufactured material you currently have on board. I’ve
|
||||
restricted it to just those to not spam speech recognition with too many
|
||||
phrases, and because those are the ones I usually want to know while jumping
|
||||
around the bubble and having an eye on any HGE that might be around.
|
||||
* `[launch;open] e d engineer`: Opens the ED Engineer tool.
|
||||
* `what [mats;materials] do i need?`: Runs the EDDI responder that tells you
|
||||
which materials are below wanted threshold. Needs setting those first. Gets
|
||||
very spammy if you do it for all of them; personally I only set them for g5
|
||||
manufactured, so I can quickly check if it’s worth looking for HGE in a system
|
||||
I’m in.
|
||||
|
||||
## Navigation
|
||||
|
||||
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
|
||||
powered by awesome EDDI so I don’t have to do the work myself!
|
||||
|
||||
* `distance [from;to] [Sol;home;the center;Beagle Point;Colonia]`: Gives you the
|
||||
current distance to the given POI.
|
||||
* `[find;target] nearest [encoded;manufactured;raw] material trader`: Targets
|
||||
the nearest respective material trader.
|
||||
* `[find;target] nearest [fuel;scoopable] star`: Targets the nearest scoopable
|
||||
star.
|
||||
* `[find;target] nearest [guardian;human] tech broker`: Targets the nearest
|
||||
respective tech broker.
|
||||
* `[find;target] nearest [interstellar factor;mission system;scoopable star]`:
|
||||
Well, you know the drill by now.
|
||||
* `[find;target] nearest mission system`: Targets the nearest system that has a
|
||||
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
|
||||
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]`:
|
||||
Targets the given system on the galaxy map.
|
||||
* `[where’s;where is] my landing pad`: Will tell you the location of your
|
||||
assigned landing pad on a starport.
|
||||
|
||||
## Ship Controls
|
||||
|
||||
Basically anything that is related to directly doing something with your ship.
|
||||
|
||||
* `[abort;cancel;stop] jumping`: Stops a currently charging FSD jump.
|
||||
* `[half;] power to [engines;shields;systems;weapons]`: Sets pips to 6/3/3
|
||||
(`half`) or 8/2/2 towards the given capacitor.
|
||||
* `[balanced;half;] power to [engines;shields;systems;weapons] [and engines;and shields;and systems;and weapons;]`:
|
||||
Sets pips to 6/6/0 (balanced), 5/5/2 (half) or 8/4/0 towards the given capacitors.
|
||||
* `[close;deploy;extend;open;retract;] [cargo scoop;hard points; landing gear] [up;down;]`:
|
||||
Overly complicated command to handle everything related to Cargo Scoop, Hard
|
||||
Points, Landing Gear. You get the gist, I guess. Works in SRV too.
|
||||
* `[disco;discovery scan]`: Executes a discovery scan. Expects the Discovery
|
||||
Scanner in your first fire group, secondary fire. [You can change
|
||||
that](configuration/EliteAttack.md#settings).
|
||||
* `[dis;]engage silent running`: Turns silent running on and off.
|
||||
* `[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,
|
||||
which sometimes leads to weird results.
|
||||
* `[jump;engage;get me out] [and scan;] [when ready;]`: Retracts everything that
|
||||
might be protruding from your ship, then jumps to the next system. If the FSD
|
||||
isn’t charging within 1s, it gets you into SC instead (e.g. if your target is
|
||||
obstructed). If given “and scan” runs a discovery scan. If given “when ready”
|
||||
waits for mass lock to clear, your FSD to cool down and you to leave scoop
|
||||
range before jumping.
|
||||
* `night vision [on;off]`: Toggles your night vision on/off. Works in SRV too.
|
||||
* `rapid fire lights`: Flashes your lights 5 times in a row.
|
||||
* `retract [all;everything]`: Retracts, well, everything.
|
||||
* `[start;stop] [firing;mining]`: Starts/stops holding down primary fire. Mostly
|
||||
useful when mining. When triggered with “mining”, also deploys the cargo
|
||||
scoop.
|
||||
* `[super;] cruise [when ready;]`: Retracts everything, then jumps to SC. If
|
||||
given “when ready” will wait for mass lock to clear and your FSD to cool down
|
||||
first.
|
||||
|
||||
## SRV Controls
|
||||
|
||||
Things relevant to your SRV, but not your ship.
|
||||
|
||||
* `[recall;dismiss] ship`: Recalls or dismisses ship. Currently does the same
|
||||
thing regardless of the state of your ship. I wish it would be possible to
|
||||
restrict it to doing one thing each, but that’s currently not possible sadly.
|
||||
* `[toggle;enable;disable] drive assist`: Handles all your drive assist needs!
|
||||
|
||||
## Targeting
|
||||
|
||||
Well … targeting stuff, I guess. Not really sure why I made that its own
|
||||
category, but oh well :)
|
||||
|
||||
* `target the [drive;drives;power plant;frame shift drive;f s d;shield
|
||||
generator]`: Targets the given submodule on your current target, or your next
|
||||
target if you don’t have one currently. Does not persist between targets.
|
||||
* `clear sub [module;system] target`: Clears the current submodule target.
|
||||
* `target next system`: Selects the next system on your route.
|
||||
* `target wing man [1;2;3]`: Targets your wingmen.
|
||||
* `target’s target`: Targets your target’s target (only works on wingmen).
|
||||
* `wing man [1;2;3] target`: Targets your wingmen’s target.
|
||||
* `wing man nav lock`: Toggles wing man nav lock on the selected wing member.
|
||||
|
||||
## UI Commands
|
||||
|
||||
Everything handling stuff that’s not related to controlling your ship, but
|
||||
manipulating some UI element(s).
|
||||
|
||||
* `[enter;leave] F S S`: Opens/closes FSS.
|
||||
* `[main;game] menu`: Opens the ESC menu.
|
||||
* `[relog;reset] to [open;solo]`: Relogs to Open or Solo mode, respectively.
|
||||
* `controls options`: Opens the controls options menu.
|
||||
* `docking request;request dock[ing;]`: Sends a docking request.
|
||||
* `galaxy map`: Opens the galaxy map.
|
||||
* `restart from Desktop`: Quits the game and restarts from an open launcher by
|
||||
clicking the play button.
|
||||
* `set [default;star;station;settlement;signal sources;anomaly;unknown;system] filter`:
|
||||
Sets a nav panel filter setting. See the command or just try different things
|
||||
for what is possible. You need to clear filters and hover over the filter
|
||||
button, then run this.
|
||||
* `system map`: Opens the system map.
|
||||
* `take [high res;] screenshot`: Takes a (high res) screenshot.
|
||||
* `toggle orbit lines`: Toggles the visibility of orbit lines.
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
The commands in here do random more or less useful things.
|
||||
|
||||
* `[are there any;] outdated stations [in this system;]`: Runs an on-demand
|
||||
check for outdated stations in the current system.
|
||||
* `[bodies;what’s;what is] left to [map;be mapped;scan]`: Tells you which bodies
|
||||
EDDI thinks are worth mapping in the system that you haven’t mapped yet.
|
||||
* `copy current system`: Copies the current system name into the clipboard.
|
||||
* `open [current;] system on EDSM`: Opens your current system on EDSM in your
|
||||
default browser.
|
||||
* `open copied system on EDSM`: Opens the system in your clipboard on EDSM in
|
||||
your default browser.
|
||||
* `open coriolis`: Opens Coriolis in your default browser.
|
||||
* `open e d d b [station;system;faction;] [search;]`: Opens EDDB in your default
|
||||
browser.
|
||||
* `open e d s m`: Opens EDSM in your default browser.
|
||||
* `open inara`: Opens Inara in your default browser.
|
||||
* `open materials finder`: Opens EDTutorials’ materials finder in your default
|
||||
browser.
|
||||
* `open miner’s tool`: Opens https://edtools.cc/miner in your default browser.
|
||||
* `open spansh`: Opens https://spansh.uk in your default browser.
|
||||
|
||||
## 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
|
||||
|
||||
Announces an estimate for high-value bodies’ payouts and the remaining mapping
|
||||
candidates in the system as given by EDDI.
|
||||
|
||||
### Body scanned
|
||||
|
||||
Announces any interesting body traits found when scanning:
|
||||
|
||||
* terraformable
|
||||
* Earth-like World, Ammonia World or Water World
|
||||
* landable and >5 g
|
||||
* semimajor axis <1.5 ls (only really interesting for planets, but there’s no
|
||||
proper way to separate them from moons, sadly)
|
||||
* radius <300 km
|
||||
|
||||
Feel free to suggest more!
|
||||
|
||||
### Carrier Cooldown
|
||||
|
||||
Tells you when your carrier is able to do its next jump.
|
||||
|
||||
### Carrier Jump Engaged
|
||||
|
||||
This event fires when your carrier jumps but you are _not_ docked at it. It
|
||||
provides way less information than the `Carrier Jumped` event, but hey, I don’t
|
||||
use most of it anyway. Basically just calls `Carrier Jumped`.
|
||||
|
||||
### Carrier Jump Request
|
||||
|
||||
Announces the system and body your carrier has just been scheduled to jump to.
|
||||
Use this to double check ingame information; I’ve had my carrier accept a body
|
||||
as jump target, but then end up around the star. This _might_ give you a heads
|
||||
up on that.
|
||||
|
||||
Also starts a command queue to give you advance warnings on carrier lockdown at
|
||||
-10, -5 and -2 minutes.
|
||||
|
||||
### Carrier Jumped
|
||||
|
||||
Announces system and body your carrier has just jumped to.
|
||||
|
||||
### Carrier Pads Locked
|
||||
|
||||
Announces your carrier’s lockdown procedures.
|
||||
|
||||
### Discovery Scan
|
||||
|
||||
Announces the number of bodies (and non-body signals) found in the system. Also
|
||||
compares the number of bodies to the amount reported by EDSM (requires Python
|
||||
scripts).
|
||||
|
||||
### Docked
|
||||
|
||||
Automatically refuels, repairs, rearms, then gets your ship into the hangar and
|
||||
opens station services. Can be individually disabled.
|
||||
|
||||
### Docking Denied
|
||||
|
||||
Tells you the reason for docking denial.
|
||||
|
||||
### Entered Normal Space
|
||||
|
||||
Throttles to 0 upon dropping from SC, if the hyperspace dethrottle option is
|
||||
enabled.
|
||||
|
||||
### Fighter Launched
|
||||
|
||||
Orders your ship to hold position so it doesn’t chase after you immediately.
|
||||
|
||||
### Jet Cone Boost
|
||||
|
||||
Sets your ship to full throttle immediately after you have supercharged.
|
||||
|
||||
### Jumped
|
||||
|
||||
* Zeroes throttle if the hyperspace dethrottle option is enabled.
|
||||
* Gets the system’s body count from EDSM if that option is enabled.
|
||||
* Gets stations with outdated data (by default: older than 1 year) from Spansh’s
|
||||
API. Again, if it is enabled.
|
||||
* Starts a discovery scan if that is enabled.
|
||||
* Last but not least tells you about planets worth scanning if you are on the
|
||||
R2R.
|
||||
|
||||
### Liftoff
|
||||
|
||||
Retracts landing gear for you. Seriously, is there any occasion in which you
|
||||
_don’t_ immediately want to retract it after takeoff?
|
||||
|
||||
### Low Fuel
|
||||
|
||||
Warns you when you reach 25% fuel. Also reports number of jumps you have left or
|
||||
the (rough) range you still have on the fumes left in your tank.
|
||||
|
||||
### Material Threshold
|
||||
|
||||
Warns you when a monitored material falls below its minimum stock level and
|
||||
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
|
||||
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
|
||||
|
||||
This event actually is several different events in one. Currently the following
|
||||
are handled:
|
||||
|
||||
* Charging: Warns you if you are jumping with less than 25% fuel.
|
||||
* Cooldown complete: Announces FSD cooldown if you are currently in normal
|
||||
space.
|
||||
|
||||
### Ship Interdicted
|
||||
|
||||
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!
|
||||
|
||||
### SRV Launched
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
Lists all bodies EDDI considers worth mapping in the current system.
|
||||
|
||||
### Undocked
|
||||
|
||||
Retracts landing gear for you. Seriously, is there any occasion in which you
|
||||
_don’t_ immediately want to retract it after takeoff?
|
|
@ -1,479 +0,0 @@
|
|||
# EliteDangerous #
|
||||
|
||||
This is my personal VoiceAttack profile for Elite: Dangerous. It started out
|
||||
ages ago as a modification of [MalicVR’s public
|
||||
profile](https://forums.frontier.co.uk/threads/malics-voice-attack-profile-for-vr.351050/),
|
||||
then looked less and less and less like that and I added and cleaned up a lot of
|
||||
things while removing the stuff I didn’t use anyway. By now it would have
|
||||
probably been simpler to start from scratch.
|
||||
|
||||
Some of it has grown to a state that it might be useful to others in its own
|
||||
package, so I’ve separated the neutron jumping and Seals stuff into their own
|
||||
profiles.
|
||||
|
||||
The rest is a random conglomerate of all things VA and E:D; from various voice
|
||||
commands to lots of EDDI event handlers.
|
||||
|
||||
Speaking of EDDI; it has become in integral part of my Elite experience,
|
||||
especially the plethora of information it extracts from the game’s journal and
|
||||
presents to you via lots and lots of status variables and by firing various
|
||||
events that can then be handled through VA commands. It’s great. Check it out.
|
||||
(You might want to make it talk a lot less in it’s personality options, or
|
||||
disable the speech responder entirely like I have.)
|
||||
|
||||
## Requirements ##
|
||||
|
||||
In addition to the bindED and EDDI VoiceAttack plugins, this profiles needs my
|
||||
[Python elite-scripts](https://github.com/alterNERDtive/elite-scripts) to do
|
||||
everything properly. The release page here includes a compiled version for
|
||||
Windows that does not need Python installed. If you use the profile package from
|
||||
the release page, they will be installed automatically.
|
||||
|
||||
## Settings ##
|
||||
|
||||
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] layout, you will have to change it back to the key that is physically
|
||||
in the place where `v` would be on QWERTY.
|
||||
|
||||
For other settings, see the [Configuration Variables](#Configuration-Variables)
|
||||
section.
|
||||
|
||||
## Including the Profile In Another Profile ##
|
||||
|
||||
This is meant to be a standalone profile, including the others in this repo (and
|
||||
a couple more). It was never designed to be included into your existing profile.
|
||||
Nevertheless, it _should_ work properly if you follow some guide lines:
|
||||
|
||||
* Run the startup command. You will need to have a startup command in your
|
||||
profile (= one that is run on profile loading) and call
|
||||
`EliteDangerous.startup` by name from that one.
|
||||
* Make sure all EDDI events that EliteDangerous needs are correctly handled. For
|
||||
all events used in EliteDangerous that you already have handlers for in your
|
||||
profile, you’ll have to include a call to `EliteDangerous.<event name>`. E.g.
|
||||
for “EDDI Jumped”, call `EliteDangerous.EDDI Jumped` by name from your `((EDDI
|
||||
Jumped))` command.
|
||||
|
||||
## Usage ##
|
||||
|
||||
### Chat Commands ###
|
||||
|
||||
There’s a bunch of commands in here to send certain things to chat. Unless
|
||||
stated otherwise, they will only work with the comms panel active, and you
|
||||
should be in the edit window ready to send. They will _not_ hit Enter on their
|
||||
own.
|
||||
|
||||
* `clear [chat;text]`: Clears the chat window. Use from outside the comms panel.
|
||||
* `[local;squad;system;wing] chat`: Puts you into the chosen chat channel.
|
||||
* `paste text`: Pastes your clipboard into Elite. Works outside the comms panel
|
||||
too, e.g. on the galaxy map inside the search field.
|
||||
* `salute; oh seven`: Will put “o7” into the chat.
|
||||
|
||||
### Engineering/Materials ###
|
||||
|
||||
* `how many [<g5 manufactured materials list>] do i have`: Tells you how many of
|
||||
the given g5 manufactured material you currently have on board. I’ve
|
||||
restricted it to just those to not spam speech recognition with too many
|
||||
phrases, and because those are the ones I usually want to know while jumping
|
||||
around the bubble and having an eye on any HGE that might be around.
|
||||
* `open e d engineer`: Opens the ED Engineer tool.
|
||||
* `what [mats;materials] do i need?`: Runs the EDDI responder that tells you
|
||||
which materials are below wanted threshold. Needs setting those first. Gets
|
||||
very spammy if you do it for all of them; personally I only set them for g5
|
||||
manufactured, so I can quickly check if it’s worth looking for HGE in a system
|
||||
I’m in.
|
||||
|
||||
### Events ###
|
||||
|
||||
The main point of this profile is to react to Elite’s journal events (powered by
|
||||
EDDI). Each of the events listed here will trigger a `((EDDI <event>))` command
|
||||
in VoiceAttack which in turn triggers `EliteDangerous.EDDI <event>` and all
|
||||
included profiles’ similar commands, e.g. `SpanshAttack.EDDI <event>`.
|
||||
|
||||
The actual `((EDDI <event>))` command will only be executed once by VoiceAttack,
|
||||
the first one it can find. Keeping it separate from the actual code to be run
|
||||
makes it easier to handle (multiple) included profiles.
|
||||
|
||||
If the command for an event will send key presses to Elite, it focuses the
|
||||
client window first to make sure they get registered properly. If it is not in
|
||||
focus, the first key press might be swallowed otherwise.
|
||||
|
||||
For other commands, the profile just assumes that you are actively doing
|
||||
something in game and it is already focused :)
|
||||
|
||||
#### Body Mapped ####
|
||||
|
||||
Announces an estimate for high-value bodies’ payouts and the remaining mapping
|
||||
candidates in the system as given by EDDI.
|
||||
|
||||
#### Body scanned ####
|
||||
|
||||
Announces any interesting body traits found when scanning:
|
||||
|
||||
* terraformable
|
||||
* Earth-like World, Ammonia World or Water World
|
||||
* landable and >5 g
|
||||
* semimajor axis <1.5 ls (only really interesting for planets, but there’s no
|
||||
proper way to separate them from moons, sadly)
|
||||
* radius <300 km
|
||||
|
||||
Feel free to suggest more!
|
||||
|
||||
#### Carrier Cooldown ####
|
||||
|
||||
Tells you when your carrier is able to do its next jump. Technically only works
|
||||
if you were docked at it when it performed the jump, but I’m doing some
|
||||
behind-the-scenes magic if you weren’t :)
|
||||
|
||||
Might be slightly off (too early) in the latter case.
|
||||
|
||||
#### Carrier Jumped ####
|
||||
|
||||
Announces system and body your carrier has just jumped to.
|
||||
|
||||
#### Carrier Jump Engaged ####
|
||||
|
||||
This event fires when your carrier jumps but you are _not_ docked at it. It
|
||||
provides way less information than the `Carrier Jumped` event, but hey, I don’t
|
||||
use most of it anyway.
|
||||
|
||||
Basically just calls `Carrier Jumped` (and makes sure that a `Carrier cooldown`
|
||||
event is triggered manually at approximately the right time).
|
||||
|
||||
#### Carrier Jump Request ####
|
||||
|
||||
Announces the system and body your carrier has just been scheduled to jump to.
|
||||
Use this to double check ingame information; I’ve had my carrier accept a body
|
||||
as jump target, but then end up around the star. This _might_ give you a heads
|
||||
up on that.
|
||||
|
||||
#### Carrier Pads Locked ####
|
||||
|
||||
Announces your carriers lockdown procedures. This _might_ only work when you are
|
||||
docked (which would make it pretty useless). Feel free to open in issue if
|
||||
that’s the case.
|
||||
|
||||
#### Commander Loading ####
|
||||
|
||||
Auto-sets my nick in the FuelRats IRC. Probably largely irrelevant to you.
|
||||
|
||||
#### Discovery Scan ####
|
||||
|
||||
Announces the number of bodies (and non-body signals) found in the system. Also
|
||||
compares the number of bodies to the amount reported by EDSM (requires Python
|
||||
scripts).
|
||||
|
||||
#### Docked ####
|
||||
|
||||
Automatically gets your ship into the hangar and opens station services.
|
||||
|
||||
#### Docking Denied ####
|
||||
|
||||
Tells you the reason for docking denial.
|
||||
|
||||
#### Entered Normal Space ####
|
||||
|
||||
Throttles to 0 upon dropping from SC, if `EliteDangerous.hyperSpaceDethrottle` is set.
|
||||
|
||||
#### Fighter Launched ####
|
||||
|
||||
Orders your ship to hold position so it doesn’t chase after you immediately.
|
||||
|
||||
#### Jet Cone Boost ####
|
||||
|
||||
Sets your ship to full throttle immediately after you have supercharged.
|
||||
|
||||
#### Jumped ####
|
||||
|
||||
* zeroes throttle
|
||||
* gets the system’s body count from EDSM (requires Python scripts)
|
||||
* gets stations with outdated data (older than 1 year) from Spansh’s API
|
||||
* if you haven’t visited the systems, starts a discovery scan (see the discovery
|
||||
scan command)
|
||||
* last but not least tells you about planets worth scanning if you are on the
|
||||
R2R
|
||||
|
||||
#### Liftoff ####
|
||||
|
||||
Retracts landing gear for you. Seriously, is there any occasion in which you
|
||||
_don’t_ immediately want to retract it after takeoff?
|
||||
|
||||
#### Low Fuel ####
|
||||
|
||||
Warns you when you reach 25% fuel. Also reports number of jumps you have left or
|
||||
the (rough) range you still have on the fumes left in your tank.
|
||||
|
||||
#### Material Threshold ####
|
||||
|
||||
Warns you when a monitored material falls below it’s minimum stock level. You
|
||||
will have to set a minimum desired amount in EDDI’s material monitor options
|
||||
first for all materials you wish to be monitored.
|
||||
|
||||
#### Message Sent ####
|
||||
|
||||
Checks any message you send for a chat prefix and sends it to the proper chat
|
||||
window. Probably largely useless to you without modification.
|
||||
|
||||
* `.nc`: Actually doesn’t send anything, but runs the
|
||||
`RatAttack.announceNearestCMDR` command with the system given in the rest of
|
||||
the message.
|
||||
* `.dc`: Sends the message to the Discord window.
|
||||
* `.tc`: Sends the message to my twitch channel window (IRC #alternerdtive).
|
||||
|
||||
There are similar event commands in RatAttack and SealAttack handling other chat
|
||||
windows.
|
||||
|
||||
#### Ship FSD ####
|
||||
|
||||
This event actually is several different events in one. Currently the following
|
||||
are handled:
|
||||
|
||||
* charging: Warns you if your target system’s main star is not scoopable,
|
||||
including an extra warning at low fuel levels. (__Note__: This only works if
|
||||
the target system is in EDSM. So it’s kind of useless for its intended use
|
||||
(exploration) and probably going to be removed at some point.)
|
||||
* cooldown complete: Announces FSD cooldown if you are currently in normal
|
||||
space.
|
||||
|
||||
#### Ship interdicted ####
|
||||
|
||||
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!
|
||||
|
||||
#### Ship targeted ####
|
||||
|
||||
This currently doesn’t do anything. I was fiddling around with automatically
|
||||
targeting a certain module on ship targeting, but it was more hassle than I had
|
||||
thought.
|
||||
|
||||
#### Shutdown ####
|
||||
|
||||
Changes my nick back to default in FuelRats IRC. Probably largely useless to
|
||||
you. If you are using FuelRats IRC you need to change/deactivate this (see
|
||||
[below](#Configuration-Variables)) or you will start impersonating me by
|
||||
accident :)
|
||||
|
||||
#### SRV Launched ####
|
||||
|
||||
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 second to turn your lights off on a short drop and/or in high gravity.
|
||||
|
||||
#### System Scan Complete ####
|
||||
|
||||
Lists you all bodies EDDI considers worth mapping in the current system.
|
||||
|
||||
#### Undocked ####
|
||||
|
||||
Retracts landing gear for you. Seriously, is there any occasion in which you
|
||||
_don’t_ immediately want to retract it after takeoff?
|
||||
|
||||
#### VA initialized ####
|
||||
|
||||
Fires when the EDDI VoiceAttack plugin is loaded. Makes sure that EDDI is set to
|
||||
quite mode even if the profile was loaded before plugin initialization had
|
||||
completed.
|
||||
|
||||
### Misc ###
|
||||
|
||||
The commands in here do random more or less useful things.
|
||||
|
||||
* `bind keys;reset key binds`: Reloads your key binds through the bindED plugin.
|
||||
You should do that after changing anything in the controls options.
|
||||
* `copy current system`: Copies the current system name into the clipboard.
|
||||
* `distance [from;to] […]`: Tells you the distance from your current position to
|
||||
the other thing you mentioned and is supported in the command. (requires
|
||||
Python scripts)
|
||||
* `do a barrow roll`: WHOOOOOOO!
|
||||
* `fix window dimensions`: When you start the game in VR, it forces into
|
||||
windowed mode with weird resolution. This changes it back. Hover the “PLAY”
|
||||
entry in the main menu, then run this. Will need adjustment for different
|
||||
graphics cards/drivers and the resolution you want.
|
||||
* `neutron [jump;trip] time`: Shorter version of the same thing in SpanshAttack.
|
||||
* `neutron jumps left`: Shorter version of the same thing in SpanshAttack.
|
||||
* `open copied system on EDSM`: Opens the system in your clipboard on EDSM in
|
||||
your default browser.
|
||||
* `open coriolis`: Opens Coriolis in your default browser.
|
||||
* `open [current;] system on EDSM`: Opens your current system on EDSM in your
|
||||
default browser.
|
||||
* `open EDDI options; configure EDDI`: Opens the EDDI configuration window.
|
||||
* `open e d d b [station;system;faction;] [search;]`: Opens EDDB in your default
|
||||
browser.
|
||||
* `open e d s m`: Opens EDSM in your default browser.
|
||||
* `open inara`: Opens Inara in your default browser.
|
||||
* `open materials finder`: Opens EDTutorials’ materials finder in your default
|
||||
browser.
|
||||
* `open miner’s tool`: Opens https://edtools.ddns.net/miner in your default
|
||||
browser.
|
||||
* `reload bindings`: Reloads your bindings for bindED.
|
||||
* `shut up EDDI`: Immediately stops any ongoing (and queued) EDDI speech.
|
||||
* `[start;stop] [EDISON;navigation]`: Hits `CTRL+ALT+E` which just so happens to
|
||||
be the start/stop hotkey I have set in E.D.I.S.O.N.
|
||||
* `[bodies;what’s;what is] left to [map;be mapped;scan]`: Tells you which bodies
|
||||
EDDI thinks are worth mapping in the system that you haven’t mapped yet.
|
||||
|
||||
### Navigation ###
|
||||
|
||||
There are so many navigation-focused commands now, they deserve there own
|
||||
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!
|
||||
|
||||
* `plot course;[target;] next [waypoint;way point]`: Plots a course to the
|
||||
system set in `~~system` or the one in your clipboard. The former way is
|
||||
usually used by other commands to not interfere with your clipboard.
|
||||
* `[find;target] nearest [encoded;manufactured;raw] material trader`: Targets
|
||||
the nearest respective material trader.
|
||||
* `[find;target] nearest [guardian;human] tech broker`: Targets the nearest respective
|
||||
tech broker.
|
||||
* `[find;target] nearest [interstellar factor;mission system;scoopable star]`: Well,
|
||||
you know the drill by now.
|
||||
* `[find;target] nearest mission system`: Targets the nearest system that has a mission
|
||||
target.
|
||||
* `[find;target] [<system>]`: Targets the given system on the galaxy map. There’s
|
||||
a bunch in there, the list is easily extensible. Drop me a note if you want
|
||||
something included.
|
||||
|
||||
### Ship Controls ###
|
||||
|
||||
Basically anything that is related to directly doing something with your ship.
|
||||
|
||||
* `[abort;cancel;stop] jumping`: Stops a currently charging FSD jump.
|
||||
* `[buggy;exploration] power`: Sets your PD to 0/4/2 or 2/4/0 respectively.
|
||||
Works in SRV too.
|
||||
* `[close;deploy;extend;open;retract;] […] [up;down;]`: Overly complicated
|
||||
command to handle everything related to Cargo Scoop, Hard Points, Landing
|
||||
Gear. You get the gist, I guess. Works in SRV too.
|
||||
* `[disco;discovery scan]`: Executes a discovery scan. To work properly, you’ll
|
||||
have to set the Discovery Scanner to your first fire group, secondary fire.
|
||||
* `[dis;]engage silent running`: Turns silent running on and off.
|
||||
* `[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,
|
||||
which sometimes leads to weird results.
|
||||
* `[jump;engage;get me out;punch it chewie] [and scan;] [when ready;]`: Retracts
|
||||
everything that might be protruding from your ship, then jumps to the next
|
||||
system. If the FSD isn’t charging within 1s, it gets you into SC instead (e.g.
|
||||
if your target is obstructed). If given “and scan” runs a discovery scan. If
|
||||
given “when ready” waits for mass lock to clear, your FSD to cool down and you
|
||||
to leave scoop range before jumping.
|
||||
* `night vision [on;off]`: Toggles your night vision on/off. Works in SRV too.
|
||||
* `power to [engines;shields;systems;weapons`: Sets 4 pips to the thing you told
|
||||
it, 1 to the others.
|
||||
* `rapid fire lights`: Flashes your lights 5 times in a row.
|
||||
* `retract [all;everything]`: Retracts, well, everything.
|
||||
* `[start;stop] [firing;mining]`: Starts/stops holding down primary fire. Mostly
|
||||
useful when mining. When triggered with “mining”, also deploys the cargo
|
||||
scoop.
|
||||
* `[super;] cruise [when ready;]`: Retracts everything, then jumps to SC. If
|
||||
given “when ready” will wait for mass lock to clear and your FSD to cool down
|
||||
first.
|
||||
|
||||
### SRV controls ###
|
||||
|
||||
Things relevant to your SRV, but not your ship.
|
||||
|
||||
* `[recall;dismiss] ship`: Recalls or dismisses ship. Currently does the same
|
||||
thing regardless of the state of your ship. I wish it would be possible to
|
||||
restrict it to doing one thing each, but that’s currently not possible sadly.
|
||||
* `[toggle;enable;disable] drive assist`: Handles all your drive assist needs!
|
||||
|
||||
### Targeting ###
|
||||
|
||||
Well … targeting stuff, I guess. Not really sure why I made that it’s own
|
||||
category, but oh well :)
|
||||
|
||||
* `target next system`: Selects the next system on your route.
|
||||
* `target wing man [1;2;3]`: Targets your wing men.
|
||||
* `target’s target`: Targets your target’s target.
|
||||
* `wing man [1;2;3] target`: Targets your wing men’s target.
|
||||
* `wing man nav lock`: Toggles wing man nav lock on the selected wing member.
|
||||
|
||||
### UI Commands ###
|
||||
|
||||
Everything handling stuff that’s not related to controlling your ship, but
|
||||
manipulating some UI element(s).
|
||||
|
||||
* `controls options`: Opens the controls options menu.
|
||||
* `docking request;request dock[ing;]`: Sends a docking request.
|
||||
* `[enter;leave] F S S`: Opens/closes FSS.
|
||||
* `galaxy map`: Opens the galaxy map.
|
||||
* `[main;game] menu`: Opens the ESC menu.
|
||||
* `[relog;reset] to [open;solo]`: Relogs to Open or Solo mode, respectively.
|
||||
* `restart from Desktop`: Quits the game and restarts from an open launcher by
|
||||
clicking the play button.
|
||||
* `set […] filter`: Sets a nav panel filter setting. See the command or just try
|
||||
different things for what is possible. You need to clear filters and hover
|
||||
over the filter button, then run this.
|
||||
* `system map`: Opens the system map.
|
||||
* `take [high res;] screenshot`: Takes a (high res) screenshot.
|
||||
* `toggle orbit lines`: Toggles the visibility of orbit lines.
|
||||
* `[toggle;show;hide] interface`: Toggles the cockpit interface (CTRL+ALT+G).
|
||||
Probably needs to be adjusted if you are not playing with Neo2 keyboard layout
|
||||
:)
|
||||
|
||||
### Update Commands ###
|
||||
|
||||
* `check for profiles update`: Does just that. Is also automatically run each
|
||||
time the profile is started.
|
||||
* `download profiles update`: Downloads a profiles update if applicable. Will
|
||||
prompt you to restart VoiceAttack when the download has finished to import the
|
||||
updated profiles.
|
||||
* `open profiles change log`: Opens `CHANGELOG.md` on Github.
|
||||
|
||||
## Logging ##
|
||||
|
||||
The profile supports logging a bunch of stuff to the VoiceAttack event log. By
|
||||
default, logging is concise and constrained to basically error messages.
|
||||
|
||||
If you need more logging (usually for debugging purposes), say `enable logging`.
|
||||
If you want to enable verbose logging _by default_, call the
|
||||
`Logging.enableLogging` command from your custom profile’s `startup` command.
|
||||
|
||||
## Configuration Variables ##
|
||||
|
||||
There are a bunch of configuration variables. You should not overwrite those
|
||||
manually, instead use the provided commands in the `_configuration` section!
|
||||
|
||||
Basically all the settings are available using the `customize settings` prefix,
|
||||
then saying `[enable;disable] <setting>` for on/off switches and `set <setting>`
|
||||
for text variables.
|
||||
|
||||
* `EDDI.quietMode` (boolean): whether or not to set EDDI to quite mode. Default:
|
||||
true.
|
||||
* `Elite.pasteKey` (string): the key used for pasting into Elite. On QWERTY this
|
||||
is `v`. Default: `p`.
|
||||
* `EliteDangerous.announceEdsmSystemStatus` (boolean): whether to announce the
|
||||
system or some of its bodies missing on EDSM. Default: true.
|
||||
* `EliteDangerous.announceMappingCandidates` (boolean): whether to announce
|
||||
mapping candidates when they are scanned. Default: true.
|
||||
* `EliteDangerous.announceOutdatedStationData` (boolean): whether to announce
|
||||
stations with outdated data in systems you jump to. Default: true.
|
||||
* `EliteDangerous.announceR2RMappingCandidates` (boolean): whether to announce
|
||||
planets worth mapping when jumping into a known system. This is useful for
|
||||
doing some R2R on the side. Default: false.
|
||||
* `EliteDangerous.autoChangeFuelratsNick` (boolean): whether to change the
|
||||
FuelRats IRC nickname automatically when changing commanders. Probably largely
|
||||
irrelevant to you. Default: false.
|
||||
* `EliteDangerous.enableCarrierAnnouncements` (boolean): whether or not to
|
||||
process fleet carrier events. Default: true.
|
||||
* `EliteDangerous.enableAutoUpdateCheck` (boolean): whether or not to
|
||||
automatically check for updates on profile startup. Default: true.
|
||||
* `EliteDangerous.flightAssistOff` (boolean): whether to automatically toggle
|
||||
FlightAssist off on liftoff. Default: true.
|
||||
* `EliteDangerous.hyperspaceDethrottle` (boolean): same thing as the SC assist
|
||||
setting; if on, will throttle to 0 automatically after jumping. Default: true.
|
||||
* `EliteDangerous.oldStationThreshold` (int): Age in days that will cause
|
||||
station data to be considered outdated. Default: 365 (1 year).
|
||||
* `python.ScriptPath` (string): the path you have placed the compiled python
|
||||
scripts in. Default: “{VA_DIR}\Sounds\scripts” (the “\Sounds\scripts” folder
|
||||
in your VoiceAttack installation directory).
|
||||
|
||||
#### Delays / Pauses ####
|
||||
|
||||
Delays needed e.g. between key presses in UI navigation can vary wildly
|
||||
depending on your PC’s specs and configuration. Therefore they should be
|
||||
configurable, shouldn’t they?
|
||||
|
||||
So far those actually are:
|
||||
|
||||
* `EliteDangerous.delays.quitToDesktop`: Delay between quitting to desktop and hitting the
|
||||
play button in the launcher.
|
|
@ -1,4 +1,4 @@
|
|||
# RatAttack #
|
||||
# RatAttack
|
||||
|
||||
This profile facilitates [Fuel Ratting](https://www.fuelrats.com). It aims to
|
||||
eliminate as much of the required manual task and attention switching as
|
||||
|
@ -6,155 +6,52 @@ possible via automation and voice commands.
|
|||
|
||||
If you don’t know what the Fuel Rats are, come hang out and ask :)
|
||||
|
||||
## Requirements ##
|
||||
|
||||
Only vanilla VoiceAttack is absolutely required to use this profile. Optionally
|
||||
you can install EDDI and my elite scripts for advanced features.
|
||||
|
||||
* [EDDI](https://github.com/EDCD/EDDI) installed as a VoiceAttack plugin: This
|
||||
will give you a better (IMO) way of using TTS. Be sure to set
|
||||
`RatAttack.useEddiForVoice`. It will also enable you to have ingame chat be
|
||||
transferred to IRC; see below.
|
||||
* [elite-scripts](https://github.com/alterNERDtive/elite-scripts): Using the
|
||||
Python scripts will give RatAttack a way to be aware of where your CMDRs are
|
||||
and give you the nearest one to a rat case. That’s only really needed if you
|
||||
actually _have_ multiple CMDRs, obviously. If you are using the profile
|
||||
package from the release page, they will be installed automatically.
|
||||
|
||||
### EDDI speech responder ###
|
||||
|
||||
For the convenience of people that have not been using EDDI in the past,
|
||||
RatAttack will deactivate the speech responder automatically to not clutter them
|
||||
with unwanted TTS.
|
||||
|
||||
If you are already an EDDI user and want to keep the default speech responder
|
||||
functionality, you will have to disable the `EDDI.quietMode` setting by running
|
||||
the `customize settings disable eddi quiet mode` command.
|
||||
|
||||
## Settings ##
|
||||
|
||||
There are a lot of preferences you can set, including some you really want to
|
||||
concern yourself with before you start using the profile. Some of the more
|
||||
advanced features heavily rely on you giving it the correct things to work with.
|
||||
|
||||
See the [Configuration Variables](#Configuration-Variables) section.
|
||||
|
||||
## Including the Profile ##
|
||||
|
||||
When including the profile, be sure to
|
||||
|
||||
* Run the startup command. You will need to have a startup command in your
|
||||
profile (= one that is run on profile loading) and call `RatAttack.startup`
|
||||
from that one.
|
||||
* Make sure all EDDI events that RatAttack needs are correctly handled. For all
|
||||
events used in RatAttack that you already have handlers for in your profile,
|
||||
you’ll have to include a call to `RatAttack.<event name>`. E.g. for “EDDI
|
||||
Message sent”, call `RatAttack.EDDI Message sent` by name from your `((EDDI
|
||||
Message sent))` command.
|
||||
|
||||
## Usage ##
|
||||
|
||||
### Going On/Off Duty ###
|
||||
## Going On/Off Duty
|
||||
|
||||
When you are on duty, RatAttack will automatically announce cases coming in
|
||||
through IRC. When off duty, it won’t.
|
||||
|
||||
* `[enable;disable] rat duty`: puts you on/off duty.
|
||||
* `open [rat;] dispatch board`: opens the web dispatch board.
|
||||
* `open [fuel rats;] dispatch board`: opens the web dispatch board.
|
||||
|
||||
### Handling a Case ###
|
||||
## Case Handling
|
||||
|
||||
#### Getting Case Data From IRC ####
|
||||
[If you have your IRC client setup
|
||||
properly](../configuration/RatAttack/#getting-case-data-from-irc), VoiceAttack
|
||||
will hold a list with all rat cases that have come in while you had it running.
|
||||
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:
|
||||
|
||||
You can setup your IRC client to pass incoming RATSIGNALS to VoiceAttack by
|
||||
writing them to a file (`%appdata%\Ratattack\ratsignal.pipe`), then calling the
|
||||
appropriate command (`RatAttack.announceCaseFromRatsignal` for notification,
|
||||
`RatAttack.getInfoFromRatsignal` for silently putting it into the case list).
|
||||
### Getting Case Information
|
||||
|
||||
This has two purposes:
|
||||
|
||||
1. announcing a new incoming case
|
||||
1. storing case data and making it available to VoiceAttack, e.g. for copying
|
||||
the case’s system into the clipboard
|
||||
|
||||
You need to make your IRC client
|
||||
|
||||
1. wait until the file disappears (for several cases coming in at once)
|
||||
1. write the RATSIGNAL to the file
|
||||
1. run the VoiceAttack command
|
||||
|
||||
In my case I am running AdiIRC and have the following script setup for handling
|
||||
this:
|
||||
|
||||
```
|
||||
on *:TEXT:RATSIGNAL - CMDR*(??_SIGNAL):#fuelrats:{
|
||||
/mkdir C:\users\<user>\appdata\roaming\RatAttack\
|
||||
/handleratsignal $1-
|
||||
}
|
||||
alias handleratsignal {
|
||||
if ( $exists(C:\users\<user>\appdata\roaming\RatAttack\ratsignal.pipe) ) {
|
||||
/sleep 1 /handleratsignal $1-
|
||||
}
|
||||
else {
|
||||
/write C:\users\<user>\appdata\roaming\RatAttack\ratsignal.pipe $1-
|
||||
if ( $away ) {
|
||||
/run -h "X:\path\to\VoiceAttack\VoiceAttack.exe" -nofocus -command "RatAttack.getInfoFromRatSignal"
|
||||
}
|
||||
else {
|
||||
/run -h "X:\path\to\VoiceAttack\VoiceAttack.exe" -nofocus -command "RatAttack.announceCaseFromRatSignal"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You get the gist; if not and you don’t know how to do the same thing for your
|
||||
IRC client or it doesn’t support copying the control characters in the ratsignal
|
||||
that the profile uses to split the information, either switch to AdiIRC or bribe
|
||||
me to include some other way to get case data into VoiceAttack.
|
||||
|
||||
**Note**: If you are running VoiceAttack as admin you need to run your IRC
|
||||
client as admin, too! Otherwise it can’t talk to VoiceAttack for security
|
||||
reasons. You really should _not_ run VoiceAttack with elevated privileges
|
||||
though. Or anything.
|
||||
|
||||
#### Internal Case List ####
|
||||
|
||||
If you have your IRC client setup properly, VoiceAttack will hold a list with
|
||||
all rat cases that have come in while you had it running. 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:
|
||||
|
||||
* `rat case number [0..19] details`: Will give you all stored info on a case.
|
||||
* `rat case number [0..30] details`: Will give you all stored info on a case.
|
||||
* `[current;] rat case details`: Will give you all stored info on the currently
|
||||
open case.
|
||||
* `distance to current rat case`: Will give you the distance from your current
|
||||
location to the currently opened rat case. Requires the use of my
|
||||
`elite-scripts` Python scripts.
|
||||
* `distance to rat case number [0..19]`: Will give you the distance from your
|
||||
current system to a case’s system. Requires the use of my `elite-scripts`
|
||||
Python scripts.
|
||||
* `nearest commander to rat case number [0..19]`: Will give you the nearest of
|
||||
your CMDRs with their distance to a case’s system. Requires some setup and the
|
||||
use of my `elite-scripts` Python scripts.
|
||||
* `nearest commander to [the;] rat case`: Will give you the nearest of your
|
||||
CMDRs with their distance to the current case’s system. Requires some setup
|
||||
and the use of my `elite-scripts` Python scripts.
|
||||
location to the currently opened rat case.
|
||||
* `distance to rat case number [0..30]`: Will give you the distance from your
|
||||
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
|
||||
your CMDRs with their distance to a case’s system. [Requires some
|
||||
setup](../configuration/RatAttack/#announcing-your-nearest-cmdr).
|
||||
* `nearest commander to [the;] rat case`: Will give you the nearest of your
|
||||
CMDRs with their distance to the current case’s system. [Requires some
|
||||
setup](../configuration/RatAttack/#announcing-your-nearest-cmdr).
|
||||
|
||||
#### Opening a Case ####
|
||||
### Opening a Case
|
||||
|
||||
* `open rat case number [0..19]`: Opens rat case with the given number. If there
|
||||
* `open rat case number [0..30]`: Opens rat case with the given number. If there
|
||||
is no case data for that case (e.g. because you don’t have your IRC client set
|
||||
up properly), it will still open it, just not have any data on it.
|
||||
* `open [latest;] rat case`: Opens the latest rat case that has come in through
|
||||
IRC. Will probably error out in creative ways if you don’t have your IRC
|
||||
client set up properly. Too tired right now to have proper error handling so
|
||||
just open an issue if you run into problems (it’s 7am, I haven’t slept and
|
||||
want to finish this doc to get the release out (yes, you are allowed to laugh
|
||||
at this section)).
|
||||
* `open [latest;] rat case`: Opens the latest rat case that has come in through
|
||||
IRC. Will only work if you actually have [your IRC client setup to send case
|
||||
announcements to
|
||||
VoiceAttack](../configuration/RatAttack/#getting-case-data-from-irc).
|
||||
|
||||
#### Closing a Case ####
|
||||
|
||||
* `[close;clear] rat case`: Closes the currently open rat case.
|
||||
Opening a case will automatically copy the client’s system to the clipboard for
|
||||
easy route plotting. This can be disabled.
|
||||
|
||||
### Making Calls ###
|
||||
|
||||
|
@ -164,29 +61,34 @@ 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
|
||||
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
|
||||
login to the game or have to take off from your current
|
||||
station/port/outpost/planet.
|
||||
* `call friend [positive;negative] [in pg;in private group;in solo;in main
|
||||
meu;sysconf;system confirmed]`: Friend request confirmations, with all the
|
||||
* `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;]`:
|
||||
Friend request confirmations, with all the
|
||||
things you might want to / should call with it.
|
||||
* `call [beacon;fuel;instance;pos;position;prep;sys;system;wing]
|
||||
[positive;negative]`: All the stuff you usually need for ratting after you
|
||||
have received the friend request.
|
||||
* `call [beacon;fuel;instance;pos;position;prep;sys;system;wing] [positive;negative]`:
|
||||
All the stuff you usually need for ratting after you have received the friend request.
|
||||
* `call wing pending`: Calls “wr pending” for when it takes 30s again to
|
||||
actually show up.
|
||||
* `call client in [exclusion zone;main menu;open;open sysconf;pg;private
|
||||
group;solo;super cruise]`: Callouts for all the various things a client could
|
||||
get themselves into.
|
||||
* `call client in [exclusion zone;main menu;open;open sysconf;pg;private group;solo;super cruise]`:
|
||||
Callouts for all the various things a client could get themselves into.
|
||||
* `call [client destroyed;client offline;sysconf;system confirmed]`: This is the
|
||||
command you don’t want to use. Include sysconf in your “friend+” or “in open”
|
||||
calls, and make sure you will never have to call “client destroyed”, would
|
||||
you?
|
||||
|
||||
### General IRC Interaction ###
|
||||
By default, VoiceAttack will ask for confirmation before sending calls to the
|
||||
`#fuelrats` channel.
|
||||
|
||||
(requires EDDI)
|
||||
### Closing a Case
|
||||
|
||||
* `[close;clear] rat case`: Closes the currently open rat case.
|
||||
|
||||
## General IRC Interaction
|
||||
|
||||
Using EDDI to read the game’s journal, you can send messages to IRC from Elite’s
|
||||
ingame chat.
|
||||
|
@ -198,86 +100,11 @@ I recommend using local chat and limiting the use to instances that will
|
|||
probably not have other players in it (e.g. instanced in normal space with the
|
||||
client or in SC in some remote system out in the black on a long range rescue).
|
||||
|
||||
* #fuelrats: Use “.fr \<message\>” to have VoiceAttack send “#\<caseNumber\>
|
||||
\<message\>” to the #fuelrats channel – or yell at you when you are not on
|
||||
a case.
|
||||
* #ratchat: Use “.rc \<message\>” to have VoiceAttack send “\<message\>” to
|
||||
#ratchat.
|
||||
* \#fuelrats: Use `.fr <message>` to have VoiceAttack send
|
||||
`#<caseNumber> <message>` to \#fuelrats – or yell at you when you
|
||||
are not on a case.
|
||||
* \#ratchat: Use `.rc <message>` to have VoiceAttack send `<message>` to
|
||||
\#ratchat.
|
||||
|
||||
These commands send their text to windows with “#fuelrats” and “#ratchat” in
|
||||
their title, respectively. If your IRC client does not do that, you will have to
|
||||
change the “target” window of the `RatAttack.sendToFuelrats` and
|
||||
`RatAttack.sendToRatchat` commands to reflect the actual window titles on your
|
||||
system. I will look into making this more elegant to change in the future.
|
||||
|
||||
## Logging ##
|
||||
|
||||
The profile supports logging a bunch of stuff to the VoiceAttack event log. By
|
||||
default, logging is concise and constrained to basically error messages.
|
||||
|
||||
If you need more logging (usually for debugging purposes), say `enable logging`.
|
||||
If you want to enable verbose logging _by default_, call the
|
||||
`Logging.enableLogging` command from your custom profile’s `startup` command.
|
||||
|
||||
## Exposed Variables ##
|
||||
|
||||
The following Variables are _global_ and thus readable (and writeable! Please
|
||||
don’t unless it’s a config variable …) from other profiles.
|
||||
|
||||
### Configuration Variables ###
|
||||
|
||||
There are a bunch of configuration variables. You should not overwrite those
|
||||
manually, instead use the provided commands in the `_configuration` section!
|
||||
|
||||
Basically all the settings are available using the `customize settings` prefix,
|
||||
then saying `[enable;disable] <setting>` for on/off switches and `set <setting>`
|
||||
for text variables.
|
||||
|
||||
* `EDDI.quietMode` (boolean): whether or not to set EDDI to quite mode. Default:
|
||||
true.
|
||||
* `EDDI.useEddiForVoice` (boolean): whether to use the EDDI plugin to handle
|
||||
text-to-speech over VoiceAttacks built-in speech function. Default: false.
|
||||
* `Elite.pasteKey` (string): the key used for pasting into Elite. On QWERTY this
|
||||
is `v`. Default: `v`.
|
||||
* `RatAttack.announceNearestCMDR` (boolean): whether or not to automatically
|
||||
announce your nearest CMDR to a case. Requires the `elite-scripts` Python
|
||||
scripts. Will probably break in creative ways if you don’t have them and turn
|
||||
it on anyway. Default: false.
|
||||
* `RatAttack.announcePlatform` (boolean): whether or not to announce the case’s
|
||||
platform by default. Useful to set if you are active on more than one
|
||||
platform. Even with this off, you will still be warned when you open a case
|
||||
that is _not_ on one of your platforms. Default: false.
|
||||
* `RatAttack.CMDRs` (string): list of your CMDR names, delimited by spaces. If
|
||||
your names include spaces, you will have to put them in quotes. Default: “"J
|
||||
Jora Jameson" NameWithNoSpace”.
|
||||
* `RatAttack.confirmCalls` (boolean): whether VoiceAttack should ask you before
|
||||
posting to #fuelrats to make sure there hasn’t been an error in voice
|
||||
recognition and you accidentally post the wrong thing. Default: true.
|
||||
* `RatAttack.autoCloseCase` (boolean): whether or not to automatically close an
|
||||
open rat case on calling “fuel+”. Default: false.
|
||||
* `RatAttack.onDuty` (boolean): whether or not you are currently on rat duty.
|
||||
Default: true.
|
||||
* `RatAttack.platforms` (string): the platforms you want to be informed of
|
||||
incoming cases for. If you are on console, you can still have VoiceAttack
|
||||
running on the PC that you are using for IRC and handle calls and stuff using
|
||||
voice! Delimited by whatever you want. Can include “PC”, “XB”, “PS4”.
|
||||
Default: “PC”.
|
||||
* `python.scriptPath` (string): the path you put the Python scripts in. Default:
|
||||
“{VA_DIR}\Sounds\scripts”.
|
||||
|
||||
### Other Variables ###
|
||||
|
||||
Current case data:
|
||||
|
||||
* `RatAttack.caseNumber` (int): the number of the case you are currently on.
|
||||
Will be `Not Set` if you are not on a case.
|
||||
* `RatAttack.onCase` (boolean): whether or not you are currently on a case.
|
||||
|
||||
Case list:
|
||||
|
||||
* `RatAttack.caseList.<case#>.cmdr` (string)
|
||||
* `RatAttack.caseList.<case#>.system` (string)
|
||||
* `RatAttack.caseList.<case#>.platform` (string)
|
||||
* `RatAttack.caseList.<case#>.codeRed` (boolean)
|
||||
|
||||
… with `<case#>` being a number between 0 and 19.
|
||||
Make sure [that your IRC client is setup
|
||||
properly](../configuration/RatAttack/#sending-text-to-fuelrats-irc).
|
||||
|
|
|
@ -1,99 +1,34 @@
|
|||
# SpanshAttack #
|
||||
# SpanshAttack
|
||||
|
||||
This profile uses the
|
||||
[ED-NeutronRouter](https://github.com/sc-pulgan/ED-NeutronRouter) plugin to plot
|
||||
neutron jumps using [spansh](https://spansh.co.uk/plotter). It fully does
|
||||
everything you need from within the game and VoiceAttack, you won’t have to
|
||||
visit the site at any point.
|
||||
[ED-NeutronRouter](https://github.com/sc-pulgan/ED-NeutronRouter) plugin to
|
||||
plot neutron jumps using [Spansh](https://spansh.co.uk/plotter). It does
|
||||
everything you need fully from within the game and VoiceAttack, you won’t have
|
||||
to visit the site at any point.
|
||||
|
||||
## Requirements ##
|
||||
|
||||
In addition to VoiceAttack, you will need the following plugins to use this
|
||||
profile:
|
||||
|
||||
* [bindED](https://forum.voiceattack.com/smf/index.php?topic=564.0)
|
||||
* [EDDI](https://github.com/EDCD/EDDI) installed as a VoiceAttack plugin
|
||||
* [ED-NeutronRouter](https://github.com/sc-pulgan/ED-NeutronRouter): required
|
||||
for SpanshAttack. **Make sure to [grab the pre-release
|
||||
1.02](https://github.com/sc-pulgan/ED-NeutronRouter/releases/tag/1.02)** since
|
||||
1.01 has a bug with a hardcoded 50 ly jump range.
|
||||
|
||||
### EDDI speech responder ###
|
||||
|
||||
For the convenience of people that have not been using EDDI in the past,
|
||||
SpanshAttack will deactivate the speech responder automatically to not clutter
|
||||
them with unwanted TTS.
|
||||
|
||||
If you are already an EDDI user and want to keep the default speech responder
|
||||
functionality, you will have to disable the `EDDI.quietMode` setting by running
|
||||
the `customize settings disable eddi quiet mode` command.
|
||||
|
||||
## Settings ##
|
||||
|
||||
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] layout, you will have to change it back to the key that is physically
|
||||
in the place where `v` would be on QWERTY.
|
||||
|
||||
For other settings, see the [Configuration Variables](#Configuration-Variables)
|
||||
section.
|
||||
|
||||
The last “setting” in the not-so-strict sense of the word is the
|
||||
`SpanshAttack.getShipRange` command. Any ship listed in there will automatically
|
||||
have its jump range used instead of VA prompting you for it. Since, again, VA
|
||||
will execute the first matching command found, you can create this command in
|
||||
your own profile when you are using SpanshAttack by including it. You can
|
||||
override a saved range for your ship by using the `plot neutron
|
||||
[course;route;trip] with custom range` command.
|
||||
|
||||
The ED-NeutronRouter plugin is technically supposed to read the current jump
|
||||
range from EDDI; sadly a) it’s
|
||||
[bugged](https://github.com/sc-pulgan/ED-NeutronRouter/issues/3) right now, and
|
||||
b) EDDI is storing the _maximum_ distance for your ship instead of the current
|
||||
/ full on fuel one.
|
||||
|
||||
## Including the Profile ##
|
||||
|
||||
When including the profile, be sure to
|
||||
|
||||
* Run the startup command. You will need to have a startup command in your
|
||||
profile (= one that is run on profile loading) and call `SpanshAttack.startup`
|
||||
from that one.
|
||||
* Make sure all EDDI events that SpanshAttack needs are correctly handled. For
|
||||
all events used in SpanshAttack that you already have handlers for in your
|
||||
profile, you’ll have to include a call to `SpanshAttack.<event name>`. E.g.
|
||||
for “EDDI Jumped”, call `SpanshAttack.EDDI Jumped` by name from your `((EDDI
|
||||
Jumped))` command.
|
||||
* (Optional) Have a `SpanshAttack.getShipRange` command in your profile to
|
||||
overwrite the default one with your ship’s ranges. See the default command for
|
||||
pointers.
|
||||
|
||||
## Usage ##
|
||||
|
||||
### Plotting a Route ###
|
||||
## Plotting a Route
|
||||
|
||||
1. _Target_ the system you want to be routed to (target, do not plot to it).
|
||||
1. Either exit the galaxy map or make sure you are on its first tab (or
|
||||
auto-plotting will break).
|
||||
1. Trigger the `SpanshAttack.plotRoute` command either by voice (`plot neutron
|
||||
[course;route;trip] [with custom range;]`) or calling it from another
|
||||
command.
|
||||
1. Trigger the `SpanshAttack.plotRoute` command either by voice
|
||||
(`plot neutron [course;route;trip] [with custom range;]`) or by
|
||||
calling it from another command.
|
||||
1. Enter your ship’s jump range if prompted.
|
||||
1. Wait for the route to be calculated. The command will automatically open the
|
||||
galaxy map and jump to the first waypoint on your route. If you run into
|
||||
weird behaviour, it’s probably because your target system is not in EDDB.
|
||||
galaxy map and search it for the first waypoint on your route.
|
||||
1. Either target the first waypoint or plot to it.
|
||||
1. Start jumping!
|
||||
|
||||
#### 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 data base (obviously
|
||||
can also only give you way points that are). If your target system is not, there
|
||||
The router can only plot a route to a system that is in its database (obviously
|
||||
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.
|
||||
|
||||
1. Check `Next system` coordinates provided by EDDI. If the system is in EDSM,
|
||||
but has for some reason not been sent over EDDN to other sites including
|
||||
Spansh we can get coordinates here.
|
||||
Spansh, we can get coordinates here.
|
||||
1. If the system is not in EDSM check EDTS. It can calculate approximate
|
||||
coordinates for a given procedurally generated system name.
|
||||
1. If that fails prompt the user for input.
|
||||
|
@ -106,39 +41,51 @@ you will be prompted to make sure you are going roughly to the right
|
|||
coordinates. You will find the system that is used for plotting, its
|
||||
coordinates and the accuracy in VoiceAttack’s log window.
|
||||
|
||||
### Neutron Jumping ###
|
||||
## Neutron Jumping
|
||||
|
||||
With standard settings, just supercharge off a neutron cone. You should
|
||||
automatically be taken to the galaxy map with the next waypoint selected.
|
||||
|
||||
In case you have disabled auto-plotting to the next waypoint, manually invoke
|
||||
the `SpanshAttack.targetNextNeutronWaypoint` command by voice (`[target;] next
|
||||
neutron [waypoint; way point]`) or calling it from another command.
|
||||
the `SpanshAttack.targetNextNeutronWaypoint` command by voice
|
||||
(`[target;] next neutron [waypoint; way point]`) or calling it from
|
||||
another command.
|
||||
|
||||
Additionally, you can use the `SpanshAttack.copyNextNeutronWaypoint`
|
||||
/ `[get;copy] next neutron [waypoint;way point]` command to copy the next
|
||||
neutron waypoint to the clipboard.
|
||||
|
||||
#### Manual Re-Plot ####
|
||||
### Skipping a Waypoint
|
||||
|
||||
Trigger the `SpanshAttack.replotRoute` command either by voice (`replot neutron
|
||||
[course;route;trip]`) or calling it from another command. This will start
|
||||
a re-plot of the current route with the same target system and jump range.
|
||||
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.
|
||||
|
||||
### Refueling ###
|
||||
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.
|
||||
|
||||
Whenever you refuel off a scoopable star, the profile will automatically
|
||||
throttle back up to 100% speed. Unless you have disabled it in your
|
||||
configuration, you will also automatically target the next system on your route
|
||||
and jump to it once you leave fuel scoop range.
|
||||
### Manual Re-Plot
|
||||
|
||||
### Clearing a Route ###
|
||||
Trigger the `SpanshAttack.replotRoute` command either by voice
|
||||
(`replot neutron [course;route;trip]`) or calling it from another command.
|
||||
This will start a re-plot of the current route with the same target system and
|
||||
jump range.
|
||||
|
||||
When you reach your target system, the neutron route will automatically be
|
||||
cleared. If you want to prematurely end your trip, call the
|
||||
## Refueling
|
||||
|
||||
Whenever you finish refueling off a scoopable star, the profile will
|
||||
automatically throttle back up to 100% speed. Unless you have disabled it in
|
||||
your configuration, you will also automatically target the next system on your
|
||||
route and jump to it once you leave fuel scoop range.
|
||||
|
||||
## Clearing a Route
|
||||
|
||||
When you reach your target system the neutron route will automatically be
|
||||
cleared. If you want to prematurely end your trip, call the
|
||||
`SpanshAttack.clearRoute` / `clear neutron [course;route;trip]` command.
|
||||
|
||||
## Other Commands ##
|
||||
## Other Commands
|
||||
|
||||
### Announcing Jumps Left ###
|
||||
|
||||
|
@ -155,87 +102,4 @@ neutron waypoint_.
|
|||
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
|
||||
`SpanshAttack.announceTripTime` or
|
||||
`how long have i been [jumping;on this trip;on this neutron trip]?` commands.
|
||||
|
||||
### Reload bindings ###
|
||||
|
||||
If you change any relevant bindings (e.g. the galaxy map key), you should run
|
||||
the `reload bindings` command to make sure that SpanshAttack presses the right
|
||||
thing for you.
|
||||
|
||||
Eh, just do it every time you edit your controls without re-starting
|
||||
VoiceAttack, just to be sure.
|
||||
|
||||
### Helper Functions ###
|
||||
|
||||
The profile contains a lot of helper functions that get called by the
|
||||
aforementioned commands. Have a look around, maybe learn something about
|
||||
VoiceAttack :)
|
||||
|
||||
## Logging ##
|
||||
|
||||
The profile supports logging a bunch of stuff to the VoiceAttack event log. By
|
||||
default, logging is concise and constrained to basically error messages.
|
||||
|
||||
If you need more logging (usually for debugging purposes), say `enable logging`.
|
||||
If you want to enable verbose logging _by default_, call the
|
||||
`Logging.enableLogging` command from your custom profile’s `startup` command.
|
||||
|
||||
## Exposed Variables ##
|
||||
|
||||
The following Variables are _global_ and thus readable (and writeable! Please
|
||||
don’t unless it’s a config variable …) from other profiles:
|
||||
|
||||
### Configuration Variables ###
|
||||
|
||||
There are a bunch of configuration variables. You should not overwrite those
|
||||
manually, instead use the provided commands in the `_configuration` section!
|
||||
|
||||
Basically all the settings are available using the `customize settings` prefix,
|
||||
then saying `[enable;disable] <setting>` for on/off switches and `set <setting>`
|
||||
for text variables.
|
||||
|
||||
* `EDDI.quietMode` (boolean): whether or not to set EDDI to quite mode. Default:
|
||||
true.
|
||||
* `EDDI.useEddiForVoice` (boolean): whether to use EDDI over VA’s builtin `say`
|
||||
command. Default: false.
|
||||
* `Elite.pasteKey` (string): the key used for pasting into Elite. On QWERTY this
|
||||
is `v`. Default: `v`.
|
||||
* `SpanshAttack.timeTrip` (boolean): whether to automatically tell you at the
|
||||
end of a trip how long it took you to get there. Default: false.
|
||||
* `SpanshAttack.announceWaypoints` (boolean): whether to announce each waypoint
|
||||
of the neutron route. Default: true.
|
||||
* `SpanshAttack.announceJumpsLeft` (string): `;`-separated list of remaining
|
||||
jumps to announce when said amounts are reached. Right now only works if they
|
||||
are _exactly_ reached when supercharging off a neutron. Note the extra `;` at
|
||||
the beginning and end of the string. Default: `;1;3;5;10;15;20;30;50;75;100;`
|
||||
* `SpanshAttack.autoJumpAfterScooping` (boolean): whether to automatically jump
|
||||
after fuel scooping (and moving out of scoop range). Default: true.
|
||||
* `SpanshAttack.autoPlot` (boolean): whether to automatically plot to the next
|
||||
waypoint on supercharging. Default: true.
|
||||
* `SpanshAttack.clearOnShutdown` (boolean): whether or not to automatically
|
||||
clear an active neutron route on Elite client shutdown. Default: true.
|
||||
* `SpanshAttack.defaultToLadenRange` (boolean): whether or not to default to
|
||||
your ship’s laden range (as reported by EDDI) instead of asking for user
|
||||
input. Sadly it’s with _current_ fuel, not full. Setting a ship’s jump range
|
||||
in the `SpanshAttack.getShipRange` command will still overrule this. Default:
|
||||
false.
|
||||
* `SpanshAttack.copyWaypointToClipboard` (boolean): whether to copy the next
|
||||
waypoint into the Windows clipboard for use in other programs. Default: false.
|
||||
* `python.scriptPath` (string): the path you put the Python scripts in.
|
||||
Default: “{VA_DIR}\Sounds\scripts”.
|
||||
|
||||
### Other Variables ###
|
||||
|
||||
These variables can be used to get information about the current neutron route.
|
||||
Please do not set them manually and / or from outside the SpanshAttack profile.
|
||||
|
||||
* `SpanshAttack.plotSystem` (string): the system actually plotted towards using
|
||||
the neutron router (onley used/set if the target system is not in the data
|
||||
base)
|
||||
* `SpanshAttack.targetSystem` (string): the target system for the current
|
||||
neutron route
|
||||
* `SpanshAttack.nextNeutronWaypoint` (string): the next waypoint on the current
|
||||
neutron route
|
||||
* `SpanshAttack.neutronJumpMode` (boolean): neutron jump mode active/inactive
|
||||
* `SpanshAttack.jumpRange` (decimal): the current ship’s jump range
|
||||
`how long have i been [jumping;on this trip;on this neutron trip]?` commands.
|
||||
|
|
|
@ -1,120 +1,52 @@
|
|||
# StreamAttack #
|
||||
# StreamAttack
|
||||
|
||||
This profile uses the [EDDI](https://github.com/EDCD/EDI) 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
|
||||
to files that can be accessed e.g. by your streaming software to be displayed on
|
||||
stream.
|
||||
|
||||
Default folder is `%appdata%\StreamAttack\`.
|
||||
|
||||
## Requirements ##
|
||||
## Commands
|
||||
|
||||
In addition to VoiceAttack, you will need the following plugins to use this
|
||||
profile:
|
||||
|
||||
* [EDDI](https://github.com/EDCD/EDDI) installed as a VoiceAttack plugin
|
||||
|
||||
### EDDI speech responder ###
|
||||
|
||||
For the convenience of people that have not been using EDDI in the past,
|
||||
StreamAttack will deactivate the speech responder automatically to not clutter
|
||||
them with unwanted TTS.
|
||||
|
||||
If you are already an EDDI user and want to keep the default speech responder
|
||||
functionality, you will have to disable the `EDDI.quietMode` setting by running
|
||||
the `customize settings disable eddi quiet mode` command.
|
||||
|
||||
## Settings ##
|
||||
|
||||
See the [Configuration Variables](#Configuration-Variables) section.
|
||||
|
||||
## Including the Profile ##
|
||||
|
||||
When including the profile, be sure to
|
||||
|
||||
* Run the startup command. You will need to have a startup command in your
|
||||
profile (= one that is run on profile loading) and call `StreamAttack.startup`
|
||||
from that one.
|
||||
* Make sure all EDDI events that StreamAttack needs are correctly handled. For
|
||||
all events used in StreamAttack that you already have handlers for in your
|
||||
profile, you’ll have to include a call to `StreamAttack.<event name>`. E.g.
|
||||
for “EDDI Jumped”, call `StreamAttack.EDDI Jumped` by name from your `((EDDI
|
||||
Jumped))` command.
|
||||
|
||||
## Commands ##
|
||||
|
||||
* `clear jump target`: clears the current jump target.
|
||||
* `set jump target`: sets the jump target to the currently targeted system.
|
||||
* `clear jump target`: Clears the current jump target.
|
||||
* `distance [to;from] jump target`: Tells you the current distance to the jump
|
||||
target.
|
||||
* `set jump target`: Sets the jump target to the currently targeted system.
|
||||
Distance will be written to the configured file.
|
||||
|
||||
* `[copy;open] ship build`: copies the current ship build (coriolis) or opens it
|
||||
* `[copy;open] ship build`: Copies the current ship build (coriolis) or opens it
|
||||
in your default browser.
|
||||
* `open StreamAttack folder`: opens the configured folder in Explorer.
|
||||
* `open StreamAttack folder`: Opens the configured folder in Explorer.
|
||||
|
||||
## Files the Profile Provides ##
|
||||
## Output Files
|
||||
|
||||
### Elite ###
|
||||
### Elite
|
||||
|
||||
#### Commander ####
|
||||
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.
|
||||
|
||||
* `Elite\cmdr\name`: the current commander’s name.
|
||||
#### Commander
|
||||
|
||||
#### Jump Target ####
|
||||
* `Elite\cmdr\name`: The current commander’s name.
|
||||
|
||||
* `Elite\jumpTarget\distance`: distance to current jump target in light years.
|
||||
* `Elite\jumpTarget\full`: pretty-printed `<distance> ly to <name>`.
|
||||
* `Elite\jumpTarget\name`: the current jump target’s system name.
|
||||
#### Jump Target
|
||||
|
||||
#### Location ####
|
||||
* `Elite\jumpTarget\distance`: Distance to current jump target in light years.
|
||||
* `Elite\jumpTarget\full`: Pretty-printed `<distance> ly to <name>`.
|
||||
* `Elite\jumpTarget\name`: The current jump target’s system name.
|
||||
|
||||
* `Elite\location\full`: depending on your status, either the station you are
|
||||
#### Location
|
||||
|
||||
* `Elite\location\full`: Depending on your status, either the station you are
|
||||
currently docked at (+ system), the body you are currently near, or the system
|
||||
you are currently in.
|
||||
* `Elite\location\system`: the system you are currently in.
|
||||
* `Elite\location\system`: The system you are currently in.
|
||||
|
||||
#### Ship ####
|
||||
#### Ship
|
||||
|
||||
* `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\model`: your current ship’s model.
|
||||
* `Elite\ship\name`: your current ship’s name.
|
||||
|
||||
## Logging ##
|
||||
|
||||
The profile supports logging a bunch of stuff to the VoiceAttack event log. By
|
||||
default, logging is concise and constrained to basically error messages.
|
||||
|
||||
If you need more logging (usually for debugging purposes), say `enable logging`.
|
||||
If you want to enable verbose logging _by default_, call the
|
||||
`Logging.enableLogging` command from your custom profile’s `startup` command.
|
||||
|
||||
## Exposed Variables ##
|
||||
|
||||
The following Variables are _global_ and thus readable (and writeable! Please
|
||||
don’t unless it’s a config variable …) from other profiles:
|
||||
|
||||
### Configuration Variables ###
|
||||
|
||||
There are a bunch of configuration variables. You should not overwrite those
|
||||
manually, instead use the provided commands in the `_configuration` section!
|
||||
|
||||
Basically all the settings are available using the `customize settings` prefix,
|
||||
then saying `[enable;disable] <setting>` for on/off switches and `set <setting>`
|
||||
for text variables.
|
||||
|
||||
* `EDDI.quietMode` (boolean): whether or not to set EDDI to quite mode. Default:
|
||||
true.
|
||||
* `EDDI.useEddiForVoice` (boolean): whether to use EDDI over VA’s builtin `say`
|
||||
command. Default: false.
|
||||
* `StreamAttack.outputDir` (string): the directory StreamAttack will save its
|
||||
information to. Default: `%appdata%\StreamAttack\`.
|
||||
* `python.ScriptPath` (string): the path you have placed the compiled Python
|
||||
scripts in. Default: “{VA_DIR}\Sounds\scripts” (the “\Sounds\scripts” folder
|
||||
in your VoiceAttack installation directory).
|
||||
|
||||
### Other Variables ###
|
||||
|
||||
These variables can be used to get information about the current neutron route.
|
||||
Please do not set them manually and / or from outside the StreamAttack profile.
|
||||
|
||||
* `StreamAttack.Elite.jumpTarget` (string): the current jump target.
|
||||
* `Elite\ship\model`: Your current ship’s model.
|
||||
* `Elite\ship\name`: Your current ship’s name.
|
||||
|
|
4
docs/VoiceAttack.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# VoiceAttack Tips
|
||||
|
||||
This will fill up eventually with tips on how to properly setup VoiceAttack for
|
||||
decent recognition.
|
53
docs/configuration/EliteAttack.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
# EliteAttack
|
||||
|
||||
## Settings
|
||||
|
||||
Toggles:
|
||||
|
||||
* `auto honk all systems`: Automatically honk upon entering a system, each jump,
|
||||
without constraints. Default: false.
|
||||
* `auto honk new systems`: Automatically honk upon entering a system if it is
|
||||
your first visit. Default: true.
|
||||
* `auto refuel`: Automatically refuel after docking at a station. Default:
|
||||
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
|
||||
against your discovery scan. Default: true.
|
||||
* `discovery scan on primary fire`: Use primary fire for honking instead of
|
||||
secondary. Default: false.
|
||||
* `flight assist off`: Permanent Flight Assist off mode. You should really do
|
||||
that, it’s great. Default: false.
|
||||
* `hyper space dethrottle`: Throttle down after a jump and when dropping from
|
||||
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
|
||||
scanning a system. (Terraformables, Water Worlds, Earth-Like Worlds and
|
||||
Ammonia Worlds that have not been mapped yet.) Default: true.
|
||||
* `outdated stations`: Announce stations with outdated data in the online
|
||||
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
|
||||
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:
|
||||
|
||||
* `outdated station threshold`: The threshold for station data to count as
|
||||
“outdated”, in days. Default: 365.
|
||||
* `scanner fire group`: The fire group your discovery scanner is assigned to.
|
||||
Default: 0 (the first one).
|
108
docs/configuration/RatAttack.md
Normal file
|
@ -0,0 +1,108 @@
|
|||
# RatAttack
|
||||
|
||||
## Getting Case Data From IRC
|
||||
|
||||
You can setup your IRC client to pass incoming RATSIGNALS to VoiceAttack by
|
||||
calling the `RatAttack-cli.exe` helper tool with the RATSIGNAL as first argument
|
||||
and an optional boolean as second argument that triggers a TTS case
|
||||
announcement. You can find it under your VoiceAttack “Apps” folder,
|
||||
`\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:
|
||||
|
||||
1. Announcing a new incoming case (if passing `true` as second argument).
|
||||
1. Storing case data and making it available to VoiceAttack, e.g. for copying
|
||||
the client’s system into the clipboard.
|
||||
|
||||
For my AdiIRC, it looks like this (obviously change the path, please):
|
||||
|
||||
```adiirc
|
||||
on *:TEXT:*RATSIGNAL*(??_SIGNAL):#fuelrats:{
|
||||
if ( $away ) {
|
||||
/run -h "X:\path\to\VoiceAttack\Apps\alterNERDtive\RatAttack-cli.exe" " $+ $replace($1-,","") $+ " false
|
||||
}
|
||||
else {
|
||||
/run -h "X:\path\to\VoiceAttack\Apps\alterNERDtive\RatAttack-cli.exe" " $+ $replace($1-,","") $+ " true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
The “replace” part handles the fact that announcements now put the system in
|
||||
quotes. They have to be escaped as double quotes (`""`) to create a correct
|
||||
command invocation.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
In case you have more than one CMDR registered as a Fuel Rat you can have
|
||||
VoiceAttack announce the nearest one to a case and the distance. You will have
|
||||
to go through a couple steps to set that up:
|
||||
|
||||
1. Have all CMDRs on EDSM.
|
||||
1. Have all profiles on EDSM set to _public_ including your flight log (which
|
||||
includes the current location).
|
||||
1. Set the CMDR names you want to use (“customize setting set fuel rat
|
||||
commanders”).
|
||||
1. Enable the nearest CMDR announcements (“customize setting enable nearest
|
||||
commander to fuel rat case”).
|
||||
|
||||
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
|
||||
ETA yet.
|
||||
|
||||
Currently there is no way to specify a platform for each CMDR separately.
|
||||
|
||||
## Sending Text to FuelRats IRC
|
||||
|
||||
The profile will attempt to send calls to “\#fuelrats”, and you can send
|
||||
messages from ingame chat to “\#fuelrats” and “\#ratchat”.
|
||||
|
||||
That will send text to windows with “\#fuelrats” and “\#ratchat” in
|
||||
their title, respectively. If your IRC client does not do that, you will have to
|
||||
change the “target” window of the `RatAttack.sendToFuelrats` and
|
||||
`RatAttack.sendToRatchat` commands to reflect the actual window titles on your
|
||||
system. I will look into making this more elegant to change in the future.
|
||||
|
||||
## Settings
|
||||
|
||||
Toggles:
|
||||
|
||||
* `auto close fuel rat case`: Automatically close a rat case when sending
|
||||
“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
|
||||
confirmation to prevent mistakes. Default: true.
|
||||
* `fuel rat duty`: On duty, receiving case announcements via TTS. Default: true.
|
||||
* `nearest commander to fuel rat case`: Announce the nearest commander to
|
||||
incoming rat cases. Default: false.
|
||||
* `platform for fuel rat case`: Announce the platform for incoming rat cases.
|
||||
Default: false.
|
||||
* `system information for fuel rat case`: System information provided by Mecha.
|
||||
Default: true.
|
||||
|
||||
Other Settings:
|
||||
|
||||
* `fuel rat commanders`: All your CMDRs that are ready to take rat cases. Use
|
||||
‘;’ as separator, e.g. “Bud Spencer;Terrence Hill”. Default: "".
|
||||
* `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".
|
47
docs/configuration/SpanshAttack.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
# SpanshAttack
|
||||
|
||||
## Supplying Your Ship’s Range
|
||||
|
||||
The ED-NeutronRouter plugin is technically supposed to read the current jump
|
||||
range from EDDI; sadly EDDI is storing the _maximum_ distance for your ship
|
||||
instead of the current / full on fuel one. The “default to laden range” option
|
||||
works reasonably well, but it has a few quirks. It always assumes full cargo,
|
||||
and it will take your _current_ fuel levels for range calculations, disregrading
|
||||
the range loss if you fill your tank.
|
||||
|
||||
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
|
||||
have with full fuel and your preferred amount of cargo/limpets.
|
||||
|
||||
In order to do that, copy the `SpanshAttack.getShipRange` command from
|
||||
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
|
||||
EDDI’s reported laden range or VoiceAttack prompting you to manually supply it.
|
||||
|
||||
![[SpanshAttack-getshiprange.png]]
|
||||
|
||||
You can override a saved range for your ship by using the
|
||||
`plot neutron [course;route;trip] with custom range` command.
|
||||
|
||||
## Settings
|
||||
|
||||
Toggles:
|
||||
|
||||
* `auto jump after scooping`: Automatically jump out when fuel scooping is
|
||||
complete. Default: true.
|
||||
* `auto plot`: Automatically plot to the next waypoint after supercharging.
|
||||
Default: true.
|
||||
* `clear neutron route on shutdown`: Clear an active neutron route when the game
|
||||
is shut down. Default: true.
|
||||
* `copy neutron waypoints to clipboard`: Copy each neutron waypoint into the
|
||||
Windows clipboard. Default: false.
|
||||
* `default to laden range`: Default to the current ship’s laden range as
|
||||
reported by EDDI instead of prompting for input. Default: false.
|
||||
* `time neutron route`: Keep track of how long a neutron route takes you to
|
||||
complete. Default: false.
|
||||
* `waypoint announcements`: Announce each waypoint by name. Default: true.
|
||||
|
||||
Other Settings:
|
||||
|
||||
* `announce jumps left`: Estimated jumps left to announce when reached. NEEDS to
|
||||
have leading and trailing “;”. Default: ";1;3;5;10;15;20;30;50;75;100;"
|
6
docs/configuration/StreamAttack.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# StreamAttack
|
||||
|
||||
## Settings
|
||||
|
||||
* `StreamAttack output directory`: The directory the status files are written
|
||||
to. Default: "%appdata%\StreamAttack\"
|
77
docs/configuration/general.md
Normal file
|
@ -0,0 +1,77 @@
|
|||
# General Configuration
|
||||
|
||||
## Settings
|
||||
|
||||
All profiles will load sane defaults if you haven’t changed anything. The
|
||||
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
|
||||
with their own distinct settings.
|
||||
|
||||
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 everything else: `customize setting set <trigger phrase>`
|
||||
|
||||
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
|
||||
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
|
||||
VoiceAttack log. If you want to reset everything back to default state, say
|
||||
`customize setting clear all my settings`.
|
||||
|
||||
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.
|
||||
|
||||
Since the settings are saved to your custom profile they will not necessarily be
|
||||
preserved when you switch profiles. Once you switch back, the correct settings
|
||||
for the profile are re-loaded.
|
||||
|
||||
### General Settings for All Profiles
|
||||
|
||||
Toggles:
|
||||
|
||||
* `auto update check`: Automatically check Github for profiles updates when the
|
||||
profile loads. Default: true.
|
||||
* `eddi quiet mode`: Make EDDI shut up. Disables all built-in speech responders.
|
||||
Default: true.
|
||||
|
||||
Other settings:
|
||||
|
||||
* `elite paste key`: The key used to paste in conjunction with CTRL. The
|
||||
physical key in your layout that would be 'V' on QWERTY. Default: 'v'.
|
||||
* `log level`: The level of detail for logging to the VoiceAttack log. Valid
|
||||
levels are "ERROR", "WARN", "NOTICE", "INFO" and "DEBUG". Default: "NOTICE".
|
||||
* `quit to desktop delay`: The delay before restarting the game after hitting
|
||||
“Exit to Desktop”, in seconds. Default: 10.0. (Used by the `restart from desktop`
|
||||
command)
|
||||
|
||||
## Note on Non-Standard Keyboard Layouts
|
||||
|
||||
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 keyboard layout
|
||||
that the game supports by default. You will have to change it to the key that
|
||||
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”.
|
||||
|
||||
## Adding Commands
|
||||
|
||||
If you want to edit a command or add your own, _do not edit the profiles
|
||||
directly_. Instead create commands in your custom profile, and copy commands you
|
||||
want to change over to that before editing them. This will make sure no changes
|
||||
are lost if you update the profiles.
|
||||
|
||||
### EDDI Events
|
||||
|
||||
Because of limitations of VoiceAttack itself, only the first matching command
|
||||
found will be executed, _including EDDI events_. That means that if you create
|
||||
commands to handle EDDI events, you are going to have to make sure that the
|
||||
appropriate handlers in my profiles are called, too. That is done by invoking
|
||||
the `eddi.Event` plugin context of the `alterNERDtive-base` plugin. Otherwise
|
||||
stuff _will_ break.
|
||||
|
||||
![[EDDI-event.png]]
|
41
docs/general.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# General Commands
|
||||
|
||||
## Configuration
|
||||
|
||||
The base profile provides voice commands for changing the profiles’ settings.
|
||||
See [the configuration section](../configuration/general#settings).
|
||||
|
||||
## Chat
|
||||
|
||||
* `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
|
||||
configured paste key. If you’re using a non-standard layout that means that
|
||||
you _cannot_ use this command to paste text into other applications.
|
||||
|
||||
## Updating
|
||||
|
||||
* `check for profiles update`: Checks Github for a new version, and alerts you
|
||||
if there is one.
|
||||
* `download profiles update`: Opens the latest release on Github and the
|
||||
VoiceAttack import folder where you can drop it.
|
||||
* `open profiles [docs;documentation;help] [file;site;]`: Opens this
|
||||
documentation, either on the web or the PDF file supplied with the installed
|
||||
release.
|
||||
* `open profiles change log`: Opens the CHANGELOG on Github.
|
||||
* `open voiceattack [apps;import;sounds] [folder;directory]`: Opens the
|
||||
respective VoiceAttack-related folder.
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
* `generate missing key binds report`: Generates a report of missing key binds
|
||||
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,
|
||||
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 elite bindings folder`: Opens Elite’s bindings folder
|
||||
(`%localappdata%\Frontier Developments\Elite Dangerous\Options\Bindings`)
|
||||
* `reload elite key binds`: Forces a reload of your Elite binds. Should not be
|
||||
necessary.
|
||||
* `shut up EDDI`: Immediately interrupts any current and pending speech on
|
||||
EDDI’s end.
|
BIN
docs/images/ED-NeutronRouter-folder.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
docs/images/EDDI-event.png
Normal file
After Width: | Height: | Size: 50 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 |
BIN
docs/images/Elite-binds.png
Normal file
After Width: | Height: | Size: 109 KiB |
BIN
docs/images/SpanshAttack-getshiprange.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
docs/images/VoiceAttack-apps.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
docs/images/VoiceAttack-download.png
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
docs/images/VoiceAttack-edit-new-command.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
docs/images/VoiceAttack-edit-startup-action.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
docs/images/VoiceAttack-edit-startup-actionlist.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
docs/images/VoiceAttack-edit-startup-execute.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
docs/images/VoiceAttack-edit-startup.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
docs/images/VoiceAttack-edit.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
docs/images/VoiceAttack-import-profile-open.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
docs/images/VoiceAttack-import-profile.png
Normal file
After Width: | Height: | Size: 87 KiB |
BIN
docs/images/VoiceAttack-new-profile-done.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
docs/images/VoiceAttack-new-profile.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
docs/images/VoiceAttack-profile-options-include.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
docs/images/VoiceAttack-profile-options-includelist.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
docs/images/VoiceAttack-profile-options-startup.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
docs/images/VoiceAttack-profile-options.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
docs/images/VoiceAttack-settings-plugin-support.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
docs/images/VoiceAttack-settings-updates.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
docs/images/VoiceAttack-settings.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
docs/images/bindED-layout.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/images/troubleshooting-raise-min-confidence.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
docs/images/troubleshooting-remove-trigger.png
Normal file
After Width: | Height: | Size: 29 KiB |
43
docs/index.md
Normal file
|
@ -0,0 +1,43 @@
|
|||
# Elite Dangerous VoiceAttack Profiles
|
||||
|
||||
These are various profiles for [VoiceAttack](https://voiceattack.com) (VA) I use
|
||||
to enhance my Elite experience. They give me important info, facilitate
|
||||
day-to-day gaming and do some special things for [Fuel
|
||||
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
|
||||
|
||||
* [EliteAttack](EliteAttack): The main Elite VA profile. Anything related to
|
||||
“just” playing the game.
|
||||
* [RatAttack](RatAttack): Manages interactions with the FuelRats IRC server.
|
||||
* [SpanshAttack](SpanshAttack): Plots and follows trips along the neutron
|
||||
highway using [Spansh’s neutron plotter](https://spansh.co.uk/plotter).
|
||||
* [StreamAttack](StreamAttack): Writes various status things to files that can
|
||||
then be read by streaming software like OBS.
|
||||
|
||||
They all require the `alterNERDtive-base` profile that, well, provides basic
|
||||
functionality common to all of the above.
|
||||
|
||||
## Need Help / Want to Contribute?
|
||||
|
||||
Well, you are in the right place. You can find comprehensive documentation right
|
||||
here.
|
||||
|
||||
If you run into any errors, please make sure you are running the latest version
|
||||
of the profiles and all [requirements](requirements.md).
|
||||
|
||||
If your problem persists, please [file an
|
||||
issue](https://github.com/alterNERDtive/VoiceAttack-profiles/issues). Thanks! :)
|
||||
|
||||
You can also [say “Hi” on Discord](https://discord.gg/kXtXm54) if that is your
|
||||
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)
|
238
docs/installing.md
Normal file
|
@ -0,0 +1,238 @@
|
|||
# Installing
|
||||
|
||||
## Install VoiceAttack
|
||||
|
||||
Grab the [most recent VoiceAttack beta
|
||||
version](https://voiceattack.com/#download-1) off the official site and install
|
||||
it.
|
||||
|
||||
If you are using the standalone version you should probably download the
|
||||
executable installer.
|
||||
|
||||
![[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
|
||||
folder](https://steamcommunity.com/sharedfiles/filedetails/?id=760447682). It is
|
||||
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
|
||||
features that have only just been added to the beta, so some things might break
|
||||
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:
|
||||
|
||||
1. Go to VoiceAttack settings. ![[VoiceAttack-settings.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
|
||||
(Note: those settings do not exist in the Steam version).
|
||||
|
||||
![[VoiceAttack-settings-updates.png]]
|
||||
|
||||
## Install EDDI
|
||||
|
||||
Install [the latest release](https://github.com/EDCD/EDDI/releases/latest) from
|
||||
Github (The `EDDI-X.Y.Z.exe` file under “Assets”). You will need to [install it
|
||||
as a 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
|
||||
already have it installed somewhere else) you can instead put it elsewhere and
|
||||
create a symbolic link. Open a command prompt (Windows key + `R`, enter “cmd”,
|
||||
hit `Enter`) and do
|
||||
|
||||
```cmd
|
||||
>cd x:\path\to\VoiceAttack\Apps
|
||||
>mklink /J EDDI x:\path\to\EDDI
|
||||
```
|
||||
|
||||
If you have installed the non-Steam version of VoiceAttack to the default folder
|
||||
within “Program Files” you will have to run the command prompt as admin (Windows
|
||||
key + `R`, enter “cmd”, hit `Control` + `Shift` + `Enter`).
|
||||
|
||||
## Install ED-NeutronRouter
|
||||
|
||||
Grab [the latest release release from
|
||||
Github](https://github.com/sc-pulgan/ED-NeutronRouter/releases/latest) (The
|
||||
`EDNeutronRouter.vX.YZ.zip` under “Assets”). 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. Click the folder set as “Apps Folder”. ![[VoiceAttack-apps.png]]
|
||||
|
||||
Now extract the contents of the downloaded file into there. Make sure that they
|
||||
are not naked files under “Apps”, but have their own folder
|
||||
“Apps\ED-NeutronRouter”! The exact folder name does not matter as long as they
|
||||
_are_ in a subfolder. Otherwise the plugin will not load.
|
||||
|
||||
![[ED-NeutronRouter-folder.png]]
|
||||
|
||||
Leave the “Apps” folder open in Windows Explorer, you will need it for the next step.
|
||||
|
||||
## Import Profiles Package
|
||||
|
||||
Acquire [the latest
|
||||
release](https://github.com/alterNERDtive/VoiceAttack-profiles/releases/latest)
|
||||
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. Click the folder set as “Apps Folder”. ![[VoiceAttack-apps.png]]
|
||||
1. Create a sub folder named “Import” if it does not exist yet.
|
||||
1. Drop the downloaded .vax file into the “Import” folder.
|
||||
1. Restart VoiceAttack.
|
||||
1. When prompted, import the profile package. VoiceAttack will restart when completed.
|
||||
|
||||
## Create a Custom Profile
|
||||
|
||||
Last but not least you are going to create your own custom VoiceAttack profile
|
||||
for Elite. It will allow you to add your own commands, override any commands in
|
||||
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
|
||||
profile example as a basis. Regardless of which way you choose, make sure to
|
||||
read the [Include Profiles](#include-profiles) section and follow the instructions there!
|
||||
|
||||
### Option 1: Create a New Profile Or Use an Existing One
|
||||
|
||||
1. Click the “Profile Actions” button, then “Create New Profile”.
|
||||
![[VoiceAttack-new-profile.png]]
|
||||
1. Give it a name and add some commands if you want to.
|
||||
1. Hit “Done” to create the new profile.
|
||||
|
||||
Alternatively you can keep using your existing profile. You will still have to
|
||||
follow the rest of the instructions in this case.
|
||||
|
||||
#### Create a Startup Command
|
||||
|
||||
First off, hit the “Edit” button in VoiceAttack.
|
||||
|
||||
![[VoiceAttack-edit.png]]
|
||||
|
||||
If you are using your existing profile (or have just created a fresh one) you
|
||||
will now have to create the startup command. Hit the “New Command” button.
|
||||
|
||||
![[VoiceAttack-edit-new-command.png]]
|
||||
|
||||
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
|
||||
make sure you do not accidentally run it via voice.
|
||||
|
||||
![[VoiceAttack-edit-startup.png]]
|
||||
|
||||
Add a new action using “Other” → “VoiceAttack Action”→ “Execute Another Command”.
|
||||
|
||||
![[VoiceAttack-edit-startup-execute.png]]
|
||||
|
||||
Choose “Execute by name (Advanced)” and enter `((alterNERDtive-base.startup))`.
|
||||
|
||||
![[VoiceAttack-edit-startup-action.png]]
|
||||
|
||||
Make sure to leave “Wait until this command completes before continuing” on and
|
||||
have this action at the top of the action list for the command. That way you can
|
||||
be sure that my profiles are initialized properly before your personal startup
|
||||
actions are processed.
|
||||
|
||||
![[VoiceAttack-edit-startup-actionlist.png]]
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
While editing the profile, hit the “Options” button.
|
||||
|
||||
![[VoiceAttack-profile-options.png]]
|
||||
|
||||
On the section labeled “Include commands from other profiles”, hit the “…”
|
||||
button.
|
||||
|
||||
![[VoiceAttack-profile-options-include.png]]
|
||||
|
||||
Add all my profiles (“alterNERDtive-base”, “EliteAttack”, “RatAttack”,
|
||||
“SpanshAttack”, “StreamAttack”).
|
||||
|
||||
![[VoiceAttack-profile-options-includelist.png]]
|
||||
|
||||
Make sure that “alterNERDtive-base” is on top of the list, the order of the
|
||||
others does not matter. But I like it nice and alphabetical. Technically you can
|
||||
leave out any profile you are not planning to use. Practically it probably will
|
||||
not hurt you to just include everything, and it will then be available for you
|
||||
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
|
||||
profile is loaded” checkbox, and select the “startup” command you have created
|
||||
earlier.
|
||||
|
||||
![[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
|
||||
|
||||
You need to have keyboard binds setup at least as secondary bindings in Elite’s
|
||||
controls options. VoiceAttack _cannot_ “push” joystick buttons for you, it can
|
||||
only do keyboard inputs. Hence its only way to interact with Elite is through
|
||||
keyboard emulation, even if you otherwise play the game with a controller or
|
||||
HOTAS. Or racing wheel. Or Rock Band set. Or bananas.
|
||||
|
||||
![[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
|
||||
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
|
||||
appropriate in your startup command.
|
||||
|
||||
![[bindED-layout.png]]
|
||||
|
||||
Currently bindED supports the `en-US`, `en-GB` and `de-Neo2` layouts. [You can
|
||||
find instructions on how to add your own
|
||||
here](https://alternerdtive.github.io/bindED/troubleshooting/#adding-a-keyboard-layout).
|
69
docs/requirements.md
Normal file
|
@ -0,0 +1,69 @@
|
|||
# Requirements
|
||||
|
||||
## VoiceAttack
|
||||
|
||||
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
|
||||
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
|
||||
for our US-based friends).
|
||||
|
||||
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
|
||||
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
|
||||
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!
|
||||
|
||||
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
|
||||
fixes/additions in beta versions quite often.
|
||||
|
||||
## EDDI
|
||||
|
||||
[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
|
||||
game as well as various third-party tools. In this case, you will need to run it
|
||||
as a VoiceAttack plugin.
|
||||
|
||||
EDDI also regularly publishes beta versions. Unless a profiles release
|
||||
explicitly states it you will _not_ have to run EDDI beta.
|
||||
|
||||
Do note that the profiles put EDDI into quiet mode by default, disabling the
|
||||
built-in speech responders. This can be changed
|
||||
[via the `EDDI quiet mode` setting](configuration/general.md#general-settings-for-all-profiles).
|
||||
|
||||
## bindED
|
||||
|
||||
[bindED](https://alterNERDtive.github.io/bindED) reads your Elite Dangerous
|
||||
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
|
||||
change any actions that you happen to not have the standard binds for.
|
||||
|
||||
This plugin is _included_ in the release package. You do _not_ have to download
|
||||
and install it manually, but you _can_ independently update it if a newer
|
||||
version is available.
|
||||
|
||||
## Elite Scripts
|
||||
|
||||
I have written a [collection of Python
|
||||
scripts](https://github.com/alterNERDtive/elite-scripts) to interface with
|
||||
various 3ʳᵈ party services like EDSM or Spansh. Those are called by the profiles
|
||||
for various tasks, like checking a system’s body count.
|
||||
|
||||
In the future they will be replaced by VoiceAttack plugin code.
|
||||
|
||||
The scripts are _included_ in the release package. You do _not_ have to download
|
||||
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.
|
||||
|
||||
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.
|
100
docs/troubleshooting.md
Normal file
|
@ -0,0 +1,100 @@
|
|||
# Troubleshooting
|
||||
|
||||
This will fill up gradually with Troubleshooting tips as people run into common
|
||||
ones.
|
||||
|
||||
## VoiceAttack does not understand me / mishears me / fires random commands
|
||||
|
||||
There is [a thread on the VoiceAttack
|
||||
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.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
Adding the “Other” → “VoiceAttack Action” → “Ignore an Unrecognized Word or
|
||||
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:
|
||||
|
||||
![[troubleshooting-remove-trigger.png]]
|
||||
|
||||
Alternatively you can raise the minimum confidence level and call the underlying
|
||||
command to make misfires less likely:
|
||||
|
||||
![[troubleshooting-raise-min-confidence.png]]
|
||||
|
||||
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.
|
103
docs/upgrading.md
Normal file
|
@ -0,0 +1,103 @@
|
|||
# Upgrading
|
||||
|
||||
To upgrade to the latest version, follow these simple steps:
|
||||
|
||||
1. Say “download profiles update”.
|
||||
1. Put the `alterNERDtive-voiceattack-profiles.vax` file from Github into
|
||||
VoiceAttack’s “Import” folder.
|
||||
1. Restart VoiceAttack.
|
||||
|
||||
In general, migration from old versions will be handled automatically. If there
|
||||
is something you have to do manually you will find the necessary steps below.
|
||||
|
||||
You can find the full
|
||||
[Changelog](https://github.com/alterNERDtive/VoiceAttack-profiles/blob/release/CHANGELOG.md)
|
||||
on Github.
|
||||
|
||||
## 3.x.x to 4.x.x
|
||||
|
||||
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
|
||||
automatically.
|
||||
|
||||
If you have not and you have used my “EliteDangerous” profile as the main
|
||||
profile … well, you will unfortunately have to take note of your settings, and
|
||||
recreate them after creating a custom profile and including everything.
|
||||
|
||||
Please do not fiddle with the configuration variables from your startup command
|
||||
(or any other, really). It _should_ not break anything, but it might. And it is
|
||||
entirely unnecessary since configuration will be saved to and loaded from the
|
||||
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
|
||||
|
||||
If you have done anything non-standard with bindED before, it might break. The
|
||||
profiles now include my fork of bindED which has a lot more features, but
|
||||
does no longer support a bunch of plugin invocations that have become obsolete.
|
||||
|
||||
Please [file an issue with
|
||||
bindED](https://github.com/alterNERDtive/bindED/issues/new/choose) on Github if
|
||||
your use case does not work anymore.
|
||||
|
||||
### EliteDangerous
|
||||
|
||||
The “EliteDangerous” profile is no longer the main profile. Instead you will
|
||||
_have_ to create a custom profile, and the new “base” profile that the others
|
||||
require to be included in your custom profile is “alterNERDtive-base”. That way
|
||||
you can use e.g. RatAttack without having to also use the general Elite profile.
|
||||
|
||||
To be consistent with the other profiles it has been renamed to “EliteAttack”.
|
||||
If you are upgrading from an older version the name will not change for you in
|
||||
the profiles list. I recommend renaming your “EliteDangerous” profile to
|
||||
“EliteAttack” to prevent confusion in the future, but it is not strictly
|
||||
necessary to do so.
|
||||
|
||||
### RatAttack
|
||||
|
||||
#### Getting Case Data From IRC
|
||||
|
||||
Handing a RATSIGNAL from IRC to VoiceAttack via text file is now deprecated and
|
||||
the feature will be removed in a future version.
|
||||
|
||||
Instead you should use the new `RatAttack-cli.exe` helper tool that uses IPC to
|
||||
talk to the VoiceAttack plugin. For that you have to change the way your IRC
|
||||
client handles incoming case announcements. Instead of writing the announcement
|
||||
to the text file and calling VoiceAttack to run a command, it will have to call
|
||||
the helper tool with a) the announcement and b) an optional true/false switch to
|
||||
determine if the case should be announced via TTS or just added to the case
|
||||
list.
|
||||
|
||||
For my AdiIRC, it looks like this (obviously change the path, please):
|
||||
|
||||
```adiirc
|
||||
on *:TEXT:*RATSIGNAL*(??_SIGNAL):#fuelrats:{
|
||||
if ( $away ) {
|
||||
/run -h "X:\path\to\VoiceAttack\Apps\alterNERDtive\RatAttack-cli.exe" " $+ $replace($1-,","") $+ " false
|
||||
}
|
||||
else {
|
||||
/run -h "X:\path\to\VoiceAttack\Apps\alterNERDtive\RatAttack-cli.exe" " $+ $replace($1-,","") $+ " true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
The `$replace` part handles the fact that case announcements now put the system
|
||||
in quotes. They have to be escaped as double quotes (`""`) to create a correct
|
||||
command line invocation.
|
||||
|
||||
#### Nearest CMDR Announcements
|
||||
|
||||
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
|
||||
whitespace.
|
||||
|
||||
Say “customize setting set fuel rat commanders” to update it.
|
50
mkdocs.yml
Normal file
|
@ -0,0 +1,50 @@
|
|||
site_name: "alterNERDtive VA profiles"
|
||||
site_url: https://alterNERDtive.github.io/VoiceAttack-profiles
|
||||
repo_url: https://github.com/alterNERDtive/VoiceAttack-profiles
|
||||
edit_uri: "edit/devel/docs/"
|
||||
site_description: "alterNERDtive VoiceAttack profiles for Elite: Dangerous"
|
||||
site_author: "alterNERDtive"
|
||||
remote_name: "origin"
|
||||
|
||||
theme:
|
||||
name: readthedocs
|
||||
prev_next_buttons_location: both
|
||||
|
||||
plugins:
|
||||
- search
|
||||
- roamlinks
|
||||
# - mkpdfs:
|
||||
# author: 'alterNERDtive'
|
||||
# output_path: 'pdf/Profiles Documentation.pdf'
|
||||
|
||||
markdown_extensions:
|
||||
- toc:
|
||||
permalink: True
|
||||
- sane_lists
|
||||
|
||||
nav:
|
||||
- 'Home': 'index.md'
|
||||
- 'Install':
|
||||
- 'requirements.md'
|
||||
- 'installing.md'
|
||||
- 'upgrading.md'
|
||||
- 'Configure':
|
||||
- 'configuration/general.md'
|
||||
- 'configuration/EliteAttack.md'
|
||||
- 'configuration/RatAttack.md'
|
||||
- 'configuration/SpanshAttack.md'
|
||||
- 'configuration/StreamAttack.md'
|
||||
- 'Use':
|
||||
- 'general.md'
|
||||
- 'EliteAttack.md'
|
||||
- 'RatAttack.md'
|
||||
- 'SpanshAttack.md'
|
||||
- 'StreamAttack.md'
|
||||
- 'Issues':
|
||||
#- 'VoiceAttack Tips': 'VoiceAttack.md'
|
||||
- 'troubleshooting.md'
|
||||
- '⎋ Changelog': 'https://github.com/alterNERDtive/VoiceAttack-profiles/blob/release/CHANGELOG.md'
|
||||
- '⎋ Report a Bug': 'https://github.com/alterNERDtive/VoiceAttack-profiles/issues/'
|
||||
- 'Watch in Action':
|
||||
- '⎋ Twitch': 'https://twitch.tv/alterNERDtive'
|
||||
- '⎋ Youtube': 'https://www.youtube.com/channel/UC3XNZA7xWed1zM1AWOOdmog'
|
103
plugins.sln
Normal file
|
@ -0,0 +1,103 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.3.32519.111
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VoiceAttack-base", "plugins\VoiceAttack-base\VoiceAttack-base.csproj", "{1C05DB3F-3449-4664-B363-A379892995E5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RatAttack", "plugins\RatAttack\RatAttack.csproj", "{64CD3BA3-7FD2-4360-B055-6927CE92DA68}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RatAttack-cli", "plugins\RatAttack-cli\RatAttack-cli.csproj", "{D72A35EC-8D39-4B96-BBC5-1B330F4CBEEF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EliteAttack", "plugins\EliteAttack\EliteAttack.csproj", "{77CEF35C-C25C-4793-AB2C-0B0C5D9A5BB8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpanshAttack", "plugins\SpanshAttack\SpanshAttack.csproj", "{D2047704-696B-4665-8D37-3AD298A8B9F9}"
|
||||
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
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1C05DB3F-3449-4664-B363-A379892995E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1C05DB3F-3449-4664-B363-A379892995E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1C05DB3F-3449-4664-B363-A379892995E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1C05DB3F-3449-4664-B363-A379892995E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{64CD3BA3-7FD2-4360-B055-6927CE92DA68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{64CD3BA3-7FD2-4360-B055-6927CE92DA68}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{64CD3BA3-7FD2-4360-B055-6927CE92DA68}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{64CD3BA3-7FD2-4360-B055-6927CE92DA68}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D72A35EC-8D39-4B96-BBC5-1B330F4CBEEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D72A35EC-8D39-4B96-BBC5-1B330F4CBEEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D72A35EC-8D39-4B96-BBC5-1B330F4CBEEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D72A35EC-8D39-4B96-BBC5-1B330F4CBEEF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{77CEF35C-C25C-4793-AB2C-0B0C5D9A5BB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{77CEF35C-C25C-4793-AB2C-0B0C5D9A5BB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{77CEF35C-C25C-4793-AB2C-0B0C5D9A5BB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{77CEF35C-C25C-4793-AB2C-0B0C5D9A5BB8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D2047704-696B-4665-8D37-3AD298A8B9F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D2047704-696B-4665-8D37-3AD298A8B9F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D2047704-696B-4665-8D37-3AD298A8B9F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D2047704-696B-4665-8D37-3AD298A8B9F9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
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
|
||||
SolutionGuid = {339E6747-C7BF-43C3-99C6-9249C9849A84}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
175
plugins/EliteAttack/EliteAttack.cs
Normal file
|
@ -0,0 +1,175 @@
|
|||
// <copyright file="EliteAttack.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 alterNERDtive.util;
|
||||
|
||||
namespace EliteAttack
|
||||
{
|
||||
/// <summary>
|
||||
/// VoiceAttack plugin for the EliteAttack profile.
|
||||
/// </summary>
|
||||
public class EliteAttack
|
||||
{
|
||||
private static readonly Version VERSION = new ("8.5");
|
||||
|
||||
private static VoiceAttackLog? log;
|
||||
private static VoiceAttackCommands? commands;
|
||||
|
||||
private static dynamic? VA { get; set; }
|
||||
|
||||
private static VoiceAttackLog Log => log ??= new (VA, "EliteAttack");
|
||||
|
||||
private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
|
||||
|
||||
/*========================================\
|
||||
| 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 ("{5B46321D-2935-4550-BEEA-36C2145547B8}");
|
||||
|
||||
/// <summary>
|
||||
/// The plugin’s display name, as required by the VoiceAttack plugin API.
|
||||
/// </summary>
|
||||
/// <returns>The display name.</returns>
|
||||
public static string VA_DisplayName()
|
||||
=> $"EliteAttack {VERSION}";
|
||||
|
||||
/// <summary>
|
||||
/// The plugin’s description, as required by the VoiceAttack plugin API.
|
||||
/// </summary>
|
||||
/// <returns>The description.</returns>
|
||||
public static string VA_DisplayInfo()
|
||||
=> "EliteAttack: a plugin for doing Elite-y things.";
|
||||
|
||||
/// <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("EliteAttack.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 "log.log":
|
||||
// log
|
||||
Context_Log(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 |
|
||||
\================*/
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
56
plugins/EliteAttack/EliteAttack.csproj
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{77CEF35C-C25C-4793-AB2C-0B0C5D9A5BB8}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>EliteAttack</RootNamespace>
|
||||
<AssemblyName>EliteAttack</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\build\alterNERDtive\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\build\alterNERDtive\EliteAttack.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\build\alterNERDtive\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\build\alterNERDtive\EliteAttack.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="EliteAttack.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VoiceAttack-base\VoiceAttack-base.csproj">
|
||||
<Project>{1c05db3f-3449-4664-b363-a379892995e5}</Project>
|
||||
<Name>VoiceAttack-base</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
55
plugins/EliteAttack/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
// <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.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("EliteAttack")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("EliteAttack")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("77cef35c-c25c-4793-ab2c-0b0c5d9a5bb8")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
55
plugins/RatAttack-cli/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
// <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.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("RatAttack-cli")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("RatAttack-cli")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("d72a35ec-8d39-4b96-bbc5-1b330f4cbeef")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
63
plugins/RatAttack-cli/RatAttack-cli.csproj
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D72A35EC-8D39-4B96-BBC5-1B330F4CBEEF}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>RatAttack_cli</RootNamespace>
|
||||
<AssemblyName>RatAttack-cli</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\build\alterNERDtive\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\build\alterNERDtive\RatAttack-cli.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\build\alterNERDtive\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\build\alterNERDtive\RatAttack-cli.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.Serialization" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RatAttack_cli.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RatAttack\RatAttack.csproj">
|
||||
<Project>{64cd3ba3-7fd2-4360-b055-6927ce92da68}</Project>
|
||||
<Name>RatAttack</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
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);
|
||||
}
|
||||
}
|
||||
}
|
55
plugins/RatAttack/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
// <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.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("VoiceAttack-plugins")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("VoiceAttack-plugins")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("64cd3ba3-7fd2-4360-b055-6927ce92da68")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
445
plugins/RatAttack/RatAttack.cs
Normal file
|
@ -0,0 +1,445 @@
|
|||
// <copyright file="RatAttack.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.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using alterNERDtive.util;
|
||||
|
||||
namespace RatAttack
|
||||
{
|
||||
/// <summary>
|
||||
/// VoiceAttack plugin for the RatAttack profile.
|
||||
/// </summary>
|
||||
public class RatAttack
|
||||
{
|
||||
private static readonly Version VERSION = new ("6.4");
|
||||
|
||||
private static readonly Regex RatsignalRegex = new (
|
||||
@"^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*$");
|
||||
|
||||
private static PipeServer<Ratsignal>? ratsignalPipe;
|
||||
private static VoiceAttackLog? log;
|
||||
private static VoiceAttackCommands? commands;
|
||||
|
||||
private static ConcurrentDictionary<int, RatCase> CaseList { get; } = new ();
|
||||
|
||||
private static dynamic? VA { get; set; }
|
||||
|
||||
private static PipeServer<Ratsignal> RatsignalPipe
|
||||
=> ratsignalPipe ??= new (
|
||||
Log,
|
||||
"RatAttack",
|
||||
new PipeServer<Ratsignal>.SignalHandler(On_Ratsignal));
|
||||
|
||||
private static VoiceAttackLog Log => log ??= new (VA, "RatAttack");
|
||||
|
||||
private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
|
||||
|
||||
/*========================================\
|
||||
| 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 ("{F2ADF0AE-4837-4E4A-9C87-8A7E2FA63E5F}");
|
||||
|
||||
/// <summary>
|
||||
/// The plugin’s display name, as required by the VoiceAttack plugin API.
|
||||
/// </summary>
|
||||
/// <returns>The display name.</returns>
|
||||
public static string VA_DisplayName()
|
||||
=> $"RatAttack {VERSION}";
|
||||
|
||||
/// <summary>
|
||||
/// The plugin’s description, as required by the VoiceAttack plugin API.
|
||||
/// </summary>
|
||||
/// <returns>The description.</returns>
|
||||
public static string VA_DisplayInfo()
|
||||
=> "RatAttack: a plugin to handle FuelRats cases.";
|
||||
|
||||
/// <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("RatAttack.version", VERSION.ToString());
|
||||
vaProxy.ProfileChanged += new Action<Guid?, Guid?, string, string>(On_ProfileChanged);
|
||||
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 "getcasedata":
|
||||
// plugin methods
|
||||
Context_GetCaseData(vaProxy);
|
||||
break;
|
||||
case "parseratsignal":
|
||||
Context_ParseRatsignal(vaProxy);
|
||||
break;
|
||||
case "startup":
|
||||
Context_Startup(vaProxy);
|
||||
break;
|
||||
case "edsm.getnearestcmdr":
|
||||
// EDSM
|
||||
Context_EDSM_GetNearestCMDR(vaProxy);
|
||||
break;
|
||||
case "log.log":
|
||||
// log
|
||||
Context_Log(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)
|
||||
{
|
||||
Log.Debug("Starting teardown …");
|
||||
Log.Debug("Closing RATSIGNAL pipe …");
|
||||
RatsignalPipe.Stop();
|
||||
Log.Debug("Teardown finished.");
|
||||
}
|
||||
|
||||
/// <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()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a RATSIGNAL and extracts case data for storage.
|
||||
/// </summary>
|
||||
/// <param name="ratsignal">The incoming RATSIGNAL.</param>
|
||||
/// <returns>The case number.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown on invalid RATSIGNAL.</exception>
|
||||
private static int ParseRatsignal(string ratsignal)
|
||||
{
|
||||
if (!RatsignalRegex.IsMatch(ratsignal))
|
||||
{
|
||||
throw new ArgumentException($"Invalid RATSIGNAL format: '{ratsignal}'.", "ratsignal");
|
||||
}
|
||||
|
||||
Match match = RatsignalRegex.Match(ratsignal);
|
||||
|
||||
string cmdr = match.Groups["cmdr"].Value;
|
||||
string? language = match.Groups["language"].Value;
|
||||
string? system = match.Groups["system"].Value;
|
||||
string? systemInfo = match.Groups["systemInfo"].Value;
|
||||
bool permitLocked = match.Groups["permit"].Success;
|
||||
string? permitName = match.Groups["permitName"].Value;
|
||||
string platform = match.Groups["platform"].Value;
|
||||
bool codeRed = match.Groups["oxygen"].Success;
|
||||
string? mode = match.Groups["mode"].Value;
|
||||
|
||||
int number = int.Parse(match.Groups["number"].Value);
|
||||
|
||||
if (string.IsNullOrEmpty(system))
|
||||
{
|
||||
system = "None";
|
||||
}
|
||||
|
||||
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}).");
|
||||
|
||||
CaseList[number] = new RatCase(cmdr, language, system, systemInfo, permitLocked, permitName, platform, mode, codeRed, number);
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
private static void On_Ratsignal(Ratsignal ratsignal)
|
||||
{
|
||||
try
|
||||
{
|
||||
int number = ParseRatsignal(ratsignal.Signal);
|
||||
Log.Notice($"New rat case: {CaseList[number]}.");
|
||||
Commands.TriggerEvent("RatAttack.incomingCase", parameters: new dynamic[] { new int[] { number }, new bool[] { ratsignal.Announce } });
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
Log.Error(e.Message);
|
||||
Commands.TriggerEvent("RatAttack.invalidRatsignal", parameters: new dynamic[] { new string[] { ratsignal.Signal } });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"Unhandled exception while parsing RATSIGNAL: '{e.Message}'.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void On_ProfileChanged(Guid? from, Guid? to, string fromName, string toName)
|
||||
=> VA_Exit1(VA);
|
||||
|
||||
/*================\
|
||||
| plugin contexts |
|
||||
\================*/
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
private static void Context_EDSM_GetNearestCMDR(dynamic vaProxy)
|
||||
{
|
||||
int caseNo = vaProxy.GetInt("~caseNo") ?? throw new ArgumentNullException("~caseNo");
|
||||
string cmdrList = vaProxy.GetText("~cmdrs") ?? throw new ArgumentNullException("~cmdrs");
|
||||
string[] cmdrs = cmdrList.Split(';');
|
||||
if (cmdrs.Length == 0)
|
||||
{
|
||||
throw new ArgumentNullException("~cmdrs");
|
||||
}
|
||||
|
||||
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)}""";
|
||||
|
||||
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
||||
|
||||
p.Start();
|
||||
string stdout = p.StandardOutput.ReadToEnd();
|
||||
string stderr = p.StandardError.ReadToEnd();
|
||||
p.WaitForExit();
|
||||
|
||||
string message = stdout;
|
||||
string? errorMessage = null;
|
||||
bool error;
|
||||
|
||||
switch (p.ExitCode)
|
||||
{
|
||||
case 0:
|
||||
error = false;
|
||||
Log.Info(message);
|
||||
break;
|
||||
case 1: // CMDR not found, Server Error, Api Exception (jeez, what a mess did I make there?)
|
||||
error = true;
|
||||
Log.Error(message);
|
||||
break;
|
||||
case 2: // System not found
|
||||
error = true;
|
||||
Log.Warn(message);
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
Log.Error(stderr);
|
||||
errorMessage = "Unrecoverable error in plugin.";
|
||||
break;
|
||||
}
|
||||
|
||||
vaProxy.SetText("~message", message);
|
||||
vaProxy.SetBoolean("~error", error);
|
||||
vaProxy.SetText("~errorMessage", errorMessage);
|
||||
vaProxy.SetInt("~exitCode", p.ExitCode);
|
||||
}
|
||||
|
||||
private static void Context_GetCaseData(dynamic vaProxy)
|
||||
{
|
||||
int cn = vaProxy.GetInt("~caseNumber");
|
||||
|
||||
if (CaseList.ContainsKey(cn))
|
||||
{
|
||||
RatCase rc = CaseList[cn];
|
||||
|
||||
vaProxy.SetInt("~~caseNumber", rc.Number);
|
||||
vaProxy.SetText("~~cmdr", rc.Cmdr);
|
||||
vaProxy.SetText("~~system", rc?.System?.ToLower());
|
||||
vaProxy.SetText("~~systemInfo", rc?.SystemInfo);
|
||||
vaProxy.SetBoolean("~~permitLocked", rc?.PermitLocked);
|
||||
vaProxy.SetText("~~permitName", rc?.PermitName);
|
||||
vaProxy.SetText("~~platform", rc?.Platform);
|
||||
vaProxy.SetText("~~mode", rc?.Mode);
|
||||
vaProxy.SetBoolean("~~codeRed", rc?.CodeRed);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warn($"Case #{cn} not found in the case list");
|
||||
}
|
||||
}
|
||||
|
||||
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 …");
|
||||
_ = 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;
|
||||
}
|
||||
}
|
||||
}
|
62
plugins/RatAttack/RatAttack.csproj
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{64CD3BA3-7FD2-4360-B055-6927CE92DA68}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>RatAttack</RootNamespace>
|
||||
<AssemblyName>RatAttack</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\build\alterNERDtive\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\build\alterNERDtive\RatAttack.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\build\alterNERDtive\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\build\alterNERDtive\RatAttack.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.Serialization" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RatAttack.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VoiceAttack-base\VoiceAttack-base.csproj">
|
||||
<Project>{1c05db3f-3449-4664-b363-a379892995e5}</Project>
|
||||
<Name>VoiceAttack-base</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
55
plugins/SpanshAttack/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
// <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.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SpanshAttack")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SpanshAttack")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("d2047704-696b-4665-8d37-3ad298a8b9f9")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
336
plugins/SpanshAttack/SpanshAttack.cs
Normal file
|
@ -0,0 +1,336 @@
|
|||
// <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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
using alterNERDtive.edts;
|
||||
using alterNERDtive.util;
|
||||
|
||||
namespace SpanshAttack
|
||||
{
|
||||
/// <summary>
|
||||
/// VoiceAttack plugin for the SpanshAttack profile.
|
||||
/// </summary>
|
||||
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 VoiceAttackLog Log => log ??= new (VA, "SpanshAttack");
|
||||
|
||||
private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
|
||||
|
||||
/*========================================\
|
||||
| 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 |
|
||||
\================*/
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
private static void Context_EDTS_GetCoordinates(dynamic vaProxy)
|
||||
{
|
||||
string name = vaProxy.GetText("~system") ?? throw new ArgumentNullException("~system");
|
||||
|
||||
bool success = false;
|
||||
string? errorType = null;
|
||||
string? errorMessage = null;
|
||||
|
||||
try
|
||||
{
|
||||
StarSystem system = EdtsApi.GetCoordinates(name);
|
||||
|
||||
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.SetBoolean("~success", success);
|
||||
if (!string.IsNullOrWhiteSpace(errorType))
|
||||
{
|
||||
Log.Error(errorMessage!);
|
||||
vaProxy.SetText("~errorType", errorType);
|
||||
vaProxy.SetText("~errorMessage", errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
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_Spansh_Nearestsystem(dynamic vaProxy)
|
||||
{
|
||||
int x = vaProxy.GetInt("~x") ?? throw new ArgumentNullException("~x");
|
||||
int y = vaProxy.GetInt("~y") ?? throw new ArgumentNullException("~y");
|
||||
int z = vaProxy.GetInt("~z") ?? throw new ArgumentNullException("~z");
|
||||
|
||||
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\Scripts\spansh.exe";
|
||||
string arguments = $@"nearestsystem --parsable {x} {y} {z}";
|
||||
|
||||
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
||||
|
||||
Dictionary<char, decimal> coords = new () { { 'x', 0 }, { 'y', 0 }, { 'z', 0 } };
|
||||
string system = string.Empty;
|
||||
decimal distance = 0;
|
||||
bool error = false;
|
||||
string errorMessage = string.Empty;
|
||||
|
||||
p.Start();
|
||||
string stdout = p.StandardOutput.ReadToEnd();
|
||||
string stderr = p.StandardError.ReadToEnd();
|
||||
p.WaitForExit();
|
||||
switch (p.ExitCode)
|
||||
{
|
||||
case 0:
|
||||
string[] stdoutExploded = stdout.Split('|');
|
||||
system = stdoutExploded[0];
|
||||
distance = decimal.Parse(stdoutExploded[2]);
|
||||
string[] stdoutCoords = stdoutExploded[1].Split(',');
|
||||
coords['x'] = decimal.Parse(stdoutCoords[0]);
|
||||
coords['y'] = decimal.Parse(stdoutCoords[1]);
|
||||
coords['z'] = decimal.Parse(stdoutCoords[2]);
|
||||
Log.Info($"Nearest system to ({x}, {y}, {z}): {system} ({coords['x']}, {coords['y']}, {coords['z']}), distance: {distance} ly");
|
||||
break;
|
||||
case 1:
|
||||
error = true;
|
||||
errorMessage = stdout;
|
||||
Log.Error(errorMessage);
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
Log.Error(stderr);
|
||||
errorMessage = "Unrecoverable error in plugin.";
|
||||
break;
|
||||
}
|
||||
|
||||
vaProxy.SetText("~system", system);
|
||||
vaProxy.SetDecimal("~x", coords['x']);
|
||||
vaProxy.SetDecimal("~y", coords['y']);
|
||||
vaProxy.SetDecimal("~z", coords['z']);
|
||||
vaProxy.SetDecimal("~distance", distance);
|
||||
vaProxy.SetBoolean("~error", error);
|
||||
vaProxy.SetText("~errorMessage", errorMessage);
|
||||
vaProxy.SetInt("~exitCode", p.ExitCode);
|
||||
}
|
||||
|
||||
private static void Context_Spansh_SytemExists(dynamic vaProxy)
|
||||
{
|
||||
string system = vaProxy.GetText("~system") ?? throw new ArgumentNullException("~system");
|
||||
|
||||
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\Scripts\spansh.exe";
|
||||
string arguments = $@"systemexists ""{system}""";
|
||||
|
||||
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
||||
|
||||
bool exists = true;
|
||||
bool error = false;
|
||||
string errorMessage = string.Empty;
|
||||
|
||||
p.Start();
|
||||
string stdout = p.StandardOutput.ReadToEnd();
|
||||
string stderr = p.StandardError.ReadToEnd();
|
||||
p.WaitForExit();
|
||||
switch (p.ExitCode)
|
||||
{
|
||||
case 0:
|
||||
Log.Info($@"System ""{system}"" found in Spansh’s DB");
|
||||
break;
|
||||
case 1:
|
||||
error = true;
|
||||
errorMessage = stdout;
|
||||
Log.Error(errorMessage);
|
||||
break;
|
||||
case 3:
|
||||
exists = false;
|
||||
Log.Info($@"System ""{system}"" not found in Spansh’s DB");
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
Log.Error(stderr);
|
||||
errorMessage = "Unrecoverable error in plugin.";
|
||||
break;
|
||||
}
|
||||
|
||||
vaProxy.SetBoolean("~systemExists", exists);
|
||||
vaProxy.SetBoolean("~error", error);
|
||||
vaProxy.SetText("~errorMessage", errorMessage);
|
||||
vaProxy.SetInt("~exitCode", p.ExitCode);
|
||||
}
|
||||
|
||||
private static void Context_Startup(dynamic vaProxy)
|
||||
{
|
||||
Log.Notice("Starting up …");
|
||||
Log.Notice("Finished startup.");
|
||||
}
|
||||
#pragma warning restore IDE0060 // Remove unused parameter
|
||||
}
|
||||
}
|
56
plugins/SpanshAttack/SpanshAttack.csproj
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D2047704-696B-4665-8D37-3AD298A8B9F9}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SpanshAttack</RootNamespace>
|
||||
<AssemblyName>SpanshAttack</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\build\alterNERDtive\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\build\alterNERDtive\SpanshAttack.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\build\alterNERDtive\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\build\alterNERDtive\SpanshAttack.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="SpanshAttack.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VoiceAttack-base\VoiceAttack-base.csproj">
|
||||
<Project>{1c05db3f-3449-4664-b363-a379892995e5}</Project>
|
||||
<Name>VoiceAttack-base</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
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")]
|
55
plugins/VoiceAttack-base/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
// <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.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("VoiceAttack-base")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("VoiceAttack-base")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020–2022")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("1c05db3f-3449-4664-b363-a379892995e5")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
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; }
|
||||
}
|
||||
}
|
||||
}
|
82
plugins/VoiceAttack-base/VoiceAttack-base.csproj
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{1C05DB3F-3449-4664-B363-A379892995E5}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>alterNERDtive</RootNamespace>
|
||||
<AssemblyName>base</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\build\alterNERDtive\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\build\alterNERDtive\base.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\build\alterNERDtive\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\build\alterNERDtive\base.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="base.cs" />
|
||||
<Compile Include="edts.cs">
|
||||
<ExcludeFromStyleCop>true</ExcludeFromStyleCop>
|
||||
</Compile>
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SettingsDialog.xaml.cs">
|
||||
<DependentUpon>SettingsDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="util.cs" />
|
||||
</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" />
|
||||
</Project>
|
691
plugins/VoiceAttack-base/base.cs
Normal file
|
@ -0,0 +1,691 @@
|
|||
// <copyright file="base.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.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
using alterNERDtive.util;
|
||||
|
||||
namespace alterNERDtive
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the base plugin orchestrating all the profile-specific plugins
|
||||
/// to work together properly. It handles things like configuration or
|
||||
/// subscribing to VoiceAttack-triggered events.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "F off :)")]
|
||||
public class BasePlugin
|
||||
{
|
||||
private static readonly Version VERSION = new ("4.5");
|
||||
|
||||
private static readonly Dictionary<Guid, string> Profiles = new ()
|
||||
{
|
||||
{ new Guid("{F7F59CFD-1AE2-4A7E-8F62-C62372418BAC}"), "alterNERDtive-base" },
|
||||
{ new Guid("{f31b575b-6ce4-44eb-91fc-7459e55013cf}"), "EliteAttack" },
|
||||
{ new Guid("{87276668-2a6e-4d80-af77-80651daa58b7}"), "RatAttack" },
|
||||
{ new Guid("{e722b29d-898e-47dd-a843-a409c87e0bd8}"), "SpanshAttack" },
|
||||
{ new Guid("{05580e6c-442c-46cd-b36f-f5a1f967ec59}"), "StreamAttack" },
|
||||
};
|
||||
|
||||
private static readonly List<string> ActiveProfiles = new ();
|
||||
private static readonly List<string> InstalledProfiles = new ();
|
||||
|
||||
private static readonly Regex ConfigurationVariableRegex = new (@$"(?<id>({string.Join("|", Profiles.Values)}))\.(?<name>.+)#");
|
||||
|
||||
private static VoiceAttackCommands? commands;
|
||||
private static Configuration? config;
|
||||
private static VoiceAttackLog? log;
|
||||
|
||||
private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
|
||||
|
||||
private static Configuration Config => config ??= new (VA, Log, Commands, "alterNERDtive-base");
|
||||
|
||||
private static VoiceAttackLog Log => log ??= new (VA, "alterNERDtive-base");
|
||||
|
||||
private static dynamic? VA { get; set; }
|
||||
|
||||
/*========================================\
|
||||
| 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 ("{F7F59CFD-1AE2-4A7E-8F62-C62372418BAC}");
|
||||
|
||||
/// <summary>
|
||||
/// The plugin’s display name, as required by the VoiceAttack plugin API.
|
||||
/// </summary>
|
||||
/// <returns>The display name.</returns>
|
||||
public static string VA_DisplayName()
|
||||
=> $"alterNERDtive-base {VERSION}";
|
||||
|
||||
/// <summary>
|
||||
/// The plugin’s description, as required by the VoiceAttack plugin API.
|
||||
/// </summary>
|
||||
/// <returns>The description.</returns>
|
||||
public static string VA_DisplayInfo()
|
||||
=> "The alterNERDtive plugin to manage all the alterNERDtive profiles!";
|
||||
|
||||
/// <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("alterNERDtive-base.version", VERSION.ToString());
|
||||
vaProxy.BooleanVariableChanged += new Action<string, bool?, bool?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
|
||||
vaProxy.DateVariableChanged += new Action<string, DateTime?, DateTime?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
|
||||
vaProxy.DecimalVariableChanged += new Action<string, decimal?, decimal?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
|
||||
vaProxy.IntegerVariableChanged += new Action<string, int?, int?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
|
||||
vaProxy.TextVariableChanged += new Action<string, string, string, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
|
||||
VA.SetBoolean("alterNERDtive-base.initialized", true);
|
||||
Commands.TriggerEvent("alterNERDtive-base.initialized", wait: false, logMissing: false);
|
||||
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 "config.dialog":
|
||||
// config
|
||||
Context_Config_Dialog(vaProxy);
|
||||
break;
|
||||
case "config.dump":
|
||||
Context_Config_Dump(vaProxy);
|
||||
break;
|
||||
case "config.getvariables":
|
||||
Context_Config_SetVariables(vaProxy);
|
||||
break;
|
||||
case "config.list":
|
||||
Context_Config_List(vaProxy);
|
||||
break;
|
||||
case "config.setup":
|
||||
Context_Config_Setup(vaProxy);
|
||||
break;
|
||||
case "config.versionmigration":
|
||||
Context_Config_VersionMigration(vaProxy);
|
||||
break;
|
||||
case "edsm.bodycount":
|
||||
// EDSM
|
||||
Context_EDSM_BodyCount(vaProxy);
|
||||
break;
|
||||
case "edsm.distancebetween":
|
||||
Context_EDSM_DistanceBetween(vaProxy);
|
||||
break;
|
||||
case "eddi.event":
|
||||
// EDDI
|
||||
Context_Eddi_Event(vaProxy);
|
||||
break;
|
||||
case "spansh.outdatedstations":
|
||||
// Spansh
|
||||
Context_Spansh_OutdatedStations(vaProxy);
|
||||
break;
|
||||
case "log.log":
|
||||
// log
|
||||
Context_Log(vaProxy);
|
||||
break;
|
||||
case "update.check":
|
||||
// update
|
||||
Context_Update_Check(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()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a given profile is currently active.
|
||||
/// </summary>
|
||||
/// <param name="profileName">The name of the profile in question.</param>
|
||||
/// <returns>The state of the profile in question.</returns>
|
||||
public static bool IsProfileActive(string profileName) => ActiveProfiles.Contains(profileName);
|
||||
|
||||
private static void CheckProfiles(dynamic vaProxy)
|
||||
{
|
||||
ActiveProfiles.Clear();
|
||||
InstalledProfiles.Clear();
|
||||
|
||||
foreach (KeyValuePair<Guid, string> profile in Profiles)
|
||||
{
|
||||
if (vaProxy.Command.Exists($"(({profile.Value}.startup))"))
|
||||
{
|
||||
// Sadly there is no way to find _active_ profiles, so we have to check the one command that always is in them.
|
||||
ActiveProfiles.Add(profile.Value);
|
||||
}
|
||||
|
||||
if (vaProxy.Profile.Exists(profile.Key))
|
||||
{
|
||||
InstalledProfiles.Add(profile.Value);
|
||||
}
|
||||
}
|
||||
|
||||
Log.Debug($"Profiles found: {string.Join<string>(", ", ActiveProfiles)}");
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "required by VoiceAttack plugin API")]
|
||||
private static void ConfigurationChanged(string option, dynamic? from, dynamic? to, Guid? guid = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Match match = ConfigurationVariableRegex.Match(option);
|
||||
if (match.Success)
|
||||
{
|
||||
string id = match.Groups["id"].Value;
|
||||
string name = match.Groups["name"].Value;
|
||||
Log.Debug($"Configuration has changed, '{id}.{name}': '{from}' → '{to}'");
|
||||
|
||||
dynamic o = Configuration.GetOption(id, name);
|
||||
|
||||
// When loaded from profile but not explicitly set, will be null.
|
||||
// Then load default.
|
||||
// Same applies to resetting a saved option (= saving null to the profile).
|
||||
if (to == null)
|
||||
{
|
||||
_ = to ?? Config.ApplyDefault(id, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// When not null, check if there’s a constraint on valid values.
|
||||
if (o.ValidValues != null)
|
||||
{
|
||||
if (!o.ValidValues.Contains(to))
|
||||
{
|
||||
// Handle “arrays” of values
|
||||
bool valid = false;
|
||||
if (to is string && ((string)to).Contains(";"))
|
||||
{
|
||||
valid = true;
|
||||
foreach (string value in ((string)to).Split(';'))
|
||||
{
|
||||
if (!o.ValidValues.Contains(value))
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
Log.Error($@"Invalid value ""{to}"" for option ""{id}.{option}"", reverting to default …");
|
||||
Config.ApplyDefault(id, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if null, EDDI isn’t up yet
|
||||
if (option == "alterNERDtive-base.eddi.quietMode#" && VA!.GetText("EDDI version") != null)
|
||||
{
|
||||
Log.Debug($"Resetting speech responder ({(to ?? false ? "off" : "on")}) …");
|
||||
Commands.Run("alterNERDtive-base.setEDDISpeechResponder");
|
||||
}
|
||||
else if (option == "alterNERDtive-base.log.logLevel#")
|
||||
{
|
||||
Log.SetCurrentLogLevel(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"Unhandled exception while handling changed variable '{option}'. ({e.Message})");
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateCheck()
|
||||
{
|
||||
Version latestVersion;
|
||||
try
|
||||
{
|
||||
latestVersion = new Version(new WebClient().DownloadString("https://raw.githubusercontent.com/alterNERDtive/VoiceAttack-profiles/release/VERSION"));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new Exception("Error fetching latest profiles version from Github.");
|
||||
}
|
||||
|
||||
Log.Notice($"Local version: {VERSION}, latest release: {latestVersion}.");
|
||||
|
||||
Commands.TriggerEvent(
|
||||
"alterNERDtive-base.updateCheck",
|
||||
parameters: new dynamic[] { new string[] { VERSION.ToString(), latestVersion.ToString() }, new bool[] { VERSION.CompareTo(latestVersion) < 0 } });
|
||||
}
|
||||
|
||||
/*================\
|
||||
| plugin contexts |
|
||||
\================*/
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
private static void Context_Config_Dialog(dynamic vaProxy)
|
||||
{
|
||||
Thread dialogThread = new Thread(new ThreadStart(() =>
|
||||
{
|
||||
System.Windows.Window options = new ()
|
||||
{
|
||||
Title = "alterNERDtive Profile Options",
|
||||
Content = new SettingsDialog(Config, Log),
|
||||
SizeToContent = System.Windows.SizeToContent.WidthAndHeight,
|
||||
ResizeMode = System.Windows.ResizeMode.NoResize,
|
||||
WindowStyle = System.Windows.WindowStyle.ToolWindow,
|
||||
};
|
||||
options.ShowDialog();
|
||||
options.Activate();
|
||||
}));
|
||||
dialogThread.SetApartmentState(ApartmentState.STA);
|
||||
dialogThread.IsBackground = true;
|
||||
dialogThread.Start();
|
||||
}
|
||||
|
||||
private static void Context_Config_Dump(dynamic vaProxy)
|
||||
{
|
||||
Config.DumpConfig();
|
||||
}
|
||||
|
||||
private static void Context_Config_List(dynamic vaProxy)
|
||||
{
|
||||
Config.ListConfig();
|
||||
}
|
||||
|
||||
private static void Context_Config_Setup(dynamic vaProxy)
|
||||
{
|
||||
Log.Debug("Loading default configuration …");
|
||||
Config.ApplyAllDefaults();
|
||||
foreach (System.Type type in new List<System.Type> { typeof(bool), typeof(DateTime), typeof(decimal), typeof(int), typeof(short), typeof(string) })
|
||||
{
|
||||
Config.SetVoiceTriggers(type);
|
||||
}
|
||||
|
||||
Config.LoadFromProfile();
|
||||
Log.Debug("Finished loading configuration.");
|
||||
}
|
||||
|
||||
private static void Context_Config_SetVariables(dynamic vaProxy)
|
||||
{
|
||||
string trigger = vaProxy.GetText("~trigger") ?? throw new ArgumentNullException("~trigger");
|
||||
Log.Debug($"Loading variables for trigger '{trigger}' …");
|
||||
Config.SetVariablesForTrigger(vaProxy, trigger);
|
||||
}
|
||||
|
||||
private static void Context_Config_VersionMigration(dynamic vaProxy)
|
||||
{
|
||||
// =============
|
||||
// === 4.3.1 ===
|
||||
// =============
|
||||
|
||||
// EliteAttack
|
||||
foreach (string option in new string[] { "autoStationService" })
|
||||
{
|
||||
string name = $"EliteAttack.{option}s#";
|
||||
string oldName = $"EliteAttack.{option}#";
|
||||
Commands.Run("alterNERDtive-base.loadVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{oldName}", "boolean" } });
|
||||
bool? value = vaProxy.GetBoolean(oldName);
|
||||
if (value != null)
|
||||
{
|
||||
Log.Info($"Migrating option {oldName} …");
|
||||
Commands.Run("alterNERDtive-base.saveVariableToProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}" }, new bool[] { (bool)value } });
|
||||
Commands.Run("alterNERDtive-base.unsetVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{oldName}", "boolean" } });
|
||||
}
|
||||
}
|
||||
|
||||
// ===========
|
||||
// === 4.2 ===
|
||||
// ===========
|
||||
|
||||
// SpanshAttack
|
||||
string edtsPath = $@"{vaProxy.SessionState["VA_SOUNDS"]}\scripts\edts.exe";
|
||||
if (File.Exists(edtsPath))
|
||||
{
|
||||
File.Delete(edtsPath);
|
||||
}
|
||||
|
||||
// ===========
|
||||
// === 4.0 ===
|
||||
// ===========
|
||||
|
||||
// EliteAttack
|
||||
string prefix = "EliteAttack";
|
||||
string oldPrefix = "EliteDangerous";
|
||||
foreach (string option in new string[] { "announceEdsmSystemStatus", "announceMappingCandidates", "announceOutdatedStationData", "announceR2RMappingCandidates", "autoRestock", "flightAssistOff", "hyperspaceDethrottle" })
|
||||
{
|
||||
string name = $"{prefix}.{option}";
|
||||
string oldName = $"{oldPrefix}.{option}";
|
||||
Commands.Run("alterNERDtive-base.loadVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{oldName}", "boolean" } });
|
||||
bool? value = vaProxy.GetBoolean(oldName);
|
||||
if (value != null)
|
||||
{
|
||||
Log.Info($"Migrating option {oldName} …");
|
||||
Commands.Run("alterNERDtive-base.saveVariableToProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}#" }, new bool[] { (bool)value } });
|
||||
Commands.Run("alterNERDtive-base.unsetVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{oldName}", "boolean" } });
|
||||
}
|
||||
}
|
||||
|
||||
// RatAttack
|
||||
prefix = "RatAttack";
|
||||
foreach (string option in new string[] { "autoCloseCase", "announceNearestCMDR", "announcePlatform", "confirmCalls", "onDuty" })
|
||||
{
|
||||
string name = $"{prefix}.{option}";
|
||||
Commands.Run("alterNERDtive-base.loadVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}", "boolean" } });
|
||||
bool? value = vaProxy.GetBoolean(name);
|
||||
if (value != null)
|
||||
{
|
||||
Log.Info($"Migrating option {name} …");
|
||||
Commands.Run("alterNERDtive-base.saveVariableToProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}#" }, new bool[] { (bool)value } });
|
||||
Commands.Run("alterNERDtive-base.unsetVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}", "boolean" } });
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string option in new string[] { "CMDRs", "platforms" })
|
||||
{
|
||||
string name = $"{prefix}.{option}";
|
||||
Commands.Run("alterNERDtive-base.loadVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}", "text" } });
|
||||
string value = vaProxy.GetText(name);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
Log.Info($"Migrating option {name} …");
|
||||
Commands.Run("alterNERDtive-base.saveVariableToProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}#", value } });
|
||||
Commands.Run("alterNERDtive-base.unsetVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}", "text" } });
|
||||
}
|
||||
}
|
||||
|
||||
// SpanshAttack
|
||||
prefix = "SpanshAttack";
|
||||
foreach (string option in new string[] { "announceWaypoints", "autoJumpAfterScooping", "autoPlot", "clearOnShutdown", "copyWaypointToClipboard", "defaultToLadenRange", "timeTrip" })
|
||||
{
|
||||
string name = $"{prefix}.{option}";
|
||||
Commands.Run("alterNERDtive-base.loadVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}", "boolean" } });
|
||||
bool? value = vaProxy.GetBoolean(name);
|
||||
if (value != null)
|
||||
{
|
||||
Log.Info($"Migrating option {name} …");
|
||||
Commands.Run("alterNERDtive-base.saveVariableToProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}#" }, new bool[] { (bool)value } });
|
||||
Commands.Run("alterNERDtive-base.unsetVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}", "boolean" } });
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string option in new string[] { "announceJumpsLeft" })
|
||||
{
|
||||
string name = $"{prefix}.{option}";
|
||||
Commands.Run("alterNERDtive-base.loadVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}", "text" } });
|
||||
string value = vaProxy.GetText(name);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
Log.Info($"Migrating option {name} …");
|
||||
Commands.Run("alterNERDtive-base.saveVariableToProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}#", value } });
|
||||
Commands.Run("alterNERDtive-base.unsetVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}", "text" } });
|
||||
}
|
||||
}
|
||||
|
||||
// StreamAttack
|
||||
prefix = "StreamAttack";
|
||||
foreach (string option in new string[] { "outputDir" })
|
||||
{
|
||||
string name = $"{prefix}.{option}";
|
||||
Commands.Run("alterNERDtive-base.loadVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}", "text" } });
|
||||
string value = vaProxy.GetText(name);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
Log.Info($"Migrating option {name} …");
|
||||
Commands.Run("alterNERDtive-base.saveVariableToProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}#", value } });
|
||||
Commands.Run("alterNERDtive-base.unsetVariableFromProfile", wait: true, parameters: new dynamic[] { new string[] { $"{name}", "text" } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void Context_Eddi_Event(dynamic vaProxy)
|
||||
{
|
||||
string eddiEvent = vaProxy.Command.Name();
|
||||
string command = eddiEvent.Substring(2, eddiEvent.Length - 4);
|
||||
Log.Debug($"Running EDDI event '{command}' …");
|
||||
Commands.RunAll(ActiveProfiles, command, logMissing: false, subcommand: true); // FIXXME: a) triggerAll or something, b) change all profiles to use "((<name>.<event>))" over "<name>.<event>"
|
||||
}
|
||||
|
||||
private static void Context_EDSM_BodyCount(dynamic vaProxy)
|
||||
{
|
||||
string system = vaProxy.GetText("~system") ?? throw new ArgumentNullException("~system");
|
||||
|
||||
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\scripts\explorationtools.exe";
|
||||
string arguments = $@"bodycount ""{system}""";
|
||||
|
||||
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
||||
|
||||
int bodyCount = 0;
|
||||
bool error = false;
|
||||
string errorMessage = string.Empty;
|
||||
|
||||
p.Start();
|
||||
string stdout = p.StandardOutput.ReadToEnd();
|
||||
string stderr = p.StandardError.ReadToEnd();
|
||||
p.WaitForExit();
|
||||
switch (p.ExitCode)
|
||||
{
|
||||
case 0:
|
||||
bodyCount = int.Parse(stdout);
|
||||
Log.Info($"EDSM body count for {system}: {bodyCount}");
|
||||
break;
|
||||
case 1:
|
||||
error = true;
|
||||
Log.Error(stdout);
|
||||
errorMessage = stdout;
|
||||
break;
|
||||
case 2:
|
||||
error = true;
|
||||
Log.Notice($@"System ""{system}"" not found on EDSM");
|
||||
errorMessage = stdout;
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
Log.Error(stderr);
|
||||
errorMessage = "Unrecoverable error in plugin.";
|
||||
break;
|
||||
}
|
||||
|
||||
vaProxy.SetInt("~bodyCount", bodyCount);
|
||||
vaProxy.SetBoolean("~error", error);
|
||||
vaProxy.SetText("~errorMessage", errorMessage);
|
||||
vaProxy.SetInt("~exitCode", p.ExitCode);
|
||||
}
|
||||
|
||||
private static void Context_EDSM_DistanceBetween(dynamic vaProxy)
|
||||
{
|
||||
string fromSystem = vaProxy.GetText("~fromSystem") ?? throw new ArgumentNullException("~fromSystem");
|
||||
string toSystem = vaProxy.GetText("~toSystem") ?? throw new ArgumentNullException("~toSystem");
|
||||
int roundTo = vaProxy.GetInt("~roundTo") ?? 2;
|
||||
|
||||
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\Scripts\explorationtools.exe";
|
||||
string arguments = $@"distancebetween --roundto {roundTo} ""{fromSystem}"" ""{toSystem}""";
|
||||
|
||||
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
||||
|
||||
decimal distance = 0;
|
||||
bool error = false;
|
||||
string errorMessage = string.Empty;
|
||||
|
||||
p.Start();
|
||||
string stdout = p.StandardOutput.ReadToEnd();
|
||||
string stderr = p.StandardError.ReadToEnd();
|
||||
p.WaitForExit();
|
||||
switch (p.ExitCode)
|
||||
{
|
||||
case 0:
|
||||
distance = decimal.Parse(stdout);
|
||||
Log.Info($"{fromSystem} → {toSystem}: {distance} ly");
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
error = true;
|
||||
Log.Error(stdout);
|
||||
errorMessage = stdout;
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
Log.Error(stderr);
|
||||
errorMessage = "Unrecoverable error in plugin.";
|
||||
break;
|
||||
}
|
||||
|
||||
vaProxy.SetDecimal("~distance", distance);
|
||||
vaProxy.SetBoolean("~error", error);
|
||||
vaProxy.SetText("~errorMessage", errorMessage);
|
||||
vaProxy.SetInt("~exitCode", p.ExitCode);
|
||||
}
|
||||
|
||||
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_Spansh_OutdatedStations(dynamic vaProxy)
|
||||
{
|
||||
string system = vaProxy.GetText("~system") ?? throw new ArgumentNullException("~system");
|
||||
int minage = vaProxy.GetInt("~minage") ?? throw new ArgumentNullException("~minage");
|
||||
bool includeSettlements = vaProxy.GetBoolean("~includeSettlements") ?? throw new ArgumentNullException("~includeSettlements");
|
||||
|
||||
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\Scripts\spansh.exe";
|
||||
string arguments = $@"oldstations --system ""{system}"" --minage {minage}{(includeSettlements ? string.Empty : " --nofeet")}";
|
||||
|
||||
Process p = PythonProxy.SetupPythonScript(path, arguments);
|
||||
|
||||
p.Start();
|
||||
string stdout = p.StandardOutput.ReadToEnd();
|
||||
string stderr = p.StandardError.ReadToEnd();
|
||||
p.WaitForExit();
|
||||
|
||||
string message = stdout;
|
||||
string? errorMessage = null;
|
||||
bool error = true;
|
||||
|
||||
switch (p.ExitCode)
|
||||
{
|
||||
case 0:
|
||||
error = false;
|
||||
Log.Notice($"Outdated stations for {system}: {message}");
|
||||
break;
|
||||
case 1:
|
||||
error = true;
|
||||
Log.Error(message);
|
||||
break;
|
||||
case 3:
|
||||
error = true;
|
||||
Log.Info($@"No outdated stations found for ""{system}""");
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
Log.Error(stderr);
|
||||
errorMessage = "Unrecoverable error in plugin.";
|
||||
break;
|
||||
}
|
||||
|
||||
vaProxy.SetText("~message", message);
|
||||
vaProxy.SetBoolean("~error", error);
|
||||
vaProxy.SetText("~errorMessage", errorMessage);
|
||||
vaProxy.SetInt("~exitCode", p.ExitCode);
|
||||
}
|
||||
|
||||
private static void Context_Startup(dynamic vaProxy)
|
||||
{
|
||||
Log.Notice("Starting up …");
|
||||
CheckProfiles(vaProxy);
|
||||
Log.Notice($"Active profiles: {string.Join(", ", ActiveProfiles)}");
|
||||
Commands.TriggerEventAll(ActiveProfiles, "startup", logMissing: false);
|
||||
Log.Notice("Finished startup.");
|
||||
}
|
||||
|
||||
private static void Context_Update_Check(dynamic vaProxy)
|
||||
{
|
||||
UpdateCheck();
|
||||
}
|
||||
#pragma warning restore IDE0060 // Remove unused parameter
|
||||
}
|
||||
}
|
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 } };
|
||||
}
|
||||
}
|
||||
}
|
1255
plugins/VoiceAttack-base/util.cs
Normal file
BIN
profiles/EliteAttack-Profile.vap
Normal file
BIN
profiles/alterNERDtive-base-Profile.vap
Normal file
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|