Skip to content
Merged
Changes from 1 commit
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
207 changes: 105 additions & 102 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,104 @@
# QuickMap

Hold the gamepad **Start button** for a configurable duration to open the **world map**. A short press opens whatever Start is natively bound to (Journal Menu or Tween Menu) as normal.
Hold the gamepad **Start button** for a configurable duration to open the **world map**. A short press opens the Journal Menu (or Tween Menu) as normal.

Inspired by Red Dead Redemption 2's hold-start-to-open-map mechanic.
> **Gamepad only.** Keyboard and mouse users are unaffected — vanilla behaviour is fully preserved.

Supports building on **Linux** (cross-compilation via `clang-cl` + [xwin](https://github.com/Jake-Shadle/xwin)) and **Windows** (MSVC).
Inspired by Red Dead Redemption 2's hold-Start-to-open-map mechanic.

---

## Prerequisites
## Requirements

### All platforms
- [Skyrim Special Edition](https://store.steampowered.com/app/489830) or Anniversary Edition
- [SKSE64](https://skse.silverlock.org/)
- [Address Library for SKSE Plugins](https://www.nexusmods.com/skyrimspecialedition/mods/32444)

## Installation

**Mod manager (recommended):**
1. Install the requirements above.
2. Install QuickMap via your mod manager.
3. Launch Skyrim via SKSE.

**Manual:**
1. Install the requirements above.
2. Copy `QuickMap.dll` and `QuickMap.ini` to `Data\SKSE\Plugins\`.
3. Launch Skyrim via SKSE.

## Configuration

Edit `Data\SKSE\Plugins\QuickMap.ini`:

```ini
[General]
; Duration in seconds the Start button must be held to open the map (default: 1.0)
fHoldDuration=1.0
```

Logs are written to:
```
%USERPROFILE%\Documents\My Games\Skyrim Special Edition\SKSE\QuickMap.log
```

---

## Development

### Prerequisites

#### All platforms
- [Git](https://git-scm.com/)
- [CMake](https://cmake.org/download/) 3.21+
- [vcpkg](https://vcpkg.io/en/getting-started) — set `VCPKG_ROOT` in your environment
- vcpkg — set `VCPKG_ROOT` in your environment

### Linux
- LLVM/Clang (provides `clang-cl`, `lld-link`, `llvm-lib`, `llvm-rc`, `llvm-mt`)
- [xwin](https://github.com/Jake-Shadle/xwin) — downloads the real Windows SDK and MSVC CRT headers/libs
#### Linux
- LLVM/Clang (`clang-cl`, `lld-link`, `llvm-lib`, `llvm-rc`, `llvm-mt`)
- [xwin](https://github.com/Jake-Shadle/xwin) — downloads the Windows SDK and MSVC CRT headers/libs
- [Ninja](https://ninja-build.org/)

```bash
# Arch / CachyOS
sudo pacman -S clang lld llvm ninja
```bash
# Arch / CachyOS
sudo pacman -S clang lld llvm ninja

# Install xwin (requires Rust/cargo)
cargo install xwin
# Install xwin (requires Rust/cargo)
cargo install xwin

# Fetch Windows SDK + MSVC CRT headers to ~/.xwin (one-time, ~700 MB)
xwin splat --output ~/.xwin
```
# Fetch Windows SDK + MSVC CRT headers to ~/.xwin (one-time, ~700 MB)
xwin splat --output ~/.xwin
```

### Windows
> **Note:** On first CMake configure, `cmake/toolchains/clang-cl-cross.cmake` creates TitleCase symlinks inside your xwin installation (e.g. `Advapi32.lib → advapi32.lib`). The originals are untouched. This is required because `lld-link` is case-sensitive but CommonLibSSE-NG references libs with mixed-case names.

#### Windows
- [Visual Studio 2022](https://visualstudio.microsoft.com/) with **Desktop development with C++**

---

## Getting Started
### Getting Started

#### Linux

### 1. Clone
##### 1. Clone

```bash
git clone --recurse-submodules https://github.com/codepuncher/QuickMap.git
cd QuickMap
```

### 2. Configure deploy path
##### 2. Configure deploy path

Edit `.env` and set `SKYRIM_MODS_FOLDER` to your mod manager's staging folder:

```bash
# Vortex (Linux, Steam):
SKYRIM_MODS_FOLDER=$HOME/.local/share/Steam/steamapps/common/Vortex Mods/skyrimse
SKYRIM_MODS_FOLDER="$HOME/.local/share/Steam/steamapps/common/Vortex Mods/skyrimse"

# MO2 (Linux):
# SKYRIM_MODS_FOLDER=$HOME/MO2/mods
# SKYRIM_MODS_FOLDER="$HOME/MO2/mods"
```

### 3. Build
##### 3. Build

```bash
./scripts/build.sh
Expand All @@ -68,33 +109,15 @@ cmake --build --preset release-linux

The DLL lands in `build/release-linux/QuickMap.dll`.

> **Note:** On first configure, `cmake/toolchains/clang-cl-cross.cmake` creates
> TitleCase symlinks inside your xwin installation, e.g.:
> ```
> ~/.xwin/sdk/lib/um/x86_64/Advapi32.lib -> advapi32.lib
> ```
> lld-link is case-sensitive but CommonLibSSE-NG references libs with mixed-case names.
> The originals are untouched.

#### Deploy to mod manager
##### Deploy to mod manager

```bash
./scripts/deploy.sh
# or directly (deploy.sh sources .env for you; cmake does not):
source .env && cmake --workflow --preset deploy
```

This configures, builds, and copies `QuickMap.dll` + `QuickMap.pdb` directly into:
```
$SKYRIM_MODS_FOLDER/QuickMap/SKSE/Plugins/
```

Vortex will detect the new mod folder automatically. Enable it in Vortex, then launch Skyrim.

On subsequent builds (no config change needed):
```bash
./scripts/deploy.sh
```
Copies `QuickMap.dll` + `QuickMap.pdb` into `$SKYRIM_MODS_FOLDER/QuickMap/SKSE/Plugins/`.
Comment thread
codepuncher marked this conversation as resolved.
Outdated

#### Windows (MSVC)

Expand All @@ -107,83 +130,35 @@ The DLL lands in `build/msvc/Release/QuickMap.dll`.

---

## What QuickMap Does

When loaded by Skyrim the plugin:

1. **Writes a log** to `%USERPROFILE%\Documents\My Games\Skyrim Special Edition\SKSE\QuickMap.log` via spdlog.
2. **Registers an input sink** at `kInputLoaded` to intercept gamepad Start button events.
3. **Refreshes the short-press binding** at `kInputLoaded`, `kPostLoadGame`, and `kNewGame` by querying `ControlMap`.

Hold duration is configurable via `Data/SKSE/Plugins/QuickMap.ini`:

```ini
[General]
fHoldDuration=1.0
```

---

## GitHub Actions CI

| Workflow | Trigger | What it does |
|---|---|---|
| `setup.yml` | First push in a repo created from this template | Renames placeholders using the repo name, then self-deletes |
| `build.yml` | PRs to `main` touching source/cmake/vcpkg | Builds on Windows (MSVC + vcpkg), uploads DLL + PDB |
| `release.yml` | Push of a `v*` tag (or manual `workflow_dispatch`) | Same build, publishes a GitHub Release with DLL + PDB; opt-in Nexus Mods upload via dispatch input |
| `format.yml` | PRs touching `src/**` or `.clang-format` | Checks C++ formatting with clang-format |
| `tidy.yml` | PRs touching `src/**`, cmake, or `.clang-tidy` | Runs clang-tidy static analysis on Windows (MSVC headers) |
| `lint.yml` | PRs touching `scripts/` | Runs shellcheck on shell scripts |
| `pr-title.yml` | PR opened/edited/reopened/synchronize | Checks PR title follows Conventional Commits (`feat`, `fix`, `chore`, `docs`, `refactor`, `ci`, `build`, `perf`, `test`, `style`, `revert`) |

### Nexus Mods Upload

`release.yml` includes an optional Nexus Mods upload step, triggered only when running via **workflow_dispatch** with `upload_to_nexus: true`.

**Prerequisites (one-time setup):**
1. Upload your first file manually via the [Nexus Mods web UI](https://www.nexusmods.com) — this creates the file group.
2. Note the `file_group_id` from the URL or mod manager.
3. Add to your repository:
- **Secret** `NEXUSMODS_API_KEY` — your Nexus Mods API key (Settings → Secrets → Actions)
- **Variable** `NEXUSMODS_FILE_GROUP_ID` — the file group ID (Settings → Variables → Actions)

> **Note:** The Nexus Mods v3 API is currently in evaluation. The upload step is opt-in and will be skipped on normal tag pushes.

---

## Git Hooks (Lefthook)
### Git Hooks (Lefthook)

Prerequisites:

- `go install github.com/evilmartians/lefthook@latest`
- `clang-format` (part of LLVM — already required for development)
- `clang-tidy` (part of LLVM — already required for development)
- `clang-format` and `clang-tidy` (part of LLVM)
- `cmake-format` (`sudo pacman -S cmake-format` on Arch/CachyOS; `pip install cmakelang` elsewhere)
- `shellcheck` (`sudo pacman -S shellcheck` on Arch/CachyOS)

Run `lefthook install` to register the hooks.
```bash
lefthook install
```

---

## Neovim / clangd Setup
### Editor Setup (clangd / Neovim)

CMake writes `compile_commands.json` to the build directory automatically.
Copy or symlink it to the project root so clangd picks it up:
CMake writes `compile_commands.json` to the build directory. Symlink it to the project root:

```bash
# After configuring:
ln -sf build/release-linux/compile_commands.json compile_commands.json
```

The `.clangd` file already sets `--target=x86_64-pc-windows-msvc` so clangd
resolves Windows headers correctly on Linux.
The `.clangd` file sets `--target=x86_64-pc-windows-msvc` so clangd resolves Windows headers correctly on Linux.

Recommended Neovim plugins: [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)
with `clangd`, and [clangd_extensions.nvim](https://github.com/p00f/clangd_extensions.nvim).
Recommended plugins: [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) with `clangd`, [clangd_extensions.nvim](https://github.com/p00f/clangd_extensions.nvim).

---

## Updating CommonLibSSE-NG
### Updating CommonLibSSE-NG

```bash
git submodule update --remote lib/commonlibsse-ng
Expand All @@ -193,6 +168,34 @@ git commit -m "chore: update CommonLibSSE-NG submodule"

---

### CI

| Workflow | Trigger | What it does |
|---|---|---|
| `ci.yml` | PRs to `main` touching source/cmake/vcpkg | clang-format (ubuntu) → clang-tidy + build (windows, parallel) |
| `release.yml` | Push of a `v*` tag or manual `workflow_dispatch` | Builds release DLL, publishes GitHub Release; opt-in Nexus Mods upload via dispatch input |
| `lint.yml` | PRs touching `scripts/` | shellcheck on shell scripts |
| `pr-title.yml` | PR opened/edited/synchronised | Validates PR title follows Conventional Commits |

#### Nexus Mods Upload

Triggered via **workflow_dispatch** with `upload_to_nexus: true`. One-time setup:
Comment thread
codepuncher marked this conversation as resolved.
Outdated

1. Upload your first file manually via the [Nexus Mods web UI](https://www.nexusmods.com) to create the file group.
2. Add to your repository:
- **Secret** `NEXUSMODS_API_KEY` — your Nexus Mods API key
- **Variable** `NEXUSMODS_FILE_GROUP_ID` — the file group ID

---

## Credits & Inspirations

- Inspired by the hold-Start-to-open-map mechanic in **Red Dead Redemption 2**
- [CommonLibSSE-NG](https://github.com/alandtse/CommonLibVR) by alandtse and contributors
- [NADS-SSE](https://github.com/EliasRipley/NADS-SSE) by EliasRipley — `PrependEventSink` + chrono timing pattern

---

## License

MIT — see [LICENSE](LICENSE).