diff --git a/docs/modding/p2ce-campaigns/commands-convars-and-launch-options.md b/docs/modding/p2ce-campaigns/commands-convars-and-launch-options.md new file mode 100644 index 00000000..fb695eed --- /dev/null +++ b/docs/modding/p2ce-campaigns/commands-convars-and-launch-options.md @@ -0,0 +1,75 @@ +--- +title: Useful Commands, Convars, and Launch Options +features: + - USE_CAMPAIGNMANAGER +--- + +# Useful Commands + +## `campaign_reload` + +Reloads the campaign list. New & change campaign scripts should appear in the UI. If you are on the campaign selection screen, re-enter that screen to see the new/update campaign. + +## `campaign_info` + +Spews information about the current campaign into the console. + +## `campaign_list` + +Lists all campaigns detected by P2:CE to the console. + +## `campaign_clear` + +Clears the currently active campaign. + +## `campaign_continue` + +Continue a campaign from the latest save. Usage: `campaign_continue [campaign_id]`. + +## `campaign_level_next` + +Changes the map to the next level in the campaign, if it exists. + +## `campaign_level_prev` + +Changes the map to the previous level in the campaign, if it exists. + +## `campaign_savedata_reset` + +Wipes all save data relating to campaign progression. Does not delete saved game files. + +## `campaign_savedata_show` + +Display save data relating to campaign progression. + +## `campaign_set_active` + +Set a specified campaign as active. Usage: `campaign_set_active [campaign_id]` + +## `campaign_start` + +Starts a specified campaign at a certain chapter. Usage: `campaign_start [campaign_id] [chapter_index]` + +## `startupmenu` + +Enters the appropriate background map as detailed by the campaign script. + +# Useful Cvars + +## `campaign_debug` + +If value is 1, prints additional debugging information to the console in relation to the campaign system. + +## `campaign_default` + +Sets the default campaign to boot into on startup. The background map will be entered automatically without intervention by a script. + +# Useful Launch Options + +## `-unlockchapters` + +Treats all campaigns as completely unlocked for testing. This does not make any changes to the progression save. Must be used in conjunction with the `-dev` launch option. + +## `-nochapterprogress` + +Treats all campaigns as completely locked for testing. This does not make any changes to the progression save. Must be used in conjunction with the `-dev` launch option. \ No newline at end of file diff --git a/docs/modding/p2ce-campaigns/getting-started.md b/docs/modding/p2ce-campaigns/getting-started.md new file mode 100644 index 00000000..770377dd --- /dev/null +++ b/docs/modding/p2ce-campaigns/getting-started.md @@ -0,0 +1,137 @@ +--- +title: Getting Started +features: + - USE_CAMPAIGNMANAGER +--- + +# Getting Started with P2:CE Campaigns + +![Campaign Selection UI](images/campaign-selection-screen.webp) + +P2:CE includes the ability for sourcemods, mappers, and addon authors to create custom campaigns. These custom campaigns can then be published to the Steam Workshop. A campaign refers to an organized bundle of maps, which could be tightly related (such as story-based campaigns) or have no relation at all (map/competition packs). + +P2:CE's campaign system is the primary form of user created playable content. Standalone maps are still available, but are folded into a "P2:CE Workshop" campaign as a playlist. + +# Creation + +A campaign addon is much like a standard addon. It will contain all required assets, and optionally link to other external dependencies on the Steam Workshop. Campaign addons ship with additional image assets that the game's menu will use in various locations. + +To begin, [create a new addon](/modding/workshop/workshopgui) and include all required content. Next, create a `campaigns.kv3` file within the `scripts` folder of the addon. This will define the campaign to the game. + +Each campaign has a subset of metadata that all dictate your how your chapters are ordered and unlocked, and what art assets are used. The campaign script is a KeyValue3 file, structured in the following way: + +> [!NOTE] +> This snippet is not valid syntax and will not work in P2:CE! + +``` +{ + meta = { + (asset information) + } + "campaigns" = { + "CAMPAIGN_ID" = { + title = (string) + unlock_all = (boolean) + meta = { + (overrides) + } + chapters = [ + // chapter block + { + title = (string) + save_comment = (string) + meta = { + (overrides) + } + maps = [ + // map entry + { + name=(string) + meta = { + (overrides) + } + } + ] + }, + // etc. + ] + } + } +} +``` +In order: +- `meta`, a block that details information for P2:CE to use in its menu presentation and loading screens. + - Meta keys are unique to the respective mod and it is up to the menu script to recognize and use them. + - Meta blocks can exist at the Root/Campaign/Chapter/Map level. Priority is established in reverse order. + - Matching fields inside the meta block will override based on this priority. For example, `background_map` specified at the chapter level overrides that field at the campaign or root level. + - Full meta keys for P2:CE are described in the [Full Script Reference](/modding/p2ce-campaigns/script-reference#meta-keys) page. +- `campaigns`, top-level block that groups all campaigns provided by the addon together. +- `CAMPAIGN_ID`, an internal name to refer to the campaign by. +- `title`, a human readable name for the campaign/chapter. This string will be localized if a token is set. +- `unlock_all`, should all chapters be unlocked to start with? +- `chapters`, an array containing blocks that describe each chapter. + - `save_comment`, optional field that sets the save comment for saves created at the belonging chapter. + - `maps`, an array containing blocks that describe each map. + - Each map must specify the `name` field. + +Fill in as much information as possible in the above snippet, or copy the sample from the [Full Script Reference](/modding/p2ce-campaigns/script-reference#ideal-meta-locations) page. + +Duplicate the chapter block for each individual chapter. Duplicate the map block inside the `maps` array for every map that belongs to that chapter. + +For example: +``` +chapters = [ + // chapter block + { + title = "My Cool Chapter 1" + maps = [ + // map entry + { name="sp_a1_intro1" }, + { name="sp_a1_intro2" }, + // comma on the last entry in an array is valid syntax + { name="sp_a1_intro3" }, + ] + }, + { + title = "My Cool Chapter 2" + maps = [ + // map entry + { name="sp_a1_intro4" }, + ] + }, +] +``` + +If you are having trouble placing meta keys, or want a script to copy and paste, see the [Full Script Reference](/modding/p2ce-campaigns/script-reference#ideal-meta-locations) page. + +Once the campaign script has been created with the necessary information, it can be found in the campaign selector. + +The bare minimum script to have a campaign appear on the selector can be found below: +``` +{ + "campaigns" = { + "[CAMPAIGN_ID]" = { + } + } +} +``` +Required art assets will be replaced with one of several fallback images if they are not found. Art assets that are optional will instead be hidden from the UI. Consult the [Full Script Reference](/modding/p2ce-campaigns/script-reference#meta-keys) for information on which assets are optional, and art asset guidelines. + +![Selector & Fallback UI](images/campaign-minimum.webp) + +**All art assets must reside in the `.assets` subfolder in the respective addon. The game will not find the art assets if they are in another location.** + +# Example Campaign Files + +P2:CE ships with local addons to play Portal 2, Portal 1, and Half-Life 2 (including its episodes). These addons can be found [here](https://github.com/StrataSource/p2ce-addons/tree/feat/campaign-tests). + +# Campaign Progression + +Campaigns have their progression information saved inside `SAVE/campaign_save_data.kv3`. This file can be erased using the `campaign_savedata_reset` command. Campaign progression is currently tracked by chapter & map number. + +# Developing a Sourcemod? + +P2:CE and its menu system was designed as a gateway to sourcemods/standalone games. If a default campaign is specified (cvar: `campaign_default`), the game will use that campaign as the base menu state instead of the standard P2:CE menu. This can be helpful for mods that cannot or do not want to create a custom menu system (or simply as a starting platform while developing the mod). + +> [!NOTE] +> **There are extra considerations to take when developing a menu script that leverages the campaign system. Full details can be found on [the Technical Notes page](/modding/p2ce-campaigns/technical-notes).** diff --git a/docs/modding/p2ce-campaigns/images/button-guideline.png b/docs/modding/p2ce-campaigns/images/button-guideline.png new file mode 100644 index 00000000..1e0870f3 Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/button-guideline.png differ diff --git a/docs/modding/p2ce-campaigns/images/campaign-boxart.webp b/docs/modding/p2ce-campaigns/images/campaign-boxart.webp new file mode 100644 index 00000000..a3f563a0 Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/campaign-boxart.webp differ diff --git a/docs/modding/p2ce-campaigns/images/campaign-button-legend.webp b/docs/modding/p2ce-campaigns/images/campaign-button-legend.webp new file mode 100644 index 00000000..353962e4 Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/campaign-button-legend.webp differ diff --git a/docs/modding/p2ce-campaigns/images/campaign-full-logo.webp b/docs/modding/p2ce-campaigns/images/campaign-full-logo.webp new file mode 100644 index 00000000..ccba646f Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/campaign-full-logo.webp differ diff --git a/docs/modding/p2ce-campaigns/images/campaign-logo.webp b/docs/modding/p2ce-campaigns/images/campaign-logo.webp new file mode 100644 index 00000000..cd638579 Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/campaign-logo.webp differ diff --git a/docs/modding/p2ce-campaigns/images/campaign-minimum.webp b/docs/modding/p2ce-campaigns/images/campaign-minimum.webp new file mode 100644 index 00000000..a0f6c29b Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/campaign-minimum.webp differ diff --git a/docs/modding/p2ce-campaigns/images/campaign-selection-screen.webp b/docs/modding/p2ce-campaigns/images/campaign-selection-screen.webp new file mode 100644 index 00000000..38466870 Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/campaign-selection-screen.webp differ diff --git a/docs/modding/p2ce-campaigns/images/chapter-modes.webp b/docs/modding/p2ce-campaigns/images/chapter-modes.webp new file mode 100644 index 00000000..427a9fda Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/chapter-modes.webp differ diff --git a/docs/modding/p2ce-campaigns/images/loading_a.webp b/docs/modding/p2ce-campaigns/images/loading_a.webp new file mode 100644 index 00000000..c81d1222 Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/loading_a.webp differ diff --git a/docs/modding/p2ce-campaigns/images/loading_b.webp b/docs/modding/p2ce-campaigns/images/loading_b.webp new file mode 100644 index 00000000..cf5c65e8 Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/loading_b.webp differ diff --git a/docs/modding/p2ce-campaigns/images/map-selector.webp b/docs/modding/p2ce-campaigns/images/map-selector.webp new file mode 100644 index 00000000..3a5e27bb Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/map-selector.webp differ diff --git a/docs/modding/p2ce-campaigns/images/map-thumbs.webp b/docs/modding/p2ce-campaigns/images/map-thumbs.webp new file mode 100644 index 00000000..2f56043e Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/map-thumbs.webp differ diff --git a/docs/modding/p2ce-campaigns/images/save-image-guideline.png b/docs/modding/p2ce-campaigns/images/save-image-guideline.png new file mode 100644 index 00000000..27dd4929 Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/save-image-guideline.png differ diff --git a/docs/modding/p2ce-campaigns/images/saves-list.webp b/docs/modding/p2ce-campaigns/images/saves-list.webp new file mode 100644 index 00000000..2a149dc3 Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/saves-list.webp differ diff --git a/docs/modding/p2ce-campaigns/images/spinner.webp b/docs/modding/p2ce-campaigns/images/spinner.webp new file mode 100644 index 00000000..619f6ee3 Binary files /dev/null and b/docs/modding/p2ce-campaigns/images/spinner.webp differ diff --git a/docs/modding/p2ce-campaigns/meta.json b/docs/modding/p2ce-campaigns/meta.json new file mode 100644 index 00000000..7e3372da --- /dev/null +++ b/docs/modding/p2ce-campaigns/meta.json @@ -0,0 +1,3 @@ +{ + "title": "P2:CE Campaigns" +} diff --git a/docs/modding/p2ce-campaigns/script-reference.md b/docs/modding/p2ce-campaigns/script-reference.md new file mode 100644 index 00000000..857d6856 --- /dev/null +++ b/docs/modding/p2ce-campaigns/script-reference.md @@ -0,0 +1,336 @@ +--- +title: Full Script Reference +features: + - USE_CAMPAIGNMANAGER +--- + +# Full Campaign Script Reference + +> [!TIP] +> **SEE ALSO:** [Bundled Campaign Scripts for Portal 1, Portal 2 & Half-Life 2](https://github.com/StrataSource/p2ce-addons/tree/feat/campaign-tests) + +# Setup +Script must exist in `scripts/campaigns.kv3` to be loaded. The file's format is KeyValues 3. This file contains a root block that then has an optional `"meta"` block, and a required `"campaigns"` block, in which every campaign will live, using a string as the ID. + +# Ideal Meta Locations + +The following is a baseline snippet of ideal meta key locations. Note that keys pointing to asset paths should be filled in and the existence of these will result in placeholder assets being used instead. +``` +{ + meta = { + author = "Author" + } + campaigns = { + "campaign_1" = { + title = "Campaign 1 Title" + unlock_all = false + meta = { + desc = "Campaign 1 Description" + box_art = "" + selector_cover = "" + selector_button_background = "" + square_logo = "" + full_logo = "" + chapter_display_mode = "list" + loading_square_logo_padding = "0" + } + chapters = [ + // copy the below block for every chapter that should be a part of this campaign + { + title = "Campaign 1 Chapter 1 Title" + save_comment = "" + maps = [ + // copy the below line for every map that should belong in this chapter + {name="campaign_1_map" meta={ title="Map 1 Title" img="" }}, + ] + meta = { + thumbnail = "" + background_map = "" + background_movie = "" + background_music = "" + loading_screen = "" + transition_screen = "" + } + } + ] + } + } +} +``` + +# Campaign Level Keys + +| Key | Type | Details | +| --- | ---- | ------- | +| `title` | string | Human readable string that will be localized if a token is provided. This is the name of the campaign. | +| `unlock_all` | boolean | (OPTIONAL, DEFAULT: FALSE) Determines if all chapters are unlocked and no unlock state should be tracked.| +| `meta` | block | (OPTIONAL) Block that describes art/background assets to P2:CE's menus. These values apply to all chapters/maps unless overridden. | +| `chapters` | array | Array of chapter blocks. | + +# Chapter Level Keys + +| Key | Type | Details | +| --- | ---- | ------- | +| `title` | string | Human readable string that will be localized if a token is provided. This is the name of the chapter. | +| `save_comment` | string | (OPTIONAL) Appended string to save files. | +| `meta` | block | (OPTIONAL) Overrides fields in the campaign's meta block. These values apply to all maps unless overridden. | +| `maps` | array | Array of chapter blocks. | + +# Map Level Keys + +| Key | Type | Details | +| --- | ---- | ------- | +| `name` | string | The map filename, without the `.bsp` extension. | +| `meta` | block | (OPTIONAL) Override values in the chapter and campaign `meta` blocks. [This block has unique keys.](#maps) | + +# Meta Keys + +> [!WARNING] +> Meta level keys are unique to P2:CE's menu implementation. Changing the UI scripts will lose what these keys provide, unless they are reimplemented. See P2:CE's [Panorama code](https://github.com/StrataSource/p2ce-panorama-ui) to see how these meta keys are implemented, and see the [Technical Details](/modding/p2ce-campaigns/technical-notes) page for more information. + +Most meta keys define art assets which are used in various locations/stretch to certain sizes. Some detail may be cropped. If you use non-standard ratios or something the UI is not expecting, it may not display properly. + +Optional keys are marked **(OPTIONAL)**. In the absence of this tag, it is either strongly recommended or required (and would result in a fallback image being used). + +**All art assets must reside in the `.assets` subfolder in the respective addon. The game will not find the art assets if they are in another location.** + +> [!WARNING] +> **ALL META KEYS ARE STRINGS, NO EXCEPTIONS.** + +## Campaign Selector + +> [!NOTE] +> Some of these assets and their specifications are derived from the [Steamworks Partner game asset requirements](https://partner.steamgames.com/doc/store/assets/libraryassets). These requirements were chosen to allow campaign authors to easily migrate their work to a standalone Steam mod at any time if they so choose. + +![Campaign Button Legend](images/campaign-button-legend.webp) + +### (1) `selector_cover` + +Recommended resolution: 920x430 (or aspect ratio equivalent) + +Path to the image to use, including the file extension. This path is relative to the addon's `.assets` directory. + +### (2) `author` + +**(OPTIONAL)** + +The name to display in the campaign selector, which will get localized if provided a token. This will override the addon author, if it can be retrieved. If no author is specified and it cannot be retrieved, it will be hidden from the UI. + +### (3) `desc` + +**(OPTIONAL)** + +Optional description to display in the campaign selector, which will get localized if provided a token. + +### (4) `selector_button_background` + +**(OPTIONAL)** + +Path to the image to use, including the file extension. This path is relative to the addon's `.assets` directory. + +Resolution: 1920x620 (or aspect ratio equivalent) + +This image will be sized to cover a region of the button. Upper and lower portions may be clipped. Important elements should be as close to the center vertically as much as possible. + +![Selector Button Background Guideline](images/button-guideline.png) + +### `box_art` + +Path to the image to use, including the file extension. This path is relative to the addon's `.assets` directory. + +Resolution: 600x900 (or aspect ratio equivalent) + +This image will be sized to fit this aspect ratio. + +![Boxart Example](images/campaign-boxart.webp) + +## Menu + +### `square_logo` + +**(OPTIONAL)** + +Path to the image to use, including the file extension. This path is relative to the addon's `.assets` directory. + +Recommended resolution: 256x256 (or aspect ratio equivalent) + +`.svg` file format recommended. All official logos are provided in this format. + +Used in loading screen and main menu. + +This logo is used in the main menu and appears when the user hovers over the resume button. If this image is not an `.svg`, it will not appear. + +This sample has the logo as Bendy, appearing behind the menu. +![Logo Example](images/campaign-logo.webp) + +![Spinner Example](images/spinner.webp) + +### `background_map` + +The background map to load into while on the menu when the player has progressed into the point where this field is defined (usually a chapter block). This normally takes priority over `background_movie` or `background_image`. If the user has disabled background map loading, `background_movie` or `background_image` is used as a fallback. + +### `background_movie` + +Path to the video to use, including the file extension. + +Resolution: 1920x1080 (or aspect ratio equivalent) + +The movie to play on the menu when the player has progressed into the point where this field is defined (usually a chapter block). This takes priority over `background_image`. + +### `background_image` + +> [!NOTE] +> **This field is the final resort. If none of the prior `background_` asset fields are specified and this asset does not exist or fails to load, a fallback image will be used instead.** + +Path to the image to use, including the file extension. This path is relative to the addon's `.assets` directory. + +Resolution: 1920x1080 (or aspect ratio equivalent) + +The image to display on the menu when the player has progressed into the point where this field is defined (usually a chapter block). + +This image will be sized to cover the entire screen as the background. + +### `background_music` + +**(OPTIONAL)** + +The music to play on the menu. This must be a soundscript entry and **cannot** be a raw sound reference. If this field is specified, it will play regardless of which `background_` asset is used on the menu. + +### `full_logo` + +**(OPTIONAL, HIDES LOGO IF NOT SPECIFIED)** + +Path to the image to use, including the file extension. This path is relative to the addon's `.assets` directory. + +Also used in main menu. + +This image will be sized to fit on the main menu. Any resolution/ratio can be used and should appear fine. Currently, the full logo will be constrainted to center fit inside a 540x130 pixel frame. + +All official logos are provided in `.svg` format. + +![Full Logo Example](images/campaign-full-logo.webp) + +## Chapter Selection + +### `chapter_display_mode` + +**(OPTIONAL, DEFAULT: "LIST")** + +![Chapter Modes Display](images/chapter-modes.webp) + +The display mode when the player enters the chapter selection screen. + +Valid values are: +- `classic` (traditional VGUI film strip with 3 chapters displayed per page) +- `super` (singular massive tile) +- `list` (default) +- `grid` (ideal for map packs) + +### `thumbnail` + +Resolution: 1920x1080 (or aspect ratio equivalent) + +Path to the image to use, including the file extension. This path is relative to the addon's `.assets` directory. + +Chapter thumbnail predominantly used in the chapter selection screen, but also appears in the saves menu. + +This image will be sized to fit for chapter selection entries. However, in the saves menu, this image will be sized to cover a region of the save button. Some parts of the image may be clipped in that regard. + +![Saves List](images/saves-list.webp) + +![Saves List Guideline](images/save-image-guideline.png) + +## Loading Screens + +### `loading_screen` + +**(OPTIONAL, DEFAULTS TO BLACK SCREEN IF NOT SPECIFIED)** + +Path to the image to use, including the file extension. This path is relative to the addon's `.assets` directory. + +Resolution: 1920x1080 (or aspect ratio equivalent) + +The image to use when the player is loading into a map from the main menu. + +This image will be sized to cover the entire screen as the background. + +### `transition_screen` + +**(OPTIONAL, DEFAULTS TO BLACK SCREEN IF NOT SPECIFIED)** + +Path to the image to use, including the file extension. This path is relative to the addon's `.assets` directory. + +Resolution: 1920x1080 (or aspect ratio equivalent) + +The image to use when the player is transitioning to a map from a previous one. + +This image will be sized to cover the entire screen as the background. + +### Loading/Transition Screen Considerations +> [!WARNING] +> **PLEASE READ THE FOLLOWING SECTION CAREFULLY.** + +P2:CE's loading screen is derived from Portal 2's where there are multiple images faded on top of each other based on loading progress. Additionally, it has two different loading screens, one for loading into a map from the menu (`loading_screen`), and another for transitioning between maps (`transition_screen`). In P2:CE specifically, the number of assets to provide is two, and the second image is faded in after the loading progress exceeds 50%. To facilitate this, `loading_screen` and `transition_screen` paths are treated specially. + +The campaign script specifies the asset name prefix and image extension, while the UI script adds a numeric suffix to the information provided. If a field is not specified, the background will be a solid black color. If a field is specified and the second asset the UI searches for does not exist, a fallback image will be used. + +![Loading Example 1](images/loading_a.webp) +![Loading Example 2](images/loading_b.webp) + +**Example:** + +Suppose that loading screen assets are defined as such within a meta block: +``` +meta = { + loading_screen="loading_screen.png" + transition_screen="transition_screen.png" +} +``` + +In the UI, these would then be translated into: +``` +loading_screens = [ + "[ADDON PATH]/.assets/loading_screen_1.png", + "[ADDON PATH]/.assets/loading_screen_2.png" +] +transition_screens = [ + "[ADDON PATH]/.assets/transition_screen_1.png", + "[ADDON PATH]/.assets/transition_screen_2.png" +] +``` +**(Note that this does not represent the actual campaign information as laid out in memory or by the campaign system, this is an example for human readability)** + +### `loading_square_logo_padding` + +**(OPTIONAL, APPLIES NO PADDING IF NOT SPECIFIED)** + +The padding to give to the logo in the spinner that appears in the loading screen to help fit it inside better. This is used for Half-Life 2's campaign script. + +While this is a string, the value given must be a whole non-negative number. + +## Maps + +> [!NOTE] +> The following keys are for meta blocks within a map block. These keys are not used anywhere else. +> +> ``` +> maps = [ +> { name = "cool_map" meta = { title = "My Awesome Map", img = "cool_map.png" } } +> ] +> ``` + +### `title` + +**(OPTIONAL)** + +Human-readable name for this map, used in the map selector. If not specified, the map selector will use the map's name. + +![Map Selector](images/map-selector.webp) + +### `img` + +**(OPTIONAL)** + +Map thumbnail asset path, used in the map selector. If this field is not specified in *any* map in the current chapter block, the asset will not appear. If there is at least one `img` field specified, the map selector turns into a grid layout and displays images for all maps (even if a map does not define one). + +![Map Selector](images/map-thumbs.webp) diff --git a/docs/modding/p2ce-campaigns/technical-notes.md b/docs/modding/p2ce-campaigns/technical-notes.md new file mode 100644 index 00000000..d6501e20 --- /dev/null +++ b/docs/modding/p2ce-campaigns/technical-notes.md @@ -0,0 +1,78 @@ +--- +title: Technical Notes +features: + - USE_CAMPAIGNMANAGER +--- + +# Technical Notes + +> [!NOTE] +> This article includes technical notes, relevant to users developing sourcemods, with the intent of rolling their own UI script code. + +# Reusing P2:CE's UI + +P2:CE's UI code was designed to be initially reused by sourcemods in the event that you cannot or do not want to roll your own UI script code. If the `campaign_default` convar is specified in `cfg/cvar_defaults.cfg`, the game will enter the campaign menu and use it as the base menu, meaning that the player cannot exit to the P2:CE's default menu. It will work with the campaign system and you can focus your efforts elsewhere until you decide to write your own menus. + +# Campaign Progression + +Campaigns have their progression information saved inside `SAVE/campaign_save_data.kv3`. This file can be erased using the `campaign_savedata_reset` command. Campaign progression is currently tracked by chapter & map number. + +# Meta Keys + +The meta block found in the campaign script is a generic block internally. The engine does not define the fields that this Wiki documents. Instead, these keys are required by P2:CE's Panorama UI code. + +In TypeScript, the meta block is represented as a `Map`, and keys are retrieved using `meta.get('key')`. If you roll your own UI code with no intention of reusing P2:CE's scripts, **none** of the meta keys (and subsequently the art asset specifications) documented by the Wiki will apply to your code. You **MUST** reimplement these keys and use them where you see fit. However, this also means that if you have other use cases for your Sourcemod, you can add keys yourself! + +> [!WARNING] +> Meta blocks cannot have blocks nested inside. Do not attempt to do so if you are implementing a custom menu script. + +# Campaign Value Fixup + +> [!NOTE] +> **This applies to all campaign script values, but predominantly the meta values.** + +When requesting a value from the campaign system, be it a chapter title, map name, or meta value (e.g. author, chapter display mode), it will return *exactly* what is specified by the script. There is no fixup for any value by the engine internally (excluding sanitization). + +For example, take the following campaign script snippet: +``` +{ + campaigns = { + "portal2_sp" = { + title = "#MainMenu_Campaigns_portal2" + meta = { + author = "#MainMenu_Campaigns_Valve_Author" + desc = "#MainMenu_Campaigns_portal2_Description" + box_art = "{campaign_art}/portal2/boxart.png" + } + } + } +} +``` + +The reference guide postulates that the `title` key will be localized if the value is a valid localization token. While this is true for P2:CE proper, **this is not the case for custom UI code.** P2:CE's UI code localizes the `title` value by itself, which is frontend functionality **and is not provided by the engine.** This means that if you were to write your own UI code and retrieve the `title` key, you would get `#MainMenu_Campaigns_portal2` returned to you, **not** the localized string. For any value that needs fixup, that functionality must be reimplemented by your sourcemod's UI code. + +**This is especially important for any value that provides an image asset path.** + +To reduce friction of creating campaign scripts, P2:CE's UI code will build asset paths for campaign authors. The UI code builds a path for an addon like this: `file://[addon path]/.assets/[asset value in script]` (except for movie assets). Like the example prior, if you write your own UI code, you will have to reimplement this functionality yourself to what you expect, or write paths in the campaign script values themselves. + +Campaigns bundled with the game itself (and **not** as a local addon) will refer to asset paths using `{named_paths}`. The above snippet uses this for `box_art`. This is a shorthand for asset paths in Panorama and these named paths are defined in `panorama/panorama.cfg`. + +# API Documentation + +Full documentation of the Campaigns API and interfacing it with Panorama can be found in the Panorama Types repository, located [here](https://github.com/StrataSource/pano-typed). + +# Campaign Bucketing + +Internally, campaigns are organized via buckets, where a bucket denotes the source of the campaign. This helps avoid ID string conflicts. The `campaign_list` console command will display campaigns and their respective buckets. + +The following buckets are used: + +- `base`: This bucket represents campaigns found within the game's `script/campaigns.kv3` file, the folder in which `gameinfo.txt` resides. +- `addon:[ADDON_FOLDER]`: This bucket represents campaigns found within a local addon. A separate bucket is created for each local addon. +- `workshop:[WORKSHOP_ID]`: This bucket represents campaigns found within an addon from the Steam Workshop. A separate bucket is created for each Workshop addon. + +When you reference an addon through an API, the ideal method is to make a full reference, created as: `[BUCKET_ID]/[CAMPAIGN_ID]`. + +For example, for the Portal 1 campaign, which is a locally shipped addon: `addon:portal1_sp/portal1_sp`. + +For a campaign shipped in the base game's files: `base/my_cool_campaign` *(This is probably what you will use a lot if you need to interface with the Campaigns API and you are rolling your own UI)*