From 4f54edf467fad9c1a90ed5db9dbd4af7f472541f Mon Sep 17 00:00:00 2001 From: Jacob Schmidt Date: Wed, 3 Jun 2026 22:48:59 -0500 Subject: [PATCH] Backport framework docs and store filter updates --- .../mission_setup/ui/_site/mission-setup.css | 10 ++ .../mission_setup/ui/_site/mission-setup.js | 78 +++++++-- .../actor/functions/fnc_initActorStore.sqf | 20 +-- arma/server/addons/main/XEH_preInit.sqf | 2 + arma/server/addons/store/README.md | 13 +- .../functions/fnc_initCatalogService.sqf | 7 +- .../functions/fnc_initMissionSetupService.sqf | 2 +- docs/MISSION_DESIGNER_GUIDE.md | 21 ++- docs/PLAYER_GUIDE.md | 2 +- docs/STORE_USAGE_GUIDE.md | 24 ++- docs/TASK_USAGE_GUIDE.md | 4 + docs/TRANSPORT_SERVICE_GUIDE.md | 12 +- .../1.getting-started/4.mission-designer.md | 16 +- .../1.getting-started/5.player-guide.md | 2 +- .../1.getting-started/8.git-workflow.md | 158 ++++++++++++++++++ .../3.server-modules/12.transport-service.md | 12 +- 16 files changed, 320 insertions(+), 63 deletions(-) create mode 100644 docus/content/1.getting-started/8.git-workflow.md diff --git a/arma/client/addons/mission_setup/ui/_site/mission-setup.css b/arma/client/addons/mission_setup/ui/_site/mission-setup.css index c8f77a2..87e50f7 100644 --- a/arma/client/addons/mission_setup/ui/_site/mission-setup.css +++ b/arma/client/addons/mission_setup/ui/_site/mission-setup.css @@ -152,6 +152,12 @@ option { grid-column: 1 / -1; } +.timer-row { + display: grid; + grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.95fr) minmax(0, 0.95fr); + gap: 0.5rem; +} + label { color: var(--text-subtle); font-size: 0.62rem; @@ -261,6 +267,10 @@ select { color: var(--text-main); } +input:disabled { + opacity: 0.45; +} + input:focus, select:focus, button:focus-visible { diff --git a/arma/client/addons/mission_setup/ui/_site/mission-setup.js b/arma/client/addons/mission_setup/ui/_site/mission-setup.js index 9128328..e4755eb 100644 --- a/arma/client/addons/mission_setup/ui/_site/mission-setup.js +++ b/arma/client/addons/mission_setup/ui/_site/mission-setup.js @@ -12,6 +12,7 @@ reputationMax: 100, penaltyMin: -5, penaltyMax: -25, + timeLimitEnabled: true, timeLimitMin: 600, timeLimitMax: 900, medicalSpawnCost: 100, @@ -41,6 +42,8 @@ } function readSettings() { + const timeLimitEnabled = document.getElementById("timeLimitEnabled")?.checked !== false; + return { enemyFaction: String(document.getElementById("enemyFaction")?.value || "IND_G_F"), maxConcurrentMissions: fieldNumber("maxConcurrentMissions"), @@ -52,8 +55,9 @@ reputationMax: fieldNumber("reputationMax"), penaltyMin: fieldNumber("penaltyMin"), penaltyMax: fieldNumber("penaltyMax"), - timeLimitMin: fieldNumber("timeLimitMin"), - timeLimitMax: fieldNumber("timeLimitMax"), + timeLimitEnabled, + timeLimitMin: timeLimitEnabled ? fieldNumber("timeLimitMin") : 0, + timeLimitMax: timeLimitEnabled ? fieldNumber("timeLimitMax") : 0, medicalSpawnCost: fieldNumber("medicalSpawnCost"), medicalHealCost: fieldNumber("medicalHealCost"), serviceRepairCost: fieldNumber("serviceRepairCost"), @@ -74,6 +78,16 @@ .replace(/'/g, "'"); } + function normalizeSettings(settings) { + const next = Object.assign({}, settings); + next.timeLimitMin = Number(next.timeLimitMin || 0); + next.timeLimitMax = Number(next.timeLimitMax || 0); + if (typeof next.timeLimitEnabled !== "boolean") { + next.timeLimitEnabled = next.timeLimitMax > 0; + } + return next; + } + function apply() { const settings = readSettings(); if (settings.moneyMax < settings.moneyMin) { @@ -94,10 +108,18 @@ return; } - if (settings.timeLimitMax < settings.timeLimitMin) { - state.error = "Time limit max must be greater than or equal to time limit min."; - render(); - return; + if (settings.timeLimitEnabled) { + if (settings.timeLimitMin < 1 || settings.timeLimitMax < 1) { + state.error = "Time limits must be positive seconds when task timers are enabled."; + render(); + return; + } + + if (settings.timeLimitMax < settings.timeLimitMin) { + state.error = "Time limit max must be greater than or equal to time limit min."; + render(); + return; + } } const costFields = [ @@ -134,6 +156,15 @@ const factionLabel = faction ? faction.display : settings.enemyFaction; const generatorProviderLabel = settings.generatorProvider === "custom" ? "Custom" : "Built-in"; const generatorProviderChecked = settings.generatorProvider === "custom" ? " checked" : ""; + const timeLimitEnabled = settings.timeLimitEnabled !== false; + const timeLimitChecked = timeLimitEnabled ? " checked" : ""; + const timeLimitDisabled = timeLimitEnabled ? "" : " disabled"; + const timeLimitLabel = timeLimitEnabled ? "Enabled" : "No Limit"; + const timeLimitMinValue = timeLimitEnabled ? settings.timeLimitMin : 600; + const timeLimitMaxValue = timeLimitEnabled ? settings.timeLimitMax : 900; + const timeLimitSummary = timeLimitEnabled + ? `${settings.timeLimitMin}s - ${settings.timeLimitMax}s` + : "No limit"; document.getElementById("app").innerHTML = `
@@ -204,13 +235,26 @@
-
- - -
-
- - +
+
+ + +
+
+ + +
+
+ + +
@@ -222,7 +266,7 @@
- +
@@ -266,10 +310,10 @@
Reward Range$${Number(settings.moneyMin).toLocaleString()} - $${Number(settings.moneyMax).toLocaleString()}
Reputation${settings.reputationMin} - ${settings.reputationMax}
Reputation Hit${settings.penaltyMin} to ${settings.penaltyMax}
-
Time Limit${settings.timeLimitMin}s - ${settings.timeLimitMax}s
+
Time Limit${timeLimitSummary}
Repair / Rearm$${Number(settings.serviceRepairCost).toLocaleString()} / $${Number(settings.serviceRearmCost).toLocaleString()}
Fuel$${Number(settings.fuelCost).toLocaleString()} / L
-
Medical$${Number(settings.medicalSpawnCost).toLocaleString()} spawn / $${Number(settings.medicalHealCost).toLocaleString()} heal
+
Medical Billing$${Number(settings.medicalSpawnCost).toLocaleString()} respawn / $${Number(settings.medicalHealCost).toLocaleString()} heal
${state.error ? `
${state.error}
` : ""}
@@ -315,7 +359,7 @@ return true; }); state.factions = factions; - state.settings = Object.assign({}, state.settings, payload.data?.settings || {}); + state.settings = normalizeSettings(Object.assign({}, state.settings, payload.data?.settings || {})); render(); return true; } diff --git a/arma/server/addons/actor/functions/fnc_initActorStore.sqf b/arma/server/addons/actor/functions/fnc_initActorStore.sqf index e2ba8de..72f2cbb 100644 --- a/arma/server/addons/actor/functions/fnc_initActorStore.sqf +++ b/arma/server/addons/actor/functions/fnc_initActorStore.sqf @@ -34,7 +34,7 @@ GVAR(ActorModel) = compileFinal createHashMapObject [[ if (isArray _loadoutConfig) exitWith { getArray _loadoutConfig }; - [[],[],[],["U_BG_Guerrilla_6_1",[["FirstAidKit", 2]]],[],[],"H_Cap_blk_ION","",[],["ItemMap","ItemGPS","ItemRadio","ItemCompass","ItemWatch",""]] + [[],[],["hgun_P07_F","","","",["16Rnd_9x21_Mag",4,17],[],""],["U_BG_Guerrilla_6_1",[["FirstAidKit", 2],["ACE_EarPlugs",1]]],["V_Rangemaster_belt",[["16Rnd_9x21_Mag",4]]],[],"H_Cap_blk_ION","",["Binocular","","","",[],[],""],["ItemMap","ItemGPS","ItemRadio","ItemCompass","ItemWatch",""]] }], ["defaults", compileFinal { private _actor = createHashMap; @@ -116,13 +116,11 @@ GVAR(ActorModel) = compileFinal createHashMapObject [[ }] ]]; -GVAR(ActorBaseStore) = compileFinal ([ - EGVAR(common,BaseStore), - createHashMapFromArray [ +GVAR(ActorBaseStore) = compileFinal createHashMapFromArray [ + ["#base", EGVAR(common,BaseStore)], ["#type", "ActorBaseStore"], ["#create", compileFinal { ["INFO", "Actor Store Initialized!"] call EFUNC(common,log); - true }], ["cacheActor", compileFinal { params [["_uid", "", [""]], ["_actor", createHashMap, [createHashMap]]]; @@ -574,13 +572,7 @@ GVAR(ActorBaseStore) = compileFinal ([ _self call ["override", [_uid, _finalActor, false]] }] -]] call { - params ["_base", "_child"]; +]; - private _merged = +_base; - { _merged set [_x, _y]; } forEach _child; - _merged -}); - -GVAR(ActorStore) = createHashMapObject [GVAR(ActorBaseStore), []]; -true +GVAR(ActorStore) = createHashMapObject [GVAR(ActorBaseStore)]; +GVAR(ActorStore) diff --git a/arma/server/addons/main/XEH_preInit.sqf b/arma/server/addons/main/XEH_preInit.sqf index 929f1ff..85c5864 100644 --- a/arma/server/addons/main/XEH_preInit.sqf +++ b/arma/server/addons/main/XEH_preInit.sqf @@ -4,6 +4,8 @@ PREP_RECOMPILE_START; #include "XEH_PREP.hpp" PREP_RECOMPILE_END; +if (isServer) then { "forge_server" callExtension ["surreal:reconnect", []]; }; + GVAR(PlayerBootstrapRegistry) = createHashMap; ["forge_icom_event", { diff --git a/arma/server/addons/store/README.md b/arma/server/addons/store/README.md index 84313ae..367ab28 100644 --- a/arma/server/addons/store/README.md +++ b/arma/server/addons/store/README.md @@ -72,12 +72,13 @@ listed for the requested category. `denylist` removes listed classnames from the generated category. Overrides are applied server-side, so checkout validation uses the same prices and descriptions the UI displays. -`modMode` applies before category filtering. `allowlist` only keeps generated -entries that match one of the configured `mods[]`; `denylist` removes matching -entries. Each `ModSources` child can define `patches[]` to detect whether the -mod is loaded, `addons[]` for config source addon/source mod names or classname -prefixes, and `prefixes[]` for classname prefixes. If a mod source defines no -patches, it is treated as available and only the source/prefix checks are used. +`modMode` applies before category filtering. `dynamic` means no mod-source +filtering. `allowlist` only keeps generated entries that match one of the +configured `mods[]`; `denylist` removes matching entries. Each `ModSources` +child can define `patches[]` to detect whether the mod is loaded, `addons[]` +for exact config source addon/source mod names, and `prefixes[]` for classname, +source addon, or source mod prefixes. If a mod source defines no patches, it is +treated as available and only the source/prefix checks are used. `units[]` follows the same `dynamic`, `allowlist`, and `denylist` behavior as item and vehicle categories. Unit purchases are immediate spawn grants, not diff --git a/arma/server/addons/store/functions/fnc_initCatalogService.sqf b/arma/server/addons/store/functions/fnc_initCatalogService.sqf index 35d1e45..fdec489 100644 --- a/arma/server/addons/store/functions/fnc_initCatalogService.sqf +++ b/arma/server/addons/store/functions/fnc_initCatalogService.sqf @@ -111,17 +111,18 @@ GVAR(StoreCatalogServiceBaseClass) = compileFinal createHashMapFromArray [ private _sourceMod = _item getOrDefault ["sourceMod", ""]; private _addons = (_self call ["getMissionStoreModSourceValues", [_modID, "addons"]]) apply { toLowerANSI _x }; private _prefixes = (_self call ["getMissionStoreModSourceValues", [_modID, "prefixes"]]) apply { toLowerANSI _x }; + private _matchPrefixes = _addons + _prefixes; private _sourceModLower = toLowerANSI _sourceMod; if (_sourceModLower in _addons) exitWith { true }; private _sourceAddonMatched = false; { if (_x in _addons) exitWith { _sourceAddonMatched = true; }; - if (_self call ["doesValueMatchAnyPrefix", [_x, _addons]]) exitWith { _sourceAddonMatched = true; }; + if (_self call ["doesValueMatchAnyPrefix", [_x, _matchPrefixes]]) exitWith { _sourceAddonMatched = true; }; } forEach _sourceAddons; if (_sourceAddonMatched) exitWith { true }; - if (_self call ["doesValueMatchAnyPrefix", [_className, _addons + _prefixes]]) exitWith { true }; - if (_self call ["doesValueMatchAnyPrefix", [_sourceMod, _addons]]) exitWith { true }; + if (_self call ["doesValueMatchAnyPrefix", [_className, _matchPrefixes]]) exitWith { true }; + if (_self call ["doesValueMatchAnyPrefix", [_sourceMod, _matchPrefixes]]) exitWith { true }; false }], diff --git a/arma/server/addons/task/functions/fnc_initMissionSetupService.sqf b/arma/server/addons/task/functions/fnc_initMissionSetupService.sqf index 4bd1707..21d7af6 100644 --- a/arma/server/addons/task/functions/fnc_initMissionSetupService.sqf +++ b/arma/server/addons/task/functions/fnc_initMissionSetupService.sqf @@ -154,7 +154,7 @@ GVAR(MissionSetupServiceBaseClass) = compileFinal createHashMapFromArray [ _penMin = _penMin min 0; _penMax = _penMax min 0; - _timeMin = _timeMin max 1; + _timeMin = _timeMin max 0; _timeMax = _timeMax max _timeMin; _medicalSpawnCost = _medicalSpawnCost max 0; _medicalHealCost = _medicalHealCost max 0; diff --git a/docs/MISSION_DESIGNER_GUIDE.md b/docs/MISSION_DESIGNER_GUIDE.md index da5ea4f..0d1517c 100644 --- a/docs/MISSION_DESIGNER_GUIDE.md +++ b/docs/MISSION_DESIGNER_GUIDE.md @@ -164,9 +164,13 @@ airports, bus stops, teleport terminals, or any other mission transport system. The framework owns the menu, billing, cargo scan, and movement logic. The mission only needs placed objects and optional arrival markers. -![Placeholder: Eden transport node object placement](images/eden/transport_node_obj.svg) +![Eden transport location one](images/eden/transport_loc_1.jpg) -![Placeholder: Eden transport node variable name](images/eden/transport_node_var.svg) +![Eden transport location two](images/eden/transport_loc_2.jpg) + +![Eden transport node object placement](images/eden/transport_obj_1.jpg) + +![Eden transport node variable name](images/eden/transport_obj_1_var.jpg) Place transport node objects with these variable names: @@ -188,7 +192,9 @@ transport_arrival_2 transport_arrival_10 ``` -![Placeholder: Eden transport arrival marker placement](images/eden/transport_arrival_marker.svg) +![Eden transport arrival marker placement](images/eden/transport_arrival_mrkr.jpg) + +![Eden transport arrival marker variable name](images/eden/transport_arrival_mrkr_var.jpg) Objects that should be excluded from the nearby cargo scan, such as the actual boat or transport vehicle used as set dressing, should use: @@ -201,7 +207,9 @@ transport_vehicle_2 transport_vehicle_10 ``` -![Placeholder: Eden transport vehicle exclusion object variable name](images/eden/transport_vehicle_var.svg) +![Eden transport vehicle exclusion object placement](images/eden/transport_veh_obj.jpg) + +![Eden transport vehicle exclusion object variable name](images/eden/transport_veh_obj_var.jpg) Minimum Eden setup: @@ -759,6 +767,11 @@ provider preference. It also exposes service pricing for medical spawn, heal, repair, rearm, refuel, and transport defaults. It does not enable or disable generated missions; use the CBA setting for that policy. +Task time limits can be disabled from the setup UI by turning off the task +timer. That stores `timeLimitMin = 0` and `timeLimitMax = 0`, which generated +tasks treat as no timer. Positive min/max values enable task timers and are +rolled in seconds. + If mission setup is enabled, the mission manager waits until the setup operator applies settings. Cancel, X, and Escape apply default values from CBA, mission parameters, and `CfgMissions`. There is no timeout that auto-applies defaults. diff --git a/docs/PLAYER_GUIDE.md b/docs/PLAYER_GUIDE.md index 9d4ea0f..6239185 100644 --- a/docs/PLAYER_GUIDE.md +++ b/docs/PLAYER_GUIDE.md @@ -227,7 +227,7 @@ Player workflow: 1. Stand near a transport point. 2. Open the actor interaction menu. 3. Select Transport. -4. Select a destination from the transport submenu, or select Back to return +4. Select a destination from the transport submenu, or select Close to return to the default interaction menu. ![Transport destination submenu](images/player/transport_destination_menu.jpg) diff --git a/docs/STORE_USAGE_GUIDE.md b/docs/STORE_USAGE_GUIDE.md index e1bf619..5648e7f 100644 --- a/docs/STORE_USAGE_GUIDE.md +++ b/docs/STORE_USAGE_GUIDE.md @@ -72,12 +72,24 @@ listed for each category. `denylist` removes listed classnames. Overrides are server-side and are used by both the UI payload and checkout validation. `units[]` uses the same filter behavior as every other category. -`modMode` applies before category filtering. `allowlist` only keeps generated -entries that match one of the configured `mods[]`; `denylist` removes matching -entries. Each `ModSources` child can define `patches[]` to detect whether the -mod is loaded, `addons[]` for config source addon/source mod names or classname -prefixes, and `prefixes[]` for classname prefixes. If a mod source defines no -patches, it is treated as available and only the source/prefix checks are used. +`modMode` applies before category filtering. `dynamic` means no mod-source +filtering. `allowlist` only keeps generated entries that match one of the +configured `mods[]`; `denylist` removes matching entries. Each `ModSources` +child can define `patches[]` to detect whether the mod is loaded, `addons[]` +for exact config source addon/source mod names, and `prefixes[]` for classname, +source addon, or source mod prefixes. If a mod source defines no patches, it is +treated as available and only the source/prefix checks are used. + +For example, to show only RHS-sourced generated inventory: + +```cpp +modMode = "allowlist"; +mods[] = {"rhs"}; +``` + +The matching `class rhs` must exist under `ModSources`. Category `mode` is still +applied afterward, so leave `mode = "dynamic"` if the mod filter should be the +only inventory filter. The current filter is global for the mission. Revisit per-store profile support if individual vendors need different inventories. diff --git a/docs/TASK_USAGE_GUIDE.md b/docs/TASK_USAGE_GUIDE.md index eebe87c..9b9d159 100644 --- a/docs/TASK_USAGE_GUIDE.md +++ b/docs/TASK_USAGE_GUIDE.md @@ -631,6 +631,10 @@ Task time limits use `0` for no limit: Positive values are measured in seconds. Do not pass `-1` as a no-limit value; the task runtime treats any non-zero task time limit as active. +The mission setup UI uses the same rule. Turning off the task timer stores +`timeLimitMin = 0` and `timeLimitMax = 0`; turning it on uses the configured +positive min/max range for generated tasks. + Defuse IED timers are different. `iedTimer` must be greater than `0`, because IEDs are expected to have an active countdown. The Eden defuse module defaults to `300` seconds. diff --git a/docs/TRANSPORT_SERVICE_GUIDE.md b/docs/TRANSPORT_SERVICE_GUIDE.md index 5708e8b..bf1c54a 100644 --- a/docs/TRANSPORT_SERVICE_GUIDE.md +++ b/docs/TRANSPORT_SERVICE_GUIDE.md @@ -2,7 +2,7 @@ The transport service provides paid point-to-point travel for players and nearby vehicles or passengers. It is framework-owned: missions only need placed -transport objects and arrival markers with the expected variable names. +transport objects and optional arrival markers with the expected variable names. ## Mission Contract @@ -117,9 +117,9 @@ this setVariable ["transportIncludeCargo", true, true]; Only use overrides when the default `transport*` convention or mission-level pricing is not appropriate. -## Reference Images +## Image Checklist -These screenshots show the default transport setup and player workflow: +Replace these placeholder image references after screenshots are captured: ![Eden transport location one](images/eden/transport_loc_1.jpg) @@ -142,3 +142,9 @@ These screenshots show the default transport setup and player workflow: ![Player transport destination submenu](images/player/transport_destination_menu.jpg) ![Player transport completion notification](images/player/transport_complete.jpg) + +## Mission-Side Code Requirement + +No mission-side transport service, addAction script, or server event bridge is +required. The framework handles menu discovery, destination selection, pricing, +billing, cargo movement, and EventBus notifications. diff --git a/docus/content/1.getting-started/4.mission-designer.md b/docus/content/1.getting-started/4.mission-designer.md index 7c36aba..97ba1e3 100644 --- a/docus/content/1.getting-started/4.mission-designer.md +++ b/docus/content/1.getting-started/4.mission-designer.md @@ -164,9 +164,13 @@ airports, bus stops, teleport terminals, or any other mission transport system. The framework owns the menu, billing, cargo scan, and movement logic. The mission only needs placed objects and optional arrival markers. -![Placeholder: Eden transport node object placement](images/eden/transport_node_obj.svg) +![Eden transport location one](images/eden/transport_loc_1.jpg) -![Placeholder: Eden transport node variable name](images/eden/transport_node_var.svg) +![Eden transport location two](images/eden/transport_loc_2.jpg) + +![Eden transport node object placement](images/eden/transport_obj_1.jpg) + +![Eden transport node variable name](images/eden/transport_obj_1_var.jpg) Place transport node objects with these variable names: @@ -188,7 +192,9 @@ transport_arrival_2 transport_arrival_10 ``` -![Placeholder: Eden transport arrival marker placement](images/eden/transport_arrival_marker.svg) +![Eden transport arrival marker placement](images/eden/transport_arrival_mrkr.jpg) + +![Eden transport arrival marker variable name](images/eden/transport_arrival_mrkr_var.jpg) Objects that should be excluded from the nearby cargo scan, such as the actual boat or transport vehicle used as set dressing, should use: @@ -201,7 +207,9 @@ transport_vehicle_2 transport_vehicle_10 ``` -![Placeholder: Eden transport vehicle exclusion object variable name](images/eden/transport_vehicle_var.svg) +![Eden transport vehicle exclusion object placement](images/eden/transport_veh_obj.jpg) + +![Eden transport vehicle exclusion object variable name](images/eden/transport_veh_obj_var.jpg) Minimum Eden setup: diff --git a/docus/content/1.getting-started/5.player-guide.md b/docus/content/1.getting-started/5.player-guide.md index f6de3ca..47ab36d 100644 --- a/docus/content/1.getting-started/5.player-guide.md +++ b/docus/content/1.getting-started/5.player-guide.md @@ -226,7 +226,7 @@ Player workflow: 1. Stand near a transport point. 2. Open the actor interaction menu. 3. Select Transport. -4. Select a destination from the transport submenu, or select Back to return +4. Select a destination from the transport submenu, or select Close to return to the default interaction menu. ![Transport destination submenu](images/player/transport_destination_menu.jpg) diff --git a/docus/content/1.getting-started/8.git-workflow.md b/docus/content/1.getting-started/8.git-workflow.md new file mode 100644 index 0000000..4f3e87b --- /dev/null +++ b/docus/content/1.getting-started/8.git-workflow.md @@ -0,0 +1,158 @@ +--- +title: "Git Workflow" +description: "This repository uses `master` as the clean framework branch. Mission folders are kept off `master` so the framework can be versioned without bundling local test missions or playable mission copies." +--- + +## Workflow Helper + +The repository includes a small helper for the common branch checks and branch +switching commands: + +```powershell +npm run workflow -- status +npm run workflow -- doctor +npm run workflow -- switch dev +npm run workflow -- switch missions +npm run workflow -- start-feature cad-task-request +npm run workflow -- release-check +``` + +The helper refuses branch switches and feature branch creation when the working +tree has uncommitted changes. Use the manual Git commands below when you need +more control. + +## Branch Roles + +- `master`: framework source, addon code, Rust extension code, docs, tooling, + and release tags. +- `missions/local-mission-copies`: local mission folders used for testing and + mission iteration. This branch is not pushed unless intentionally needed. +- `archive/pre-v0.1-history`: read-only archive of the previous full `master` + history before the `v0.1.0` baseline cleanup. + +## Daily Framework Work + +Start from the clean framework branch. + +```powershell +git switch master +git pull +git status --short --branch +``` + +Create a short-lived feature branch for framework work. + +```powershell +git switch -c feature/garage-marker-selection +``` + +Make the change, validate it, then commit. + +```powershell +git status --short --branch +git add arma/client/addons/garage/functions/fnc_initContextService.sqf +git commit -m "Improve garage spawn marker selection" +``` + +Merge the work back into `master`. Squash merges keep future `master` history +compact. + +```powershell +git switch master +git merge --squash feature/garage-marker-selection +git commit -m "Improve garage spawn marker selection" +git push +``` + +Remove the local feature branch when it is no longer needed. + +```powershell +git branch -D feature/garage-marker-selection +``` + +## Mission Work + +Switch to the local mission branch before editing mission folders. + +```powershell +git switch missions/local-mission-copies +git status --short --branch +``` + +Mission folders currently tracked on that branch: + +```text +arma/forge_framework.Malden +arma/forge_pmc_simulator.Tanoa +arma/forge_pmc_simulator_v2.Tanoa +``` + +Commit mission-only changes on the mission branch. + +```powershell +git add arma/forge_pmc_simulator.Tanoa +git commit -m "Update PMC simulator mission setup" +``` + +Do not merge the mission branch into `master`. If a mission change becomes +framework code, copy only the reusable files or logic onto a framework feature +branch created from `master`. + +Example: + +```powershell +git switch master +git switch -c feature/cad-on-demand-task-request + +# Bring over only the framework files needed from the mission branch. +git checkout missions/local-mission-copies -- arma/client/addons/cad/functions/fnc_initUIBridge.sqf +git checkout missions/local-mission-copies -- arma/server/addons/cad/XEH_preInit.sqf + +git add arma/client/addons/cad/functions/fnc_initUIBridge.sqf arma/server/addons/cad/XEH_preInit.sqf +git commit -m "Add CAD on-demand mission task request bridge" +``` + +## Release Versioning + +Use tags to mark framework releases. + +Version guideline: + +- Patch, such as `v0.1.1`: fixes and small compatible changes. +- Minor, such as `v0.2.0`: new modules or features. +- Major, such as `v1.0.0`: stable release line or breaking changes. + +Create a release tag from `master`. + +```powershell +git switch master +git pull +git status --short --branch +git tag -a v0.1.1 -m "v0.1.1" +git push origin master +git push origin v0.1.1 +``` + +## Safety Checks + +Before committing on `master`, check that no mission folders are staged. + +```powershell +git status --short --branch +``` + +On `master`, these paths should not appear: + +```text +arma/forge_framework.Malden +arma/forge_pmc_simulator.Tanoa +arma/forge_pmc_simulator_v2.Tanoa +``` + +If mission files appear while on `master`, stop and switch to the mission +branch before continuing. + +```powershell +git switch missions/local-mission-copies +``` + diff --git a/docus/content/3.server-modules/12.transport-service.md b/docus/content/3.server-modules/12.transport-service.md index 724d98f..c1a86dd 100644 --- a/docus/content/3.server-modules/12.transport-service.md +++ b/docus/content/3.server-modules/12.transport-service.md @@ -1,6 +1,6 @@ --- title: "Transport Service Guide" -description: "The transport service provides paid point-to-point travel for players and nearby vehicles or passengers. It is framework-owned: missions only need placed transport objects and arrival markers with the expected variable names." +description: "The transport service provides paid point-to-point travel for players and nearby vehicles or passengers. It is framework-owned: missions only need placed transport objects and optional arrival markers with the expected variable names." --- ## Mission Contract @@ -109,9 +109,9 @@ this setVariable ["transportIncludeCargo", true, true]; Only use overrides when the default `transport*` convention is not appropriate. -## Reference Images +## Image Checklist -These screenshots show the default transport setup and player workflow: +Replace these placeholder image references after screenshots are captured: ![Eden transport location one](images/eden/transport_loc_1.jpg) @@ -134,3 +134,9 @@ These screenshots show the default transport setup and player workflow: ![Player transport destination submenu](images/player/transport_destination_menu.jpg) ![Player transport completion notification](images/player/transport_complete.jpg) + +## Mission-Side Code Requirement + +No mission-side transport service, addAction script, or server event bridge is +required. The framework handles menu discovery, destination selection, pricing, +billing, cargo movement, and EventBus notifications.