48 Commits
Author SHA1 Message Date
Storm Dragon c359c037e1 Preparing to merge. 2025-09-05 00:01:59 -04:00
Storm Dragon 08be529a33 Few fixes for custom music addons. 2025-09-04 14:54:05 -04:00
Storm Dragon 380bb2ba81 Support for custom music mods. The file name must contain the words in the correct order with correct upper case letters: Custom Music Mod and can optionally include spaces, -, or _. 2025-09-04 13:04:16 -04:00
Storm Dragon 96fc322d6e Fixed a but with how files were loaded. This should improve both game sounds and the reliability of the near by object reporting. 2025-08-13 17:18:41 -04:00
Storm Dragon f1e197729a Several bug fixes, added optional DOOM Metal X file tracking. 2025-08-08 23:54:38 -04:00
Storm Dragon 5ac894a6ec Added another metal mod option. 2025-08-08 02:18:05 -04:00
Storm Dragon d906292d5e Fixed a few renaming issues that cause some of the maps and addons to fail. Removed Demo and tutorial options because now part of main game. 2025-07-30 22:39:41 -04:00
Storm Dragon e9ca4f02e0 More changes for the new version. 2025-07-13 22:04:13 -04:00
Storm Dragon 34c42fa55c Updated deathmatch to include lobby map. 2025-07-13 20:41:57 -04:00
Storm Dragon 1c9d1127d1 update version to 9.0 2025-07-13 20:02:24 -04:00
Storm Dragon c9f9e66c7c Added support for Orca's new self-voiced capabilities. 2025-06-15 21:32:07 -04:00
Storm Dragon 2efd0de68f Make Toby Deth Match maps optional but enabled by default. 2025-05-28 14:29:50 -04:00
Storm Dragon a896792c58 Hopefully fix bug with bat file generation. 2025-05-28 13:53:47 -04:00
Storm Dragon 23441c8b28 Fixed music for funny packs. 2025-03-31 22:03:08 -04:00
Storm Dragon 6124419d29 Testing updates. 2025-03-30 21:58:26 -04:00
Storm Dragon b17f1c0672 Updated the keybinding fix part of the program. 2025-03-25 15:12:20 -04:00
Storm Dragon 432a55308f Added the targeting key, z, to auto bindings. 2025-03-25 13:34:45 -04:00
Storm Dragon 60ece5b489 Attempt to standardize controls for all mods. 2025-03-24 21:39:02 -04:00
Storm Dragon 9b8b21cc55 Generated scripts for posix systems now find the path to gzdoom in case it is not in /usr/bin. 2025-03-23 20:56:50 -04:00
Storm Dragon d10312c0d2 Added the powershell script so it will be available for generated scripts. 2025-03-22 22:41:33 -04:00
Storm Dragon 9e73910121 Experimental: Add generate script for when a game is launched. It's partially for debugging, and also for players to customize games beyond the scope of the launcher. 2025-03-22 22:28:02 -04:00
Storm Dragon 6a8f866943 Add optional doom_flags.txt so you can add flags for all games. This is experimental and may be removed. 2025-03-16 02:03:41 -04:00
Storm Dragon 21e933ab53 Fixed an error in Wolfendoom json file. 2025-02-20 20:40:53 -05:00
Storm Dragon 893f7bf455 Make sure the renamer loads any time Toby Doom levels are selected, so Project Brutality, for example, should have metal again. 2025-02-14 00:30:49 -05:00
Storm Dragon 5d8aae9386 Paths for simple menu system updated because they were not working on some systems. 2025-01-29 11:43:17 -05:00
Storm Dragon 4309fd8994 ProjectMSX added in custom games. Thanks nicotomia from forum.audiogames.net. 2025-01-29 11:42:32 -05:00
Storm Dragon c2e5a8ee3d Fixed the simple menu addon in all json files. 2025-01-27 12:18:08 -05:00
Storm Dragon 78f7ae506d Yet another attempt and handling charsets. 2025-01-25 10:56:27 -05:00
Storm Dragon a0e539d3ce Specifically set the encoding to UTF-8. Simplify speak_thread. 2025-01-25 08:41:11 -05:00
Storm Dragon db40032d3d Removed proximity addon from several json files because it's now built in. 2025-01-24 11:49:13 -05:00
Storm Dragon c3c9da9403 Back to trying to fix non-English encodings. 2025-01-22 14:18:18 -05:00
Storm Dragon a71bb0e608 Disable text to speech if self-voice is selected. This was harder than I thought it would be. Please report bugs if found. 2025-01-22 02:58:55 -05:00
Storm Dragon 02b598e987 Moved Audio Manual to a button as requested by Alando1. 2025-01-22 01:12:47 -05:00
Storm Dragon 6cd034c594 Removed the jack filtering because it needs to be redone. 2025-01-19 17:07:33 -05:00
Storm Dragon ad55390801 Another attempt at fixing speech processing for non-English characters. 2025-01-19 12:10:15 -05:00
Storm Dragon 6e9aaa9751 This attempts to fix the error:
"Error processing game output: 'gbk' codec can't decode byte 0xac in
position 33: illegal multibyte sequence"
as reported by nicotomia from the audiogames.net forum.
2025-01-17 13:39:29 -05:00
Storm Dragon 1a9b8d5c03 Had to update the jack filter because it would have matched a player name. 2025-01-15 17:04:41 -05:00
Storm Dragon d51b5fadd8 Squished more jack stuff. 2025-01-15 16:36:35 -05:00
Storm Dragon 41f525f51b Also filter out jack grumblings and messages that start with Cannot. 2025-01-15 16:29:39 -05:00
Storm Dragon f94521bfb1 Filter out alsa grumblings. 2025-01-15 16:26:32 -05:00
Storm Dragon c83714866d Update message when desired mod is not available to indicate it will be opened in the browser. 2025-01-15 08:55:28 -05:00
Storm Dragon 18279b6e7b Remove the music renamer from the DVD mod because it might cause problems with other maps. 2025-01-13 18:58:05 -05:00
Storm Dragon f82c4d2559 Updated the Doomguy Verses Daleks custom file. 2025-01-13 18:55:48 -05:00
Storm Dragon 3ee8fd0098 Doomguy Verses the Daleks custom game file added. 2025-01-12 22:18:33 -05:00
Storm Dragon 2e5c14d5d6 Moved the nvda controll,er client to the base git directory since pyinstaller deletes it while building.? 2025-01-11 15:41:11 -05:00
Storm Dragon fc53c8be24 I am sure I had fixed this once already, must have forgotten to copy over the code. Make Windows not rely on the DoomTTS.ps1 script. 2025-01-11 15:37:58 -05:00
Storm Dragon 9dd3d49174 Improved some menu strings. 2025-01-10 16:49:02 -05:00
Storm Dragon c332370ba1 Fixed the missing . in the StarWars custom file. Updated the file name and the name of the mod. 2025-01-10 14:38:51 -05:00
12 changed files with 2080 additions and 451 deletions
+231
View File
@@ -0,0 +1,231 @@
# Change the next line to $true to enable the script
$useTextToSpeech = $true
# Set this to $true to use SAPI, $false to use nvdaControllerClient or fall back to clipboard
$useSAPI = $false
# Set the speech rate. -10 to 10, default 0
$speechRate = 0
# Do not edit below this line.
######################################################################
# Exit if text-to-speech is disabled
if (-not $useTextToSpeech) {
exit
}
# Define antigrep, and sed patterns
$antigrepPatterns = @(
'^P_StartScript:',
'^[Ff]luidsynth:',
'^(Facing|INTRO|MAP[0-9]+|README)',
'^ *TITLEMAP',
'key card',
'^\[Toby Accessibility Mod\] (INTRO|READMe)([0-9]+).*',
"^(As |Computer Voice:|I |I've|Monorail|Ugh|What|Where)",
[regex]::Escape('Ugh... Huh? What the hell was that?! Better go check it out...')
)
$sedPatterns = @(
@("\[Toby Accessibility Mod\] M_", "[Toby Accessibility Mod] "),
@("^\[Toby Accessibility Mod\] ", ""),
@("^MessageBoxMenu$", "Confirmation menu: Press Y for yes or N for no"),
@("^Mainmenu$", "Main menu"),
@("^Playerclassmenu$", "Player class menu"),
@("^Skillmenu$", "Difficulty menu"),
@("^NGAME", "New game"),
@("^LOADG$", "Load game"),
@("^SAVEG$", "Save game"),
@("^QUITG$", "Quit game"),
@('"cl_run" = "true"', "Run"),
@('"cl_run" = "false"', "Walk"),
@('.*/:Game saved. \(', ""),
@('^\*\*\*', ""),
@('^\+', "")
)
# Check PowerShell version
$requiredPowershellVersion = [Version]"5.1"
$currentPowershellVersion = $PSVersionTable.PSVersion
$logFile = ".\DoomTTS.log"
Set-Content -Path $logFile -Value "Logging started $(Get-Date -Format 'dddd MMMM dd, yyyy') at $(Get-Date -Format 'hh:mmtt')"
Add-Content -Path $logFile -Value "Powershell $currentPowershellVersion"
if ($currentVersion -lt $requiredVersion) {
Add-Content -Path $logFile -Value "PowerShell version $requiredPowershellVersion or later is required. Exiting."
exit
}
# Function for logging
function Write-Log {
param (
[string]$Message,
[string]$Type = "INFO" # Can be INFO, ERROR, or SPEECH
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "$Message [$Type] [$timestamp]"
# Append the message to the log file
Add-Content -Path $logFile -Value $logMessage
# If it's an error, also write to the console
if ($Type -eq "ERROR") {
Write-Host $logMessage -ForegroundColor Red
}
}
# Function to load NVDA DLL and check if NVDA is running
function Initialize-NVDA {
try {
# Declare the P/Invoke signatures
$signature = @"
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int NvdaTestIfRunning();
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void NvdaSpeakText([MarshalAs(UnmanagedType.LPWStr)] string text);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void NvdaBrailleMessage([MarshalAs(UnmanagedType.LPWStr)] string message);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void NvdaCancelSpeech();
"@
Add-Type -MemberDefinition $signature -Name "NvdaFunctions" -Namespace "Win32Functions"
# Load the NVDA client library
$dllPath = ".\nvdaControllerClient.dll"
$nvdaDll = [Win32Functions.NvdaFunctions]::LoadLibrary($dllPath)
if ($nvdaDll -eq [IntPtr]::Zero) {
throw "Failed to load nvdaControllerClient.dll"
}
# Define function pointers
$nvdaTestIfRunning = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
[Win32Functions.NvdaFunctions]::GetProcAddress($nvdaDll, "nvdaController_testIfRunning"),
[Type][Win32Functions.NvdaFunctions+NvdaTestIfRunning]
)
$nvdaSpeakText = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
[Win32Functions.NvdaFunctions]::GetProcAddress($nvdaDll, "nvdaController_speakText"),
[Type][Win32Functions.NvdaFunctions+NvdaSpeakText]
)
$nvdaBrailleMessage = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
[Win32Functions.NvdaFunctions]::GetProcAddress($nvdaDll, "nvdaController_brailleMessage"),
[Type][Win32Functions.NvdaFunctions+NvdaBrailleMessage]
)
$nvdaCancelSpeech = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
[Win32Functions.NvdaFunctions]::GetProcAddress($nvdaDll, "nvdaController_cancelSpeech"),
[Type][Win32Functions.NvdaFunctions+NvdaCancelSpeech]
)
# Test if NVDA is running
$res = $nvdaTestIfRunning.Invoke()
if ($res -ne 0) {
$errorMessage = [ComponentModel.Win32Exception]::new([System.Runtime.InteropServices.Marshal]::GetLastWin32Error()).Message
throw "NVDA is not running or communication failed. Error: $errorMessage"
}
return @{
SpeakText = $nvdaSpeakText
BrailleMessage = $nvdaBrailleMessage
CancelSpeech = $nvdaCancelSpeech
}
}
catch {
Write-Log -Message "Error initializing NVDA: $_" -Type "ERROR"
return $null
}
}
# Function to speak text using SAPI, NVDA, or copy to clipboard
function Speak-Text {
param (
[string]$text
)
Write-Log -Message "Speaking: $text" -Type "SPEECH"
if ($useSAPI) {
try {
$tts = New-Object -ComObject SAPI.SPVoice
$tts.Rate = $speechRate
$tts.Speak($text)
} catch {
Write-Log -Message "Error using SAPI: $_" -Type "ERROR"
}
} else {
$nvdaFunctions = Initialize-NVDA
if ($nvdaFunctions) {
try {
$nvdaFunctions.SpeakText.Invoke($text)
} catch {
Write-Log -Message "Error using nvdaControllerClient.dll: $_" -Type "ERROR"
Set-Clipboard -Value $text
}
} else {
Set-Clipboard -Value $text
Write-Log -Message "Failed to initialize NVDA, text copied to clipboard" -Type "INFO"
}
}
}
# Process the output with grep, antigrep, and sed-like functionality
function Process-Output {
param (
[string]$line,
[string[]]$antigrepPatterns,
[array]$sedPatterns
)
# Apply antigrep (exclude lines)
foreach ($pattern in $antigrepPatterns) {
if ($line -match $pattern) {
return # Skip this line
}
}
# Apply sed (modify lines)
foreach ($pattern in $sedPatterns) {
$line = $line -replace $pattern[0], $pattern[1]
}
return $line
}
# Start reading the piped output
$stream = [System.IO.StreamReader]::new([Console]::OpenStandardInput(), [System.Text.Encoding]::UTF8)
# Use the 40 - line to let us know when to start speaking.
$startProcessing = $false
while ($null -ne ($line = $stream.ReadLine())) {
Write-Log -Message "Raw input: $line" -Type "INFO"
# Check for the separator
if ($line -match '^-{5,}$') {
$startProcessing = $true
continue # Skip the separator
}
# Only process lines after we've seen the separator
if ($startProcessing) {
$processedLine = Process-Output -line $line -antigrepPatterns $antigrepPatterns -sedPatterns $sedPatterns
if ($processedLine) {
Write-Log -Message "Processed line: $processedLine" -Type "INFO"
Speak-Text -text $processedLine
}
}
}
+1615 -137
View File
File diff suppressed because it is too large Load Diff
-124
View File
@@ -1,124 +0,0 @@
#!/usr/bin/env bash
pushd "$doomPath"
# Set up the pk3 and wad files
gameOption=(
"$(find /usr/share/games/ -name 'Project_Brutality-master.pk3')"
"${doomPath}/TobyAccMod_V${tobyVersion}.pk3"
"${doomPath}/PB-Toby-Compatibility-Addon.pk3"
"${doomPath}/Toby-Universal-Pickup-Beacon-Prototype.pk3"
"${doomPath}/TobyDeathArena_V1-0.wad"
)
# Death match setup
ipAddress="$(dialog --backtitle "Deathmatch Options" \
--clear \
--no-tags \
--ok-label "Join" \
--cancel-label "Exit" \
--extra-button \
--extra-label "Host" \
--inputbox "Enter ip or URL, required for join." -1 -1 --stdout)"
buttonCode=$?
[[ $buttonCode -eq 1 ]] && exit 0
if [[ $buttonCode -eq 0 ]]; then
if [[ "${#ipAddress}" -lt 3 ]]; then
dialog --backtitle "Deathmatch" --clear --msgbox "No ip address or URL given." -1 -1 --stdout
exit 1
fi
flags=('-join' "${ipAddress}")
else
# List of maps included:
maps=(
"1" "Com Station (2-4 players)"
"2" "Warehouse (2-4 players)"
"3" "Sector 3 (2-4 players)"
"4" "Dungeon of Doom (2-4 players)"
"5" "Ocean Fortress (2-4 players)"
"6" "Water Treatment Facility (2-4 players)"
"7" "Phobos Base Site 4 (2-4 players)"
"8" "Hangar Bay 18 (2-4 players)")
# Array of how many players a given map supports in dialog rangebox syntax
declare -a mapPlayers=(
[1]="2 4"
[2]="2 4"
[3]="2 4"
[4]="2 4"
[5]="2 4"
[6]="2 4"
[7]="2 4"
[8]="2 4")
map="$(dialog --backtitle "Select Map" \
--clear \
--no-tags \
--cancel-label "Exit" \
--ok-label "Next" \
--menu "Please select one" 0 0 0 "${maps[@]}" --stdout)"
fraglimit="$(dialog --backtitle "Fraglimit" \
--clear \
--ok-label "Next" \
--cancel-label "Exit" \
--rangebox "Select Fraglimit" -1 -1 1 500 20 --stdout)"
[[ $? -eq 1 ]] && exit 0
# Get ip address
yourIpAddress="$(curl -4s https://icanhazip.com)"
players="$(dialog --backtitle "Host Deathmatch Game" \
--clear \
--ok-label "Next" \
--cancel-label "Exit" \
--rangebox "Select number of players. Remember to give them your IP address: ${yourIpAddress}" -1 -1 ${mapPlayers[$map]} --stdout)"
[[ $? -eq 1 ]] && exit 0
skillLevel="$(dialog --backtitle "Host Deathmatch Game" \
--clear \
--ok-label "Start" \
--cancel-label "Exit" \
--extra-button \
--extra-label "Bots Only" \
--rangebox "Select difficulty. 1 easiest, 5 hardest." -1 -1 1 5 3 --stdout)"
code=$?
[[ $code -eq 1 ]] && exit 0
if [[ $code -eq 3 ]]; then
players=1
dialog --backtitle "Preparing to Launch" \
--msgbox "When the game starts, press \` to open the console. Type addbot, press enter. Repeat addbot for as many bots as you would like. Press \` again to close the console." -1 -1 --stdout
fi
flags=(
'-host' "${players}"
'-skill' "${skillLevel}"
'-deathmatch'
'+set' 'sv_cheats' '1'
'+fraglimit' "$fraglimit"
'+dmflags' '16384' '+dmflags' '4' '+dmflags' '128' '+dmflags' '4096'
'+dmflags2' '512' '+dmflags2' '1024'
'-extratic' '-dup' '3'
'-warp' "$map"
)
fi
# Check for and include if present a wad. Some people may not have it.
if [[ -e "${doomPath}/DoomMetalVol7.wad" ]]; then
gameOption+=" DoomMetalVol7.wad"
elif [[ -e "${doomPath}/DoomMetalVol6.wad" ]]; then
gameOption+=" DoomMetalVol6.wad"
fi
# Extend the search for new messages to be read.
grepStrings+=('-e' ' died.'
'-e' 'Ectoplasmic Surge!'
'-e' ' has been '
'-e' '^(Armor|Health) boosted!'
'-e' 'Lesser demon energy'
'-e' '^Found '
'-e' 'Got the '
'-e' 'Picked up '
'-e' '^(Mega|Soul)sphere$'
'-e' '^Took '
'-e' ' was .*(\.|!)'
'-e' '^Vanguard of the gods!$'
'-e' "You've found "
'-e' 'You (collected|got|found|picked up) ')
# Launch the game and pipe things to be spoken through speech-dispatcher.
# This also leaves the console output intact for people who may want to read it.
exec stdbuf -oL ${gzdoom} ${gameOption[@]} "${flags[@]}" | while IFS= read -r l ; do echo "$l" | { grep "${grepStrings[@]}" | grep "${antiGrepStrings[@]}" | sed "${sedStrings[@]}" | spd-say -e ${spd_module} ${spd_pitch} ${spd_rate} ${spd_voice} ${spd_volume} -- > /dev/null 2>&1; }; echo "$l";done
+2 -1
View File
@@ -10,10 +10,11 @@
} }
], ],
"files": [ "files": [
"Addons/MENU/TobyV{toby_base_version}_*", "Addons/MENU/TobyV*_SimpleMenu.pk3",
"aoddoom1.wad" "aoddoom1.wad"
], ],
"optional_files": [ "optional_files": [
"DOOM Metal X IDKFA Soundtrack.pk3",
"DoomMetalVol7.wad", "DoomMetalVol7.wad",
"DoomMetalVol6.wad" "DoomMetalVol6.wad"
], ],
+25
View File
@@ -0,0 +1,25 @@
{
"name": "DoomGuy Verses the Daleks",
"dependencies": [
{
"file": "DoomguyVsTheDaleks_V1.1.wad",
"url": "https://www.moddb.com/mods/doomguy-vs-the-daleks",
"messages": [
"Place \"DoomguyVsTheDaleks_V1.1.wad\" in the Toby Doom directory. On Linux/Mac this is ~/.local/games/doom"
]
}
],
"files": [
"Addons/MENU/TobyV*_SimpleMenu.pk3",
"Addons/DOOM/TobyV*_Decorations.pk3",
"Addons/DOOM/TobyV*_Guns.pk3",
"Addons/DOOM/TobyV*_Pickups.pk3",
"DoomguyVsTheDaleks_V1.1.wad"
],
"optional_files": [
"DOOM Metal X IDKFA Soundtrack.pk3",
"DoomMetalVol7.wad",
"DoomMetalVol6.wad"
],
"use_map_menu": true
}
+1 -2
View File
@@ -10,8 +10,7 @@
} }
], ],
"files": [ "files": [
"Addons/MENU/TobyV{toby_base_version}_*", "Addons/MENU/TobyV*_SimpleMenu.pk3",
"Addons/DOOM/TobyV{toby_base_version}_Proximity.pk3",
"GMOTA_V.1.5.2.pk3" "GMOTA_V.1.5.2.pk3"
], ],
"flags": [ "flags": [
+17
View File
@@ -0,0 +1,17 @@
{
"name": "ProjectMSX",
"dependencies": [
{
"file": "projectmsx_v0.2a.pk3",
"url": "https://www.moddb.com/mods/project-msx",
"messages": [
"Place projectmsx_v0.2a.pk3 in the Toby Doom directory. On Linux/Mac this is ~/.local/games/doom."
]
}
],
"files": [
"Addons/MENU/TobyV*_SimpleMenu.pk3",
"projectmsx_v0.2a.pk3"
],
"use_map_menu": true
}
+2 -1
View File
@@ -12,11 +12,12 @@
} }
], ],
"files": [ "files": [
"Addons/DOOM/TobyV{toby_base_version}_Proximity.pk3", "Addons/MENU/TobyV*_SimpleMenu.pk3",
"PB-Toby-Compatibility-Addon.pk3", "PB-Toby-Compatibility-Addon.pk3",
"Project_Brutality.pk3" "Project_Brutality.pk3"
], ],
"optional_files": [ "optional_files": [
"DOOM Metal X IDKFA Soundtrack.pk3",
"DoomMetalVol7.wad", "DoomMetalVol7.wad",
"DoomMetalVol6.wad" "DoomMetalVol6.wad"
], ],
+2 -1
View File
@@ -11,10 +11,11 @@
} }
], ],
"files": [ "files": [
"Addons/DOOM/TobyV{toby_base_version}_Proximity.pk3", "Addons/MENU/TobyV*_SimpleMenu.pk3",
"Project_Brutality-Latest.pk3" "Project_Brutality-Latest.pk3"
], ],
"optional_files": [ "optional_files": [
"DOOM Metal X IDKFA Soundtrack.pk3",
"DoomMetalVol7.wad", "DoomMetalVol7.wad",
"DoomMetalVol6.wad" "DoomMetalVol6.wad"
], ],
+1 -2
View File
@@ -29,8 +29,7 @@
] ]
}, },
"files": [ "files": [
"Addons/MENU/TobyV{toby_base_version}_*", "Addons/MENU/TobyV*_SimpleMenu.pk3"
"Addons/DOOM/TobyV{toby_base_version}_Proximity.pk3"
], ],
"flags": [ "flags": [
"+bind", "Ctrl", "+attack", "+bind", "Ctrl", "+attack",
@@ -1,15 +1,16 @@
{ {
"name": "Star Wars", "name": "Xim Star Wars",
"dependencies": [ "dependencies": [
{ {
"file": "Xim-StarWars-v3.1.5.pk3", "file": "Xim-StarWars-v3.1.5.pk3",
"url": "https://www.moddb.com/mods/xims-star-wars-doom", "url": "https://www.moddb.com/mods/xims-star-wars-doom",
"messages": [ "messages": [
"Place Xim-StarWars-v3.1.5.pk3 in the Toby Doom directory, on Linux or Mac, ~/.local/games/doom" "Extract Xim-StarWars-v3.1.5.6.zip to the Toby Doom directory, on Linux or Mac, ~/.local/games/doom"
] ]
} }
], ],
"files": [ "files": [
"Addons/MENU/TobyV*_SimpleMenu.pk3",
"Xim-StarWars-v3.1.5.pk3", "Xim-StarWars-v3.1.5.pk3",
"Addons/STARWARS/*.pk3" "Addons/STARWARS/*.pk3"
], ],