Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
build/
test/
25 changes: 24 additions & 1 deletion BUILD_WINDOWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Building Devotion on Windows (with WSL)

1. Install Windows Subsystem for Linux
2. Launch the command line or powershell
3. Type 'wsl' to launch the WSL default shell
4. Within the shell, navigate to the repo directory
5. 'make'

# Building Devotion on Windows (without WSL)

This repo is built with GNU Make and Unix tooling. On Windows you do **not** need the Windows Subsystem for Linux (WSL). Use [**MSYS2**](https://www.msys2.org/) instead—a minimal POSIX environment alongside MinGW-w64—not a Linux distro.
This repo is built with GNU Make and Unix tooling. On Windows you could use the Windows Subsystem for Linux (WSL) to build it but alternatively you can use [**MSYS2**](https://www.msys2.org/). It's a minimal POSIX, not a full-blown distro, and has the advantage that you don't need windows hypervisor features installed to run it, unlike WSL.

## 1. Install MSYS2

Expand Down Expand Up @@ -45,6 +53,21 @@ Artifacts:
- Staged pak contents: `build/pk3/`
- Packaged PK3: `build/devotion-<version>.pk3` (basename from the root Makefile)

## 4. Build and local test install

From the repo root in **PowerShell** (with MSYS2 on `PATH`, or `msys2_shell.cmd` available):

```powershell
.\build_windows.ps1 # build only
.\build_windows.ps1 -Deploy # build, then copy PK3 to test\devotion\
.\build_windows.ps1 -NoBuild -Deploy # deploy only (PK3 already built)
.\build_windows.ps1 -Quiet # suppress per-file compile lines and config banner (warnings/errors still print)
```

From MSYS2 MINGW64 you can pass the same flag to GNU Make: `make QUIET=1` (also applies to `make clean QUIET=1`). This uses the ioquake3-style `QUIET=1` variable in [`ratoa_gamecode/Makefile`](ratoa_gamecode/Makefile); do not confuse it with `V=1`, which prints full compiler command lines.

The `test/` tree is gitignored so you'll have to build a test environment yourself in that folder: You need a minimal local Quake III install (`baseq3/`, `devotion/`, Quake3e binaries). After `-Deploy`, run the test install yourself (e.g. `test\quake3e-vulkan.x64 +set fs_game devotion`).

## 5. Troubleshooting

**`cp: cannot stat '.../vm/*.qvm': No such file or directory`**
Expand Down
13 changes: 9 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ ASSETS_DIR := ratoa_assets

GAMECODE_OPTS := WITH_MULTITOURNAMENT=0

# QUIET=1: suppress make chatter and per-file compile lines (see ratoa_gamecode/Makefile).
ifeq ($(QUIET),1)
MAKEFLAGS += -s --no-print-directory
endif

OUTPUT_DIR := build
PK3_DIR := $(OUTPUT_DIR)/pk3

Expand All @@ -44,21 +49,21 @@ release: qvm $(OUTPUT_DIR)
mkdir $(PK3_DIR)/vm
cp $(GAMECODE_QVM_DIR)/*.qvm $(PK3_DIR)/vm/
#cd $(PK3_DIR) && zip -r ../$(RATMOD_PK3) -- .
cd $(PK3_DIR) && $(CURDIR)/caca_deterministic_zip.sh \
cd $(PK3_DIR) && QUIET=$(QUIET) $(CURDIR)/caca_deterministic_zip.sh \
$(TIMESTAMP) ../$(RATMOD_PK3) .

qvm:
$(MAKE) -C $(GAMECODE_DIR) $(GAMECODE_OPTS) \
BUILD_GAME_SO=0 BUILD_GAME_QVM=1
BUILD_GAME_SO=0 BUILD_GAME_QVM=1 QUIET=$(QUIET)

$(OUTPUT_DIR):
mkdir -p $(OUTPUT_DIR)

clean_assets:
$(MAKE) -C $(ASSETS_DIR) clean
$(MAKE) -C $(ASSETS_DIR) clean QUIET=$(QUIET)

clean_gamecode:
$(MAKE) -C $(GAMECODE_DIR) clean
$(MAKE) -C $(GAMECODE_DIR) clean QUIET=$(QUIET)

clean_output:
rm -rf $(OUTPUT_DIR)
Expand Down
78 changes: 78 additions & 0 deletions build_windows.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Build Devotion on Windows via MSYS2 MINGW64.
# Important: mingw64 must be on the PATH.
# Optional: copy the built PK3 into the local test install (test\devotion\).
param(
[switch]$Deploy,
[switch]$NoBuild,
[switch]$Quiet
)

$ErrorActionPreference = "Stop"
$RepoRoot = $PSScriptRoot

function Deploy-TestPk3 {
$BuildDir = Join-Path $RepoRoot "build"
$ModDir = Join-Path $RepoRoot "test\devotion"

if (-not (Test-Path $ModDir)) {
Write-Error "Test install not found at $ModDir"
}

$pk3 = Get-ChildItem -Path $BuildDir -Filter "devotion-*.pk3" -File |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1

if (-not $pk3) {
Write-Error "No devotion-*.pk3 in $BuildDir - run build first (omit -NoBuild)."
}

Get-ChildItem -Path $ModDir -Filter "devotion-*.pk3" -File | ForEach-Object {
if ($_.FullName -ne (Join-Path $ModDir $pk3.Name)) {
Remove-Item -LiteralPath $_.FullName -Force
Write-Host "Removed old $($_.Name)"
}
}

$dest = Join-Path $ModDir $pk3.Name
Copy-Item -LiteralPath $pk3.FullName -Destination $dest -Force
Write-Host ('Deployed {0} to {1}' -f $pk3.Name, $dest)
}

Push-Location $RepoRoot
try {
if (-not $NoBuild) {
$quietFlag = if ($Quiet) { "QUIET=1" } else { "" }
$makeArgs = if ($quietFlag) {
"make clean $quietFlag;make $quietFlag"
} else {
"make clean;make"
}
# Compiler warnings go to stderr; merge streams without NativeCommandError noise.
$prevEap = $ErrorActionPreference
$ErrorActionPreference = 'Continue'
try {
msys2_shell.cmd -mingw64 -defterm -no-start -here -c $makeArgs 2>&1 |
ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
$_.ToString()
} else {
$_
}
}
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
finally {
$ErrorActionPreference = $prevEap
}
if ($Quiet) {
Write-Host "Build succeeded."
}
}

if ($Deploy) {
Deploy-TestPk3
}
}
finally {
Pop-Location
}
6 changes: 5 additions & 1 deletion caca_deterministic_zip.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ shift 2
find "$@" -type d -print0 | xargs -0r chmod 755
find "$@" -type f -print0 | xargs -0r chmod 644
find "$@" -print0 -print0 | xargs -0r touch
find "$@" | sort | zip -X -@ "$OUTFILE"
if [ "$QUIET" = "1" ]; then
find "$@" | sort | zip -q -X -@ "$OUTFILE"
else
find "$@" | sort | zip -X -@ "$OUTFILE"
fi



34 changes: 30 additions & 4 deletions docs/BOT-CVARS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ Console variables that control bot AI, navigation, chat, and fill rules. Set the
| Name | Origin | Default | Valid values | Description |
|------|--------|---------|--------------|-------------|
| `bot_aasoptimize` | Vanilla | `0` | 0 or 1 | When `1`, allows the bot navigation library to optimize the map’s AAS data when it is built or loaded. |
| `bot_challenge` | Vanilla | `0` | 0 or 1 | Harder bots: steadier aim when locked on and more precise view tracking. Disables `bot_humanizeaim` while enabled. |
| `bot_challenge` | Vanilla | `0` | 0 or 1 | Harder bots on **legacy** aim: steadier tracking and snap-to-target when locked on. No effect on `bot_enhanced_aim` (enhanced harness ignores this cvar). |
| `bot_developer` | Vanilla | `0` | 0 or 1 | Extra bot-library debug output. Requires `sv_cheats 1`. |
| `bot_debugAim` | Devotion | `0` | 0 or 1 | Publishes bot aim on `ps.grapplePoint`, `STAT_EXTFLAGS` (`EXTFL_BOT_AIM_DEBUG`), and `ent->s.origin2` for `cg_debugBotAim`. Works with or without enhanced aim. Requires `sv_cheats 1`. |
| `bot_enable` | Vanilla | `0` | 0 or 1 | Master switch: bots only load and play when `1`. Usually set in `server.cfg` (provided by the engine, not the game module). |
| `bot_enhanced` | Devotion | `0` | 0 or 1 | Master switch for Devotion bot AI upgrades (aim harness, smart weapons, tactics). When `0`, sub-cvars have no effect. Saved to config. |
| `bot_enhanced_aim` | Devotion | `0` | 0 or 1 | Smoother, more human-like bot aiming when `1` and `bot_enhanced` is `1` (`0` = classic snap aim). Independent of `bot_challenge`. Saved to config. |
| `bot_enhanced_tactics` | Devotion | `0` | 0 or 1 | Extra combat decisions when `1` and `bot_enhanced` is `1`: gauntlet rush/flee, react to third-party damage, finish wounded targets, prefer nearer threats. Saved to config. |
| `bot_enhanced_items` | Devotion | `1` | 0 or 1 | Visible mega/red/yellow armor pickup with committed goals when `1` and `bot_enhanced` is `1`. Saved to config. |
| `bot_enhanced_items_debug` | Devotion | `0` | 0 or 1 | Server console lines when bots commit to or abandon major item pickups. |
| `bot_enhanced_weapons` | Devotion | `0` | 0 or 1 | Smarter weapon picks by range and ammo when `1` and `bot_enhanced` is `1` (e.g. rail/MG at distance, rocket mid-range, shotgun up close). Saved to config. |
| `bot_fastchat` | Vanilla | `0` | 0 or 1 | When `1`, bots are more likely to use chat lines (skips some random “stay quiet” rolls). |
| `bot_forceclustering` | Vanilla | `0` | 0 or 1 | Forces the navigation system to rebuild area clusters for the current map (slow; map load / AAS build). |
| `bot_forcereachability` | Vanilla | `0` | 0 or 1 | Forces reachability between areas to be recalculated (slow; map load / AAS build). |
| `bot_forcewrite` | Vanilla | `0` | 0 or 1 | Forces the navigation `.aas` file to be written to disk when the map is processed. |
| `bot_grapple` | Vanilla | `0` | 0 or 1 | When `1`, bots may use the off-hand grapple for movement where the mod supports it. |
| `bot_humanizeaim` | Devotion | `0` | 0 or 1 | Smoother, more human-like bot aiming when `1` (`0` = classic snap aim). No effect while `bot_challenge` is `1`. Saved to config. |
| `bot_interbreedbots` | Vanilla | `10` | integer ≥ 1 | Number of bots spawned when a bot “interbreeding” run starts. |
| `bot_interbreedchar` | Vanilla | `` | bot name string | Bot character file to use for interbreeding; setting this starts a tournament-style breeding session. Cleared after spawn. |
| `bot_interbreedcycle` | Vanilla | `20` | integer ≥ 1 | How many matches to run before the best bot’s AI is saved and a new generation is spawned. |
Expand All @@ -29,12 +35,32 @@ Console variables that control bot AI, navigation, chat, and fill rules. Set the
| `bot_report` | Vanilla | `0` | 0 or 1 | Updates internal bot status info shown in server config strings. Requires `sv_cheats 1`. |
| `bot_rocketjump` | Vanilla | `1` | 0 or 1 | When `1`, bots may rocket-jump for vertical movement; `0` disables it. |
| `bot_saveroutingcache` | Vanilla | `0` | 0 or 1 | One-shot: saves the routing cache for the current map, then resets to `0`. Requires `sv_cheats 1`. |
| `bot_smartWeaponChoice` | Devotion | `0` | 0 or 1 | Smarter weapon picks by range and ammo when `1` (e.g. rail/MG at distance, rocket mid-range, shotgun up close). `0` = original picker. Saved to config. |
| `bot_tacticalAI` | Devotion | `0` | 0 or 1 | Extra combat decisions when `1`: gauntlet rush/flee, react to third-party damage, finish wounded targets, prefer nearer threats. `0` = legacy behavior. Saved to config. |
| `bot_testclusters` | Vanilla | `0` | 0 or 1 | Debug: print AAS area/cluster under the bot’s view. Requires `sv_cheats 1`. |
| `bot_testichat` | Vanilla | `0` | 0 or 1 | Test mode: new bots fire their “enter game” chat line immediately. |
| `bot_testrchat` | Vanilla | `0` | 0 or 1 | Test mode: triggers random chat handling in the bot library. |
| `bot_testsolid` | Vanilla | `0` | 0 or 1 | Debug: report whether the bot’s view point is in solid AAS. Requires `sv_cheats 1`. |
| `bot_thinktime` | Vanilla | `100` | integer (ms), max 200 | Milliseconds between bot AI updates; lower = more reactive bots, higher = less CPU. Capped at 200. |
| `bot_visualizejumppads` | Vanilla | `0` | 0 or 1 | Debug: draw jump-pad reachability in the navigation mesh. |
| `bot_wigglefactor` | Vanilla | `0.0` | 0.0–1.0 | How often bots change strafe direction in combat; higher = more side-to-side movement. |

## Deprecated enhanced-bot cvars

These names are **not registered** by the game module anymore. On first load, if a new `bot_enhanced_*` cvar is still at its default and the old name is set in `server.cfg`, the value is copied once and `bot_enhanced` is turned on when needed. A one-line message is printed to the server console when any deprecated name is detected.

| Deprecated | Replaced by |
|------------|-------------|
| `bot_humanizeaim` | `bot_enhanced` + `bot_enhanced_aim` |
| `bot_smartWeaponChoice` | `bot_enhanced` + `bot_enhanced_weapons` |
| `bot_tacticalAI` | `bot_enhanced` + `bot_enhanced_tactics` |

Example (equivalent to the old `set bot_humanizeaim 1`):

```text
set bot_enhanced 1
set bot_enhanced_aim 1
set bot_enhanced_items 1
```

Sub-cvars alone (`bot_enhanced_aim 1` without `bot_enhanced 1`) have no effect unless the master is enabled or legacy migration runs at init.

For architecture, extension points, and the **Phase 8 parity test checklist**, see [BOT-ENHANCED-ARCHITECTURE.md](BOT-ENHANCED-ARCHITECTURE.md).
Loading