Heartwood Heroes: Modding Guide (Scripts, Data Formats, and Resource Lists) - GamePretty

Modding workflow
Creating new mods
Create a folder named “mods” in the game’s root folder. The game will load local mods from subdirectories in this folder.
E.g. to start work on a new mod, create the folder mods/MyNewMod, and start adding mod files to it. See further documentation on what files and data the game looks for.
Most data is reloaded when a scenario is started from the main menu, but adding new scenarios, paperdolls or resources requires a restart of the game.
Uploading to Steam
Once the mod is ready to be shared, copy its folder to another folder called steam_uploads (also located in the game’s root folder).
E.g. from mods/MyNewMod to steam_uploads/MyNewMod
This folder serves as a repository for uploading data to Steam and is not loaded by the game directly.
Optionally add PNG file called steamicon.png, which will be used as the icon for the mod on Steam Workshop.
Open the game and go to the Mods menu from the main menu. You will see a list of all the mods in steam_uploads. The first time you upload a mod, the mod will need to be initialized. Press the Init button, and a new file called modinfo.dat will be created in the mod’s folder. Do not delete or edit this file, as it contains important data connecting this mod to Steam. It cannot be recreated.
Once the mod is initialized and ready, the Upload button will be available, as well as title and description info. You can edit these fields and they will be updated on Steam Workshop when you upload. You should also add a message to describe what’s changed in this upload.
When you press the Upload button, the game will check that all files compile correctly and then start uploading to Steam. Hopefully everything goes well, and then a success message will be displayed. If anything went wrong, an error message will be displayed instead.
Then what?
Continue working on your mod in mods/ folder and when new changes are ready to be uploaded, copy the contents to its counterpart in steam_uploads, but make sure not to overwrite modinfo.dat.
To make a mod visible to others, you need to go into Steam Workshop and change its visibility. You can also edit descriptions and titles there, though note that those changes will not be downloaded back to steam_uploads and may be overwritten the next time you upload.
Scripts – Basic syntax
Comments:Line comments
// this is a line comment, anything after the two slashes will be ignored --- this is also a line comment
Instructions (
...
e.g.
setlocal alpha 555
exception:
if arguments are expressions (see below), they need to be separated by a comma
currently this only applies to one instruction: add_stat, which takes a string
expression and an int expression as arguments
e.g.
add_stat "vio", 5+rand(3)
newlines separate instructions
exception: if, while, else, and blocks {, }, do not require newlines for the instruction that follow
see section: Basic Statements
Values:
Values of script variables can currently have 3 types
(Only the decimal form is currently supported)
String a string value “hello” List a list value of multiple other values {5, “hello”, {“another”, “list”}}Comparisons are only valid between types of the same kind
e.g.
5 = "5"
is always false
Operations always result in the same type as the first operand, and the second will be converted to this type of possible
e.g.
Expressions can be used as arguments to instructions to perform calculations
Any number of operators and comparisons can be combined anywhere that an expression is expected
They can use any of the following as operands
variables: an unquoted string, e.g., alpha. Will load the value of a previously defined script variable or a built-in value (see later) The order of precedence for loading values is 1. local variables (defined with setlocal) 2. script variables (defined with setvar) 3. built-in variables 4. globals (defined with global) literals: integers, e.g. 5 strings, e.g. "abc" lists, e.g. {5,5,5,5}
Sub-expressions can be grouped with parentheses
e.g.
(alpha + beta) * gamma alpha + (beta * gamma)
Available operators
(a and b are operands, they can be either named variables or literals)
Prefix operators:
+a (does nothing) -a negation negates a value, e.g. turns 5 into -5. Only valid for ints !a boolean inversion turns a boolean true (1) into false (0) and vice versa Only valid for ints
Arithmetic operators:
a * b multiplication multiplies a with b, e.g. 5*2 => 10 Only valid for ints a / b division divides a with b, e.g. 10 / 2 => 5 Only valid for ints a + b addition Ints: adds a and b, e.g: 5+2 => 7 Strings: appends b to the end of a, e.g: "abc" + "d" => "abcd" Lists: appends b as the last element of the list, e.g: {1,2,3} + "hello" => {1,2,3,"hello"} a - b subtraction subtracts a and b, e.g. 10 - 2 => 7 Only valid for ints
Ordering operators
(operands must be of same type)
(not defined for lists)
a < b "less than" comparison Ints: 1 if a is less than b, otherwise 0, e.g. 10 < 5 => 0 Strings: calculates lexical string ordering, e.g: "a" < "b" => 1 a <= b "less than or equal to" comparison Ints: 1 if a is less than or equal b, otherwise 0, e.g. 10 <= 10 => 1 Strings: calculates lexical string ordering, e.g: "b" <= "a" => 0 a > b "greater than" comparison Ints: 1 if a is greather than b, otherwise 0, e.g: 10 > 5 => 1 Strings: calculates lexical string ordering, e.g: "a" > "b" => 0 a >= b "greater than or equal to" comparison Ints: 1 if a is greater than or equal to be, otherwise 0, e.g: 10 >= 10 => 1 Strings: calculates lexial string ordering: e.g: "b" >= "a" => 1
Comparison operators
(always false if operands are not of same type)
a = b equality comparison 1 if a and b are exactly equal, otherwise 0 Lists: checks that each element of the lists are equal a != n inequality comparison 1 if and b are not exactly equal, otherwise 0 Lists: checks if any of the elements of the lists are not equal
Logical operators
(interpret their operands as boolean values (true/1 or false/0))
(non-zero ints are considered true, zero is false)
(non-empty strings are considered false, otherwise all strings are true)
(non-empty lists are considiered false, other all lists are true)
a && b logical AND 1 if both a and b are true, otherwise 0 a || b logical OR 1 if either a or b are true, 0 if both are zero
Index operator
a[b] gets the value at index b of a Ints: not valid Strings: returns the character value at the specified index as an int Lists: returns the value at the specified index
Scripts – Additional expressions
Additional expressionsFunction calls:
function_name()
calls the built-in function function_name with the specified arguments (see below for
trying to call an unknown function will result in a compile error
e.g: rand(5), returns a random value between 0 and 4
see section “Built-in functions” for full list of available functions
Select:
[: ]
selects any of the specified arguments based on the value of the
e.g:
[rand(3): "a", "b", "c"]
will result in either “a”, “b” or “c”, based on the value of rand(3)
conditional operator (
if
a warning will be issued and the first item chosen
shorthands:
a|b|c
shorthand for [diff: a,b,c]
a\b\c
shorthand for [q_diff, a,b,c]
Argument list expression (
Argument lists are used in function calls, list literals, and certain other contexts
They are a list of expressions separated by commas;
e.g.
func(1,2,3)
1,2,3 is the
they are usually enclosed by parentheses, but in list by brackets [],
and in select expressions, the square bracket ends the list
List expansion operator (…
This operator expands a list value into additional individual arguments in an
it is only valid in places that accepts an
e.g.
setlocal arr {1,2,3} func(...arr)
will be interpreted as func(1,2,3)
as arr is a list variable
using the operator on a non-indexable value is an error
using it on a string will result in a list of character values
e.g.
..."abc"
may result in {97,98,99}
Scripts – Statements
Statements (A statement is one of the following
– an instruction - if – an if statement
- while – a loop statement
- end – a return statement
- @/label – a label statement
- jump – a jump statement
- {
…} – a block statement; multiple statements enclosed in brackets
Basic Statements
If
if
if statement
executes the statement
e.g.
if alpha = 5 dbg_log("hello")
only executes dbg_log if alpha is 5
for multiline ifs, use block statements
if alpha = 5 { dbg_log("hello") dbg_log("world") }
can be nested to to any depth
e.g.
if (alpha = 5) if (beta = 4) if (gamma = 3) dbg_log("yup")
only executes dbg_log if alpha is 5, and beta is 4, and gamma is 3
(this could of course also be written as if (alpha = 5 && beta = 4 && gamma = 3) )
If-else
if<"then" stmt> else <"else" stmt>
if-else statement
executes
if
e.g.
if alpha = 5 dbg_log("hello from 5") else dbg_log("hello from something else")
as with any statement, use block statements for multiline ifs or else blocks
Looping
while
loop statement
executes
use block statements for multiple instruction etc. etc.
End
end []
return statement
ends execution of the current script
if the current script has been started with call, returns control to the calling script
can push value of the optional
Label
@
or
label
label statement
creates a new label named
only valid in the current script context
label names must be unique
unused labels will result in a compile error
Jump
jump
jump statement
moves execution from the current position to the instruction following the label
e.g.
@branch1 ... jump branch1
goes back and runs the code from branch1 again (beware of infinite loops when jumping upwards)
caution: excessive jumping makes code hard to follow and reason about,
prefer using other methods of structuring code
Set variable
setvar
set script variable statement
sets a variable named
this value is available throughout the whole script
e.g.
setvar alpha rand(4) * (beta + gamma)
shorthands:
addvar=> setvar ( + ( ))
adds
subvar=> setvar ( - ( ))
subtracts
Set local variable
setlocal
set local variable statement
sets a local variable named
this value is only available in current script context (event),
not in other events, not even if they have been goto’d or call’d
e.g.
setlocal alpha "hello " + "world"
shorthands
addlocal
same as addvar, but for local variables
sublocal
same as subvar, but for local variables
Debug log
dbg_log()
debug log statement
prints the arguments in
Scripts – Built-in functions
Built-in FunctionsThese can be used in expressions. to_int(a) returns a interpeted as an int to_str(a) returns a interpreted as a string rand(a) returns a random value between integers 0 and a-1 (always less than a) rand(a,b) returns a random value between integers a, and b-1 (always less than b) rand_entry(a) returns a randomly selected entry in the list or string a var(a) returns the value of the script variable named by the string a length(a) returns the length of the string or list a subset(a, idx) returns a subset of the string or list a, starting at idx subset(a, idx, end) returns a subset of the string or list a, starting at idx and ending at end get_name(a) returns a string value containing the name defined by the string a monster_name(a) returns a string value containing the name of the monster defined by the string a monster_gfx(a) returns a string value containing the resource name of the graphics of the monster defined by the string a has(a) return true or false depending on if the current play has a certain gear, magic, etc.
special values:
“gear” – checks if the player has an item of type weapon, armor, or relic
“weapon”/”magic”/”armor”/”relic”/”mist” – checks if the player has an item of this item type ranked_player(a) returns the index of the player of rank a (ie. 1 – 4, if 4 players)
can be used with e.g. pl_port to set the portrait of the player of a certain rank
pl_port ranked_player(2)
sets the portrait to player of rank 2
Scripts – Built-in variables
Built-in script variablesThese can be used in expressions. stats list of the names of all possible stats a player can have diff the difficulty of the current tile the player is on q_diff the difficulty of the player’s current quest pl_name a string of the current player’s name playerrank the current player’s rank numberofplayers the number of players that currently playing nplayers same as numberofplayers turns_left the number of turns left of the game total_turns the total number of turns at the start of the game vio
tou
mag
sne
soc
coo value of the current player’s current stat of this type gold value of current player’s current amount of cash lvl current player’s level turns number of turns taken in the game game_time measures the number of milliseconds elapsed since the game was started
Scripts – Script instructions
Script InstructionsThese instructions handle how scripts are parsed or define new events. strict
legacy
changes the parsing mode of the parser
these are only valid outside of events and will be interpreted as the end of the event if present inside an event
global
defines a new global variable named
only valid outside of events and will be interpreted as the end of an event
id:
defines a new event named
the id must be unique, if the event already exists in the base game you will get an error
if you really want to override an existing script, mark the event as override.
e. g.
id: event_that_exists override
if no such event actually exists to override, you will instead get an error for that.
Scripts – Event instructions
Event instructionsThe following instructions are only valid inside an event goto
starts the event
if the optional
argument variables are named
argv: a list of all the arguments
arg_0 … arg_N: named variables of the values in the order defined in
argc: number of arguments passed to event
e,g,
goto test_event (1, 2, 3)
test_event will have local variables
argv = {1, 2, 3}
argc = 3
arg_0 = 1, arg_1 = 2, arg_2 = 3
call
same goto, but when
after call
if
e.g.
call test_event rval dbg_log(rval) id: test_event end 5
dbg_log will display 5, as that was the value returned from test_event and stored in rval
rng
…
defines a random switch statement
selects a random value between 0 and N and executes one of the following N instruction based on that value
e.g.
rng 3 dbg_log("selected 0") dbg_log("selected 1") dbg_log("selected 2")
will execute one of the dbg_log statements
the others are skipped
as with other
rng
NOTE: Preferably don’t use this one
similar to rng, but reads all the immediately following instructions of type
and uses them in the list of random instructions to execute
e.g.
rng jump jump label1 jump label2 jump label3 @label1
will use one of the random jump instructions between rng and label1
ch_if
ch_0
ch_1
ch_2
ch_str
NOTE: Wonky legacy syntax here
choice statement, displays a choice box, with a number of options
any of these initiates parsing of a choice statement
ch_0, ch_1, ch_2
Pushes the line as a new choice option
ch_str
Takes a string expression and pushes the value as a new choice option
ch_if
Make the next ch_X statement conditional on the value of the
If it is false/0, that option can’t be selected
If the value of ch_X is -, that option is ignored
NOTE: This is not necessary and only available for legacy reasons
If you only want two options, then you only need to write two ch_X instructions
text in choice boxes is filtered, see section String Filtering
choice
acts as break between ch_X and the results of the choices
reads as many
that is, with two choices, it will read two
e.g.
ch_0 Choice 1 ch_str "Choice 2" choice dbg_log("chose 1") dbg_log("chose 2")
displays a choice box with two options: “Choice 1” and “Choice 2”.
Depending on which is chosen, either of the two dbg_logs are executed
Statements not chosen are skipped
As with other
endturn
removes all remaining moves of the current player and skips the “resolve tile” step of the turn
meaning no other events would be drawn
exhaust
removes all remaining moves of the current player
add_ee
adds the event
if the enchantment event can’t be placed on the current tile the script jumps
to the optional label
fg_ev
do this before “fight” to add an override after-winning-event to the fight.
this will ignore any after-winning-event set in the monster data.
this override will remain with the monster on the map.
(if you want an event when you lose a fight, you add it in the monsters data:
– lose_ev:
start_fight
start a fight with a monster with id of the value of
e.g.
start_fight "monster_id"
starts a fight with the monster monster_id
shorthands
fight=> start_fight " "
start_fight_msg
works like start_fight except it shows a random encounter message in the beginning of combat
block_check
shortcut to check levels based on area [#blockerlvls]
and does a goto: to [#monster_lvlblockers] if level is not high enough
Scripts – Event instructions (quests)
q_nmsets the name of the quest to
any event that has a q_nm command in its body can’t be drawn if an
active quest has the name
sets the quest event to
q_rew
sets the quest reward to
also accepts select literals
q_mr
value of
sets the minimum range for the quest objective
q_diff
if you set
but if you set this to 0, the quest will be placed in your current region or below
q_area
= darklair / castle
places the next add_quest or add_quest_all in this specific area.
other areas than darklair and castle will show an error
= NULL disables this feature and places quests normally, only needed if you place more than one quest in one event
q_req
explanation of requirement to do the quest event
displays
add_quest [
adds a new quest and spawns the event in an appropriate place.
relies on q_nm and q_ev and q_rew being set beforehand.
if this event was the “next event” of a quest, that quest is replaced with this new one.
optional
- all, adds quest for all players
- main, adds as main quest
shorthands
add_quest_all => add_quest all add_quest_main => add_quest main
Scripts – Event instructions (misc)
waitwait for
e.g.
wait 25
waits for 0.5 seconds
wait_for_input [
waits until the player presses a button
if
death_check
checks if the player is dead, and if so ends the script
Scripts – Event instructions (text)
box_clearclears the message box nm_clear
clears the name box
name
displays the value of
shorthands
nm=> name " " nm_p => name pl_name display the current player name nm_n => name get_name(" ") displays a name string nm_m => name monster_name(" ") displays name of monster
message
displays the values of
text in message box is filtered, see section String Filtering
box
displays the line
text in message box is filtered, see section String Filtering
nag
works like the box command if the user has the Hint Messages setting on
otherwise this command is skipped
add
adds the line
text in message box is filtered, see section String Filtering
Scripts – Event instructions (misc. scene, graphics)
reset_snok_countersnok events MUST have this
reset the Snok counter which allows players to get a Snok encounter
must be called in every Snok event when the player gets the reward
if the group has Snok event group with 1 or more in event_groups.txt it’s allowed to draw it. Castle And Dark Castle have no Snok available, so it cannot be drawn there. next_act
makes the game move forward one act after the event.
run_scene
runs an EventScene prefab from Resources/EventScenes/ named as value of
shorthands
scene=> run_scene " "
set_bkg
sets the background image to the value of
shorthands
bkg=> set_bkg " "
bkg_restore
restores the background to the tile-appropriate one
set_port
sets the portrait to the value of
to clear, use img name “None”, which is a small 100% transparent texture
shorthands
port=> set_port " " port_m => set_port monster_gfx(" ")
port_pl
displays the portrait of player of index
shorthands
port_rank_pl=> port_pl ranked_player( )
displays the portrait of the player of a certain rank
Scripts – Event instructions (audio, effects, music)
play_fxshow a portrait fx (sweat drop, anger thingy, shake etc). will be automatically cleared when changing portrait
these will stack so you can mix severalshorthands
fxp=> play_fx " "
fxp_clear
remove all current portrait fx
play_music
plays the song
shorthands
music=> play_music " "
set_next_music
set the song
shorthands
music_next=> set_next_music " "
set_map_music
sets the song
shorthands
map_music=> set_map_music " "
set_next_map_music
set the song
shorthands
map_music_next=> set_next_map_music " "
music_interrupt
instantly pauses the overworld music and instantly stops the “event music”.
music_fadeout
stops the event music with a fadeout
music_pause
pauses the event music
music_resume
resumes the paused event music
play_snd
plays the sound effect
this sound interrupts the previous event sound
shorthands
sfx=> play_snd " "
play_snd_ducked
(UNDER CONSTRUCTION)
plays a sound just like the play_snd command but
the music ducks this quickly and intensely
shorthands
dsfx=> play_snd_ducked " "
Scripts – Event instructions (stats, items, jobs, rewards, etc.)
add_statupdates the stat
will display a message box notifying the player of the change
e.g.
add_stat "vio", 5+rand(3)
adds 5-7 to the stat VIO
shorthands
+vio=> add_stat "vio", +tou => add_stat "tou", +mag => add_stat "mag", +sne => add_stat "sne", +soc => add_stat "soc", +coo => add_stat "coo", +rst => add_stat rand_entry(stats), updates a random stat
add_item
gives the player a specific item
shorthands
+item=> add_item " "
rem_item
removes the item
shorthands
-item:=> rem_item " " NOTE: colon after -item differentiates it from -item below
rem_item_type
removes an item of a specific type from the player’s invetory, if it exists
shorthands
-item => rem_item_type "all" NOTE: lack of colon differentiates it from -item: -weapon => rem_item_type "weapon" -armor => rem_item_type "armor" -relic => rem_item_type "relic" -magic => rem_item_type "magic" -gear => rem_item_type "gear"
add_exp
updates the player’s EXP value with the value of
shorthands
+xp=> add_exp
add_hp
updates the player’s HP with the value of
if HP drops below 0, the event ends immediately
shortands
+hp=> add_hp
add_status
adds the status
shorthands
+s=> add_status " "
rem_status
removes the status
no textbox is shown if the player doesn’t have the status effect
shorthands
-s=> rem_status " "
status_clear
removes all the status effects from the players
automatically shows a textbox for every status removed
set_job
changes the players job to
shorthands
+job=> set_job " "
give_reward
gives the player a random item from the category in
shorthands
+reward=> give_reward " " +reward: #jobarea gives equipment tagged for the specific job the player currently is. If a new job is added, equipment must be tagged, or this function will crash the event.
Scripts – Event attributes
Event AttributesThese look like instructions but are interpreted during compilation and added to an event as attributes freq
sets how frequently an event appears
group
sets which group an event belongs to
all events except those special or starter attributes must have a group
valid groups are:
- good (something good happens)
- bad (something bad happens)
- event (random chance events)
- snok (only appears for the player in last place)
- quest (events that start quests)
loc
sets which location the event should appear in
an event can have multiple loc attributes and then it will appear in all those locations
valid loc are:
- road (generally very low risk and rewards, no quests)
- town (generally very low risk and rewards, no quests)
- flowers (generally find jobs)
- forest (generally find cash)
- ruins (generally find equipment)
- runestones (generally find spells)
- mountain (generally high risk and high rewards)
diff
sets difficulty of the event
the first region is 0, the final region is 3
special
marks this event as special, it will not appear as a random event
pvp
marks this event as a pvp event, it will not appear as a random event if the player has disabled pvp events
enchantment
sets the event as special and marks it be used for enchant events
enchantment_diff
sets the tier of the area this enchantment would spawn in
0 is the default and means the current space when spawned in an event or a random space
if it is randomly placed by proceeding to a new act
enchantment_unremovable
makes this enchant event unremovable by other enchants (such as golden road)
put this after the enchantment:
starter
a possible starter quest that happens before the game
automatically sets event as “special” as well
lastplace_only
event can only randomly spawn for someone in last place
notfirst_only
event can only randomly spawn for someone in not in first place
first_only
event can only randomly spawn for someone in first place
notlast_only
event can only randomly spawn for someone not in last place
not_in_quests
prevents a random event from being chosen if a quest with a q_ev found in
e.g.
not_in_quests {event_1, event_2}
event ids are checked to make sure events with those ids actually exist
Note that when regular random quests are created in the games random events that event is already getting prevented from being picked again for as long as the quest remains on the quest log
Scripts – String filtering
Strings in certain message boxes are “filtered”, this means they can contain certain variablesThese are enclosed in
Any available script variable can be used and displayed in this wayThere are also some special values:
E.g.
box We are currently in...
May display “We are currently in Freaky Forest…” in the message box.
Scripts – About events and event groups
A player who has been in last place for 3 consecutive turns (or 4 turns when there are only two players), and is a minimum of 2 levels behind the leading player, automatically gets a Snok event if one is available at that location.
All events have a cooldown of 8 turns before any player can draw them again. Quests have a cooldown of 25 turns.
The castle and darklair locations have a special case; they only contain the events defaultcastle and defaultdarklair respectively.
When a player gets a random event, the event group is chosen first, and then a specific event is chosen within that group.
The Clairvoyant skill has a chance of rerolling the event group once if the Bad group was drawn. The Lucky status forces the Good or Quest group to be drawn, and the Unlucky status forces the Bad group to be drawn.
This is the frequency of each group of random events when exploring/loitering on each location type per region:
Location Region Event Good Bad Quest Waste Battle Snok Road 1 24 34 3 2 37 1 Road 2-4 20 22 15 10 33 1 Town 1 45 45 5 5 1 Town 2-4 35 35 20 10 1 Flowers 1 25 25 5 35 10 1 Flowers 2-4 25 25 20 20 10 1 Forest 1 15 15 5 32 33 1 Forest 2-4 15 15 13 24 33 1 Ruins 1 15 20 5 38 22 1 Ruins 2-4 15 20 10 33 22 1 Runestones 1 15 20 5 38 22 1 Runestones 2-4 15 20 10 33 22 1 Mountain 1-4 15 15 13 24 33 1Data formats – Common
Data specified in square […] brackets are optional, and it is not an error to leave them out. Some default value will be used instead.
Values specified as <…> means those values should be defined by you. The brackets should not be included in the actual data file.
E.g., if a specification says
Data formats – Resources
Mod file: resources.txt(define all resources in this file)
File comments allowedResources are loaded when needed, that is, if a resource is defined but never used, it will not get loaded.
All paths should be considered local to the root folder of the mod.
Resource ids can in some cases override “hardcoded” resources, ie. those that come built-in with the game. This can be done for e.g. any texture referenced by scripts, or enemy sprites. To always use a certain built-in resource, reference it as res:/
Format:
[Textures] tex{ path: }
Note: Valid file formats are png and jpg
[Sprites] sprite{ path: [pixels_per_unit: ] [pivot_x: ] [pivot_y: ] }
Notes: Same file formats as for textures
[Music] music{ path: [loop_left:
Notes:
The song will loop if loop_left is a smaller value than loop_right.
The ‘next:’ variable only matters if this song is used as the overworld song.
When a new act begins the game checks the ‘next:’ variable for what song to switch to.
Example:
tex TestMod_apamouth { path: textures/apa_mouth.png } sprite TestMod_Sprite1 { path: textures/sprite1.png pixels_per_unit: 75 pivot_y: -70 }
Data formats – Paperdoll
Mod file: paperdoll.txt(define all new doll parts in this file)
File comments allowedAdds new selectable mouths, hairstyles, etc., for the player sprites
Format:
{ gfx: [tag: ] }
Available
- hair_back – piece of hair rendered behind head
- head – the sprite’s basic head shape
- mouth – the mouth
- eyes – eyes
- hair_front – piece of hair rendered in front of the head
Notes:
Tags are an optional feature that determine which parts that are incompatible with one another.
Currently only used for hairs. If a hair_front part has a tag, a hair_back needs to have the same tag in order to be used with that hair_front. Otherwise it will be skipped when trying to select it in the menu.
Example:
head apafrog { gfx: TestMod_apahead } eyes apaeyes { gfx: TestMod_apaeyes } mouth apamouth { gfx: TestMod_apamouth }
Data formats – Scenario
Mod file: scenarios.txt(define all new scenarios in this file)
File comments allowedDefines new scenarios that can be selected in the game menu.
Format:
{ name: "" [desc: " "] start_event: