Even before making any modifications to the randomisation logic itself, there are a few things that need to be done to have generation recognise your new flag and make it available for use in any logic updates. The most important of these is flagspec.txt
, although you will also likely want to update uispec.txt
to make the new flag available on the website.
flagspec.txt
, present in the FreeEnt
directory, sets out the schema for flag strings. There are three major sections to flagspec.txt
- SPEC
, IMPLICIT
, and SLUGS
.
Each line in SPEC
contains a list of (usually) related flags as they appear in the flag string. As an example, here is the single line showing the K flags:
Kvanilla Kmain Ksummon Kmoon Kmiab Knofree Kunsafe Kforce:magma/Kforce:hook
The / indicates flags that are directly mutually exclusive.
“Numeric” flags are sets of separate internal flags; as an example of this, here is one of the sets of C flags:
Cj:spells Cj:abilities Cnekkie Cnodupes Cparty:1/Cparty:2/Cparty:3/Cparty:4 Cbye Cpermajoin Cpermadeath/Cpermadeader Chero
We can see that Cparty is actually four separate flags.
Note that SPEC
contains an AUTO_OBJECTIVES
subsection which maps conventional objectives to each of the O1: through O8: flagsets. This section is automatically generated from the separate objective_spec.txt
by the usual process of updating autogenerated files documented below. In most cases you won't have to worry about this, particularly since “mode” objectives are handled largely separately from this file (except in cases where the objective doesn't line up with an already extant objective, as you can see from the internal_dkmatter
objective present in objective_spec.txt
for Omode:dkmatter
purposes).
IMPLICIT
specifies additional flag logic, usually indicating that certain flags cannot be active when certain flags are specified. As an example, here is a line related to Tvanilla
:
Tvanilla : ~Tshuffle & ~Tstandard & ~Tpro & ~Twild & ~Twildish & ~Tempty
The ~ indicates “not”, and the & indicates “and”; the above line therefore specifies that if Tvanilla
is active that none of Tshuffle
, Tstandard
, Tpro
, Twild
, Twildish
, or Tempty
can be active.
Regular expressions are also supported to an extent, per the O and G lines which are respectively:
Onone : ~/^O(mode|\d+|random):/
Gnone : ~/^G(?!none)/
respectively indicating that if Onone
is active that no Omode
or Orandom
can be active and that if Gnone
is active that no other G
flags can be active.
SLUGS
maps flag string names to their respective identifiers in the randomiser code. As an example, here is the line for Omode:classicforge
:
Omode:classicforge objective_mode_classicforge
This indicates that if the Omode:classicforge
flag is set then this will be indicated by env.options.flags
containing objective_mode_classicforge
and also allowing the flag to be checked by that name in f4c scripts. Here is an example from adamant.f4c
:
//%flag objective_mode_classicforge on% text(map #SmithyHouseMainFloor message $05) { It's done! __I'm gonna keep it. } //%end%
And one from core_rando.py
:
if env.options.flags.has('objective_mode_classicforge'): keyitem_assigner.item_tier(3).append(ItemReward('#item.Excalibur'))
flagsetcore.py
(in the FreeEnt
directory) contains much of the logic for parsing flagsets; it is of particular interest here because of the fix
function which contains additional logic that cannot be captured by flagspec.txt
. To illustrate, here are the first two such checks in fix
:
if flagset.has_any('Ksummon', 'Kmoon', 'Kmiab') and not flagset.has('Kmain'): flagset.set('Kmain') self._lib.push(log, ['correction', 'Advanced key item randomizations are enabled; forced to add Kmain']) if flagset.has('Kvanilla'): self._simple_disable(flagset, log, 'Key items not randomized', ['Kunsafe'])
If your flag has advanced interactions with other flags, you will need to incorporate that here.
uispec.txt
(in the FreeEnt/server
directory) specifies how your flag is displayed on the website. As an example, here is the KEY ITEMS
section:
== KEY ITEMS <>* Key Items .[Kvanilla]- No key item randomization ..[Knofree]! No free key item in Toroia .[Kmain] Randomize key items ..[Ksummon]! Mix with summon quest rewards ..[Kmoon]! Mix with moon boss rewards ..[Kmiab]! Mix with monster-in-a-box chests ..[Knofree]! No free key item in Toroia ..<> Underworld access ...(Kforce:magma) Guarantee underworld access via Magma Key ...(Kforce:hook)! Force underworld access via Hook route ..[Kunsafe]! No safety checks
The . indicates level of indentation; indented items appear as a dropdown below their parent item. <> indicates a section or subsection that is not itself a flag. [] maps a line to its associated flag as an individually selectable item. () at the same level of indentation indicates mutually exclusive flags. ! indicates a red (dangerous) flag.
uispec_flagdescriptions.txt
(in the FreeEnt/server
directory) maps flag names to their descriptions on the website.
You may notice that just updating all of the above files is insufficient to have the generator and website recognise your new flag. This is because they depend upon information that is compiled / transpiled from these files as opposed to the files directly.
For convenience, there is a compile_all_specs.bat
(Windows) / compile_all_specs.sh
(other operating systems) script available that runs all of the steps necessary to update the compiled files from the base specs. Once you've made all of the changes you need to the above files, simply run this script to make your flag available on the website and to the generator.