From d3e1a42539de7d572f28a0971671be1101ff3182 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Fri, 20 Sep 2024 15:06:33 +0200 Subject: [PATCH] Fix indentation in codeblocks --- docs/Modding/guides/gettingstarted.md | 166 ++++---- .../guides/keyvalue/crosshairmodding.md | 78 ++-- docs/Modding/guides/keyvalue/localisation.md | 38 +- docs/Modding/guides/publishing.md | 10 +- .../guides/reversing/squirrelreversing.md | 74 ++-- docs/Modding/guides/scripting/custommenus.md | 400 +++++++++--------- docs/Modding/guides/scripting/gamemodemods.md | 330 +++++++-------- docs/Modding/guides/tools/BIKVideoModding.md | 8 +- docs/Modding/guides/tools/MDLModding.md | 30 +- docs/Modding/guides/tools/VTFModding.md | 86 ++-- docs/Modding/guides/tools/rpakmodding.md | 72 ++-- docs/Modding/guides/tools/soundmodding.md | 82 ++-- docs/Modding/plugins/interfacesapi.md | 98 ++--- docs/Modding/reference/northstar/chathooks.md | 180 ++++---- .../northstar/customdamagesources.md | 62 +-- .../northstar/dependencyconstants.md | 42 +- .../reference/northstar/httprequests.md | 74 ++-- .../reference/northstar/modsettings.md | 14 +- .../reference/northstar/serversiderui.md | 72 ++-- .../reference/northstar/usefulfuncs.md | 12 +- .../reference/respawn/clientcommands.md | 8 +- docs/Modding/reference/respawn/dialog.md | 40 +- .../reference/respawn/hud_element_notation.md | 152 +++---- docs/Modding/reference/respawn/hud_menus.md | 50 +-- docs/Modding/reference/respawn/movers.md | 84 ++-- .../respawn/native_server/damageinfo.md | 46 +- .../reference/respawn/native_server/netvar.md | 20 +- docs/Modding/reference/respawn/rui.md | 148 +++---- docs/Modding/reference/respawn/titan.md | 4 +- docs/Modding/reference/respawn/topology.md | 94 ++-- docs/Modding/repak/assets/datatable.md | 8 +- docs/Modding/repak/assets/texture.md | 20 +- docs/Modding/repak/assets/uiatlas.md | 138 +++--- docs/Modding/repak/map.md | 140 +++--- docs/Modding/squirrel/async.md | 198 ++++----- docs/Modding/squirrel/class.md | 276 ++++++------ .../squirrel/cpp_api/objecthandling.md | 44 +- .../squirrel/cpp_api/objectmanipulation.md | 102 ++--- docs/Modding/squirrel/cpp_api/sq_functions.md | 96 ++--- docs/Modding/squirrel/functions.md | 80 ++-- docs/Modding/squirrel/intro.md | 52 +-- docs/Modding/squirrel/networking.md | 158 +++---- docs/Modding/squirrel/statements.md | 84 ++-- .../squirrel/statements/controlflow.md | 2 +- docs/Modding/squirrel/types/arrays.md | 50 +-- docs/Modding/squirrel/types/entities.md | 6 +- docs/Modding/squirrel/types/functionrefs.md | 6 +- docs/Modding/squirrel/types/ornull.md | 12 +- docs/Modding/squirrel/types/structs.md | 62 +-- docs/Modding/squirrel/types/tables.md | 12 +- 50 files changed, 2060 insertions(+), 2060 deletions(-) diff --git a/docs/Modding/guides/gettingstarted.md b/docs/Modding/guides/gettingstarted.md index 91a5f229..15717a0d 100644 --- a/docs/Modding/guides/gettingstarted.md +++ b/docs/Modding/guides/gettingstarted.md @@ -31,15 +31,15 @@ Provided is a template `mod.json`, for a detailed list of values read the `cheatsheet` ```json - { - "Name": "Yourname.Modname", - "Description": "Woo yeah wooo!", - - "LoadPriority": 0, - "ConVars": [], - "Scripts": [], - "Localisation": [] - } +{ + "Name": "Yourname.Modname", + "Description": "Woo yeah wooo!", + + "LoadPriority": 0, + "ConVars": [], + "Scripts": [], + "Localisation": [] +} ``` Inside the `mod` folder, existing files found in the engine's virtual file system will @@ -48,24 +48,24 @@ be overwritten and new files can be added. If you need to define new Squirrel fi example for this might be: ```json - "Scripts": [ - { - "Path": "path/to/file.nut", - "RunOn": "( CLIENT || SERVER ) && MP" - }, - { - "Path": "path/to/another_file.nut", - "RunOn": "( CLIENT || SERVER ) && MP", - "ClientCallback": { - "Before": "ClientPreMapspawnThing", - "After": "AfterMapspawnClientThing" - }, - "ServerCallback": { - "Before": "ServerPreMapspawncrap", - "After": "ServerAfterMapspawnWoo" - } - } - ] +"Scripts": [ + { + "Path": "path/to/file.nut", + "RunOn": "( CLIENT || SERVER ) && MP" + }, + { + "Path": "path/to/another_file.nut", + "RunOn": "( CLIENT || SERVER ) && MP", + "ClientCallback": { + "Before": "ClientPreMapspawnThing", + "After": "AfterMapspawnClientThing" + }, + "ServerCallback": { + "Before": "ServerPreMapspawncrap", + "After": "ServerAfterMapspawnWoo" + } + } +] ``` `"Path"` indicates where the script is, `"RunOn"` is the Squirrel VM context (see @@ -85,35 +85,35 @@ This guide will dig into each of the possible `mod.json` fields. Please note tha This is what a well-formatted `mod.json` looks like: ```json - { - "Name": "Northstar.CustomServers", - "Description": "Attempts to recreate the behaviour of vanilla Titanfall 2 servers, as well as changing some scripts to allow better support for mods", - "Version": "1.5.0", - "LoadPriority": 0, - "ConVars": [ - { - "Name": "ns_private_match_last_mode", - "DefaultValue": "tdm" - }, - { - "Name": "ns_private_match_last_map", - "DefaultValue": "mp_forwardbase_kodai" - } - ], - "Scripts": [ - { - "Path": "sh_northstar_utils.gnut", - "RunOn": "CLIENT || SERVER || UI" - }, - { - "Path": "mp/_classic_mp_dropship_intro.gnut", - "RunOn": "SERVER && MP" - } - ], - "Localisation": [ - "resource/northstar_custom_%language%.txt" - ] - } +{ + "Name": "Northstar.CustomServers", + "Description": "Attempts to recreate the behaviour of vanilla Titanfall 2 servers, as well as changing some scripts to allow better support for mods", + "Version": "1.5.0", + "LoadPriority": 0, + "ConVars": [ + { + "Name": "ns_private_match_last_mode", + "DefaultValue": "tdm" + }, + { + "Name": "ns_private_match_last_map", + "DefaultValue": "mp_forwardbase_kodai" + } + ], + "Scripts": [ + { + "Path": "sh_northstar_utils.gnut", + "RunOn": "CLIENT || SERVER || UI" + }, + { + "Path": "mp/_classic_mp_dropship_intro.gnut", + "RunOn": "SERVER && MP" + } + ], + "Localisation": [ + "resource/northstar_custom_%language%.txt" + ] +} ``` !!! note @@ -171,14 +171,14 @@ If I don't want to wait 15 seconds for matches to start on my server, `ns_private_match_countdown_length` in its `mod.json` manifesto: ```json - "ConVars": [ - { - "Name": "ns_private_match_countdown_length", - "DefaultValue": "15" - }, +"ConVars": [ + { + "Name": "ns_private_match_countdown_length", + "DefaultValue": "15" + }, - ... - ] + ... +] ``` I can setup the `ns_private_match_countdown_length` variable in my @@ -189,8 +189,8 @@ When starting a match, `Northstar.CustomServers` mod will retrieve the configura variable value, or its default value if it hasn't been specified in configuration file: ```squirrel - // start countdown - SetUIVar( level, "gameStartTime", Time() + GetConVarFloat( "ns_private_match_countdown_length" ) ) +// start countdown +SetUIVar( level, "gameStartTime", Time() + GetConVarFloat( "ns_private_match_countdown_length" ) ) ``` !!! note @@ -247,24 +247,24 @@ The scripts field lets you declare an array of Squirrel files to import into you Each script entry must have a "Path" value and a "RunOn" value. ```json - "Scripts": [ - { - "Path": "path/to/file.nut", - "RunOn": "( CLIENT || SERVER ) && MP" - }, - { - "Path": "path/to/another_file.nut", - "RunOn": "( CLIENT || SERVER ) && MP", - "ClientCallback": { - "Before": "ClientPreMapspawnThing", - "After": "AfterMapspawnClientThing" - }, - "ServerCallback": { - "Before": "ServerPreMapspawncrap", - "After": "ServerAfterMapspawnWoo" - } - } - ] +"Scripts": [ + { + "Path": "path/to/file.nut", + "RunOn": "( CLIENT || SERVER ) && MP" + }, + { + "Path": "path/to/another_file.nut", + "RunOn": "( CLIENT || SERVER ) && MP", + "ClientCallback": { + "Before": "ClientPreMapspawnThing", + "After": "AfterMapspawnClientThing" + }, + "ServerCallback": { + "Before": "ServerPreMapspawncrap", + "After": "ServerAfterMapspawnWoo" + } + } +] ``` #### Path diff --git a/docs/Modding/guides/keyvalue/crosshairmodding.md b/docs/Modding/guides/keyvalue/crosshairmodding.md index 42fe4441..43b5bf0a 100644 --- a/docs/Modding/guides/keyvalue/crosshairmodding.md +++ b/docs/Modding/guides/keyvalue/crosshairmodding.md @@ -13,14 +13,14 @@ Example Mod: ``` WeaponData { - RUI_CrosshairData + RUI_CrosshairData + { + Crosshair_1 { - Crosshair_1 - { - "ui" "ui/crosshair_alternator" - } + "ui" "ui/crosshair_alternator" } } + } ``` 3: change "ui/crosshair_alternator" to your desired crosshair @@ -34,22 +34,22 @@ Weapons].txt into one** ``` - WeaponData - { - active_crosshair_count "2" //Amount of crosshairs you want to use +WeaponData +{ + active_crosshair_count "2" //Amount of crosshairs you want to use - RUI_CrosshairData - { - Crosshair_1 - { - "ui" "ui/crosshair_alternator" - } - Crosshair_2 - { - "ui" "ui/crosshair_tri" - } - } - } + RUI_CrosshairData + { + Crosshair_1 + { + "ui" "ui/crosshair_alternator" + } + Crosshair_2 + { + "ui" "ui/crosshair_tri" + } + } +} ``` **To add more crosshairs add another Crosshair\_\ X following the @@ -69,16 +69,16 @@ Simply add the following line below the "ui" line Below the "ui" line, Like this: ``` +{ + RUI_CrosshairData { - RUI_CrosshairData - { - Crosshair_1 - { - "ui" "ui/crosshair_alternator" //THis is the Croshair - "base_spread" "3.0" //This is a spread Multiplier, Line doesn't exist by default - } - } - } + Crosshair_1 + { + "ui" "ui/crosshair_alternator" //THis is the Croshair + "base_spread" "3.0" //This is a spread Multiplier, Line doesn't exist by default + } + } +} ``` * This only affects the visual spread of the crosshair, not the actual bullet spread. Positive Values increase spread while negative decrease it. By default it is based on the weapon's own stats. @@ -86,16 +86,16 @@ Below the "ui" line, Like this: ## No Crosshair? ``` - WeaponData - { - RUI_CrosshairData - { - Crosshair_1 - { - "ui" "ui/crosshair_sniper_amped" //This means NO crosshair - } - } - } +WeaponData + { + RUI_CrosshairData + { + Crosshair_1 + { + "ui" "ui/crosshair_sniper_amped" //This means NO crosshair + } + } +} ``` ## Crosshair Index: diff --git a/docs/Modding/guides/keyvalue/localisation.md b/docs/Modding/guides/keyvalue/localisation.md index 4ae85e2b..afaa19f5 100644 --- a/docs/Modding/guides/keyvalue/localisation.md +++ b/docs/Modding/guides/keyvalue/localisation.md @@ -23,19 +23,19 @@ Languages natively supported by Titanfall2 are: Here's what a translation file looks like: ```json - "lang" +"lang" +{ + "Language" "english" + "Tokens" { - "Language" "english" - "Tokens" - { - "MENU_LAUNCH_NORTHSTAR" "Launch Northstar" - "MENU_TITLE_MODS" "Mods" - "RELOAD_MODS" "Reload Mods" - "WARNING" "Warning" - "CORE_MOD_DISABLE_WARNING" "Disabling core mods can break your client!" - "DISABLE" "Disable" - } + "MENU_LAUNCH_NORTHSTAR" "Launch Northstar" + "MENU_TITLE_MODS" "Mods" + "RELOAD_MODS" "Reload Mods" + "WARNING" "Warning" + "CORE_MOD_DISABLE_WARNING" "Disabling core mods can break your client!" + "DISABLE" "Disable" } +} ``` It begins with the `"lang"` instruction, contains a `"Language"` key indicating @@ -58,11 +58,11 @@ For example, Northstar translation files are named You can import them from your `mod.json` manifesto this way: ```json - { - "Localisation": [ - "resource/northstar_client_localisation_%language%.txt" - ] - } +{ + "Localisation": [ + "resource/northstar_client_localisation_%language%.txt" + ] +} ``` !!! note @@ -80,19 +80,19 @@ For example, to translate the "Launch Northstar" button on main menu, instead of calling: ``` - AddComboButton( comboStruct, headerIndex, buttonIndex++, "Launch Northstar" ) +AddComboButton( comboStruct, headerIndex, buttonIndex++, "Launch Northstar" ) ``` We'll use: ``` - AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_LAUNCH_NORTHSTAR" ) +AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_LAUNCH_NORTHSTAR" ) ``` You can also use the `Localize` method client-side: ``` - Localize( "#MENU_LAUNCH_NORTHSTAR" ) +Localize( "#MENU_LAUNCH_NORTHSTAR" ) ``` ## Northstar translations diff --git a/docs/Modding/guides/publishing.md b/docs/Modding/guides/publishing.md index a05f7de5..acd2b0bb 100644 --- a/docs/Modding/guides/publishing.md +++ b/docs/Modding/guides/publishing.md @@ -12,7 +12,7 @@ If the changes your mod makes can be represented in screenshots, gameplay record To do so, simply upload the image or gif to a host of your choice (Imgur, GitHub, and even Discord all work). To display the image directly on your page in Thunderstore, add the following line to your README: ```markdown - ![alt text, this text shows up when image cannot be loaded](https://example.com/image/to/link/to.gif) +![alt text, this text shows up when image cannot be loaded](https://example.com/image/to/link/to.gif) ``` @@ -25,10 +25,10 @@ The best place to publish your mod is [Thunderstore](https://northstar.thunderst The Thunderstore package zip structure is as follows: ``` - mods/./ - icon.png - manifest.json - README.md +mods/./ +icon.png +manifest.json +README.md ``` diff --git a/docs/Modding/guides/reversing/squirrelreversing.md b/docs/Modding/guides/reversing/squirrelreversing.md index 2d20a84b..6bfb71b0 100644 --- a/docs/Modding/guides/reversing/squirrelreversing.md +++ b/docs/Modding/guides/reversing/squirrelreversing.md @@ -39,54 +39,54 @@ You can search for a string in memory with `Search > Memory`. Select `String` as The first occurence is at `server.dll+0x2b44f3`. If you wait for the function to be decompiled, you'll see the string in this code: ```c - _DAT_181055f60 = "IsServer"; - _DAT_181055f68 = "IsServer"; - _DAT_181055fb8 = 0; - _DAT_181055f90 = 0; - _DAT_181055f98 = 0; - _DAT_181055fc0 = FUN_18029a630; - _DAT_181055f88 = _DAT_181055f88 & 0xff; - _DAT_181055f70 = ZEXT816(0x1808fa7f8); - _DAT_181055f80 = 0; - _DAT_181055f8c = 0; - _DAT_181055f9c = 6; +_DAT_181055f60 = "IsServer"; +_DAT_181055f68 = "IsServer"; +_DAT_181055fb8 = 0; +_DAT_181055f90 = 0; +_DAT_181055f98 = 0; +_DAT_181055fc0 = FUN_18029a630; +_DAT_181055f88 = _DAT_181055f88 & 0xff; +_DAT_181055f70 = ZEXT816(0x1808fa7f8); +_DAT_181055f80 = 0; +_DAT_181055f8c = 0; +_DAT_181055f9c = 6; ``` Because the squirrel function executes native code, the callback `FUN_18029a630` is probably where it's located. You can double click the reference to decompile the function. ```c - undefined4 FUN_18029a630(undefined8 param_1) - { - char cVar1; - undefined4 uVar2; - - uVar2 = 1; - FUN_180003710(param_1,1); - cVar1 = FUN_18001d840(param_1); - if (cVar1 != '\0') { - uVar2 = 0xffffffff; - } - return uVar2; +undefined4 FUN_18029a630(undefined8 param_1) +{ + char cVar1; + undefined4 uVar2; + + uVar2 = 1; + FUN_180003710(param_1,1); + cVar1 = FUN_18001d840(param_1); + if (cVar1 != '\0') { + uVar2 = 0xffffffff; } + return uVar2; +} ``` From this you can assume that native closures in squirrel_re still use the `SQRESULT` convention, because the closure returns `-1` if `FUN_18001d840` returns `NULL`, which is typically an error and `1` if nothing happens. It's also obvious that either `FUN_180003710` or `FUN_18001d840` pushes a boolean to the stack. It's probably `FUN_180003710` because it takes an extra parameter but you can check `IsClient` at `server.dll+0x29a4d0` as a reference. ```c - undefined4 FUN_18029a4d0(undefined8 param_1) - { - char cVar1; - undefined4 uVar2; - - FUN_180003710(param_1,0); - cVar1 = FUN_18001d840(param_1); - uVar2 = 1; - if (cVar1 != '\0') { - uVar2 = 0xffffffff; - } - return uVar2; +undefined4 FUN_18029a4d0(undefined8 param_1) +{ + char cVar1; + undefined4 uVar2; + + FUN_180003710(param_1,0); + cVar1 = FUN_18001d840(param_1); + uVar2 = 1; + if (cVar1 != '\0') { + uVar2 = 0xffffffff; } + return uVar2; +} ``` This is virtually the same, except that `FUN_180003710` is being called with a `0`. @@ -95,7 +95,7 @@ Decompile the function, then right click the function and select `Edit Function Right now the signature looks like this: ```c - void FUN_180003710(longlong param_1, int param_2) +void FUN_180003710(longlong param_1, int param_2) ``` `param_1` has to be a pointer to the Squirrel VM, because a pointer on 64x systems is 8 bytes long (the same as `longlong`) and the `HSquirrelVM` struct is larger than 8 bytes. @@ -105,5 +105,5 @@ The second parameter has to be the value that will be pushed to the VM as a bool You can change the signature now to this, to make code using the function more readable. Because `HSquirrelVM` isn't defined yet, the type needs to stay `longlong` for now. ```c - void sq_pushbool(longlong sqvm, int value) +void sq_pushbool(longlong sqvm, int value) ``` diff --git a/docs/Modding/guides/scripting/custommenus.md b/docs/Modding/guides/scripting/custommenus.md index e5c6b303..faf79b67 100644 --- a/docs/Modding/guides/scripting/custommenus.md +++ b/docs/Modding/guides/scripting/custommenus.md @@ -7,20 +7,20 @@ This tutorial will explain how to create a mod that adds a new menu that's viewa First, create a new folder with this `mod.json`: ```json - { - "Name": "CustomMenuTutorial", - "Description": "Custom menu tutorial", - "LoadPriority": 1, - "Scripts": [ - { - "Path": "ui/custom_menu.nut", - "RunOn": "UI", - "UICallback": { - "Before": "AddCustomMenu" - } +{ + "Name": "CustomMenuTutorial", + "Description": "Custom menu tutorial", + "LoadPriority": 1, + "Scripts": [ + { + "Path": "ui/custom_menu.nut", + "RunOn": "UI", + "UICallback": { + "Before": "AddCustomMenu" } - ] - } + } + ] +} ``` Then create `custom_menu.nut` in `./mod/scripts/vscripts/ui`. @@ -30,12 +30,12 @@ Then create `custom_menu.nut` in `./mod/scripts/vscripts/ui`. Create `AddCustomMenu` in `custom_menu.nut` like this and make it global: ```squirrel - global function AddCustomMenu +global function AddCustomMenu - void function AddCustomMenu() - { - AddMenu( "CustomMenu", $"resource/ui/menus/custommenu.menu", CustomMenu_Init ) - } +void function AddCustomMenu() +{ + AddMenu( "CustomMenu", $"resource/ui/menus/custommenu.menu", CustomMenu_Init ) +} ``` `AddCustomMenu` will get called when the UI vm is initializing and instantiate your menu. You can access your menu with `GetMenu( "CustomMenu" )` after it has been initialized. @@ -45,81 +45,81 @@ Next, create the file that defines the layout of your menu. It's already referen ??? ".menu configuration" ``` - resource/ui/menus/custommenu.menu + resource/ui/menus/custommenu.menu + { + menu { - menu + ControlName Frame + xpos 0 + ypos 0 + zpos 3 + wide f0 + tall f0 + autoResize 0 + visible 1 + enabled 1 + pinCorner 0 + PaintBackgroundType 0 + infocus_bgcolor_override "0 0 0 0" + outoffocus_bgcolor_override "0 0 0 0" + + Vignette // Darkened frame edges + { + ControlName ImagePanel + InheritProperties MenuVignette + } + + Title // The title of this menu + { + ControlName Label + InheritProperties MenuTitle + labelText "#CUSTOM_MENU_TITLE" + } + + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Content + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + SomeLabel // A label that is placed in the middle of the screen + { + ControlName Label + + labelText "Some Label" + + auto_wide_tocontents 1 // Set width automatically relative to the label content + + xpos %50 + ypos %50 + } + + SomeButton // A button that is placed directly beneath the label + { + ControlName RuiButton + InheritProperties RuiSmallButton + + tall 50 + wide 250 + + labelText "Some Button" + textAlignment center + + pin_to_sibling SomeLabel + pin_corner_to_sibling TOP + pin_to_sibling_corner BOTTOM + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Footer + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + FooterButtons // Allow adding footers to this menu { - ControlName Frame - xpos 0 - ypos 0 - zpos 3 - wide f0 - tall f0 - autoResize 0 - visible 1 - enabled 1 - pinCorner 0 - PaintBackgroundType 0 - infocus_bgcolor_override "0 0 0 0" - outoffocus_bgcolor_override "0 0 0 0" - - Vignette // Darkened frame edges - { - ControlName ImagePanel - InheritProperties MenuVignette - } - - Title // The title of this menu - { - ControlName Label - InheritProperties MenuTitle - labelText "#CUSTOM_MENU_TITLE" - } - - - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// Content - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - SomeLabel // A label that is placed in the middle of the screen - { - ControlName Label - - labelText "Some Label" - - auto_wide_tocontents 1 // Set width automatically relative to the label content - - xpos %50 - ypos %50 - } - - SomeButton // A button that is placed directly beneath the label - { - ControlName RuiButton - InheritProperties RuiSmallButton - - tall 50 - wide 250 - - labelText "Some Button" - textAlignment center - - pin_to_sibling SomeLabel - pin_corner_to_sibling TOP - pin_to_sibling_corner BOTTOM - } - - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// Footer - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - FooterButtons // Allow adding footers to this menu - { - ControlName CNestedPanel - InheritProperties FooterButtons - } + ControlName CNestedPanel + InheritProperties FooterButtons } } + } ``` Now you'll need to define `CustomMenu_Init`. This is the function previously defined that contains all initializations needed for this menu. @@ -127,28 +127,28 @@ Now you'll need to define `CustomMenu_Init`. This is the function previously def First, create an instantiated struct for variables that should be available in the scope of your custom menu script. ```squirrel - struct { - var menu - } file +struct { + var menu +} file ``` At the moment, this struct can only contain your menu. To set it, edit `AddCustomMenu` like this: ```diff - void function AddCustomMenu() - { - AddMenu( "CustomMenu", $"resource/ui/menus/custommenu.menu", CustomMenu_Init ) -+ file.menu = GetMenu( "CustomMenu" ) - } +void function AddCustomMenu() +{ + AddMenu( "CustomMenu", $"resource/ui/menus/custommenu.menu", CustomMenu_Init ) ++ file.menu = GetMenu( "CustomMenu" ) +} ``` Now, define `CustomMenu_Init`. It doesn't need to be global. ```squirrel - void function CustomMenu_Init() - { - AddMenuFooterOption( file.menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) - } +void function CustomMenu_Init() +{ + AddMenuFooterOption( file.menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) +} ``` This adds a footer to your menu, that allows the user to navigate back. @@ -158,44 +158,44 @@ This adds a footer to your menu, that allows the user to navigate back. Currently, there is no way to access your menu. You can open your (or any other menu) with `AdvanceMenu`. ```squirrel - AdvanceMenu( GetMenu( "CustomMenu" ) ) +AdvanceMenu( GetMenu( "CustomMenu" ) ) ``` This is useful for callbacks triggered by button presses like from footers. To add a footer to the Main menu, first edit your `mod.json` code callbacks: ```diff - "Scripts": [ - { - "Path": "ui/custom_menu.nut", - "RunOn": "UI", - "UICallback": { -+ "Before": "AddCustomMenu", // <- Notice the added comma -+ "After": "AddCustomMenuFooter" - } +"Scripts": [ + { + "Path": "ui/custom_menu.nut", + "RunOn": "UI", + "UICallback": { ++ "Before": "AddCustomMenu", // <- Notice the added comma ++ "After": "AddCustomMenuFooter" } - ] + } +] ``` We need a new callback that's run after all menus are initialized to add any footers to them. Create the global function `AddCustomMenuFooter` in `custom_menu.nut` like this: ```squirrel - void function AddCustomMenuFooter() - { - AddMenuFooterOption( - GetMenu( "MainMenu" ), // Get the main menu. We want to add a footer to this one. Change this if you want to add a footer to another menu - BUTTON_X, // This sets the gamepad button that will trigger the click callback defined later - PrependControllerPrompts( BUTTON_X, " Custom Menu" ), // This is the text that will show as the label of the footer if a gamepad is used - "Custom Menu", // This is the label text of the footer if no gamepad is used - void function( var button ) // This is the click callback. - { - /* - This is an anonymous function. - It will be run every time the footer is pressed. - */ - AdvanceMenu( file.menu ) - } - ) - } +void function AddCustomMenuFooter() +{ + AddMenuFooterOption( + GetMenu( "MainMenu" ), // Get the main menu. We want to add a footer to this one. Change this if you want to add a footer to another menu + BUTTON_X, // This sets the gamepad button that will trigger the click callback defined later + PrependControllerPrompts( BUTTON_X, " Custom Menu" ), // This is the text that will show as the label of the footer if a gamepad is used + "Custom Menu", // This is the label text of the footer if no gamepad is used + void function( var button ) // This is the click callback. + { + /* + This is an anonymous function. + It will be run every time the footer is pressed. + */ + AdvanceMenu( file.menu ) + } + ) +} ``` ## Scripting Menu Logic @@ -207,31 +207,31 @@ We'll use the button we defined earlier in the `.menu` file to increase a number first, add `someLabel` and `clicks` to the `file` struct. Then define the label in the `AddCustomMenu` and add a callback to the button. ```diff - struct { - var menu -+ var someLabel -+ int clicks - } file - - void function AddCustomMenu() - { - AddMenu( "CustomMenu", $"resource/ui/menus/custommenu.menu", CustomMenu_Init ) - file.menu = GetMenu( "CustomMenu" ) -+ file.someLabel = Hud_GetChild( file.menu, "SomeLabel" ) - -+ var someButton = Hud_GetChild( file.menu, "SomeButton" ) -+ Hud_AddEventHandler( someButton, UIE_CLICK, OnSomeButtonClick ) - } +struct { + var menu ++ var someLabel ++ int clicks +} file + +void function AddCustomMenu() +{ + AddMenu( "CustomMenu", $"resource/ui/menus/custommenu.menu", CustomMenu_Init ) + file.menu = GetMenu( "CustomMenu" ) ++ file.someLabel = Hud_GetChild( file.menu, "SomeLabel" ) + ++ var someButton = Hud_GetChild( file.menu, "SomeButton" ) ++ Hud_AddEventHandler( someButton, UIE_CLICK, OnSomeButtonClick ) +} ``` Now you need to define the `OnSomeButtonClick` callback that's triggered when the button is activated. ```squirrel - void function OnSomeButtonClick( var button ) - { - file.clicks++ - Hud_SetText( file.someLabel, format( "clicked the button %i times", file.clicks ) ) - } +void function OnSomeButtonClick( var button ) +{ + file.clicks++ + Hud_SetText( file.someLabel, format( "clicked the button %i times", file.clicks ) ) +} ``` ### Adding a Reset Button @@ -239,51 +239,51 @@ Now you need to define the `OnSomeButtonClick` callback that's triggered when th First you need to add a definition in your `custommenu.menu` file: ``` - ResetButton - { - ControlName RuiButton - InheritProperties RuiSmallButton +ResetButton +{ + ControlName RuiButton + InheritProperties RuiSmallButton - tall 50 - wide 250 + tall 50 + wide 250 - labelText "Reset Counter" - textAlignment center + labelText "Reset Counter" + textAlignment center - pin_to_sibling SomeButton - pin_corner_to_sibling TOP - pin_to_sibling_corner BOTTOM - } + pin_to_sibling SomeButton + pin_corner_to_sibling TOP + pin_to_sibling_corner BOTTOM +} ``` Then add a `UIE_CLICK` callback for the button. It also makes sense to move the code that updates the label text to it's own function so it can be reused by the reset button. ```diff - void function AddCustomMenu() - { - AddMenu( "CustomMenu", $"resource/ui/menus/custommenu.menu", CustomMenu_Init ) - file.menu = GetMenu( "CustomMenu" ) - file.someLabel = Hud_GetChild( file.menu, "SomeLabel" ) - - var someButton = Hud_GetChild( file.menu, "SomeButton" ) -+ var resetButton = Hud_GetChild( file.menu, "ResetButton" ) - - Hud_AddEventHandler( someButton, UIE_CLICK, OnSomeButtonClick ) -+ Hud_AddEventHandler( resetButton, UIE_CLICK, OnResetButtonClick ) - } - - void function OnSomeButtonClick( var button ) - { - file.clicks++ - - Hud_SetText( file.someLabel, format( "clicked the button %i times", file.clicks ) ) -+ UpdateClickLabel() - } - - void function OnResetButtonClick( var button ) - { - file.clicks = 0 -+ UpdateClickLabel() - } +void function AddCustomMenu() +{ + AddMenu( "CustomMenu", $"resource/ui/menus/custommenu.menu", CustomMenu_Init ) + file.menu = GetMenu( "CustomMenu" ) + file.someLabel = Hud_GetChild( file.menu, "SomeLabel" ) + + var someButton = Hud_GetChild( file.menu, "SomeButton" ) ++ var resetButton = Hud_GetChild( file.menu, "ResetButton" ) + + Hud_AddEventHandler( someButton, UIE_CLICK, OnSomeButtonClick ) ++ Hud_AddEventHandler( resetButton, UIE_CLICK, OnResetButtonClick ) +} + +void function OnSomeButtonClick( var button ) +{ + file.clicks++ +- Hud_SetText( file.someLabel, format( "clicked the button %i times", file.clicks ) ) ++ UpdateClickLabel() +} + + void function OnResetButtonClick( var button ) +{ + file.clicks = 0 ++ UpdateClickLabel() +} + void function UpdateClickLabel() + { @@ -298,27 +298,27 @@ You can add callbacks for menu events, for example when a menu is closed or open If you want to reset the counter if the menu is closed, edit `AddCustomMenu` like this: ```diff - void function AddCustomMenu() - { - AddMenu( "CustomMenu", $"resource/ui/menus/custommenu.menu", CustomMenu_Init ) - file.menu = GetMenu( "CustomMenu" ) - file.someLabel = Hud_GetChild( file.menu, "SomeLabel" ) +void function AddCustomMenu() +{ + AddMenu( "CustomMenu", $"resource/ui/menus/custommenu.menu", CustomMenu_Init ) + file.menu = GetMenu( "CustomMenu" ) + file.someLabel = Hud_GetChild( file.menu, "SomeLabel" ) - var someButton = Hud_GetChild( file.menu, "SomeButton" ) - var resetButton = Hud_GetChild( file.menu, "ResetButton" ) + var someButton = Hud_GetChild( file.menu, "SomeButton" ) + var resetButton = Hud_GetChild( file.menu, "ResetButton" ) - Hud_AddEventHandler( someButton, UIE_CLICK, OnSomeButtonClick ) - Hud_AddEventHandler( resetButton, UIE_CLICK, OnResetButtonClick ) + Hud_AddEventHandler( someButton, UIE_CLICK, OnSomeButtonClick ) + Hud_AddEventHandler( resetButton, UIE_CLICK, OnResetButtonClick ) -+ AddMenuEventHandler( file.menu, eUIEvent.MENU_CLOSE, OnCloseCustomMenu ) - } ++ AddMenuEventHandler( file.menu, eUIEvent.MENU_CLOSE, OnCloseCustomMenu ) +} ``` And define the callback `OnCloseCustomMenu` to simply call `OnResetButtonClick`. ```squirrel - void function OnCloseCustomMenu() - { - OnResetButtonClick( null ) - } +void function OnCloseCustomMenu() +{ + OnResetButtonClick( null ) +} ``` diff --git a/docs/Modding/guides/scripting/gamemodemods.md b/docs/Modding/guides/scripting/gamemodemods.md index 38a39856..c37f6a30 100644 --- a/docs/Modding/guides/scripting/gamemodemods.md +++ b/docs/Modding/guides/scripting/gamemodemods.md @@ -10,36 +10,36 @@ The `mod.json` is responsible for governing when, and where your mod is loaded, However, once you get the hang of it, it should be fairly easy to use. ```json - { - "Name" : "SimpleRandomiser", - "Description" : "A randomiser gamemode that randomizes your loadouts!", - "Version": "0.1.0", - "LoadPriority": 1, +{ + "Name" : "SimpleRandomiser", + "Description" : "A randomiser gamemode that randomizes your loadouts!", + "Version": "0.1.0", + "LoadPriority": 1, ``` The script above defines the pubic and listed details of the mod. ```json - "Scripts": [ - { - "Path": "gamemodes/_gamemode_simplerandomiser.nut", - "RunOn": "SERVER && MP" - }, - { - "Path": "gamemodes/cl_gamemode_simplerandomiser.nut", - "RunOn": "CLIENT && MP" +"Scripts": [ + { + "Path": "gamemodes/_gamemode_simplerandomiser.nut", + "RunOn": "SERVER && MP" + }, + { + "Path": "gamemodes/cl_gamemode_simplerandomiser.nut", + "RunOn": "CLIENT && MP" + }, + { + "Path": "sh_gamemode_simplerandomiser.nut", + "RunOn": "MP", + "ClientCallback": { + "Before": "simplerandomiser_init" }, - { - "Path": "sh_gamemode_simplerandomiser.nut", - "RunOn": "MP", - "ClientCallback": { - "Before": "simplerandomiser_init" - }, - "ServerCallback": { - "Before": "simplerandomiser_init" - } + "ServerCallback": { + "Before": "simplerandomiser_init" } - ], + } +], ``` The script above defines both what functions to run, when to run them and WHERE to run them, @@ -55,10 +55,10 @@ For example, both server and client needs to know whether if this gamemode exist ```json - "Localisation": [ - "resource/simplerandomiser_localisation_%language%.txt" - ] - } + "Localisation": [ + "resource/simplerandomiser_localisation_%language%.txt" + ] +} ``` This defines the path to the language file, and its main use is to localize strings such as the announcement texts, gamemode and so on. @@ -68,35 +68,35 @@ Name this file `mod.json`, and it should go in the mods root folder, that being Here's what the end result would look like: ```json +{ + "Name" : "SimpleRandomiser", + "Description" : "SimpleRandomiser", + "Version": "0.1.0", + "LoadPriority": 1, + "Scripts": [ { - "Name" : "SimpleRandomiser", - "Description" : "SimpleRandomiser", - "Version": "0.1.0", - "LoadPriority": 1, - "Scripts": [ - { - "Path": "gamemodes/_gamemode_simplerandomiser.nut", - "RunOn": "SERVER && MP" - }, - { - "Path": "gamemodes/cl_gamemode_simplerandomiser.nut", - "RunOn": "CLIENT && MP" + "Path": "gamemodes/_gamemode_simplerandomiser.nut", + "RunOn": "SERVER && MP" + }, + { + "Path": "gamemodes/cl_gamemode_simplerandomiser.nut", + "RunOn": "CLIENT && MP" + }, + { + "Path": "sh_gamemode_simplerandomiser.nut", + "RunOn": "MP", + "ClientCallback": { + "Before": "simplerandomiser_init" }, - { - "Path": "sh_gamemode_simplerandomiser.nut", - "RunOn": "MP", - "ClientCallback": { - "Before": "simplerandomiser_init" - }, - "ServerCallback": { - "Before": "simplerandomiser_init" - } + "ServerCallback": { + "Before": "simplerandomiser_init" } - ], - "Localisation": [ - "resource/simplerandomiser_localisation_%language%.txt" - ] } +], + "Localisation": [ + "resource/simplerandomiser_localisation_%language%.txt" + ] +} ``` ## Language file @@ -105,15 +105,15 @@ This follows a fairly simple template, the only thing of note is that you often ``` - "lang" +"lang" +{ + "Language" "english" + "Tokens" { - "Language" "english" - "Tokens" - { - "MODE_SETTING_CATEGORY_SIMPLERANDOMISER" "Simple Randomiser" - "SIMPLERANDOMISER" "Randomise" - } + "MODE_SETTING_CATEGORY_SIMPLERANDOMISER" "Simple Randomiser" + "SIMPLERANDOMISER" "Randomise" } +} ``` Name this file `simplerandomiser_localisation_english.txt` and place it in the `yourmodsname/mod/resource/` folder. @@ -123,21 +123,21 @@ Name this file `simplerandomiser_localisation_english.txt` and place it in the ` Let's begin the process by first creating the file `sh_gamemode_simplerandomiser.nut` and making the core components of the gamemode, which is to define the gamemode properties. ```squirrel - global function simplerandomiser_init // initializing functions - global const string GAMEMODE_SIMPLERANDOMISER = "rand" - // we want a short term to use which allows server owners to - // select our gamemode without typing the entire name - // also makes it easier for us lol - - void function simplerandomiser_init() - { - // start defining what to do before the map loads on this gamemode +global function simplerandomiser_init // initializing functions +global const string GAMEMODE_SIMPLERANDOMISER = "rand" +// we want a short term to use which allows server owners to +// select our gamemode without typing the entire name +// also makes it easier for us lol + +void function simplerandomiser_init() +{ + // start defining what to do before the map loads on this gamemode AddCallback_OnCustomGamemodesInit( CreateGamemodeRand ) // define various properties such as name, desc, so on AddCallback_OnRegisteringCustomNetworkVars( RandRegisterNetworkVars ) // server callbacks stuff - } +} - void function CreateGamemodeRand() - { +void function CreateGamemodeRand() +{ GameMode_Create( GAMEMODE_SIMPLERANDOMISER ) GameMode_SetName( GAMEMODE_SIMPLERANDOMISER, "#GAMEMODE_SIMPLERANDOMISER" ) // localizations will be handled later GameMode_SetDesc( GAMEMODE_SIMPLERANDOMISER, "#PL_rand_desc" ) @@ -159,29 +159,29 @@ Let's begin the process by first creating the file `sh_gamemode_simplerandomiser // set this to 25 score limit default GameMode_SetDefaultScoreLimits( GAMEMODE_SIMPLERANDOMISER, 25, 0 ) - #if SERVER - GameMode_AddServerInit( GAMEMODE_SIMPLERANDOMISER, GamemodeRand_Init ) // server side initalizing function - GameMode_SetPilotSpawnpointsRatingFunc( GAMEMODE_SIMPLERANDOMISER, RateSpawnpoints_Generic ) - GameMode_SetTitanSpawnpointsRatingFunc( GAMEMODE_SIMPLERANDOMISER, RateSpawnpoints_Generic ) - // until northstar adds more spawnpoints algorithm, we are using the default. - #elseif CLIENT - GameMode_AddClientInit( GAMEMODE_SIMPLERANDOMISER, ClGamemodeRand_Init ) // client side initializing function - #endif - #if !UI - GameMode_SetScoreCompareFunc( GAMEMODE_SIMPLERANDOMISER, CompareAssaultScore ) - // usually compares which team's score is higher and places the winning team on top of the losing team in the scoreboard - #endif - } - - void function RandRegisterNetworkVars() - { +#if SERVER + GameMode_AddServerInit( GAMEMODE_SIMPLERANDOMISER, GamemodeRand_Init ) // server side initalizing function + GameMode_SetPilotSpawnpointsRatingFunc( GAMEMODE_SIMPLERANDOMISER, RateSpawnpoints_Generic ) + GameMode_SetTitanSpawnpointsRatingFunc( GAMEMODE_SIMPLERANDOMISER, RateSpawnpoints_Generic ) + // until northstar adds more spawnpoints algorithm, we are using the default. +#elseif CLIENT + GameMode_AddClientInit( GAMEMODE_SIMPLERANDOMISER, ClGamemodeRand_Init ) // client side initializing function +#endif +#if !UI + GameMode_SetScoreCompareFunc( GAMEMODE_SIMPLERANDOMISER, CompareAssaultScore ) + // usually compares which team's score is higher and places the winning team on top of the losing team in the scoreboard +#endif +} + +void function RandRegisterNetworkVars() +{ if ( GAMETYPE != GAMEMODE_SIMPLERANDOMISER ) return Remote_RegisterFunction( "ServerCallback_Randomiser" ) - // will come in useful later when we want the server to communicate to the client - // for example, making an announcement appear on the client - } + // will come in useful later when we want the server to communicate to the client + // for example, making an announcement appear on the client +} ``` The comments should hopefully explain what most of everything does, but just to summarize: @@ -197,16 +197,16 @@ Now that we're done, name this file `sh_gamemode_simplerandomiser.nut` and place Now that we're down with defining the gamemode, its time to focus on the component on that makes the gamemode function in-game. For this, it will be mostly handled by the server scripts, so head into `_gamemode_simplerandomiser.nut` to begin writing the randomizing script. ```squirrel - global function GamemodeRand_Init +global function GamemodeRand_Init - void function GamemodeRand_Init() - { - #if SERVER +void function GamemodeRand_Init() +{ + #if SERVER SetLoadoutGracePeriodEnabled( false ) // prevent modifying loadouts with grace period SetWeaponDropsEnabled( false ) // prevents picking up weapons on the ground - AddCallback_OnPlayerRespawned( GiveRandomGun ) - #endif - } + AddCallback_OnPlayerRespawned( GiveRandomGun ) + #endif +} ``` As you may have noticed, checking if it is a server is a special case, so we use `#if SERVER` and `#endif` instead of the usual `if(thing){stuff}` @@ -217,10 +217,10 @@ Firstly, we need to know what weapons we can equip. For this we define an array: ```squirrel - array pilotWeapons = ["mp_weapon_alternator_smg", - "mp_weapon_autopistol", - "mp_weapon_car", - "mp_weapon_dmr"] +array pilotWeapons = ["mp_weapon_alternator_smg", + "mp_weapon_autopistol", + "mp_weapon_car", + "mp_weapon_dmr"] ``` Here we have defined an array with only 4 weapons in it, you can make this list however you like but remember to separate all but the last item with a `,` @@ -231,10 +231,10 @@ As we already know its going to call the function `GiveRandomGun` when a player First we strip any existing weapons: ```squirrel - void function GiveRandomGun(entity player) - { - foreach ( entity weapon in player.GetMainWeapons() ) - player.TakeWeaponNow( weapon.GetWeaponClassName() ) +void function GiveRandomGun(entity player) +{ + foreach ( entity weapon in player.GetMainWeapons() ) + player.TakeWeaponNow( weapon.GetWeaponClassName() ) ``` This iterates through each weapon (that being the primary, secondary and anti-titan weapons) and removes them individually. @@ -242,48 +242,48 @@ This iterates through each weapon (that being the primary, secondary and anti-ti Then lets give them a new, random weapon by selecting a random item from our previous array: ```squirrel - player.GiveWeapon( pilotWeapons[ RandomInt( pilotWeapons.len() ) ] ) +player.GiveWeapon( pilotWeapons[ RandomInt( pilotWeapons.len() ) ] ) ``` Now, remember the server callback that we defined earlier in `sh_gamemode_simplerandomiser.nut`? Let's put that to use. We are going to make it so the player receives an announcement whenever they have their weapons randomized. ```squirrel - // checks if the toggle option is set to enabled - if ( GetCurrentPlaylistVarInt( "rand_enableannouncements", 1 ) == 1 ) - Remote_CallFunction_NonReplay( player, "ServerCallback_Randomiser" ) // call the function that will be used client-side +// checks if the toggle option is set to enabled +if ( GetCurrentPlaylistVarInt( "rand_enableannouncements", 1 ) == 1 ) + Remote_CallFunction_NonReplay( player, "ServerCallback_Randomiser" ) // call the function that will be used client-side ``` Overall, the server script should look like this. ```squirrel - global function GamemodeRand_Init +global function GamemodeRand_Init - void function GamemodeRand_Init() - { - #if SERVER +void function GamemodeRand_Init() +{ + #if SERVER SetLoadoutGracePeriodEnabled( false ) // prevent modifying loadouts with grace period SetWeaponDropsEnabled( false ) // prevents picking up weapons on the ground - AddCallback_OnPlayerRespawned( GiveRandomGun ) - #endif - } + AddCallback_OnPlayerRespawned( GiveRandomGun ) + #endif +} - array pilotWeapons = ["mp_weapon_alternator_smg", - "mp_weapon_autopistol", - "mp_weapon_car", - "mp_weapon_dmr"] +array pilotWeapons = ["mp_weapon_alternator_smg", + "mp_weapon_autopistol", + "mp_weapon_car", + "mp_weapon_dmr"] - void function GiveRandomGun(entity player) - { - foreach ( entity weapon in player.GetMainWeapons() ) - player.TakeWeaponNow( weapon.GetWeaponClassName() ) +void function GiveRandomGun(entity player) +{ + foreach ( entity weapon in player.GetMainWeapons() ) + player.TakeWeaponNow( weapon.GetWeaponClassName() ) - player.GiveWeapon( pilotWeapons[ RandomInt( pilotWeapons.len() ) ] ) + player.GiveWeapon( pilotWeapons[ RandomInt( pilotWeapons.len() ) ] ) - // checks if the toggle option is set to enabled - if ( GetCurrentPlaylistVarInt( "rand_enableannouncements", 1 ) == 1 ) - Remote_CallFunction_NonReplay( player, "ServerCallback_Randomiser", GetCurrentPlaylistVarFloat( "rand_announcementduration", 3 ) ) // call the function that will be used client-side - } + // checks if the toggle option is set to enabled + if ( GetCurrentPlaylistVarInt( "rand_enableannouncements", 1 ) == 1 ) + Remote_CallFunction_NonReplay( player, "ServerCallback_Randomiser", GetCurrentPlaylistVarFloat( "rand_announcementduration", 3 ) ) // call the function that will be used client-side +} ``` Name this file `_gamemode_simplerandomiser.nut` and place it in the `yourmodsname/mod/scripts/vscripts/gamemodes` folder as well. @@ -293,12 +293,12 @@ Make sure to double check that all spellings are correct in your mod as everythi Lastly, for your `cl_gamemode_simplerandomiser.nut`, we are going to utilize the callback functions from earlier, as well as add some music to play during the gamemode. ```squirrel - global function ClGamemodeRand_Init - global function ServerCallback_Randomiser +global function ClGamemodeRand_Init +global function ServerCallback_Randomiser - void function ClGamemodeRand_Init() - { - RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_freeagents_intro", TEAM_IMC ) +void function ClGamemodeRand_Init() +{ + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_freeagents_intro", TEAM_IMC ) RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_freeagents_intro", TEAM_MILITIA ) RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_freeagents_outro_win", TEAM_IMC ) @@ -315,11 +315,11 @@ Lastly, for your `cl_gamemode_simplerandomiser.nut`, we are going to utilize the RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_freeagents_lastminute", TEAM_IMC ) RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_freeagents_lastminute", TEAM_MILITIA ) - } +} - void function ServerCallback_Randomiser( float duration ) - { - AnnouncementData announcement = Announcement_Create( "#RAND_RANDOMIZED" ) +void function ServerCallback_Randomiser( float duration ) +{ + AnnouncementData announcement = Announcement_Create( "#RAND_RANDOMIZED" ) Announcement_SetSubText( announcement, "#RAND_RANDOMIZED_DESC" ) Announcement_SetTitleColor( announcement, <0,0,1> ) Announcement_SetPurge( announcement, true ) @@ -328,7 +328,7 @@ Lastly, for your `cl_gamemode_simplerandomiser.nut`, we are going to utilize the Announcement_SetDuration( announcement, duration ) Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) AnnouncementFromClass( GetLocalViewPlayer(), announcement ) - } +} ``` What this script does is quite simple. It registers default music to play during the intro portion, when winning, drawing or losing, as well as the event when the timelimit reaches 3 minutes or 1 minute left. @@ -344,23 +344,23 @@ Technically, yes, you could. But it wouldn't look pretty. Remember all those str Hence, open your `simplerandomiser_localisation_english.txt` which is located in the `yourmodsname/mod/resource/` folder. ```json - "lang" - { +"lang" +{ "Language" "english" "Tokens" { "PL_rand" "Simple Randomiser" // displays in the lobby settings - "rand_enableannouncements" "Toggle announcements" // describe the togglable setting + "rand_enableannouncements" "Toggle announcements" // describe the togglable setting "rand_announcementduration" "Announcement duration" // describe the numerical setting "PL_rand_lobby" "Simple Randomiser Lobby" // displays in lobby "PL_rand_desc" "Your weapons are randomised! Fight and win!" // displays in the description of the gamemode in the lobby "PL_rand_hint" "Your weapons are randomised! Fight and win!" // displays in the scoreboard of the gamemode ingame "PL_rand_abbr" "RAND" "GAMEMODE_TBAG" "Simple Randomiser" // displays in the loading screen - "RAND_RANDOMIZED" "Weapons Randomized" // displays in the announcement text - "RAND_RANDOMIZED_DESC" "Fight and win!" // displays below the announcement text, as a description - } + "RAND_RANDOMIZED" "Weapons Randomized" // displays in the announcement text + "RAND_RANDOMIZED_DESC" "Fight and win!" // displays below the announcement text, as a description } +} ``` Alright, we're finally done! However, there's just one thing missing, which is to let the game know what maps are available for this gamemode to play on. @@ -374,8 +374,8 @@ Yes, you will need to create a folder called `keyvalues` which is separate from Next, inside this `playlists_v2.txt`, we will need to allow/disallow what maps can the gamemode be played on. ```text - playlists - { +playlists +{ Gamemodes { rand @@ -395,8 +395,8 @@ Next, inside this `playlists_v2.txt`, we will need to allow/disallow what maps c gamemode_score_hint #GAMEMODE_SCORE_HINT_TDM } } - } - Playlists + } + Playlists { rand { @@ -416,20 +416,20 @@ Next, inside this `playlists_v2.txt`, we will need to allow/disallow what maps c { rand { - maps + maps { - mp_forwardbase_kodai 1 - mp_grave 1 - mp_homestead 1 - mp_thaw 1 - mp_black_water_canal 1 - mp_eden 1 - mp_drydock 1 - mp_crashsite3 1 - mp_complex3 1 - mp_angel_city 1 - mp_colony02 1 - mp_glitch 1 + mp_forwardbase_kodai 1 + mp_grave 1 + mp_homestead 1 + mp_thaw 1 + mp_black_water_canal 1 + mp_eden 1 + mp_drydock 1 + mp_crashsite3 1 + mp_complex3 1 + mp_angel_city 1 + mp_colony02 1 + mp_glitch 1 mp_lf_stacks 1 mp_lf_deck 1 mp_lf_meadow 1 @@ -439,14 +439,14 @@ Next, inside this `playlists_v2.txt`, we will need to allow/disallow what maps c mp_relic02 1 mp_wargames 1 mp_rise 1 - mp_coliseum 1 - mp_coliseum_column 1 + mp_coliseum 1 + mp_coliseum_column 1 } } } } - } } +} ``` There isn't much to say here except that we enabled this gamemode to played on all maps. So if this gamemode is set to auto-rotate maps in a server, it will go from one map to the next in order. You could disable certain maps by changing the `1` to a `0`. diff --git a/docs/Modding/guides/tools/BIKVideoModding.md b/docs/Modding/guides/tools/BIKVideoModding.md index 1b8dac6e..96f3ac02 100644 --- a/docs/Modding/guides/tools/BIKVideoModding.md +++ b/docs/Modding/guides/tools/BIKVideoModding.md @@ -27,10 +27,10 @@ The Video will now be in the same folder as the original one and converted to a 3. Make a mod according to [Getting Started](../gettingstarted.md) 4. Copy the .bik to the following path in your mod folder: ```text - author.mod/ - ├─ mod.json - ├─ media/ - │ ├─ menu_act01.bik + author.mod/ + ├─ mod.json + ├─ media/ + │ ├─ menu_act01.bik ``` 5. Your mod should now load a custom Main Menu Video diff --git a/docs/Modding/guides/tools/MDLModding.md b/docs/Modding/guides/tools/MDLModding.md index 2fc802e2..f2098a6a 100644 --- a/docs/Modding/guides/tools/MDLModding.md +++ b/docs/Modding/guides/tools/MDLModding.md @@ -105,14 +105,14 @@ We will add a cube to the side of the Flatline and assign a custom material to i - You will now see a list of all files in the `.vpk` file on the left side looking something like this: ``` text - RootDir - ├── materials - ├── resource - ├── cfg - ├── scripts - ├── models - ├── maps - └── depot +RootDir +├── materials +├── resource +├── cfg +├── scripts +├── models +├── maps +└── depot ``` - Navigate to the `models` folder (this is where all models in this file are located). @@ -265,13 +265,13 @@ If you have materials with multiple paths (different folders in the game files) Usage: ```text - $renamematerial +$renamematerial ``` Example: ```text - $renamematerial "models\weapons_r2\coolmaterial\cool_material" "models\amazing\uncoolmaterial\cool_material2" +$renamematerial "models\weapons_r2\coolmaterial\cool_material" "models\amazing\uncoolmaterial\cool_material2" ``` Command docs: [VALVe developer docs $renamematerial](https://developer.valvesoftware.com/wiki/$renamematerial) @@ -294,11 +294,11 @@ Command docs: [VALVe developer docs $renamematerial](https://developer.valvesoft - Open your `.qc` file in a text editor of your choice. - On the top of the file you will see so called "bodygroup" lines, these are used to define the bodygroups of the model. They look a bit like this: ``` - $bodygroup "body" - { - studio "ptpov_vinson_v_vinson.smd" - blank - } + $bodygroup "body" + { + studio "ptpov_vinson_v_vinson.smd" + blank + } ``` - For each bodygroup you will want to change the files to be the dmx files you exported in the previous step. (in most cases its gonna be just renaming all the files to `.dmx` instead of `.smd`). diff --git a/docs/Modding/guides/tools/VTFModding.md b/docs/Modding/guides/tools/VTFModding.md index efa8294a..3a3d661b 100644 --- a/docs/Modding/guides/tools/VTFModding.md +++ b/docs/Modding/guides/tools/VTFModding.md @@ -63,38 +63,38 @@ In the same folder you extracted your mdl's. Make a `materials` folder next to t Example: ``` - models - materials +models +materials ``` Recreate the path you changed in the `materials` folder, such that the last section is a .vmt file: ```text - materials - └─ models - └─ weapons_r2 - └─ car_smg - └─ car_ctm.vmt +materials +└─ models + └─ weapons_r2 + └─ car_smg + └─ car_ctm.vmt ``` Inside your .vmt paste: ``` - "UnlitTwoTexture" - { - - "$surfaceprop" "metal" - "$basetexture" "" - "$texture2" "" - "$bumpmap" "" - "$allowoverbright" "1" - "$vertexcolor" 1 - "$vertexalpha" 1 - "$decal" "1" - "$model" 1 - "$nocull" "1" - } +"UnlitTwoTexture" +{ + + "$surfaceprop" "metal" + "$basetexture" "" + "$texture2" "" + "$bumpmap" "" + "$allowoverbright" "1" + "$vertexcolor" 1 + "$vertexalpha" 1 + "$decal" "1" + "$model" 1 + "$nocull" "1" +} ``` @@ -127,19 +127,19 @@ In some cases you might have to create another vtf with literally any image. Put Your root folder should look somewhat like this ```text - root - ├─ materials - │ └─ models - │ └─ weapons_r2 - │ └─ car_smg - │ ├─ YOURTEXTURE.vtf - │ ├─ YOURTEXTURE.vtf - │ └─ car_ctm.vmt - └─ models - └─ weapons - └─car101 - ├─ ptpov_car101.mdl - └─ w_car101.mdl +root +├─ materials +│ └─ models +│ └─ weapons_r2 +│ └─ car_smg +│ ├─ YOURTEXTURE.vtf +│ ├─ YOURTEXTURE.vtf +│ └─ car_ctm.vmt +└─ models + └─ weapons + └─car101 + ├─ ptpov_car101.mdl + └─ w_car101.mdl ``` @@ -158,15 +158,15 @@ You need to create a .vtf texture with multiple frames imported to a single .vtf At the bottom of your vmt but before the `}`, add this: ```text - "Proxies" - { - AnimatedTexture - { - animatedTextureVar $basetexture - animatedTextureFrameNumVar $frame - animatedTextureFrameRate 30 - } - } +"Proxies" +{ + AnimatedTexture + { + animatedTextureVar $basetexture + animatedTextureFrameNumVar $frame + animatedTextureFrameRate 30 + } +} ``` diff --git a/docs/Modding/guides/tools/rpakmodding.md b/docs/Modding/guides/tools/rpakmodding.md index 18fb9c73..3a20abea 100644 --- a/docs/Modding/guides/tools/rpakmodding.md +++ b/docs/Modding/guides/tools/rpakmodding.md @@ -30,12 +30,12 @@ Once it has been downloaded, it is recommended to set up your file structure as Depending on the version of RePak, some of these folders and files might be already there for you ```text - RePak - ├── RePak.exe - ├── pack_all.bat - ├── rpaks - ├── maps - └── assets +RePak +├── RePak.exe +├── pack_all.bat +├── rpaks +├── maps +└── assets ``` - `RePak`: the base folder where your RePak/RPak related files go @@ -51,8 +51,8 @@ Once it has been downloaded, it is recommended to set up your file structure as Below is the script that should be copied into the file. ```bat - for %%i in ("%~dp0maps\*") do "%~dp0RePak.exe" "%%i" - pause +for %%i in ("%~dp0maps\*") do "%~dp0RePak.exe" "%%i" +pause ``` ## Making RPaks @@ -121,19 +121,19 @@ They can be named anything you want, but should be put in the `RePak\maps` folde Below is an example of a map file that creates an RPak called `example.rpak` which contains 1 texture asset. ```json - { - "name":"example", - "assetsDir":"../assets", - "outputDir":"../rpaks", - "starpakPath": "example.starpak", - "version": 7, - "files":[ - { - "$type":"txtr", - "path":"texture/models/camo_skins/camo_skin04_col" - } - ] - } +{ + "name":"example", + "assetsDir":"../assets", + "outputDir":"../rpaks", + "starpakPath": "example.starpak", + "version": 7, + "files":[ + { + "$type":"txtr", + "path":"texture/models/camo_skins/camo_skin04_col" + } + ] +} ``` - `name`: the name of the file that gets created by RePak. @@ -176,20 +176,20 @@ In this example, the `camo_skin04_col.rpak` rpak is completely replaced by `exam This is fine for camo RPaks, but isn't suitable for more complex RPaks ```json +{ + "Preload": + { + "example.rpak": false + }, + "Aliases": + { + "camo_skin04_col.rpak": "example.rpak" + }, + "Postload": { - "Preload": - { - "example.rpak": false - }, - "Aliases": - { - "camo_skin04_col.rpak": "example.rpak" - }, - "Postload": - { - } } +} ``` - `Preload`: if set to `true` this makes RPaks get loaded as soon as possible. @@ -229,10 +229,10 @@ The file structure of your `paks` folder should be similar to this: ![PaksStructure](https://user-images.githubusercontent.com/66967891/181840126-98e48860-84d0-496d-8f2e-1cea4dea7363.png) ```text - paks - ├── example.rpak - ├── example.starpak - └── rpak.json +paks +├── example.rpak +├── example.starpak +└── rpak.json ``` - `example.rpak`: this is the RPak file that you made. diff --git a/docs/Modding/guides/tools/soundmodding.md b/docs/Modding/guides/tools/soundmodding.md index 8d2fc7d2..cb5635e2 100644 --- a/docs/Modding/guides/tools/soundmodding.md +++ b/docs/Modding/guides/tools/soundmodding.md @@ -63,12 +63,12 @@ Example of a `mod.json` (documented here: [Getting Started](../gettingstarted.md ```json - { - "Name": "MOD_NAME_HERE", - "Description": "DESCRIPTION_HERE", - "Version": "0.1.0", - "LoadPriority": 2 - } +{ + "Name": "MOD_NAME_HERE", + "Description": "DESCRIPTION_HERE", + "Version": "0.1.0", + "LoadPriority": 2 +} ``` @@ -82,10 +82,10 @@ The event JSON files must contain both `EventId` and `AudioSelectionStrategy` li ```json - { - "EventId": [ "pilot_grapple_fire" ], - "AudioSelectionStrategy": "sequential" - } +{ + "EventId": [ "pilot_grapple_fire" ], + "AudioSelectionStrategy": "sequential" +} ``` The `AudioSelectionStrategy` can be either: @@ -128,12 +128,12 @@ This is usually because there's some metadata left in the audio. Remove it to fi ??? script ```shell - shopt -s globstar nullglob - for f in *.wav **/*.wav - do - ffmpeg -i "$f" -map 0 -map_metadata -1 -c:v copy -c:a copy "${f%.wav}.new.wav" - mv -f "${f%.wav}.new.wav" "$f" - done + shopt -s globstar nullglob + for f in *.wav **/*.wav + do + ffmpeg -i "$f" -map 0 -map_metadata -1 -c:v copy -c:a copy "${f%.wav}.new.wav" + mv -f "${f%.wav}.new.wav" "$f" + done ``` - Sound is slightly higher/lower pitched in game. This is usually because the sampling rate of your sound doesn't match the original sound's sampling rate. You can use a tool like Audacity to resample your sound to match the original rate. Consult `_creating_your_sound` for more information. @@ -157,43 +157,43 @@ This is usually because there's some metadata left in the audio. Remove it to fi === "WAV script" ```shell - #WAV to WAV 16-bit 48000 Hz. - #wav_converter.sh - - shopt -s globstar nullglob - for f in *.wav **/*.wav - do - ffmpeg -i "$f" -acodec pcm_s16le -ar 48000 "${f%.wav}.new.wav" - mv -f "${f%.wav}.new.wav" "$f" - done + #WAV to WAV 16-bit 48000 Hz. + #wav_converter.sh + + shopt -s globstar nullglob + for f in *.wav **/*.wav + do + ffmpeg -i "$f" -acodec pcm_s16le -ar 48000 "${f%.wav}.new.wav" + mv -f "${f%.wav}.new.wav" "$f" + done ``` === "MP3 Script" ```shell - #MP3 to WAV 16-bit 48000 Hz. - #mp3-wav_converter.sh - - shopt -s globstar nullglob - for f in *.mp3 - do - ffmpeg -i "${f}" -vn -c:a pcm_s16le -ar 48000 "${f%.*}.wav" - done + #MP3 to WAV 16-bit 48000 Hz. + #mp3-wav_converter.sh + + shopt -s globstar nullglob + for f in *.mp3 + do + ffmpeg -i "${f}" -vn -c:a pcm_s16le -ar 48000 "${f%.*}.wav" + done ``` === "Script for other formats" ```shell - #Replace .format with the one you want to convert. - #format-wav_converter.sh - - shopt -s globstar nullglob - for f in *.format - do - ffmpeg -i "${f}" -vn -c:a pcm_s16le -ar 48000 "${f%.*}.wav" - done + #Replace .format with the one you want to convert. + #format-wav_converter.sh + + shopt -s globstar nullglob + for f in *.format + do + ffmpeg -i "${f}" -vn -c:a pcm_s16le -ar 48000 "${f%.*}.wav" + done ``` ## Installation diff --git a/docs/Modding/plugins/interfacesapi.md b/docs/Modding/plugins/interfacesapi.md index e7a665f8..d7b912bd 100644 --- a/docs/Modding/plugins/interfacesapi.md +++ b/docs/Modding/plugins/interfacesapi.md @@ -18,17 +18,17 @@ An interface is just an abstract class to force all functions into a vftable. Exposes some system functionality to plugins ```cpp - // 32 bit - enum LogLevel { - INFO, - WARN, - ERR, - }; - - // handle: handle of the plugin. Passed to the plugin on init. - void Log(HMODULE handle, LogLevel level, char* msg); // logs a message with the plugin's log name - void Unload(HMODULE handle); // unloads the plugin - void Reload(HMODULE handle); +// 32 bit +enum LogLevel { + INFO, + WARN, + ERR, +}; + +// handle: handle of the plugin. Passed to the plugin on init. +void Log(HMODULE handle, LogLevel level, char* msg); // logs a message with the plugin's log name +void Unload(HMODULE handle); // unloads the plugin +void Reload(HMODULE handle); ``` ## Required Plugin Interfaces @@ -38,37 +38,37 @@ Interfaces that have to be exposed for the plugin to be loaded. ### PluginId001 ```cpp - // strings of data about the plugin itself. may be extended in the future - // 32 bit - enum PluginString { - NAME, // the name of the plugin - LOG_NAME, // the name used for logging - DEPENDENCY_NAME, // the name used for squirrel dependency constants created. The value returned for this has to be a valid squirrel identifier or the plugin will fail to load - } - - // bitfields about the plugin - // 32 bit - enum PluginField { - CONTEXT // 0x1 if the plugin is allowed to run on dedicated servers and 0x2 if the plugin is allowed to run on clients (is this even needed seems useless to me) - } - - char* GetString(PluginString prop); - i64 GetField(PluginField prop); +// strings of data about the plugin itself. may be extended in the future +// 32 bit +enum PluginString { + NAME, // the name of the plugin + LOG_NAME, // the name used for logging + DEPENDENCY_NAME, // the name used for squirrel dependency constants created. The value returned for this has to be a valid squirrel identifier or the plugin will fail to load +} + +// bitfields about the plugin +// 32 bit +enum PluginField { + CONTEXT // 0x1 if the plugin is allowed to run on dedicated servers and 0x2 if the plugin is allowed to run on clients (is this even needed seems useless to me) +} + +char* GetString(PluginString prop); +i64 GetField(PluginField prop); ``` ### PluginCallbacks001 ```cpp - struct PluginNorthstarData { HMODULE handle; }; - - // COPY THE initData IT MAY BE MOVED AT RUNTIME - void Init(HMODULE nsModule, const PluginNorthstarData* initData, bool reloaded); // called after the plugin has been validated. The nsmodule allows northstar plugins to work for the ronin client as well (assuming they update their fork lmao) - void Finalize(); // called after all plugins have been loaded. Useful for dependencies - void Unload(); // called just before the plugin is getting unloaded - void OnSqvmCreated(CSquirrelVM* sqvm); // the context of the sqvm is contained in the instance - void OnSqvmDestroying(CSquirrelVM* sqvm); // callback with the sqvm instance that's about to be destroyed (for UI, CLIENT is destroyed for some reason??) - void OnLibraryLoaded(HMODULE module, const char* libraryName); // called for any library loaded by the game (for example engine.dll) - void RunFrame(); // just runs on every frame of the game I think +struct PluginNorthstarData { HMODULE handle; }; + +// COPY THE initData IT MAY BE MOVED AT RUNTIME +void Init(HMODULE nsModule, const PluginNorthstarData* initData, bool reloaded); // called after the plugin has been validated. The nsmodule allows northstar plugins to work for the ronin client as well (assuming they update their fork lmao) +void Finalize(); // called after all plugins have been loaded. Useful for dependencies +void Unload(); // called just before the plugin is getting unloaded +void OnSqvmCreated(CSquirrelVM* sqvm); // the context of the sqvm is contained in the instance +void OnSqvmDestroying(CSquirrelVM* sqvm); // callback with the sqvm instance that's about to be destroyed (for UI, CLIENT is destroyed for some reason??) +void OnLibraryLoaded(HMODULE module, const char* libraryName); // called for any library loaded by the game (for example engine.dll) +void RunFrame(); // just runs on every frame of the game I think ``` ## What's an interface anyways? @@ -78,21 +78,21 @@ Interfaces are just abstract classes. So make sure the first parameter is always an example what NSSys001 looks like in C: ```cpp - typedef enum { - LOG_INFO, - LOG_WARN, - LOG_ERR, - }; - - typedef struct CSys { - struct { +typedef enum { + LOG_INFO, + LOG_WARN, + LOG_ERR, +}; + +typedef struct CSys { + struct { void (*log)(struct CSys* self, HMODULE handle, LogLevel level, char* msg); void (*unload)(struct CSys* self, HMODULE handle); - }* vftable; - } CSys; + }* vftable; +} CSys; - // use like this - g_c_sys->vftable->log(g_c_sys, g_handle, LOG_INFO, "my balls are itching"); +// use like this +g_c_sys->vftable->log(g_c_sys, g_handle, LOG_INFO, "my balls are itching"); ``` Interfaces are created with CreateInterface that's exposed in another dll. diff --git a/docs/Modding/reference/northstar/chathooks.md b/docs/Modding/reference/northstar/chathooks.md index 961d3e28..39ab0d53 100644 --- a/docs/Modding/reference/northstar/chathooks.md +++ b/docs/Modding/reference/northstar/chathooks.md @@ -57,22 +57,22 @@ The client chat callbacks allow you to intercept chat messages and modify or blo **Example:** ```squirrel - ClClient_MessageStruct function MyChatFilter(ClClient_MessageStruct message) + ClClient_MessageStruct function MyChatFilter(ClClient_MessageStruct message) + { + if (message.message.find("nft") != null) { - if (message.message.find("nft") != null) - { - message.shouldBlock = true - } + message.shouldBlock = true + } - message.message = StringReplace(message.message, "yes", "no", true, true) + message.message = StringReplace(message.message, "yes", "no", true, true) - return message - } + return message + } - void function MyModInit() - { - AddCallback_OnReceivedSayTextMessage(MyChatFilter) - } + void function MyModInit() + { + AddCallback_OnReceivedSayTextMessage(MyChatFilter) + } ``` @@ -88,10 +88,10 @@ players, they only display them locally. **Example:** ```squirrel - void function OnGameStarted() - { - Chat_GameWriteLine("You got this, " + GetLocalClientPlayer().GetPlayerName() + "!") - } + void function OnGameStarted() + { + Chat_GameWriteLine("You got this, " + GetLocalClientPlayer().GetPlayerName() + "!") + } ``` @@ -102,18 +102,18 @@ players, they only display them locally. **Example:** ```squirrel - void function InitialiseHEVSuit() - { - Chat_GameWriteLine("SENSOR ARRAYS-") - ActivateSensorArrays() - Chat_GameWrite("ACTIVATED") - wait 1 - Chat_GameWriteLine("BIOMETRIC MONITORING SYSTEMS-") - ActivateBiometricMonitoringSystems() - Chat_GameWrite("ACTIVATED") - wait 1 - Chat_GameWriteLine("HAVE A VERY SAFE DAY.") - } + void function InitialiseHEVSuit() + { + Chat_GameWriteLine("SENSOR ARRAYS-") + ActivateSensorArrays() + Chat_GameWrite("ACTIVATED") + wait 1 + Chat_GameWriteLine("BIOMETRIC MONITORING SYSTEMS-") + ActivateBiometricMonitoringSystems() + Chat_GameWrite("ACTIVATED") + wait 1 + Chat_GameWriteLine("HAVE A VERY SAFE DAY.") + } ``` !!! cpp-function "void Chat_NetworkWriteLine(string text)" @@ -123,10 +123,10 @@ players, they only display them locally. **Example:** ```squirrel - void function MyModInit() - { - Chat_NetworkWriteLine("MyMod v1.0.0 is good to go!") - } + void function MyModInit() + { + Chat_NetworkWriteLine("MyMod v1.0.0 is good to go!") + } ``` @@ -137,17 +137,17 @@ players, they only display them locally. **Example:** ```squirrel - void function OnButtonPressed() - { - Chat_NetworkWrite("Connecting in 3...") - wait 1 - Chat_NetworkWrite("2...") - wait 1 - Chat_NetworkWrite("1...") - wait 1 - Chat_NetworkWrite("0") - Connect() - } + void function OnButtonPressed() + { + Chat_NetworkWrite("Connecting in 3...") + wait 1 + Chat_NetworkWrite("2...") + wait 1 + Chat_NetworkWrite("1...") + wait 1 + Chat_NetworkWrite("0") + Connect() + } ``` @@ -189,21 +189,21 @@ The server chat callbacks allow you to intercept incoming chat messages and modi **Example:** ```squirrel - ClServer_MessageStruct function MyChatFilter(ClServer_MessageStruct message) + ClServer_MessageStruct function MyChatFilter(ClServer_MessageStruct message) + { + if (message.message.find("nft") != null) { - if (message.message.find("nft") != null) - { - message.shouldBlock = true - } + message.shouldBlock = true + } - message.message = StringReplace(message.message, "yes", "no", true, true) + message.message = StringReplace(message.message, "yes", "no", true, true) - return message - } - void function MyModInit() - { - AddCallback_OnReceivedSayTextMessage(MyChatFilter) - } + return message + } + void function MyModInit() + { + AddCallback_OnReceivedSayTextMessage(MyChatFilter) + } ``` @@ -225,10 +225,10 @@ With custom messages you can send chat messages at any time, to all players or t **Example:** ```squirrel - void function OnSayRedCommand(entity player, string text) - { - Chat_Impersonate(player, "red text -> \x1b[31m" + text) - } + void function OnSayRedCommand(entity player, string text) + { + Chat_Impersonate(player, "red text -> \x1b[31m" + text) + } ``` @@ -247,14 +247,14 @@ With custom messages you can send chat messages at any time, to all players or t **Example:** ```squirrel - void function OnSendToFriendsCommand(entity fromPlayer, string text) + void function OnSendToFriendsCommand(entity fromPlayer, string text) + { + array friends = GetPlayerFriends(fromPlayer) + foreach (friend in friends) { - array friends = GetPlayerFriends(fromPlayer) - foreach (friend in friends) - { - Chat_PrivateMessage(fromPlayer, friend, text, true) - } + Chat_PrivateMessage(fromPlayer, friend, text, true) } + } ``` @@ -270,22 +270,22 @@ With custom messages you can send chat messages at any time, to all players or t **Example:** ```squirrel - void function RestartServerThread() - { - // wait one hour - wait 3600 - Chat_ServerBroadcast("Server will be shut down in \x1b[93m5 seconds") - wait 1 - Chat_ServerBroadcast("Server will be shut down in \x1b[93m4 seconds") - wait 1 - Chat_ServerBroadcast("Server will be shut down in \x1b[93m3 seconds") - wait 1 - Chat_ServerBroadcast("Server will be shut down in \x1b[93m2 seconds") - wait 1 - Chat_ServerBroadcast("Server will be shut down in \x1b[93m1 second") - wait 1 - StopServer() - } + void function RestartServerThread() + { + // wait one hour + wait 3600 + Chat_ServerBroadcast("Server will be shut down in \x1b[93m5 seconds") + wait 1 + Chat_ServerBroadcast("Server will be shut down in \x1b[93m4 seconds") + wait 1 + Chat_ServerBroadcast("Server will be shut down in \x1b[93m3 seconds") + wait 1 + Chat_ServerBroadcast("Server will be shut down in \x1b[93m2 seconds") + wait 1 + Chat_ServerBroadcast("Server will be shut down in \x1b[93m1 second") + wait 1 + StopServer() + } ``` @@ -303,16 +303,16 @@ With custom messages you can send chat messages at any time, to all players or t **Example:** ```squirrel - void function OnBanCommand(entity player, array args) + void function OnBanCommand(entity player, array args) + { + if (!PlayerIsModerator(player)) { - if (!PlayerIsModerator(player)) - { - Chat_ServerPrivateMessage(player, "You do not have the permissions to perform this command.", true, false) - return - } - - BanPlayerByName(args[0]) + Chat_ServerPrivateMessage(player, "You do not have the permissions to perform this command.", true, false) + return } + + BanPlayerByName(args[0]) + } ``` @@ -322,7 +322,7 @@ All messages support ANSI escape codes for customising text color. These are com meaning. For example, the string: ```text - Hello world, \x1b[31mthis text is red\x1b[0m. And \x1b[34mthis text is blue\x1b[0m. +Hello world, \x1b[31mthis text is red\x1b[0m. And \x1b[34mthis text is blue\x1b[0m. ``` `\x1b` is a special character that Squirrel (and other languages) replace with a reserved ASCII character. For future diff --git a/docs/Modding/reference/northstar/customdamagesources.md b/docs/Modding/reference/northstar/customdamagesources.md index b8638d7d..07477305 100644 --- a/docs/Modding/reference/northstar/customdamagesources.md +++ b/docs/Modding/reference/northstar/customdamagesources.md @@ -19,47 +19,47 @@ Damage source IDs should be added in `"After"` server callbacks. For example, we can call the methods from a function in `damage_source_example.nut`: ```squirrel - global function SimpleSourceInit - - void function SimpleSourceInit() - { - // Server-side code - - // Register a single damage source ID - RegisterWeaponDamageSource( "mp_weapon_minigun", "Minigun" ) - - // Register multiple damage source IDs - RegisterWeaponDamageSources( - { - mp_titanweapon_barrage_core_launcher = "Barrage Core", - mp_titanweapon_grenade_launcher = "Grenade Launcher" - } - ) - } +global function SimpleSourceInit + +void function SimpleSourceInit() +{ + // Server-side code + + // Register a single damage source ID + RegisterWeaponDamageSource( "mp_weapon_minigun", "Minigun" ) + + // Register multiple damage source IDs + RegisterWeaponDamageSources( + { + mp_titanweapon_barrage_core_launcher = "Barrage Core", + mp_titanweapon_grenade_launcher = "Grenade Launcher" + } + ) +} ``` Then call the function as an `"After"` server callback in the `mod.json`: ```javascript - { - "Scripts": [ - { - "Path": "damage_source_example.nut", - "RunOn": "SERVER && MP", - "ServerCallback": { - "After": "SimpleSourceInit" - } - }, - ] - } +{ + "Scripts": [ + { + "Path": "damage_source_example.nut", + "RunOn": "SERVER && MP", + "ServerCallback": { + "After": "SimpleSourceInit" + } + }, + ] +} ``` Now, these damage source IDs can be referenced in script like so: ```squirrel - eDamageSourceId.mp_weapon_minigun - eDamageSourceId.mp_titanweapon_barrage_core_launcher - eDamageSourceId.mp_titanweapon_grenade_launcher +eDamageSourceId.mp_weapon_minigun +eDamageSourceId.mp_titanweapon_barrage_core_launcher +eDamageSourceId.mp_titanweapon_grenade_launcher ``` and their corresponding precached weapons (if applicable) will automatically use their custom damage source IDs. diff --git a/docs/Modding/reference/northstar/dependencyconstants.md b/docs/Modding/reference/northstar/dependencyconstants.md index 6fcbd9ab..5ed7b178 100644 --- a/docs/Modding/reference/northstar/dependencyconstants.md +++ b/docs/Modding/reference/northstar/dependencyconstants.md @@ -18,17 +18,17 @@ Contditons you can check for are These conditions can also be combined with the regular squirrel boolean expressions ```squirrel - #if SERVER - Chat_ServerBroadcast("Message from the server VM") - #endif +#if SERVER +Chat_ServerBroadcast("Message from the server VM") +#endif ``` ```squirrel - #if (CLIENT && MP) || DEV - ... - #elseif SP - ... - #endif +#if (CLIENT && MP) || DEV +... +#elseif SP +... +#endif ``` ## Dependency Constants @@ -39,29 +39,29 @@ loaded, these use the Compiler directives syntax. Inside your `mod.json` define a constant as: ```squirrel - { - // mod.json stuff - "Dependencies": { - // sets the constant to 0 or 1, depending if the mod with the name "Mod Name" exists and is enabled - "CONSTANT_NAME": "Mod Name" - } +{ + // mod.json stuff + "Dependencies": { + // sets the constant to 0 or 1, depending if the mod with the name "Mod Name" exists and is enabled + "CONSTANT_NAME": "Mod Name" } +} ``` For Example: ```json - "PLAYER_HAS_ROGUELIKE_MOD": "TF|Roguelike" +"PLAYER_HAS_ROGUELIKE_MOD": "TF|Roguelike" ``` Will define a constant `PLAYER_HAS_ROGUELIKE_MOD` that is set to `0` or `1` depending if the mod is enabled. It then can be used as a constant/compiler flag. ```squirrel - #if PLAYER_HAS_ROGUELIKE_MOD - print("player has roguelike mod") - Roguelike_Function(); - #else - print("Can't use the function because the mod is off :'(") - #endif +#if PLAYER_HAS_ROGUELIKE_MOD +print("player has roguelike mod") +Roguelike_Function(); +#else +print("Can't use the function because the mod is off :'(") +#endif ``` diff --git a/docs/Modding/reference/northstar/httprequests.md b/docs/Modding/reference/northstar/httprequests.md index 5d3fb288..a6c1bfa8 100644 --- a/docs/Modding/reference/northstar/httprequests.md +++ b/docs/Modding/reference/northstar/httprequests.md @@ -185,22 +185,22 @@ The HTTP system uses a few enums and structs for requests and their callbacks. such as `callback` in this example. ```squirrel - HttpRequest request - request.method = HttpRequestMethod.GET - request.url = "https://my.spyglass.api/sanctions/get_by_id" - request.queryParameters[ "id" ] <- [ id.tostring() ] - - void functionref( HttpRequestResponse ) onSuccess = void function ( HttpRequestResponse response ) : ( callback ) - { - SpyglassApi_OnQuerySanctionByIdSuccessful( response, callback ) - } - - void functionref( HttpRequestFailure ) onFailure = void function ( HttpRequestFailure failure ) : ( callback ) - { - SpyglassApi_OnQuerySanctionByIdFailed( failure, callback ) - } - - return NSHttpRequest( request, onSuccess, onFailure ) + HttpRequest request + request.method = HttpRequestMethod.GET + request.url = "https://my.spyglass.api/sanctions/get_by_id" + request.queryParameters[ "id" ] <- [ id.tostring() ] + + void functionref( HttpRequestResponse ) onSuccess = void function ( HttpRequestResponse response ) : ( callback ) + { + SpyglassApi_OnQuerySanctionByIdSuccessful( response, callback ) + } + + void functionref( HttpRequestFailure ) onFailure = void function ( HttpRequestFailure failure ) : ( callback ) + { + SpyglassApi_OnQuerySanctionByIdFailed( failure, callback ) + } + + return NSHttpRequest( request, onSuccess, onFailure ) ``` @@ -228,20 +228,20 @@ The HTTP system uses a few enums and structs for requests and their callbacks. This is the same example as NSHttpRequest()'s example. However, it uses this function instead. ```squirrel - table > params - params[ "id" ] <- [ id.tostring() ] + table > params + params[ "id" ] <- [ id.tostring() ] - void functionref( HttpRequestResponse ) onSuccess = void function ( HttpRequestResponse response ) : ( callback ) - { - SpyglassApi_OnQuerySanctionByIdSuccessful( response, callback ) - } + void functionref( HttpRequestResponse ) onSuccess = void function ( HttpRequestResponse response ) : ( callback ) + { + SpyglassApi_OnQuerySanctionByIdSuccessful( response, callback ) + } - void functionref( HttpRequestFailure ) onFailure = void function ( HttpRequestFailure failure ) : ( callback ) - { - SpyglassApi_OnQuerySanctionByIdFailed( failure, callback ) - } + void functionref( HttpRequestFailure ) onFailure = void function ( HttpRequestFailure failure ) : ( callback ) + { + SpyglassApi_OnQuerySanctionByIdFailed( failure, callback ) + } - return NSHttpGet( "https://my.spyglass.api/sanctions/get_by_id", params, onSuccess, onFailure ) + return NSHttpGet( "https://my.spyglass.api/sanctions/get_by_id", params, onSuccess, onFailure ) ``` @@ -289,16 +289,16 @@ The HTTP system uses a few enums and structs for requests and their callbacks. In this example, we'll convert a table to JSON, and send it over to a web API. ```squirrel - table myData = {} - myData[ "uid" ] <- player.GetUID() - myData[ "username" ] <- player.GetPlayerName() - myData[ "isBot" ] <- player.IsBot().tostring() - - string json = EncodeJSON( myData ) - if ( NSHttpPostBody( "https://api.stats.tf/player/connect", json ) ) - { - printt( "Successfully attempted to upload player connection stats to API." ) - } + table myData = {} + myData[ "uid" ] <- player.GetUID() + myData[ "username" ] <- player.GetPlayerName() + myData[ "isBot" ] <- player.IsBot().tostring() + + string json = EncodeJSON( myData ) + if ( NSHttpPostBody( "https://api.stats.tf/player/connect", json ) ) + { + printt( "Successfully attempted to upload player connection stats to API." ) + } ``` diff --git a/docs/Modding/reference/northstar/modsettings.md b/docs/Modding/reference/northstar/modsettings.md index 45895d80..961f508f 100644 --- a/docs/Modding/reference/northstar/modsettings.md +++ b/docs/Modding/reference/northstar/modsettings.md @@ -7,11 +7,11 @@ ConVars are the easiest way to implement settings for your mod using the Mod Set Your mod needs to register itself and all ConVars that are a part of your mod that should be accessible in the Mod Settings menu. To do this, simply add a new script to your mod that runs only in the UI VM like this: ```json - "Path": "ui/ms_example_mod.nut", - "RunOn": "UI", - "UICallback": { +"Path": "ui/ms_example_mod.nut", +"RunOn": "UI", +"UICallback": { "Before": "ExampleMod_AddModSettings" - } +} ``` Inside of the callback specified here, you can add your settings. @@ -120,10 +120,10 @@ Inside of the callback specified here, you can add your settings. To create custom wrapper functions you need to specify the stack position where the root of your Mod Setting declarations take place. ```squirrel - void function AddModSettingsDropDown( string displayName, array options ) - { +void function AddModSettingsDropDown( string displayName, array options ) +{ NSModSettingsAddButton( displayName, void function() { OpenDropDown( options ) }, 3 ) - } +} ``` Note that in this example the stack position is `3`, since `AddModSettingsButton` needs to walk one additional step to the callback function. diff --git a/docs/Modding/reference/northstar/serversiderui.md b/docs/Modding/reference/northstar/serversiderui.md index 1f6a03ca..49992be7 100644 --- a/docs/Modding/reference/northstar/serversiderui.md +++ b/docs/Modding/reference/northstar/serversiderui.md @@ -22,12 +22,12 @@ alt="/_static/serversiderui/vote.png" /> **Example:** ```squirrel - void function CreateDummyPoll() - { - array options = [ "Vote for a map!", "Amongsus", "sussy", "when", "1.10", "hi H0l0" ] - foreach(entity player in GetPlayerArray()) - NSCreatePollOnPlayer(player, "Vote who's the biggest dummy!", options, 30) - } +void function CreateDummyPoll() +{ + array options = [ "Vote for a map!", "Amongsus", "sussy", "when", "1.10", "hi H0l0" ] + foreach(entity player in GetPlayerArray()) + NSCreatePollOnPlayer(player, "Vote who's the biggest dummy!", options, 30) +} ``` ### Getting Response @@ -41,11 +41,11 @@ alt="/_static/serversiderui/vote.png" /> **Example:** ```squirrel - void function CheckResponseToDummyPoll(entity player) - { - if(NSGetPlayerResponse(player) != -1) - print("Player has voted!") - } +void function CheckResponseToDummyPoll(entity player) +{ + if(NSGetPlayerResponse(player) != -1) + print("Player has voted!") +} ``` ## Large Message @@ -65,10 +65,10 @@ alt="/_static/serversiderui/largemessage.gif" /> **Example:** ```squirrel - void function SendDummyLargeMessage(entity player) - { - NSSendLargeMessageToPlayer(player,"I'm not a dummy >:(", "You are", 10, "ui/fd_tutorial_tip.rpak") - } +void function SendDummyLargeMessage(entity player) +{ + NSSendLargeMessageToPlayer(player,"I'm not a dummy >:(", "You are", 10, "ui/fd_tutorial_tip.rpak") +} ``` ## Info Message @@ -88,10 +88,10 @@ alt="/_static/serversiderui/info.gif" /> **Example:** ```squirrel - void function SendDummyInfoMessage(entity player) - { - NSSendInfoMessageToPlayer(player, "we were sent at the same time but I was sent sooner") - } +void function SendDummyInfoMessage(entity player) +{ + NSSendInfoMessageToPlayer(player, "we were sent at the same time but I was sent sooner") +} ``` ## PopUp @@ -111,10 +111,10 @@ alt="/_static/serversiderui/popup.gif" /> **Example:** ```squirrel - void funcions SendDummyPopUp(entity player) - { - NSSendPopUpMessageToPlayer(player, "very cool text I like") - } +void funcions SendDummyPopUp(entity player) +{ + NSSendPopUpMessageToPlayer(player, "very cool text I like") +} ``` ## Announcement @@ -134,10 +134,10 @@ alt="/_static/serversiderui/announcement.gif" /> **Example:** ```squirrel - void function SendDummyAnnouncement(entity player) - { - NSSendAnnouncementMessageToPlayer(player, "Very cool announcement", "Hi Karma", <1,1,0>, 1, ANNOUNCEMENT_STYLE_QUICK) - } +void function SendDummyAnnouncement(entity player) +{ + NSSendAnnouncementMessageToPlayer(player, "Very cool announcement", "Hi Karma", <1,1,0>, 1, ANNOUNCEMENT_STYLE_QUICK) +} ``` ## Status @@ -168,13 +168,13 @@ alt="/_static/serversiderui/status.gif" /> **Examples:** ```squirrel - void function TestStatusMessage_Threaded(entity player) - { - string id = UniqueString("votes#") - NSCreateStatusMessageOnPlayer(player, "have voted", "[0/12]", id) - wait 3 - NSEditStatusMessageOnPlayer(player, "have voted", "[1/12]", id) - wait 10 - NSDeleteStatusMessageOnPlayer(player, id) - } +void function TestStatusMessage_Threaded(entity player) +{ + string id = UniqueString("votes#") + NSCreateStatusMessageOnPlayer(player, "have voted", "[0/12]", id) + wait 3 + NSEditStatusMessageOnPlayer(player, "have voted", "[1/12]", id) + wait 10 + NSDeleteStatusMessageOnPlayer(player, id) +} ``` diff --git a/docs/Modding/reference/northstar/usefulfuncs.md b/docs/Modding/reference/northstar/usefulfuncs.md index 8b064368..e285c48e 100644 --- a/docs/Modding/reference/northstar/usefulfuncs.md +++ b/docs/Modding/reference/northstar/usefulfuncs.md @@ -364,7 +364,7 @@ Below are a list of useful functions added by Northstar. replaces text that should be localized on the client ```squirrel - string localized = Localize( token ) + string localized = Localize( token ) ``` !!! cpp-function "int ornull function string.find( string s )" @@ -376,12 +376,12 @@ Below are a list of useful functions added by Northstar. You can eliminate the possibility of the returned index being null by casting like this: ```squirrel - int ornull index = GetMapName().find( "mp" ) + int ornull index = GetMapName().find( "mp" ) - if( !index ) - return - int( index ) - int n = index + 1 //now we do not need the ornull anymore + if( !index ) + return + int( index ) + int n = index + 1 //now we do not need the ornull anymore ``` !!! cpp-function "string function string.slice( int start, int end = null )" diff --git a/docs/Modding/reference/respawn/clientcommands.md b/docs/Modding/reference/respawn/clientcommands.md index 2bf1d671..12f84a96 100644 --- a/docs/Modding/reference/respawn/clientcommands.md +++ b/docs/Modding/reference/respawn/clientcommands.md @@ -7,11 +7,11 @@ Client commands are how the clients communicate with the server. Mods can define Registers a function as a callback for a client command. This can only be done once per client command string. ```squirrel - AddClientCommandCallback("commandname", commandcallback) + AddClientCommandCallback("commandname", commandcallback) - void CommandCalled(entity player, array args) { - print("commandname: was called with " + args); - } + void CommandCalled(entity player, array args) { + print("commandname: was called with " + args); + } ``` diff --git a/docs/Modding/reference/respawn/dialog.md b/docs/Modding/reference/respawn/dialog.md index abf33c96..4bc19ce1 100644 --- a/docs/Modding/reference/respawn/dialog.md +++ b/docs/Modding/reference/respawn/dialog.md @@ -98,9 +98,9 @@ All the data in the struct that can be changed. **Example** ```squirrel - DialogData dialog - dialog.message = "Hello there" - OpenDialog( dialog ) + DialogData dialog + dialog.message = "Hello there" + OpenDialog( dialog ) ``` !!! cpp-function "void AddDialogButton( DialogData dialog, string text, void functionref() callback )" @@ -116,15 +116,15 @@ All the data in the struct that can be changed. **Example** ```squirrel - void function SendDialogWithButton() - { - DialogData dialog - dialog.message = "Hello there" - AddDialogButton(dialog, "Button 1 %%$r2_ui/menus/loadout_icons/primary_weapon/primary_kraber%%", void function():() { - printt( "pressed button 1" ) - }) - OpenDialog( dialog ) - } + void function SendDialogWithButton() + { + DialogData dialog + dialog.message = "Hello there" + AddDialogButton(dialog, "Button 1 %%$r2_ui/menus/loadout_icons/primary_weapon/primary_kraber%%", void function():() { + printt( "pressed button 1" ) + }) + OpenDialog( dialog ) + } ``` !!! cpp-function "void AddDialogFooter( DialogData dialog, string text )" @@ -150,14 +150,14 @@ All the data in the struct that can be changed. the folowing code produces this output: ```squirrel - DialogData dialog - dialog.header = "This is the header" - dialog.message = "this is the body, it is green \n \n Hello There \n \n General Kenobi" - dialog.messageColor = [0,200,0,100] - dialog.showSpinner = true - dialog.showPCBackButton = true - AddDialogButton( dialog, "Button 1 %%$r2_ui/menus/loadout_icons/primary_weapon/primary_kraber%%", ButtonOnePressed ) - OpenDialog( dialog ) +DialogData dialog +dialog.header = "This is the header" +dialog.message = "this is the body, it is green \n \n Hello There \n \n General Kenobi" +dialog.messageColor = [0,200,0,100] +dialog.showSpinner = true +dialog.showPCBackButton = true +AddDialogButton( dialog, "Button 1 %%$r2_ui/menus/loadout_icons/primary_weapon/primary_kraber%%", ButtonOnePressed ) +OpenDialog( dialog ) ``` diff --git a/docs/Modding/reference/respawn/hud_element_notation.md b/docs/Modding/reference/respawn/hud_element_notation.md index be6c9d5a..4b9211b9 100644 --- a/docs/Modding/reference/respawn/hud_element_notation.md +++ b/docs/Modding/reference/respawn/hud_element_notation.md @@ -10,42 +10,42 @@ It is not possible to create elements at runtime so you have to define all eleme An Element is declared in the following way: ``` - // please follow this structure - ElementName - { - ControlName name - // optional: classname, inheritance, ids ... +// please follow this structure +ElementName +{ + ControlName name + // optional: classname, inheritance, ids ... - // optional: other properties + // optional: other properties - // optional: pinning - } + // optional: pinning +} ``` If you're working on a **menu**, you need a `menu` object that contains all elements, for example like this: ``` - resource/ui/menus/profiles_menu.menu +resource/ui/menus/profiles_menu.menu +{ + menu { - menu - { - ControlName Frame - xpos 0 - ypos 0 - zpos 3 - wide f0 - tall f0 - autoResize 0 - visible 1 - enabled 1 - pinCorner 0 - PaintBackgroundType 0 - infocus_bgcolor_override "0 0 0 0" - outoffocus_bgcolor_override "0 0 0 0" - - // elements - } + ControlName Frame + xpos 0 + ypos 0 + zpos 3 + wide f0 + tall f0 + autoResize 0 + visible 1 + enabled 1 + pinCorner 0 + PaintBackgroundType 0 + infocus_bgcolor_override "0 0 0 0" + outoffocus_bgcolor_override "0 0 0 0" + + // elements } +} ``` It usually doesn't matter if you use quotation marks to assign string values to parameters. @@ -58,15 +58,15 @@ It's not possible to load other files as menus or panels. A `.menu` represents a The rest of the file needs to be wrapped in curly brackets. ``` - resource/ui/menus/more/folders/my_menu.menu +resource/ui/menus/more/folders/my_menu.menu +{ + MyObject { - MyObject - { - // object properties go here - } - - // more objects ... + // object properties go here } + + // more objects ... +} ``` ### Properties @@ -430,9 +430,9 @@ Usable conditions are: the game's language. ```text - // use allcaps only in russian - allCaps 0 [!$RUSSIAN] - allCaps 1 [$RUSSIAN] + // use allcaps only in russian + allCaps 0 [!$RUSSIAN] + allCaps 1 [$RUSSIAN] ``` @@ -442,42 +442,42 @@ On top of that, logical operators like `!`, `&&` and `||` are available as well. #### Example: ```text - // This element only shows on pc - IngameTextChat [$WINDOWS] - { - ControlName CBaseHudChat - InheritProperties ChatBox - - destination "match" - - visible 0 - - pin_to_sibling Screen - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_LEFT - xpos -45 - ypos -616 - } - - // This element has different widths depending on the game resolution - LoadingTip - { - ControlName Label - ypos 10 - wide 1630 [$WIDESCREEN_16_9] - wide 1441 [!$WIDESCREEN_16_9] - auto_tall_tocontents 1 - labelText "" - textalign "north-west" - font Default_28 - wrap 1 - fgcolor_override "217 170 75 255" - visible 0 - - pin_to_sibling LoadingGameMode - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } +// This element only shows on pc +IngameTextChat [$WINDOWS] +{ + ControlName CBaseHudChat + InheritProperties ChatBox + + destination "match" + + visible 0 + + pin_to_sibling Screen + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_LEFT + xpos -45 + ypos -616 +} + +// This element has different widths depending on the game resolution +LoadingTip +{ + ControlName Label + ypos 10 + wide 1630 [$WIDESCREEN_16_9] + wide 1441 [!$WIDESCREEN_16_9] + auto_tall_tocontents 1 + labelText "" + textalign "north-west" + font Default_28 + wrap 1 + fgcolor_override "217 170 75 255" + visible 0 + + pin_to_sibling LoadingGameMode + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT +} ``` @@ -528,9 +528,9 @@ You can calculate the position or dimensions etc. with different units. If you p x percent of the screen. ``` - // cover the entire screen - width %100 - height %100 + // cover the entire screen + width %100 + height %100 ``` !!! cpp-function "fx" diff --git a/docs/Modding/reference/respawn/hud_menus.md b/docs/Modding/reference/respawn/hud_menus.md index 81682d96..881cc0ea 100644 --- a/docs/Modding/reference/respawn/hud_menus.md +++ b/docs/Modding/reference/respawn/hud_menus.md @@ -7,24 +7,24 @@ Before working on HUD, it's recommended to `extract ) +entity mover = CreateScriptMover( <0,0,0> ) - // moving the mover to <0,0,10> in 1 second - mover.NonPhysicsMoveTo( <0,0,10>, 1, 0, 0 ) +// moving the mover to <0,0,10> in 1 second +mover.NonPhysicsMoveTo( <0,0,10>, 1, 0, 0 ) - // wating so the mover gets to the destination - wait 1 +// wating so the mover gets to the destination +wait 1 - // sending it back - mover.NonPhysicsMoveTo( <0,0,0>, 1, 0, 0 ) +// sending it back +mover.NonPhysicsMoveTo( <0,0,0>, 1, 0, 0 ) - // then stoping the mover in 0.5 seconds - wait 0.5 - mover.NonPhysicsStop() +// then stoping the mover in 0.5 seconds +wait 0.5 +mover.NonPhysicsStop() ``` ```squirrel - // creating a elevator - // using a mover with a model - entity mover = CreateScriptMoverModel( $"models/props/turret_base/turret_base.mdl", < -40.5605, -1827.87, -223.944 >, <0,0,0>, SOLID_VPHYSICS, 1000 ) - mover.SetPusher( true ) // making it into a pusher +// creating a elevator +// using a mover with a model +entity mover = CreateScriptMoverModel( $"models/props/turret_base/turret_base.mdl", < -40.5605, -1827.87, -223.944 >, <0,0,0>, SOLID_VPHYSICS, 1000 ) +mover.SetPusher( true ) // making it into a pusher - // for loop to move the elevator up and down - for(;;) - { - mover.NonPhysicsMoveTo( < -35.4312, -1827.87, 523.046 >, 4.8, 0.1, 0.1 ) - wait 6 +// for loop to move the elevator up and down +for(;;) +{ + mover.NonPhysicsMoveTo( < -35.4312, -1827.87, 523.046 >, 4.8, 0.1, 0.1 ) + wait 6 - mover.NonPhysicsMoveTo( < -35.4312, -1827.87, -223.944 >, 4.8, 0.1, 0.1 ) - wait 6 - } + mover.NonPhysicsMoveTo( < -35.4312, -1827.87, -223.944 >, 4.8, 0.1, 0.1 ) + wait 6 +} ``` ```squirrel - // Phase shifting the player to a destination - // setting a position - vector destination = <250,1000,100> - // checking if the player is valid - if ( IsValid( player ) ) - { - // creating the mover - entity mover = CreateOwnedScriptMover( player ) - player.SetParent( mover ) // parenting the player ( so they move with the mover ) - mover.NonPhysicsMoveTo( destination, 0.5, 0, 0 ) // saying to the moveer to move - vector angles = player.GetAngles() // angles saved - PhaseShift( player, 0.1, 1 ) // phase shifitng the player - player.SetAngles( angles ) // setting the player to the original angles - } - wait 0.6 // wating so the mover moves - - if ( IsValid( player ) ) - { - player.ClearParent() // removing the player from the mover - } +// Phase shifting the player to a destination +// setting a position +vector destination = <250,1000,100> +// checking if the player is valid +if ( IsValid( player ) ) +{ + // creating the mover + entity mover = CreateOwnedScriptMover( player ) + player.SetParent( mover ) // parenting the player ( so they move with the mover ) + mover.NonPhysicsMoveTo( destination, 0.5, 0, 0 ) // saying to the moveer to move + vector angles = player.GetAngles() // angles saved + PhaseShift( player, 0.1, 1 ) // phase shifitng the player + player.SetAngles( angles ) // setting the player to the original angles +} +wait 0.6 // wating so the mover moves + +if ( IsValid( player ) ) +{ + player.ClearParent() // removing the player from the mover +} ``` diff --git a/docs/Modding/reference/respawn/native_server/damageinfo.md b/docs/Modding/reference/respawn/native_server/damageinfo.md index fdb22ce7..cc91da68 100644 --- a/docs/Modding/reference/respawn/native_server/damageinfo.md +++ b/docs/Modding/reference/respawn/native_server/damageinfo.md @@ -225,27 +225,27 @@ You can get a bitflag of all damage types used with `DamageInfo_GetDamageType`. ```squirrel - global enum damageTypes - { - gibs = (DF_GIB) - largeCaliberExp = (DF_BULLET | DF_GIB | DF_EXPLOSION) - gibBullet = (DF_BULLET | DF_GIB) - instant = (DF_INSTANT) - dissolve = (DF_DISSOLVE) - projectileImpact = (DF_GIB) - pinkMist = (DF_GIB) //If updated from DF_GIB, change the DF_GIB in Arc Cannon to match. - ragdoll = (DF_RAGDOLL) - titanStepCrush = (DF_TITAN_STEP) - arcCannon = (DF_DISSOLVE | DF_GIB | DF_ELECTRICAL ) - electric = (DF_ELECTRICAL) //Only increases Vortex Shield decay for bullet weapons atm. - explosive = (DF_RAGDOLL | DF_EXPLOSION ) - bullet = (DF_BULLET) - largeCaliber = (DF_BULLET | DF_KNOCK_BACK) - shotgun = (DF_BULLET | DF_GIB | DF_SHOTGUN ) - titanMelee = (DF_MELEE | DF_RAGDOLL) - titanBerserkerMelee = (DF_MELEE | DF_RAGDOLL) - titanEjectExplosion = (DF_GIB | DF_EXPLOSION) - dissolveForce = (DF_DISSOLVE | DF_KNOCK_BACK | DF_EXPLOSION) - rodeoBatteryRemoval = (DF_RODEO | DF_EXPLOSION | DF_STOPS_TITAN_REGEN ) - } + global enum damageTypes + { + gibs = (DF_GIB) + largeCaliberExp = (DF_BULLET | DF_GIB | DF_EXPLOSION) + gibBullet = (DF_BULLET | DF_GIB) + instant = (DF_INSTANT) + dissolve = (DF_DISSOLVE) + projectileImpact = (DF_GIB) + pinkMist = (DF_GIB) //If updated from DF_GIB, change the DF_GIB in Arc Cannon to match. + ragdoll = (DF_RAGDOLL) + titanStepCrush = (DF_TITAN_STEP) + arcCannon = (DF_DISSOLVE | DF_GIB | DF_ELECTRICAL ) + electric = (DF_ELECTRICAL) //Only increases Vortex Shield decay for bullet weapons atm. + explosive = (DF_RAGDOLL | DF_EXPLOSION ) + bullet = (DF_BULLET) + largeCaliber = (DF_BULLET | DF_KNOCK_BACK) + shotgun = (DF_BULLET | DF_GIB | DF_SHOTGUN ) + titanMelee = (DF_MELEE | DF_RAGDOLL) + titanBerserkerMelee = (DF_MELEE | DF_RAGDOLL) + titanEjectExplosion = (DF_GIB | DF_EXPLOSION) + dissolveForce = (DF_DISSOLVE | DF_KNOCK_BACK | DF_EXPLOSION) + rodeoBatteryRemoval = (DF_RODEO | DF_EXPLOSION | DF_STOPS_TITAN_REGEN ) + } ``` diff --git a/docs/Modding/reference/respawn/native_server/netvar.md b/docs/Modding/reference/respawn/native_server/netvar.md index ad6c3ca2..7aedd414 100644 --- a/docs/Modding/reference/respawn/native_server/netvar.md +++ b/docs/Modding/reference/respawn/native_server/netvar.md @@ -55,19 +55,19 @@ Remote functions allow the `SERVER` to call registered script functions on the ` To register custom remote functions you are **required** to use this callback because functions can only be registered once. ```squirrel - globalize_all_functions +globalize_all_functions - void function MyMod_Init() - { - AddCallback_OnRegisteringCustomNetworkVars( MyModRegisterRemoteFunctions ) - } +void function MyMod_Init() +{ + AddCallback_OnRegisteringCustomNetworkVars( MyModRegisterRemoteFunctions ) +} - void function MyModRegisterRemoteFunctions() - { - Remote_RegisterFunction( "ExampleRemoteFunction" ) - } +void function MyModRegisterRemoteFunctions() +{ + Remote_RegisterFunction( "ExampleRemoteFunction" ) +} - void function ExampleRemoteFunction() {} +void function ExampleRemoteFunction() {} ``` !!! cpp-function "void Remote_RegisterFunction( string name )" diff --git a/docs/Modding/reference/respawn/rui.md b/docs/Modding/reference/respawn/rui.md index fad6b716..10dd8e7e 100644 --- a/docs/Modding/reference/respawn/rui.md +++ b/docs/Modding/reference/respawn/rui.md @@ -3,88 +3,88 @@ Functions for creating a rui, and methods of the rui object ```squirrel - // To create one, do: - rui = RuiCreate( $"ui/assetname.rpak", topology, drawGroup, sortKey ) // sortkey = int to prevent z-fighting. higher -> in front - - // You can then manipulate it using the following: - RuiSetDrawGroup( rui, drawGroup ) - RuiSetString( rui, argName, value ) - RuiSetBool( rui, argName, value ) - RuiSetInt( rui, argName, value ) - RuiSetFloat( rui, argName, value ) - RuiSetFloat2( rui, argName, value ) // value is a vector; only x and y are used - RuiSetFloat3( rui, argName, value ) - RuiSetColorAlpha( rui, argName, color, alpha ) // color is a vector - - // To destroy it, just do: - RuiDestroy( rui ) +// To create one, do: +rui = RuiCreate( $"ui/assetname.rpak", topology, drawGroup, sortKey ) // sortkey = int to prevent z-fighting. higher -> in front + +// You can then manipulate it using the following: +RuiSetDrawGroup( rui, drawGroup ) +RuiSetString( rui, argName, value ) +RuiSetBool( rui, argName, value ) +RuiSetInt( rui, argName, value ) +RuiSetFloat( rui, argName, value ) +RuiSetFloat2( rui, argName, value ) // value is a vector; only x and y are used +RuiSetFloat3( rui, argName, value ) +RuiSetColorAlpha( rui, argName, color, alpha ) // color is a vector + +// To destroy it, just do: +RuiDestroy( rui ) ``` Drawgroups ``` - RUI_DRAW_WORLD - RUI_DRAW_HUD - RUI_DRAW_COCKPIT - RUI_DRAW_NONE +RUI_DRAW_WORLD +RUI_DRAW_HUD +RUI_DRAW_COCKPIT +RUI_DRAW_NONE ``` Trackers ``` - // VECTOR TYPES - RUI_TRACK_ABSORIGIN_FOLLOW // Create at absorigin, and update to follow the entity - RUI_TRACK_POINT_FOLLOW // Create on attachment point, and update to follow the entity - RUI_TRACK_OVERHEAD_FOLLOW // Create at the top of the entity's bbox - RUI_TRACK_EYEANGLES_FOLLOW - - // FLOAT TYPES - RUI_TRACK_HEALTH // Health as fraction from 0 to 1 - RUI_TRACK_FRIENDLINESS // 0 if ent is enemy, 1 if it's friendly - RUI_TRACK_PLAYER_SUIT_POWER // Player's suit power from 0 to 1 - RUI_TRACK_PLAYER_GRAPPLE_POWER // Player's grapple power from 0 to 1 - RUI_TRACK_PLAYER_SHARED_ENERGY // Players shared energy value - RUI_TRACK_WEAPON_CHARGE_FRACTION // Weapon charge as fraction from 0 to 1 - RUI_TRACK_WEAPON_SMART_AMMO_LOCK_FRACTION // Smart ammo weapon lock fraction from 0 to N - RUI_TRACK_WEAPON_READY_TO_FIRE_FRACTION // Weapon cooldown as fraction from 0 to 1 - RUI_TRACK_WEAPON_RELOAD_FRACTION // Weapon reloading as fraction from 0 to 1 - RUI_TRACK_WEAPON_DRYFIRE_FRACTION - RUI_TRACK_WEAPON_CLIP_AMMO_FRACTION // Weapon clip ammo as fraction from 0 to 1 - RUI_TRACK_WEAPON_REMAINING_AMMO_FRACTION // Weapon remaining ammo as fraction from 0 to 1 - RUI_TRACK_WEAPON_CLIP_AMMO_MAX - RUI_TRACK_WEAPON_STOCKPILE_AMMO_MAX - RUI_TRACK_WEAPON_LIFETIME_SHOTS - RUI_TRACK_WEAPON_AMMO_REGEN_RATE - RUI_TRACK_BOOST_METER_FRACTION // Player boost meter as fraction from 0 to 1 - RUI_TRACK_GLIDE_METER_FRACTION // Player glide meter as fraction from 0 to 1 - RUI_TRACK_SHIELD_FRACTION // Shield health as fraction from 0 to 1 - RUI_TRACK_STATUS_EFFECT_SEVERITY // Status effect severity as fraction from 0 to 1; attachmentIndex used as status effect index - RUI_TRACK_SCRIPT_NETWORK_VAR // Value of a script network variable (use GetNetworkedVariableIndex()) - RUI_TRACK_SCRIPT_NETWORK_VAR_GLOBAL // Value of a script network variable without an entity (use GetNetworkedVariableIndex()) - RUI_TRACK_SCRIPT_NETWORK_VAR_LOCAL_VIEW_PLAYER // Value of a script network variable on the local view player (changes automatically during kill replay) (use GetNetworkedVariableIndex()) - RUI_TRACK_FRIENDLY_TEAM_SCORE - RUI_TRACK_FRIENDLY_TEAM_ROUND_SCORE // The value of score2 for friendlies - RUI_TRACK_ENEMY_TEAM_SCORE - RUI_TRACK_ENEMY_TEAM_ROUND_SCORE // The value of score2 for enemies - RUI_TRACK_MINIMAP_SCALE - RUI_TRACK_SOUND_METER // Sound meter as fraction from 0 to 1. - - // INT TYPES - RUI_TRACK_MINIMAP_FLAGS, - RUI_TRACK_MINIMAP_CUSTOM_STATE, - RUI_TRACK_TEAM_RELATION_VIEWPLAYER, // ENEMY: -1, NEUTRAL: 0, FRIENDLY: 1 - RUI_TRACK_TEAM_RELATION_CLIENTPLAYER, // ENEMY: -1, NEUTRAL: 0, FRIENDLY: 1 - RUI_TRACK_SCRIPT_NETWORK_VAR_INT, // Value of a script network variable (use GetNetworkedVariableIndex()) - RUI_TRACK_SCRIPT_NETWORK_VAR_GLOBAL_INT, // Value of a script network variable without an entity (use GetNetworkedVariableIndex()) - RUI_TRACK_SCRIPT_NETWORK_VAR_LOCAL_VIEW_PLAYER_INT, // Value of a script network variable on the local view player (changes automatically during kill replay) (use GetNetworkedVariableIndex()) - - // GAMETIME TYPES - RUI_TRACK_LAST_FIRED_TIME, - RUI_TRACK_MINIMAP_THREAT_SECTOR, - - // IMAGE TYPES - RUI_TRACK_WEAPON_MENU_ICON, - RUI_TRACK_WEAPON_HUD_ICON +// VECTOR TYPES +RUI_TRACK_ABSORIGIN_FOLLOW // Create at absorigin, and update to follow the entity +RUI_TRACK_POINT_FOLLOW // Create on attachment point, and update to follow the entity +RUI_TRACK_OVERHEAD_FOLLOW // Create at the top of the entity's bbox +RUI_TRACK_EYEANGLES_FOLLOW + +// FLOAT TYPES +RUI_TRACK_HEALTH // Health as fraction from 0 to 1 +RUI_TRACK_FRIENDLINESS // 0 if ent is enemy, 1 if it's friendly +RUI_TRACK_PLAYER_SUIT_POWER // Player's suit power from 0 to 1 +RUI_TRACK_PLAYER_GRAPPLE_POWER // Player's grapple power from 0 to 1 +RUI_TRACK_PLAYER_SHARED_ENERGY // Players shared energy value +RUI_TRACK_WEAPON_CHARGE_FRACTION // Weapon charge as fraction from 0 to 1 +RUI_TRACK_WEAPON_SMART_AMMO_LOCK_FRACTION // Smart ammo weapon lock fraction from 0 to N +RUI_TRACK_WEAPON_READY_TO_FIRE_FRACTION // Weapon cooldown as fraction from 0 to 1 +RUI_TRACK_WEAPON_RELOAD_FRACTION // Weapon reloading as fraction from 0 to 1 +RUI_TRACK_WEAPON_DRYFIRE_FRACTION +RUI_TRACK_WEAPON_CLIP_AMMO_FRACTION // Weapon clip ammo as fraction from 0 to 1 +RUI_TRACK_WEAPON_REMAINING_AMMO_FRACTION // Weapon remaining ammo as fraction from 0 to 1 +RUI_TRACK_WEAPON_CLIP_AMMO_MAX +RUI_TRACK_WEAPON_STOCKPILE_AMMO_MAX +RUI_TRACK_WEAPON_LIFETIME_SHOTS +RUI_TRACK_WEAPON_AMMO_REGEN_RATE +RUI_TRACK_BOOST_METER_FRACTION // Player boost meter as fraction from 0 to 1 +RUI_TRACK_GLIDE_METER_FRACTION // Player glide meter as fraction from 0 to 1 +RUI_TRACK_SHIELD_FRACTION // Shield health as fraction from 0 to 1 +RUI_TRACK_STATUS_EFFECT_SEVERITY // Status effect severity as fraction from 0 to 1; attachmentIndex used as status effect index +RUI_TRACK_SCRIPT_NETWORK_VAR // Value of a script network variable (use GetNetworkedVariableIndex()) +RUI_TRACK_SCRIPT_NETWORK_VAR_GLOBAL // Value of a script network variable without an entity (use GetNetworkedVariableIndex()) +RUI_TRACK_SCRIPT_NETWORK_VAR_LOCAL_VIEW_PLAYER // Value of a script network variable on the local view player (changes automatically during kill replay) (use GetNetworkedVariableIndex()) +RUI_TRACK_FRIENDLY_TEAM_SCORE +RUI_TRACK_FRIENDLY_TEAM_ROUND_SCORE // The value of score2 for friendlies +RUI_TRACK_ENEMY_TEAM_SCORE +RUI_TRACK_ENEMY_TEAM_ROUND_SCORE // The value of score2 for enemies +RUI_TRACK_MINIMAP_SCALE +RUI_TRACK_SOUND_METER // Sound meter as fraction from 0 to 1. + +// INT TYPES +RUI_TRACK_MINIMAP_FLAGS, +RUI_TRACK_MINIMAP_CUSTOM_STATE, +RUI_TRACK_TEAM_RELATION_VIEWPLAYER, // ENEMY: -1, NEUTRAL: 0, FRIENDLY: 1 +RUI_TRACK_TEAM_RELATION_CLIENTPLAYER, // ENEMY: -1, NEUTRAL: 0, FRIENDLY: 1 +RUI_TRACK_SCRIPT_NETWORK_VAR_INT, // Value of a script network variable (use GetNetworkedVariableIndex()) +RUI_TRACK_SCRIPT_NETWORK_VAR_GLOBAL_INT, // Value of a script network variable without an entity (use GetNetworkedVariableIndex()) +RUI_TRACK_SCRIPT_NETWORK_VAR_LOCAL_VIEW_PLAYER_INT, // Value of a script network variable on the local view player (changes automatically during kill replay) (use GetNetworkedVariableIndex()) + +// GAMETIME TYPES +RUI_TRACK_LAST_FIRED_TIME, +RUI_TRACK_MINIMAP_THREAT_SECTOR, + +// IMAGE TYPES +RUI_TRACK_WEAPON_MENU_ICON, +RUI_TRACK_WEAPON_HUD_ICON ``` !!! cpp-class "rui : public var" @@ -92,8 +92,8 @@ Trackers !!! cpp-function "void RuiSetResolution(rui, screenSizeX, screenSizey)" ```squirrel - screenSizeX = GetScreenSize()[0] - screenSizeY = GetScreenSize()[1] + screenSizeX = GetScreenSize()[0] + screenSizeY = GetScreenSize()[1] ``` !!! cpp-function "void RuiSetDrawGroup( rui, drawGroup )" diff --git a/docs/Modding/reference/respawn/titan.md b/docs/Modding/reference/respawn/titan.md index 65c05cf4..ec9153b3 100644 --- a/docs/Modding/reference/respawn/titan.md +++ b/docs/Modding/reference/respawn/titan.md @@ -3,8 +3,8 @@ Functions for getting titan, and methods of the titan object ```squirrel - entity soul = player.IsTitan() ? player.GetTitanSoul() : player.GetPetTitan().GetTitanSoul() - // getting the titan depends on wether the player is in the titan or not +entity soul = player.IsTitan() ? player.GetTitanSoul() : player.GetPetTitan().GetTitanSoul() +// getting the titan depends on wether the player is in the titan or not ``` diff --git a/docs/Modding/reference/respawn/topology.md b/docs/Modding/reference/respawn/topology.md index 5939050c..f745449d 100644 --- a/docs/Modding/reference/respawn/topology.md +++ b/docs/Modding/reference/respawn/topology.md @@ -7,12 +7,12 @@ The position of topologies are relative to the position of their parent. Since the number of topologies that can be created is very limited and Vanilla uses most of the slots already, try to minimize your topology uses. Instead of creating new ones, check if you can use one that already exists: ```squirrel - clGlobal.topoFullScreen - clGlobal.topoCockpitHudPermanent - clGlobal.topoTitanCockpitLowerHud - clGlobal.topoTitanCockpitInstrument1 // yes, with a 1 - clGlobal.topoTitanCockpitHud - clGlobal.topoCockpitHud +clGlobal.topoFullScreen +clGlobal.topoCockpitHudPermanent +clGlobal.topoTitanCockpitLowerHud +clGlobal.topoTitanCockpitInstrument1 // yes, with a 1 +clGlobal.topoTitanCockpitHud +clGlobal.topoCockpitHud ``` ## Creating Topologies @@ -58,50 +58,50 @@ Drawcalls determine how and where RUIs on a topology are being rendered. ## HUD Topology example ```squirrel - // Cover the top left quadrant of the screen with a basic image - float[2] s = GetScreenSize() - var topo = RuiTopology_CreatePlane( <0,0,0>, , <0,s[1] / 2,0>, true ) // RUIs scale with the topology they are being drawn on so make sure to use the correct dimensions - RuiCreate( $"ui/basic_image.rpak", topo, RUI_DRAW_HUD, 0 ) +// Cover the top left quadrant of the screen with a basic image +float[2] s = GetScreenSize() +var topo = RuiTopology_CreatePlane( <0,0,0>, , <0,s[1] / 2,0>, true ) // RUIs scale with the topology they are being drawn on so make sure to use the correct dimensions +RuiCreate( $"ui/basic_image.rpak", topo, RUI_DRAW_HUD, 0 ) ``` ## Worldspace Topology example ```squirrel - // REMEMBER TO DESTROY ALL TOPOS, RUIS AND PROPS YOU CREATE WHEN YOU NO LONGER NEED THEM - // ripped from respawn - var function Worldspace_CreateRUITopology( vector org, vector ang, float width, float height ) - { - // adjust so the RUI is drawn with the org as its center point - org += ( (AnglesToRight( ang )*-1) * (width*0.5) ) - org += ( AnglesToUp( ang ) * (height*0.5) ) - - // right and down vectors that get added to base org to create the display size - vector right = ( AnglesToRight( ang ) * width ) - vector down = ( (AnglesToUp( ang )*-1) * height ) - - return RuiTopology_CreatePlane( org, right, down, true ) - } - - void function WorldSpaceTopoTest() - { - // To rotate a topology without manually calculating and updating position and dimensions you can parent the topology to a client side prop - entity player = GetLocalClientPlayer() - entity weapon = player.GetActiveWeapon() - - vector fwd = AnglesToForward( weapon.GetAngles() ) - vector right = AnglesToRight( weapon.GetAngles() ) - vector up = AnglesToUp( weapon.GetAngles() ) - vector conf = < 20, -40, 30 > // float next to the player's weapon - - int attachIndex = weapon.LookupAttachment( "muzzle_flash" ) - entity anchor = CreateClientSidePropDynamic( weapon.GetAttachmentOrigin( attachIndex ) + fwd * conf.x + right * conf.y + up * conf.z, <0,0,0>, $"models/dev/empty_model.mdl") // props need a model but this one is invisible so we don't need to set visibility manually - var topo = Worldspace_CreateRUITopology( <0,0,0>, <0,90,0>, 128, 64 ) // origin <0,0,0> so the topo sits at the origin of the prop - - var tm_box = RuiCreate( $"ui/helmet_scanning_percentbar.rpak", topo, RUI_DRAW_WORLD, 0 ) - RuiSetString( tm_box, "stage3TextTop", "Top" ) - RuiSetString( tm_box, "stage3TextBottom", "Bottom" ) - - anchor.SetParent( weapon ) - RuiTopology_SetParent( topo, anchor ) - } +// REMEMBER TO DESTROY ALL TOPOS, RUIS AND PROPS YOU CREATE WHEN YOU NO LONGER NEED THEM +// ripped from respawn +var function Worldspace_CreateRUITopology( vector org, vector ang, float width, float height ) +{ + // adjust so the RUI is drawn with the org as its center point + org += ( (AnglesToRight( ang )*-1) * (width*0.5) ) + org += ( AnglesToUp( ang ) * (height*0.5) ) + + // right and down vectors that get added to base org to create the display size + vector right = ( AnglesToRight( ang ) * width ) + vector down = ( (AnglesToUp( ang )*-1) * height ) + + return RuiTopology_CreatePlane( org, right, down, true ) +} + +void function WorldSpaceTopoTest() +{ + // To rotate a topology without manually calculating and updating position and dimensions you can parent the topology to a client side prop + entity player = GetLocalClientPlayer() + entity weapon = player.GetActiveWeapon() + + vector fwd = AnglesToForward( weapon.GetAngles() ) + vector right = AnglesToRight( weapon.GetAngles() ) + vector up = AnglesToUp( weapon.GetAngles() ) + vector conf = < 20, -40, 30 > // float next to the player's weapon + + int attachIndex = weapon.LookupAttachment( "muzzle_flash" ) + entity anchor = CreateClientSidePropDynamic( weapon.GetAttachmentOrigin( attachIndex ) + fwd * conf.x + right * conf.y + up * conf.z, <0,0,0>, $"models/dev/empty_model.mdl") // props need a model but this one is invisible so we don't need to set visibility manually + var topo = Worldspace_CreateRUITopology( <0,0,0>, <0,90,0>, 128, 64 ) // origin <0,0,0> so the topo sits at the origin of the prop + + var tm_box = RuiCreate( $"ui/helmet_scanning_percentbar.rpak", topo, RUI_DRAW_WORLD, 0 ) + RuiSetString( tm_box, "stage3TextTop", "Top" ) + RuiSetString( tm_box, "stage3TextBottom", "Bottom" ) + + anchor.SetParent( weapon ) + RuiTopology_SetParent( topo, anchor ) +} ``` diff --git a/docs/Modding/repak/assets/datatable.md b/docs/Modding/repak/assets/datatable.md index 422227ca..828b60df 100644 --- a/docs/Modding/repak/assets/datatable.md +++ b/docs/Modding/repak/assets/datatable.md @@ -5,10 +5,10 @@ ### 1. Example Datatable Asset ```json - { - "$type": "dtbl", - "path": "datatable/custom_datatable", - } +{ + "$type": "dtbl", + "path": "datatable/custom_datatable", +} ``` ### 2. Example Datatable `.csv` File diff --git a/docs/Modding/repak/assets/texture.md b/docs/Modding/repak/assets/texture.md index 79f4615d..184f58a7 100644 --- a/docs/Modding/repak/assets/texture.md +++ b/docs/Modding/repak/assets/texture.md @@ -28,11 +28,11 @@ following compression types: ### 1. Basic Texture Asset - No streaming ```json - { - "$type": "txtr", - "path": "textures/models/humans/test_texture", - "disableStreaming": true - } +{ + "$type": "txtr", + "path": "textures/models/humans/test_texture", + "disableStreaming": true +} ``` !!! note @@ -48,11 +48,11 @@ following compression types: ### 2. Streamed Texture Asset ```json - { - "$type": "txtr", - "path": "textures/models/humans/test_texture_2", - "starpakPath": "test_texture_2.starpak" - } +{ + "$type": "txtr", + "path": "textures/models/humans/test_texture_2", + "starpakPath": "test_texture_2.starpak" +} ``` !!! note diff --git a/docs/Modding/repak/assets/uiatlas.md b/docs/Modding/repak/assets/uiatlas.md index 3132fd9e..41aa2413 100644 --- a/docs/Modding/repak/assets/uiatlas.md +++ b/docs/Modding/repak/assets/uiatlas.md @@ -9,28 +9,28 @@ reference a single texture asset, known as the `atlas` and have an array of ### 1. Basic UI Image Atlas with 2 Textures ```json - { - "$type":"uimg", - "path":"rui/atlas/example1", - "atlas":"rui/example1", - "textures": - [ - { - "path":"rui/example1/texture1", - "width":128, - "height":128, - "posX":0, - "posY":0 - }, - { - "path":"rui/example1/texture2", - "width":128, - "height":128, - "posX":128, - "posY":0 - } - ] - } +{ + "$type":"uimg", + "path":"rui/atlas/example1", + "atlas":"rui/example1", + "textures": + [ + { + "path":"rui/example1/texture1", + "width":128, + "height":128, + "posX":0, + "posY":0 + }, + { + "path":"rui/example1/texture2", + "width":128, + "height":128, + "posX":128, + "posY":0 + } + ] +} ``` !!! note @@ -41,53 +41,53 @@ reference a single texture asset, known as the `atlas` and have an array of ### 2. Full Map File With a UI Image Atlas ```json - { - "name":"blue_fire", - "assetsDir":"../depot", - "outputDir":"../rpaks", - "version": 7, - "files":[ - { - "$type":"txtr", - "path":"rui/blue_fire" - }, - { - "$type":"uimg", - "path":"rui/atlas/blue_fire", - "atlas":"rui/blue_fire", - "textures":[ - { - "path":"blue_fire/hud/flame_wall", - "width":128, - "height":128, - "posX":0, - "posY":0 - }, - { - "path":"blue_fire/menu/flame_wall", - "width":128, - "height":128, - "posX":128, - "posY":0 - }, - { - "path":"blue_fire/hud/flame_shield", - "width":128, - "height":128, - "posX":0, - "posY":128 - }, - { - "path":"blue_fire/menu/flame_shield", - "width":128, - "height":128, - "posX":128, - "posY":128 - } - ] - } - ] - } +{ + "name":"blue_fire", + "assetsDir":"../depot", + "outputDir":"../rpaks", + "version": 7, + "files":[ + { + "$type":"txtr", + "path":"rui/blue_fire" + }, + { + "$type":"uimg", + "path":"rui/atlas/blue_fire", + "atlas":"rui/blue_fire", + "textures":[ + { + "path":"blue_fire/hud/flame_wall", + "width":128, + "height":128, + "posX":0, + "posY":0 + }, + { + "path":"blue_fire/menu/flame_wall", + "width":128, + "height":128, + "posX":128, + "posY":0 + }, + { + "path":"blue_fire/hud/flame_shield", + "width":128, + "height":128, + "posX":0, + "posY":128 + }, + { + "path":"blue_fire/menu/flame_shield", + "width":128, + "height":128, + "posX":128, + "posY":128 + } + ] + } + ] +} ``` !!! note diff --git a/docs/Modding/repak/map.md b/docs/Modding/repak/map.md index ac783d3e..7cb56f2d 100644 --- a/docs/Modding/repak/map.md +++ b/docs/Modding/repak/map.md @@ -7,17 +7,17 @@ `example1.json` ```json - { - "version": 7 - } +{ + "version": 7 +} ``` ```text - root - ├── RePak.exe - ├── example1.json - └── build - └─ example1.rpak +root +├── RePak.exe +├── example1.json +└── build + └─ example1.rpak ``` !!! note @@ -33,34 +33,34 @@ `example2.json` ```json - { - "name": "example2", - "assetsDir": "../depot", - "outputDir": "../output", - "version": 7, - "starpakPath": "example2.starpak", - "files": - [ - { - "$type": "txtr", - "path": "textures/models/my_texture" - } - ] - } +{ + "name": "example2", + "assetsDir": "../depot", + "outputDir": "../output", + "version": 7, + "starpakPath": "example2.starpak", + "files": + [ + { + "$type": "txtr", + "path": "textures/models/my_texture" + } + ] +} ``` ```text - root - ├── RePak.exe - ├── maps - | └─ example2.json - ├── depot - | └─ textures - | └─ models - | └─ my_texture.dds - └── output - ├─ example2.starpak - └─ example2.rpak +root +├── RePak.exe +├── maps +| └─ example2.json +├── depot +| └─ textures +| └─ models +| └─ my_texture.dds +└── output + ├─ example2.starpak + └─ example2.rpak ``` !!! note @@ -80,46 +80,46 @@ `example3.json` ```json - { - "name": "example3", - "assetsDir": "../depot", - "outputDir": "../output", - "version": 7, - "starpakPath": "example3.starpak", - "files": - [ - { - "$type": "txtr", - "path": "textures/models/my_texture_col" - }, - { - "$type": "txtr", - "path": "textures/models/my_texture_nml" - }, - { - "$type": "txtr", - "starpakPath": "example3-spc.starpak", - "path": "textures/models/my_texture_spc" - } - ] - } +{ + "name": "example3", + "assetsDir": "../depot", + "outputDir": "../output", + "version": 7, + "starpakPath": "example3.starpak", + "files": + [ + { + "$type": "txtr", + "path": "textures/models/my_texture_col" + }, + { + "$type": "txtr", + "path": "textures/models/my_texture_nml" + }, + { + "$type": "txtr", + "starpakPath": "example3-spc.starpak", + "path": "textures/models/my_texture_spc" + } + ] +} ``` ```text - root - ├── RePak.exe - ├── maps - | └─ example3.json - ├── depot - | └─ textures - | └─ models - | ├─ my_texture_col.dds - | ├─ my_texture_nml.dds - | └─ my_texture_spc.dds - └── output - ├─ example3.starpak - ├─ example3-spc.starpak - └─ example3.rpak +root +├── RePak.exe +├── maps +| └─ example3.json +├── depot +| └─ textures +| └─ models +| ├─ my_texture_col.dds +| ├─ my_texture_nml.dds +| └─ my_texture_spc.dds +└── output + ├─ example3.starpak + ├─ example3-spc.starpak + └─ example3.rpak ``` !!! note diff --git a/docs/Modding/squirrel/async.md b/docs/Modding/squirrel/async.md index f9f4ccf1..5841fec1 100644 --- a/docs/Modding/squirrel/async.md +++ b/docs/Modding/squirrel/async.md @@ -17,22 +17,22 @@ A thread is considered finished, after the threaded function returned a value. T To create a new coroutine, call a function with the `thread` keyword before. ```squirrel - thread void function(){}() - thread MyFunction() +thread void function(){}() +thread MyFunction() ``` To get a thread object, use the `newthread` function. ```squirrel - void function CoroutineExample() - { - suspend( "passback" ) // passback is optional - print( "threaded statement" ) - } - - var co = newthread( CoroutineExample ) - var suspendedReturn = co.call() // you NEED to use .call, invoking the function with () won't work - co.wakeup() // continue thread +void function CoroutineExample() +{ + suspend( "passback" ) // passback is optional + print( "threaded statement" ) +} + +var co = newthread( CoroutineExample ) +var suspendedReturn = co.call() // you NEED to use .call, invoking the function with () won't work +co.wakeup() // continue thread ``` ### wait @@ -40,13 +40,13 @@ To get a thread object, use the `newthread` function. The `wait` statement halts threads for a set amount of time specified after the `wait` keyword. Integers and floats are accepted as times in seconds. ```squirrel - void function WaitExample( float n ) - { - wait 1 // wait 1 second - wait n // wait n seconds - } +void function WaitExample( float n ) +{ + wait 1 // wait 1 second + wait n // wait n seconds +} - thread WaitExample( 0.5 ) // thread will halt for a total 1.5 seconds +thread WaitExample( 0.5 ) // thread will halt for a total 1.5 seconds ``` To wait a single frame, don't use `wait 0` since it doesn't actually wait a game frame. For example, if you have a client loop that does wait 0 even if the game is paused the loop will still run. Use `WaitFrame()` instead. @@ -56,16 +56,16 @@ When using infinite loops it's important to work with `wait` statements to avoid If you want to wait until a thread is finished, you can spin off the thread that you wait for with the `waitthread` keyword. ```squirrel - void function ParentThread() +void function ParentThread() +{ + printt( "pre spinoff " + string( Time() ) ) + waitthread void function() { - printt( "pre spinoff " + string( Time() ) ) - waitthread void function() - { - printt( "mid spinoff " + string( Time() ) ) - wait 1 - } - printt( "post spinoff" + string( Time() ) ) + printt( "mid spinoff " + string( Time() ) ) + wait 1 } + printt( "post spinoff" + string( Time() ) ) +} ``` ### OnThreadEnd @@ -73,43 +73,43 @@ If you want to wait until a thread is finished, you can spin off the thread that Use the `OnThreadEnd` function to execute a callback after a thread has ended. This is useful for cleanup functions that remove entities after they're used or similar. ```squirrel - void function PlayIncomingFX( vector origin, int teamNum ) - { - wait 1.50 - EmitSoundAtPosition( teamNum, origin, "Titan_1P_Warpfall_Start" ) - - local colorVec = Vector( 0, 255, 0 ) - entity cpoint = CreateEntity( "info_placement_helper" ) - SetTargetName( cpoint, UniqueString( "pickup_controlpoint" ) ) - DispatchSpawn( cpoint ) - cpoint.SetOrigin( colorVec ) - entity glowFX = PlayFXWithControlPoint( INCOMING_SPAWN_FX, origin, cpoint, -1, null, null, C_PLAYFX_LOOP ) - - OnThreadEnd( - function() : ( glowFX, cpoint ) - { - if ( IsValid( glowFX ) ) - glowFX.Destroy() - if ( IsValid( cpoint ) ) - cpoint.Destroy() - } - ) +void function PlayIncomingFX( vector origin, int teamNum ) +{ + wait 1.50 + EmitSoundAtPosition( teamNum, origin, "Titan_1P_Warpfall_Start" ) + + local colorVec = Vector( 0, 255, 0 ) + entity cpoint = CreateEntity( "info_placement_helper" ) + SetTargetName( cpoint, UniqueString( "pickup_controlpoint" ) ) + DispatchSpawn( cpoint ) + cpoint.SetOrigin( colorVec ) + entity glowFX = PlayFXWithControlPoint( INCOMING_SPAWN_FX, origin, cpoint, -1, null, null, C_PLAYFX_LOOP ) + + OnThreadEnd( + function() : ( glowFX, cpoint ) + { + if ( IsValid( glowFX ) ) + glowFX.Destroy() + if ( IsValid( cpoint ) ) + cpoint.Destroy() + } + ) - wait 1.25 - } + wait 1.25 +} ``` ### Example Script ```squirrel - void function SetPositionDelayed( entity ent, vector pos, float delay ) - { - wait delay - ent.SetOrigin( pos ) - } - - SetPositionDelayed( player, <0, 0, 100>, 5.0 ) - SetPositionDelayed( player, <0, 0, 50>, 2.5 ) // this will finish sooner. +void function SetPositionDelayed( entity ent, vector pos, float delay ) +{ + wait delay + ent.SetOrigin( pos ) +} + +SetPositionDelayed( player, <0, 0, 100>, 5.0 ) +SetPositionDelayed( player, <0, 0, 50>, 2.5 ) // this will finish sooner. ``` @@ -170,8 +170,8 @@ It's also possible to trigger and catch signals with methods that aren't propert Wait for any of the passed signals to be triggered. ```squirrel - // Wait for the NPC to die, delete, or get leeched, then remove the npc from the array - WaitSignal( ent, "OnDeath", "OnDestroy", "OnLeeched" ) + // Wait for the NPC to die, delete, or get leeched, then remove the npc from the array + WaitSignal( ent, "OnDeath", "OnDestroy", "OnLeeched" ) ``` !!! cpp-function "void EndSignal( var obj, string signal )" @@ -183,43 +183,43 @@ It's also possible to trigger and catch signals with methods that aren't propert For example, if we want to tell a player not to give up after being killed several times, we can write it this way: ```squirrel - // First, we register signal we want to use - RegisterSignal("OnMultipleDeaths") +// First, we register signal we want to use +RegisterSignal("OnMultipleDeaths") - void function WatchForDeaths (entity player) - { - int deathsCount = 0 +void function WatchForDeaths (entity player) +{ + int deathsCount = 0 - while( GamePlayingOrSuddenDeath() ) + while( GamePlayingOrSuddenDeath() ) + { + if ( player.isDead() ) // This doesn't exist, don't try this at home { - if ( player.isDead() ) // This doesn't exist, don't try this at home - { - deathsCount += 1 + deathsCount += 1 - if (deathsCount >= 42) - { - // This sends "OnMultipleDeaths" signal on player entity - player.Signal( "OnMultipleDeaths" ) - } + if (deathsCount >= 42) + { + // This sends "OnMultipleDeaths" signal on player entity + player.Signal( "OnMultipleDeaths" ) } } } +} - void function DontGiveUp (entity player) - { - // This is a blocking call - player.WaitSignal("OnMultipleDeaths"); +void function DontGiveUp (entity player) +{ + // This is a blocking call + player.WaitSignal("OnMultipleDeaths"); - // This will not run until entity received "OnMultipleDeaths" signal - SendHudMessage( player, "Don't give up!", -1, 0.4, 255, 0, 0, 0, 0, 3, 0.15 ) - } + // This will not run until entity received "OnMultipleDeaths" signal + SendHudMessage( player, "Don't give up!", -1, 0.4, 255, 0, 0, 0, 0, 3, 0.15 ) +} - // Launch our methods in dedicated threads - entity player = GetPlayerArray()[0] - thread WatchForDeaths( player ) - thread DontGiveUp( player ) +// Launch our methods in dedicated threads +entity player = GetPlayerArray()[0] +thread WatchForDeaths( player ) +thread DontGiveUp( player ) ``` In this example, the `DontGiveUp` method is launched at the same time as `WatchForDeaths`; but it will not @@ -305,20 +305,20 @@ is set, thread will end (after calling any `OnThreadEnd` methods). #### Example ```squirrel - void function FlagExample() - { - FlagInit( "BombHasExploded" ) - - thread BombTicker() - - FlagWait( "BombHasExploded" ) - print( "bomb just exploded" ) - } - - void function BombTicker() - { - Assert( IsNewThread(), "BombTicker must be threaded off" ) - wait RandomFloatRange( 3, 9 ) - FlagSet( "BombHasExploded" ) - } +void function FlagExample() +{ + FlagInit( "BombHasExploded" ) + + thread BombTicker() + + FlagWait( "BombHasExploded" ) + print( "bomb just exploded" ) +} + +void function BombTicker() +{ + Assert( IsNewThread(), "BombTicker must be threaded off" ) + wait RandomFloatRange( 3, 9 ) + FlagSet( "BombHasExploded" ) +} ``` diff --git a/docs/Modding/squirrel/class.md b/docs/Modding/squirrel/class.md index acd54ae7..e7170f86 100644 --- a/docs/Modding/squirrel/class.md +++ b/docs/Modding/squirrel/class.md @@ -13,8 +13,8 @@ To declare a class, first add the `untyped` keyword and the class as a variable file level. ```squirrel - untyped - var ExampleClass +untyped +var ExampleClass ``` The `untyped` declaration is required because instances have an unknown type and it's @@ -34,11 +34,11 @@ Most classes use a constructor. A constructor is a function of the instance that executed on object creation. ```squirrel - void function initClient() { - class ExampleClass { - constructor(){print("Instance of ExampleClass created");} - } +void function initClient() { + class ExampleClass { + constructor(){print("Instance of ExampleClass created");} } +} ``` You can require parameters in the constructor. Keep in mind that you have to pass those @@ -49,19 +49,19 @@ Function parameters are passed as type `var`, but the type keyword is not requir ){}; func( var parameter ){};` are both correct. ```squirrel - class ExampleClass { - propertyString = null // Actual type is var - propertyInt = null // Actual type is var - constructor( var pString, var pInt ) { - this.propertyString = expect string(pString); - this.propertyInt = expect int(pInt); - } - } +class ExampleClass { + propertyString = null // Actual type is var + propertyInt = null // Actual type is var + constructor( var pString, var pInt ) { + this.propertyString = expect string(pString); + this.propertyInt = expect int(pInt); + } +} - // See section "Declaring Objects" for more information on object creation - var obj = ExampleClass( "foo", 1 ); - printt(obj.propertyString, obj.propertyString ) // foo, 1 - var lObj = ExampleClass(); tObj = ExampleClass( "" , 0 , 0); // Both throw an error compile time because parameters don't match with the constructor +// See section "Declaring Objects" for more information on object creation +var obj = ExampleClass( "foo", 1 ); +printt(obj.propertyString, obj.propertyString ) // foo, 1 +var lObj = ExampleClass(); tObj = ExampleClass( "" , 0 , 0); // Both throw an error compile time because parameters don't match with the constructor ``` Usually objects have properties. To define them, just add their identifier into the @@ -72,14 +72,14 @@ Every object has a reference to itself called `this`. You can change parameters object by reference. ```squirrel - void function initClient() { - class ExampleClass { - property = null - constructor( var parameter ) { - this.property = expect int(parameter); - } +void function initClient() { + class ExampleClass { + property = null + constructor( var parameter ) { + this.property = expect int(parameter); } } +} ``` You can't use the class name as a type. Use `var` instead. You can't `expect` them @@ -91,26 +91,26 @@ Functions of a class have to return a value of type `var`. This may be `null`. Define functions like this: ```squirrel - global var ExampleClass; - void function initClassF(){ - class ExampleClass { - variable = "default value" - - // Set field 'variable' of this instance to passed parameter - function setV( pV ){ - this.variable = pV - } - - // Return field 'variable' of this instance - function getV(){ - return this.variable; // return value can be of any type - } +global var ExampleClass; +void function initClassF(){ + class ExampleClass { + variable = "default value" + + // Set field 'variable' of this instance to passed parameter + function setV( pV ){ + this.variable = pV + } + + // Return field 'variable' of this instance + function getV(){ + return this.variable; // return value can be of any type } - var inst = ExampleClass(); - print(inst.getV()); // -> default value - inst.setV("new value"); - print(inst.getV()); // -> new value } + var inst = ExampleClass(); + print(inst.getV()); // -> default value + inst.setV("new value"); + print(inst.getV()); // -> new value +} ``` ## Inserting Properties Into Classes @@ -119,10 +119,10 @@ It's possible to insert more properties into a class at runtime. To achieve this the `<-` operator. ```squirrel - // Using `ExampleClass` and `exampleObject` from example above - ExampleClass.newProperty <- "New property in class" - // The value of the new index may be of any type. - ExampleClass.newFunc <- function(){return "Function return value";} +// Using `ExampleClass` and `exampleObject` from example above +ExampleClass.newProperty <- "New property in class" +// The value of the new index may be of any type. +ExampleClass.newFunc <- function(){return "Function return value";} ``` !!! note @@ -131,22 +131,22 @@ the `<-` operator. instantiation* ```squirrel - var ExampleErrorClass; + var ExampleErrorClass; - func(){ - class ExampleErrorClass {}; - var eInst = ExampleErrorClass() - eInst.e <- "Instance error value"; // Asserts error: class instances do not support the new slot operator - ExampleErrorClass.e <- "Class error value"; // Fails because an instance of class ExampleErrorClass has already been created. Asserts error: trying to modify a class that has already been instantiated - } + func(){ + class ExampleErrorClass {}; + var eInst = ExampleErrorClass() + eInst.e <- "Instance error value"; // Asserts error: class instances do not support the new slot operator + ExampleErrorClass.e <- "Class error value"; // Fails because an instance of class ExampleErrorClass has already been created. Asserts error: trying to modify a class that has already been instantiated + } ``` Inserting functions is also possible using the `::` operator ```squirrel - function ExampleClass::AddOne( var param /* parameters have to be var */ ){ return expect int( param ) + 1 } - var e = ExampleClass() - print( expect int( e.AddOne( 1 ) ) ) // prints 2 +function ExampleClass::AddOne( var param /* parameters have to be var */ ){ return expect int( param ) + 1 } +var e = ExampleClass() +print( expect int( e.AddOne( 1 ) ) ) // prints 2 ``` This allows mods to extend functionality of classes declared in the base game and other @@ -155,24 +155,24 @@ mods that have already been loaded. For example, extending functionality of the CPlayer class might look like this: ```squirrel - global function InitCPlayerInsert - - void function InitCPlayerInsert() - { - CPlayer.afkCount <- 0 // Insert new property into the CPlayer class - CPlayer.maxAFKCount <- 3 - function CPlayer::AFK(){ // Kick a player when they are afk multiple times in a match - if ( this.afkCount >= this.maxAFKCount ) - ClientCommand( this, "disconnect You have been AFK too often in a match") - else - { - this.afkCount++ - SendHudMessage( this, format( "You are AFK!\nYou will get kicked after %i more violations", this.maxAFKCount - this.afkCount ), -1, 0.4, 255, 255, 255, 0, 0.5, 5, 0.9 ) - } - } - - // To trigger the method, do GetPlayerArray()[0].AFK() +global function InitCPlayerInsert + +void function InitCPlayerInsert() +{ + CPlayer.afkCount <- 0 // Insert new property into the CPlayer class + CPlayer.maxAFKCount <- 3 + function CPlayer::AFK(){ // Kick a player when they are afk multiple times in a match + if ( this.afkCount >= this.maxAFKCount ) + ClientCommand( this, "disconnect You have been AFK too often in a match") + else + { + this.afkCount++ + SendHudMessage( this, format( "You are AFK!\nYou will get kicked after %i more violations", this.maxAFKCount - this.afkCount ), -1, 0.4, 255, 255, 255, 0, 0.5, 5, 0.9 ) + } } + + // To trigger the method, do GetPlayerArray()[0].AFK() +} ``` This will allow scripts to run the `AFK` method on CPlayer entities, which will kick a @@ -189,25 +189,25 @@ inherited from a modified class. To create an instance, do: ```squirrel - class ExampleClass { - property = null - constructor( var parameter ) { - this.property = expect int(parameter); - } +class ExampleClass { + property = null + constructor( var parameter ) { + this.property = expect int(parameter); } +} - var exampleObject = ExampleClass(1); - int n = exampleObject.property // n = 1 - exampleObject.property++; - n = exampleObject.property // n = 2 +var exampleObject = ExampleClass(1); +int n = exampleObject.property // n = 1 +exampleObject.property++; +n = exampleObject.property // n = 2 ``` It's also possible to create an instance without calling the constructor. ```squirrel - // Using 'ExampleClass' from previous examples - var e = ExampleClass.instance() - e.constructor(1) // Constructor is a normal function so you can call it manually. +// Using 'ExampleClass' from previous examples +var e = ExampleClass.instance() +e.constructor(1) // Constructor is a normal function so you can call it manually. ``` Like the example above shows you can manipulate properties of a class directly. There is @@ -218,8 +218,8 @@ doesn't have a reference to itself, meaning that the `this` keyword refers to th table. ```squirrel - var class = ExampleClass - var instance = class.constructor() +var class = ExampleClass +var instance = class.constructor() ``` ## Cloning Instances @@ -229,38 +229,38 @@ reference to itself. This means that any modifications inside of a function are to the original object. ```squirrel - void function initClass(){ - class Container { - content = null - constructor ( var pString ) { - this.content = expect string(pString); - } +void function initClass(){ + class Container { + content = null + constructor ( var pString ) { + this.content = expect string(pString); } - var con = Container("original string") - manipulateContainer( con ) - print(con.content) // -> manipulated string - } - - void function manipulateContainer( var con ){ - con.content = "manipulated string"; } + var con = Container("original string") + manipulateContainer( con ) + print(con.content) // -> manipulated string +} + +void function manipulateContainer( var con ){ + con.content = "manipulated string"; +} ``` You can avoid this by using cloned objects. Use the `clone` keyword to create a copy of an object. ```squirrel - // Assumes the 'Container' class from the previous example has already been declared - void function initClass(){ - var originalObj = Container("original string") - var clonedObj = clone originalObj - manipulateContainer( clonedObj ) - printt(orignalObj.content, clonedObj.content) // -> original string, manipulated string - } - - void function manipulateContainer( var con ){ - con.content = "manipulated string"; - } +// Assumes the 'Container' class from the previous example has already been declared +void function initClass(){ + var originalObj = Container("original string") + var clonedObj = clone originalObj + manipulateContainer( clonedObj ) + printt(orignalObj.content, clonedObj.content) // -> original string, manipulated string +} + +void function manipulateContainer( var con ){ + con.content = "manipulated string"; +} ``` @@ -271,10 +271,10 @@ hold multiple class objects that emulate the behaviour of namespaces to a certai extend. ```squirrel - global table fakeNamespace = { - class1 = null, - class2 = null - } +global table fakeNamespace = { + class1 = null, + class2 = null +} ``` This allows you to group classes together in a single global variable. @@ -282,41 +282,41 @@ This allows you to group classes together in a single global variable. You can use the classes inside of the table like this: ```squirrel - // Create a class object in field - class fakeNamespace.class1 { constructor(){ print("constructing instance of class1") } } - class fakeNamespace.class2 { constructor(){ print("constructing instance of class2") } } +// Create a class object in field +class fakeNamespace.class1 { constructor(){ print("constructing instance of class1") } } +class fakeNamespace.class2 { constructor(){ print("constructing instance of class2") } } - // Access class object in field - var c1 = fakeNamespace.class1() - var c2 = fakeNamespace.class2() +// Access class object in field +var c1 = fakeNamespace.class1() +var c2 = fakeNamespace.class2() - // Insert functions into class object in field - fakeNamespace.class1.testfunc <- var function(){ print( "inserted function in class1" ) } +// Insert functions into class object in field +fakeNamespace.class1.testfunc <- var function(){ print( "inserted function in class1" ) } ``` You can also declare classes in an array: ```squirrel - array classes // This has to be at file level +array classes // This has to be at file level - // This has to be inside of a function: - classes.append( class { constructor(){ print( "inline constructor" ) } ) - var instance = classes[0]() +// This has to be inside of a function: +classes.append( class { constructor(){ print( "inline constructor" ) } ) +var instance = classes[0]() ``` And in a similar fashion in structs: ```squirrel - struct { - var class1 = null - var class2 = null - } classes // This has to be at file level - - // This has to be inside of a function: - classes.class1 = class { constructor(){ print( "inline constructor" ) } ) - classes.class2 = class { constructor(){ print( "inline constructor" ) } ) - var c1 = classes.class1() - var c2 = classes.class2() +struct { + var class1 = null + var class2 = null +} classes // This has to be at file level + +// This has to be inside of a function: +classes.class1 = class { constructor(){ print( "inline constructor" ) } ) +classes.class2 = class { constructor(){ print( "inline constructor" ) } ) +var c1 = classes.class1() +var c2 = classes.class2() ``` !!! warning @@ -325,7 +325,7 @@ And in a similar fashion in structs: won't compile. ```squirrel - class Child extends Parent{} + class Child extends Parent{} ``` Make sure you check out the squirrel documentation on diff --git a/docs/Modding/squirrel/cpp_api/objecthandling.md b/docs/Modding/squirrel/cpp_api/objecthandling.md index cdcf2288..f24e9186 100644 --- a/docs/Modding/squirrel/cpp_api/objecthandling.md +++ b/docs/Modding/squirrel/cpp_api/objecthandling.md @@ -152,13 +152,13 @@ Used to add global constants for scripts. ```cpp - getConstants(sqvm); + getConstants(sqvm); - pushstring(sqvm, "MY_CONSTANT"); - pushstring(sqvm, "MY_VALUE"); - newslot(sqvm, -3, false); + pushstring(sqvm, "MY_CONSTANT"); + pushstring(sqvm, "MY_VALUE"); + newslot(sqvm, -3, false); - removeFromStack(sqvm); // don't forget this! + removeFromStack(sqvm); // don't forget this! ``` @@ -172,13 +172,13 @@ returns `0` if the function was found. ```cpp - SQObject functionobj {}; - int result = sq_getfunction(m_pSQVM->sqvm, funcname, &functionobj, 0); - if (result != 0) // This func returns 0 on success for some reason - { - NS::log::squirrel_logger()->error("Call was unable to find function with name '{}'. Is it global?", funcname); - return SQRESULT_ERROR; - } + SQObject functionobj {}; + int result = sq_getfunction(m_pSQVM->sqvm, funcname, &functionobj, 0); + if (result != 0) // This func returns 0 on success for some reason + { + NS::log::squirrel_logger()->error("Call was unable to find function with name '{}'. Is it global?", funcname); + return SQRESULT_ERROR; + } ``` !!! cpp-function "T* getentity(HSquirrelVM* sqvm, SQInteger iStackPos)" @@ -212,16 +212,16 @@ More information about function calls are available [here](sq_functions.md) ```cpp - ADD_SQFUNC("void", SQCallbackTest, "void functionref()", "", ScriptContext::UI) - { - SQObject fn; // Make an empty sqobject. This will hold the function object later - g_pSquirrel->__sq_getobject(sqvm, 1, &fn); // Assign the function object to the SQOBJECT - g_pSquirrel->pushobject(sqvm, &fn); // Push the function object for the call - g_pSquirrel->pushroottable(sqvm); // Push the root table for the function stack - g_pSquirrel->__sq_call(sqvm, 1, false, true); // call the function with one parameter (the 'this' object) - - return SQRESULT_NULL; - } + ADD_SQFUNC("void", SQCallbackTest, "void functionref()", "", ScriptContext::UI) + { + SQObject fn; // Make an empty sqobject. This will hold the function object later + g_pSquirrel->__sq_getobject(sqvm, 1, &fn); // Assign the function object to the SQOBJECT + g_pSquirrel->pushobject(sqvm, &fn); // Push the function object for the call + g_pSquirrel->pushroottable(sqvm); // Push the root table for the function stack + g_pSquirrel->__sq_call(sqvm, 1, false, true); // call the function with one parameter (the 'this' object) + + return SQRESULT_NULL; + } ``` !!! cpp-function "SQRESULT get(HSquirrelVM* sqvm, const SQInteger stackpos)" diff --git a/docs/Modding/squirrel/cpp_api/objectmanipulation.md b/docs/Modding/squirrel/cpp_api/objectmanipulation.md index 6697db05..e50ab08b 100644 --- a/docs/Modding/squirrel/cpp_api/objectmanipulation.md +++ b/docs/Modding/squirrel/cpp_api/objectmanipulation.md @@ -13,16 +13,16 @@ creates a new array and pushes it to the stack ```cpp - newarray(sqvm, 0); - pushstring(sqvm, "val1"); - arrayappend(sqvm, -2); - pushinteger(sqvm, 15); - arrayappend(sqvm, -2); - - /* - The array on the stack now looks like this: - [ "val1", 15 ] - */ + newarray(sqvm, 0); + pushstring(sqvm, "val1"); + arrayappend(sqvm, -2); + pushinteger(sqvm, 15); + arrayappend(sqvm, -2); + + /* + The array on the stack now looks like this: + [ "val1", 15 ] + */ ``` @@ -56,31 +56,31 @@ pops a key and a value from the stack and performs a set operation on the table or class that is at position idx in the stack, if the slot does not exist it will be created. ```cpp - newtable(sqvm); - // slot 1 - pushstring(sqvm, "key"); - pushstring(sqvm, "value"); - newslot(sqvm, -3); - // slot 2 - pushstring(sqvm, "key2"); - pushasset(sqvm, "value2"); - newslot(sqvm, -3); - // slot 3 - pushstring(sqvm, "key3"); - newtable(sqvm); - pushstring(sqvm, "sub"); - pushinteger(sqvm, 13); - newslot(sqvm, -3); - newslot(sqvm, -3); - - /* - The table on the stack now looks like this: - { - key = "value" - key2 = $"value2" - key3 = { sub = 13 } - } - */ + newtable(sqvm); + // slot 1 + pushstring(sqvm, "key"); + pushstring(sqvm, "value"); + newslot(sqvm, -3); + // slot 2 + pushstring(sqvm, "key2"); + pushasset(sqvm, "value2"); + newslot(sqvm, -3); + // slot 3 + pushstring(sqvm, "key3"); + newtable(sqvm); + pushstring(sqvm, "sub"); + pushinteger(sqvm, 13); + newslot(sqvm, -3); + newslot(sqvm, -3); + + /* + The table on the stack now looks like this: + { + key = "value" + key2 = $"value2" + key3 = { sub = 13 } + } + */ ``` ## Structs @@ -106,22 +106,22 @@ Pops a value from the stack and fills the field at `fieldIndex` from the struct object that needs to be at the top of the stack. ```cpp - pushnewstructinstance(sqvm, 2); // create a struct instance with 2 slots - pushinteger(sqvm, 12); - sealstructslot(sqvm, 0); - pushstring(sqvm, "example", -1); - sealstructslot(sqvm, 1); - - /* - Assuming the compiler expects this slot: - struct ExStruct { int i, string s } - , the struct on the stack looks like this - - ExStruct { - i = 12, - s = "example" - } - */ + pushnewstructinstance(sqvm, 2); // create a struct instance with 2 slots + pushinteger(sqvm, 12); + sealstructslot(sqvm, 0); + pushstring(sqvm, "example", -1); + sealstructslot(sqvm, 1); + + /* + Assuming the compiler expects this slot: + struct ExStruct { int i, string s } + , the struct on the stack looks like this + + ExStruct { + i = 12, + s = "example" + } + */ ``` # Userdata diff --git a/docs/Modding/squirrel/cpp_api/sq_functions.md b/docs/Modding/squirrel/cpp_api/sq_functions.md index 2595d9d3..bad9053f 100644 --- a/docs/Modding/squirrel/cpp_api/sq_functions.md +++ b/docs/Modding/squirrel/cpp_api/sq_functions.md @@ -22,32 +22,32 @@ Parameters are the initial stack in the function context. Return a string from a native registered function: ```cpp - ADD_SQFUNC("string", CPlugTest, "", "returns \"native gaming\"", ScriptContext::CLIENT | ScriptContext::SERVER) - { - g_pSquirrel->pushstring(sqvm, "native gaming"); // push a string to the stack +ADD_SQFUNC("string", CPlugTest, "", "returns \"native gaming\"", ScriptContext::CLIENT | ScriptContext::SERVER) +{ + g_pSquirrel->pushstring(sqvm, "native gaming"); // push a string to the stack - return SQRESULT_NOTNULL; // Signal that the topmost item on the stack is returned by this function - } + return SQRESULT_NOTNULL; // Signal that the topmost item on the stack is returned by this function +} ``` Return a complex `ornull` type: ```cpp - ADD_SQFUNC("array ornull", CPlugComplex, "int n", "returns null", ScriptContext::CLIENT | ScriptContext::SERVER | ScriptContext::UI) - { - SQInteger n = g_pSquirrel->getinteger(sqvm, 1); +ADD_SQFUNC("array ornull", CPlugComplex, "int n", "returns null", ScriptContext::CLIENT | ScriptContext::SERVER | ScriptContext::UI) +{ + SQInteger n = g_pSquirrel->getinteger(sqvm, 1); - if (n == 0) - return SQRESULT_NULL; + if (n == 0) + return SQRESULT_NULL; - g_pSquirrel->newarray(sqvm, 0); - g_pSquirrel->pushinteger(sqvm, n); - g_pSquirrel->arrayappend(sqvm, 2); - g_pSquirrel->pushinteger(sqvm, n * 2); - g_pSquirrel->arrayappend(sqvm, 2); + g_pSquirrel->newarray(sqvm, 0); + g_pSquirrel->pushinteger(sqvm, n); + g_pSquirrel->arrayappend(sqvm, 2); + g_pSquirrel->pushinteger(sqvm, n * 2); + g_pSquirrel->arrayappend(sqvm, 2); - return SQRESULT_NOTNULL; // return the array [ n, n * 2 ] or NULL if n == 0 - } + return SQRESULT_NOTNULL; // return the array [ n, n * 2 ] or NULL if n == 0 +} ``` ## Replacing Squirrel Functions @@ -71,10 +71,10 @@ It's also possible to add an override directly with the `AddFuncOverride` functi - `SQFunc func` A function object that replaces the logic ```cpp - // Replaces dangerous vanilla functions to only log their call with no further logic. - g_pSquirrel->AddFuncOverride("DevTextBufferWrite", SQ_StubbedFunc); - g_pSquirrel->AddFuncOverride("DevTextBufferClear", SQ_StubbedFunc); - g_pSquirrel->AddFuncOverride("DevTextBufferDumpToFile", SQ_StubbedFunc); +// Replaces dangerous vanilla functions to only log their call with no further logic. +g_pSquirrel->AddFuncOverride("DevTextBufferWrite", SQ_StubbedFunc); +g_pSquirrel->AddFuncOverride("DevTextBufferClear", SQ_StubbedFunc); +g_pSquirrel->AddFuncOverride("DevTextBufferDumpToFile", SQ_StubbedFunc); ``` ## Script Contexts @@ -113,7 +113,7 @@ Squirrel functions need to return a `SQRESULT`. Valid results are If you want to call into squirrel asynchronously, use `AsyncCall`_ instead. ```cpp - Call("PluginCallbackTest"); // PluginCallbackTest() + Call("PluginCallbackTest"); // PluginCallbackTest() ``` @@ -127,7 +127,7 @@ Squirrel functions need to return a `SQRESULT`. Valid results are This is a squirrel API wrapper added by northstar. It's not available for plugins and is supposed to abstract squirrel calls. ```cpp - Call("PluginCallbackTest", "param"); // PluginCallbackTest("param") + Call("PluginCallbackTest", "param"); // PluginCallbackTest("param") ``` @@ -167,19 +167,19 @@ Squirrel functions need to return a `SQRESULT`. Valid results are This is a squirrel API wrapper added by northstar. It's not available for plugins and is supposed to abstract squirrel calls. ```cpp - SQObject functionobj {}; - SQRESULT result = g_pSquirrel->sq_getfunction(sqvm, "PluginCallbackTest", &functionobj, 0); // Get a global squirrel function called "PluginCallbackTest" - - if (result == SQRESULT_ERROR) - { - spdlog::error("Unable to find function. Is it global?"); - return SQRESULT_ERROR; - } - - g_pSquirrel->pushobject(sqvm, &functionobj); - g_pSquirrel->pushroottable(sqvm); - g_pSquirrel->pushstring(sqvm, "param"); - return g_pSquirrel->_call(sqvm, 1); // PluginCallbackTest("param") + SQObject functionobj {}; + SQRESULT result = g_pSquirrel->sq_getfunction(sqvm, "PluginCallbackTest", &functionobj, 0); // Get a global squirrel function called "PluginCallbackTest" + + if (result == SQRESULT_ERROR) + { + spdlog::error("Unable to find function. Is it global?"); + return SQRESULT_ERROR; + } + + g_pSquirrel->pushobject(sqvm, &functionobj); + g_pSquirrel->pushroottable(sqvm); + g_pSquirrel->pushstring(sqvm, "param"); + return g_pSquirrel->_call(sqvm, 1); // PluginCallbackTest("param") ``` @@ -206,16 +206,16 @@ Squirrel functions need to return a `SQRESULT`. Valid results are Throws an error with `error` being the thrown object. ```cpp - ADD_SQFUNC("void", CPlugThrowTest, "", "", ScriptContext::UI) - { - return g_pSquirrel->raiseerror(sqvm, "test error"); - } - - /* sq: - try { - CPlugThrowTest() - } catch(e) { - print(e) // "test error" - } - */ + ADD_SQFUNC("void", CPlugThrowTest, "", "", ScriptContext::UI) + { + return g_pSquirrel->raiseerror(sqvm, "test error"); + } + + /* sq: + try { + CPlugThrowTest() + } catch(e) { + print(e) // "test error" + } + */ ``` diff --git a/docs/Modding/squirrel/functions.md b/docs/Modding/squirrel/functions.md index 01b039dc..03859400 100644 --- a/docs/Modding/squirrel/functions.md +++ b/docs/Modding/squirrel/functions.md @@ -9,10 +9,10 @@ Functions in squirrel are defined with this syntax: ` function args ) - { - // client side command handle logic ... - } +void function MessageUtils_ClientInit() +{ + AddServerToClientStringCommandCallback( "ServerHUDMessageShow", ServerCallback_CreateServerHUDMessage ) +} + +void function ServerCallback_CreateServerHUDMessage ( array args ) +{ + // client side command handle logic ... +} ``` ## `SERVER` to `UI` vm @@ -137,7 +137,7 @@ and execute with the function serverside: #### Example ```squirrel - Remote_CallFunction_UI( player, "ScriptCallback_UnlockAchievement", achievementID ) +Remote_CallFunction_UI( player, "ScriptCallback_UnlockAchievement", achievementID ) ``` ## `CLIENT` to `SERVER` vm @@ -165,13 +165,13 @@ Since version 1.5 mods can receive notifications when a client command has been Example usage with the :doc:`PrivateMatchLaunch` clientcommand ```squirrel - void function init(){ - AddClientCommandNotifyCallback("PrivateMatchLaunch", started) - } + void function init(){ + AddClientCommandNotifyCallback("PrivateMatchLaunch", started) + } - void function started(entity player, array args){ - print(player + " started the match") - } + void function started(entity player, array args){ + print(player + " started the match") + } ``` Please refer to :ref:`list_client_commands` for a list of native client commands you could catch. @@ -188,16 +188,16 @@ You can also pass parameters to the function. `identifier` is the name of the fu ## Example ```squirrel - #if UI - global function CallMe - - void function CallMe( int a, int b ) - { - printt( a + b ) - } - #elseif CLIENT - RunUIScript( "CallMe", 1, 2 ) // 3 - #endif +#if UI +global function CallMe + +void function CallMe( int a, int b ) +{ + printt( a + b ) +} +#elseif CLIENT +RunUIScript( "CallMe", 1, 2 ) // 3 +#endif ``` ## `UI` to `CLIENT` vm @@ -212,16 +212,16 @@ You can also pass parameters to the function. `identifier` is the name of the fu #### Example ```squirrel - #if CLIENT - global function CallMe - - void function CallMe( int a, int b ) - { - printt( a + b ) - } - #elseif UI - RunClientScript( "CallMe", 1, 2 ) // 3 - #endif +#if CLIENT +global function CallMe + +void function CallMe( int a, int b ) +{ + printt( a + b ) +} +#elseif UI +RunClientScript( "CallMe", 1, 2 ) // 3 +#endif ``` diff --git a/docs/Modding/squirrel/statements.md b/docs/Modding/squirrel/statements.md index b21c367d..1b05b7fd 100644 --- a/docs/Modding/squirrel/statements.md +++ b/docs/Modding/squirrel/statements.md @@ -5,13 +5,13 @@ If statements use a similar style to most programming languages and will execute their asigned code if the test placed inside returns the boolean value true. If I wanted to have something occur if, and only if, our previous `ReturnTrueOrFalse` function returned true, then you can use: ```squirrel - if( ReturnTrueOrFalse() ) +if( ReturnTrueOrFalse() ) ``` Conditional operators can also be used to make comparisons, such as `==` (equals), `<` (less than), `<=` (less than or equal), `!=` (not equal), etc., returning true if their condition is satisfied. For example, to execute code if a dice roll landed on 5: ```squirrel - if( RandomInt( 6 ) + 1 == 5 ) +if( RandomInt( 6 ) + 1 == 5 ) ``` Like other languages, if statements can be connected to `else if` and `else` statements. `else if` statements must be used immediately after an `if` or `else if` and will only check their condition if the preceding statements failed. `else` statements behave similarly, but always run if the preceding statements failed and must be last. @@ -20,8 +20,8 @@ Squirrel supports ternary operations like most languages. The value of the expre The Syntax is `condition ? if_condition_true : if_condition_false`. This is especially useful when declaring variables or passing parameters. ```squirrel - // shortenedUsername is "longus..."" if username is "longusername" or "short" if username is "short" - string shortenedUsername = username.len() > 9 ? username.slice(0,6) + "..." : username; +// shortenedUsername is "longus..."" if username is "longusername" or "short" if username is "short" +string shortenedUsername = username.len() > 9 ? username.slice(0,6) + "..." : username; ``` ## Loops @@ -33,15 +33,15 @@ Loops are used to execute the same code n times. A while loop runs as long as the condition evaluates to a truthy value. ```squirrel - while( true ) - { +while( true ) +{ // this will result in an endless loop because the probe condition will never be false - } +} - while( RandomInt( 2 ) ) - { +while( RandomInt( 2 ) ) +{ // This will run until a 1 is generated by chance, because squirrel treats 0 as a falsy value and 1 as truthy. - } +} ``` ### Do While Loop @@ -49,10 +49,10 @@ A while loop runs as long as the condition evaluates to a truthy value. A do while loop is the same as a while loop but the condition is checked **after** the body is executed. ```squirrel - do - { +do +{ // this will execute only one time - } while( false ) +} while( false ) ``` ### For Loop @@ -62,18 +62,18 @@ A for loop also runs until a condition is met however it provides you with a cou The Syntax is as follows: `for( int counter; condition; behaviour_after_body_execution )` ```squirrel - // prints 0, 1, 2, 3, 4 - for( int i; i < 5; i++ ) - { +// prints 0, 1, 2, 3, 4 +for( int i; i < 5; i++ ) +{ print( i ) - } +} - array arr = [ 14, 2, 18, 9 ] - // prints 14, 2, 18, 9 - for( int i; i < arr.len() * 2; i += 2 ) - { +array arr = [ 14, 2, 18, 9 ] +// prints 14, 2, 18, 9 +for( int i; i < arr.len() * 2; i += 2 ) +{ print( arr[i] ) - } +} ``` ### Foreach Loop @@ -81,23 +81,23 @@ The Syntax is as follows: `for( int counter; condition; behaviour_after_body_exe A foreach loop iterates over a `table` or an `array` and executes for each entry. The loop provides you with an optional counter for arrays or key for tables. ```squirrel - array arr = [ 1, 2, 3, 4 ] - table map = { +array arr = [ 1, 2, 3, 4 ] +table map = { key1 = "mapped value 1", key2 = "mapped value 2" - } +} - // prints 0 1, 1 2, 2 3, 3 4 - foreach( int index, int value in arr ) - { +// prints 0 1, 1 2, 2 3, 3 4 +foreach( int index, int value in arr ) +{ printt( index, value ) - } +} - // prints key1 mapped value 1, key2 mapped value 2 - foreach( string key, string value in map ) - { +// prints key1 mapped value 1, key2 mapped value 2 +foreach( string key, string value in map ) +{ printt( key, value ) - } +} ``` ## Implicit conditional behavior @@ -121,28 +121,28 @@ So great, we can loop and check things, but what can we do with this information For example, lets make our `ReturnTrueOrFalse` function, that randomly picks either true or false, first: ```squirrel - bool function ReturnTrueOrFalse() { +bool function ReturnTrueOrFalse() { return RandomInt(2) == 1 - } +} ``` Note that while functions always need `{}`, single-line `if`/`else` statements and loops do not: ```squirrel - if(ReturnTrueOrFalse()) +if(ReturnTrueOrFalse()) printt("Only called if true") ``` Now let's make a more complicated function that will use the previous script to determine true or false, printing a list each time it returns true: ```squirrel - array someinformation = [1,2,3,4,5,6] - void function ThisDoesStuff(){ +array someinformation = [1,2,3,4,5,6] +void function ThisDoesStuff(){ while(ReturnTrueOrFalse()){ - foreach( int information in someinformation){ - printt(information) - } + foreach( int information in someinformation){ + printt(information) + } } - } +} ``` diff --git a/docs/Modding/squirrel/statements/controlflow.md b/docs/Modding/squirrel/statements/controlflow.md index a968ac03..e55816b3 100644 --- a/docs/Modding/squirrel/statements/controlflow.md +++ b/docs/Modding/squirrel/statements/controlflow.md @@ -7,7 +7,7 @@ Squirrel supports most basic control flow statements. `if` statements check if a condition evaluates to `true`. ```squirrel - if ( expression ) +if ( expression ) body ``` diff --git a/docs/Modding/squirrel/types/arrays.md b/docs/Modding/squirrel/types/arrays.md index 6b5ce31c..da88d0fd 100644 --- a/docs/Modding/squirrel/types/arrays.md +++ b/docs/Modding/squirrel/types/arrays.md @@ -15,12 +15,12 @@ Arrays are always zero indexed with `[ ]`. The indexes are always n Array literals are a comma or newline seperated sequence of expressions delimited by an opening bracket `[` and a corresponding closing bracket `]`. ```squirrel - array a = [ 1, 2, 3 ] - array b = [ +array a = [ 1, 2, 3 ] +array b = [ 1 2 3 - ] +] ``` ## Primitive Arrays @@ -28,15 +28,15 @@ Array literals are a comma or newline seperated sequence of expressions delimite Primitive arrays are arrays that can hold any value. Their content is therefore untyped. ```squirrel - array a - a.append( 1 ) // add a number - a.append( "str" ) // add a string - a.append( [] ) // add an empty array - - // because the content type of the array is not defined, all content will be var - var n = a[0] - var str = a[1] - var arr = a[2] +array a +a.append( 1 ) // add a number +a.append( "str" ) // add a string +a.append( [] ) // add an empty array + +// because the content type of the array is not defined, all content will be var +var n = a[0] +var str = a[1] +var arr = a[2] ``` ## Complex Arrays @@ -48,10 +48,10 @@ The content type needs to be specified within `<` and `>` brackets. There is no way to define a complex array that holds multiple different types. ```squirrel - array a - a.append( 1 ) - a.append( 0x2 ) - a.append( "3" ) // this will throw a compile error because the array can only contain integers +array a +a.append( 1 ) +a.append( 0x2 ) +a.append( "3" ) // this will throw a compile error because the array can only contain integers ``` @@ -68,12 +68,12 @@ You can index and change content values like with regular arrays. When initializing a static array you can omit all values after your initial values with `...`. All following values will get default initialized with the content's default. ```squirrel - float[3] v1 - float[8] v2 = [ 1.0, 2.0, ... ] - v2[2] = 3.0 +float[3] v1 +float[8] v2 = [ 1.0, 2.0, ... ] +v2[2] = 3.0 - print( v1[0] ) // notice how no value needs to be pushed into the vector - print( v2[7] ) // will print 0.0 because it has been default initialized +print( v1[0] ) // notice how no value needs to be pushed into the vector +print( v2[7] ) // will print 0.0 because it has been default initialized ``` ## Compatability @@ -83,11 +83,11 @@ It is not possible to cast or convert an array between their different forms. Fo Instead you need to create an entirely new array with the target type or add all contents manually. ```squirrel - array orig = [ "a", "b", "c" ] - array target +array orig = [ "a", "b", "c" ] +array target - target.clear() // clear all contents from the target array - foreach( v in orig ) // iterate over the original array and add all contents to the target array +target.clear() // clear all contents from the target array +foreach( v in orig ) // iterate over the original array and add all contents to the target array target.append( v ) ``` diff --git a/docs/Modding/squirrel/types/entities.md b/docs/Modding/squirrel/types/entities.md index 42e67b23..4664b162 100644 --- a/docs/Modding/squirrel/types/entities.md +++ b/docs/Modding/squirrel/types/entities.md @@ -11,10 +11,10 @@ You can not specify which entity class a variable is supposed to hold so you nee If you need to check the class of an entity at runtime you can do so with the `instanceof` operator. ```squirrel - bool function IsCPlayer( entity e ) - { +bool function IsCPlayer( entity e ) +{ return e instanceof CPlayer - } +} ``` Entities are `null` initialized and there are no literals for entities. diff --git a/docs/Modding/squirrel/types/functionrefs.md b/docs/Modding/squirrel/types/functionrefs.md index 3b9a4e58..1e5e02ab 100644 --- a/docs/Modding/squirrel/types/functionrefs.md +++ b/docs/Modding/squirrel/types/functionrefs.md @@ -5,11 +5,11 @@ Function references are a complex type that can reference any function or closur The type keyword is `functionref` and needs to include any parameter types and optionally return types. ```squirrel - void function CallDelayed( void functionref() fn ) - { +void function CallDelayed( void functionref() fn ) +{ wait 1 fn() - } +} ``` You can call functionrefs like a regular function. The return type of a functionref will default to `var` if omitted. Omitting the return type is only possible in `untyped` files. diff --git a/docs/Modding/squirrel/types/ornull.md b/docs/Modding/squirrel/types/ornull.md index 99490801..a1cd0293 100644 --- a/docs/Modding/squirrel/types/ornull.md +++ b/docs/Modding/squirrel/types/ornull.md @@ -8,16 +8,16 @@ This is required for nesting structs inside themselves to ensure they are fixed To use the value of an `ornull` variable you need to ensure that it is not `null` and then cast to the correct type. ```squirrel - int ornull n = null - n = 1 +int ornull n = null +n = 1 - if( n != null ) - { +if( n != null ) +{ expect int( n ) // n is now in this scope an int n += 2 - } +} - print( n ) // 3 +print( n ) // 3 ``` Being required to cast the value of `ornull` variables makes it impossible to use it with types that cannot be casted like complex arrays. You can still make complex ornull variables, just be aware that the content type can never be recasted. diff --git a/docs/Modding/squirrel/types/structs.md b/docs/Modding/squirrel/types/structs.md index 370ec105..42583fa1 100644 --- a/docs/Modding/squirrel/types/structs.md +++ b/docs/Modding/squirrel/types/structs.md @@ -9,12 +9,12 @@ Before using a struct you need to define it and all contents. The fields are typed like any regular variable. ```squirrel - struct MyStruct - { +struct MyStruct +{ int field1 string field2 array field3 - } +} ``` You can then use `MyStruct` as a type anywhere in the file. @@ -42,21 +42,21 @@ Similar like in static arrays, you can omit any fields that should have their ty Struct fields can be any type, this includes previously declared structs as well. ```squirrel - struct Engine - { +struct Engine +{ string manufacturer - } +} - struct Tire - { +struct Tire +{ string material - } +} - struct Car - { +struct Car +{ Engine engine, Tire[4] tires - } +} ``` ### Self Nesting Structs @@ -64,11 +64,11 @@ Struct fields can be any type, this includes previously declared structs as well Structs can contain fields of their own type, however they need to be **null initialized**. You can achieve this by specifying their type as `ornull`. ```squirrel - struct LinkedList - { +struct LinkedList +{ var content LinkedList ornull nextNode - } +} ``` ## Field Default Values @@ -78,10 +78,10 @@ Any struct field can have an optional default value. If omitted, the type's defa Default values need to be a constant expression that can be evaluated at compile time. ```squirrel - struct Dice - { +struct Dice +{ int[6] sides = [ 1, 2, 3, 4, 5, 6 ] - } +} ``` ## Singleton Instances @@ -89,27 +89,27 @@ Default values need to be a constant expression that can be evaluated at compile You can define a struct and initialize a local variable of that struct instantly with singletons. These are often used to have global variables that are only used in a single script file. ```squirrel - struct { +struct { var menu - } file +} file - void function InitMyMenu() - { +void function InitMyMenu() +{ file.menu = GetMenu( "SomeMenu" ) - } +} ``` Singletons can also be used for struct fields. ```squirrel - struct Car - { +struct Car +{ struct { - string manufacturer - } engine - } + string manufacturer + } engine +} - // ... - Car car - car.engine.manufacturer = "Vinson Dynamics" +// ... +Car car +car.engine.manufacturer = "Vinson Dynamics" ``` diff --git a/docs/Modding/squirrel/types/tables.md b/docs/Modding/squirrel/types/tables.md index 4b52bd74..4b1d13a1 100644 --- a/docs/Modding/squirrel/types/tables.md +++ b/docs/Modding/squirrel/types/tables.md @@ -25,13 +25,13 @@ Each entry needs to have a key, seperated from the initial value with a `=`. Table keys will be by default strings if you just write their identifier in the literal. However they can also be any expression if wrapped with `[` and `]`. ```squirrel - table t = { key1 = 1, key2 = "2" } - table t2 = { +table t = { key1 = 1, key2 = "2" } +table t2 = { randomValue = getSomethingRandom() [1] = 0x1 - } +} - printt( t["key1"], t2[1] ) // 1 1 +printt( t["key1"], t2[1] ) // 1 1 ``` ## Primitive Tables @@ -45,7 +45,7 @@ Any value of key of the table will therefore be `var` if retrieved. Complex tables are tables that have their content types defined. It is necessary to both define the key and value types. ```squirrel - table numbers = { +table numbers = { one = 1, two = 2, three = 3, @@ -55,6 +55,6 @@ Complex tables are tables that have their content types defined. It is necessary seven = 7, eight = 8, nine = 9 - } +} ```