47 Commits

Author SHA1 Message Date
MrFastwind
4ff3e5107f fix: prevent group_diag from prematurely marking patrol groups for deletion
Tags patrol groups (KPLIB_patrol_group) so group_diag skips them, and
cleans up the tag + enables deleteGroupWhenEmpty only once the patrol
lifecycle is complete. Prevents the '_grp was nil' log spam by fixing
the root cause rather than just silencin the symptom.
2026-07-03 16:37:05 +02:00
f12355f581 Merge pull request 'spam in logs of "Error Undefined variable in expression: _grp"' (#1) from fix/patrol-spawn into master
All checks were successful
Build Mission PBO / pack (push) Successful in 1m0s
Build Mission PBO / deploy (push) Successful in 6s
Reviewed-on: #1
2026-07-02 14:43:25 +00:00
MrFastwind
91e3099f0e fix(kp-framework): Fixes spam in logs of "Error Undefined variable in
expression: _grp" in \scripts\server\patrols\manage_one_patrol.sqf...,
line 62
2026-07-02 04:08:00 +02:00
5f1d7688c9 Difficulty crank
All checks were successful
Build Mission PBO / pack (push) Successful in 13s
Build Mission PBO / deploy (push) Successful in 6s
2026-06-30 18:10:35 +03:00
5a3643c71a Raising OPFOR unitcap, neutering civs, removing guerillas
All checks were successful
Build Mission PBO / pack (push) Successful in 14s
Build Mission PBO / deploy (push) Successful in 10s
2026-06-28 21:00:07 +03:00
a1e9cef54d Decrease civ amount (+tabs)
All checks were successful
Build Mission PBO / pack (push) Successful in 14s
Build Mission PBO / deploy (push) Successful in 6s
2026-06-28 12:41:21 +03:00
6251e1dea7 Merge branch 'master' of https://git.r3d.codes/REDCODE/CTI34-KPLIB-Ruha
All checks were successful
Build Mission PBO / pack (push) Successful in 13s
Build Mission PBO / deploy (push) Successful in 6s
2026-06-28 03:05:13 +03:00
b4dadd0af6 blufor sqf comment spaces 2026-06-28 03:05:09 +03:00
fd6558b65a Fixed formatting and commas
All checks were successful
Build Mission PBO / pack (push) Successful in 1m3s
Build Mission PBO / deploy (push) Successful in 7s
2026-06-27 19:45:13 +00:00
890a7cca94 Removed extra comma
All checks were successful
Build Mission PBO / pack (push) Successful in 14s
Build Mission PBO / deploy (push) Successful in 7s
2026-06-27 19:40:51 +00:00
f3bfbc80ef Disabled civilians
All checks were successful
Build Mission PBO / pack (push) Successful in 10s
Build Mission PBO / deploy (push) Successful in 7s
2026-06-27 17:50:01 +00:00
6e0f18f6ad Disabled penalty for destroying civilian buildings
All checks were successful
Build Mission PBO / pack (push) Successful in 15s
Build Mission PBO / deploy (push) Successful in 8s
2026-06-27 17:30:45 +00:00
e4ead21bea MT-LB comment out due to CSAT crew
All checks were successful
Build Mission PBO / pack (push) Successful in 26s
Build Mission PBO / deploy (push) Successful in 7s
2026-06-27 18:24:46 +03:00
e8f2b34bec sets preset for opfor to rhs_afrf (which has been modded by us)
All checks were successful
Build Mission PBO / pack (push) Successful in 14s
Build Mission PBO / deploy (push) Successful in 6s
2026-06-15 15:58:29 +02:00
6dd2f1d59c Updated civs and OPFOR
All checks were successful
Build Mission PBO / pack (push) Successful in 13s
Build Mission PBO / deploy (push) Successful in 15s
2026-06-15 14:47:46 +02:00
MrFastwind
f68c6efc3c Update build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 23s
Build Mission PBO / deploy (push) Successful in 7s
2026-06-14 02:55:47 +02:00
MrFastwind
b98956e04b Update build.yml
Some checks failed
Build Mission PBO / pack (push) Successful in 30s
Build Mission PBO / deploy (push) Failing after 16s
2026-06-14 02:42:27 +02:00
MrFastwind
1a3bb4a561 Update build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 22s
Build Mission PBO / deploy (push) Has been skipped
2026-06-14 02:26:26 +02:00
MrFastwind
9b2cf602ed Update build.yml
Some checks failed
Build Mission PBO / pack (push) Failing after 19s
Build Mission PBO / deploy (push) Has been skipped
2026-06-14 02:23:43 +02:00
MrFastwind
970fe97875 Clean up of comments
All checks were successful
Build Mission PBO / pack (push) Successful in 9s
Build Mission PBO / deploy (push) Has been skipped
2026-06-14 01:56:47 +02:00
MrFastwind
7c2e53b78f Update build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 11s
Build Mission PBO / deploy (push) Has been skipped
2026-06-14 01:54:40 +02:00
MrFastwind
5a7879bca8 move mission into src
Some checks failed
Build Mission PBO / pack (push) Failing after 20s
Build Mission PBO / deploy (push) Has been skipped
2026-06-14 01:53:24 +02:00
b5bd14928e Update .gitea/workflows/build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 10s
Build Mission PBO / deploy (push) Has been skipped
2026-06-13 23:27:48 +00:00
8c41bcd936 Update .gitea/workflows/build.yml
Some checks failed
Build Mission PBO / pack (push) Failing after 5s
Build Mission PBO / deploy (push) Has been skipped
2026-06-13 23:26:51 +00:00
07c87a0b55 Update .gitea/workflows/build.yml
Some checks failed
Build Mission PBO / pack (push) Failing after 12s
Build Mission PBO / deploy (push) Has been skipped
2026-06-13 23:25:57 +00:00
789114a7ce Update .gitea/workflows/build.yml 2026-06-13 23:23:05 +00:00
84bb67d10c Update .gitea/workflows/build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 6s
Build Mission PBO / deploy (push) Has been skipped
2026-06-13 23:18:44 +00:00
7e3b4c89c7 Update .gitea/workflows/build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 6s
Build Mission PBO / deploy (push) Has been skipped
2026-06-13 23:17:49 +00:00
be59719980 Update .gitea/workflows/build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 5s
Build Mission PBO / deploy (push) Has been skipped
2026-06-13 23:17:04 +00:00
600145e0d7 Update .gitea/workflows/build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 9s
Build Mission PBO / deploy (push) Has been skipped
2026-06-13 23:16:00 +00:00
MrFastwind
e543c4266a Update build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 9s
Build Mission PBO / deploy (push) Has been skipped
2026-06-14 01:10:22 +02:00
9f17ba8b3b Update .gitea/workflows/build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 10s
Build Mission PBO / deploy (push) Has been skipped
2026-06-13 23:04:14 +00:00
MrFastwind
74c328b8d4 Update build.yml
All checks were successful
Build Mission PBO / pack (push) Successful in 21s
Build Mission PBO / deploy (push) Has been skipped
2026-06-14 01:00:04 +02:00
ddb208ab24 Update .gitea/workflows/build.yml
Some checks failed
Build Mission PBO / pack (push) Failing after 8s
Build Mission PBO / deploy (push) Has been skipped
2026-06-13 21:57:30 +00:00
c9e0546f7c Update .gitea/workflows/build.yml
Some checks failed
Build Mission PBO / pack (push) Failing after 7s
Build Mission PBO / deploy (push) Has been skipped
2026-06-13 21:46:17 +00:00
d698c3b03b updated CI
Some checks failed
Build Mission PBO / pack (push) Failing after 10s
Build Mission PBO / deploy (push) Has been skipped
2026-06-11 16:03:22 +02:00
4df954bb1b Attempt fix n5
Some checks failed
Build Mission PBO / pack (push) Failing after 8s
Build Mission PBO / deploy (push) Has been skipped
2026-06-11 02:01:42 +02:00
61f1dcaa83 Revert "fix: pipe PBO via stdout to bypass DinD volume mount issue"
Some checks failed
Build Mission PBO / pack (push) Failing after 8s
Build Mission PBO / deploy (push) Has been skipped
This reverts commit e345451c7e.
2026-06-11 02:00:04 +02:00
e345451c7e fix: pipe PBO via stdout to bypass DinD volume mount issue
Some checks failed
Build Mission PBO / pack (push) Failing after 10s
Build Mission PBO / deploy (push) Has been skipped
2026-06-11 01:58:50 +02:00
eba2c13015 fix: run docker as runner user to fix artifact upload
Some checks failed
Build Mission PBO / pack (push) Failing after 16s
Build Mission PBO / deploy (push) Has been skipped
2026-06-11 01:53:40 +02:00
d3db656725 attempt fix 3
Some checks failed
Build Mission PBO / pack (push) Failing after 12s
Build Mission PBO / deploy (push) Has been skipped
2026-06-11 01:51:29 +02:00
47d7c43a57 attempt fix 2
Some checks failed
Build Mission PBO / pack (push) Failing after 7s
Build Mission PBO / deploy (push) Has been skipped
2026-06-11 01:45:00 +02:00
4cc3f9c889 attempt fix for CI upload
All checks were successful
Build Mission PBO / pack (push) Successful in 15s
Build Mission PBO / deploy (push) Has been skipped
2026-06-11 01:41:34 +02:00
8b153bb106 Revert "CI: replace Docker-based armake2 with direct cargo install"
This reverts commit 110e7e9653.
2026-06-11 01:40:25 +02:00
110e7e9653 CI: replace Docker-based armake2 with direct cargo install
Some checks failed
Build Mission PBO / pack (push) Failing after 5s
Build Mission PBO / deploy (push) Has been skipped
2026-06-11 01:39:47 +02:00
6ad0a00056 Fix CI pack source path: use /workspace instead of mission folder name
All checks were successful
Build Mission PBO / pack (push) Successful in 8s
Build Mission PBO / deploy (push) Has been skipped
The git repo root IS the mission folder. actions/checkout puts files
directly in the workspace, so there's no subdirectory matching the
mission folder name. Use /workspace (the container mount point) as
the pack source.
2026-06-11 01:36:16 +02:00
c502ec56bb Generate comprehensive AGENTS.md with SQF language spec, Arma 3 editing conventions, and project analysis 2026-06-11 01:26:37 +02:00
482 changed files with 1042 additions and 338 deletions

View File

@@ -3,11 +3,11 @@ name: Build Mission PBO
on:
push:
branches: [main, master]
tags: ['v*']
tags: ["v*"]
workflow_dispatch:
env:
PBO_NAME: CTI_34_KP_Liberation_v0.96.7a_Ruha.ruha.pbo
PBO_NAME: "KPLib-Ruha.ruha.pbo"
jobs:
pack:
@@ -16,37 +16,31 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: mkdir build
- name: Pack mission folder into PBO
run: |
docker run --rm \
-v "${{ github.workspace }}:/workspace" \
-w /workspace \
arwynfr/armake2:debian \
pack \
"CTI 34 KP Liberation v0.96.7a Ruha.ruha" \
"${{ env.PBO_NAME }}"
uses: docker://arwynfr/armake2:debian
with:
args: pack src "build/${{ env.PBO_NAME }}"
- name: Verify PBO integrity
run: |
docker run --rm \
-v "${{ github.workspace }}:/workspace" \
-w /workspace \
arwynfr/armake2:debian \
inspect "${{ env.PBO_NAME }}"
uses: docker://arwynfr/armake2:debian
with:
args: inspect "build/${{ env.PBO_NAME }}"
- name: Upload PBO as artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: ${{ env.PBO_NAME }}
path: ${{ env.PBO_NAME }}
path: build/${{ env.PBO_NAME }}
if-no-files-found: error
deploy:
if: false
needs: [pack]
runs-on: ubuntu-latest
steps:
- name: Download PBO artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v3
with:
name: ${{ env.PBO_NAME }}
@@ -55,6 +49,7 @@ jobs:
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
password: ${{ secrets.SERVER_PASSWORD }}
# key: ${{ secrets.SSH_PRIVATE_KEY }}
source: ${{ env.PBO_NAME }}
target: /path/to/server/mpmissions/
target: /home/arma3server/serverfiles/mpmissions/

20
.gitignore vendored
View File

@@ -1,12 +1,12 @@
*.pbo
*.bisign
*.bikey
*.zip
*.log
*.rpt
*.psd
*.bak
*.tmp
*.swp
src/*.pbo
src/*.bisign
src/*.bikey
src/*.zip
src/*.log
src/*.rpt
src/*.psd
src/*.bak
src/*.tmp
src/*.swp
.vs/
__history/

625
AGENTS.md Normal file
View File

@@ -0,0 +1,625 @@
# AGENTS.md — Arma 3 KP Liberation Mission Project Specification
## 1. Project Overview
**Mission:** CTI 34 KP Liberation v0.96.7a Ruha.ruha
**Type:** Arma 3 CTI (Capture the Island) multiplayer mission
**Max Players:** 34
**Map:** Ruha
**Framework:** KP Liberation v0.96.7a (fork of GreuhZbug → KillahPotatoes)
**Repository:** https://github.com/KillahPotatoes/KP-Liberation
This is a Ukraine-themed fork with custom BLUFOR preset using UA_Azov, b_afougf, FA_UAF, UF_ mod classnames.
### File Inventory
| File Type | Count | Lines of Code |
|------------|-------|---------------|
| `.sqf` | ~393 | ~47,570 |
| `.hpp` | ~33 | ~6,827 |
| `.xml` | 1 | 7,321 |
| `.sqm` | 1 | 189 |
| `.fsm` | 3 | — |
| Other | ~46 | — |
| **Total** | ~477 | ~62,000+ |
### Top-level Directory Layout
```
/
├── mission.sqm — Binary editor file (Arma Eden)
├── description.ext — Mission config (configFile syntax)
├── CfgFunctions.hpp — Function registry
├── init.sqf — Entry point
├── kp_liberation_config.sqf — Main gameplay configuration
├── kp_objectInits.sqf — Object-specific triggers
├── onPlayerRespawn.sqf — Respawn handler
├── whitelist.sqf — Commander whitelist
├── stringtable.xml — Locale strings
├── pbo.json — PBO compression config
├── AGENTS.md — This file
├── scripts/ — Shared/client/server scripts
│ ├── shared/ — Runs on all machines
│ ├── client/ — Client-only (40+ files, 14 subdirs)
│ ├── server/ — Server-only (70+ files, 17 subdirs)
│ └── fob_templates/ — FOB building layouts
├── functions/ — Compiled KPLIB functions (84 files)
│ ├── curator/ — Zeus curator handlers
│ └── ui/ — Overlay UI
├── presets/ — Faction unit pricing
│ ├── init_presets.sqf — Preset loader
│ ├── blufor/ — 16 faction presets
│ ├── opfor/ — 16 faction presets
│ ├── resistance/ — 9 faction presets
│ └── civilians/ — 9 faction presets
├── arsenal_presets/ — Arsenal unlock definitions (16 files)
├── ui/ — HUD/dialog definitions (21 files)
├── KP/ — KP modules
│ ├── KPGUI/ — GUI framework (defines, classes)
│ └── KPPLM/ — Player menu (functions, UI)
├── GREUH/ — Legacy GREUH module
│ ├── Scripts/ — 10 legacy scripts
│ └── UI/ — Interface HPP
└── res/ — Assets (PAA, OGG, JPG)
```
---
## 2. SQF Language Specification
SQF (Status Quo Function) is Arma 3's primary scripting language — a C-like, preprocessed, operator-based language with no formal keyword grammar for control flow (control structures are operators that accept code blocks as arguments).
### 2.1 Grammar & Syntax Rules
**Statements** — every expression MUST end with `;` (semicolon):
```sqf
private _x = 5;
hint str _x;
```
**Expressions** — there are only three expression types:
- **Nular** — zero arguments, like a computed variable: `player`, `time`, `side player`
- **Unary** — one argument on the right: `!alive`, `hint "hello"`, `west`
- **Binary** — two arguments: `a + b`, `str _x`, `a isEqualTo b`
**Operator precedence** follows a strict table (highest 11 → lowest 1):
| Precedence | Operators |
|------------|-----------|
| 11 | `*`, `/`, `%`, `mod`, `atan2` |
| 10 | `+`, `-`, `: (config)` |
| 9 | `select` |
| 8 | `^` |
| 7 | `==`, `!=`, `<`, `>`, `<=`, `>=`, `isEqualTo`, `isNotEqualTo` |
| 6 | `!`, `not` |
| 5 | `&&`, `and` |
| 4 | `||`, `or` |
| 3 | `> (binary)`, `>= (binary)`, `< (binary)`, `<= (binary)` |
| 2 | `then`, `do`, `count`, `apply`, `findIf` |
| 1 | `else`, `exitWith` |
**Brackets:**
- `()` — override precedence or group expressions
- `[]` — define arrays
- `{}` — code blocks (Code data type)
**Comments:**
- `//` single-line (preprocessor removes them)
- `/* */` multi-line block
- `comment "text"` runtime comment command (SQF level, not preprocessor)
### 2.2 Data Types
| Type | Examples | Notes |
|------|----------|-------|
| **Scalar** (Number) | `42`, `-3.14`, `1e6` | Double precision |
| **Boolean** | `true`, `false` | |
| **String** | `"hello"` | Double quotes only in SQF |
| **Array** | `[1, "a", player]` | 0-indexed, heterogeneous |
| **Code** | `{ hint "hi" }` | Block, assigned or passed |
| **Object** | `player`, `cursorTarget` | In-game entity reference |
| **Side** | `west`, `east`, `independent`, `civilian` | |
| **Group** | `group player` | Unit group |
| **Config** | `configFile >> "CfgVehicles"` | Config tree reference |
| **Display** | `findDisplay 46` | UI display |
| **Control** | `_display displayCtrl 1000` | UI control |
| **Namespace** | `missionNamespace`, `uiNamespace` | Variable containers |
| **Script** | `_handle = _x spawn _code` | Script handle |
| **NaN** | `objNull`, `nil` | Special null values |
| **HashMap** | `createHashMap` | Arma 3 v2.01+ |
### 2.3 Variables
**Scope rules:**
- **Global:** no prefix — `KP_liberation_version`
- **Private (local):** `_` prefix — `_myVar`
- **Mission namespace:** `missionNamespace setVariable ["varname", value]`
**Declaration via `private` keyword (MANDATORY to avoid upper-scope pollution):**
```sqf
private _myVar = 42;
private ["_a", "_b", "_c"]; // array form (legacy)
params ["_param1", "_param2"]; // auto-private via params
```
**Naming conventions observed in this project:**
| Pattern | Example | Scope |
|---------|---------|-------|
| `KP_liberation_*` | `KP_liberation_ace` | Global config |
| `GRLIB_*` | `GRLIB_sector_size` | Legacy global |
| `KPLIB_*` | `KPLIB_init` | Mission global |
| `_under_score` | `_sector`, `_nearestFob` | Local variable |
| `_i`, `_x`, `_forEachIndex` | `_i` | Loop iteration |
| `MACRO_NAME` | `COLOR_GREEN` | `#define` constant (UPPER_SNAKE_CASE mandatory) |
### 2.4 Control Structures (Operator-based, no reserved keywords)
```sqf
// if-then-else
if (_a > _b) then { hint "bigger" } else { hint "smaller" };
// while-do
while { _i < 10 } do { _i = _i + 1 };
// for-do (range)
for "_i" from 0 to 9 do { systemChat str _i };
// for-do (array iteration — forEach)
{ hint _x } forEach [1,2,3];
// switch-do
switch (_var) do {
case 1: { hint "one" };
case 2: { hint "two" };
default { hint "other" };
};
// exitWith (early return)
if (_condition) exitWith { _defaultValue };
// waitUntil
waitUntil { !isNil "KPLIB_init" };
```
### 2.5 Arrays
- 0-indexed, dynamic, heterogeneous
- Access: `_arr select 0` or `_arr #0`
- Slicing: `_arr select [0, 3]`
- Range syntax: `_arr # [0, 3]` (Arma 3 v2.14+)
- Common operators: `pushBack`, `append`, `apply`, `select`, `resize`, `deleteAt`, `arrayIntersect`, `in`, `findIf`, `count`
**Preset arrays (this project):**
```sqf
// Multi-dimensional with resource costs
infantry_units = [
["classname", supplies, ammunition, fuel],
["B_soldier_F", 20, 0, 0]
];
// Last element MUST NOT have a trailing comma
```
### 2.6 Functions
**Compiled via CfgFunctions.hpp (preferred):**
```hpp
class KPLIB {
class functions {
file = "functions";
class log {};
class checkClass {};
class spawnVehicle {};
};
};
```
Usage: `[_text, "TAG"] call KPLIB_fnc_log;`
**Compiled inline (this project's secondary pattern):**
```sqf
kill_manager = compileFinal preprocessFileLineNumbers "scripts\shared\kill_manager.sqf";
```
Usage: `[] call kill_manager;`
**Function parameter conventions:**
```sqf
params [
["_text", "", [""] ], // Default: "", Type filter: String
["_tag", "INFO", [""] ], // Default: "INFO", Type filter: String
["_debug", false, [true] ] // Default: false, Type filter: Boolean
];
```
### 2.7 Preprocessor (`#` directives, C-like)
Case-sensitive in Arma 3.
**`#define` — constant macro:**
```sqf
#define COLOR_GREEN { 0.2, 0.23, 0.18, 0.75 }
#define FACTION_BLUFOR(k) (k == 0)
```
**Macro arguments** — whole-word replacement by default. Use `##` for word-part concatenation:
```sqf
#define GET_PARAM(outVar, paramName, paramDefault) \
outVar = [paramName,paramDefault] call KPLIB_fnc_getSaveableParam; \
publicVariable #outVar;
```
**`#include` — file inclusion:**
```sqf
#include "defines.hpp"
#include <file.txt> // brackets = quotes (equivalent)
```
**`__LINE__`, `__FILE__`** — debug directives (added by `preprocessFileLineNumbers`)
**`#ifdef` / `#ifndef` / `#endif`** — conditional compilation
**Critical pitfalls:**
- No `__EXEC` or `__EVAL` in SQF scripts (only in configs)
- Macro body swallows spaces around non-space characters; tabs are NOT spaces
- Backslash `\` for multi-line macros MUST be the last character on the line
- Macros do NOT propagate across files (each file preprocessed independently)
- `loadFile` does NOT preprocess; `preprocessFile` and `preprocessFileLineNumbers` DO
### 2.8 File I/O & Script Execution
| Method | Preprocesses? | Returns | Use Case |
|--------|:---:|:---:|----------|
| `preprocessFileLineNumbers` | Yes | String (with `#line` info) | Compiling functions |
| `preprocessFile` | Yes | String (no line info) | Loading config text |
| `loadFile` | No | String (raw) | Raw file content |
| `execVM` | Yes | Script handle | Fire-and-forget scripts |
| `compileFinal` | No* | Code | Lock compiled code |
| `call` | — | Any | Synchronous execution |
| `spawn` | — | Script handle | Async execution |
*`compileFinal` does NOT preprocess; pass it preprocessed string:
```sqf
_code = compileFinal preprocessFileLineNumbers "file.sqf";
```
### 2.9 Networking / Remote Execution
```sqf
// Execute on all clients
[_arg1, _arg2] remoteExec ["functionName", 0];
// Execute on server only
remoteExecCall ["fnc_name", 2];
// Execute on specific client (owner ID)
remoteExecCall ["fnc_name", _ownerID];
// JIP (Join In Progress) persistent
remoteExecCall ["fnc_name", 0, _jipObject];
```
**This project's pattern:** Server-to-client via `remote_call_*.sqf` compiled scripts, Client-to-server via `remoteExecCall` targeting server (ID 2).
---
## 3. Arma 3 Mission Editing Conventions
### 3.1 Mission File Types
| File | Purpose | Format |
|------|---------|--------|
| `mission.sqm` | Editor-placed entities, markers, triggers, waypoints | Binary/text hybrid |
| `description.ext` | Mission config (CfgDebriefing, CfgRespawnInventory, etc.) | Config class syntax |
| `CfgFunctions.hpp` | Function registry (included by description.ext) | SQF preprocessed |
| `init.sqf` | Entry point, runs on all machines | SQF |
| `stringtable.xml` | Multi-language localization | XML |
| `*.hpp` | Header/includes (macros, UI classes, function registries) | SQF preprocessed |
| `*.sqf` | Script files | SQF |
| `*.fsm` | Finite State Machine definitions | FSM format |
### 3.2 PBO Format
**Two types:**
- **Mission PBO:** Contains `mission.sqm`, no `config.cpp`, no PBO prefix header. Lives in `mpmissions/`.
- **Addon PBO:** Contains `config.cpp`/`config.bin`, has PBO property header (`prefix=...`). Lives in `addons/`.
**PBO structure (binary):**
```
[Header entries (21-byte records)] [Data blocks] [Optional SHA-1 signature]
```
Each header entry: null-terminated filename (ASCIIZ) + 4-byte MIME type + 4x ulong fields.
**Building on Linux:** Use `armake2 pack` for missions (no binarization), `armake2 build` for addons.
### 3.3 description.ext (Config syntax)
Uses config-class syntax (similar to C++ classes but preprocessed):
```sqf
class CfgDebriefing {
class Victory {
title = "Mission Complete";
subtitle = "All sectors captured";
description = "The island has been liberated.";
picture = "bg_victory";
};
};
```
Key attributes set in this project's `description.ext`:
- `briefingName`, `overviewText`, `author` — Mission metadata
- `respawn`, `respawnDelay`, `respawnOnStart` — Respawn settings
- `class CfgDebriefing {}` — End-mission screens
- `class Header { gameType = CTI; ... }` — MP lobby info
### 3.4 Init Order (Lifecycle)
1. `description.ext` parsed
2. `mission.sqm` loaded (all editor-placed objects, triggers, markers)
3. `init.sqf` runs on all machines (if not using `enableDynamicSimulation`)
4. JIP players run `init.sqf` on join
**KP Liberation init flow** (`init.sqf:22-64`):
```
1. Set version, disable saving
2. KPLIB_fnc_initSectors()
3. #include "scripts/shared/defines.hpp"
4. Call fetch_params.sqf (mission params)
5. Call kp_liberation_config.sqf (hardcoded config)
6. Call init_presets.sqf (faction load)
7. Call kp_objectInits.sqf (triggers)
8. KPPLM or GREUH player menu init
9. Call init_shared.sqf (compile shared)
10. Call init_server.sqf (server only)
11. HC manager
12. Client init (if player)
13. Revive system init
```
### 3.5 Config Class Syntax (ext / cpp)
- `class` keyword MUST be lowercase
- Properties use `=` not `:`
- Strings: `"double quotes"`
- Arrays: `{ element, element }` in configs, `[element, element]` in SQF
- Semicolons required after each property
- Inheritance: `class MyClass : BaseClass {}`
### 3.6 mod.cpp vs description.ext
- **mod.cpp** — placed in `@modname/` root, defines mod metadata in Steam Workshop
- **description.ext** — placed in mission root, defines mission-specific settings
- **config.cpp** — placed in addons, defines `CfgPatches`, `CfgVehicles`, etc.
---
## 4. KP Liberation Architecture
### 4.1 Namespace Conventions
| Prefix | Scope | Definition |
|--------|-------|------------|
| `KPLIB_` | Mission globals | CfgFunctions.hpp namespace (KPLIB_fnc_*) |
| `KP_liberation_` | Configuration/state | kp_liberation_config.sqf |
| `GRLIB_` | Legacy (original Liberation) | Config/system globals |
| `KPPLM_` | Player menu module | KPPLM_functions.hpp |
| `KPGUI_` | GUI framework | KPGUI_defines.hpp |
| `GREUH_` | Legacy GREUH module | GREUH_config.sqf |
| `F_` | Legacy function prefix (sparse) | Inline compiled scripts |
### 4.2 Init Flags
| Variable | Description |
|----------|-------------|
| `KPLIB_init` | All init complete |
| `KPLIB_initServer` | Server init complete |
| `KPLIB_initPresets` | Presets loaded |
| `KP_serverParamsFetched` | Mission params received |
| `GRLIB_respawn_marker` | Respawn position set |
| `GRLIB_player_configured` | Player loadout configured |
### 4.3 Remote Call Architecture
**Server → Client files** (in `scripts/client/remotecall/`):
- `remote_call_battlegroup.sqf`
- `remote_call_endgame.sqf`
- `remote_call_fob.sqf`
- `remote_call_incoming.sqf`
- `remote_call_intel.sqf`
- `remote_call_prisonner.sqf`
- `remote_call_sector.sqf`
**Client → Server files** (in `scripts/server/remotecall/`):
- `build_remote_call.sqf`
- `build_fob_remote_call.sqf`
- `cancel_build_remote_call.sqf`
- Plus logistics (add_logi*, del_logi*, save_logi*)
### 4.4 Subsystem Debug Flags
Set in `kp_liberation_config.sqf`, enable verbose logging:
```sqf
KP_liberation_kill_debug = false;
KP_liberation_civrep_debug = false;
KP_liberation_asymmetric_debug = false;
KP_liberation_logging = false; // Master switch
```
### 4.5 CfgFunctions.hpp Structure
```hpp
class KPLIB {
// Server-agnostic functions (in functions/)
class functions {
file = "functions";
class log {};
class checkClass {};
class getSaveData {};
class setSaveData {};
class getLoadout {};
class setLoadout {};
// ... 80 entries
};
// Zeus curator
class functions_curator {
file = "functions\curator";
class initCuratorHandlers {};
class requestZeus {};
};
// Overlay UI
class functions_ui {
file = "functions\ui";
class overlayUpdateResources {};
};
};
#include "scripts\client\CfgFunctions.hpp" // Client tutorials
#include "scripts\server\CfgFunctions.hpp" // Server sector, HC
#include "KP\KPPLM\KPPLM_functions.hpp" // Player menu
```
### 4.6 Preset System
Each preset file exports arrays indexed by build menu page (7 pages):
1. `infantry_units` — Page 1
2. `light_vehicles` — Page 2
3. `heavy_vehicles` — Page 3
4. `air_vehicles` — Page 4
5. `sea_vehicles` — Page 5
6. `buildings` — Page 6
7. `support_vehicles` — Page 7
Plus:
- `squads` — AI squad compositions
- `elite_vehicles` — Military-base-unlockable vehicles
Array format: `["classname", supplies, ammo, fuel]`
Arsenal presets define `GRLIB_arsenal_weapons`, `GRLIB_arsenal_magazines`, `GRLIB_arsenal_items`, `GRLIB_arsenal_backpacks` arrays of classname strings.
### 4.7 Logging System
```sqf
[_message, _tag] call KPLIB_fnc_log;
// Output: [KPLIB] [TAG] message text (via diag_log)
```
Tags used: `PARAM`, `PRESETS`, `MISSIONSTART`, `STATS`, `KILL`, `MOD`, `CIVREP`, `CIVINFO`, `ASYMMETRIC`, `SECTORSPAWN`, `SUPPORTMODULES`, `ERROR`, `BLACKLIST`, `INFO`
---
## 5. Coding Standards & Conventions (for this project)
### 5.1 Syntax Rules
- **Every statement MUST end with `;`** — no exceptions
- **No trailing commas** in arrays — last element before `]` must not have `,`
- **No `00` number literals** — `0` not `00` (SQF parses `00` as octal or breaks)
- **No double semicolons `;;`** — causes SQF parse errors
- **Strings require double quotes** `"..."` — single quotes are only for config paths
- **Round brackets `()` are optional** in control structure conditions but RECOMMENDED for readability and correct precedence
### 5.2 Naming
| Construct | Convention | Example |
|-----------|------------|---------|
| Global variables | `Prefix_lowercase_camelCase` | `KP_liberation_ace`, `GRLIB_unitcap` |
| Private variables | `_lowercase_camelCase` | `_sectorPos`, `_nearestFob` |
| Constants (`#define`) | `UPPER_SNAKE_CASE` | `COLOR_GREEN`, `GUI_GRID_W` |
| KPLIB functions | `KPLIB_fnc_descriptiveName` | `KPLIB_fnc_log` |
| Script files | `descriptive_name.sqf` | `kill_manager.sqf`, `do_build.sqf` |
| Function files | `fn_descriptiveName.sqf` | `fn_log.sqf`, `fn_checkClass.sqf` |
| UI HPP files | `liberation_name.hpp` | `liberation_build.hpp` |
| Preset files | `faction_variant.sqf` | `rhs_usaf_wdl.sqf` |
### 5.3 File Prologue (all `functions/` files)
```sqf
/*
File: fn_functionName.sqf
Author: KP Liberation Dev Team - https://github.com/KillahPotatoes
Date: 2020-04-16
Last Update: 2020-04-20
License: MIT License - http://www.opensource.org/licenses/MIT
Description:
Brief one-paragraph description.
*/
```
### 5.4 Indentation
- **4 spaces** per indent level
- Align array elements vertically for readability:
```sqf
blufor_squad_inf_light = [
["B_soldier_F", 20, 0, 0],
["B_soldier_AR_F",25, 0, 0]
];
```
### 5.5 What To Avoid
- **Do NOT add `0 = ` prefix** to command calls (unnecessary since Arma 3 v2.04)
- **Do NOT use `_this select N`** — use `params` instead
- **Do NOT use SQS** (deprecated); use SQF exclusively
- **Do NOT use `goto`/labels** — use structured control flow
- **Do NOT put code in unit init boxes** in mission.sqm (runs client-side per connection)
- **Do NOT modify GREUH/** files unless explicitly asked (legacy, separate maintainer)
- **Do NOT use `exec`** (SQS); use `execVM` or `call`/`spawn`
- **Do NOT introduce semicolons after closing braces** `};` unless followed by another statement on the same line
### 5.6 Best Practices
- `params` with type filtering for ALL function parameters
- `private` for ALL local variables to prevent scope pollution
- `compileFinal preprocessFileLineNumbers` for reusable compiled code
- Debug flags for subsystem verbosity (not commented-out code)
- Use `arrayIntersect` for deduplication, `apply` for transformations
- Use `remoteExecCall` over `remoteExec` when return value is not needed (faster)
- Always include JIP object parameter for persistent remoteExec
### 5.7 Common Pitfalls & Error Patterns
| Mistake | Symptom | Fix |
|---------|---------|-----|
| `00` numeric literal | Parse error or octal value | Use `0` instead |
| `;;` double semicolon | Parse error | Remove extra `;` |
| Trailing comma in array | Parse error | Remove last `,` |
| Mismatched brackets | Silent runtime failure | Count `(` vs `)` and `[` vs `]` |
| Non-private variable shadows global | Unexpected behavior | Add `private` keyword |
| Missing `;` | Parse error cascades | Add semicolon |
| Unquoted string macro arg with comma | Macro breaks | Wrap in `""` or use `##` |
| `#include` path starting with `\` | File not found | Use relative path without leading `\` |
| Using `localize` inside `#define` | Hardcoded language | Use `$STR_XXX` reference instead |
| Wrong bracket type in config | Class parse error | Configs use `{}` not `[]` for arrays |
| Semicolon after `}` of control struct | Usually valid, but redundant/wrong when followed by `else` | Remove `;` before `else` |
---
## 6. PBO Build & Deployment
### 6.1 Local Build
```bash
# Pack mission folder (no binarization)
armake2 pack "CTI 34 KP Liberation v0.96.7a Ruha.ruha" "CTI_34_KP_Liberation_v0.96.7a_Ruha.ruha.pbo"
# Verify
armake2 inspect "CTI_34_KP_Liberation_v0.96.7a_Ruha.ruha.pbo"
```
### 6.2 CI/CD (Gitea Actions)
Workflow file: `.gitea/workflows/build.yml`
- Trigger: push to main/master, tags `v*`, manual
- Uses `arwynfr/armake2:debian` Docker image
- Produces artifact: `CTI_34_KP_Liberation_v0.96.7a_Ruha.ruha.pbo`
- Includes disabled `deploy` job template for SCP-to-server
---
## 7. References
- **SQF Syntax:** https://community.bistudio.com/wiki/SQF_Syntax
- **Control Structures:** https://community.bistudio.com/wiki/Control_Structures
- **PreProcessor Commands:** https://community.bistudio.com/wiki/PreProcessor_Commands
- **Code Best Practices:** https://community.bistudio.com/wiki/Code_Best_Practices
- **Description.ext:** https://community.bohemia.net/wiki/Description.ext
- **PBO File Format:** https://community.bistudio.com/wiki/PBO_File_Format
- **KP Liberation:** https://github.com/KillahPotatoes/KP-Liberation
- **armake2:** https://github.com/KoffeinFlummi/armake2
- **Code Optimisation:** https://community.bistudio.com/wiki/Code_Optimisation
- **Multiplayer Scripting:** https://community.bistudio.com/wiki/Multiplayer_Scripting

View File

@@ -1,51 +0,0 @@
/*
Needed Mods:
- None
Optional Mods:
- None
*/
// Civilian classnames.
civilians = [
"C_Man_Fisherman_01_F",
"C_man_w_worker_F",
"C_man_1_1_F",
"C_man_p_beggar_F",
"C_Man_Messenger_01_F",
"C_man_hunter_1_F",
"C_journalist_F",
"C_Journalist_01_War_F",
"C_man_shorts_2_F",
"C_Man_UtilityWorker_01_F",
"C_man_1",
"C_Man_casual_1_F",
"C_Man_casual_2_F",
"C_Man_casual_3_F",
"C_Man_casual_4_F",
"C_Man_casual_5_F",
"C_Man_casual_6_F",
"C_man_polo_1_F",
"C_man_polo_2_F",
"C_man_polo_3_F",
"C_man_polo_4_F",
"C_man_polo_5_F",
"C_man_polo_6_F"
];
// Civilian vehicle classnames.
civilian_vehicles = [
"C_Quadbike_01_F",
"C_Hatchback_01_F",
"C_Hatchback_01_sport_F",
"C_Offroad_01_F",
"C_Offroad_01_repair_F",
"C_SUV_01_F",
"C_Van_01_fuel_F",
"C_Van_01_transport_F",
"C_Van_01_box_F",
"C_Truck_02_fuel_F",
"C_Truck_02_transport_F",
"C_Truck_02_covered_F",
"C_Truck_02_box_F"
];

View File

@@ -1,149 +0,0 @@
/*
Needed Mods:
- RHS AFRF
Optional Mods:
- None
*/
// Enemy infantry classes
opfor_officer = "rhs_msv_emr_officer"; // Officer
opfor_squad_leader = "rhs_msv_emr_sergeant"; // Squad Leader
opfor_team_leader = "rhs_msv_emr_efreitor"; // Team Leader
opfor_sentry = "rhs_msv_emr_rifleman"; // Rifleman (Lite)
opfor_rifleman = "rhs_msv_emr_rifleman"; // Rifleman
opfor_rpg = "rhs_msv_emr_LAT"; // Rifleman (LAT)
opfor_grenadier = "rhs_msv_emr_grenadier"; // Grenadier
opfor_machinegunner = "rhs_msv_emr_arifleman"; // Autorifleman
opfor_heavygunner = "rhs_msv_emr_machinegunner"; // Heavy Gunner
opfor_marksman = "rhs_msv_emr_marksman"; // Marksman
opfor_sharpshooter = "rhs_msv_emr_marksman"; // Sharpshooter
opfor_sniper = "rhs_msv_emr_marksman"; // Sniper
opfor_at = "rhs_msv_emr_at"; // AT Specialist
opfor_aa = "rhs_msv_emr_aa"; // AA Specialist
opfor_medic = "rhs_msv_emr_medic"; // Combat Life Saver
opfor_engineer = "rhs_msv_emr_engineer"; // Engineer
opfor_paratrooper = "rhs_msv_emr_RShG2"; // Paratrooper
// Enemy vehicles used by secondary objectives.
opfor_mrap = "rhs_tigr_msv"; // GAZ-233011
opfor_mrap_armed = "rhs_tigr_sts_msv"; // GAZ-233014 (Armed)
opfor_transport_helo = "RHS_Mi8mt_Cargo_vvsc"; // Mi-8MT (Cargo)
opfor_transport_truck = "RHS_Ural_MSV_01"; // Ural-4320 Transport (Covered)
opfor_ammobox_transport = "RHS_Ural_Open_MSV_01"; // Ural-4320 Transport (Open) -> Has to be able to transport resource crates!
opfor_fuel_truck = "RHS_Ural_Fuel_MSV_01"; // Ural-4320 Fuel
opfor_ammo_truck = "rhs_gaz66_ammo_msv"; // GAZ-66 Ammo
opfor_fuel_container = "Land_Pod_Heli_Transport_04_fuel_F"; // Taru Fuel Pod
opfor_ammo_container = "Land_Pod_Heli_Transport_04_ammo_F"; // Taru Ammo Pod
opfor_flag = "rhs_Flag_Russia_F"; // Flag
/* Adding a value to these arrays below will add them to a one out of however many in the array, random pick chance.
Therefore, adding the same value twice or three times means they are more likely to be chosen more often. */
/* Militia infantry. Lightweight soldier classnames the game will pick from randomly as sector defenders.
Think of them like garrison or military police forces, which are more meant to control the local population instead of fighting enemy armies. */
militia_squad = [
"RUS_MSV_sr_efreitor", // Rifleman
"RUS_MSV_sr_grenadier", // Rifleman
"RUS_MSV_sr_gunner", // Rifleman
"RUS_MSV_sr_juniorsergeant", // Rifleman (AT)
"RUS_MSV_sr_machinegunner", // Autorifleman
"RUS_MSV_sr_private", // Marksman
"RUS_MSV_sr_riflemangrenadierassistant", // Medic
"RUS_MSV_sr_riflemanmachinegunnerassistant" // Engineer
];
// Militia vehicles. Lightweight vehicle classnames the game will pick from randomly as sector defenders.
militia_vehicles = [
"rhs_tigr_sts_msv" // GAZ-233014 (Armed)
];
// Militia vehicles. Lightweight vehicle classnames the game will pick from randomly as sector defenders. Can also be empty for only infantry milita.
opfor_vehicles = [
"rhs_tigr_sts_msv", // GAZ-233014 (Armed)
"rhs_tigr_sts_msv", // GAZ-233014 (Armed)
"rhs_tigr_sts_msv", // GAZ-233014 (Armed)
"rhs_bmp2d_msv", // BMP-2D
"rhs_bmp2k_msv", // BMP-2K
"rhs_brm1k_msv", // BRM-1K
"rhs_zsu234_aa", // ZSU-23-4V
"rhs_zsu234_aa", // ZSU-23-4V
"rhs_t80", // T80
"rhs_t80", // T80
"rhs_t90a_tv", // T90A
"rhs_t90sab_tv" // T90SA (2016)
];
// All enemy vehicles that can spawn as sector defenders and patrols but at a lower enemy combat readiness (aggression levels).
opfor_vehicles_low_intensity = [
"rhs_tigr_sts_msv", // GAZ-233014 (Armed)
"rhs_tigr_sts_msv", // GAZ-233014 (Armed)
"rhs_btr80_msv", // BTR-80
"rhs_btr80a_msv" // BTR-80A
];
// All enemy vehicles that can spawn as battlegroups, either assaulting or as reinforcements, at high enemy combat readiness (aggression levels).
opfor_battlegroup_vehicles = [
"rhs_tigr_sts_msv", // GAZ-233014 (Armed)
"rhs_tigr_sts_msv", // GAZ-233014 (Armed)
"rhs_tigr_sts_msv", // GAZ-233014 (Armed)
"RHS_Ural_Open_MSV_01", // Ural-4320 Transport
"RHS_Ural_MSV_01", // Ural-4320 Transport (Covered)
"rhs_bmp2d_msv", // BMP-2D
"rhs_bmp2k_msv", // BMP-2K
"rhs_brm1k_msv", // BRM-1K
"rhs_zsu234_aa", // ZSU-23-4V
"rhs_zsu234_aa", // ZSU-23-4V
"rhs_t80", // T80
"rhs_t80", // T80
"rhs_t90a_tv", // T90A
"RHS_Mi24P_AT_vvsc", // Mi-24P (AT)
"RHS_Mi24V_AT_vvsc", // Mi-24V (AT)
"RHS_Mi8mt_Cargo_vvsc", // Mi-8MT (Cargo)
"RHS_Ka52_vvsc" // Ka-52
];
// All enemy vehicles that can spawn as battlegroups, either assaulting or as reinforcements, at lower enemy combat readiness (aggression levels).
opfor_battlegroup_vehicles_low_intensity = [
"rhs_tigr_msv", // GAZ-233011
"rhs_tigr_sts_msv", // GAZ-233014 (Armed)
"rhs_tigr_sts_msv", // GAZ-233014 (Armed)
"RHS_Ural_Open_MSV_01", // Ural-4320 Transport
"rhs_btr80_msv", // BTR-80
"rhs_btr80a_msv", // BTR-80A
"rhs_zsu234_aa", // ZSU-23-4V
"RHS_Mi24P_AT_vvsc", // Mi-24P (AT)
"RHS_Mi24V_AT_vvsc", // Mi-24V (AT)
"RHS_Mi8mt_Cargo_vvsc" // Mi-8MT (Cargo)
];
/* All vehicles that spawn within battlegroups (see the above 2 arrays) and also hold 8 soldiers as passengers.
If something in this array can't hold all 8 soldiers then buggy behaviours may occur. */
opfor_troup_transports = [
"RHS_Ural_Open_MSV_01", // Ural-4320 Transport
"RHS_Ural_MSV_01", // Ural-4320 Transport (Covered)
"rhs_btr80_msv", // BTR-80
"rhs_btr80a_msv", // BTR-80A
"rhs_bmp2d_msv", // BMP-2D
"RHS_Mi8mt_Cargo_vvsc", // Mi-8MT (Cargo)
"RHS_Mi24P_AT_vvsc", // Mi-24P (AT)
"RHS_Mi24V_AT_vvsc" // Mi-24V (AT)
];
// Enemy rotary-wings that will need to spawn in flight.
opfor_choppers = [
"RUS_VKS_ka52", // Mi-8MT (Cargo)
"RUS_VKS_mi24p", // Mi-24P (AT)
"RUS_VKS_mi28n", // Mi-24V (AT)
"RUS_VKS_mi8mt", // Ka-52
"RUS_VKS_mi8mtv2"
];
// Enemy fixed-wings that will need to spawn in the air.
opfor_air = [
"RHS_Su25SM_vvs", // Su-25
"RUS_VKS_su25sm", // Su-25 (KH29)
"RUS_VKS_mig29s",
"RUS_VKS_mig29smt",
"RUS_VKS_tu95ms6"
];

Some files were not shown because too many files have changed in this diff Show More