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
13 changes: 6 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ jobs:
runs-on: ubuntu-latest

permissions:
contents: read
pull-requests: read

outputs:
Expand All @@ -27,9 +28,10 @@ jobs:
ci: ${{ steps.filter.outputs.ci }}

steps:
- uses: actions/checkout@v6

- uses: dorny/paths-filter@v4
id: filter
if: github.event_name == 'pull_request'
with:
filters: |
src:
Expand Down Expand Up @@ -77,7 +79,7 @@ jobs:

test:
needs: [changes, clang-format]
runs-on: windows-latest
runs-on: windows-2022

if: >-
always() &&
Expand All @@ -92,7 +94,6 @@ jobs:

permissions:
contents: read
actions: write

steps:
- name: Checkout
Expand Down Expand Up @@ -130,7 +131,7 @@ jobs:

build:
needs: [changes, clang-format]
runs-on: windows-latest
runs-on: windows-2022

if: >-
always() &&
Expand All @@ -144,7 +145,6 @@ jobs:

permissions:
contents: read
actions: write

steps:
- name: Checkout
Expand Down Expand Up @@ -187,7 +187,7 @@ jobs:

clang-tidy:
needs: [changes, clang-format, build, test]
runs-on: windows-latest
runs-on: windows-2022

if: >-
always() &&
Expand All @@ -204,7 +204,6 @@ jobs:

permissions:
contents: read
actions: write

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ on:
pull_request:
paths:
- 'scripts/**'
- 'README.md'
- 'docs/**/*.md'
- '.vale.ini'
- '.vale/styles/**'
- 'dprint.json'
- 'lefthook.yml'
- '.github/workflows/lint.yml'
workflow_dispatch:

permissions: {}

Expand All @@ -23,3 +31,28 @@ jobs:
uses: azohra/shell-linter@v0.8.0
with:
path: "scripts/*.sh"

markdown:
runs-on: ubuntu-latest

permissions:
contents: read
checks: write
pull-requests: write

steps:
- uses: actions/checkout@v6

- name: Check markdown formatting
uses: dprint/check@v2.3
with:
args: README.md docs/**/*.md

- name: Annotate markdown prose
uses: vale-cli/vale-action@v2
with:
files: "."
vale_flags: "--glob=README.md --glob=docs/**/*.md"
reporter: github-pr-check
filter_mode: nofilter
fail_on_error: true
5 changes: 4 additions & 1 deletion .github/workflows/nexus-upload.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ jobs:
printf '%s\n' "$DELIM" >> "$GITHUB_OUTPUT"

- name: Upload to Nexus Mods
uses: Nexus-Mods/upload-action@v1.0.0-beta.5
uses: Nexus-Mods/upload-action@v1.0.0-beta.7
with:
api_key: ${{ secrets.NEXUSMODS_API_KEY }}
file_group_id: ${{ vars.NEXUSMODS_FILE_GROUP_ID }}
Expand All @@ -114,3 +114,6 @@ jobs:
description: ${{ steps.notes.outputs.notes }}
version: ${{ steps.version.outputs.value }}
archive_existing_file: true
primary_mod_manager_download: true
allow_mod_manager_download: true
show_requirements_pop_up: true
3 changes: 1 addition & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ permissions: {}

jobs:
release:
runs-on: windows-latest
runs-on: windows-2022

permissions:
contents: write
actions: write

steps:
- name: Checkout
Expand Down
8 changes: 8 additions & 0 deletions .vale.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
StylesPath = .vale/styles
MinAlertLevel = warning
Vocab = Project
IgnoredScopes = code, tt

[*.md]
BasedOnStyles = Project
TokenIgnores = (\bhttps?://\S+\b), (\[/?url(?:=[^\]]+)?\]), (\b[A-Za-z0-9_.-]+\.(?:dll|ini|exe|zip|7z|md|yml|yaml|json)\b), (\b[A-Za-z0-9_.-]+/[A-Za-z0-9_./-]+\b)
7 changes: 7 additions & 0 deletions .vale/styles/Project/Acronyms.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
extends: substitution
message: "Use '%s' instead of '%s'."
level: warning
ignorecase: false
swap:
pr: PR
ci: CI
10 changes: 10 additions & 0 deletions .vale/styles/Project/AvoidVague.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extends: existence
message: "Avoid vague wording like '%s'."
level: warning
ignorecase: true
tokens:
- just
- simply
- obviously
- easy
- easily
7 changes: 7 additions & 0 deletions .vale/styles/Project/Capitalization.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
extends: substitution
message: "Use '%s' instead of '%s'."
level: warning
ignorecase: false
swap:
github actions: GitHub Actions
skyrim special edition: Skyrim Special Edition
7 changes: 7 additions & 0 deletions .vale/styles/Project/LinkText.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
extends: existence
message: "Use descriptive link text instead of '%s'."
level: warning
ignorecase: true
tokens:
- click here
- this link
15 changes: 15 additions & 0 deletions .vale/styles/config/vocabularies/Project/accept.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ExampleMod
SKSE
SKSE64
CommonLibSSE-NG
Lefthook
NexusMods
GitHub
vcpkg
CMake
clangd
clang-format
clang-tidy
dprint
Vale
xwin
1 change: 1 addition & 0 deletions .vale/styles/config/vocabularies/Project/reject.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
skse
27 changes: 24 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,30 @@ else()
set(_default_deploy "${CMAKE_BINARY_DIR}/deploy/${PROJECT_NAME}")
endif()

set(DEPLOY_DIR
"${_default_deploy}"
CACHE PATH "Deploy destination (set SKYRIM_MODS_FOLDER or SKYRIM_FOLDER in .env)")
set(DEPLOY_DIR_OVERRIDE
""
CACHE
PATH
"Override deploy destination (leave empty to derive from SKYRIM_MODS_FOLDER or SKYRIM_FOLDER in the environment, optionally sourced from .env)"
)

# DEPLOY_DIR was previously written to the cache by the project and is no longer supported.
# Clear it so stale cached values don't shadow the env-derived path. Users who want a
# fixed deploy path should use -DDEPLOY_DIR_OVERRIDE=... instead.
if(DEFINED CACHE{DEPLOY_DIR})
message(WARNING "DEPLOY_DIR is no longer a cache variable and has been removed. "
"To pin a fixed deploy path, set -DDEPLOY_DIR_OVERRIDE=... instead.")
unset(DEPLOY_DIR CACHE)
endif()

# Always recompute so environment changes take effect on every configure.
# DEPLOY_DIR_OVERRIDE (if set) wins over the env-derived default.
unset(DEPLOY_DIR CACHE)
if(NOT DEPLOY_DIR_OVERRIDE STREQUAL "")
set(DEPLOY_DIR "${DEPLOY_DIR_OVERRIDE}")
else()
set(DEPLOY_DIR "${_default_deploy}")
endif()

install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION "${DEPLOY_DIR}/SKSE/Plugins")

Expand Down
30 changes: 21 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Supports building on **Linux** (cross-compilation via `clang-cl` + [xwin](https:
---

<!-- nexus:start -->

## Requirements

- [SKSE64](https://skse.silverlock.org/)
Expand All @@ -16,11 +17,13 @@ Supports building on **Linux** (cross-compilation via `clang-cl` + [xwin](https:
## Installation

**Mod manager (recommended):**

1. Install the requirements above.
2. Install ExampleMod via your mod manager.
3. Launch Skyrim via SKSE.

**Manual:**

1. Install the requirements above.
2. Copy `ExampleMod.dll` to `Data\SKSE\Plugins\`.
3. Launch Skyrim via SKSE.
Expand All @@ -29,6 +32,7 @@ Supports building on **Linux** (cross-compilation via `clang-cl` + [xwin](https:

- Compatible with Skyrim SE and AE.
- No ESP/ESL required.

<!-- nexus:end -->

---
Expand All @@ -48,11 +52,13 @@ When loaded by Skyrim the plugin:
### 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

#### 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
- [Ninja](https://ninja-build.org/)
Expand All @@ -70,13 +76,16 @@ xwin splat --output ~/.xwin

> **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.

#### Windows

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

---
Expand Down Expand Up @@ -111,6 +120,7 @@ cd your-mod
```

This will:

- Replace mod name and author placeholders across all files
- Initialise git submodules (CommonLibSSE-NG + vcpkg)
- Bootstrap vcpkg
Expand Down Expand Up @@ -148,13 +158,15 @@ source .env && cmake --workflow --preset deploy
```

This configures, builds, and copies `ExampleMod.dll` + `ExampleMod.pdb` directly into:

```
$SKYRIM_MODS_FOLDER/ExampleMod/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
```
Expand Down Expand Up @@ -251,20 +263,21 @@ python3 scripts/generate-nexus-page.py | pbcopy # macOS

### 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 |
| `ci.yml` | PRs to `main` touching `src/`, `test/`, `cmake/`, `vcpkg.json`, `CMakeLists.txt`, `CMakePresets.json` | `clang-format` (ubuntu) → `test` + `build` (windows, parallel) → `clang-tidy` (windows) |
| `release.yml` | Push of a `v*` tag | Builds, packages via `scripts/package.sh`, publishes a GitHub Release with zip + PDB |
| `nexus-upload.yml` | Release published or manual `workflow_dispatch` | Downloads release zip, generates cliff release notes, uploads to Nexus Mods |
| `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`, `refactor`) |
| 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 |
| `ci.yml` | PRs to `main` touching `src/`, `test/`, `cmake/`, `vcpkg.json`, `CMakeLists.txt`, `CMakePresets.json` | `clang-format` (ubuntu) → `test` + `build` (windows, parallel) → `clang-tidy` (windows) |
| `release.yml` | Push of a `v*` tag | Builds, packages via `scripts/package.sh`, publishes a GitHub Release with zip + PDB |
| `nexus-upload.yml` | Release published or manual `workflow_dispatch` | Downloads release zip, generates cliff release notes, uploads to Nexus Mods |
| `lint.yml` | PRs touching `scripts/`, `README.md`, or `docs/` | Runs shellcheck on shell scripts, plus dprint formatting and Vale prose checks on Markdown |
| `pr-title.yml` | PR opened/edited/reopened/synchronize | Checks PR title follows Conventional Commits (`feat`, `fix`, `chore`, `refactor`) |

#### Nexus Mods Upload

`nexus-upload.yml` triggers automatically when a GitHub Release is published, or can be run manually via **workflow_dispatch** with a version input.

**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:
Expand All @@ -276,4 +289,3 @@ python3 scripts/generate-nexus-page.py | pbcopy # macOS
## License

MIT — see [LICENSE](LICENSE).

18 changes: 18 additions & 0 deletions dprint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://dprint.dev/schemas/v0.json",
"includes": [
"README.md",
"docs/**/*.md"
],
"excludes": [
"lib/**",
"build/**",
"vcpkg_installed/**"
],
"plugins": [
"https://plugins.dprint.dev/markdown-0.22.1.wasm"
],
"markdown": {
"textWrap": "maintain"
}
}
Loading
Loading