# Table of Contents - [Indie Marc | Home](#indie-marc-home) - [TCG Engine](#tcg-engine) - [Asset Installation | TCG Engine](#asset-installation-tcg-engine) - [Testing Multiplayer | TCG Engine](#testing-multiplayer-tcg-engine) - [AI | TCG Engine](#ai-tcg-engine) - [Resources and Prefabs | TCG Engine](#resources-and-prefabs-tcg-engine) - [Cards | TCG Engine](#cards-tcg-engine) - [Testing in Solo | TCG Engine](#testing-in-solo-tcg-engine) - [Cloud Server Installation | TCG Engine](#cloud-server-installation-tcg-engine) - [Remote Access and Authentication | TCG Engine](#remote-access-and-authentication-tcg-engine) - [Conditions and Effects | TCG Engine](#conditions-and-effects-tcg-engine) - [Save File | TCG Engine](#save-file-tcg-engine) - [Status | TCG Engine](#status-tcg-engine) - [Game Rules | TCG Engine](#game-rules-tcg-engine) - [Scripts Overview | TCG Engine](#scripts-overview-tcg-engine) - [Abilities | TCG Engine](#abilities-tcg-engine) - [Netcode Plus | NetcodePlus](#netcode-plus-netcodeplus) - [TCG Engine Roguelike](#tcg-engine-roguelike) - [Getting Started | Dialogue Quests](#getting-started-dialogue-quests) - [User Login API](#user-login-api) - [Test with Insomnia | TCG Engine](#test-with-insomnia-tcg-engine) - [Filters | TCG Engine](#filters-tcg-engine) - [Web API | TCG Engine](#web-api-tcg-engine) - [Local Installation | TCG Engine](#local-installation-tcg-engine) - [Cloud Server Installation | TCG Engine](#cloud-server-installation-tcg-engine) - [Enable Email Sending | TCG Engine](#enable-email-sending-tcg-engine) - [Enable HTTPS | TCG Engine](#enable-https-tcg-engine) - [Asset Installation | NetcodePlus](#asset-installation-netcodeplus) - [Asset Installation | TCG Engine Roguelike](#asset-installation-tcg-engine-roguelike) - [Testing in Solo | TCG Engine Roguelike](#testing-in-solo-tcg-engine-roguelike) - [Network Types | NetcodePlus](#network-types-netcodeplus) - [Testing Locally | NetcodePlus](#testing-locally-netcodeplus) - [Testing Multiplayer | TCG Engine Roguelike](#testing-multiplayer-tcg-engine-roguelike) - [Lobby and Matchmaking | NetcodePlus](#lobby-and-matchmaking-netcodeplus) - [Install Server Locally | User Login API](#install-server-locally-user-login-api) - [Unity Services Server | TCG Engine Roguelike](#unity-services-server-tcg-engine-roguelike) - [Cloud Server Installation | TCG Engine Roguelike](#cloud-server-installation-tcg-engine-roguelike) - [Cloud Server Installation | NetcodePlus](#cloud-server-installation-netcodeplus) - [Unity Services Server | NetcodePlus](#unity-services-server-netcodeplus) - [Test with Insomnia | User Login API](#test-with-insomnia-user-login-api) - [Messages and Choices | Dialogue Quests](#messages-and-choices-dialogue-quests) - [Narrative Event | Dialogue Quests](#narrative-event-dialogue-quests) - [Actors | Dialogue Quests](#actors-dialogue-quests) - [Resources and Prefabs | TCG Engine Roguelike](#resources-and-prefabs-tcg-engine-roguelike) - [Remote Access and DB Authentication | User Login API](#remote-access-and-db-authentication-user-login-api) - [Save File | TCG Engine Roguelike](#save-file-tcg-engine-roguelike) - [Enable HTTPS | User Login API](#enable-https-user-login-api) - [Quests | Dialogue Quests](#quests-dialogue-quests) - [Managers and Important Scripts | NetcodePlus](#managers-and-important-scripts-netcodeplus) - [Cloud Server Installation | User Login API](#cloud-server-installation-user-login-api) - [Scenario and Maps | TCG Engine Roguelike](#scenario-and-maps-tcg-engine-roguelike) - [SNetworkObject | NetcodePlus](#snetworkobject-netcodeplus) - [Conditions | Dialogue Quests](#conditions-dialogue-quests) - [Connection Process | NetcodePlus](#connection-process-netcodeplus) - [SNetworkBehaviour | NetcodePlus](#snetworkbehaviour-netcodeplus) - [Effects | Dialogue Quests](#effects-dialogue-quests) - [Tags | Dialogue Quests](#tags-dialogue-quests) - [Map Events | TCG Engine Roguelike](#map-events-tcg-engine-roguelike) - [Enable Email Sending | User Login API](#enable-email-sending-user-login-api) - [UI | Dialogue Quests](#ui-dialogue-quests) - [SNetworkVariable | NetcodePlus](#snetworkvariable-netcodeplus) - [Characters | TCG Engine Roguelike](#characters-tcg-engine-roguelike) - [SNetworkActions | NetcodePlus](#snetworkactions-netcodeplus) - [Register and Login | User Login API](#register-and-login-user-login-api) - [Network Messages | NetcodePlus](#network-messages-netcodeplus) - [Save File | Dialogue Quests](#save-file-dialogue-quests) - [Get Users | User Login API](#get-users-user-login-api) - [Unity Requests | User Login API](#unity-requests-user-login-api) - [Gain Rewards | User Login API](#gain-rewards-user-login-api) - [Status | TCG Engine Roguelike](#status-tcg-engine-roguelike) - [Abilities | TCG Engine Roguelike](#abilities-tcg-engine-roguelike) - [Custom Conditions | Dialogue Quests](#custom-conditions-dialogue-quests) - [Activity | User Login API](#activity-user-login-api) - [Support and Community | NetcodePlus](#support-and-community-netcodeplus) - [Edit Users | User Login API](#edit-users-user-login-api) - [AI | TCG Engine Roguelike](#ai-tcg-engine-roguelike) - [Contacts/Friends | User Login API](#contacts-friends-user-login-api) - [Custom Effects | Dialogue Quests](#custom-effects-dialogue-quests) - [Scripts Overview | Dialogue Quests](#scripts-overview-dialogue-quests) - [In Control | Dialogue Quests](#in-control-dialogue-quests) - [New Input System | Dialogue Quests](#new-input-system-dialogue-quests) - [Survival Engine | Dialogue Quests](#survival-engine-dialogue-quests) - [Filters | TCG Engine Roguelike](#filters-tcg-engine-roguelike) - [NetcodePlus Integration | User Login API](#netcodeplus-integration-user-login-api) - [Conditions and Effects | TCG Engine Roguelike](#conditions-and-effects-tcg-engine-roguelike) - [Map Events | TCG Engine Roguelike](#map-events-tcg-engine-roguelike) - [Custom Code and Data | User Login API](#custom-code-and-data-user-login-api) - [Scripts Overview | TCG Engine Roguelike](#scripts-overview-tcg-engine-roguelike) - [Enemy Behaviors | TCG Engine Roguelike](#enemy-behaviors-tcg-engine-roguelike) - [Support and Community | User Login API](#support-and-community-user-login-api) - [Cards | TCG Engine Roguelike](#cards-tcg-engine-roguelike) - [Managers and Important Scripts | NetcodePlus](#managers-and-important-scripts-netcodeplus) - [Unity Requests | User Login API](#unity-requests-user-login-api) - [Custom Code and Data | User Login API](#custom-code-and-data-user-login-api) - [Support and Community | NetcodePlus](#support-and-community-netcodeplus) --- # Indie Marc | Home ### [](https://indiemarc.gitbook.io/home#documentation) Documentation [![Logo](https://indiemarc.gitbook.io/home/~gitbook/image?url=https%3A%2F%2Findiemarc.gitbook.io%2Fnetcodeplus%2F%7Egitbook%2Ficon%3Fsize%3Dsmall%26theme%3Dlight&width=20&dpr=4&quality=100&sign=8784042b&sv=2)Netcode Plus | NetcodePlusindiemarc.gitbook.io](https://indiemarc.gitbook.io/netcodeplus/) [![Logo](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Ficon%252FWYfe7QExqH3YisUNlBJx%252Flogo.png%3Falt%3Dmedia%26token%3D49cde28c-8de0-4557-b560-fda847db266f&width=48&height=48&sign=e7ae58fa&sv=2)TCG Engineindiemarc.gitbook.io](https://indiemarc.gitbook.io/tcg-engine/) [![Logo](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Ficon%252FKycmdHJF1kvL2C030U56%252Flogo.png%3Falt%3Dmedia%26token%3D49cde28c-8de0-4557-b560-fda847db266f&width=48&height=48&sign=b9124f95&sv=2)TCG Engine Roguelikeindiemarc.gitbook.io](https://indiemarc.gitbook.io/tcg-engine-roguelike/) [![Logo](https://indiemarc.gitbook.io/home/~gitbook/image?url=https%3A%2F%2Findiemarc.gitbook.io%2Fdialogue-quests%2F%7Egitbook%2Ficon%3Fsize%3Dsmall%26theme%3Dlight&width=20&dpr=4&quality=100&sign=7a230fb&sv=2)Getting Started | Dialogue Questsindiemarc.gitbook.io](https://indiemarc.gitbook.io/dialogue-quests/) [![Logo](https://indiemarc.gitbook.io/home/~gitbook/image?url=https%3A%2F%2Findiemarc.gitbook.io%2Fuser-api%2F%7Egitbook%2Ficon%3Fsize%3Dsmall%26theme%3Dlight&width=20&dpr=4&quality=100&sign=49ac893&sv=2)User Login API | User Login APIindiemarc.gitbook.io](https://indiemarc.gitbook.io/user-api/) ### [](https://indiemarc.gitbook.io/home#tutorial-videos) Tutorial Videos [![Logo](https://indiemarc.gitbook.io/home/~gitbook/image?url=https%3A%2F%2Fwww.youtube.com%2Fs%2Fdesktop%2F626d9c6b%2Fimg%2Ffavicon_144x144.png&width=20&dpr=4&quality=100&sign=ad777991&sv=2)Indie MarcYouTube](https://www.youtube.com/@indiemarc/videos) ### [](https://indiemarc.gitbook.io/home#support-and-community) Support and Community [![Logo](https://indiemarc.gitbook.io/home/~gitbook/image?url=https%3A%2F%2Fdiscord.com%2Fassets%2Ffavicon.ico&width=20&dpr=4&quality=100&sign=8ea7e5a0&sv=2)Join the Indie Marc - Game Dev Discord Server!Discord](https://discord.gg/JpVwUgG) ### [](https://indiemarc.gitbook.io/home#asset-store) Asset Store [![Logo](https://indiemarc.gitbook.io/home/~gitbook/image?url=https%3A%2F%2Fassetstore.unity.com%2Ffavicon.ico&width=20&dpr=4&quality=100&sign=bc9a6628&sv=2)Indie Marc · Publisher Profile | Unity Asset Storeassetstore.unity.com](https://assetstore.unity.com/publishers/40117?aid=1100l9QHv) Last updated 1 year ago --- # TCG Engine TCG Engine is a template to create online card games in Unity. It supports both solo play and multiplayer on a dedicated authoritative server. It also comes with an AI coded with the Minimax algorithm. ### [](https://indiemarc.gitbook.io/tcg-engine#structure) Structure There are 3 main app instances: Game Client (Unity), Game Server (Unity), and an optional Web API (NodeJS and MongoDB). ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FOrMOvCaDNRvY95GIBU4U%252FServerSetup-TCG.png%3Falt%3Dmedia%26token%3Ddb302084-7171-4dff-814d-08c4950c4aa9&width=300&dpr=4&quality=100&sign=f3a2a56f&sv=2) The NodeJS app is a HTTP API that handles user login, and save all their data into a database. Such as which cards they own, what are their current decks, and how much coins they have. Both the game client and game server can send http web requests (in JSON format) to the api. Some functions need special privilege (such as giving rewards) so that regular users can't give themselves rewards. On the other hand, things such as editing decks can be sent directly from the client. Note that the Web API is completely optional and the template is designed to work without it (with the exception of some features such as the leaderboard and friend list). Without the API all user data will be saved locally instead. The Unity Game Server handles all game actions and gameplay logic, and also does the matchmaking. The Game Server is not necessary if you only want to use the asset for solo play. To run the game in solo you do not need to install any server, just run the client from Unity after importing the template (see asset installation). ### [](https://indiemarc.gitbook.io/tcg-engine#coding-and-development) Coding and Development This is **not** a no-coding asset. And while cards and abilities can be edited directly from the data files (scriptable objects), you will need to edit the code to add features or change the core game rules. I made the decision to not include any custom editor GUI to keep the code as simple as possible and useable for a varied level of programming skills. A custom GUI editor would make the code a LOT more complex, and while they are nice at first for people with no experience, they can quickly become extremely limitative, or force you to do more programming for every task since you would need to consider the editor as well... My goal is to encourage people to go and edit the code directly. I put a high priority on keeping the code clean and well structured. We have a Discord community for people to help each other if you are just starting with coding. And I will be glad to listen to any feedback to improve the code in future versions if needed. Check the Scripts section for more info on the most important scripts, and how to inherit the base conditions and effects class to make your own. ### [](https://indiemarc.gitbook.io/tcg-engine#tutorials) Tutorials Tutorial videos are available on Youtube. [https://www.youtube.com/@indiemarc/videos](https://www.youtube.com/@indiemarc/videos) Last updated 1 year ago --- # Asset Installation | TCG Engine ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/asset-installation#packages) Packages When importing TCG Engine asset, I would recommend to also import all Project Settings. If you override project settings, you need to prevent the ProjectVersion.txt file from importing, because that will break your project (Unity can't downgrade version). This is a Unity bug I am trying to report to Unity. Just turn off the checkbox during Step 2 of 2. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FIxUaBBDpiFpgsacLJ1rf%252Fvers.png%3Falt%3Dmedia%26token%3D1d15a6cd-d818-47b0-8cc1-83b1c66274ea&width=300&dpr=4&quality=100&sign=d5a768f2&sv=2) If you do not wish to override projects settings, you need to make sure you have these packages installed. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FHJIRX2m26AHZjBCwB4et%252Fpackages.png%3Falt%3Dmedia%26token%3D322a57f3-b2db-497c-8efb-beed1818e8a7&width=300&dpr=4&quality=100&sign=9283a93a&sv=2) These are the packages in my project, the ones in green are necessary, the others are optional. Toolchain Win Linux is necessary to build the dedicated server on Linux (I use Linux for my server). I would recommend updating to the latest version of each package, not to the version in this screenshot. ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/asset-installation#render-pipeline) Render pipeline If you plan to use URP (recommended pipeline), in the Projects Settings - Graphics, set the render pipeline to one of the render asset found in the TcgEngine/Render folder. You may also assign the other render asset to the appropriate quality under Projects Settings - Quality. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FpLRpjjomlHOc64P8Wfyx%252Furp.png%3Falt%3Dmedia%26token%3D565a926d-0162-40d4-9003-fcbebba2cdfb&width=300&dpr=4&quality=100&sign=f16d462d&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/asset-installation#urp-only) URP Only ? I would strongly recommend to use URP for a card game. HDRP would be overkill for this type of game since it's more aimed at more realistic 3D games, and the built-in pipeline would prevent you from using cool features such as shader graph or some post-processing effects. Built-in Pipeline is still supported (in 1.01+), if you choose to use Built-in pipeline, go in the TcgEngine/Materials folder and import the Built-in material package. Scripts will also work in HDRP, but the demo FX are currently not supported on HDRP. ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/asset-installation#linux-dedicated-server-build) Linux Dedicated Server Build If you want to be able to build a Linux Dedicated Server, you will also need to install a Unity Module. Go in Unity Hub -> Install -> Settings -> Click on Add Modules Install the Linux Dedicated Server Build Support ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FLVP3PggVDSsBtpB5J8eM%252Fmodule.png%3Falt%3Dmedia%26token%3D20b6369c-bac4-45d4-ac06-c2da508ef9ea&width=300&dpr=4&quality=100&sign=3dd92572&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/asset-installation#restart-unity) Restart Unity In Unity 6, you may need to restart Unity after importing the asset, for the control inputs to work. That's it for the installation, you should now be able to run the game. ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/asset-installation#frequent-install-errors) Frequent Install Errors Check the errors in console after installing the package and trying to run the game. **UI not responding to any click in Menus,** In your project settings Edit-Project Settings-Player-Other Settings : Verify that Active Input Handling and set it to "Both" (If you don't have the Input System package this should be set to Old Input Manager instead). Also try restarting Unity. **Burst Compiler** error, usually you just need to restart Unity. **Invalid Dependencies com.unity.feature.development,** go in package manager, in project, and remove the package with a red ! next to it. If you have this its probably because your unity version downgraded though, so look at the next paragraph just below because that's important, you should not downgrade. **Unity HUB trying to convince you to change Unity Version** when you reopen the project, please do not downgrade Unity Version, as it will break any Unity project, you can only upgrade Unity version. Sometimes Unity Hub still tries to make you downgrade to the Unity version this asset was created with (because of a Unity bug in some Unity Versions that override unity project version when importing project settings). If Unity Hub changed your Unity Version on your project, just reset it to the one you originally used to install the asset. This Asset should work on ALL unity versions after 2020.3.37 (including it), as long as you don't downgrade after importing. **UI not responding to any click in Menus,** could be because you have the Input System installed while the template uses the built-in input. You can safely remove the Input System Package in Package Manager. Otherwise, if you want to keep it for your project: you just need to go in Edit-Project Settings-Player-Other Settings : Active Input Handling and set it to "Both" (If you don't have the Input System package this should be set to Input Manager instead). Last updated 2 months ago --- # Testing Multiplayer | TCG Engine There are two different ways to test the multiplayer gameplay. * Peer 2 peer * Dedicated Server For the final version of the game, it is strongly suggested to use the dedicated server for multiplayer, as peer 2 peer comes with more limited features (matchmaking is on the dedicated server) and because players won't need to setup their firewall and router for port forwarding. A peer 2 peer option is still available to make it easier and faster to test things. ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/testing-multiplayer#peer-to-peer) Peer to Peer To test in peer to peer, build the game with the scene TestP2P as the first scene. And make sure the Game scene is also included in the build. When opening the build you will be asked to join or host, and will be able to join someone else. You can simply run the build twice on the same pc, so that you can play with both players. You can also open the Unity project twice instead of doing a build. (See at the bottom of this page) ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/testing-multiplayer#dedicated-server) Dedicated Server You can either run the dedicated server locally or run it on a cloud server. To run it on the cloud, see the page Cloud Server Installation. To run it locally. Make a build with only 1 scene: Server You can also check the box "Server Build" to disable all graphics from the build. Go in Resources/NetworkData, and change the game server url to the IP or url of your dedicated server (if you run it locally put 127.0.0.1). You can run the server build, and then connect to it from Unity or from a Client build. Client build should include the menu and game scenes. In the client menu, click on Multiplayer. If it shows "Connecting to server..." this means it can't connect to it. If it shows "Finding opponent...", you successfully connected to your server. #### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/testing-multiplayer#client-build) Client Build ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FTOiNABpwgDR2GsagJJXM%252FClientBuild.png%3Falt%3Dmedia%26token%3D45c832df-3e4c-4ca4-bbb8-82cb16d3748e&width=300&dpr=4&quality=100&sign=c27fe5a9&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/testing-multiplayer#server-build) Server Build ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FlfDeCgAxGRa4Hgz4mXVR%252FServerBuild.png%3Falt%3Dmedia%26token%3D1b524924-5e61-47fa-919f-a27bcb0e1cb7&width=300&dpr=4&quality=100&sign=52058d1c&sv=2) (In newest Unity Version, there will be a Dedicated Server tab on the left side instead of a Server Build checkbox). ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/testing-multiplayer#opening-the-unity-project-twice) Opening the Unity Project Twice Opening the unity project twice can save you some build time if you want to quickly be able to test two clients, or one client and one dedicated server, directly from Unity instead of having to make a build each time. Check this tutorial (it is for one of my other assets) to learn how to open the same unity project twice: [https://indiemarc.gitbook.io/netcodeplus/getting-started/testing-locally](https://indiemarc.gitbook.io/netcodeplus/getting-started/testing-locally) Last updated 2 years ago --- # AI | TCG Engine In Resources/GameplayData you can change the AI type and AI level. There are two AI available: Random, and Minimax. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FzC8znbkS7QhQAE0Y4aB0%252Fai.png%3Falt%3Dmedia%26token%3D51d6e3c5-6f95-489c-a0cc-bc785e42550c&width=300&dpr=4&quality=100&sign=924d6ef5&sv=2) Random is a very weak AI that just plays randomly. While Minimax is a much stronger AI that will evaluate moves using an Heuristic. It is quite strong but will not beat a good player. AI level is not relevant for the Random AI. It will change the strength of the Minimax AI. 10 is the maximum level and has no randomness in the calculation. The lower the value, the more randomness will be added to heuristic calculation. The reason I included a random AI, is that it is much more practical for testing, if you don't want to get completely destroyed while trying to test a specific card. Also, if you are going to edit the code of the game rules (in GameLogic.cs), this could affect the AI and if you want to focus on game rules before worrying about the AI issues, it is much easier to edit and adapt the Random AI since its script is like x10 shorter. The other advantage of the random AI is if you want to debug the GameLogic.cs script, since the AI will use the functions in that script hundreds of times when trying to predict moves, it can be really hard to debug that script. The random AI does not use the GameLogic.cs for predictions, and only use it for doing the actual actions. You can go back to the Mini Max AI once your gameplay works well and you are ready to tackle the AI. Last updated 2 years ago --- # Resources and Prefabs | TCG Engine ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/resources-and-prefabs#resources-folder) Resources Folder Under the Resources folder, you can find all the data for cards, abilities, decks and more... #### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/resources-and-prefabs#networkdata) NetworkData If you click on NetworkData, you can change the URL of the game server and web api. Also you should see the auth\_type set to Test (LocalSave in newer versions). Which means it is not using the API and users are saved locally on your PC. Leave this option to Test until you finished to install the Web API on your own server. To test with a game server or web API installed locally, you should change the URL to 127.0.0.1 ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FjWImkIEP5ZxYGWTAsVxH%252Fauth_type.png%3Falt%3Dmedia%26token%3D9a1c01e2-32d8-4900-9ebb-f5ccbd409098&width=300&dpr=4&quality=100&sign=793403cf&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/resources-and-prefabs#gameplaydata) GameplayData Gameplay data let you change various game values such as starting health, mana and deck size. At the bottom you can also set the Test decks. These are the deck used in test mode when running the Game Scene directly without going through the menu. For testing new cards, you should add a lot of that card into the test deck and you will be able to test it easily by just running the Game scene. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252F54N9gybBTXEGmcKpDW16%252Fgamedata.png%3Falt%3Dmedia%26token%3D52c18ef8-0f33-40db-94de-70f7a880f973&width=300&dpr=4&quality=100&sign=a7e3db98&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/resources-and-prefabs#carddata-and-abilitydata) CardData and AbilityData All cards and abilities data are held in scriptable objects. You can duplicate a card with Ctrl-D, and assign new art, stats and skills. Note on ID: the id is what is saved in the save file or database to know which cards a player own or which cards are in his deck. So once you choose an ID for a card, try to not change it, also try to avoid spaces or special characters in the ID. The title can be changed freely and can contain special characters (as long as your font support it). ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FOwpAcTxx0QmHHZs491pN%252Fbear.png%3Falt%3Dmedia%26token%3Dfaeb030e-5f25-4475-8b03-a56fe953d6a6&width=300&dpr=4&quality=100&sign=1f9dba0e&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/resources-and-prefabs#conditiondata-and-effectdata) ConditionData and EffectData Abilities use conditions and effects to determine how they work. An example of effect would be dealing damage, and an example of condition could be "Is an enemy character". You can code your own by creating a script that inherits from ConditionData or EffectData. And then create a data file inside the resources folder from those script. You can create a new data file by right clicking inside a folder: Create-TcgEngine. ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/resources-and-prefabs#prefabs) Prefabs Prefabs can be found in TcgEngine/Prefabs folder. **Managers** Contain game manager scripts, should be added to all your game scenes (but not the menus). **TheNetwork** Contain network managers scripts for the game client, game server, and the api client, should be added to all scenes including menu. This prefab has DontDestroyOnLoad, unlike most other managers or prefabs. **GameUI** Main UI script for the game scene. Contains almost everything that is static and stays on screen, and panels that appear/disappear. While editing the UI prefab, on the CanvasGroup components, you can set the alpha value to 1 or 0 to show or hide a specific panel. #### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/resources-and-prefabs#boardcard-handcard-and-cardui) BoardCard, HandCard and CardUI If you want to edit the shape or positioning of cards, these are the prefabs you will want to edit inside Prefabs/Gameplay. The same prefab is used for all cards since the art and text is replaced when a card appear in game. Last updated 1 year ago --- # Cards | TCG Engine All cards can be edited in the Resources/Cards folder, you can use Ctrl-D on a card file to duplicate it if you want to create a new one. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252Fl1arXw2hxVxRcYDlJH3r%252Fcard_data.png%3Falt%3Dmedia%26token%3D1bd91ed9-bb95-4683-81ea-8e0446720a27&width=300&dpr=4&quality=100&sign=de7d0be1&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/cards#id) ID the id is what is saved in the save file or database to know which cards a player own or which cards are in their deck. So once you choose an ID for a card, try to not change it, also try to avoid spaces or special characters in the ID. The title can be changed freely and can contain special characters (as long as your font support it). ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/cards#type) Type There are currently 5 card types in the engine: * Character: Is played on the board and can attack * Artifact/Location: Is played on the board but cannot attack * Spell: Is discarded and its effect is resolved immediately * Secret: Stays hidden and will trigger during the opponent's turn if the trigger condition is met. * Equipment: Must be played on a character already in play. Will be discarded when the character dies. Maximum of 1 equip per character. ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/cards#traits) Traits Traits do not have intrinsict effects, but can be referenced by abilities. For example the Alpha Wolf has an ability "All wolves gain +1 attack". This is done by adding the wolf trait to all wolf card, and by adding the condition is\_wolf on the ability target. ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/cards#abilities) Abilities References to the abilities this card has. See ability section for more details. ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/cards#deckbuilding-packs-and-cost) Deckbuilding, Packs and Cost Cost is the price in coins to buy the card from the menu. If the deckbuilding checkbox is off, that card won't be seen in the deckbuilder. This is usually off for cards that can only be summoned by abilities. You can also assign in which pack a specific card can appear, it's rarity will determine the frequency of the card appearing when opening that pack. Last updated 1 year ago --- # Testing in Solo | TCG Engine ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/testing-in-solo#testing-in-solo) Testing in Solo To run the game in solo, just open any scene in Unity (in project tab, TcgEngine/Scenes folder) and hit play at the top. Click Play again to stop the game. If you run from a Menu it will ask you to login in test mode (just enter any username you want). If you run from the Game scene, it will start playing with the test decks (set in Resources/GameplayData). Last updated 2 years ago --- # Cloud Server Installation | TCG Engine Follow these steps to create a cloud server and host the Unity game server. In this example, we are going to use Digital Ocean, but the server application can be hosted on any cloud provider of your choice. If you do not have an account already, you can use this referral link to create an account, and the first two months will be free. [https://m.do.co/c/ca46a35fd4dd](https://m.do.co/c/ca46a35fd4dd) ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/cloud-server-installation#prerequisites) Prerequisites You will need to download these two applications in order to access your server. One is a SFTP file manager and the other is a SSH command line tool. These tools are for Windows, but there are plenty of SFTP and SSH alternatives on Mac/Linux. WinSCP: [https://winscp.net/eng/index.php](https://winscp.net/eng/index.php) Putty: [https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) (Recently it seems like the putty website is often down, I managed to install it from the Windows Store instead). When installing Putty, make sure to also install PuttyGen (it is to generate ssh keys). ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/cloud-server-installation#create-a-droplet) Create a Droplet After you created a Digital Ocean account and entered your credit card information, and that your account is ready to use, you are ready to create a Droplet. 1) In Droplets section, click on Create -> Droplet 2) Select the OS: I use Ubuntu 22.04 3) Choose the specs of your server I use the $20 server personally, but you may be fine with a cheaper one for development, or may need a bigger one depending of your player count. I would go with at least 1GB+ ram, many users had issues with the 512mb ram droplet. 4) Choose any region (closest to you will have better performances). 5) Select a SSH key (see next section to generate a new one) 6) Select a hostname for your server (can be anything). 7) Click Create Droplet ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FDKomS9j97CeHHLj9yo2n%252FDroplet.png%3Falt%3Dmedia%26token%3Dacc5fbaf-fc63-4cf7-a481-922c1cbab824&width=300&dpr=4&quality=100&sign=32de6075&sv=2) Once your droplet is ready, the IP of your server will be displayed. You will need that IP later when creating the unity build. ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/cloud-server-installation#generate-ssh-key-with-puttygen) Generate SSH key with PuttyGen To generate a key, open PuttyGen and click on generate. Once done, save the private key file on your computer. Then copy the public key displayed on screen to Digital Ocean. On Digital Ocean, Add a name to your key and then click on Add SSH key. Make sure to store your private key file in a secure place, if you lose the key you won’t be able to access your droplet. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FPKhMO3rXyNvsATtP924m%252Fputty.png%3Falt%3Dmedia%26token%3Dcf0edb7d-2e85-4984-90ee-f176e22f7acc&width=300&dpr=4&quality=100&sign=12bb9302&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/cloud-server-installation#create-the-server-build-in-unity) Create the Server Build in Unity Before creating your server build, make sure the Resources/NetworkData settings are correct. Set your URL to the server IP (or domain of you have one). And set the port you want to use. When building the game server. You only need to include the **Server** scene. Since our Digital Ocean server is on Linux, select Linux as the platform on x86\_64, and check the box Server Build (In some Unity versions it is a different tab called "Dedicated Server"). ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/cloud-server-installation#connect-to-your-server-with-winscp) Connect to your server with WinSCP Open WinSCP and create a new connection. Enter the IP of your server as Host, and enter root as the username. The password is blank since we use a SSH key instead. Click on Advanced, then SSH/Authentification, then select your private key file there. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252Fp8x2DIiZipOdlp301DEY%252Fwinscp.png%3Falt%3Dmedia%26token%3D28ae0a32-d568-46cd-baed-725617519721&width=300&dpr=4&quality=100&sign=71e3a54a&sv=2) This will give you access to the server files, now you can upload your build into any folder, in my demo I created this folder: Copy /server/game **Important**: /root/server/game is not the same as /server/game, do not install inside /root/ because that is a reserved folder for the root user. And some people experienced issues installing inside /root/ ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FLZnfdZFmabiG4B15AoY2%252Fserver-folder.png%3Falt%3Dmedia%26token%3D86803d62-4986-44bf-a00d-ecb6de319164&width=300&dpr=4&quality=100&sign=34b0d3b0&sv=2) To access the **command line**, from WinSCP, click on Commands->Open in Putty. Once you gain access you can navigate to the server folder with Copy cd /server Now we need to give the server permission to execute our build, to do that, we can run Copy chmod -R 755 game ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/cloud-server-installation#test-the-game-server) Test the Game Server Run the game server to test it: Copy cd /server/game ./TcgEngineServer.x86_64 Now you should be able to connect to it from your client build (or from unity). Before you run the client, make sure that Resources/NetworkData url is set to your server ip, and also add back all the client scenes in your build settings. Launch the game, and from the menu, click on Multiplayer. If the screens shows "Connecting to server" it can't connect. If it shows "Searching for player" This means you are successfully connected! In putty, use Ctrl-C at any time to stop the server from running and return to command line. ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/cloud-server-installation#run-the-server-as-a-service) Run the server as a Service While running directly the game server is a good way to test (since you can see the live debug console). This method isn’t persistent and your app will stop as soon as you leave putty. To create a persistent server you need to create a service. In Unity, go to TcgEngine/Install folder, there should be a tcg.service file there. Upload that file to your server at this path: Copy /etc/systemd/system Open the file you just uploaded (double click in WinSCP) then make sure the path to your game server is set correctly. To start/restart/stop the service, you can use these commands from putty (“tcg” is the name of your service file). Copy systemctl start tcg systemctl restart tcg systemctl stop tcg You can also run this command to check if the service is running (and use ctrl-c when you want to quit top) Copy top Now that your service is running, you can try to connect to it from the client build or from Unity. In the same way you connected to it before. ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/cloud-server-installation#firewall-setup) Firewall setup It’s good to block the port you don’t use on your server, from the command line, you can run Copy ufw allow ssh ufw allow 8777 ufw enable And to check the status of your firewall: Copy ufw status Be sure to always run allow ssh before enabling the firewall, otherwise you will lose your putty connection and won’t be able to connect anymore. ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/cloud-server-installation#updates) Updates If you make changes to the data or gameplay logic, and need to rebuild your game server. To re-upload all you need to do is first: Copy systemctl stop tcg Then, reupload your game server in WinScp inside /server/game. You don't need to delete previous files if the build has the same name, they should be overwritten, this way you don't need to call chmod. If you deleted the files you may need to call chmod again. Copy systemctl start tcg Last updated 2 months ago --- # Remote Access and Authentication | TCG Engine To allow remote access, you will need to enable authentication on MongoDB. This will allow you to connect to your database remotely with Mongo Compass. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/remote-access-and-authentication#add-mongo-credentials) Add Mongo Credentials First step will be to create Mongo users, so that the database cannot be accessed without a password. In putty, open mongo command line with Copy mongo In some more recent mongo or ubuntu versions, the command is **mongosh** instead of mongo. While mongo is running in the command line prompt, you can run mongo commands. Use this one to change to the admin database to manage users Copy use admin Run these command to add mongo users. Make sure to set a different password for each, save them somewhere to use later, and note the database name (in this example its called tcgengine). It is best to use a complex random password ex: "ha28SjfhsZX4Mcn2asd", and save those somewhere secure. Don't use a password you frequently use online. Important: Mongo Users are not the same than your actual users in the database. You don't need a mongo user for each real user. Mongo users are just a list of apps credentials who can connect to mongo. I usually only create 3 users, not more. One root user, one for the NodeJS app, and one read-only user to use in mongo compass. Create a Root user Copy db.createUser({user:"root", pwd:"123456789", roles:[{role: "dbAdminAnyDatabase", db: "admin"}, {role: "readWriteAnyDatabase", db: "admin"}] }) Create a user for your app Copy db.createUser({user: "api", pwd: "123456789", roles: [{role: "readWrite", db: "tcgengine"}]}) And finally I also like to create a read-only user Copy db.createUser({user: "viewer", pwd: "123456789", roles: [{role: "read", db: "tcgengine"}]}) If you made a mistake you can delete a user with Copy db.dropUser("viewer") Use Ctrl-C at anytime to quit mongo and return to regular ubuntu command line. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/remote-access-and-authentication#enable-authentication) Enable Authentication On your server open the file: /etc/mongod.conf Change the Binding IP to Copy bindIp: 127.0.0.1,10.11.12.13 With the second IP after the coma being the IP of your server where the API and mongo are installed. This will allow remote access to your MongoDB. Add these lines in the mongod.conf file Copy security: authorization: "enabled" This will prevent connecting without a username/password. You will instead need to use one of the users you created during Mongo Installation. Important: Changing the binding IP will allow anyone to try to connect directly to your database from anywhere, as long as they have the password. It can be useful for development if you want to read your database from Mongo Compass, but it is also an increased security risk. If you allow remote connection you should also setup your server firewall properly so that it blocks requests that don't come from your IP for the MongoDB port. See the Firewall section below. Restart mongo to enable your conf changes Copy systemctl restart mongod Make sure you didn't break anything by changing the config Copy systemctl status mongod ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/remote-access-and-authentication#update-api-config.js) Update API config.js For NodeJS app access, In WinSCP, open the **config.js** file to edit a few things Change mongo\_user to "api" (or any other mongo user you created for your app) Change mongo\_pass to the password your set for your api user Change mongo\_db to the database name you granted access to your mongo users. Now also restart your NodeJS app to make sure it can still connect to Mongo. When testing something you can start the app normally with `node server.js` to see the errors in console instead of using forever. When everything is working, you can start the app with forever. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/remote-access-and-authentication#access-from-mongo-compass) Access from Mongo Compass You can also connect to your database from your PC, in Mongo Compass, using a string similar to this one Copy mongodb://[user]:[password]@[hosturl]:27017/[database]?authSource=admin For Example Copy mongodb://root:123456789@survival-engine.com:27017/tcgengine?authSource=admin The host URL can either be a domain or IP address. If you already setup your ufw firewall previously, you may not be able to connect to it from Compass since port 27017 is not open (see below). You should be able to connect to mongo from the NodeJS app even if the port is blocked on the firewall, since they are on the same server. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/remote-access-and-authentication#firewall-setup) Firewall setup It’s good to block the port you don’t use on your server, from the command line, you can run Copy ufw allow ssh ufw allow http ufw allow https ufw enable http will open port 80, and https will open port 443, and ssh will open port 22 And to check the status of your firewall: Copy ufw status Be sure to always run `allow ssh` before enabling the firewall, otherwise you will lose your putty connection and won’t be able to connect anymore. If you also want to open a direct access to MongoDB (to use in Mongo Compass), you can enable port 27017 but only for your IP address. Copy ufw allow from 1.2.3.4 to any port 27017 Important to replace 1.2.3.4 by your own [external IP address](https://api.ipify.org/) . 27017 is the default port for Mongo so no need to change it. It will open port 27017 but only for requests coming from your IP address. This can be really useful to read the Database on your PC for development, you can turn off the access when going live. The firewall will not block local access, so your API should be able to access your database if installed on the same server. If for some reason your MongoDB isn't on the same server as your nodejs API, you will also need to allow the api server IP on your ufw firewall. Last updated 11 months ago --- # Conditions and Effects | TCG Engine If you want to create new effects or conditions for your card abilities, you can create a new script that inherits from ConditionData or EffectData, and override one of the functions. ### [](https://indiemarc.gitbook.io/tcg-engine/scripts/conditions-and-effects#effects) Effects For example, let's create a new ability effect to return all your cards into your deck, shuffle it, and then redraw the same number of cards. Create a new script called EffectRedrawHand.cs with: Copy using UnityEngine; using TcgEngine; using TcgEngine.Gameplay; [CreateAssetMenu(fileName = "effect", menuName = "TcgEngine/Effect/RedrawHand", order = 10)] public class EffectRedrawHand : EffectData { public override void DoEffect(GameLogic logic, AbilityData ability, Card caster, Player target) { int nb_cards = target.cards_hand.Count; //Store number of cards in hand target.cards_deck.AddRange(target.cards_hand); //Add hand cards to your deck target.cards_hand.Clear(); //Empty hand array logic.ShuffleDeck(target.cards_deck); //Shuffle Deck logic.DrawCard(target.player_id, nb_cards ); //Redraw Hand } } Notice in the definition of the function, the target is a Player, this means we will need to select a player target (like PlayerSelf or PlayerOpponent) when creating the ability. ### [](https://indiemarc.gitbook.io/tcg-engine/scripts/conditions-and-effects#conditions) Conditions Now lets say we want the player to only use this ability if they have at least 3 cards in hand. We can create a condition for it. Create a new script called ConditionHandCount.cs Copy using UnityEngine; using TcgEngine; [CreateAssetMenu(fileName = "condition", menuName = "TcgEngine/Condition/CountHand", order = 10)] public class ConditionCountHand : ConditionData { public int value; public override bool IsTriggerConditionMet(Game data, AbilityData ability, Card caster) { Player player = data.GetPlayer(caster.player_id); int nb_cards = player.cards_hand.Count; return nb_cards >= value; } } ### [](https://indiemarc.gitbook.io/tcg-engine/scripts/conditions-and-effects#data-files) Data Files We will now create the data files for the effect we just created. And then Link it to the ability. In Unity, right click inside a folder, and select Create -> TcgEngine -> Effects, select your new effect, it should be named what you set in the tag \[CreateAssetMenu\] in your new script. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252Fp2rwVm8XbaX0tFylyZ1V%252FCreateEffect.png%3Falt%3Dmedia%26token%3Db8fd7fd9-ed1e-43ae-9111-1994f0681b88&width=300&dpr=4&quality=100&sign=fffd46da&sv=2) Do the same thing with your new condition, and set the value to 3. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FVPgF0uI29GODHa5xWCjC%252Fhand_card.png%3Falt%3Dmedia%26token%3D5e0da52b-3fa7-451d-b359-e20b7cd7268e&width=300&dpr=4&quality=100&sign=858a6bb5&sv=2) Now in Resources/Abilities, create a new ability, you can dupplicate an existing one to make it faster with Ctrl-D Set these settings on the ability ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252F2bleUwzmnpdeFjiPnHpa%252Fnew_ability.png%3Falt%3Dmedia%26token%3Deb468b1e-93a4-479f-91a3-7c67d9afa4c1&width=300&dpr=4&quality=100&sign=c50562bd&sv=2) You can now add that ability to any card, this will give the card a new Activated ability that cost 2 mana, that can only be used when you have 3 or more cards in hand, and that will shuffle back your hand into the deck and redraw the same number of cards. ### [](https://indiemarc.gitbook.io/tcg-engine/scripts/conditions-and-effects#trigger-condition-vs-target-condition) Trigger Condition vs Target Condition A trigger condition will be checked to know if the ability should trigger or not, while a target condition will be checked to see if a target is valid. If trigger conditions are true, the ability will be resolved (mana/action will be spent, fx will appear). The target condition is checked for each individual target after the ability was already triggered. For example if you have an ability that you can cast when you have 5 HP or less and that affects ALL blue cards on the board, 5 HP would be a trigger condition, while "is blue" would be a target condition. When creating a new script, use IsTriggerConditionMet for trigger conditions and use IsTargetConditionMet for target conditions. And place the condition in the appropriate array on the ability. Target conditions can be defined with 3 different types of targets: Card, Player or Slot. Last updated 1 year ago --- # Save File | TCG Engine If you're in LocalSave mode, each user data will be saved locally on your PC. You can find the save file inside Unity's persistantDataPath folder. Each OS has a different path, so check here to know where: [https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html](https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html) Inside the folder, you will find a save file for each user you created. You can delete one to reset the user. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FfmbjXcr6lNyIxIYM7f6g%252Fimage.png%3Falt%3Dmedia%26token%3Db3b3d952-145a-4afa-aecf-a33e19cfa413&width=300&dpr=4&quality=100&sign=a6498509&sv=2) Last updated 1 year ago --- # Status | TCG Engine Status are ongoing effects or skills afflicted to a card or player. If you want an ability that grants a new permanent bonus or bonus that last for a few turns, it needs to be a status. Exampled of status in the demo are: Taunt, Stealth, Silenced, Paralyzed... Abilities can give status with a duration to a card. A duration of 0 means that it is permanent. Otherwise it represent the number of half-turns (each player count as a half-turn, so if you want something that last for 3 complete turns it should be set to 6). Some status also have a "value" such as Armor which reduce damage by that value. Since the effect of status are more varied and don't have specific timing like abilities, they are coded directly in the GameLogic.cs for each status (each one shouldn't take more than 2-3 lines of code). If you want to add new status you will need to edit the core rules in that script. Last updated 2 years ago --- # Game Rules | TCG Engine In the demo, the game rules are quite similar to other online card games such as Hearthstone or Magic the Gathering. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FUhzgMYbBjPBP6QBXj7Nx%252Fbear-info2.png%3Falt%3Dmedia%26token%3D966bd55f-fd99-46e0-92e5-1152158115ce&width=300&dpr=4&quality=100&sign=50c0008f&sv=2) **Mana Cost:** how much it cost to play the card from your hand. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FryrhTBEMnsVQAtanCdDK%252Fmana.png%3Falt%3Dmedia%26token%3D1a232fa2-57c4-449e-9b56-4c153ca6bbb0&width=300&dpr=4&quality=100&sign=3be22666&sv=2) **Rarity:** Rarer cards appear less often when opening packs. In the demo you have: Green = Common, Blue = Uncommon, Yellow = Rare, Red = Mythic **Attack:** When attacking, HP of the other card will be reduced by the attack of your card. **HP:** When it reaches 0 the card is destroyed **Card Ability:** Each card can have unique abilities explained when hovering the card. ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/game-rules#card-types) Card Types **Characters:** Cards placed on the board, with Attack and HP, that are able to attack other cards or the other player. **Artifacts:** Also placed on the board, but cannot attack and has no attack value. Instead it usually has a passive ability. **Spells:** One time effect resolved immediately when played, then it goes directly in your discard. **Secrets:** When played, the card will stay hidden to the other player. It will be triggered (and effect resolved) during your opponent's turn when the trigger condition is met, described on each card. **Equipment**: Must be played on a character already in play. Will be discarded when the character dies. Maximum of 1 equip per character. ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/game-rules#win-condition) Win Condition ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FcesI8ijznyjtl99e1NMl%252Fhp.png%3Falt%3Dmedia%26token%3D3765f56e-9499-4564-bc7b-1e2eae36667e&width=300&dpr=4&quality=100&sign=d9b4af1&sv=2) Win when your opponent's HP is reduced to 0. You can reduce their HP by attacking the player directly with your creatures on the board. (Drag the attacker into the opponent's hand of cards). ### [](https://indiemarc.gitbook.io/tcg-engine/getting-started/game-rules#changing-game-rules) Changing Game Rules If your game needs a different set of rules. You will need to edit the scripts. The most important script for game rules is GameLogic.cs, as well as all game-data scripts in the Scripts/GameLogic folder. Such as Game.cs Player.cs Card.cs and Slot.cs More info on this in the Scripts section. Last updated 1 year ago --- # Scripts Overview | TCG Engine ### [](https://indiemarc.gitbook.io/tcg-engine/scripts/scripts-overview#important-scripts) Important Scripts If you're planning on editing the code. A good place to start with is everything inside the Scripts/GameLogic folder. **GameLogic.cs** Is probably one of the most important script. Defines all the core gameplay logic and game rules. It is used by both the server (to resolve actions received) and by the AI (to make predictions). Game Actions are sent by the GameClient.cs, and received by the GameServer.cs to then be executed by GameLogic, GameServer connects to callbacks inside GameLogic.cs, to know when it should send a refresh to all clients. I would strongly suggest to edit directly this script to create your own rules, and not try to change the game rules by creating a separate script. This will keep your project simpler in the long term, and you probably won't need to update this script to future version of the engine so much since it doesn't contain anything related to systems like networking message, ui, visuals or other. It is purely game rule logic. If you edit the code, do not access this script directly from a client-side script, and do not try to change the visuals or run audio fx from there, since this script is run by the server and AI and not the client. Namespaces serve as a reminder (client side scripts are in a different namespace than server ones). #### [](https://indiemarc.gitbook.io/tcg-engine/scripts/scripts-overview#game.cs-player.cs-card.cs-slot.cs) Game.cs Player.cs Card.cs Slot.cs Contains data for the current state of the game, Game.cs is the data sent to clients during a network refresh (and it contains players and cards). If you need to add new stats to your cards, you will need to edit Card.cs (as well as edit CardData.cs). Unlike CardData.cs which represent the card original fixed stats, Card.cs represent the current state of a card (with edited values, status effects, owner, and position on the board). So a stat that never changes during the game (such as the card rarity) do not need to be added to Card.cs and can only be added to CardData.cs. But a stat that can be affected by abilities (attack) need to be in both scripts. #### [](https://indiemarc.gitbook.io/tcg-engine/scripts/scripts-overview#boardcard.cs-handcard.cs-boardslot.cs) BoardCard.cs, HandCard.cs, BoardSlot.cs All scripts in GameClient folder are usually just the visual representation of the data. So for example, BoardCard.cs will take the values contained in Card.cs and display it with sprites and ui text. These scripts are never relevant to the AI, GameLogic or Server, since their only role is to display the data received from the server. #### [](https://indiemarc.gitbook.io/tcg-engine/scripts/scripts-overview#gameui.cs-and-playerui.cs) GameUI.cs and PlayerUI.cs Main scripts for the in-game UI. GameUI is only there once while PlayerUI has one for each player. #### [](https://indiemarc.gitbook.io/tcg-engine/scripts/scripts-overview#gameclient.cs) GameClient.cs Main script for the client side of the game, this script is only in the game scene. It will connect to the server and send the various actions executed by the player, it will also receives refresh from the server, update the state, and let the other client-side scripts update what is shown on the board. **ServerManager.cs and GameServer.cs** Main scripts for the server, ServerManager is the top-level script that will receive connections, client messages and redirect them to the appropriate game, if a server run multiple games at the same time, it will contain a list of GameServer, each with a different UID, and each network message received will be sent to the correct game server instance. There is also a script ServerManagerLocal.cs which simulates the server in local when playing in solo, this one only contain 1 GameServer instead of a list. Last updated 2 years ago --- # Abilities | TCG Engine Abilities can be found in the Resources/Abilities folder. They can be assigned to cards to give them special power. The engine is also made in a way to make it easy to code your own abilities. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FdEsZ0BOKkUlgNkACIWEA%252Fability_Data.png%3Falt%3Dmedia%26token%3D2c77a5ac-f998-4257-ad9f-615a9a316a16&width=300&dpr=4&quality=100&sign=a6781188&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/abilities#trigger) Trigger Determines WHEN the ability will be resolved. **Ongoing:** Always active as long as this card is in play. (Ongoing only works with a limited number of effects such as status and stat bonus). Ongoing abilities bonus are recalculated any time there is a state change. **Activate**: For Activated abilities, the player will need to manually click-hold on the card and select the ability. Some activated abilities can cost mana or can cost the character's turn action. **On Play**: Resolved when the card is played from your hand. **On Play Other**: Resolved when this card is already in play and another card is played. Usually this type of trigger will have some trigger conditions. **Start/End of Turn:** Resolved once every turn, during your turn. **On Before/After Attack:** Resolved when attacking with the card. OnAfterAttack will resolve only if the card survived the attack. **On Before/After Defend:** Resolved when being attacked. OnAfterDefend will resolve only if the card survived the attack. **On Kill:** When killing another card during an attack. **On Death:** When this card dies. **On Death Other:** When this card is in play and another card dies. #### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/abilities#trigger-condition) Trigger Condition Ability won't trigger unless all the trigger conditions are met. For example, you could have an "OnPlay" ability that only triggers if the player has less than 10 health, or a Start of Turn ability that triggers only if you have 5 cards on the board.. There are many conditions already available in the Resources/Condition folder, but you can also code your own. (See the scripts section). ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/abilities#target) Target Determines WHO is affected by the ability? There are 3 different categories of possible target: * Cards * Players * Board Slots And different targets you can choose form: * **Self:** The card with this ability * **Player Self:** The owner of the card with this ability * **All Cards Board:** All cards currently in play, excluding secrets. * **All Cards Hand:** All cards in both player's hand. * **All Cards All Piles:** All existing cards, on board, hand, deck, discard or secret area. You will usually want to use some target conditions to filter only the deck or discard or other. * **All Slots:** All slots on the board, whether they are empty or occupied. Usually used for summon abilities. * **All Card Data:** All existing card data in the game (scriptable objects), this is usually used to instantiate new cards (like discover effect), since it doesn't represent an existing card in the game, but only the data of the card. * **Play Target:** When playing a spell, you will be asked to drag the spell directly on top of a target when playing it. Use only for spells. * **Ability Triggerer:** The card that caused the ability to be triggered. This is usually the same than the caster (self) but for some Triggers it is not. OnPlayOther, OnDeathOther, OnAttack, OnDefend, and OnKill have a different triggerer than the caster. * **Select Target:** Player will be asked to click on a target of his choice on the board. Can be a card, player or slot. Choice can be restricted with a target condition. * **Card Selector:** A menu will open to let the player select a card as target. This is useful for abilities that let you retrieve a card from your discard or deck. Choice of cards can be refined with target condition. * **Choice Selector:** A menu will open to let the player choose between a few different abilities. If you use this, place the choice abilities under chain\_abilities array. #### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/abilities#target-conditions) Target Conditions This is really useful to target multiple cards (but not all) or to limit the choices of the player. For example, if you want an ability that says "All wolves gain +1 attack", the Target would be "All Board Cards", and the target condition "Is Wolf". Another example would be a skill that let you take a blue spell from your discard. The Target would be "Card Selector", and the target conditions would be "Is Blue" and "Is Spell" (You also need to add "Is Ally" and "Is In Discard" with the card selector, otherwise it will show cards in your deck and your opponent deck/discard). #### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/abilities#target-filters) Target Filters Target filters are a bit more complex and slightly less performant than conditions, since they involve manipulating arrays instead of just a bool check. But they are a lot more flexible when you want to target multiple targets with a more global condition instead of a condition that is only checked on each individual target. For example targets filters could be used to target X number of random targets on the board, or to target the card with the highest attack, cards that have duplicates, etc.. This is done by targeting AllBoardCards and then adding a filter that will use all board cards as source and only add the new targets into the destination array. Filters also work with AllPlayers and AllSlots. More info on this will be added to the Scripts section. ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/abilities#effect) Effect Determines WHAT will happen to the targets when the ability is resolved. Several effects are already available in the Resources/Effects folder. If an effect has a parameter and you want to use it with different values, you can simply duplicate one effect with Ctrl-D. Effects can also be coded easily like conditions, by creating your own scripts. See the scripts section to know how to code your own effects. A value and duration can be passed to each effect. ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/abilities#chain-abilities) Chain Abilities Some more complex abilities could have multiple effects, each with different targets and conditions, but that are all triggered by the same thing. To simplify the creation of these more complex abilities, you can instead create multiple abilities, and only the first one will have a trigger. Set the trigger to None on the other ones. And only attach the first ability on your card. Then, on that first ability, add the other abilities into the chain\_abilities array. This means those abilities will be triggered immediately after the first one, whenever it is triggered. This array is also used when using the Choice Selector. ### [](https://indiemarc.gitbook.io/tcg-engine/files-and-data/abilities#activated-abilities) Activated Abilities Activated abilities can have a mana or exhaust cost required to activate the ability. Exhaust means the card won't be able to attack in the same turn, or use the ability on the first turn it is played. An activated ability without an exhaust cost can be triggered multiple times per turn. Last updated 2 years ago --- # Netcode Plus | NetcodePlus NetcodePlus is an extension of Unity’s Netcode for GameObjects. For documentation on the original Netcode, you can check here: [https://docs-multiplayer.unity3d.com/netcode/current/about/index.html](https://docs-multiplayer.unity3d.com/netcode/current/about/index.html) Instead of using **NetworkObject** and **NetworkBehaviour** components, this assets uses **SNetworkObject** and **SNetworkBehaviour**. It is still possible to use the original NetworkObject component in your project, but it should not be on the same objects that uses the new ones. **What has changed in NetcodePlus?** \-Components (SNetworkObject, SNetworkBehaviour) \-Spawn System \-Network Action System (SNetworkActions replacing RPC calls) \-Network Variables (SNetworkVariable) **What has NOT changed?** \-Transport Layer (Unity Transport) \-Scene Management \-Messaging & Serialization **What is new?** Built-in way to create a Dedicated Game Server Built-in way to create a Dedicated Lobby Server Improved Connection Process that allow easily transferring data before the game starts. Easy Integration with other systems (Relay, Authentication...) Some cool demos and examples **Why the new components?** \-The Original Netcode would try to send all network variables of all spawned object to a newly connected client, which would often be over the message size limit for a big scene. In NetcodePlus you can control when and which variable are sent when a new client connects, Spawn requests will be batched into small groups instead of sent all at the same time. \-Scene objects are not spawned until the full new connection process is completed, allowing players to transfer data between them before the objects and player start spawning. This is extremely useful to share save files or other initialization data before all scene objects start syncing. \-By adding the SNetworkOptimizer component to a prefab, the game will automatically sync (spawn) objects that are near the players, and stop syncing (despawn) the ones that are far (you can set the distance). Which greatly improve performances. \-NetcodePlus includes a new feature: Network Actions. A way to remotely call functions that is written in pure C# (no \[tags\] and no code generated at compilation, like it is the case with RPC calls). It streamlines function calls and syncing variables, since both can be done the same way. \-A Network Action can also be triggered to run on both the server and client in one call, and will work even if the object isn't spawned, which can help having scripting consistency between playing peer-to-peer, on a dedicated server or offline (a ClientRpc would run locally on a p2p host but not on dedicated server, and not run at all if the object isn't spawned. So Rcp require more effort to handle each different kind of server in the code). This avoids having a lot of `if(isSpawned) DoSomethingRpc() else DoSomething()` in your code. \-Another advantage of Network Actions is that actions initiated from a client that should be executed by another client will first be sent to the server and be automatically forwarded to the correct recipients by the server, without the need to add specific code for this. You should use Network Actions instead of RPC calls with SNetworkObject, the same things can be achieved, just in a different way and with more options. Note that you can still use RPC calls on objects with the original netcode NetworkObject component. Do not put both components on the same object, it will not work. Although you can have both on different objects in the same scene. Keep in mind that regular NetworkObject will be spawned before the new connection process finishes.. Last updated 1 year ago --- # TCG Engine Roguelike TCG Engine Roguelike Edition is a template to create Roguelike Deckbuilding games in Unity. Based on the original TCG Engine, it has been reworked to support Players VS AI adventure, with map progress, events, and deckbuilding throughout your adventure. It supports both solo play and co-op multiplayer, using peer to peer or a dedicated server. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/#structure) Structure Both the Game Client and Game Server are part of the same Unity project. The Game Server also includes Lobby system to create rooms and let other players join. If you want to play solo or join others with p2p with direct IP, you do not need the game server. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/#coding-and-development) Coding and Development This is **not** a no-coding asset. And while cards and abilities can be edited directly from the data files (scriptable objects), you will need to edit the code to add features or change the core game rules. I made the decision to not include any custom editor GUI to keep the code as simple as possible and useable for a varied level of programming skills. A custom GUI editor would make the code a LOT more complex, and while they are nice at first for people with no experience, they can quickly become extremely limitative, or force you to do more programming for every task since you would need to consider the editor as well... My goal is to encourage people to go and edit the code directly. I put a high priority on keeping the code clean and well structured. We have a Discord community for people to help each other if you are just starting with coding. And I will be glad to listen to any feedback to improve the code in future versions if needed. Check the Scripts section for more info on the most important scripts, and how to inherit the base conditions and effects class to make your own. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/#tutorials) Tutorials Tutorial videos are available on Youtube. [https://www.youtube.com/@indiemarc/videos](https://www.youtube.com/@indiemarc/videos) Last updated 1 year ago --- # Getting Started | Dialogue Quests The best way to get started with the Dialogue System is to look at the demo scenes. The following document helps to explain more in detail how to create dialogues and quests. There are 3 things you will need to start creating dialogues: * The DQ Manager * The Actor component on your characters. * A Narrative Event with Dialogue Messages. ### [](https://indiemarc.gitbook.io/dialogue-quests/#dq-manager) DQ Manager Must be included once in your scene when you want to use the dialogue and quests system. It can be found in the prefabs folder. This manager runs the events and dialogues, loads the UI (DQUICanvas), and handles all user controls. Inside the DQ Manager prefab, you can change some of the default settings like the path where the data is loaded, and the default controls. Add the DQ Manager to your scene if it is not already there. ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FYmJ6jjX9kQCaDaWjkDbp%252FDQManager.png%3Falt%3Dmedia%26token%3D240ec108-8055-452e-8c7c-7e170f48a1c3&width=768&dpr=4&quality=100&sign=a0ad8e36&sv=2) ### [](https://indiemarc.gitbook.io/dialogue-quests/#actor-component) Actor Component You will need to add the Actor component on the characters who can talk in dialogues. This includes your player character as well as at least 1 NPC. You can add the component directly on the prefab. Then, on the new component you will need to link the ActorData related to this character. You can dupplicate one of the data in Resources/Actors with Ctrl-D, rename it, change the ID, and then link it to your character prefab. ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FppEjFgfdPrw7HdFTGWV9%252FPlayerComponent.png%3Falt%3Dmedia%26token%3Df0b0e4ec-765f-4acf-b30d-484dc18d7823&width=768&dpr=4&quality=100&sign=c6fb7329&sv=2) On the Actor Data in Resources folder, make sure that your player data is set to is\_player, while the NPC actor have this toggle off. ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252Fg9heJ72SSr0tmYYpOyoS%252FActorData.png%3Falt%3Dmedia%26token%3D473401c6-4dce-4883-8301-f1f771551095&width=768&dpr=4&quality=100&sign=62054aa&sv=2) ### [](https://indiemarc.gitbook.io/dialogue-quests/#create-your-first-dialogue) Create your first Dialogue In your scene, in the Hierarchy, you can right click and Create Empty to create a new GameObject. Then, while that object is selected, in the inspector, you can add a component NarrativeEvent Create a few child object under that event for the dialogues messages and add the DialogueMsg component to them. On the Event, set the trigger\_type to NearActor, and the trigger\_actor to your NPC, and on the dialogue, set the actor to either the NPC or your player. Add some text for the dialogue. ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252F1LCabLQB9UbfrUjB2tmo%252FNarrativeEvent.png%3Falt%3Dmedia%26token%3D477325ba-61f8-4c92-b188-4d0abfdb2330&width=768&dpr=4&quality=100&sign=d7e31747&sv=2) ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FTk8GRNnU8kARZOPIF5b4%252FNarrativeEventMsg.png%3Falt%3Dmedia%26token%3Dfcb1f939-a54b-46fe-b69e-fd8f8a4ef260&width=768&dpr=4&quality=100&sign=8e157ce1&sv=2) Note that the Event trigger\_limit is set to 1, which means the dialogue can only happen once, if you want it to repeat indefinitely, you can set that value to 0. You can now test your first dialogue! Just move your character near the NPC in your scene, and it should automatically start. Last updated 1 year ago --- # User Login API User API is a custom web api and database for user authentication, and storing user data. It contains NodeJS server side code, MongoDB database, and Unity demo to show how to access it. One of the advantage of this type of API is that it can be accessed from multiple platforms that will all share the same users and data. For example you could have a Website, a Unity Game, and a Game Server that all access it to manage or read user data. #### [](https://indiemarc.gitbook.io/user-api/#asset-demo-server-structure) Asset Demo Server Structure ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FEy78BbcMX8MXIfordfj8%252FServerSetup-UserAPI.png%3Falt%3Dmedia%26token%3D018d2fc6-3fcd-4f5d-abc4-441bff1aedb7&width=300&dpr=4&quality=100&sign=ed3f8d81&sv=2) #### [](https://indiemarc.gitbook.io/user-api/#example-of-extended-server-structure) Example of Extended Server Structure ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252F7Kf6VWUbGTwxCan8DBps%252FServerSetup-UserAPI2.png%3Falt%3Dmedia%26token%3Dc988ff46-04d6-4495-85c3-58fb702bd189&width=300&dpr=4&quality=100&sign=278b58c1&sv=2) This asset is compatible with NetcodePlus, which could be used for your game server. For example you could add some custom code on your server to give rewards or validate the users connecting. If you have any website (not included in this asset) you would be able to access the API data from it with some simple http requests. Last updated 2 years ago --- # Test with Insomnia | TCG Engine Insomnia is a really useful tool to test direct http request before coding them in your client (Unity). So you can test your API server directly before coding the client-side code. Http requests are usually called automatically by the Unity Client and Unity Server, but if you want to understand a bit more how they work in the background, you can try to run these in insomnia: Download the Free version of Insomnia [https://insomnia.rest/](https://insomnia.rest/) Start Insomnia, You can either create a new collection: Create -> Request, or import mine Create -> Import from file (you can find the file in TcgEngine/Install folder). Then click on your new collection to open the list of requests. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FNLb5cdUg12zPz5I50JfB%252FInsomnia-register.png%3Falt%3Dmedia%26token%3D0769693b-2aaa-4005-b3f5-096f119ab87c&width=300&dpr=4&quality=100&sign=da709e1a&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/test-with-insomnia#register-a-user) Register a user From here you can create request to test your API. Let's try to create a new admin user. You can edit an existing request or create a new one. Copy POST http://127.0.0.1/users/register Change the Body to JSON and put this as body: Copy { "username": "admin", "email": "admin@test.com", "password": "admin" } Since we are testing locally, the password/email doesn't matter for now. We just use something easy to remember. Make sure NodeJS is running in your command line window, and click on SEND If it works, hopefully you should see something like this. Copy { "success": true, "id": "64079a109630dced89a3f612" } ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/test-with-insomnia#login) Login Copy POST http://127.0.0.1/auth Change the Body to JSON and put this as body: Copy { "username": "admin", "password": "admin" } When login is sucessful, it will give you an access\_token, you will need it to execute any requests that require authentication. Copy the access token you got (without the ") ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/test-with-insomnia#read-the-list-of-all-users) Read the list of all users Let's create a new request to read the list of all users Copy GET http://127.0.0.1/users Leave the body empty, instead click on Headers and add one, as header name, write: Copy authorization And as value paste the access token you got when login in. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FE9n11cp4PNaB62w3Ksea%252Fheaders.png%3Falt%3Dmedia%26token%3D5565fe83-6578-42c1-ad3d-a030380b9e57&width=300&dpr=4&quality=100&sign=30c9af61&sv=2) Now click on send, it should show the full list of existing users.\\ ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/test-with-insomnia#read-the-list-of-all-cards) Read the list of all cards This request will let you see all the cards uploaded to the API. This request could be useful if you would like to create a website that display all your cards. The image could simply be the id of the card + .png uploaded to a specific folder of your website. Copy GET http://127.0.0.1/cards ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/test-with-insomnia#check-who-is-online) Check who is online This request will let you see the list of all users who interacted with the API in the last 10 minutes. Copy GET http://127.0.0.1/online ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/test-with-insomnia#granting-permissions) Granting Permissions If you also have a game server, you could create a "server" user with permission level 5. This will allow the user to give rewards and read other users, but won't let it assign permissions or delete users (only an admin can). To set permission\_level of a user through requests, if you already have at least 1 admin user, you can login with the admin user and use Copy POST http://127.0.0.1/users/permission/edit/6407a114953 Replace the ID at the end of the URL by the ID of the user you want to target. Use the authorization token of your admin user. And set the body to: Copy { "permission_level" : 5 } There are only 4 relevant permission levels in this API. 1 for regular users, 5 for the game server, 10 for admins, and 0 for deactivated users. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/test-with-insomnia#other-request) Other Request? Great, now you know how to use Insomnia, you can do the same for all other requests. To know which requests are possible, check the .routes.js files inside the NodeJS code. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/test-with-insomnia#testing-request-on-the-cloud-server) Testing request on the cloud server To test online request, once you installed your cloud server, you can replace 127.0.0.1 by the IP of your server, or your domain name. If you enabled https, you can also replace http by https in the URL. Other than that everything should work the same. Last updated 1 year ago --- # Filters | TCG Engine Filters works in a similar way as conditions, and also help determine the targets of an ability. A filter always has a source array and a destination array (containing either Cards, Players or Slots), and the function should add the valid targets to the destination array and return it. The advantage of filters is that they are a bit more flexible than conditions, but are also less performant and more complex (because of array manipulation). Filters also cannot be used for the trigger or for some targets that let the player make a selection. Filters are best used with the All Cards, All Players or All Slots targets. In this example, the filter is used to find the card that has the highest attack. The ability target is set to All Cards Boards, which means the source array contains all the cards on the board. And destination array will contain only the cards with the highest attack. Copy using System.Collections; using System.Collections.Generic; using UnityEngine; using TcgEngine; [CreateAssetMenu(fileName = "filter", menuName = "TcgEngine/Filter/HighestAttack", order = 10)] public class FilterHighestAttack : FilterData { public override List FilterTargets(Game data, AbilityData ability, Card caster, List source, List dest) { //Find highest attack value int highest= 0; foreach (Card card in source) { int attack= card.GetAttack(); if (attack > highest) highest= attack; } //Add all highest (more than one card can be targeted) foreach (Card card in source) { int attack = card.GetAttack(); if (attack == highest) dest.Add(card); } return dest; //Return all cards with highest attack } } Similar to conditions and effects, you need to create a scriptable object from the Create->TcgEngine menu. Filters can be added on the ability data inside the filters\_target array. Last updated 2 years ago --- # Web API | TCG Engine The web API enables User Login and storing user data online. It is optional and turned off by default. Once you are familiar with the TCG Engine, you can start installing it to turn on some additional features: * User Authentication (with password) * Database to save all user data online (card collection, decks, packs, coins...) * Leaderboard and ELO Ranking * Friend list The API is made with NodeJS and uses a Mongo Database. Other apps can access the API by sending HTTP requests. For example a request to Register a user, Login, Edit your deck, or give rewards. Some of the requests require elevated privileges, for example the Give Reward request cannot be performed by a regular user. Your unity game server can have its own credentials to access the api. The advantage of this type of API, as opposed to have the whole server managed by Unity. Is that it allows different app to access the api. For example if you later decide to have a website and want to show user accounts or cards there, your website could simply connect to the API and access all the data. Also this allows you to have separate servers for the API where everything is saved, and for your game server. The Game server can require much more processing power than a NodeJS app. So for this reason if you get a lot of users, you may need to have multiple game server, without fragmenting your data since they can all access the same API. So in short, Unity is better for real-time server and executing game logic, where a lot of data and code is shared with the client. But NodeJS is much better and more performant for creating an independent http API with database that isn't so much related to the gameplay. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252FOrMOvCaDNRvY95GIBU4U%252FServerSetup-TCG.png%3Falt%3Dmedia%26token%3Ddb302084-7171-4dff-814d-08c4950c4aa9&width=300&dpr=4&quality=100&sign=f3a2a56f&sv=2) Last updated 2 years ago --- # Local Installation | TCG Engine You can install Mongo and NodeJS locally to test the server without hosting it on the cloud. This can help for development. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/local-installation#install-nodejs-and-mongo-on-windows) Install NodeJS and Mongo on Windows Install the LTS version of NodeJS [https://nodejs.org/en/](https://nodejs.org/en/) Download and Install MongoDB community [https://www.mongodb.com/try/download/community](https://www.mongodb.com/try/download/community) And Mongo Compass to access the database with an interface (It may have installed already when installing MongoDB). [https://www.mongodb.com/products/compass](https://www.mongodb.com/products/compass) You can open windows services to see if Mongo is running (Start -> search for "services"), then search for Mongo in the list of services. You can also use this Services window to restart mongo if needed. Inside TcgEngine/Install, there is a folder containing all the server code. Unzip it in a new project folder outside of your Unity Project (to prevent Unity from generating a meta file for each file). Once the files are unzipped, open windows command line (click on Start-> type CMD) Navigate to your NodejS code folder, where you extracted the files, that folder should contain the server.js file and package.json file. Copy cd C:\Marc\Unity\TcgEngineAPI Install the NodeJS modules Copy npm install Then try to run node Copy node server.js Click ctrl-C at anytime to exit You should now be able to access the API either from Unity or from Insomnia. To access from Unity, make sure that Resources/ApiData has the api path set to 127.0.0.1, https is turned off, and auth\_type is set to API. Then, run the LoginMenu scene and try registering a new user. If you want to edit the API code, I would suggest to use an IDE such as [Visual Studio Code](https://code.visualstudio.com/) . ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/local-installation#use-mongo-compass-to-check-the-database) Use Mongo Compass to check the database Open Mongo compass, click on new connection, and enter this string Copy mongodb://127.0.0.1:27017/tcgengine ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252Ft2NKPhHLA18iFsbHPS7a%252Fmongo-compass2.png%3Falt%3Dmedia%26token%3D79e393b6-abca-4716-8ce6-ec0566b021da&width=300&dpr=4&quality=100&sign=37d7b602&sv=2) If it connects correctly, you can click on tcgengine to see your current data. If tcgengine doesn't appear on the left, it may be because there is no data yet. To add data you can register a new user, either through the Unity demo, or with Insomnia. ![](https://indiemarc.gitbook.io/tcg-engine/~gitbook/image?url=https%3A%2F%2F2533758046-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FjsBgAenEXusKcO8RelBI%252Fuploads%252F5YTlTLuDDnXmqNkmers1%252Fmongo-compass.png%3Falt%3Dmedia%26token%3D0fbfb350-25bf-438c-a04c-0f4fd7134af8&width=300&dpr=4&quality=100&sign=dd1f9059&sv=2) If you click on "users" you should be able to see the list of all current active users and their data. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/local-installation#demo-config) Demo Config In Unity, go to Resources/NetworkData From that file, you can set the api url and whether it is using https or not. To test locally, use these config Auth\_type: `API` Api URL: `127.0.0.1` Api Https: `false` And then run the LoginMenu scene. In newest versions of Unity (2022+), HTTP is blocked by default and only HTTPS is allowed, but since our API doesn't have a SSL certificate yet, we need to test with HTTP. To allow HTTP request, go in Edit -> Project Settings -> Player Settings -> Other Settings -> Allow Download over HTTP. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/local-installation#upload-data-to-api) Upload Data to API You will need to sync your data (cards, packs and more...) with the API so that some features work properly, such as pack opening, level rewards and starter decks selection. To do this, go in the Scenes/Tools and open the scene CardUploader. Run it from unity and login with an admin user. It will start uploading automatically all your data to your API database. Whenever you add or edit cards, packs, decks or rewards, you should do this step again if you want your API to be up to date. Last updated 1 year ago --- # Cloud Server Installation | TCG Engine Assuming you already followed the step [here](https://indiemarc.gitbook.io/tcg-engine/getting-started/cloud-server-installation) , and already installed your cloud server. Follow these steps to now install the API on your droplet. It should work no matter if you install the API on the same droplet than your game server, or on a different one, they both work. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/cloud-server-installation#upload-the-code) Upload the code You can find the API code inside a zip in the asset **Install** folder. You can unzip and **upload the NodeJS code** into any folder. In my demo I created this folder and uploaded all the JS code there. /server/api Note: If you previously installed NodeJS locally, a node\_modules folder will have been created in your files. You don't need to upload this folder since it can be quite big and we will reinstall it on the server anyway. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/cloud-server-installation#install-mongodb) Install MongoDB To access the **command line**, from WinSCP, click on Commands->Open in Putty. Follow the instruction to install MongoDB [https://www.digitalocean.com/community/tutorials/how-to-install-mongodb-on-ubuntu-20-04](https://www.digitalocean.com/community/tutorials/how-to-install-mongodb-on-ubuntu-20-04) If you get an error about libssl, check this to resolve it: [https://askubuntu.com/questions/1403619/mongodb-install-fails-on-ubuntu-22-04-depends-on-libssl1-1-but-it-is-not-insta](https://askubuntu.com/questions/1403619/mongodb-install-fails-on-ubuntu-22-04-depends-on-libssl1-1-but-it-is-not-insta) Start Mongo with Copy sudo systemctl start mongod And make sure it is working correctly Copy sudo systemctl status mongod If you want mongo db to start automatically when the droplet starts, run Copy sudo systemctl enable mongod ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/cloud-server-installation#install-nodejs-and-npm) Install NodeJS and NPM Run this to install NodeJS and NPM Copy sudo apt install nodejs Copy sudo apt install npm Install forever globally to run NodeJS as a service Copy npm install forever -g Install node modules required for the API app (make sure you uploaded the nodejs code to that folder first). Copy cd /server/api Copy npm install In WinSCP, open the **config.js** file to edit a few things Change jwt\_secret to any random value Use a different port for your API and for your Game Server, normally i use the default http ports for the api (80 for http and 443 for https). In command line, try to run the app to see if it is working Copy cd /server/api Copy node server.js If there are no error message, this means the app is working! Use ctrl-c to quit the app. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/cloud-server-installation#enable-port-on-firewall) Enable Port on Firewall If you enabled UFW in previous steps, you will also need to allow port 80 and 443 Copy ufw allow http ufw allow https ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/cloud-server-installation#run-nodejs-as-a-service) Run NodeJS as a service You can use forever to run NodeJS as a service so it stays on when you close the command line window Copy forever start --uid tcgapi -a server.js When you make any changes, or reupload the app, you can restart with Copy forever restart tcgapi You can also check if it is running properly Copy forever list ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/cloud-server-installation#unity-test-and-create-admin-user) Unity Test and Create Admin User Go in Unity, in Resources/NetworkData, change the api\_url to the IP of you server, and set api\_https to false (since SSL cert is not installed yet). Also change auth\_type to API. In newest versions of Unity (2022+), HTTP is blocked by default and only HTTPS is allowed, but since our API doesn't have a SSL certificate yet, we need to test with HTTP. To allow HTTP request, go in Edit -> Project Settings -> Player Settings -> Other Settings -> Allow Download over HTTP. While your NodeJS app is running, in the Login Menu scene. Click on Register and create a new user. The very first user that you Register will be granted Admin role, then, all following users will be regular users. If you wish to create another admin user later, you will need to first register it, and then go in the Scenes/Tools/ChangePermission scene to update it's permission level, by login in with the first admin user. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/cloud-server-installation#build-game-server-with-new-settings) Build Game Server with new settings After your NetworkData settings are set correctly, you will need to rebuild your Game Server, Create a new user for the server in the login scene. And use the ChangePermission scene to set it's permission to 5. Go into the Server scene, and click on the Server object, in the list of components you will see a field for username and password, add the credentials of the server user you created. This will allow your server to give rewards and also record all match results in the DB. You can now build your game server and reupload/restart it. **Note:** Important to never include the Server scene in your client build, or you will expose this server password if people decide to decompile the client. This is why I included the field for password in the Server scene and not in NetworkData like the rest of settings. So that the client build does not have this data anywhere. ### [](https://indiemarc.gitbook.io/tcg-engine/web-api/cloud-server-installation#upload-data-to-api) Upload Data to API You will need to sync your data (cards, packs and more...) with the API so that some features work properly, such as pack opening, level rewards and starter decks selection. To do this, go in the Scenes/Tools and open the scene CardUploader. Run it from unity and login with an admin user. It will start uploading automatically all your data to your API database. Whenever you add or edit cards, packs, decks or rewards, you should do this step again if you want your API to be up to date. Last updated 4 months ago --- # Enable Email Sending | TCG Engine The NodeJS api is able to send emails, but you will need to configure your SMTP settings. First you will need to own a domain and an email that has SMTP access. Your email provider will mention the host, port and password you should use to send email with SMTP. You can use any provider of your choice for email and domain. As long as the email provider supports sending with SMTP. Open config.js and set all smtp related values: Copy smtp_enabled: true, smtp_name: "Tcg Engine", //Name of sender in emails smtp_email: "contact@domain.com", //Email used to send smtp_server: "smtp.mailgun.org", //SMTP server URL smtp_port: "465", smtp_user: "contact@domain.com", //SMTP auth user smtp_password: "ABCDEFGHIJKLMNOP", //SMTP auth password The password is usually not the password you use to login to the email provider dashboard. Most of the time there will be a section to generate an app key and you should use that as password. You will also need to change api\_url at the top of config.js, so that confirmation links in your email use the correct url to your api. Last updated 1 year ago --- # Enable HTTPS | TCG Engine To make your API more secure, it is best to enable HTTPS. We will do so by creating a free SSL certificate with certbot. Before doing that, you will need to own a domain, you can buy a domain on any registrar such as Google Domain, and add a A record that points the domain to your server IP. Then, to install certbot and create a SSL certificate, you can follow these steps: [https://www.digitalocean.com/community/tutorials/how-to-use-certbot-standalone-mode-to-retrieve-let-s-encrypt-ssl-certificates-on-ubuntu-22-04](https://www.digitalocean.com/community/tutorials/how-to-use-certbot-standalone-mode-to-retrieve-let-s-encrypt-ssl-certificates-on-ubuntu-22-04) When generating the SSL cert, turn off your NodeJS server because they verify your ssl using the port 80 so it cannot be already in use by your API. For auto-renewals to work, it is better to turn off http (and turn on only https) in your config.js Copy forever stop tcgapi If you manage to create your SSL certificate successfully, remember the path where it was generated, it is usually here: Copy /etc/letsencrypt/live/yoursite.com/cert.pem Go in your config.js file of your node app, and change the 3 paths to point to the **full path** of your cert files: https\_key (privkey.pem), https\_ca (chain.pem), and https\_cert (cert.pem). Set allow\_https to true (you can also set allow\_http to false after everything works) Restart the NodeJS app. Copy cd /server/api forever start --uid tcgapi -a server.js In insomnia, try to access a request with https:// instead of http:// In Unity, in Resources/NetworkData, check the box Api\_Https Last updated 1 year ago --- # Asset Installation | NetcodePlus If you did not import the project settings, go in package manager and install those packages. ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252FSgR65PJX3JhvMIUIZC3V%252Fpackages.png%3Falt%3Dmedia%26token%3D0b7b2620-6b50-457f-a776-36016eef1528&width=768&dpr=4&quality=100&sign=29f285b8&sv=2) You do not need those exact versions, you just need to make sure that your package version is compatible with your Unity version. Once those packages are installed, there should be no more errors in the console. You can try to open one of the scenes and test the project in single player. Last updated 1 year ago --- # Asset Installation | TCG Engine Roguelike ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/asset-installation#packages) Packages When importing TCG Engine asset, I would recommend to also import all Project Settings. If you override project settings, you need to prevent the ProjectVersion.txt file from importing, because that will break your project (Unity can't downgrade version). This is a Unity bug I am trying to report to Unity. Just turn off the checkbox during Step 2 of 2. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2FIwpx7MOo4sJgyhjJlJ8V%2Fvers.png&width=300&dpr=4&quality=100&sign=21e78d58&sv=2) If you do not wish to override projects settings, you need to make sure you have these packages installed. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FpUOO5HmsTxRbrxvFTcQm%252Fpackages.png%3Falt%3Dmedia%26token%3Def637acd-03ed-4c33-b405-66fd1a7e43e2&width=300&dpr=4&quality=100&sign=db3045e7&sv=2) I would recommend updating to the latest version of each package, not to the version in this screenshot. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/asset-installation#render-pipeline) Render pipeline If you plan to use URP (recommended pipeline), in the Projects Settings - Graphics, set the render pipeline to one of the render asset found in the TcgEngine/Render folder. You may also assign the other render asset to the appropriate quality under Projects Settings - Quality. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2F3I5bv6jyRKpWH2iK7yUx%2Furp.png&width=300&dpr=4&quality=100&sign=5a3290c1&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/asset-installation#urp-only) URP Only ? I would strongly recommend to use URP for a card game. HDRP would be overkill for this type of game since it's more aimed at more realistic 3D games, and the built-in pipeline would prevent you from using cool features such as shader graph or some post-processing effects. Built-in Pipeline is still supported (in 1.01+), if you choose to use Built-in pipeline, go in the TcgEngine/Materials folder and import the Built-in material package. Scripts will also work in HDRP, but the demo FX are currently not supported on HDRP. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/asset-installation#linux-dedicated-server-build) Linux Dedicated Server Build If you want to be able to build a Linux Dedicated Server, you will also need to install a Unity Module. Go in Unity Hub -> Install -> Settings -> Click on Add Modules Install the Linux Dedicated Server Build Support ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2FZrMbddkiBw0MjnV3G7Gk%2Fmodule.png&width=300&dpr=4&quality=100&sign=eb1437ad&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/asset-installation#restart-unity) Restart Unity In Unity 6, you may need to restart Unity after importing the asset, for the control inputs to work. That's it for the installation, you should now be able to run the game. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/asset-installation#frequent-install-errors) Frequent Install Errors Check the errors in console after installing the package and trying to run the game. **UI not responding to any click in Menus,** In your project settings Edit-Project Settings-Player-Other Settings : Verify that Active Input Handling and set it to "Both" (If you don't have the Input System package this should be set to Old Input Manager instead). Also try restarting Unity. **Burst Compiler** error, usually you just need to restart Unity. **Invalid Dependencies com.unity.feature.development,** go in package manager, in project, and remove the package with a red ! next to it. If you have this its probably because your unity version downgraded though, so look at the next paragraph just below because that's important, you should not downgrade. **Unity HUB trying to convince you to change Unity Version** when you reopen the project, please do not downgrade Unity Version, as it will break any Unity project, you can only upgrade Unity version. Sometimes Unity Hub still tries to make you downgrade to the Unity version this asset was created with (because of a Unity bug in some Unity Versions that override unity project version when importing project settings). If Unity Hub changed your Unity Version on your project, just reset it to the one you originally used to install the asset. This Asset should work on ALL unity versions after 2020.3.37 (including it), as long as you don't downgrade after importing. Last updated 2 months ago --- # Testing in Solo | TCG Engine Roguelike ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/testing-in-solo#testing-in-solo) Testing in Solo To run the game in solo, just open any scene in Unity (in project tab, TcgEngine/Scenes folder) and hit play at the top. Click Play again to stop the game. If you run from the Game scene, it will start playing with the test decks (set in Resources/GameplayData). Last updated 1 year ago --- # Network Types | NetcodePlus There are 3 different network types you can use included in this asset. Each one have their own advantages. * Peer to peer (including LAN) * Dedicated Server * Relay Server ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/network-types#peer-to-peer) Peer to peer Simplest way to connect and test since it doesn’t require you to host a server. All you need to do do is Host a game from the Menu scene, and then Join with another player using the host’s IP: **Local IP:** 127.0.0.1 if running the game twice on the same PC. **Internal IP:** 192.168.x.x (this is LAN, you can see the host internal IP in the menu). **External IP**: x.x.x.x (you can google “what is my IP” to know this). The disadvantage of this method is that the host needs to open ports and allow the application on their firewall. Also, if connecting with external IP, the host will need to setup port forwarding on their router. The default port is 7700 but it can be changed in the NetworkData settings in Resources folder. ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/network-types#dedicated-game-server) Dedicated Game Server A dedicated server means that there is no host, instead the host is a game server you upload on a cloud server, and run, that other people can connect to. This is a bit more complex to setup because you need to manage your own server. There can only be 1 game per server app (although you can run the application multiple time on the same cloud server, each with a different port). To help with this, there is a lobby server (which is a separate build) that makes it easier for player to find other players, and that will automatically start and stop a new dedicated game server for each game room. The advantage of this method is that there is no player host, so the game does not stop if the host leaves, and no one needs to setup port forwarding. But this method will require you to setup a server, and will require the most server processing power. Since the entire game logic runs on your server. To build the dedicated server, put the ServerGame as the first scene, and make sure to also include all playable game scenes. Another document will explain how to install this. For testing purposes, you can run the dedicated server locally on your pc, either from a build or from unity. You can also connect directly to a dedicated server in the same way you would connect to a host: from clicking on Join in the Menu and using the server’s IP. ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/network-types#relay-server) Relay Server Using a relay server can be used as a compromise between the other 2 methods. You will still have a host (so game shuts down if the host leaves), but the host won’t need to setup port forwarding and do not need to setup their firewall. The relay server does not handle game logic, but will act as a middleman, transferring all messages between the client and the host. A relay server will require way less processing power than a dedicated server, but it will have the greatest delays, since all messages needs to transit through the relay, and if the relay is far from your host it may increase network delays. In this asset, the offered relay server solution is with Unity Services Relay. More info here: [https://docs.unity.com/relay/](https://docs.unity.com/relay/) To use it, you will need to link your project to a Unity ID inside the Services Window, and you will need to enable Unity Relay on your Unity dashboard: [https://dashboard.unity3d.com/](https://dashboard.unity3d.com/) Also you will need to change the protocol type on the UnityTransport to Relay. At the moment, in this asset, you can’t connect directly to a relay server (since the process is a bit more complex). Instead, you need to connect through the lobby server in Relay mode. Last updated 2 years ago --- # Testing Locally | NetcodePlus The easiest way to test the game, right after downloading the asset, is to build the game client (with Menu as first scene). And then run it twice on your PC. You can Host with one, and Join the game on local ip (127.0.0.1) on the other one. [](https://indiemarc.gitbook.io/netcodeplus/getting-started/testing-locally#creating-two-projects) Creating Two Projects ----------------------------------------------------------------------------------------------------------------------------- Creating two Projects Even if creating a build is the simplest way to test the game, it is not the most efficient method. While working on your game, you may want to iterate quickly and test many times a feature, without having to create a new build for every single change. By default, Unity does not allow to open the same project twice, but there is a trick to allow this. It is probably possible to do it on Mac and Linux, but the following will explain how to do it on Windows: Create a new empty project folder outside of the original project folder ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252FTtEfOL8xSFVJW8egf5F9%252FFolders.png%3Falt%3Dmedia%26token%3Db4943292-d693-4e11-bc38-d26e0ff439cd&width=300&dpr=4&quality=100&sign=c3b9ab59&sv=2) Then, copy these folders from the original project to the new project: Packages, ProjectSettings, UserSettings (but not Assets) ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252F4tyCXz8XIjHEFvEHXwIq%252FFolders2.png%3Falt%3Dmedia%26token%3D622b1305-3770-4ecd-a4ce-1367d589a5a8&width=300&dpr=4&quality=100&sign=78d7a2e0&sv=2) Open the command prompt in admin mode (click on start, type “cmd” in the search, then right click on command prompt, and “run as admin”. Change to your new project folder by typing Copy cd C:\Marc\Unity\SurvivalEngine2 (replace with the path to your new folder) Create a simlink to the Assets folder using this command Copy mklink /D Assets C:\Marc\Unity\SurvivalEngine\Assets Replace by the path with the Assets folder of your original project. The /D options means it’s a directory and not a file. Note: If your path has spaces or special characters, you may need to put the path in between quotations : `"C:\Marc\My Projects\Survival Engine\Assets"` Done! You can now open both projects in Unity. Whenever you change any file inside Assets, it will automatically change it in the other project. The project settings won’t be the same, but it allows you to setup the build settings differently in each project (could be one for the client, one for the game server). From Unity, you can run the game directly from any scene (without going through the menu). Doing so will start the game as a “Host”, which also includes single player. If you want to join another player, you need to go through the Menu, and click join. Last updated 1 year ago --- # Testing Multiplayer | TCG Engine Roguelike There are three different ways to test the multiplayer gameplay. * Peer 2 peer * Dedicated Server * Unity Services It is suggested to use the dedicated server or unity services for multiplayer, as peer 2 peer comes with more limited features (lobby system is not available in P2P) and because players won't need to setup their firewall and router for port forwarding. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/testing-multiplayer#peer-to-peer) Peer to Peer To test in peer to peer, build the game and in the menu click on Multiplayer LAN. You will be asked to join or host, and will be able to join someone else. You can simply run the build twice on the same pc, so that you can play with both players. You can also open the Unity project twice instead of doing a build. (See at the bottom of this page) ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/testing-multiplayer#dedicated-server) Dedicated Server You can either run the dedicated server locally or run it on a cloud server. To run it on the cloud, see the page Cloud Server Installation. To run it locally. Make a build with only 1 scene: Server You can also check the box "Server Build" to disable all graphics from the build. Go in Resources/NetworkData, and change the game server url to the IP or url of your dedicated server (if you run it locally put 127.0.0.1). You can run the server build, and then connect to it from Unity or from a Client build. Client build should include the menu and game scenes. In the client menu, click on Multiplayer Lobby. If it shows "Connecting to server..." this means it can't connect to it. If it loads the list of rooms (there may be none), you successfully connected to your server. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/testing-multiplayer#client-build) Client Build ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2F4kAg2u2SC3nmlKcJapmJ%2FClientBuild.png&width=300&dpr=4&quality=100&sign=708e5774&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/testing-multiplayer#server-build) Server Build ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252F0OYNdD4pBlVw27bEVmzP%252FServerBuild.png%3Falt%3Dmedia%26token%3D8f0a39ba-c036-4a22-8770-11924ba71e41&width=300&dpr=4&quality=100&sign=eaea152&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/testing-multiplayer#unity-services) Unity Services You will not need a server build if you use Unity Services. Only a client build (same as above). More Information in the Unity Services page. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/testing-multiplayer#opening-the-unity-project-twice) Opening the Unity Project Twice Opening the unity project twice can save you some build time if you want to quickly be able to test two clients, or one client and one dedicated server, directly from Unity instead of having to make a build each time. Check this tutorial (it is for one of my other assets) to learn how to open the same unity project twice: [https://indiemarc.gitbook.io/netcodeplus/getting-started/testing-locally](https://indiemarc.gitbook.io/netcodeplus/getting-started/testing-locally) Last updated 1 year ago --- # Lobby and Matchmaking | NetcodePlus The lobby server is a separate application that can help your players to find each other. Unlike the game server, the lobby server only needs to be run once, and as many players as you want can connect to it (as long as the server specs allows it). Once a player joins a game room and starts the game, it will disconnect from the lobby server and connect to the host or game server. The lobby server can be used with any of the 3 network types. To change which network type the lobby uses, edit the Resources/NetworkData file. The lobby server itself is always dedicated, but after the player connects to a game, it will connect to the appropriate host (either peer-to-peer to another player, or through the relay, or to a dedicated game server). The lobby server also includes matchmaking features. ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/lobby-and-matchmaking#dedicated-game-server-launcher) Dedicated Game Server Launcher When the lobby is in dedicated server mode, the lobby will also take care of starting the dedicated game servers (one for each game, and each one with a different port). To make this work, you need to include the game server build inside a folder (the path can be set in NetworkData). The path is absolute, unless it starts with ./ or ../ In that case the path is relative to unity’s Application.dataPath, which is either the data folder of the build, or the assets folder of the unity project. This example would allow you to run the lobby in dedicated mode from Unity: ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252FNVlGB6w2v7F8OT5QV2LG%252FServerFolder.png%3Falt%3Dmedia%26token%3Dabfc240f-7b83-42a6-9018-8566e95fc807&width=300&dpr=4&quality=100&sign=e03dae4d&sv=2) ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/lobby-and-matchmaking#build-the-lobby) Build the Lobby To build the lobby server, you only need to include one scene: ServerLobby. For players to access to lobby, they can do it from this scene: MenuLobby For online play, you will need to upload and run your lobby server executable on a cloud server. If in dedicated server mode, you need to do the same with the game server executable. More info on this in another document: Cloud Server Setup. Last updated 2 years ago --- # Install Server Locally | User Login API You can install Mongo and NodeJS locally to test the server without hosting it on the cloud. This can help for development. ### [](https://indiemarc.gitbook.io/user-api/getting-started/install-server-locally#install-nodejs-and-mongo-on-windows) Install NodeJS and Mongo on Windows Install the LTS version of NodeJS [https://nodejs.org/en/](https://nodejs.org/en/) Download and Install MongoDB community [https://www.mongodb.com/try/download/community](https://www.mongodb.com/try/download/community) And Mongo Compass to access the database with an interface (It may have installed already when installing MongoDB). [https://www.mongodb.com/products/compass](https://www.mongodb.com/products/compass) You can open windows services to see if Mongo is running (Start -> search for "services"), then search for Mongo in the list of services. You can also use this Services window to restart mongo if needed. Inside Assets/NodeJS, there is a folder containing all the server code. Unzip it in a new project folder outside of your Unity Project (to prevent Unity from generating a meta file for each file). Once the files are unzipped, open windows command line (click on Start-> type CMD) Navigate to your NodejS code folder, where you extracted the files, that folder should contain the server.js file and package.json file. Copy cd C:\Marc\Unity\UserLoginAPI Install the NodeJS modules Copy npm install Then try to run node Copy node server.js Click ctrl-C at anytime to exit You should now be able to access the API either from the unity Unity or from Insomnia. To access from Unity, make sure that Resources/ApiData has the api path set to 127.0.0.1, https is turned off, and then run the Demo scene. And try registering a new user. If you want to edit the api code, I would suggest to use an IDE such as [Visual Studio Code](https://code.visualstudio.com/) . ### [](https://indiemarc.gitbook.io/user-api/getting-started/install-server-locally#use-mongo-compass-to-check-the-database) Use Mongo Compass to check the database Open Mongo compass, click on new connection, and enter this string Copy mongodb://127.0.0.1:27017/userdb ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252Frruql8rdf55YYsICEe45%252Fcompass1.png%3Falt%3Dmedia%26token%3D66cabcca-9ad3-43cc-921f-9e6b556fe488&width=300&dpr=4&quality=100&sign=aef7abec&sv=2) If it connects correctly, you can click on userdb to see your current data. If userdb doesn't appear on the left, it may be because there is no data yet. To add data you can register a new user, either through the Unity demo, or with Insomnia. ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252F26yfqfokhKDotoRpQLt0%252Fcompass2.png%3Falt%3Dmedia%26token%3D5ad664f1-596a-435e-b093-594cf096c753&width=300&dpr=4&quality=100&sign=2492fe3a&sv=2) If you click on "users" you should be able to see the list of all current active users and their data. ### [](https://indiemarc.gitbook.io/user-api/getting-started/install-server-locally#demo-config) Demo Config In Unity, go to Resources/ApiData From that file, you can set the api url and whether it is using https or not. To test locally, use these config Api URL: `127.0.0.1` Api Https: `false` And then run the Demo scene. In newest versions of Unity (2022+), HTTP is blocked by default and only HTTPS is allowed, but since our API doesn't have a SSL certificate yet, we need to test with HTTP. To allow HTTP request, go in Edit -> Project Settings -> Player Settings -> Other Settings -> Allow Download over HTTP. Last updated 1 year ago --- # Unity Services Server | TCG Engine Roguelike [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/unity-services-server#unity-services-server) Unity Services Server -------------------------------------------------------------------------------------------------------------------------------------------- Instead of using a dedicated game server, you can also use Unity Lobby + Unity Relay to connect your players, so that you don't need to host your own dedicated server, but they also don't need to change their firewall and router settings. This means the game server logic is executed by the host player instead or your own server, but the network messages are sent through a relay service to prevent firewall issues. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/unity-services-server#link-project-to-unity-services) Link Project to Unity Services #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/unity-services-server#link-unity-project) **Link Unity Project** First you need to link your project to Unity Services inside Project Settings-Services #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/unity-services-server#enable-relay) **Enable Relay** Go on the Unity Dashboard [https://dashboard.unity3d.com/](https://dashboard.unity3d.com/) Make sure you select the project you linked to. And enable Lobby and Relay in the Multiplayer tab. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/unity-services-server#change-settings-in-your-project) Change Settings in your Project Change **NetworkData** in Resources/NetworkData Change server\_type to Unity Services. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FKyqOQl0xVJSpESJqRIuh%252Fnetdata.png%3Falt%3Dmedia%26token%3D8a91e966-65ac-4edf-8cd3-ee872a931e23&width=768&dpr=4&quality=100&sign=aa874d20&sv=2) Open the network manager prefab, and under UnityTransport, change the Protocol to Relay ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FWCgQ1JHNbtLjpn9Qdqx8%252Fimage%2520%287%29.png%3Falt%3Dmedia%26token%3D4284f298-0df5-4170-adbd-11d0b927ac7b&width=768&dpr=4&quality=100&sign=7c1c8500&sv=2) Now you should be able to test from the Menu scene. It if you have issues connecting, it may be because of version mismatch between Unity Engine, Netcode package, Lobby package and Relay package. Try updating Netcode, Lobby and Relay packages to latest or recommended version in the Package Manager. Last updated 1 year ago --- # Cloud Server Installation | TCG Engine Roguelike Follow these steps to create a dedicated cloud server. In this example, we are going to use Digital Ocean, but the server application can be hosted on any cloud provider of your choice. If you do not have an account already, you can use this referral link to create an account, and the first two months will be free. [https://m.do.co/c/ca46a35fd4dd](https://m.do.co/c/ca46a35fd4dd) ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/cloud-server-installation#prerequisites) Prerequisites You will need to download these two applications in order to access your server. One is a SFTP file manager and the other is a SSH command line tool. These tools are for Windows, but there are plenty of SFTP and SSH alternatives on Mac/Linux. WinSCP: [https://winscp.net/eng/index.php](https://winscp.net/eng/index.php) Putty: [https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) (Recently it seems like the putty website is often down, I managed to install it from the Windows Store instead). When installing Putty, make sure to also install PuttyGen (it is to generate ssh keys). ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/cloud-server-installation#create-a-droplet) Create a Droplet After you created a Digital Ocean account and entered your credit card information, and that your account is ready to use, you are ready to create a Droplet. 1) In Droplets section, click on Create -> Droplet 2) Select the OS: I use Ubuntu 22.04 3) Choose the specs of your server I use the $20 server personally, but you may be fine with a cheaper one for development, or may need a bigger one depending of your player count. I would go with at least 1GB+ ram, many users had issues with the 512mb ram droplet. 4) Choose any region (closest to you will have better performances). 5) Select a SSH key (see next section to generate a new one) 6) Select a hostname for your server (can be anything). 7) Click Create Droplet ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2FtLXGx5fW2pVi8ucTAXHE%2FDroplet.png&width=300&dpr=4&quality=100&sign=b5422e2d&sv=2) Once your droplet is ready, the IP of your server will be displayed. You will need that IP later when creating the unity build. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/cloud-server-installation#generate-ssh-key-with-puttygen) Generate SSH key with PuttyGen To generate a key, open PuttyGen and click on generate. Once done, save the private key file on your computer. Then copy the public key displayed on screen to Digital Ocean. On Digital Ocean, Add a name to your key and then click on Add SSH key. Make sure to store your private key file in a secure place, if you lose the key you won’t be able to access your droplet. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2F4mYZziZn0xmRDr7bYMxJ%2Fputty.png&width=300&dpr=4&quality=100&sign=799ad1b8&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/cloud-server-installation#create-the-server-build-in-unity) Create the Server Build in Unity Before creating your server build, make sure the Resources/NetworkData settings are correct. Set your URL to the server IP (or domain of you have one). And set the port you want to use. When building the game server. You only need to include the **Server** scene. Since our Digital Ocean server is on Linux, select Linux as the platform on x86\_64, and check the box Server Build (In some Unity versions it is a different tab called "Dedicated Server"). ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/cloud-server-installation#connect-to-your-server-with-winscp) Connect to your server with WinSCP Open WinSCP and create a new connection. Enter the IP of your server as Host, and enter root as the username. The password is blank since we use a SSH key instead. Click on Advanced, then SSH/Authentification, then select your private key file there. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2FVoxl8RYXgx0asBHWHqrN%2Fwinscp.png&width=300&dpr=4&quality=100&sign=9a5950e4&sv=2) This will give you access to the server files, now you can upload your build into any folder, in my demo I created this folder: Copy /server/game **Important**: /root/server/game is not the same as /server/game, do not install inside /root/ because that is a reserved folder for the root user. And some people experienced issues installing inside /root/ ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2F0eMA5cQ9MmCxBaWGfsS8%2Fserver-folder.png&width=300&dpr=4&quality=100&sign=6cbc73d4&sv=2) To access the **command line**, from WinSCP, click on Commands->Open in Putty. Once you gain access you can navigate to the server folder with Copy cd /server Now we need to give the server permission to execute our build, to do that, we can run Copy chmod -R 755 game ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/cloud-server-installation#test-the-game-server) Test the Game Server Run the game server to test it: Copy cd /server/game ./TcgEngineServer.x86_64 Now you should be able to connect to it from your client build (or from unity). Before you run the client, make sure that Resources/NetworkData url is set to your server ip, and also add back all the client scenes in your build settings. Launch the game, and from the menu, click on Multiplayer. If the screens shows "Connecting to server" it can't connect. If it shows "Searching for player" This means you are successfully connected! In putty, use Ctrl-C at any time to stop the server from running and return to command line. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/cloud-server-installation#run-the-server-as-a-service) Run the server as a Service While running directly the game server is a good way to test (since you can see the live debug console). This method isn’t persistent and your app will stop as soon as you leave putty. To create a persistent server you need to create a service. In Unity, go to TcgEngine/Install folder, there should be a tcg.service file there. Upload that file to your server at this path: Copy /etc/systemd/system Open the file you just uploaded (double click in WinSCP) then make sure the path to your game server is set correctly. To start/restart/stop the service, you can use these commands from putty (“tcg” is the name of your service file). Copy systemctl start tcg systemctl restart tcg systemctl stop tcg You can also run this command to check if the service is running (and use ctrl-c when you want to quit top) Copy top Now that your service is running, you can try to connect to it from the client build or from Unity. In the same way you connected to it before. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/cloud-server-installation#firewall-setup) Firewall setup It’s good to block the port you don’t use on your server, from the command line, you can run Copy ufw allow ssh ufw allow 8778 ufw enable And to check the status of your firewall: Copy ufw status Be sure to always run allow ssh before enabling the firewall, otherwise you will lose your putty connection and won’t be able to connect anymore. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/getting-started/cloud-server-installation#updates) Updates If you make changes to the data or gameplay logic, and need to rebuild your game server. To re-upload all you need to do is first: Copy systemctl stop tcg Then, reupload your game server in WinScp inside /server/game. You don't need to delete previous files if the build has the same name, they should be overwritten, this way you don't need to call chmod. If you deleted the files you may need to call chmod again. Copy systemctl start tcg Last updated 2 months ago --- # Cloud Server Installation | NetcodePlus Follow these steps to create a server and host the lobby server and/or the game server. In this example, we are going to use Digital Ocean, but the server application can be hosted on any cloud provider of your choice. If you do not have an account already, you can use this referral link to create an account, and the first two months will be free. [https://m.do.co/c/ca46a35fd4dd](https://m.do.co/c/ca46a35fd4dd) ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#prerequisites) Prerequisites You will need to download these two applications in order to access your server. One is a SFTP file manager and the other is a SSH command line tool. These tools are for Windows, but there are plenty of SFTP and SSH alternatives on Mac/Linux. WinSCP: [https://winscp.net/eng/index.php](https://winscp.net/eng/index.php) Putty: [https://www.putty.org/](https://www.putty.org/) When installing Putty, make sure to also install PuttyGen (it is to generate ssh keys). ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#create-a-droplet) Create a Droplet After you created a Digital Ocean account and entered your credit card information, and that your account is ready to use, you are ready to create a Droplet. 1) In Droplets section, click on Create -> Droplet 2) Select the OS: I use Ubuntu 22.04 3) Choose the specs of your server I recommend 2+ CPU. (For dev the $20 server should be more than enough, but if you have a lot of players, you will probably need to upgrade that later.) 4) Choose any region (closest to you will have better performances). 5) Select a SSH key (see next section to generate a new one) 6) Select a hostname for your server (can be anything). 7) Click Create Droplet ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252FJcGT1C2l9q9IHHXU7HMA%252FDroplet.png%3Falt%3Dmedia%26token%3D5bf69da0-c2a9-406f-9bdd-4a395f239288&width=300&dpr=4&quality=100&sign=e013d61f&sv=2) Once your droplet is ready, the IP of your server will be displayed. You will need that IP later when creating the unity build. ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#generate-ssh-key-with-puttygen) Generate SSH key with PuttyGen To generate a key, open PuttyGen and click on generate. Once done, save the private key file on your computer. Then copy the public key displayed on screen to Digital Ocean. On Digital Ocean, Add a name to your key and then click on Add SSH key. Make sure to store your private key file in a secure place, if you lose the key you won’t be able to access your droplet. ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252FCAbmG0YYKrybTJEHDEe8%252Fputty.png%3Falt%3Dmedia%26token%3D33a1502b-92cd-4734-b514-463b7d3a73cc&width=300&dpr=4&quality=100&sign=49e906b2&sv=2) ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#create-the-server-build-in-unity) Create the Server Build in Unity There are 2 builds you need to create: ServerLobby and ServerGame. The lobby is an independent app that allows players to find each other, once a game is started by the lobby, players will be redirected to the game server. The game server will be launched once for every game created. While the lobby server never has more than 1 instance running. You can create your builds from File->Build Settings. #### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#game-server) Game Server When building the game server. Make sure to add the **ServerGame** scene as the first scene. You also need to include **all the game scenes** you want players to be able to play in. Since our Digital Ocean server is on Linux, select Linux as the platform on x86\_64, and check the box Server Build (In some Unity versions it is a different platform called "Dedicated Server"). #### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#lobby-server) Lobby Server Before building the lobby, you will need to go inside Resources folder and select NetworkData file. There you need to set 3 things: lobby\_url, lobby\_game\_type, and game\_path\_linux. (The path is absolute, unless it starts with .. or ./ then it will be relative to Application.dataPath) When building the lobby server. You only need to include 1 scene: **ServerLobby**. Since our Digital Ocean server is on linux, select Linux as the platform on x86\_64, and check the box Server Build. ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252FWBGEzwNDtphcdaKOqaN6%252FlobbyBuild.png%3Falt%3Dmedia%26token%3D7b72d2bc-0831-4eaa-b729-953e98ab8bb1&width=300&dpr=4&quality=100&sign=98057f97&sv=2) ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#connect-to-your-server-with-winscp) Connect to your server with WinSCP Open WinSCP and create a new connection. Enter the IP of your server as Host, and enter Root as the username. The password is blank since we use a SSH key instead. Click on Advanced, then SSH/Authentification, then select your private key file there. ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252FLsXsn5cWpMlcOoXTvAzv%252Fwinscp.png%3Falt%3Dmedia%26token%3Db9362799-3db5-451e-acfd-c35a2155941b&width=300&dpr=4&quality=100&sign=c3b60193&sv=2) This will give you access to the server files, now you can upload your builds into 2 separate folders, in my demo I created these folders: /server/game /server/lobby **Important**: /root/server/game is not the same as /server/game, do not install inside /root/ because that is a reserved folder for the system. ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252FGMYT7oyk5O1YXQIMvoPp%252Fwinscp-folders.png%3Falt%3Dmedia%26token%3D27ae0bea-d851-4a86-97b8-16afb2b852a0&width=300&dpr=4&quality=100&sign=46e6a9f3&sv=2) To access the **command line**, from WinSCP, click on Commands->Open in Putty. Once you gain access you can navigate to the server folder with cd /server Now we need to give the server permission to execute our build, to do that, we can run Copy chmod -R 755 game chmod -R 755 lobby ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#test-the-game-server) Test the Game Server Run the game server to test it: Copy cd /server/game ./ServerGame.x86_64 Now you should be able to connect to it from your client build (or from unity). Launch the game in Unity from the regular menu, click on join, and use the server IP as host. If you manage to connect, this means your game server is working! If you can’t connect or receive an error about the scene not found, make sure that the DemoSimple scene is enabled in the Build Settings (this is the default scene the game server runs on, you can change that default scene in ServerGame scene). Use Ctrl-C at any time to stop the server from running and return to command line. When the game server is launched by the lobby, the scene will be passed as parameter instead of running the default scene. ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#test-the-lobby-server) Test the Lobby Server Copy cd /server/lobby ./ServerLobby.x86_64 In Unity, in Resources/NetworkData, make sure the lobby\_url is set correctly, since this is the IP your client will try to connect to. Now from Unity, launch the LobbyMenu scene and try connect. If you reach the list of games, this means you can connect to your lobby. You can now try to create a game and start it. **Important**: Your lobby server relies on being able to launch the game server application for each game room created, so make sure your game server is properly setup before you run the lobby in Dedicated Server mode. If you run the lobby in Peer-2-peer or in Relay mode, you don’t need to upload and install a game server since the lobby will make players connect directly to each other. ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#run-the-lobby-as-a-service) Run the lobby as a Service While running directly the game and lobby is a good way to test (since you can see the live debug console). This method isn’t persistent and your app will stop as soon as you leave putty. To create a persistent server you need to create a service. In Unity, go to NetcodePlus/Install folder, there should be a lobby.service file there. Upload that file to your server at this path: Copy /etc/systemd/system Open the file you just uploaded (double click in WinSCP) then make sure the path to the lobby server is set correctly. To start/restart/stop the service, you can use these commands from putty (“lobby” is the name of your service file). Copy systemctl start lobby systemctl restart lobby systemctl stop lobby You can also run this command to check if the service is running (and use ctrl-c when you want to quit top) Copy top Now that your service is running, you can try to connect to it from the client build or from Unity. In the same way you connected to it before. ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/cloud-server-installation#firewall-setup) Firewall setup It’s good to block the port you don’t use on your server, from the command line, you can run Copy ufw allow ssh ufw allow 7500:7600/udp ufw allow 7500:7600/tcp ufw enable And to check the status of your firewall: Copy ufw status Be sure to always run allow ssh before enabling the firewall, otherwise you will lose your putty connection and won’t be able to connect anymore. Last updated 2 years ago --- # Unity Services Server | NetcodePlus Instead of using a dedicated game server, you can also use Unity Lobby + Unity Relay to connect your players, so that you don't need to host your own dedicated server, but they also don't need to change their firewall and router settings. This means the game server logic is executed by the host player instead or your own server, but the network messages are sent through a relay service to prevent firewall issues. ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/unity-services-server#link-project-to-unity-services) Link Project to Unity Services **Link Unity Project** First you need to link your project to Unity Services inside Project Settings-Services **Enable Relay** Go on the Unity Dashboard [https://dashboard.unity3d.com/](https://dashboard.unity3d.com/) Make sure you select the project you linked to. And enable Lobby and Relay in the Multiplayer tab. ### [](https://indiemarc.gitbook.io/netcodeplus/getting-started/unity-services-server#change-settings-in-your-project) Change Settings in your Project Change **NetworkData** in Resources/NetworkData Change lobby\_type to Unity Services, and change lobby\_game\_type to RelayServer. Change auth\_type to Unity. Use auth\_auto\_logout when testing 2 instances on the same pc so that it doesn't use the same UserID twice. (Because it would prevent you from connecting to the same game). ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252F5WS21MadmerTVUx5wQ7P%252FUnityServices.png%3Falt%3Dmedia%26token%3D9188e54b-3900-4770-8f63-cc688b89a4cc&width=768&dpr=4&quality=100&sign=25549215&sv=2) Open the network manager prefab, and under UnityTransport, change the Protocol to Relay ![](https://indiemarc.gitbook.io/netcodeplus/~gitbook/image?url=https%3A%2F%2F2420431882-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXf6tqhOjNfN1X0JaSdNA%252Fuploads%252F9uyBd51tIdglE5SNUNJn%252Ftransport.png%3Falt%3Dmedia%26token%3Da4aad05a-6a4c-442a-83a1-13ab5dd463f3&width=300&dpr=4&quality=100&sign=b6905af9&sv=2) Now you should be able to test from the LobbyMenu scene. It if you have issues connecting, it may be because of version mismatch between Unity Engine, Netcode package, Lobby package and Relay package. Try updating Netcode, Lobby and Relay packages to latest or recommended version in the Package Manager. Last updated 1 year ago --- # Test with Insomnia | User Login API Insomnia is a really useful tool to test direct http request before coding them in your app. So you can test your API server directly before coding the client-side code. Download the Free version of Insomnia [https://insomnia.rest/](https://insomnia.rest/) Start Insomnia, You can either create a new collection: Create -> Request, or import mine Create -> Import from file (you can find the file in Assets/NodeJS folder). Then click on your new collection to open the list of requests. ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FyL3NcNDkP5Jq8KJWrFZr%252FInsomnia.png%3Falt%3Dmedia%26token%3D16008cd0-e381-47fd-8036-b3aa2fc3830f&width=300&dpr=4&quality=100&sign=be093d0c&sv=2) #### [](https://indiemarc.gitbook.io/user-api/getting-started/test-with-insomnia#register-a-user) Register a user From here you can create request to test your API. Let's try to create a new admin user. You can edit an existing request or create a new one. Copy POST http://127.0.0.1/users/register Change the Body to JSON and put this as body: Copy { "username": "admin", "email": "admin@test.com", "password": "admin" } Since we are testing locally, the password/email doesn't matter for now. We just use something easy to remember. Make sure NodeJS is running in your command line window, and click on SEND If it works, hopefully you should see something like this. Copy { "success": true, "id": "64079a109630dced89a3f612" } #### [](https://indiemarc.gitbook.io/user-api/getting-started/test-with-insomnia#change-admin-permission-manually) Change ADMIN permission manually There are no direct function to create the first ADMIN user, so we will go change the permissionLevel in mongo directly. You can open in Mongo Compass, click on your new user and change the permissionLevel to 10 ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FYkKlTnNpOxTO1lbUwEat%252Fmongo-perm.png%3Falt%3Dmedia%26token%3D7d491e32-3d64-4a96-8c8d-88f63b151709&width=300&dpr=4&quality=100&sign=358c7acb&sv=2) This will allow the admin user to execute more function, and also let it grant permissions to other users if needed. #### [](https://indiemarc.gitbook.io/user-api/getting-started/test-with-insomnia#login-with-a-user) Login with a user Now use the auth request to login with the admin user Copy POST http://127.0.0.1/auth Body JSON again: Copy { "username": "admin", "password": "admin" } Click on SEND, if it works you should see something like this Copy { "id": "64079ef79630dced89a3f61c", "username": "admin", "access_token": "eyJhbGciOiJIUzI1NiI421XVCJ9.eyJ1c2VySWQiOiI2NDA3OWVmNzk2MzBkY2VkODlhM2Y2MWMiLCJ1c2VybmFtZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbkB0ZXN0LmNvbSIsInBlcm1pc3Npb25MZXZlbCI6MSwidmFsaWRhdGlvbkxldmVsIjowLCJwcm92aWRlciI6InVzZXJuYW1lIiwicmVmcmVzaEtleSI6Ik83OUtFYVovMGU5cDA5TFY0N3Q4aXc9PSIsImlhdCI6MTY3ODIyMTA1MH0.ly_Ivy1XV-lOvxx_Bj-9qHaH5n4YXHez0kXmCbyAy_s", "refresh_token": "NVM5RDNvbGdySSa2d24Y0xtMDkyL0NMWThhSEhKVk1iMTZQNjFqNHpNTXpxZ2s5OHVmVzdRbXl4cHU4RDN0QUIxUThqcDBqOGRWbWtjaUQ1Y0d2dldPcEE9PQ==", "permission_level": 10, "validation_level": 0, "version": "0.01" } This gives you an access\_token you will need to execute any requests that require authentication. Copy the access token you got (without the ") #### [](https://indiemarc.gitbook.io/user-api/getting-started/test-with-insomnia#read-the-list-of-all-users) Read the list of all users Let's create a new request to read the list of all users Copy GET http://127.0.0.1/users Leave the body empty, instead click on Headers and add one, as header name, write: Copy authorization And as value paste the access token you got when login in. ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FQ4zKUC0z74Cgcop7Khts%252Fheaders.png%3Falt%3Dmedia%26token%3Db4b7d66f-6551-426d-8166-ef7fd938fe8b&width=300&dpr=4&quality=100&sign=6667f83f&sv=2) Now click on send, it should show the full list of existing users. Great, now you know how to use Insomnia, you can do the same for all other requests. To know which requests are possible, check the other sections of this doc, or check the .routes.js files inside the NodeJS code. #### [](https://indiemarc.gitbook.io/user-api/getting-started/test-with-insomnia#granting-permissions) Granting Permissions If you also have a game server, you could create a "server" user with permission level 5. This will allow the user to give rewards and read other users, but won't let it assign permissions or delete users (only an admin can). To set permission Level of a user through requests, if you already have at least 1 admin user, you can login with the admin user and use Copy POST http://127.0.0.1/users/permission/edit/6407a114953 Replace the ID at the end of the URL by the ID of the user you want to target. Use the authorization token of your admin user. And set the body to: Copy { "permission_level" : 5 } There are only 4 relevant permission levels in this API. By default, for new users the permission Level will be 1, which is what it should be for most users. See [permission levels here](https://indiemarc.gitbook.io/user-api/requests/edit-users) . ### [](https://indiemarc.gitbook.io/user-api/getting-started/test-with-insomnia#testing-request-on-the-cloud-server) Testing request on the cloud server To test online request, once you installed your cloud server, you can replace 127.0.0.1 by the IP of your server, or your domain name. If you enabled https, you can also replace http by https in the URL. Other than that everything should work the same. Last updated 2 years ago --- # Messages and Choices | Dialogue Quests ### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/messages-and-choices#messages) Messages Dialogue messages must be added as child objects of a NarrativeEvent. They will be executed in order when when an Event is triggered. ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FKQNdENKCAJjaVM0ZnG7K%252FDialogueMsg.png%3Falt%3Dmedia%26token%3Dc5680a03-ba34-44f1-8670-b4fc434f5a67&width=768&dpr=4&quality=100&sign=270269b3&sv=2) **Actor:** The character that will tell that message. The character must have the Actor script. **Audio clip:** A sound played during this message. **Duration:** How long (in seconds) this dialogue will be shown (only if the dialogue\_type selected is InGame on the Event, In DialoguePanel mode, the user must click to continue). **Pause:** Pause time (in seconds) between this message and the next one. ### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/messages-and-choices#choices) Choices Dialogue choices must be added as child objects of a NarrativeEvent, on the same object as one of the Dialogue messages. You simply need to link to another Event on "Go To" of each choice. The linked event can be set to "Manual" as it is triggered by a choice instead of a Trigger. When the player selects a choice in the dialogue, it will stop the current event and start the one set on "Go To". ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FCQZ1iJVXKG013jt7N21X%252Fchoices.png%3Falt%3Dmedia%26token%3D2a731f42-959a-430b-b1f1-ed8df0a8785c&width=768&dpr=4&quality=100&sign=cd6ce8b0&sv=2) Last updated 1 year ago --- # Narrative Event | Dialogue Quests Narrative Event are what triggers dialogue, or effects such as starting or ending a quest. The way the system works, is by creating a hierarchy of objects for your dialogues. When an Event is triggered, each child object contained in it will be executed 1 by 1, in the order they appear. Child objects can contain dialogues, conditions or effects. This is an example of dialogue hierarchy. In this example, DialogueRoot is an empty game object with no component attached. The NarrativeEvent component is attached to the 3 objects called Event. ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FnkkPtbNHzvoQM0tFjofY%252FHierarchy2.png%3Falt%3Dmedia%26token%3D19427189-8ecc-4ae9-9bbf-20ca9dc1c890&width=768&dpr=4&quality=100&sign=23ec5fe7&sv=2) This is another example of a NarrativeEvent. Test event has the NarrativeEvent component. And the two Msg objects have the DialogueMessage component. (See next section). ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252F1LCabLQB9UbfrUjB2tmo%252FNarrativeEvent.png%3Falt%3Dmedia%26token%3D477325ba-61f8-4c92-b188-4d0abfdb2330&width=768&dpr=4&quality=100&sign=d7e31747&sv=2) **Event ID:** is an optional ID reference to the event if you want its state (such as number of times triggered) saved to file. **Trigger Target:** Reference to object in your scene that will trigger this event (ex: region) **Trigger Actor:** Reference to the actor triggering this event (if set to Actor Interact or Actor Near) **Trigger limit:** will determine how many times that event can be triggered, with 0 meaning infinite. If the event has an event\_id the trigger count will be saved into the data file. **Dialogue Type:** Defines which dialogue panel will appear if the event contains dialogues. **Important:** Important dialogues cannot be skipped, and the user must go through all the messages. Also an Important dialogue will display an Icon on top of the Actor when the player is nearby. Non-Important Dialogue can be skipped (right click by default). **Pause Gameplay:** Will pause the game while this event is running. If you want this to work you need to link to the UnityAction onPause and onUnpause and pause your game. (NarrativeManager). ### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/narrative-event#trigger-types) Trigger Types Defines how the event is triggered, there are different types available: **Manual:** Needs to be Triggered by script **Auto Trigger:** Will trigger automatically whenever the conditions are true. Make sure to add conditions for this type of event because the game will try to trigger it every frame. **Interval:** Trigger every X seconds **Near Actor:** Triggers when the player is near the specified actor. **Interact Actor:** Triggers when the player interacts with the specified actor. In the demo a simple mouse click near the actor will trigger the interaction. **Enter/Exit Regions:** Triggers when the player enters or exit the specified region. Regions are prefabs you can add to your scene. **After Event:** Trigger after another speficied Event finishes. ### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/narrative-event#narrative-groups) Narrative Groups Groups are optional, but if you decide to use them, they can be a way to organize the event. In that case, the object hierarchy of your dialogues should be like this. ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FBNKhnS50k3qCpmhOpaah%252FHierarchy.png%3Falt%3Dmedia%26token%3D12df5ec7-73b9-48d0-83bb-36b75bd6d5af&width=768&dpr=4&quality=100&sign=679f64f8&sv=2) Groups have the NarrativeGroup component attached. Events have the NarrativeEvent attached. Msg and Effect can have DialogueMessage, NarrativeEffect and/or NarrativeCondition. And the DialoguesRoot is just an empty gameobject to put all your dialogues into. When events are part of a group, they may not trigger at the same time. The first event in a group will be the one triggered if the conditions to trigger it are valid. If not, then the second event is considered, until all the events in the group have be considered. When events are not in the same group, there is no such "sequential" check and events can trigger in any order. Last updated 1 year ago --- # Actors | Dialogue Quests Actors are characters that are allowed to participate in a dialogue, they have a portrait, title and can trigger events or be set as the one saying a specific dialogue message. Make sure to add the Actor script on the Player character, and to check is\_player, to allow this character to initiate dialogues. Actor are defined in a scriptableObject (right click -> Create -> DialogueQuests -> Actor). It’s best to put the files in the Resources/Actors folder to have them loaded every scene (see the Loader script in the DQManager to set the path where they are loaded). ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FrV4FqRWj1JApj8nm8tLO%252FActorData2.png%3Falt%3Dmedia%26token%3D4959293b-1ec1-42f3-ae2b-73b6ae50edb6&width=768&dpr=4&quality=100&sign=ab9c5a85&sv=2) **Actor ID:** a reference unique to each actor, used in the save file. **Is Player:** check for the player character. **Animation:** It's possible to add an animation to a portrait of an actor. To test the animation while in edit mode, you should set the animator controller on the portrait in the UI (DQUICanvas, set the panel canvas\_group alpha value to 1 to make it visible and test the animation). **Load Dialogues:** Optional: any prefab set there will be spawned in every scene containing this actor. This allows the creation of events that are not scene dependent. Once your actor data file is defined, you need to add the Actor.cs component to a prefab or object in the scene. And set the right actor data on it. Last updated 1 year ago --- # Resources and Prefabs | TCG Engine Roguelike ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/resources-and-prefabs#resources-folder) Resources Folder Under the Resources folder, you can find all the data for cards, abilities, decks and more... #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/resources-and-prefabs#networkdata) NetworkData If you click on NetworkData, you can change the URL of the game server. To test with a game server installed locally, you should change the URL to 127.0.0.1 ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FIurZjaApONAEoq1eMGSq%252FNetworkData.png%3Falt%3Dmedia%26token%3Dd7e1f866-86a0-4d33-8a15-7616f6e394a4&width=768&dpr=4&quality=100&sign=dd76fe86&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/resources-and-prefabs#gameplaydata) GameplayData Gameplay data let you change various game values such as card hand max, xp per level, and more. At the bottom you can also set the Test values. These are the data used in test mode when running the Map or Battle scene directly without going through the menu to create a new game. For testing new cards, you should add a lot of that card into the test cards and you will be able to test it easily by just running the Game scene. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FbpiyKAQRiF9A99aLZ8K5%252FGameplayData.png%3Falt%3Dmedia%26token%3D3aeb8b73-ba32-4f7f-8e8d-942541bb6e58&width=768&dpr=4&quality=100&sign=d1630945&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/resources-and-prefabs#characterdata-carddata-and-abilitydata) CharacterData, CardData and AbilityData All characters, cards and abilities data are held in scriptable objects. You can duplicate a card with Ctrl-D, and assign new art, stats and skills. Note on ID: the id is what is saved in the save file to know which cards a player own or which cards are in his deck. So once you choose an ID for a card, try to not change it, also try to avoid spaces or special characters in the ID. The title can be changed freely and can contain special characters (as long as your font support it). ScenarioData, MapData, MapEvents Specific to the Map section of the game, will determine the possible map locations you can visit, what can happen at each location, and what type of enemies you can encounter. A scenario is the top level data, each game will consist of 1 scenario that can be selected when creating a new game, a scenario will go through multiple maps 1 by 1 until they are all completed. Within a map, there will be various locations to explore, each location will contain a randomized MapEvent amongst the ones that are available to this map. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/resources-and-prefabs#conditiondata-and-effectdata) ConditionData and EffectData During battles, card abilities use conditions and effects to determine how they work. An example of effect would be dealing damage, and an example of condition could be "Is an enemy character". You can code your own by creating a script that inherits from ConditionData or EffectData. And then create a data file inside the resources folder from those script. You can create a new data file by right clicking inside a folder: Create-TcgEngine. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/resources-and-prefabs#prefabs) Prefabs Prefabs can be found in TcgEngine/Prefabs folder. **GameClient** Main Manager for the client side of the game, must be added to all game scenes including battles, maps and game setup scene, but NOT in menus or on the server scene. **TheNetwork** Contain network managers scripts for the game client, game server, and the api client, should be added to all scenes including menu, game and server. This prefab has DontDestroyOnLoad, unlike most other managers or prefabs. **MapUI** Main UI prefab for the map section of the game. While editing the UI prefab, on the CanvasGroup components, you can set the alpha value to 1 or 0 to show or hide a specific panel. **BattleUI** Main UI script for the battle scene. Just like the MapUI, you can also hide/show panels with the canvas group. **Prefabs/Characters** In this folder you will find 1 prefab for each of the champion or enemies available in game. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/resources-and-prefabs#handcard-and-cardui) HandCard and CardUI If you want to edit the shape or positioning of cards, these are the prefabs you will want to edit inside Prefabs/Gameplay. The same prefab is used for all cards since the art and text is replaced when a card appear in game. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/resources-and-prefabs#characterui) CharacterUI Prefab that is common to all character prefabs. Contains things like the HP bar, shield, status icons, intent icon. Last updated 1 year ago --- # Remote Access and DB Authentication | User Login API It is better to enable authentication on MongoDB to make it more secure, and also to allow remote access. On your server open the file: /etc/mongod.conf Change the Binding IP to Copy bindIp: 127.0.0.1,10.11.12.13 With the second IP after the coma being the IP of your server where the API and mongo are installed. This will allow remote access to your MongoDB. Add these lines in the conf file Copy security: authorization: "enabled" This will prevent connecting without a username/password. You will instead need to use one of the users you created during Mongo Installation. Important: Changing the binding IP will allow anyone to try to connect directly to your database from anywhere, as long as they have the password. It can be useful for development if you want to read your database from Mongo Canvas, but it is also an increased security risk. If you allow remote connection you should also setup your server firewall properly so that it blocks requests that don't come from your IP for the MongoDB port. See the Firewall section below. Restart mongo to enable your conf changes Copy systemctl restart mongod Make sure you didn't break anything by changing the config Copy systemctl status mongod Now you can connect to your database from your PC, in Mongo Compass, using a string similar to this one Copy mongodb://[user]:[password]@[hosturl]:27017/[database]?authSource=admin For Example Copy mongodb://root:123456789@survival-engine.com:27017/userdb?authSource=admin The host URL can either be a domain or IP address. Now also restart your NodeJS app to make sure it can still connect to Mongo. When testing something you can start the app normally with `node server.js` to see the errors in console instead of using forever. ### [](https://indiemarc.gitbook.io/user-api/getting-started/remote-access-and-db-authentication#firewall-setup) Firewall setup It’s good to block the port you don’t use on your server, from the command line, you can run Copy ufw allow ssh ufw allow http ufw allow https ufw enable http will open port 80, and https will open port 443 And to check the status of your firewall: Copy ufw status Be sure to always run `allow ssh` before enabling the firewall, otherwise you will lose your putty connection and won’t be able to connect anymore. If you also want to open a direct access to MongoDB (to use in Mongo Compass), you can enable port 27017 but only for your IP address. Copy ufw allow from 1.2.3.4 to any port 27017 Important to replace 1.2.3.4 by your own [external IP address](https://api.ipify.org/) . 27017 is the default port for Mongo so no need to change it. It will open port 27017 but only for requests coming from your IP address. This can be really useful to read the Database on your PC for development, you can turn off the access when going live. Last updated 1 year ago --- # Save File | TCG Engine Roguelike Both singleplayer and multiplayer games can be saved locally on your PC. You can find the save file inside Unity's persistantDataPath folder. Each OS has a different path, so check here to know where: [https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html](https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html) Inside the folder, you will find a save file for the last game started with each user. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FFmxjXdXvPqTztxyYDwRn%252FSaveFile.png%3Falt%3Dmedia%26token%3D8219e736-ef01-4b3f-836a-841097504dd9&width=768&dpr=4&quality=100&sign=179f122b&sv=2) Last updated 1 year ago --- # Enable HTTPS | User Login API To make your API more secure, it is best to enable HTTPS. We will do so by creating a free SSL certificate with certbot. Before doing that, you will need to own a domain, you can buy a domain on any registrar such as Google Domain, and add a A record that points the domain to your server IP. Then, to install certbot and create a SSL certificate, you can follow these steps: [https://www.digitalocean.com/community/tutorials/how-to-use-certbot-standalone-mode-to-retrieve-let-s-encrypt-ssl-certificates-on-ubuntu-22-04](https://www.digitalocean.com/community/tutorials/how-to-use-certbot-standalone-mode-to-retrieve-let-s-encrypt-ssl-certificates-on-ubuntu-22-04) When generating the SSL cert, turn off your NodeJS server because they verify your ssl using the port 80 so it cannot be already in use by your API. For auto-renewals to work, it is better to turn off http (and turn on only https) in your config.js If you manage to create your SSL certificate successfully, remember the path where it was generated, it is usually here: Copy /etc/letsencrypt/live/yoursite.com/cert.pem Go in your config.js file of your node app, and change the 3 paths to point to the correct files. https\_key, https\_ca, and https\_cert. Set allow\_https to true (you can also set allow\_http to false after everything works) Restart the NodeJS app. In insomnia, try to access a request with https:// instead of http:// In Unity, in Resources/ApiData, check the box Api\_Https Last updated 2 years ago --- # Quests | Dialogue Quests Quest are scriptable objects (right click -> Create -> DialogueQuests -> Quest). And loaded from the Resources/Quests folder (by default), by the DQ Manager. ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FYAEiUhAsdPLKvt6yEdsa%252Fquests.png%3Falt%3Dmedia%26token%3Ddc8882db-615a-4a07-86cd-74f333757069&width=768&dpr=4&quality=100&sign=e1fddea0&sv=2) **Quest ID:** a reference unique to each quest, used in the save file. **Title and Desc:** Text displayed as title and description of this quest. Icon: Icon for the quest. (optional). **Sort Order:** Optional, to sort the quest in a specific order in the quest panel. ### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/quests#how-to-start-or-complete-a-quest) How to Start or Complete a quest? Quests are started, and completed by using NarrativeEvents and NarrativeEffects. Quests have 4 possible status: not started, active, completed, failed. Alternatively, it is also possible to Start or Complete a quest by calling a function in script: Copy QuestData quest = QuestData.Get("quest_id"); NarrativeManager.Get().StartQuest(quest); ### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/quests#quest-steps) Quest Steps Quest Steps are optional, but it is possible to define additional "steps" to a quest. The text will be updated in the Quest Journal based on which step the quest currently is at. You can update the current step of a quest with a NarrativeEffect, or by calling a function inside NarrativeManager. ### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/quests#quest-journal) Quest Journal Quests will appear in the Quest Panel (open it with J by default), once they are started or completed. Last updated 1 year ago --- # Managers and Important Scripts | NetcodePlus ### [](https://indiemarc.gitbook.io/netcodeplus/concepts/managers-and-important-scripts#managers) Managers There should 2 main managers prefabs in your project. One Network Manager and one Game Manager. The network manager is persistant (DontDestroyOnLoad) and should be in all your scenes including menu and game scenes. TheNetwork.cs is attached to this manager. The game manager is NOT persistant and should only be in your game scenes. It contain NetworkGame.cs #### [](https://indiemarc.gitbook.io/netcodeplus/concepts/managers-and-important-scripts#thenetwork.cs) TheNetwork.cs Main networking script, it handles connecting clients to host, registering prefabs, and has basics functions to know if you’re on a server or client, and the ID of each client. This object is set to DontDestroyOnLoad so it persists between scenes. Use functions such as StartHost(), StartServer() and StartClient() to start a new connection. #### [](https://indiemarc.gitbook.io/netcodeplus/concepts/managers-and-important-scripts#networkgame.cs) NetworkGame.cs Unlike TheNetwork, this one don’t persist between scenes. Should only be added to game scenes. It registers network messages specific to the gameplay. Handles spawning and despawning objects, and manages SNetworkVariable and SNetworkActions. ### [](https://indiemarc.gitbook.io/netcodeplus/concepts/managers-and-important-scripts#lobby-and-dedicated-server) Lobby and Dedicated Server #### [](https://indiemarc.gitbook.io/netcodeplus/concepts/managers-and-important-scripts#clientlobby.cs-serverlobby.cs) ClientLobby.cs ServerLobby.cs Managers for the client or server side of the lobby. Lobby uses Web Requests instead of connecting with Netcode. (WebTool.cs manages sending web requests). Which allow for a client to be connected to both the lobby and game at the same time. #### [](https://indiemarc.gitbook.io/netcodeplus/concepts/managers-and-important-scripts#servergame.cs) ServerGame.cs Main script for the dedicated server scene. It can receive command line parameters when started, such as the scene to load, game id and port. And it will start the game server based on parameters received. ### [](https://indiemarc.gitbook.io/netcodeplus/concepts/managers-and-important-scripts#components) Components #### [](https://indiemarc.gitbook.io/netcodeplus/concepts/managers-and-important-scripts#snetworkobject.cs) SNetworkObject.cs Add to all object prefabs that should be synced between server and clients, without it you can't use SNetworkBehavior, SNetworkActions and SNetworkVariable in your scripts. This script contains Spawn() and Despawn() functions to start/stop syncing an object, and it also holds a unique network\_id for each object in the scene. #### [](https://indiemarc.gitbook.io/netcodeplus/concepts/managers-and-important-scripts#snetworkoptimizer.cs) SNetworkOptimizer.cs Add this to any object to automatically spawn/despawn based on the distance of that object to players. Can be useful for optimization. #### [](https://indiemarc.gitbook.io/netcodeplus/concepts/managers-and-important-scripts#snetworkplayer.cs) SNetworkPlayer.cs Base script to add to your player character prefab. Is used by SNetworkOptimizer to know which objects should be active, it also holds the player\_id associated with that player. Can be inherited into your own custom script. Last updated 2 years ago --- # Cloud Server Installation | User Login API Follow these steps to create a server and host the lobby server and/or the game server. In this example, we are going to use Digital Ocean, but the server application can be hosted on any cloud provider of your choice. If you do not have an account already, you can use this referral link to create an account, and the first two months will be free. [https://m.do.co/c/ca46a35fd4dd](https://m.do.co/c/ca46a35fd4dd) ### [](https://indiemarc.gitbook.io/user-api/getting-started/cloud-server-installation#prerequisites) Prerequisites You will need to download these two applications in order to access your server. One is a SFTP file manager and the other is a SSH command line tool. These tools are for Windows, but there are plenty of SFTP and SSH alternatives on Mac/Linux. WinSCP: [https://winscp.net/eng/index.php](https://winscp.net/eng/index.php) Putty: [https://www.putty.org/](https://www.putty.org/) When installing Putty, make sure to also install PuttyGen (it is to generate ssh keys). ### [](https://indiemarc.gitbook.io/user-api/getting-started/cloud-server-installation#create-a-droplet) Create a Droplet After you created a Digital Ocean account and entered your credit card information, and that your account is ready to use, you are ready to create a Droplet. 1) In Droplets section, click on Create -> Droplet 2) Select the OS: I use Ubuntu 22.04 3) Choose the specs of your server I recommend 2+ CPU. (For dev the $20 server should be more than enough, but if you have a lot of players, you will probably need to upgrade that later.) 4) Choose any region (closest to you will have better performances). 5) Select a SSH key (see next section to generate a new one) 6) Select a hostname for your server (can be anything). 7) Click Create Droplet ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FkCY2xqztzHBHDj2nbDDc%252Fdigital-ocean.webp%3Falt%3Dmedia%26token%3Dbf9ce055-11fd-4c41-af52-3b21891f802d&width=300&dpr=4&quality=100&sign=fbad02a1&sv=2) Once your droplet is ready, the IP of your server will be displayed. You will need that IP later when creating the unity build. ### [](https://indiemarc.gitbook.io/user-api/getting-started/cloud-server-installation#generate-ssh-key-with-puttygen) Generate SSH key with PuttyGen To generate a key, open PuttyGen and click on generate. Once done, save the private key file on your computer. Then copy the public key displayed on screen to Digital Ocean. On Digital Ocean, Add a name to your key and then click on Add SSH key. Make sure to store your private key file in a secure place, if you lose the key you won’t be able to access your droplet. ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FqY5vQr19DebQOfpwqB53%252Fssh-key.webp%3Falt%3Dmedia%26token%3D9fa72865-fbc3-44c2-992d-5cfadabda3bf&width=300&dpr=4&quality=100&sign=dfd1c36e&sv=2) ### [](https://indiemarc.gitbook.io/user-api/getting-started/cloud-server-installation#connect-to-your-server-with-winscp) Connect to your server with WinSCP Open WinSCP and create a new connection. Enter the IP of your server as Host, and enter Root as the username. The password is blank since we use a SSH key instead. Click on Advanced, then SSH/Authentication, then select your private key file there. ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FGM0cDoduNAWViAiD7SOD%252Fwin-scp.webp%3Falt%3Dmedia%26token%3Da17bf357-0746-43e2-8e71-35147845b978&width=300&dpr=4&quality=100&sign=526b865d&sv=2) This will give you access to the server files You can unzip and **upload the NodeJS code** into any folder. In my demo I created this folder and uploaded all the JS code there. /server/api To access the **command line**, from WinSCP, click on Commands->Open in Putty. Once you gain access you can navigate to the server folder with cd /server/api ### [](https://indiemarc.gitbook.io/user-api/getting-started/cloud-server-installation#install-mongodb) Install MongoDB Follow the instruction to install MongoDB [https://www.digitalocean.com/community/tutorials/how-to-install-mongodb-on-ubuntu-20-04](https://www.digitalocean.com/community/tutorials/how-to-install-mongodb-on-ubuntu-20-04) If you get an error about libssl, check this to resolve it: [https://askubuntu.com/questions/1403619/mongodb-install-fails-on-ubuntu-22-04-depends-on-libssl1-1-but-it-is-not-insta](https://askubuntu.com/questions/1403619/mongodb-install-fails-on-ubuntu-22-04-depends-on-libssl1-1-but-it-is-not-insta) Start Mongo with Copy sudo systemctl start mongod And make sure it is working correctly Copy sudo systemctl status mongod Open mongo command line with Copy mongo While mongo is running in the command line prompt, you can run mongo commands. Use this one to change to the admin database to manage users Copy use admin Run these command to add mongo users. Make sure to set a different password for each, save them somewhere to use later, and note the database name (in this example its called userdb). Important: Mongo Users are not the same than your actual users in the database. You don't need a mongo user for each real user. Mongo users are just a list of apps credentials who can connect to mongo. I usually only create 3 users, not more. One root user, one for the NodeJS app, and one read-only user to use in mongo compass. Create a Root user Copy db.createUser({user:"root", pwd:"123456789", roles:[{role: "dbAdminAnyDatabase", db: "admin"}, {role: "readWriteAnyDatabase", db: "admin"}] }) Create a user for your app Copy db.createUser({user: "api", pwd: "123456789", roles: [{role: "readWrite", db: "userdb"}]}) And finally I also like to create a read-only user Copy db.createUser({user: "viewer", pwd: "123456789", roles: [{role: "read", db: "userdb"}]}) If you made a mistake you can delete a user with Copy db.dropUser("viewer") Use Ctrl-C at anytime to quit mongo and return to regular ubuntu command line. ### [](https://indiemarc.gitbook.io/user-api/getting-started/cloud-server-installation#install-nodejs-and-npm) Install NodeJS and NPM Run this to install NodeJS and NPM Copy sudo apt install nodejs Copy sudo apt install npm Install forever globally to run NodeJS as a service Copy npm install forever -g Install node modules for the User API app Copy cd /server/api Copy npm install In WinSCP, open the **config.js** file to edit a few things Change mongo\_user to "api" (or any other mongo user you created for your app) Change mongo\_pass to the password your set for your api user Change jwt\_secret to any random value In command line, try to run the app to see if it is working Copy cd /server/api Copy node server.js If there are no error message, this means the app is working! Use ctrl-c to quit the app. ### [](https://indiemarc.gitbook.io/user-api/getting-started/cloud-server-installation#run-nodejs-as-a-service) Run NodeJS as a service You can use forever to run NodeJS as a service so it stays on when you close the command line window Copy forever start --uid userapi -a server.js When you make any changes, or reupload the app, you can restart with Copy forever restart userapi You can also check if it is running properly Copy forever status Last updated 2 years ago --- # Scenario and Maps | TCG Engine Roguelike Scenarios and Maps data can be edited in the Resources/Scenario or Resources/Maps folders, you can use Ctrl-D on a file to duplicate it if you want to create a new one. A scenario is the top level data, each game will consist of 1 scenario that can be selected when creating a new game, a scenario will go through multiple maps 1 by 1 until they are all completed. Within a map, there will be various locations to explore, each location will contain a randomized Map Events amongst the ones that are available to this map. In the demo there is only 1 scenario, but it has been dupplicated to test the scenario at different player count. So there is a scenario for 1 player, one for 2 players and one for 4 players. Maps are Randomly generated based on a set of configurations on the map data. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252F8qGiOcTFKhbwVXvLGlG9%252FMap.png%3Falt%3Dmedia%26token%3D4651bd5b-9f51-485e-a1ac-652bca8938d6&width=768&dpr=4&quality=100&sign=b8b3bc35&sv=2) Randomly Generated Map ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/scenario-and-maps#scenario-data) Scenario Data ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252F3RQxEYrTVtxNhBOxxJBb%252FScenarioData.png%3Falt%3Dmedia%26token%3Df8f006cd-76f1-43fa-ab10-ed942468df3b&width=300&dpr=4&quality=100&sign=306d5a61&sv=2) On the scenario, you can set the number of champions (or players) and the starting gold/xp, as well as the maps that will be visited during the game. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/scenario-and-maps#map-data) Map Data ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FK2bCJ7vNmkCL2OWp5G50%252FMapData.png%3Falt%3Dmedia%26token%3D95cb041d-e7fb-4bfc-8a74-1dcfea8e1c60&width=300&dpr=4&quality=100&sign=4de01929&sv=2) Maps are randomized each game, but in a way that is defined in the map data. On each map you can set the default scenes for the map and for battles. **Depth**: The number of locations that needs to be visited to complete the map. So a map with depth of 10 will have 10 column from left to right (each column can have more than 1 location). **Width Min**: Minimum number of possible locations in a single column **Width Max**: Maximum number of possible locations in a single column. **Fork Probability**: The probability that a location will split into 2 choices for the player to chose. So a value of 0.25 would mean that 1/4 of locations will give you a choice for the next location, while 3/4 of locations will go in a straight line. **Events**: Possible events that can be at any location, some events are battles, other events can be choices the player need to make, and other events can be a shop to buy items or upgrade your cards. **Fixed Locations Width**: You can define a fixed width on any column, for example, if you want only once choice for the last depth (lets say you want a boss at the end) you could set that depth 10 has always a width of 1. **Fixed Locations Events:** You can define fixed event that will always appear at a specific location, for example you could set that the last location is always a boss battle, or that every 3 depth you get the chance to upgrade you cards. Last updated 1 year ago --- # SNetworkObject | NetcodePlus All object prefabs that need to be spawned or despawned must have the SNetworkComponent attached. This component is required if you inherit any other scripts from SNetworkBehaviour on the same object. #### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkobject#spawn) Spawn() Starts syncing the object with clients. If the object does not exist on the client it will be instantiated. This function must be called on the server side. You may pass the owner client\_id as parameter, by default the owner is the server. Make sure you registered the prefab with TheNetwork.Get(). RegisterPrefab() before trying to spawn so that all clients are aware this prefab exists. Note that you do not need to call Spawn() manually if auto\_spawn is active on the component. #### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkobject#despawn) Despawn() Stops syncing the object with clients. The object won't be destroyed and will stay in the scene. Must be called from the server side. #### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkobject#destroy) Destroy() Despawns and then destroys the object on all clients and the server. It is recommended to NOT use the default unity GameObject.Destroy() function for any object with SNetworkObject component, and use this one instead. To make sure that the object gets destroyed everywhere instead of just locally. #### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkobject#changeowner-ulong) ChangeOwner(ulong) Change the owner of the object. Must be called on the server side. The new owner ID will be sent to all clients so that they are aware of who is the new owner. The owner of the object is the one allowed to Trigger SNetworkActions to be executed remotely. Use only on objects that are already spawned. Otherwise you can set the owner when spawning with Spawn(client\_id); Last updated 2 years ago --- # Conditions | Dialogue Quests Conditions can be added to a NarrativeEvent or to a DialogueMessage. Conditions prevent an Event from triggering unless the condition is met. They can also prevent a specific dialogue message or effect from triggering under an event. If there are more than one condition on the same event, all of them must be true for the event to trigger. #### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/conditions#condition-on-an-event) Condition on an Event (In this case, this event will only trigger if the CollectGift quest is active). ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FLUQY1GIi0NoxV2Ntqiu9%252FEventCondition.png%3Falt%3Dmedia%26token%3D6213e2d0-2be3-47b0-8c0d-05c6e1835fe2&width=768&dpr=4&quality=100&sign=a2585b7f&sv=2) #### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/conditions#condition-on-a-dialogue-message) Condition on a dialogue message (In this case, when FirstTalk event is triggered, Msg1 and Msg2 will always be displayed, but Msg3 has two possible variants based on the actor relation value.) ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252F0RxikaggDUaqJs12SnqM%252FMsgCondition.png%3Falt%3Dmedia%26token%3D0045b031-7a80-45d2-89ac-1000e1564649&width=768&dpr=4&quality=100&sign=605b4f49&sv=2) #### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/conditions#condition-types) Condition Types **Custom Int/Float/String:** will check if a custom value is set to a specific value. **IsVisible:** will check if a GameObject exists and if it's active. **InsideRegion:** will check if a GameObject is inside a region. Quest Started/Active will check quests status. **EventTriggered:** Will check if another Event was triggered before. The event checked will need to have an Event ID for this to work. **ActorRelation:** Check an actor’s relation value set by other effects. It is possible to code your own Conditions, see the scripts section. Last updated 1 year ago --- # Connection Process | NetcodePlus NetcodePlus connection process has been improved to allow players to share data such as save file or game options before all objects in the scene start spawning. This page will explain what happens in the background when a player connects to the server using the StartHost(), StartServer() or StartClient() function inside TheNetwork.cs Server 1. Server starts listening with StartHost() or StartServer() 2. If a host, a PlayerID is assigned to the host. 3. All the OnReady() functions are triggered on the server. Client 1. Client connect to Game server with StartClient() 2. Server Approve or Reject the connection (You can define conditions with checkApproval) 3. Client automatically changes scene as soon as server approved connection 4. Server Assign PlayerID and send it to client 5. Client receives PlayerID and send Player Data to server 6. Server receives Player Data and send World Data to client 7. Client receives World Data, and send Ready state to server 8. All the OnReady() functions are triggered on the client. 9. Server Receives Ready state and starts spawning the player and all other network objects 10. Client receive Spawn request from server, and spawn player and other objects There are multiple events you can connect to inside TheNetwork.cs to determine what happens at each one of these steps. You can check the script directly, it contains comments on each of those actions. Any custom script related to the connection process should be attached to a scene persistent object so that it is still working while switching scene and not destroyed. In the demo all these following examples are defined in TheNetworkDemo.cs, which is attached to the NetworkManager prefab and has DontDestroyOnLoad. ### [](https://indiemarc.gitbook.io/netcodeplus/concepts/connection-process#connection-approval) Connection Approval You can define conditions to approve or reject a new client connecting by listening to the checkApproval delegate. Copy private void Start() { TheNetwork.Get().checkApproval += OnApprove; } Copy private bool OnApprove(ulong client_id, ConnectionData cdata) { return true; //Approve everything } ### [](https://indiemarc.gitbook.io/netcodeplus/concepts/connection-process#player-id-vs-client-id) Player ID vs Client ID ClientID (ulong) is assigned automatically by Netcode when a client connects. And increments each connection (so it will be a different ID if a client reconnects). Player ID is unique to NetcodePlus and you have control on which ID you assign to each player by using the findPlayerID delegate. This is really useful if you want to reassign the same ID to a player who reconnects, and helps keeping track of players accurately in a save file or other data. Copy private void Start() { TheNetwork.Get().findPlayerID += FindPlayerID; } Copy private int FindPlayerID(ulong client_id) { GameData gdata = GameData.Get(); ClientData client = TheNetwork.Get().GetClient(client_id); //Find existing player id by username (for reconnections) PlayerData user_player = gdata.GetPlayer(client.username); if (user_player != null) { return user_player.player_id; } //No player found, assign new player ID PlayerData player = gdata.AddNewPlayer(client.username); if (player != null) { return player.player_id; } //Max player count reached return -1; } This is just an example as GameData and PlayerData aren't class in NetcodePlus, and are instead in the game demo scripts. You can define whatever logic you like to assign player ID, if you don't define findPlayerID, then the PlayerID will just be the same than the ClientID ### [](https://indiemarc.gitbook.io/netcodeplus/concepts/connection-process#player-data-and-world-data) **Player Data and World Data** These are completely optional and defined in each project. But basically player data is custom data sent from the client to the server on connection, and world data is custom data sent from the server to the client on connection. You can send any data you like if you connect to these delegates: onReceiveWorld, onSendWorld, onReceivePlayer, onSendPlayer. If those events are not defined, then an empty network message will be sent just to aknowledge that the step is completed. Copy private void OnSendWorld(FastBufferWriter writer) { GameData sdata = GameData.Get(); if (sdata != null) { byte[] bytes = NetworkTool.Serialize(sdata); writer.WriteValueSafe(bytes.Length); if (bytes.Length > 0) writer.WriteBytesSafe(bytes, bytes.Length); } else { writer.WriteValueSafe(0); } } Copy private void OnReceiveWorld(FastBufferReader reader) { reader.ReadValueSafe(out int count); if(count > 0) { byte[] bytes = new byte[count]; reader.ReadBytesSafe(ref bytes, count); GameData sdata = NetworkTool.Deserialize(bytes); if (sdata != null) { GameData.Override(sdata); } } } In this example, onSendPlayer is not defined so no data is sent from the client to the server on connection. Also, GameData is a custom class specific to the project and not to NetcodePlus. If you want more examples on how to transfer data on connection, check TheNetworkDemo.cs ### [](https://indiemarc.gitbook.io/netcodeplus/concepts/connection-process#spawning-the-player) Spawning the player One of the last step is to spawn the player character. By default it will be spawned at object position that has the PlayerSpawn component attached with the same PlayerID. But you can define your own functions to determine the prefab to spawn and position to spawn with those delegates: findPlayerSpawnPos, findPlayerPrefab You can also return null from the findPlayerPrefab delegate to not spawn anything at all, and instead you can manually call SpawnPlayer() inside TheNetwork.cs ### [](https://indiemarc.gitbook.io/netcodeplus/concepts/connection-process#onready) onReady onReady is a new delegate you can connect to in TheNetwork that will be triggered once the connection process is completed (before objects are spawned). Objects that are spawned or instantiated after you are already connected, will trigger OnReady at the same time than the Start() function instead. On the server side onReady is triggered at the start as long as the host/server is started and all condition are true in checkReady. * Last updated 2 years ago --- # SNetworkBehaviour | NetcodePlus SNetworkBehaviour should not be added directly as a component. When you create a new script that will use networking features, you should inherit from SNetworkBehaviour instead of MonoBehaviour. Copy public class Tank : SNetworkBehaviour There are a few functions you can override #### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkbehaviour#onready) OnReady() Will be triggered only after the NetcodePlus improved connection process has completed. This function will only be called once for each object, even if you spawn/despawn it multiple times. Use this function instead of Start() if you need to wait to have all the game data up to date before initializing the object. This function can trigger even if the object is not spawned yet, and can trigger before or after OnSpawn depending on when the object is spawned. In other words, when instantiating a new object in an existing connected game, it will be called at the same time than Start() (depending on which script triggers its Start function first), but if the object exist before the connection is established, it won't be called until the connection process finishes transferring all the initialization data (see Connection Process page). #### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkbehaviour#onspawn) OnSpawn() Called right after an object is spawned. Spawning is the process of starting to sync an object between server and client. If an object is not IsSpawned, it won't be synced. If it is it will. This function will be called multiple times on the same object if the object is despawned and spawned again (Like if using the SNetworkOptimizer and going in and out of range of the object). #### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkbehaviour#ondespawn) OnDespawn() Called just before an object is despawned. It will also be called if using the Destroy() function inside SNetworkObject (not the unity Destroy() function). Since that function will make sure the object is despawned before destroying it. #### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkbehaviour#onbeforespawn) OnBeforeSpawn() Called before spawning an object (on the server side only since the object doesn't exist yet on the client). This function can be useful if you want to send some custom data with the spawn request using SetSpawnData. ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkbehaviour#spawndata) SpawnData It is possible to add custom data to a Spawn. To do this, you can write the data in OnBeforeSpawn and read it in OnSpawn Copy protected override void OnBeforeSpawn() { TowerRefreshData sdata = new TowerRefreshData(); sdata.player_id = player_id; sdata.hp = hp; SetSpawnData(sdata); } Copy protected override void OnSpawn() { TowerRefreshData sdata = GetSpawnData(); player_id = sdata.player_id; hp = sdata.hp; } The data class must be INetworkSerializable Copy public class TowerRefreshData : INetworkSerializable { public int player_id; public int hp; public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter { serializer.SerializeValue(ref player_id); serializer.SerializeValue(ref hp); } } Last updated 2 years ago --- # Effects | Dialogue Quests Effects can be added on one of the children of an Event, either on the same object as a DialogueMessage or on an empty object just for the effect. Just like dialogues, they will be executed in the order they appear. It is possible to create Events that only contain effects (with no dialogues). ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FWIZGoyKFRP9NLMjVqhKN%252FMsgEffect.png%3Falt%3Dmedia%26token%3D81ebe227-3c5f-4927-9a53-307782e076ea&width=768&dpr=4&quality=100&sign=2d810d40&sv=2) In this example, after the FirstTalk event was triggered, and after all the dialogue messages 1, 2 and 3 have been shown, the quest FollowArrow will be completed. #### [](https://indiemarc.gitbook.io/dialogue-quests/dialogue-and-quests/effects#effect-types) Effect Types **Custom Int/Float/String:** Set a custom variable for future conditions or to display with tags. **Show/Hide:** Will SetActive or not an object **Spawn/Destroy:** Will Instantiate or Destroy an object. **Actor Relation:** Add to, or set a custom value linked to a specific Actor. This doesn’t do anything by itself, but you can use that value as a condition in other events. **Start/Cancel/Complete/Fail Quest:** Changes the status of a quest. **Quest Step:** Set the step of a quest, this normally changes the text description set in QuestData. **Quest Value:** Just like Custom Ints and Actor Relation, set a custom variable but linked to a specific quest. Doesn’t do anything by itself, but can be referenced by conditions or displayed. **Start Event:** Allow you to start another event, ignoring its conditions. **Start Event If Met:** Allow you to start another event, but only if its conditions are true. Play SFX/Music: Just play a sound or start a music. Wait can add a delay before the next effect. It is possible to code your own Effects, see the scripts section. Last updated 1 year ago --- # Tags | Dialogue Quests It is possible to display variables as part of a dialogue message or as part of the description of a quest. To set the variable, use NarrativeEffects: Custom Int, Custom String, Custom Float, or Quest Value. Or alternatively, you can also call one of the functions inside NarrativeData. Copy NarrativeData.Get().SetCustomInt("kill_count", 5); To display the value in a DialogueMessage, use this tag Copy [i:kill_count] For example ![](https://indiemarc.gitbook.io/dialogue-quests/~gitbook/image?url=https%3A%2F%2F2695461605-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZ6jVzoPVfaRoTB4fAWHC%252Fuploads%252FwtePrzVVcfoHDvr5VnaU%252Ftags.png%3Falt%3Dmedia%26token%3Df0e16d8d-6098-4a89-92a9-11e4e0cc02b5&width=768&dpr=4&quality=100&sign=b1cb109f&sv=2) Here is how to display each type of variable Custom Int Copy [i:variable_id] Custom Float Copy [f:variable_id] Custom String Copy [s:variable_id] Quest Value Copy [q:quest_id:variable_id] Actor Relation Copy [a:actor_id] Last updated 1 year ago --- # Map Events | TCG Engine Roguelike Map Events define what happens when the players move to a new location on the map. There can be many different types of events that can be used. Each type of event will have a default icon that will display at the location on the map, giving a clue to the player what type of event is at the location, without totally revealing it in advance. These icons can be changed on the prefab MapLocation **Depth Min/Max**: All events can have a minimum or maximum depth you can encounter this event on the map, if both value are set to 0, that event can appear at any depth level. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/map-events#battle-events) Battle Events Events that will start a battle and load the battle scene. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FRLm6NaJfajOpF8T5ajTY%252FEventBattle.png%3Falt%3Dmedia%26token%3Da27e191b-7f31-4cf5-ade7-1fa64c9ed250&width=768&dpr=4&quality=100&sign=4250e9ed&sv=2) On this type of event you can set the scene to load (or leave it empty to use the map's default scene) and the enemies that will be in the battle. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/map-events#choice-events) Choice Events ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FWq40XdD0wUrOpL1UkqVs%252FEventChoice.png%3Falt%3Dmedia%26token%3D099928a8-dcd2-4754-aee2-f16fc70fdc49&width=768&dpr=4&quality=100&sign=e4b7f98a&sv=2) Choice events show some text to the player and let the player decide between different options. Normally each of the choices will link to another event, like an effect event or battle. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/map-events#trade-events) Trade Events Use this event to give rewards to the player or force them to lose some specific items. You don't actually need to trade anything, you can have nothing in the Spend section and only give rewards like gold or cards with this type of event. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FJKR0dJArPpdwTHuabNko%252FEventTrade.png%3Falt%3Dmedia%26token%3Dd15d681f-99bf-489b-8743-6fd7058cea2d&width=768&dpr=4&quality=100&sign=507f57c2&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/map-events#effect-events) Effect Events These events use the condition and effect system used by abilities during battles, so if you need to use an effect or check a condition about the game state, you can use this type of event. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FEWfLQooun6wjcI9kxOhr%252FEventEffect.png%3Falt%3Dmedia%26token%3Db776f257-4172-4598-9961-6780356ff4dd&width=768&dpr=4&quality=100&sign=4dab6fd3&sv=2) See the Abilities section to understand the parameters in this type of event, since they work a bit the same way. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/map-events#shop-upgrade-events) Shop / Upgrade Events These simply open the shop or upgrade panel, to buy items or upgrade your cards. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/map-events#custom-events) Custom Events It is possible to code your own map events, more info on coding your own in the scripts section. Last updated 1 year ago --- # Enable Email Sending | User Login API The NodeJS api is able to send emails, but you will need to configure your SMTP settings. First you will need to own a domain and an email that has SMTP access. Your email provider will mention the host, port and password you should use to send email with SMTP. Personally I like to use [Google Domains](https://domains.google.com/) to purchase my domains and [Mailgun](https://get.sinchemail.com/c4z1hgxt456l) for sending emails (it's free for 1000 emails per month with Pay as You Go plan). But you can use any similar provider of your choice. Open config.js and set all smtp related values: Copy smtp_enabled: true, smtp_name: "User API", //Name of sender in emails smtp_email: "contact@domain.com", //Email used to send smtp_server: "smtp.mailgun.org", //SMTP server URL smtp_port: "465", smtp_user: "contact@domain.com", //SMTP auth user smtp_password: "ABCDEFGHIJKLMNOP", //SMTP auth password The password is usually not the password you use to login to the email provider dashboard. Most of the time there will be a section to generate an API key and you should use that as password. Last updated 2 years ago --- # UI | Dialogue Quests If you want to edit the UI, you can simply open the DQUICanvas prefab, and change anything you want from there. If a panel is not visible, you can click on that panel, and on the CanvasGroup component set the alpha value to 1 so that you can see and edit that panel. Last updated 1 year ago --- # SNetworkVariable | NetcodePlus Network variables are an alternative to network actions, but achieve a very similar thing. The main difference is that the variable refresh can be executed automatically instead of having to manually call Trigger(). ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkvariable#defining-variables) Defining Variables You can define a class variable and then link it inside OnSpawn Copy private SNetworkVariable sync_state = new SNetworkVariable(); Copy protected override void OnSpawn() { sync_state.Init(this, "refresh", NetworkDelivery.UnreliableSequenced, NetworkActionTarget.Clients); sync_state.AutoRefresh(true, sync_refresh_rate); //Set the refresh rate } protected override void OnDespawn() { sync_state.Clear(); } ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkvariable#read-write-the-variable) Read / Write the variable You can access the variable value with Copy sync_state.value The reason why in the example the variable is instantiated before OnSpawn is so that .value can be accessed even if the object is not spawned. Instead we call Init() inside OnSpawn to link it to the network. ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkvariable#onreceive-onsend) onReceive, onSend You can optionally define a callback to be called whenever the variable refresh is received or sent. Copy sync_state.onReceive = OnReceive; sync_state.onSend = OnSend; ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkvariable#delivery-target-and-authority) Delivery, Target, and Authority These work exactly the same way as SNetworkActions. But unlike actions, the default values are different. Default target is All for actions and Clients for variables. Default delivery is Reliable for actions and UnreliableSequenced for variables. Authority is also based on who is the owner. Last updated 2 years ago --- # Characters | TCG Engine Roguelike All champions data and enemies data can be edited in the Resources/Characters folder, you can use Ctrl-D on a character file to duplicate it if you want to create a new one. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FdKi2lJpbd0GCETTKd2I0%252FChampionData.png%3Falt%3Dmedia%26token%3Db4ac465f-579d-49af-88d1-2bebc4845882&width=300&dpr=4&quality=100&sign=dbea7250&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/characters#id) ID the id is what is saved in the save file to know which cards a player own or which cards are in their deck. So once you choose an ID for a card, try to not change it, also try to avoid spaces or special characters in the ID. The title can be changed freely and can contain special characters (as long as your font support it). #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/characters#prefab) Prefab Link to the prefab that will be spawned during a battle. Prefab should already be setup correctly with the appropriate sprite for this character, as well as contain the characterUI. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/characters#traits) Traits Traits do not have intrinsic effects, but can be referenced by abilities. For example the Howl card has an ability "All wolves gain +1 power". This is done by adding the wolf trait to all wolf characters, and by adding the condition is\_wolf on the ability target. **Abilities** Permanant abilities that the character has during battles. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/characters#champions) Champions #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/characters#start-cards) Start Cards Cards that will be in this champion's deck at the start of the game. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/characters#unlock-cards) Unlock Cards Cards that can be earned during the adventure. Instead of referencing each card individually, you must select a class of cards. For example, the Adventurer champion can earn both Adventurer cards and Neutral cards. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/characters#enemies) Enemies ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252FSrMXrjdq8H9QsV61CfF1%252FEnemyData.png%3Falt%3Dmedia%26token%3D9d6208cc-5b3c-454e-980e-3ae708b77e2a&width=300&dpr=4&quality=100&sign=67101769&sv=2) #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/characters#behavior) Behavior Defines the enemy behavior, this is how the enemy will determine which card to play each turn. Unlike player characters, enemies have access to their whole card pool and don't have a "hand", but the card they play will be decided by their behavior. They still need enough mana to spend to play a card. Most enemies have the Random behavior, but for some (like boss battles) it can be more interesting to define a more specific behavior. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/characters#reward-gold-xp) Reward Gold/XP Gold and XP earned by the players when defeating this enemy. Last updated 1 year ago --- # SNetworkActions | NetcodePlus Network Actions allow you to sync variables or to call functions over the network. To use network actions, you must have a script that inherits from SNetworkBehaviour. Then, you need to declare: Copy private SNetworkActions actions; You need to link the behavior and Register() your actions inside OnReady or OnSpawn If you register inside OnSpawn, this means the actions will only work when the object is spawned. You should Clear() them inside OnDespawn() to avoid dupplicates if the object is spawned again. If you register inside OnReady, the actions will work locally even if the object is not spawned. And will work remotely when the object is spawned. Clear() does not need to be called since everything will be cleared when you disconnect or the object is destroyed. ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkactions#registering-actions) Registering Actions Actions that work whether the object is spawned or not Copy protected override void OnReady() { actions = new SNetworkActions(this); actions.Register("damage", DoDamage); actions.RegisterSerializable("refresh", DoRefresh); } Actions that work only when the object is spawned Copy protected override void OnSpawn() { actions = new SNetworkActions(this); actions.RegisterInt("damage", DoDamage); actions.RegisterSerializable("refresh", DoRefresh); } Copy protected override void OnDespawn() { actions.Clear(); } ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkactions#triggering-actions) Triggering Actions The Register function that you call will determine which parameter should be added to the function called on Trigger. Copy public void Damage(int damage) { actions?.Trigger("damage", 1); //Will call DoDamage(); } private void DoDamage(int damage) { hp -= damage; if (hp <= 0) Kill(); } Copy public void Refresh() { TowerRefreshData refresh = new TowerRefreshData(); refresh.player_id = player_id; refresh.hp = hp; actions?.Trigger("refresh", refresh); //Will call DoRefresh } private void DoRefresh(SerializedData sdata) { TowerRefreshData refresh = sdata.Get(); player_id = refresh.player_id; hp = refresh.hp; } ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkactions#serializeddata) SerializedData When you register your action, the function you call will determine the parameter the callback should have. For example, RegisterInt, RegisterFloat, RegisterString will callback a function with a int/float/string parameter respectively. If you want to pass more than one parameter. You must RegisterSerializable() and create a INetworkSerializable class to contain all the variables. The callback function will receive a SerializedData and you simply need to call Get<>() to get your class. Copy protected override void OnSpawn() { actions = new SNetworkActions(this); actions.RegisterSerializable("refresh", DoRefresh); } Copy private void DoRefresh(SerializedData sdata) { TowerRefreshData refresh = sdata.Get(); ... } And the data class Copy public class TowerRefreshData : INetworkSerializable { public int player_id; public int hp; public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter { serializer.SerializeValue(ref player_id); serializer.SerializeValue(ref hp); } } ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkactions#networkdelivery) NetworkDelivery When registering an action, you can select a different NetworkDelivery, this will determine if the message is Reliable or Unreliable (faster). You can also sequence messages or fragment them. Check Netcode documentation for the different type of delivery: [NetworkDelivery](https://docs-multiplayer.unity3d.com/netcode/current/api/Unity.Netcode.NetworkDelivery/index.html) For really big data, ReliableFragmentedSequenced must be used otherwise it will exceed the maximum size of a single network message. Keep in mind that ReliableFragmentedSequenced Cannot be forwarded. ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkactions#networkactiontarget) NetworkActionTarget You can also select a target, which determines who should execute the actions. For example the target All will execute the code on both the server and clients. While the target Server will execute it only on the server Copy protected override void OnReady() { actions.Register("damage", DoDamage, NetworkDelivery.Reliable, NetworkActionTarget.ServerAndSelf); actions.RegisterSerializable("refresh", DoRefresh, NetworkDelivery.Unreliable, NetworkActionTarget.Clients); } If a client (or server) triggers an action that targets itself, it will run it locally, if it targets something else, it will send the action through the network. NetworkActionTarget * All: Action will be executed on all clients and server. * Clients: Action will be executed on all clients only (not the host). * Server: Action will be executed on server only. * ServerAndSelf: Action will be executed both locally and on the server (but will not be forwarded to other clients). * Single: Single Target, use SetTarget(client\_id) to choose the target before triggering, must be triggered from server if targeting a client other than self. ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkactions#authority) Authority Trigger requests coming from clients that do not have authority will be ignored. A device has authority if it is the owner of the NetworkObject or if it is the server. Actions can still be triggered locally when the client does not have authority. The server has authority on everything. If a client with authority triggers an action that target other Clients, the server will receive it and then forward the action to all clients. (Messages cant be sent directly from client to client, and must be forwarded by the server). #### [](https://indiemarc.gitbook.io/netcodeplus/scripting/snetworkactions#example) Example Copy protected override void OnReady() { //Define all the actions here actions = new SNetworkActions(this); actions.RegisterVector(ActionType.OrderMove, DoMoveTo, NetworkDelivery.Reliable, NetworkActionTarget.All); } public void MoveTo(Vector3 pos) { //This function can be called from either the client or the server actions.Trigger(ActionType.OrderMove, pos); } private void DoMoveTo(Vector3 pos) { //Code here will be executed on both the client and server, since the target is All } Since the target is set to ALL and the server is the owner of this NetworkObject (this is decided when Spawn() is called, not from Register), the following will happen: If a client calls MoveTo(), the function DoMoveTo() will only be executed locally (since it target clients and server will ignore triggers from non-owner). If a server calls MoveTo(), the function DoMoveTo() will be executed locally on the server, AND then sent to all clients to be executed there too. Because the server has authority to send the action, and because the target is set to All. Last updated 2 years ago --- # Register and Login | User Login API ### [](https://indiemarc.gitbook.io/user-api/requests/register-and-login#registering-a-user) Registering a user Copy POST http://127.0.0.1/users/register Copy { "username": "Player", "email": "player@test.com", "password": "12345" } ### [](https://indiemarc.gitbook.io/user-api/requests/register-and-login#login) Login Copy POST http://127.0.0.1/auth Copy { "username": "Player", "password": "12345" } ### [](https://indiemarc.gitbook.io/user-api/requests/register-and-login#refresh-login) Refresh Login Refresh login can be done to extend the expiration of a token without providing your password again. You will need the access token and the refresh token of a previous login. Any access level can do this. Copy POST http://127.0.0.1/auth/refresh Copy { "refresh_token": "OGhueE8zRlcySlZRUHZkbG1U" } Header `authorization` `access_token` ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FQ4zKUC0z74Cgcop7Khts%252Fheaders.png%3Falt%3Dmedia%26token%3Db4b7d66f-6551-426d-8166-ef7fd938fe8b&width=300&dpr=4&quality=100&sign=6667f83f&sv=2) ### [](https://indiemarc.gitbook.io/user-api/requests/register-and-login#validate-token) Validate Token Can be used to just validate if your access token is still valid. Any access level can do this. Copy GET http://127.0.0.1/auth/validate Header: `authorization` `access_token` Last updated 2 years ago --- # Network Messages | NetcodePlus To send simple custom network messages you can use the functions that are inside Copy TheNetwork.Get().Messaging... These functions are using Netcode's NamedMessage in the background, but adds some extra validations. For networked objects it is recommended to NOT use direct messages, and instead use the SNetworkActions which will save you a lot of lines of code. Direct messages can be used inside generic managers or for initialization. ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/network-messages#listenmsg-and-unlistenmsg) ListenMsg and UnlistenMsg Use ListenMsg("id", callback) to listen for incoming network messages. Copy Messaging.ListenMsg("attack", ReceiveAttack); Copy Messaging.UnlistenMsg("attack"); Copy private void ReceiveAttack(ulong client_id, FastBufferReader reader) { reader.ReadValueSafe(out int damage); ... } ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/network-messages#send-vs-sendall) Send vs SendAll Send allows you to send the message to a client of your choice (if called from the server) or to send to the server (if called from client). SendAll can only be called from the server and will send to all connected clients. ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/network-messages#sendint-sendbool-sendfloat-sendbytes) SendInt, SendBool, SendFloat, SendBytes... These function are used to send basic types as the only data in the message. Copy private void Attack(int damage) { Messaging.SendIntAll("attack", damage, NetworkDelivery.Reliable); } ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/network-messages#sendobject) SendObject To send any class or struct (must inherit from INetworkSerializable). See original Netcode documentation to understand serialization: [INetworkSerializable](https://docs-multiplayer.unity3d.com/netcode/current/advanced-topics/serialization/inetworkserializable/index.html) Note that it is not possible to send GameObjects or class that contain non-serializable fields. Copy private void Attack(AttackData attack_data) { Messaging.SendObjectAll("attack", attack_data, NetworkDelivery.Reliable); } ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/network-messages#sendbuffer) SendBuffer Use this function to send a FastBufferWriter, this is the original Netcode way to use namedMessages. Make sure to Dispose() the buffer if you created a new one. Copy private void Attack(AttackData attack_data, int damage) { FastBufferWriter writer = new FastBufferWriter(128, Allocator.Temp, TheNetwork.MsgSizeMax); writer.WriteNetworkSerializable(attack_data); writer.WriteValueSafe(damage); Messaging.SendBufferAll("attack", writer, NetworkDelivery.Reliable); writer.Dispose(); } ### [](https://indiemarc.gitbook.io/netcodeplus/scripting/network-messages#forward-and-forwardall) Forward and ForwardAll Forward should only be called by the server. And allows you to resend a message you receive from a client to another client (or to all other clients). Last updated 2 years ago --- # Save File | Dialogue Quests To integrate save features into your game, you will need to call the Save() and Load() function inside NarrativeData script. You can access it with NarrativeData.Get(); All variable inside NarrativeData script will be saved, as long as they are Serializable. You can find the save file inside Unity's persistantDataPath folder. Each OS has a different path, so check here to know where: [https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html](https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html) Last updated 1 year ago --- # Get Users | User Login API ### [](https://indiemarc.gitbook.io/user-api/requests/get-users#get-all-users) Get All Users Get a list of all users. Any access level can do this, but admin will get access to more information, for example emails and permission levels are only visible to admins, password and keys are hidden to everyone. Copy GET http://127.0.0.1/users Header `authorization` `access_token` ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FsGtedH22cvu8aUnNkuS9%252Fheaders2.png%3Falt%3Dmedia%26token%3D30579e2b-f191-4b3d-95eb-22ca0b3042d1&width=300&dpr=4&quality=100&sign=d7b771a2&sv=2) ### [](https://indiemarc.gitbook.io/user-api/requests/get-users#get-one-user) Get One User Get a specific user. Just like the previous request. Admins will see more information. Copy GET http://127.0.0.1/users/:userId :userId must be replaced by a username or a user id, for example Copy GET http://127.0.0.1/users/Marc Header `authorization` `access_token` ### [](https://indiemarc.gitbook.io/user-api/requests/get-users#get-online) Get Online Get the list of active users, users are active if they logged in in the past 10 minutes. This request requires no access token, but provides no information other than the usernames. Copy GET http://127.0.0.1/online Last updated 2 years ago --- # Unity Requests | User Login API To call any request from unity, you will need to use ApiClient.cs For example, the Get Users request is: Copy GET http://127.0.0.1/users In Unity, you could do Copy private async Task GetUsers() { string url = ApiClient.ServerURL + "/users"; WebResponse res = await ApiClient.Get().SendGetRequest(url); ListResponse list = ApiTool.JsonToArray(res.data); UserData[] users = list.list; return users; } To send a post request with data in the body, you can do Copy public async Task Login(string user, string password) { LoginRequest data = new LoginRequest(); data.username = user; data.password = password; string url = ServerURL + "/auth"; string json = ApiTool.ToJson(data); WebResponse res = await SendPostRequest(url, json); LoginResponse login_res = ApiTool.JsonToObject(res.data); return login_res; } In this example the request was: Copy POST http://127.0.0.1/auth 127.0.0.1 is the api\_url you set in Resources/ApiData. Once your server is online, replace 127.0.0.1 with your server IP or server domain. See other pages for requests definitions. Last updated 2 years ago --- # Gain Rewards | User Login API Only the access levels `admin` or `server` can give rewards. In the base template there are only XP and coins values as example. But by editing the code you could add any data you like to the users schema. Copy POST http://127.0.0.1/users/rewards/gain/:userId Replace `:userId` by the ID of a user like `63cf123e98f493e8c` Copy { "refreshToken": "OGhueE8zRlcySlZRUHZkbG1U" } Header `authorization` `access_token` Last updated 2 years ago --- # Status | TCG Engine Roguelike Status are ongoing effects or skills afflicted to a card or character. If you want an ability that grants a new permanent bonus or bonus that last for a few turns, it needs to be a status. Exampled of status in the demo are: Poisoned, Silenced, Paralyzed... Abilities can give status with a value. If the status is set to "auto-reduce" the value will reduce by 1 at the start of each turn of the afflicted character. When the value reaches 0 the status is removed. Since the effect of status are more varied and don't have specific timing like abilities, they are coded directly in the BattleLogic.cs for each status (each one shouldn't take more than 2-3 lines of code). If you want to add new status you will need to edit the core rules in that script. Last updated 1 year ago --- # Abilities | TCG Engine Roguelike Abilities can be found in the Resources/Abilities folder. They can be assigned to cards or characters to give them special power. The engine is also made in a way to make it easy to code your own abilities. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2F82X4eOusdxuRNs5GNF7l%2Fability_Data.png&width=300&dpr=4&quality=100&sign=51342e05&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/abilities#trigger) Trigger Determines WHEN the ability will be resolved. **Ongoing:** Always active as long as this card is in play. (Ongoing only works with a limited number of effects such as status and stat bonus). Ongoing abilities bonus are recalculated any time there is a state change. These would only work if the ability is attached to something that stays in play such as a power card or character. **On Play**: Resolved when the card is played from your hand. **On Play Other**: Resolved when this card is already in play (power card or character) and another card is played. Usually this type of trigger will have some trigger conditions. **On Drawn**: Resolved when the card is drawn into your hand. **Start/End of Turn:** Resolved once every turn, during your turn. **On Death**: When the character with this ability dies. **On Damaged**: When the character with this ability is damaged. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/abilities#trigger-condition) Trigger Condition Ability won't trigger unless all the trigger conditions are met. For example, you could have an "OnPlay" ability that only triggers if the player has less than 10 health, or a Start of Turn ability that triggers only if you have 5 cards on the board.. There are many conditions already available in the Resources/Condition folder, but you can also code your own. (See the scripts section). ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/abilities#target) Target Determines WHO is affected by the ability? There are 3 different categories of possible target: * Cards * Characters * Board Slots And different targets you can choose form: * **Card Self:** The card with this ability * **Character Self:** The character who played the card * **All Characters:** All characters currently in the battle. * **All Cards Hand:** All cards in all character's hand. * **All Cards All Piles:** All existing cards, in hand, deck, discard or power area. You will usually want to use some target conditions to filter only the deck or discard or other. * **All Slots:** All slots on the board, whether they are empty or occupied. Usually used for summon abilities. * **All Card Data:** All existing card data in the game (scriptable objects), this is usually used to instantiate new cards (like discover effect), since it doesn't represent an existing card in the game, but only the data of the card. * **Play Target:** When playing a spell, you will be asked to drag the spell directly on top of a target when playing it. Use only for spells. * **Ability Triggerer:** The card that caused the ability to be triggered. This is usually the same than the caster (self) but for some Triggers it is not. For example, OnPlayOther has a different triggerer than the caster. * **Select Target:** Player will be asked to click on a target character of his choice on the board. * **Card Selector:** A menu will open to let the player select a card as target. This is useful for abilities that let you retrieve a card from your discard or deck. Choice of cards can be refined with target condition. * **Choice Selector:** A menu will open to let the player choose between a few different abilities. If you use this, place the choice abilities under chain\_abilities array. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/abilities#target-conditions) Target Conditions This is really useful to target multiple cards (but not all) or to limit the choices of the player. For example, if you want an ability that says "All wolves gain +1 attack", the Target would be "All Characters", and the target condition "Is Wolf". Another example would be a skill that let you take an adventurer spell from your discard. The Target would be "Card Selector", and the target conditions would be "Is Adventurer" and "Is Spell" (You also need to add "Is Ally" and "Is In Discard" with the card selector, otherwise it will show cards in your deck and your opponent deck/discard). #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/abilities#target-filters) Target Filters Target filters are a bit more complex and slightly less performant than conditions, since they involve manipulating arrays instead of just a bool check. But they are a lot more flexible when you want to target multiple targets with a more global condition instead of a condition that is only checked on each individual target. For example targets filters could be used to target X number of random targets on the board, or to target the card with the highest hp, cards that have duplicates, etc.. This is done by targeting AllCharacters and then adding a filter that will use all board cards as source and only add the new targets into the destination array. Filters also work with AllCards and AllSlots. More info on this will be added to the Scripts section. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/abilities#effect) Effect Determines WHAT will happen to the targets when the ability is resolved. Several effects are already available in the Resources/Effects folder. If an effect has a parameter and you want to use it with different values, you can simply duplicate one effect with Ctrl-D. Effects can also be coded easily like conditions, by creating your own scripts. See the scripts section to know how to code your own effects. A value and duration can be passed to each effect. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/abilities#chain-abilities) Chain Abilities Some more complex abilities could have multiple effects, each with different targets and conditions, but that are all triggered by the same thing. To simplify the creation of these more complex abilities, you can instead create multiple abilities, and only the first one will have a trigger. Set the trigger to None on the other ones. And only attach the first ability on your card. Then, on that first ability, add the other abilities into the chain\_abilities array. This means those abilities will be triggered immediately after the first one, whenever it is triggered. This array is also used when using the Choice Selector. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/abilities#undefined) Last updated 1 year ago --- # Custom Conditions | Dialogue Quests If you want to create new effects or conditions, you can create a new script that inherits from ConditionData or EffectData, and override one of the functions. ### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/custom-conditions#conditions) Conditions For example, let's create a new condition that checks how many quests have been completed by the player: ConditionQuestCount.cs Copy using UnityEngine; using DialogueQuests; [CreateAssetMenu(fileName = "condition", menuName = "DialogueQuests/Conditions/QuestCount", order = 10)] public class ConditionQuestCount : ConditionData { public override bool IsMet(NarrativeEvent evt, NarrativeCondition condition, Actor player, Actor triggerer) { //Loop and count completed quests int count = 0; foreach (QuestData quest in QuestData.GetAll()) { if (quest.IsCompleted()) count++; } //Use int operator to compare the number of quests to value_int return condition.CompareInt(count, condition.value_int); } public override bool ShowValueInt() { return true; } public override bool ShowOperatorInt() { return true; } public override string GetLabelValueInt() { return "Nb Quests"; } } The loop will count all the completed quests, then the compare int will compare the amount of completed quest to the operator and value defined in the scriptable object data file. The other function explains which value should be visible in the unity inspector. In our case, a int value, and the int operator (to select between: less, greater, equal, not equal...). You can also define the labels that will appear in the unity inspector. ### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/custom-conditions#data-files) Data Files We will now create the data files for the condition we just created. In Unity, right click inside a folder (the other conditions are in the Resources folder), and select Create -> DialogueQuests -> Conditions, select your new condition, it should be named what you set in the tag \[CreateAssetMenu\] in your new script. You can now add the condition to any dialogues or events, using the NarrativeCondition component. ### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/custom-conditions#other-values) Other Values If you want to see the list of possible values that can be displayed in the inspector for effects, open the ConditionData.cs script and you will see all the available functions that can be overridden. Last updated 1 month ago --- # Activity | User Login API In the code, you can keep records of requests that have been called. By default, an activity log is stored for register, gain reward, and set permission. An ADMIN can access the list with: Copy GET http://127.0.0.1/activity Last updated 2 years ago --- # Support and Community | NetcodePlus Any questions, suggestions or bugs? Come join our Discord community, and ask your questions. We will try to help guide you to do what you are trying to achieve. Discord: [https://discord.gg/JpVwUgG](https://discord.gg/JpVwUgG) Last updated 2 years ago --- # Edit Users | User Login API All request on this page require the same header Header `authorization` `access_token` ### [](https://indiemarc.gitbook.io/user-api/requests/edit-users#edit-user) Edit User Function that let you edit your own personal information like avatar (and potentially other values like name, quote, banner). Does not let you change values that would let you cheat like coins, xp... Admins can edit anyone, other users can only edit themselves. Copy POST http://127.0.0.1/users/edit/:userId Replace `:userId` by the id of a user like `63cf123e98f08f4f18493e8c` Copy { "avatar" : "test" } ### [](https://indiemarc.gitbook.io/user-api/requests/edit-users#edit-permission-level) Edit Permission Level Only admins can change permissions levels Copy POST http://127.0.0.1/users/permission/edit/:userId Copy { "permission_level" : 5 } **10:** admin, can do everything, including assigning permissions **5:** game server, can give rewards, read/validate other users **1:** regular user, some information about other users are hidden (such as email), cannot give rewards, can only edit his own information **0:** deactivated user, use for banning users. Cannot do anything. ### [](https://indiemarc.gitbook.io/user-api/requests/edit-users#change-password) Change Password Any user can only change their own password. Copy POST http://127.0.0.1/users/password/edit Copy { "password_previous": "test", "password_new": "12345" } ### [](https://indiemarc.gitbook.io/user-api/requests/edit-users#reset-password) Reset Password Can be used as a forgotten password feature. Does not require an access token. Copy POST http://127.0.0.1/users/password/reset Copy { "email": "email@test.com" } A email will be sent with a recovery code if the user exists. You will need to setup your SMTP inside config.js to let your API send emails. To confirm, another request must be called with the code Copy POST http://127.0.0.1/users/password/reset/confirm Copy { "email": "email@test.com", "code": "GVTNYKEA", "password": "123456" } Email is inputted again for verification purposes. The code is the one sent by email. And password is the new password you want to set so it can be anything. Last updated 2 years ago --- # AI | TCG Engine Roguelike In Tcg Engine Roguelike edition, the AI works based on defined behaviors assigned to each enemy. The behavior determines which card and which target they select during their turn. Enemies (unlike player characters) have access to all the cards in their deck. Most basic enemies will just have the "random" behavior, which just picks a random card from the deck and plays it. But for more complex enemies like a boss, other behaviors can be defined. For example you could have an enemy that only attacks the character with the lower hp, or an enemy that plays basic attack, and switches to more powerful attacks when having lost half of its HP. New behavior can be coded, more info in the Scripts section. Last updated 1 year ago --- # Contacts/Friends | User Login API Can be used as a friend list for each user. Use these functions to add/remove users to someone's list. Users can only add/remove contacts on their own account. To accept/reject a friend request, you also use the same add/remove functions. All requests in this page require the same header Header `authorization` `access_token` ### [](https://indiemarc.gitbook.io/user-api/requests/contacts-friends#add-contact) Add Contact Copy POST http://127.0.0.1/users/friends/add Copy { "username" : "player" } ### [](https://indiemarc.gitbook.io/user-api/requests/contacts-friends#remove-contact) Remove Contact Copy POST http://127.0.0.1/users/friends/remove Copy { "username" : "player" } ### [](https://indiemarc.gitbook.io/user-api/requests/contacts-friends#get-contact-list) Get Contact List Copy GET http://127.0.0.1/users/friends/list Last updated 2 years ago --- # Custom Effects | Dialogue Quests If you want to create new effects or conditions, you can create a new script that inherits from ConditionData or EffectData, and override one of the functions. ### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/custom-effects#effects) Effects For example, let's create a new effect that destroy all the Actor near the player: EffectDestroyNearby.cs Copy using UnityEngine; using DialogueQuests; [CreateAssetMenu(fileName = "condition", menuName = "DialogueQuests/Effects/DestroyNearby", order = 10)] public class EffectDestroyNearby : EffectData { public override void DoEffect(NarrativeEvent evt, NarrativeEffect effect, Actor player, Actor triggerer) { if(player != null) { foreach(Actor actor in Actor.GetAll()) { float dist = (actor.transform.position - player.transform.position).magnitude; if(actor != player && dist < effect.value_float) { GameObject.Destroy(actor.gameObject); } } } } public override bool ShowValueFloat() { return true; } public override string GetLabelValueFloat() { return "Range"; } } The effect will loop on all actors and check the range with the player who triggered the event, if the actor isn't the player and is also within the range, it will be destroyed. The other function defines which values should appear in the unity inspector, in this case it is only a float value named Range. ### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/custom-effects#data-files) Data Files We will now create the data files for the effect we just created (the other effects are in the Resources folder). And then Link it to the ability. In Unity, right click inside a folder, and select Create -> DialogueQuests-> Effects, select your new effect, it should be named what you set in the tag \[CreateAssetMenu\] in your new script. You can now add the effect to any dialogues or events, using the NarrativeEffect component. ### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/custom-effects#other-values) Other Values If you want to see the list of possible values that can be displayed in the inspector for effects, open the EffectData.cs script and you will see all the available functions that can be overridden. Last updated 1 month ago --- # Scripts Overview | Dialogue Quests Here is an overview of the main scripts in DQ. #### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/scripts-overview#narrativemanager.cs) NarrativeManager.cs Main manager script for the DQ asset, it should be part of the DQ Manager prefab and contain various functions to start/stop an Event or to start/stop quests. Access with NarrativeManager.Get() #### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/scripts-overview#narrativedata.cs) NarrativeData.cs Contains all the data that can be saved, when calling the Save() function inside that script, all the variables inside the NarrativeData class will be serialized to a save file. It contains the status of quests, the list of events that have been triggered, and other useful data like custom variables that have been set. Access with NarrativeData.Get() #### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/scripts-overview#theaudio.cs) TheAudio.cs Audio Manager that can be used to play sfx or music, by calling functions like PlaySFX or PlayMusic. #### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/scripts-overview#dialoguepanel.cs) DialoguePanel.cs UI script for displaying dialogues when they are playing QuestPanel.cs UI script for displaying quests when the quest journal is opened Components All the components discussed in the previous section of this doc, should have the same script name as its respective component. #### [](https://indiemarc.gitbook.io/dialogue-quests/scripts/scripts-overview#undefined) Last updated 1 year ago --- # In Control | Dialogue Quests Integration with InControl 1. Import both assets 2. If there are no compile errors, the "Scripting Define Symbol" IN\_CONTROL should be added automatically to the player settings. If not, add it manually. 3. Import the InControl package in Upgrades folder 4. Attach the script to the Manager prefabs (Prefabs/DQManager) 5. Connect a USB gamepad such as Xbox One controller, and run the game! Last updated 1 year ago --- # New Input System | Dialogue Quests Integration with the New Input System Gamepad 1. Import Dialogue and Quests 2. Install Unity Input System in the package manager 3. In BuildSettings->PlayerSettings, set the Active Input Handling to Both 4. Import the NewInputSystem package in Upgrades folder 5. Attach the script to the Manager prefabs (Prefabs/DQManager) 6. Connect a USB gamepad such as Xbox One controller, and run the game! Last updated 1 year ago --- # Survival Engine | Dialogue Quests Integration with Survival Engine or Farming Engine 1. Import Survival Engine (or Farming Engine) first (v1.10+) 2. Import Dialogue and Quests 3. If there are no compile errors, the "Scripting Define Symbol" DIALOGUE\_QUESTS should be added automatically to the player settings. If not add it manually. 4. Make sure the DQManager prefab is in the scene, and that you add the Actor script to the PlayerCharacter! Then everything should work! 5. Optional but strongly recommended: Download the Demo package, it contains a demo scene to show how the two assets work together. (Available on Discord Sharing channel) 6. Open demo the scene in the DialogueQuestsDemo folder and try it! For a tutorial on how to integrate DQ with the networked features of Survival Engine online, please visit my discord server for additional resources to help you with that (You will find it under the Sharing channel) [https://discord.com/channels/407995895196418048/1037493215152058468](https://discord.com/channels/407995895196418048/1037493215152058468) Last updated 1 year ago --- # Filters | TCG Engine Roguelike Filters works in a similar way as conditions, and also help determine the targets of an ability. A filter always has a source array and a destination array (containing either Cards, Characters or Slots), and the function should add the valid targets to the destination array and return it. The advantage of filters is that they are a bit more flexible than conditions, but are also less performant and more complex (because of array manipulation). Filters also cannot be used for the trigger or for some targets that let the player make a selection. Filters are best used with the All Cards, All Characters or All Slots targets. In this example, the filter is used to find the character that has the highest hp. The ability target is set to All Characters, which means the source array contains all the cards on the board. And destination array will contain only the cards with the highest attack. Copy using System.Collections; using System.Collections.Generic; using UnityEngine; using TcgEngine; [CreateAssetMenu(fileName = "filter", menuName = "TcgEngine/Filter/HighestHP", order = 10)] public class FilterHighestHP : FilterData { public override List FilterTargets(Battle data, AbilityData ability, BattleCharacter caster, Card card, List source, List dest) { //Find highest hp value int highest= 0; foreach (BattleCharacter character in source) { int hp = character.GetHP(); if (hp > highest) highest = hp ; } //Add all highest (more than one card can be targeted) foreach (BattleCharacter character in source) { int hp = character.GetHP(); if (hp == highest) dest.Add(character); } return dest; //Return all characters with highest HP } } Similar to conditions and effects, you need to create a scriptable object from the Create->TcgEngine menu. Filters can be added on the ability data inside the filters\_target array. Last updated 1 year ago --- # NetcodePlus Integration | User Login API You can integrate this User API with NetcodePlus or Survival Engine Online. To do so, import both assets into your project. Follow the steps of each asset to install the NetcodePlus Server and the User Login Web API Once everything works individually, you can enable User API login by going into Resources/NetworkData And change the Authentication type ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FwHD5e8aXhTtLtNOXUMcB%252Fnetworkdata.png%3Falt%3Dmedia%26token%3Da126a4a9-6b4c-4e87-b4f6-ebbaf0f0145b&width=300&dpr=4&quality=100&sign=a2bda5c9&sv=2) Also make sure that all your ApiData config are set properly and that your server and database are running. In this example the api is running locally. But it can be a on a remote server as well. ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FkFzkSzA2vjFRGXCOjpsH%252Fapi-data.png%3Falt%3Dmedia%26token%3D7abd8b25-9360-4edd-9c8e-fc52048d54dd&width=300&dpr=4&quality=100&sign=cf213722&sv=2) Open the MenuLobby scene and add the ApiManager prefab to it. Also, enable the hidden password field in the scene. ![](https://indiemarc.gitbook.io/user-api/~gitbook/image?url=https%3A%2F%2F2041776644-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FEwpSlXwezgSjDYM49YiR%252Fuploads%252FXPdxosSieIjMJLah5tAC%252Fpassword-field.png%3Falt%3Dmedia%26token%3D74eced72-1f30-43bc-9d8d-c12d0b2adff3&width=300&dpr=4&quality=100&sign=1282bc26&sv=2) Run the scene and try to login with your username / password. You should also add the ApiManager to your other scenes, it can be added inside another manager prefab that you use in your game scenes. For other features such as editing your account, you will need to integrate the ui into your Netcode project. But you can use the UserLogin demo as example of how to do this, depending on which features you need. Last updated 2 years ago --- # Conditions and Effects | TCG Engine Roguelike If you want to create new effects or conditions for your card abilities, you can create a new script that inherits from ConditionData or EffectData, and override one of the functions. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/scripts/conditions-and-effects#effects) Effects For example, let's create a new card ability effect to return all your cards into your deck, shuffle it, and then redraw the same number of cards. Create a new script called EffectRedrawHand.cs with: Copy using UnityEngine; using TcgEngine; using TcgEngine.Gameplay; [CreateAssetMenu(fileName = "effect", menuName = "TcgEngine/Effect/RedrawHand", order = 10)] public class EffectRedrawHand : EffectData { public override void DoEffect(BattleLogic logic, AbilityData ability, BattleCharacter character, Card card, BattleCharacter target) { int nb_cards = target.cards_hand.Count; //Store number of cards in hand target.cards_deck.AddRange(target.cards_hand); //Add hand cards to your deck target.cards_hand.Clear(); //Empty hand array logic.ShuffleDeck(target.cards_deck); //Shuffle Deck logic.DrawCard(target, nb_cards ); //Redraw Hand } } Notice in the definition of the function, the target is a BattleCharacter, this means we will need to select a character target (like CharacterSelf or AllCharacters) when creating the ability. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/scripts/conditions-and-effects#conditions) Conditions Now lets say we want the player to only use this ability if they have at least 3 cards in hand. We can create a condition for it. Create a new script called ConditionHandCount.cs Copy using UnityEngine; using TcgEngine; [CreateAssetMenu(fileName = "condition", menuName = "TcgEngine/Condition/CountHand", order = 10)] public class ConditionCountHand : ConditionData { public int value; public override bool IsTriggerConditionMet(Battle data, AbilityData ability, BattleCharacter character, Card card) { int nb_cards = character.cards_hand.Count; return nb_cards >= value; } } ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/scripts/conditions-and-effects#data-files) Data Files We will now create the data files for the effect we just created. And then Link it to the ability. In Unity, right click inside a folder, and select Create -> TcgEngine -> Effects, select your new effect, it should be named what you set in the tag \[CreateAssetMenu\] in your new script. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2FrB7krGGzOzA277jtO6eG%2FCreateEffect.png&width=300&dpr=4&quality=100&sign=f0dc6fd&sv=2) Do the same thing with your new condition, and set the value to 3. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2F2BYzsHAHUc7rwKMRx0iT%2Fblobs%2FfGNYM6o5quYvNO0SgjWi%2Fhand_card.png&width=300&dpr=4&quality=100&sign=f2c39eb8&sv=2) Now in Resources/Abilities, create a new ability, you can duplicate an existing one to make it faster with Ctrl-D Set these settings on the ability ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252F0JZhyGy4YSguiqw7PWsY%252Fredraw_hand.png%3Falt%3Dmedia%26token%3D95d5362a-326b-4c23-be94-e4a3126bba12&width=300&dpr=4&quality=100&sign=2f820189&sv=2) You can now add that ability to any card, this will give the card a new ability that when played, if you have 3 or more cards in hand, will shuffle back your hand into the deck and redraw the same number of cards. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/scripts/conditions-and-effects#trigger-condition-vs-target-condition) Trigger Condition vs Target Condition A trigger condition will be checked to know if the ability should trigger or not, while a target condition will be checked to see if a target is valid. If trigger conditions are true, the ability will be resolved (mana/action will be spent, fx will appear). The target condition is checked for each individual target after the ability was already triggered. For example if you have an ability that you can cast when you have 5 HP or less and that affects ALL blue cards on the board, 5 HP would be a trigger condition, while "is blue" would be a target condition. When creating a new script, use IsTriggerConditionMet for trigger conditions and use IsTargetConditionMet for target conditions. And place the condition in the appropriate array on the ability. Target conditions can be defined with 3 different types of targets: Card, Player or Slot. Last updated 1 year ago --- # Map Events | TCG Engine Roguelike You can create your own Map Events if the existing ones are not doing what you'd like to do. Or you can edit existing ones. They can be found in Scripts/Events folder. Map events will be activated AreEventsConditionMet : Will check if the event can be done. This function can be especially useful for events that are triggered by a choice event. The choices that return a false condition will not be displayed in the list of choices for the event. DoEvent: The code executed when the players move to that location and the event start. Let's create an example event that gives a random card to a champion. If the championhas less than 10 cards in their deck. Since this example is not linked to any UI, it would best be used as choice when selecting from an EventChoice. Or as chain event after an EventText. Copy [CreateAssetMenu(fileName = "Special", menuName = "TcgEngine/MapEvent/Special", order = 10)] public class EventSpecial : EventData { public override bool AreEventsConditionMet(World world, Champion champion) { return champion.cards.Count < 10; } public override void DoEvent(WorldLogic logic, Champion champion) { int seed = logic.WorldData.GetLocationSeed(1234); //Use seed-based randomization, so the result is based on seed selected in menu System.Random rand = new System.Random(seed); List cards = CardData.GetRewardCards(champion.ChampionData.team); //List of champions cards that can be unlocked CardData card = cards[rand.Next(0, cards.Count)]; //Get Random card champion.AddCard(card); } } Then, like other scriptable objects, you would need to create the data file for this event in the Resources folder by right click - TcgEngine/MapEvent/Special. Last updated 1 year ago --- # Custom Code and Data | User Login API Here is a quick explanation of the different javascript code files and where to go to change things. ### [](https://indiemarc.gitbook.io/user-api/other/custom-code-and-data#users.model.js) users.model.js Contain the schema variables for the database. If you want to add new values, you need to add them here inside the schema at the start of the file. For more information, check mongoose doc: [https://mongoosejs.com/docs/guide.html](https://mongoosejs.com/docs/guide.html) ### [](https://indiemarc.gitbook.io/user-api/other/custom-code-and-data#users.controller.js) users.controller.js Contains the code logic that happens when a request is called. Usually those functions will have a request and response as parameter and will call Copy return res.status(204).send(data); To return the status code and json data to the client. ### [](https://indiemarc.gitbook.io/user-api/other/custom-code-and-data#users.routes.js) users.routes.js contain all the requests definitions and comment on parameters they should have in the body or in Copy app.get("/users", [\ AuthTool.isValidJWT,\ AuthTool.isPermissionLevel(USER),\ UsersController.list,\ ]); This functions defines the `https://yourapi.com/users` request. And will return the list of all users. ### [](https://indiemarc.gitbook.io/user-api/other/custom-code-and-data#example-of-adding-variables-to-the-code) Example of adding variables to the code Let's say we want to add a description variable and a gem variable. In the model.js file, add this inside the schema Copy desc: {type: String, default: ""}, gem: {type: Number, default: 0}, The description is just some text the user can add to their account, since they are allowed to change it themselves, we will add it to the edit user function (where we change the avatar). The gems variable should not be edited by the users because it represent a currency they own, so only the server should be able to give it to users. For this reason we will add it to the rewards request. users.controller.js, editUserAccount function Copy var avatar = req.body.avatar; var desc= req.body.desc; Copy if(avatar && typeof avatar !== "string") return res.status(400).json({error: "Invalid avatar"}); if(desc&& typeof desc!== "string") return res.status(400).json({error: "Invalid description"}); Copy //Change Avatar if(avatar) userData.avatar = avatar; //Change Description if(desc) userData.desc = desc ; users.controller.js, gainReward function Copy var coin = req.body.coin || 0; var xp = req.body.xp || 0; var gem = req.body.gem || 0; Copy if(coin && typeof coin !== "number") return res.status(400).json({error: "Invalid parameters"}); if(xp && typeof xp !== "number") return res.status(400).json({error: "Invalid parameters"}); if(gem && typeof gem !== "number") return res.status(400).json({error: "Invalid parameters"}); Copy user.coin += coin; user.xp += xp; user.gem += gem; In Unity, inside ApiMsg.cs you will need to edit the class EditUserRequest and GainRewardRequest to add the new variables. Last updated 2 years ago --- # Scripts Overview | TCG Engine Roguelike ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/scripts/scripts-overview#important-scripts) Important Scripts If you're planning on editing the code. A good place to start with is everything inside the Scripts/GameLogic folder. **WorldLogic.cs and BattleLogic.cs** Is probably one of the most important scripts. Defines all the core gameplay logic and game rules. It is run by the server or host. WorldLogic is for everything that happens outside of battles (map events, moving on the map, game setup...), while BattleLogic is for battles. Game Actions are sent by the GameClient.cs, and received by the GameServer.cs to then be executed by WorldLogic/BattleLogic, GameServer connects to callbacks, to know when it should send a refresh to all clients. I would strongly suggest to edit directly this script to create your own rules, and not try to change the game rules by creating a separate script. This will keep your project simpler in the long term, and you probably won't need to update this script to future version of the engine so much since it doesn't contain anything related to systems like networking message, ui, visuals or other. It is purely game rule logic. If you edit the code, do not access this script directly from a client-side script, and do not try to change the visuals or run audio fx from there, since this script is run by the server and AI and not the client. Namespaces serve as a reminder (client side scripts are in a different namespace than server ones). #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/scripts/scripts-overview#world.cs-battle.cs-player.cs-character.cs-card.cs-slot.cs) World.cs Battle.cs Player.cs Character.cs Card.cs Slot.cs Contains data for the current state of the game, World.cs is the data sent to clients during a network refresh (and it contains everything related to the current state of the game). One of the variable inside World.cs is Battle, during battles, only this needs to be refresh as it contains the whole state of the current battle. World.cs is also the class that will be serialized to a file when saving the game. If you need to add new stats to your cards, you will need to edit Card.cs (as well as edit CardData.cs). Unlike CardData.cs which represent the card original fixed stats, Card.cs represent the current state of a card (with edited values, status effects, owner, and position). So a stat that never changes during the game (such as the card rarity) do not need to be added to Card.cs and can only be added to CardData.cs. But a stat that can be affected by abilities (attack) need to be in both scripts. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/scripts/scripts-overview#boardcharacter.cs-handcard.cs-boardslot.cs) BoardCharacter.cs, HandCard.cs, BoardSlot.cs All scripts in GameClient folder are usually just the visual representation of the data. So for example, BoardCharacter.cs will take the values contained in Character.cs and display it with sprites and ui text. These scripts are never relevant to the AI, GameLogic or Server, since their only role is to display the data received from the server. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/scripts/scripts-overview#mapui.cs-battleui.cs) MapUI.cs, BattleUI.cs Main scripts for the in-game UI. MapUI.cs is for the map scene. While BattleUI is for the battle scenes. #### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/scripts/scripts-overview#gameclient.cs) GameClient.cs Main script for the client side of the game, this script is only in the game scenes. It will connect to the server and send the various actions executed by the player, it will also receives refresh from the server, update the state, and let the other client-side scripts update what is shown on the board. LobbyClient.cs This is the client script but for the menu. It will connect to the server to find other players if using the lobby features. **ServerManager.cs and GameServer.cs** Main scripts for the server, ServerManager is the top-level script that will receive connections, client messages and redirect them to the appropriate game, if a server run multiple games at the same time, it will contain a list of GameServer, each with a different UID, and each network message received will be sent to the correct game server instance. There is also a script ServerManagerLocal.cs which simulates the server in local when playing in solo, this one only contain 1 GameServer instead of a list. Last updated 1 year ago --- # Enemy Behaviors | TCG Engine Roguelike Enemy behaviors determine how enemies select the cards to play. The behavior should normally be predictable so that the intent can be shown to the player. If randomization is needed, its best to make it based on the location seed and the current turn, so that the intent is calculated the same way as the actual action. To create a new behavior, you can duplicate one of the behavior scripts The first function is the most important, because its what determines which card will be played, the other 3 functions are only used for card abilities that ask the enemy to make a selection. The list of cards or characters, will already only contain the VALID targets, so you don't need to check again if the target is valid, only to check which one you want to prioritize. Let's try to create a new behavior example that make the enemy attack the character with the lowest health, and use the ability that deals the most damage. Copy [CreateAssetMenu(fileName = "behavior", menuName = "TcgEngine/Behaviors/LowHP", order = 20)] public class BehaviorLowHP : BehaviorData { public override Card SelectPlayCard(Battle data, BattleCharacter character, List cards, int turn) { //Find card with highest damage int highest = 0; Card target = cards.Count > 0 ? cards[0] : null; //Play first card if no card deals damage foreach (Card card in cards) { foreach (AbilityData ability in card.GetAbilities()) { int damage = card.GetAbilityValue(character); if (ability.HasEffect() && damage > highest) { target = card; highest = damage; } } } return target; } public override BattleCharacter SelectCharacterTarget(Battle data, BattleCharacter character, Card card, List characters, int turn) { //Find lowest HP int lowest = 9999; BattleCharacter target = null; foreach (BattleCharacter tcharacter in characters) { if (tcharacter.GetHP() < lowest) { lowest = tcharacter.GetHP(); target = tcharacter; } } return target; } public override Card SelectCardTarget(Battle data, BattleCharacter character, Card card, List cards, int turn) { return GetRandomCard(data, character, cards, turn); } public override Slot SelectSlotTarget(Battle data, BattleCharacter character, Card card, List slots, int turn) { return GetRandomSlot(data, character, slots, turn); } public override string GetBehaviorText() { return "Attacks the champion with lowest health"; } } Then, like other scriptable objects, you would need to create the data file for this event in the Resources folder by right click - TcgEngine/Behaviors/LowHP. Then you would need to link the behavior to an enemy data. Last updated 1 year ago --- # Support and Community | User Login API Any questions, suggestions or bugs? Come join our Discord community, and ask your questions. We will try to help guide you to do what you are trying to achieve. Discord: [https://discord.gg/JpVwUgG](https://discord.gg/JpVwUgG) If you need to contact me you can do it from my website: [https://indiemarc.com/](https://indiemarc.com/) Also, if you like the asset, you can leave a review on Unity. Would be really great! Last updated 2 years ago --- # Cards | TCG Engine Roguelike All cards can be edited in the Resources/Cards folder, you can use Ctrl-D on a card file to duplicate it if you want to create a new one. ![](https://indiemarc.gitbook.io/tcg-engine-roguelike/~gitbook/image?url=https%3A%2F%2F2996529479-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F2BYzsHAHUc7rwKMRx0iT%252Fuploads%252Fee8WIZ4uPjo0v0YLHrQU%252FCardData2.png%3Falt%3Dmedia%26token%3D802b5547-0d3e-43c6-bec0-a7fee68cc5d9&width=300&dpr=4&quality=100&sign=2a85f420&sv=2) ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/cards#id) ID the id is what is saved in the save file to know which cards a player own or which cards are in their deck. So once you choose an ID for a card, try to not change it, also try to avoid spaces or special characters in the ID. The title can be changed freely and can contain special characters (as long as your font support it). ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/cards#type) Type There are currently 4 card types in the engine: * Card: Regular card that can be earned and added to your deck. * Item: When acquired, will go into your champion inventory instead of your deck. Items are represented by CardData as well because they work the same way as cards in the game logic during battles. There are 3 types of items: * Quest: Will be in your inventory but cannot be used during battles. * Consumable: Will appear at the top of UI during battles and can be consumed. When a player does, its ability will trigger as if it was a card played. * Equipment: Will be added to your deck during battles, just like other cards. The difference with a regular card is that it will also appear in your inventory, so they can be sold at a shop. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/cards#battle-type) Battle Type The battle type will determine the card behavior when played during a battle. * Spell: One time effect, the card is discarded after played * Power: Card does not go into discard, instead it goes into power zone and has permanant effect for the rest of the battle. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/cards#abilities) Abilities References to the abilities this card has. See ability section for more details. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/cards#upgrade-stats) Upgrade Stats Level Max: Maximum level this card can be upgraded to. Upgrade Mana: cost modification to play this card, for each level this card was upgraded. ### [](https://indiemarc.gitbook.io/tcg-engine-roguelike/files-and-data/cards#intent) Intent Can be left empty for most player cards. For enemy cards, will define what type of icon will appear above the enemy head when the enemy intends to play this card. Last updated 1 year ago --- # Managers and Important Scripts | NetcodePlus Managers and Important Scripts | NetcodePlus --- # Unity Requests | User Login API Unity Requests | User Login API --- # Custom Code and Data | User Login API Custom Code and Data | User Login API --- # Support and Community | NetcodePlus Support and Community | NetcodePlus ---