-
Notifications
You must be signed in to change notification settings - Fork 3
Custom Scripting Guide
As this guide is advanced, it's recommended to check every other wiki pages before this one.
Bane Of Wargs can be easily modded and there is quite a lot of possibilities. But custom scripts allows the game engine to be even more modular, allowing plugins to have no limits of what's possible to do. Custom scripts let you interact with the game engine, how the regular game data won't allow you. Custom scripts are python scripts, as the game engine is coded in python, that allow you to interact with the game engine by importing the game engine's many class and functions, and by importing major game variables. Currently, there is two ways to get a custom script triggered: in dialogs and events and when using utility items. This guide contains every bit of information about custom scripting, going from the explanation of every class of the game engine, and how to create custom scripts properly. You can find many examples of game custom scripts here.Note that you wanna have a basic understanding of python to create custom scripts.
Custom scripts are placed under the scripts/
directory, in the root. You can name your script pretty much however you want. Once you create it, you wanna create a basic function, that you then run at the very last line of your script:
def run():
print("Hello !")
# Run the action
run()
This simple script will print Hello !
to the UI. Note that the game engine doesn't use print functions, and it has its own print function, that has some functionalities and improvements, as printing faster and formatting numbers (same for the input function):
from terminal_handling import cout, cinput # import game engine console functions
def run():
cout("Hello !")
cinput("How are you?")
# Run the action
run()
The script will now print Hello !
to the console, and ask how the player is. We can upgrade the script by making a choice menu, and make the script respond differently, following the choice:
import terminal_handling # import the terminal_handling class
from terminal_handling import cout # import game engine console functions
def run():
cout("Hello !")
cout("How are you?")
choice = terminal_handling.show_menu(['Doing great!', 'Amazing!', 'Fine']) # display a choice menu with a list of choices, and store the choice to a `choice` variable
if choice == 'Doing great!' or choice == 'Amazing!':
cout("Perfect!")
else:
cout("Cool.")
# Run the action
run()
The script is now more complex, but it has noting to do with the game. To introduce the game re-usable variables, we're gonna store that response to a player attribute we're gonna create:
import terminal_handling # import the terminal_handling class
from terminal_handling import cout # import game engine console functions
def run(player):
cout("Hello !")
cout("How are you?")
choice = terminal_handling.show_menu(['Doing great!', 'Amazing!', 'Fine']) # display a choice menu with a list of choices, and store the choice to a `choice` variable
player["mood"] = choice # store the choice to a new player attribute
if choice == 'Doing great!' or choice == 'Amazing!':
cout("Perfect!")
else:
cout("Cool.")
# Run the action
run(player) # import the `player` game variable, which contains the player save data
Our script now also stores that answer to a new player attribute we called mood
. But let's rewrite the script from scratch, and make a script that randomly choose an enemy thumbnail, and ask the player which enemy it is, which multiple choices (taken from scripts/drawing_enigma.py
:
import random
import time
import text_handling # import the game engine's class that formats text
import terminal_handling # import the game engine's class that handles console stuff
from colors import * # import the game engine's class that contains a database of terminal compatible color
from terminal_handling import cout, cinput # import console output and input functions
def run(enemy, player, preferences):
completed = False # let know that the player hasn't completed the enigma
chosen_enemy = "" # placeholder
while chosen_enemy not in player["enemies list"]: # as long is the chosen enemy is not known by the player, choose another one from the game variable 'enemy', which contains every enemy data.
chosen_enemy = list(enemy)[
random.randint(0, len(list(enemy))) - 1 # choose a random enemy
]
chosen_enemy_data = enemy[chosen_enemy] # load the enemy data
options = [chosen_enemy] # create the list that contains all the possible choices, by already adding the right enemy
count = 0
while count < 4: # choose four more random enemies, to add to the possible choices
random_enemy = list(enemy)[random.randint(0, len(list(enemy)) - 1)]
if random_enemy not in options: # check if the chosen enemy isn't already in the choices
options += [random_enemy]
count += 1
random.shuffle(options) # randomize the list, so that the choices are shuffled
while not completed: # loop while the player hasn't complete the enigma
text_handling.clear_prompt() # clear the terminal screen
text_handling.print_enemy_thumbnail(chosen_enemy, preferences) # use the text_handling game engine's class to print the enemy thumbnail just from its name.
cout(f"\n{COLOR_STYLE_BRIGHT}Which enemy is this?{COLOR_RESET_ALL}") # just prompt text
choice = terminal_handling.show_menu(options) # display the menu with the possible choices
if choice == chosen_enemy: # if the player's right
cout(f"\n{COLOR_CYAN}Right answer!{COLOR_RESET_ALL}")
completed = True # mark the enigma as completed and close the loop
return completed
else:
cout(f"\n{COLOR_YELLOW}Wrong answer!{COLOR_RESET_ALL}") # inform the player he's wrong
time.sleep(2)
# Actually run the action, and tells the game which arguments to use
run(enemy, player, preferences)
This is a good example of how re-usable variables can be used, as databases. Now, to actually make these scripts run, we're gonna create a simple utility item:
Custom Script Runner:
type: "Utility"
key: 'J'
script name: example_script.py
gold: 99
arguments: # as the script requires these three
- enemy
- player
- preferences
description: our custom script runner!
thumbnail: placeholder string
If we load the game, and we add ourselves the item using the debug command $player$data$
we'll be able to run the script:
Check the Wiring Dialogs wiki page to know how to run scripts from dialogs, and the Creating Events wiki page to know how to run scrips from events.
Now, a little bit more about game variables. Game variables are dictionaries, that for the most part contain the game content data, as enemies, npcs, map points, map zones, etc... and other the player save data, the preferences etc... You'll often use these variables when creating variables, and you always have to list them in an arguments
key, at the same location as the script name
key (you don't need an arguments
key if your script doesn't require any). This page contains the list of every game variable, and its content. What I recommend you to do is to make a string that just prints to the console the content of every game variable, so you have more knowledge on how they are.
Starting from v0.24-alpha, 'custom-made' arguments can be specified like this:
arguments:
- player # a regular argument
- zone
- custom_one_2: True # a custom made one
- custom_one_3: "hello" # it can really be anything
- custom_one_4: 8
- custom_one_5: [1, 7, 8] # it can be a simplified list
- custom_one_6: # or a regular list
- 1
- 7
- 8
- custom_one_7: {"first key": "hi", "second key": "hi again"} # or a simplified dictionary
- custom_one_8: # or a regular one
first key: "hi"
second key: "hi again"
This final part of the guide will be the most important part, as every class and their functions will be explained here, so that you know the main ones, and you're able to create custom scripts that interact with the game engine, and that uses useful functions. The document that contains every bit of information about the game engine functions can be found at docs/ENGINE_FUNCTIONS.md
.
- Running The Game
- Gameplay Guide
- GitHub Discussions
- Building Source Code
- Game Preferences
- The Game Folder
- The World Of Bane Of Wargs
- Game Timeline Plot
- Yaml Syntax
- Creating Mods
- Creating Starts
- Creating Map Points
- Creating Enemies
- Creating Enemies Categories
- Creating Map Zones
- Creating Items
- Creating Drinks
- Writing Dialogs
- Creating Missions
- Creating Events
- Creating NPCS
- Creating Mounts
Additional Knowledge