On this page 29 sections
- Words used on this page
- Settings files
blse.ini_getblse.ini_setblse.ini_sectionsandblse.ini_keys- Translated strings
blse.translateblse.translation_keysblse.languageblse.translate_text- Values on entities
blse.entity_setblse.entity_getblse.entity_keysblse.entity_clearblse.entity_find- The shared database
blse.db_getblse.db_setblse.db_keysblse.version_at_least- JSON files
blse.json_readblse.json_writeblse.json_setblse.json_files- Saving data
blse.before_saveblse.new_game
Where a mod keeps its data, and how it talks to players in their language. Pick the place by who needs the data and how long:
| You want to keep... | Use | Kept in |
|---|---|---|
| Settings the player edits (keys, speeds, on/off) | Settings files (ini_get, ini_set) |
Bin\loader\blse\config\<mod>.ini, for every save |
| Text in the player's language | Translated strings (translate) |
Bin\loader\blse\translations\<mod>_<language>.txt |
| A mark on one NPC or object ("already fed on") | Values on entities (entity_set, entity_get) |
the save |
| Structured data other mods or plugins should read | The shared database (db_get, db_set) |
the save |
| Data shared by every save (statistics, unlocks) | JSON files (json_read, json_write) |
Bin\loader\blse\data\<file>.json |
| Your own mod's state in the save | Saving data (attributes of G) |
the save |
A first example: a setting the player can change, a count kept in the save, and a message in the player's language.
import blse
# Bin\loader\blse\config\mymod.ini: [General] bonus = 5 (written with the default the first time)
bonus = blse.ini_get('mymod', 'General', 'bonus', 5)
if blse.ini_get('mymod', 'General', 'bonus') is None:
blse.ini_set('mymod', 'General', 'bonus', bonus)
def count_kill():
kills = blse.db_get('mymod.kills', 0) + 1 # saved with the game
blse.db_set('mymod.kills', kills)
# Bin\loader\blse\translations\mymod_english.txt: KILLS<tab>{} kills so far.
blse.console_print(blse.translate('mymod', '$KILLS{%d}' % kills) + '\n')Read this first
- Values on entities, the shared database and
Gare saved with the game; settings, translations and JSON files are plain files shared by every save. - Values on entities only work while a level runs (after
blse.level_init, beforeblse.level_shutdown), from Python's normal code (the main thread). The shared database also needs the main thread. - Start every name with your mod's name (
'mymod.kills',mymod.ini): every mod shares the same database, entity values and folders. - Bad names raise
ValueError; a missing file or value returns thedefault(orNone). - Python 2.1 has no booleans: store 1 and 0. JSON
true/falseread as 1 and 0.
Words used on this page#
- Mod name (
mod): your mod's short name, used in file names: 1 to 63 characters ofA-Z a-z 0-9 _ - ., not starting with., and not a Windows device name (con,nul,aux,prn,com1-com9,lpt1-lpt9). - Section, key, value (
.inifiles): a file is split into[Sections]; each holdskey = valuelines. - Entity, index, handle: see the world page.
entityis an index (1 = the player) or a handle. - Save store: the part of the game's save where BLSE keeps its data (inside the game's script globals,
G). G: the game's own object for saved script data (__main__.G). Everything set on it is written into each save.- Path (database and JSON): where a value sits inside nested dicts and lists: keys separated by
., list positions in[ ], counted from 0 ('mymod.names[1]'). - JSON: a common text format for dicts (
{}), lists ([]), strings, numbers,true/falseandnull(Python'sNone). - Pickle, picklable: Python's way of writing objects into a file; the game pickles
Ginto each save. Numbers, strings, lists, tuples and dicts of them are picklable. - UTF-8, UTF-16, BOM: ways to store text with accents and other alphabets. A BOM is a short mark at the start of a file that tells the encoding; Notepad writes one.
- Payload: the text an event hands to your handler.
Settings files#
Mods' settings in .ini files: Bin\loader\blse\config\<mod>.ini, which players edit with any text editor.
; a comment (also # at the start of a line)
[Sprint]
key = ALT
speed_factor = 1.6| Function | |
|---|---|
blse.ini_get(mod, section, key[, default]) |
The value as a string, or default (None) if the file or key is missing. With a number as default, the value comes as that type (ini_get('sprint', 'Sprint', 'speed_factor', 1.6) -> 1.6), or the default if it is not a number |
blse.ini_set(mod, section, key, value) |
Writes the value (a string or a number; None removes the key, every copy of it in the section) and keeps the rest of the file as it was, comments included; makes the folder and file if needed. Returns 1 or 0 |
blse.ini_sections(mod) / blse.ini_keys(mod, section) |
The sections, or a section's keys, in the file's order; None if there is no such file |
mod is 1-63 of A-Z a-z 0-9 _ - .. Sections and keys are matched without regard to case; spaces around keys and values are ignored, and a value in double quotes keeps its own. Nothing after a value is a comment (color = #FF0000 is a color). Files are UTF-8, up to 1 MB. Ship the file with comments explaining each setting (examples/config/sprint.ini), and write missing keys with their defaults so players can find them.
Names, in detail: a section is up to 127 characters without ] ('' means the keys before the first [section]); a key is 1 to 127 characters without = or [, not starting with ; or #. Neither may start or end with a space or tab, and neither may hold a line break. A bad name raises ValueError. The settings files work at any time, also at the main menu.
blse.ini_get#
blse.ini_get(mod, section, key[, default]) # -> str, int, float, or defaultReads one setting. Use it at the top of your script to load your mod's options.
mod(str): the file's name without.ini('sprint'readsconfig\sprint.ini).section,key(str): where the value is; case is ignored.default(any, optional): what you get when the file or key is missing (Noneif left out). Its type also decides the result's type:- an int: the value is read as a whole number (
'010'is 10); if it is not one ('1.6','fast'), you getdefault; - a float: the value is read as a number; if it is not one, you get
default; - anything else: the value as text.
- an int: the value is read as a whole number (
- Returns the value, or
default. RaisesValueErrorfor a bad name,RuntimeErrorif memory runs out.
speed = blse.ini_get('sprint', 'Sprint', 'speed_factor', 1.6) # 1.6 if missing or not a number
key = blse.ini_get('sprint', 'Sprint', 'key', 'ALT') # textblse.ini_set#
blse.ini_set(mod, section, key, value) # -> 1 or 0Writes one setting and keeps everything else in the file as it was (comments, order, the other keys). Use it to write the defaults the first time, or to save an option the player changed in a menu.
mod,section,key: as forini_get. A missing folder, file or section is created.value: a string (one line, up to 4095 characters), an int or a float (written with up to 15 digits), orNoneto remove the key (every copy of it in the section). A value of another type, with a line break, too long, or a float that is not finite raisesValueError.- Returns
1when written (also when nothing changed: the file is then not rewritten),0if the file exists but cannot be read, or cannot be written.
blse.ini_set('sprint', 'Sprint', 'speed_factor', 1.8)
blse.ini_set('sprint', 'Sprint', 'old_option', None) # removes itblse.ini_sections and blse.ini_keys#
blse.ini_sections(mod) # -> [section, ...] or None
blse.ini_keys(mod, section) # -> [key, ...] or NoneList what a settings file holds, in the file's order. Use them for files with a section per item (one per weapon, one per NPC).
mod,section: as forini_get.- Return the names as written in the file,
[]for a section that does not exist, orNoneif there is no such file. RaiseValueErrorfor a bad name.
for section in blse.ini_sections('mymod_shops') or []:
price = blse.ini_get('mymod_shops', section, 'price', 100)Translated strings#
Text for each language in files next to the mod: Bin\loader\blse\translations\<mod>_<language>.txt, one string a line, a key, a tab (or =), the text:
; sprint_english.txt
$TIRED You are out of breath.
$READY = Ready to sprint\nagain| Function | |
|---|---|
blse.translate(mod, key) |
The text for key (with or without $; case is ignored) from the language's file, else from <mod>_english.txt, else the key itself without $. UTF-8 |
blse.translation_keys(mod) |
The keys of the mod's file for the current language (or English) |
blse.language() |
The language: 'english', 'german', 'russian', ... |
blse.translate_text(text) |
A '$KEY' text translated from any mod's files (b0.5.43), or the text as given if no file has the key |
Files are UTF-8 (a BOM is fine) or UTF-16 LE with a BOM. Lines starting with ;, # or // are comments; \n, \t, \\ in the text are a line break, a tab and a backslash. Bloodlines has no language setting (each translation of the game replaces its files), so BLSE uses Windows' display language; players choose another one with language = german in [Translations] of config\blse.ini (BLSE writes language = auto there the first time). Files and the setting are read again when the scripts run again (an engine restart). The game's fonts lack some characters: in the HUD, an em dash (—) shows as a box, while letters like é à ô show.
Keys, in detail: 1 to 255 characters after the optional $, without spaces, tabs or =; lines with another key are skipped. When a line has both a tab and =, the first of them separates the key from the text. Files may be up to 4 MB.
Since b0.5.43:
- Placeholders:
$FOUND{3}{$GOLD}looks upFOUND(You found {} {}) and fills each{}with the next value in braces, in order; a value starting with$is translated too. Works intranslateand everywhere below. - Interface text is translated: a text starting with
$given tohud_set(and hints),show_text,window_create(the title),menu_add_label,menu_add_button,menu_set_textandmenu_set_hintis looked up in every mod's files for the language (then English; files in name order, the first with the key wins). Text without a translation is shown as given, so'$5 a night'stays as it is.
blse.hud_set('greet', '$MYMOD_HELLO{Kindred}', 0.5, 0.15, '#FFFFFF', 26, 'center') # MYMOD_HELLO\tGood evening, {}.blse.translate#
blse.translate(mod, key) # -> strGives the text for a key in the player's language, from your mod's files. Use it for every message your mod shows, so translators only need to add a file.
mod(str): your mod's name; the files aretranslations\<mod>_<language>.txt.key(str): the key, with or without$, case ignored, optionally followed by placeholder values in braces ('$FOUND{3}{$GOLD}'). Each{}in the text is filled with the next value; a value starting with$is translated too (up to 4 levels deep). Extra{}without a value stay as they are.- Returns the text: from the player's language file, else from
<mod>_english.txt, else the key itself without$(and without its placeholder values). RaisesValueErrorfor a bad mod name or key, or for braces that are not whole{...}groups after the key;RuntimeErrorif memory runs out.
# mymod_english.txt: FOUND<tab>You found {} {}. GOLD<tab>gold coins
blse.translate('mymod', '$FOUND{3}{$GOLD}') # 'You found 3 gold coins.'blse.translation_keys#
blse.translation_keys(mod) # -> [key, ...]Lists the keys of your mod's file for the current language (or the English file if there is none), in file order, each once. Keys come in lower case and without $. Use it to check a translation for missing keys.
mod(str): your mod's name.- Returns the list (
[]if neither file exists). RaisesValueErrorfor a bad mod name.
english_only = blse.translation_keys('mymod')blse.language#
blse.language() # -> strThe language BLSE uses: the language setting in [Translations] of config\blse.ini if it is set (letters, digits, _ and -, up to 32 characters, in lower case), else Windows' display language. Windows' languages BLSE knows are english, german, french, spanish, italian, russian, ukrainian, polish, czech, hungarian, portuguese, dutch, swedish, turkish, japanese, korean and chinese; any other is english.
if blse.language() == 'russian':
blse.log('using the Russian files')blse.translate_text#
blse.translate_text(text) # -> str(b0.5.43) Translates a '$KEY' text from any mod's files, the same way the interface functions do. Use it when you build a text yourself and want the same behaviour as hud_set.
text(str): a text starting with$(placeholders allowed). Any other text is returned unchanged.- Returns the translation (the player's language, then English; every mod's files in name order, the first file with the key wins), or
textunchanged if no file has the key. RaisesRuntimeErrorif memory runs out.
blse.translate_text('$MYMOD_HELLO{Kindred}') # 'Good evening, Kindred.'
blse.translate_text('$5 a night') # '$5 a night' (no such key)Values on entities#
Named values on any entity (an NPC, the player, a prop), saved with the game and shared by every mod: one mod marks an NPC, another reads the mark.
| Function | |
|---|---|
blse.entity_set(entity, key, value) |
Stores a string, a number, or a list or dict (b0.5.42) (None removes it). Returns 1 or 0 |
blse.entity_get(entity, key[, default]) |
The value (a string, an int or a float, as it was set), or default (None) |
blse.entity_keys(entity) |
The keys stored on the entity ([] if none), or None if there is no such entity |
blse.entity_clear(entity[, prefix]) |
Removes the entity's values whose key starts with prefix (all without one); how many were removed |
blse.entity_find(key) |
The handles of this level's entities (and the player) that have key |
entity is an index (1 = the player) or a handle. Keys: 1-63 of A-Z a-z 0-9 _ - ., compared without regard to case; start them with your mod's name ('mymod.fed_on'). Values up to 4096 characters, 256 keys an entity. While a level runs.
Values follow the entity: the player's everywhere; another entity's while it exists, also after a load and when its level is entered again. A loaded save gives entities new indexes but puts them back where they were saved, so BLSE notes each entity's position whenever the game saves (a save, or the level's state at a transition) and finds it again by class, name and that position at the level's first frame. An entity that is removed (killed and cleaned up, picked up, deleted by a script) loses its values. Plugins use the same values as text (entity_data_get/entity_data_set).
def on_fed(target):
blse.entity_set(target, 'mymod.fed', blse.entity_get(target, 'mymod.fed', 0) + 1)blse.entity_set#
blse.entity_set(entity, key, value) # -> 1 or 0Stores a value on an entity, in the save. Use it to remember something about one NPC or object: that the player fed on it, paid it, or that your mod spawned it.
entity: index or handle.key(str): 1 to 63 characters ofA-Z a-z 0-9 _ - ., case ignored (stored in lower case). Start it with your mod's name. A bad key raisesValueError.value: a string (no NUL characters), an int, a float (finite), a list, tuple or dict (b0.5.42; stored as JSON, so a tuple reads back as a list), orNoneto remove the key. At most 4096 characters once stored. Another type raisesTypeError; a too long value or a NUL characterValueError.- Returns
1when stored or removed (also when the key was not there),0otherwise: no level runs, the entity does not exist, it already has 256 keys, or the save store refused the change. RaisesRuntimeErrorif memory runs out.
blse.entity_set(npc, 'mymod.paid', 50)
blse.entity_set(npc, 'mymod.info', {'met': 1, 'mood': 'angry'})
blse.entity_set(npc, 'mymod.paid', None) # removedblse.entity_get#
blse.entity_get(entity, key[, default]) # -> the value, or defaultReads a value stored with entity_set (by any mod).
entity: index or handle.key(str): as forentity_set(a bad key raisesValueError).default(optional): returned when there is no such value, no such entity, or no level runs.Noneif left out.- Returns the value with the type it was stored with: a string, an int, a float, or a list or dict.
if blse.entity_get(npc, 'mymod.paid', 0) >= 50:
blse.console_print('Already paid.\n')blse.entity_keys#
blse.entity_keys(entity) # -> [key, ...] or NoneLists the keys stored on an entity (by every mod), in lower case. Use it while debugging, or to copy all values.
- Returns the keys (
[]if the entity has none), orNoneif there is no such entity or no level runs.
blse.log(str(blse.entity_keys(1))) # the player's valuesblse.entity_clear#
blse.entity_clear(entity[, prefix]) # -> intRemoves several values at once: all your mod's values with prefix set to your mod's name.
entity: index or handle.prefix(str, optional): only keys starting with it (case ignored). Left out or'': all the entity's values, including other mods' ones.- Returns how many values were removed (
0also when the entity does not exist or no level runs).
blse.entity_clear(npc, 'mymod.')blse.entity_find#
blse.entity_find(key) # -> [handle, ...]Finds every entity on this level that has a value with this key. Use it to find all NPCs your mod marked, for example after a load.
key(str): as forentity_set(a bad key raisesValueError).- Returns the handles, in index order (the player first if it has the key);
[]if none or no level runs.
for npc in blse.entity_find('mymod.paid'):
blse.log('paid: %d' % npc)The shared database#
One JSON document saved with the game and shared by every mod, Python and plugins alike. G holds a Python mod's own data; this is where mods leave structured data for each other (and for plugins, which cannot read G).
| Function | |
|---|---|
blse.db_get(path[, default]) |
The value at path (dicts, lists, strings, numbers), or default (None). '' gives the whole database |
blse.db_set(path, value) |
Sets it, making the dicts on the way (None removes it). Returns 1 or 0 |
blse.db_keys([path]) |
The keys of the dict at path (the top without one), or None |
blse.version_at_least(version) |
1 if this BLSE is that version or newer ('b0.5.42') |
Paths as for JSON files: 'mymod.stats.kills', 'mymod.names[1]'; start them with your mod's name. Saved, loaded and cleared on a new game with the game's script globals; up to 1 MB. Plugins: db_get/db_set with JSON text.
blse.db_set('mymod.stats', {'kills': 0, 'names': []})
blse.db_set('mymod.stats.kills', blse.db_get('mymod.stats.kills', 0) + 1)Values on entities (entity_set) may also be lists and dicts since b0.5.42: blse.entity_set(npc, 'mymod.info', {'met': 1, 'mood': 'angry'}).
blse.db_get#
blse.db_get(path[, default]) # -> the value, or default(b0.5.42) Reads a value from the shared database.
path(str): where the value is ('mymod.stats.kills','mymod.names[1]');''gives the whole database as a dict. A malformed path raisesValueError.default(optional): returned when nothing is atpath(or the database cannot be used now, for example off the main thread).Noneif left out.- Returns dicts, lists, strings, ints, floats or
None(JSONtrue/falseas 1/0). RaisesRuntimeErrorif memory runs out.
names = blse.db_get('mymod.names', [])blse.db_set#
blse.db_set(path, value) # -> 1 or 0(b0.5.42) Stores a value in the shared database, in the save.
path(str): where to put it; not''(the top stays a dict). Missing dicts on the way are made; a list index one past the end appends. A malformed or empty path raisesValueError.value: dicts (string keys), lists, tuples, strings, numbers orNoneto remove the value. Nested at most 64 deep, 200000 values at most (elseValueError); another type raisesTypeError.- Returns
1when stored or removed (also when there was nothing to remove),0if the path crosses a value that is not a dict or list, the whole database would grow past 1 MB, or the database cannot be used now (off the main thread).
blse.db_set('mymod.names[0]', 'Beckett') # appends to an empty list
blse.db_set('mymod', None) # removes all of mymod's datablse.db_keys#
blse.db_keys([path]) # -> [key, ...] or None(b0.5.42) Lists the keys of a dict in the shared database. Use blse.db_keys() to see which mods store data.
path(str, optional): the dict to look at; the top of the database if left out.- Returns the keys, or
Noneif nothing is atpathor it is not a dict. A malformed path raisesValueError.
blse.db_keys() # e.g. ['mymod', 'othermod']
blse.db_keys('mymod') # ['stats', 'names']blse.version_at_least#
blse.version_at_least(version) # -> 1 or 0(b0.5.42) Tells whether the BLSE running is this version or newer. Use it before calling a function a newer BLSE added, to show a clear message instead of an error.
version(str): like'b0.5.42': an optional prefix of letters, then numbers separated by dots. Anything else raisesValueError.- Returns
1or0.
if not blse.version_at_least('b0.5.49'):
blse.console_print('mymod needs BLSE b0.5.49 or newer.\n')JSON files#
Structured data in Bin\loader\blse\data\<file>.json, shared by every save (statistics, unlocks, settings with lists). The game's Python (2.1) has no json module; BLSE reads and writes JSON itself.
| Function | |
|---|---|
blse.json_read(file[, path]) |
The file's contents (or the value at path) as dicts, lists, strings, ints, floats and None; None if the file or value is missing. ValueError with the line for a broken file |
blse.json_write(file, value[, pretty]) |
Writes dicts (string keys), lists, tuples, strings, numbers and None (pretty 1, the default, indents). Returns 1 or 0 |
blse.json_set(file, path, value) |
Sets one value and keeps the rest of the file (None removes it); makes the objects on the way. Returns 1 or 0 |
blse.json_files([folder]) |
The JSON files (without .json) in data or a folder of it |
file: a name, with folders separated by / ('mymod/stats'), of A-Z a-z 0-9 _ - . (not starting or ending with ., and not a Windows device name such as con, nul, aux, com1). Values given to BLSE may be nested 64 deep (200000 values at most); files are read up to 160 deep. path: keys separated by ., list indexes in [ ] ('stats.kills', 'list[2].name', '' the whole file); setting the index one past the end appends. Python 2.1 has no booleans: JSON true/false read as 1 and 0 (and other values in the file stay as they were when json_set changes one). Whole numbers beyond a Python int come back as floats. Plugins: json_get/json_set with JSON text.
A file name is at most 200 characters; a file at most 4 MB. A bad file name or path raises ValueError. The JSON functions work at any time, also at the main menu.
blse.json_read#
blse.json_read(file[, path]) # -> the value, or NoneReads a JSON file, or one value inside it.
file(str): the name without.json('mymod/stats'readsdata\mymod\stats.json).path(str, optional): one value inside the file;''(default) the whole file.- Returns dicts, lists, strings, ints, floats and
None;Nonealso when the file or the value is missing. RaisesValueErrorwith the line number for a file that is not valid JSON (or cannot be read, or is over 4 MB).
stats = blse.json_read('mymod/stats') or {}
kills = blse.json_read('mymod/stats', 'kills')blse.json_write#
blse.json_write(file, value[, pretty]) # -> 1 or 0Writes a whole JSON file, replacing it. Folders on the way are made.
file(str): as forjson_read.value: dicts (string keys), lists, tuples, strings, numbers,None; nested at most 64 deep, 200000 values at most (elseValueError); another type raisesTypeError.pretty(int, optional):1(default) writes it indented over several lines, easy to read;0writes one line.- Returns
1when written,0if the file would be over 4 MB or cannot be written.
blse.json_write('mymod/stats', {'kills': 3, 'unlocked': ['knife', 'bat']})blse.json_set#
blse.json_set(file, path, value) # -> 1 or 0Changes one value in a JSON file and keeps the rest; makes the file if it is missing. The file is written indented.
file,path: as forjson_read. Missing objects on the way are made; a list index one past the end appends.value: as forjson_write, orNoneto remove the value atpath.- Returns
1when written (or when there was nothing to remove),0if the path crosses a value that is not an object or list, or the file cannot be written. RaisesValueErrorif the existing file is not valid JSON.
blse.json_set('mymod/stats', 'kills', (blse.json_read('mymod/stats', 'kills') or 0) + 1)
blse.json_set('mymod/stats', 'unlocked[2]', 'katana') # appendsblse.json_files#
blse.json_files([folder]) # -> [name, ...]Lists the JSON files in data (or one of its folders), without .json. Use it for a folder with one file per item.
folder(str, optional): a folder insidedata('mymod');''(default) isdataitself.- Returns the names (
[]if the folder does not exist). RaisesValueErrorfor a bad folder name.
for name in blse.json_files('mymod/profiles'):
profile = blse.json_read('mymod/profiles/' + name)Saving data#
To store a mod's state exactly when the game saves, set it on G in a blse.before_save handler:
import blse, __main__
state = {'kills': 0}
def on_save(topic, data):
__main__.G.mymod_kills = state['kills'] # written into this save
blse.subscribe('blse.before_save', on_save)Python mods do not need BLSE for this: attributes of the game's __main__.G object are saved with the game (the game pickles them into every save), so G.mymod_counter = 3 persists. Values must be picklable. Native plugins' save data lives in G.blse_data, a dict of strings (a value longer than about 100 characters is kept as a list of short strings, b0.5.40); scripts may read it but should not replace it.
A bug of the game, fixed by BLSE (b0.5.40): the game reads G back from a save (and at every level transition) with its own line reader, which keeps only the first 128 characters of a line and writes past its buffer beyond 256. Every string in G is one line, so a string longer than about 125 characters broke the next load or transition (cPickle.UnpicklingError, then a crash). BLSE replaces that reader with one without the limit, so long strings in G are safe while BLSE runs; a save that has one cannot be loaded without BLSE. Always on: it is part of BLSE's save system, not a switchable fix (b0.5.49). A mod that should also work without BLSE keeps its G strings under about 120 characters. BLSE's own saved data (plugins' save data, values on entities, the shared database, kept looks and scales, companions) is always stored within the game's limit, so a save made with BLSE loads in the game without it.
Python's error output (tracebacks the game prints to its console) is also written to blse.log since b0.5.40, as [python] python error output: ... lines.
blse.new_game (b0.5.25): the first level of a game state that was not loaded from a save (a new character's first map, or a console map command from the main menu); G is fresh, so reset your module's in-memory state. Data: the map name. Sent before blse.level_init reaches other subscribers. BLSE detects it with a marker in G.blse_data; saves made before b0.5.25 get the marker when loaded. It is not sent for loads or level transitions.
blse.before_save#
Fires right before the game writes a save: a save game, an autosave, or the current level's state at a level change. Messages still queued for Python are delivered first, then this one, at once, so whatever a handler sets on G is in the save (b0.5.9). The payload is the map's name. See also the events page.
def on_save(topic, data):
__main__.G.mymod_state = {'kills': state['kills']} # data is the map name
blse.subscribe('blse.before_save', on_save)blse.new_game#
(b0.5.25) Fires at the first level of a new game (see above). The payload is the map's name. Use it to reset your module's variables, which would otherwise still hold the last game's values.
def on_new_game(topic, data):
state['kills'] = 0
blse.subscribe('blse.new_game', on_new_game)To read your state back after a load, read G in a blse.after_load or blse.level_init handler (see the events page):
def on_load(topic, data):
state['kills'] = getattr(__main__.G, 'mymod_kills', 0)
blse.subscribe('blse.after_load', on_load)