- Pack description is in manifest.json, including available Variants.
- Everything a pack provides is done through Lua, starting at scripts/init.lua.
- Data (that is loaded through Lua) is stored as JSON inside the pack.
- Images (that are referenced in JSON) are PNGs, GIFs or JPEGs inside the pack.
- Most strings/identifiers are case sensitive.
manifest.json
in the root of the pack.
The only things of consequence right now are:
{
"name": "<Readable Name>",
"package_uid": "<unique string for saves>",
"package_version": "<unique string for open and saves>",
"platform": "<platform>",
"platform_override": "<optional actual platform>",
"variants": {
"<some_variant_uid>": {
"display_name": "<Readable Name>",
"flags": [
"<some flag>"
]
}
},
"versions_url": "https://example.com/versions.json",
"min_poptracker_version": "0.23.1",
"target_poptracker_version": "0.23.1"
}
Other fields:
{
"game_name": "<Readable Name>",
"author": "<Readbale Names>"
}
Each pack can have multiple variants (e.g. map or compact).
platform_override
can be used to set the platform without changing the platform
value for compatibility reasons.
If platform is "snes", the snes autotracker is to be enabled.
If platform is "n64", the LuaConnector autotracker is to be enabled.
Currently supported flags:
"ap"
: pack supports Archipelago autotracking. See AUTOTRACKING.md."uat"
: pack supports UAT autotracking. See AUTOTRACKING.md."lorom"
: (SNES) game has LoROM mapping - if not listed in gameinfo.cpp"hirom"
: (SNES) game has HiROM mapping"exlorom"
: (SNES) game has ExLoROM mapping"exhirom"
: (SNES) game has ExHiROM mapping
versions_url
can be used for automatic updates. Information from global packs.json
takes precedence.
See https://github.com/black-sliver/PopTracker/tree/packlist for more information.
min_poptracker_version
will check if the version is compatible when loading the pack.
It can be written as x
, x.y
or x.y.z
.
target_poptracker_version
may influence behavior to not break a pack for breaking API or behavioral changes.
There is no guarantee that everything will have a compatibility layer, but it's best practice to put the latest known
working version number there.
Optional, settings.json
in the root of the pack.
Configures behavior of the pack.
{
"smooth_scaling": true|false|null, // configure the image scaling method. null = default = currently crisp
"smooth_map_scaling": true|false|null, // configure the image scaling method for maps. null = default = smooth
}
NOTE: User overrides for settings are merged with the pack, replacing individual keys, not the whole file.
-
When calling a provided method, use
:
instead of.
-
When loading files, the search path is ./ as well as ./variant/, so that
you can have global items in
items/items.json
OR per-variant items in[variant]/items/item.json
The following interfaces are provided:
string .ActiveVariantUID
: variant of the pack that is currently loadedbool :AddItems(jsonfilename)
: load items from jsonbool :AddMaps(jsonfilename)
: load maps from jsonbool :AddLocations(jsonfilename)
: load locations from jsonbool :AddLayouts(jsonfilename)
: load layouts from jsonint :ProviderCountForCode(code)
: number of items that provide the code (sum of count for consumables)mixed :FindObjectForCode(string)
: returns items forcode
or location section for@location/section
void :UiHint(name,string)
: sends a hint to the Ui, see Ui Hints. Only available in PopTracker, since 0.11.0bool .BulkUpdate
: can be set to true from Lua to pause running logic rules.
bool :LoadScript(luafilename)
: load and execute a lua script from absolute filename inside packrequire
can be used instead (since PopTracker 0.21.0)require
behaves mostly like Lua require since 0.25.6"foo.baz"
will try/scripts/foo/baz.lua
,/scripts/foo/baz/init.lua
,/foo/baz.lua
and/foo/baz/init.lua
...
contains mod name for relative require since 0.25.6
bool :AddMemoryWatch(name,addr,len,callback,interal)
: add a memory watch for auto-tracking, see AUTOTRACKING.mdbool :RemoveMemoryWatch(name)
: remove memory watch by name, available since 0.11.0bool :AddWatchForCode(name,code,callback)
: callback(code) will be called whenever an item changed state that canProvide(code). Only available in PopTracker, since 0.11.0, will return a reference (name) to the watch since 0.18.2. Use "*" to trigger for all codes since 0.25.5.bool :RemoveWatchForCode(name)
: remove watch by nameLuaItem :CreateLuaItem()
: create a LuaItem (custom item) instance
- see AUTOTRACKING.md
use ImageRef = string
ImageRef :FromPackRelativePath(filename)
: for now this will just return filename and path resoltuion is done later.
a string in the form of "1.0.0"
-- TODO: move to Tracker.PopVersion ?
a table representing an enum with the following constants:
None
, Partial
, Inspect
, SequenceBreak
, Normal
, Cleared
DEBUG
set to true to get more error or debug outputrequire
function, see ScriptHost:LoadScript
use ImageRef = string
ImageRef .Icon
: change the icon. UseImageReference:FromPackRelativePath
.string .IconMods
: icon modifier, see JSON's img_mods. Only available in PopTracker, since 0.11.0string .Name
: item's nameobject .ItemState
: (any) object to track internal state in luaclosure(LuaItem) .OnLeftClickFunc
: called when left-clickingclosure(LuaItem) .OnRightClickFunc
: called when right-clicking- TODO: Middle, Forward, Backward or a generalized onClick(button)
closure(LuaItem,string code) .CanProvideCodeFunc
: called to determine if item has codeclosure(LuaItem,string code) .ProvidesCodeFunc
: called to track progress, closure should returns 1 if code is provided (can provide && active)closure(LuaItem,string code) .AdvanceToCodeFunc
: called to change item's stage to provide code (not in use yet)closure(LuaItem) .SaveFunc
: called when saving, closure should return a lua object that works in LoadFuncclosure(LuaItem,object data) .LoadFunc
: called when loading, data as returned bySaveFunc
closure(LuaItem,key,value) .PropertyChangedFunc
: called when :Set is called and the value changed:Set(key,value)
: write to property store (NOTE: property store == .ItemState):Get(key)
: read from property store. not sure what this is good for if we have.ItemState
:SetOverlay(string)
: set overlay text (see JsonItem), only available in PopTracker:SetOverlayBackground(string)
: set overlay background (see JsonItem), only available in PopTracker, since 0.17.0:SetOverlayFontSize(int)
: set overlay font size (~pixels), only available in PopTracker, since 0.17.2.Owner
: returns empty table at the moment for compatibility reasons, since 0.18.2.Type
: gets the type of the item as string (always "custom"), since 0.23.0
Probably more to come.
bool .Active
: enable/disable itemint .CurrentStage
: set/get stage for staged itemsint .AcquiredCount
: set/get current amount for consumablesint .MinCount
: set/get min amount for consumables (available since 0.21.0)int .MaxCount
: set/get max amount for consumables (available since 0.14.0):SetOverlay(string)
: set overlay text (like count, for non-consumables), only available in PopTracker:SetOverlayBackground(string)
: set background: "#000000" is (A)RGB, "" is transparent, only available in PopTracker, since 0.17.0:SetOverlayFontSize(int)
: set overlay font size (~pixels), only available in PopTracker, since 0.17.2.Owner
: returns empty table at the moment for compatibility reasons, since 0.18.2.Increment
: sets or gets the increment (left-click) value of consumables.Decrement
: sets or gets the decrement (right-click) value of consumables.Type
: gets the type of the item as string ("toggle", ...), since 0.23.0.Icon
: like LuaItem.Icon, since 0.26.0. Prefer stages instead. Only implemented for toggles and static and exact behavior may change in the future.
Probably more to come.
.Owner
: returns empty table at the moment, see Locations.ChestCount
: how many chests are in the section.AvailableChestCount
: read/write how many chests are NOT checked.AccessibilityLevel
: read-only, giving one of the AccessibilityLevel constants
.AccessibilityLevel
: read-only, giving one of the AccssibilityLevel constants (will not give CLEARED at the moment), since 0.25.5
[
{
"name": "<Readable Name>",
"type": "<type>",
...
},
...
]
Type:
-
"progressive"
:-
has any number of states (
"stages"
) -
adds automatic "off" stage if
"allow_disabled": true
(default true) -
adds optional
"loop": false
to determine if the states should loop (last → first) when clicking -
adds optional
"initial_stage_idx": 0
-
adds array of states (
"stages"
)"stages": [ { "img": "path/to/img.png", "disabled_img": "path/to/disabled.png", // optional, grey img if missing "codes": "check_identifier", "secondary_codes": "state_identifier", // unused at the moment "inherit_codes": false, "img_mods": "@disabled", "disabled_img_mods": "...", "name": "optional name override" // since 0.21.1 }, ... ]
-
img_mods filter to be applied on the img
@disabled
: grey-scaleoverlay|path/to/img.png|overlay_filters...
: draw a second image over it; overlay_filters are applied to overlay (since 0.25.6)- NOTE: order matters, applied left to right
-
inherit_codes: true will make stage3 provide codes for item, stage1, 2 and 3 (default true)
-
-
"toggle"
:-
only has on/off
-
greyed-out version will be generated by the tracker
-
adds
img
andcodes
at the same level{ ... "img": "path/to/img.png", "img_mods": "optional_filter", "codes": "check_identifier" }
-
adds
disabled_img
: override img when off -
adds
disabled_img_mods
: likeimg_mods
but for off. Defaults toimg_mods
+"@disabled"
). Any value (e.g."none"
) disables defaults. -
adds
initial_active_state
: precollected if true, since 0.25.4
-
-
"consumable"
:- has AcquiredCount (0 = grey/disabled)
- adds
"min_quantity": 0
, since 0.21.0 - adds
"max_quantity": 0
- adds
"increment": 1
can be used if an item pickup is always a certain count, since 0.18.3 - adds
"decrement": 1
can be used if using an item always uses up multiple, since 0.18.3 - adds optional
"initial_quantity": 0
- adds optional
"overlay_background": ""
set text background color with "#000000" (A)RGB notation - adds optional
"overlay_font_size": 0
set font size of overlay text - adds alias
badge_font_size
foroverlay_font_size
-
"progressive_toggle"
:- like progressive with
allow_disabled: false
, but the current stage can be toggled between "on" and "off" - precollected overlay if
initial_active_state
is true, since 0.25.5
- like progressive with
-
"composite_toggle"
:- is linked to two items left and right that have to be defined before
- lua access is through linked items' .Active only
- adds
"item_left": "code"
and"item_right": "code"
- adds 4 stages via
"images": [
{
"left": false, "right": false,
// img, mods like stage
},
{
"left": true, "right": false,
// img, mods like stage
},
// ...
]
"toggle_badged"
:- display
"img"
over"base_item"
- toggle visibility of
"img"
with right mouse button - change underlying item with left mouse button
- precollected overlay if
initial_active_state
is true, since 0.25.4
- display
{
"name": "Some Item",
"type": "...",
"img": "path/to/item.png",
"codes": "some_item"
},
{
"name": "Combination's name",
"type": "toggle_badged",
"base_item": "some_item",
"img": "path/to/overlay.png",
"codes": "some_overlay"
}
Maps are referenced by name in layouts.
[
{
"name": "map_identifier",
"location_size": 24, // size of locations on the map, unit is pixels of img
"location_border_thickness": 2, // border around the locations
"img": "path/to/img.png"
},
...
]
TODO: we want to add more stuff, like displaying numbers besides locations
Locations define drops on maps, rules to have them accessible as well as the looks of it
[
{
"name": "Area name",
"short_name": "Area", // shorter version of name. currently unused
"access_rules": [
"<rule1>,<rule2>",
"<rule3>,<rule4>",
"{<checkrule1>, <checkrule2>}",
...
],
"visibility_rules": [
... // like access rules but for visibility of the location or section
],
"chest_unopened_img": "path/to/chest.png", // default if children do not override
"chest_opened_img": "path/to/chest.png",
"overlay_background": "#000000", // set background for number of unopened chests #(AA)RRGGBB
"color": "#ff0000", // color accent/tint of the location tooltip. currently unused
"parent": "parent's name", // read below
"children": [
{
"name": "Location or check name",
"access_rules": [
"<rule on top of parent's>",
...
],
"chest_unopened_img": "path/to/chest.png", // default if section does not override
"chest_opened_img": "path/to/chest.png",
"map_locations": [
{
"map": "map_name",
"x": 123,
"y": 234,
"size": 24, // override map default, since 0.21.1
"border_thickness": 2, // override map default, since 0.21.1
"restrict_visibility_rules": [
... // additional visibility rules for individual map locations, since 0.26
],
"force_invisibility_rules": [
... // additional visibility rules that hide the map location if true, since 0.26
]
},
... // having multiple locations seems to have problems?
],
"sections": [
{
"name": "Human readable name",
"clear_as_group": true|false, // one click does all checks in this section
"chest_unopened_img": "path/to/chest.png",
"chest_opened_img": "path/to/chest.png",
"item_count": 1, // number of checks in this section (all use the same image)
"hosted_item": "item", // this item will be checked when cleared
"access_rules": [
"<rule on top of parent's>",
...
],
"visibility_rules": [
"<rule on top of parent's>",
...
]
},
{
"ref": "Path/to/another/section" // links and displays a section from another location here
},
...
]
}
]
}
]
Locations:
Each map_location
is a square on the map and shows a popup with individual chests.
Rules:
Rules starting with $
will call the Lua function with that name, @<location>/<section>
will use the result of a different access rule, other rules will just look at items' code
(runs ProviderCountForCode(rule)).
Rules starting with ^
interpret the value as AccessibilityLevel instead of count. That is ^$func
can directly set the AccessibilityLevel, sometimes removing the need for []
and {}
(see below). Only available in PopTracker, since 0.25.6.
For $
rules, arguments can be supplied with |
. $test|a|b
will call test("a","b")
.
The return value has to be a number (count) or boolean (since v0.20.4).
Rules inside [
]
are optional (i.e. glitches work around this rule).
Rule-goups inside {
}
are a different set of rules to mark the section as "checkable but not collectible", marked blue on the map.
<rule1>-<rule4>
in example above are combined as: (<rule1> AND <rule2>) OR (<rule3> AND <rule4>)
have to be met to collect.
{<checkrule1>, <checkrule2>}
in example above are combined as: (<checkrule1> AND <checkrule2>)
have to be met to check.
Individual rules can be specified as json array instead of string, which allows to use ,
inside names or arguments. Only available in PopTracker, since 0.19.1.
Rules can be specified as a single string, which is equivalent to [[string]]
. Only available in PopTracker, since 0.25.6.
Parent:
With "parent"
, the location's parent can be overwritten. Since PopTracker v0.19.2.
This is useful to put a location from dungeons.json
into a location from overworld.json
,
which could also be done with @
access rules.
Sections: The popup is segmented into sections.
A room with magic and 3 chests could have a section for 1 magic and a section for the 3 chests.
Depending on the map it is also possible to have 1 location per chest, but checking that off takes longer.
Name is optional and will be displayed above the section.
Sections can be addressed from Lua with Tracker:FindObjectForCode("@location_name/section_name")
hosted_item
is a comma separated list of item codes that are always in this section.
item_count
is the number of checks (chests, ...) and defaults to 1 unless hosted_item
is used, in which case it defaults to 0.
ref
make this section a reference to another section, ignoring all other properties defined here. This can be used to have the same section in detailed and overworld maps.
Tracker Lua Interface:
Tracker:FindObjectForCode('@location_name/section_name')
returns a Section or nilTracker:FindObjectForCode('@location_name')
returns a Location or nil
Section Lua Interface:
.Owner
: probably points to location, but we return an empty table at the moment..Owner.ModifiedByUser
isnil
..ChestCount
: read how many chests are in the section.AvailableChestCount
: read/write how many chests are NOT checked.AccessibilityLevel
: read-only, giving one of the AccssibilityLevel constants
Location Lua Interface:
.AccessibilityLevel
: read-only, giving one of the AccssibilityLevel constants, since 0.25.5
Future: We probably want to add a different (additional) interface to Pop for this:
- Give every chest an id
Tracker:setChestState(id,state)
- we would then have pop-autotracking.lua and emo-autotracking.lua
- layouts define how the items and maps are placed in the UI
- layout definitions are a map of
"name" => widget
where widget can be some container, a reference, an item grid/array, a single item or a (world-)map - the named layout
"tracker_default"
is the root object of the tracker view - if
"tracker_default"
is missing,"tracker_horizontal"
or"tracker_vertical"
is used (no way for the user to pick yet) - the named layout
"tracker_broadcast"
is the root object of the broadcast view - the named layout
"settings_popup"
is the root object of a pack/variant specific settings window - the named layout
"tracker_capture_item"
is not supported yet ("item picker popup" for hints) - containers have
"content"
which can be an array of other widgets or a json object for a single other widget
the final hierarchy looks something like this: json root -> "tracker_default" -> "content" -> "content" -> ...
Properties:
{
"type": "{container,dock,array,tabbed,group,item,itemgrid,map,layout,recentpins}",
"background": "#000000", // background color #(AA)RRGGBB
"h_alignment": "{left,right,center,stretch}", // defaults to center for item grid
"v_alignment": "{top,bottom,center,stretch}",
"dock": "{top,bottom,left,right}", // if inside a dock, where to dock
"orientation": "{horizontal,vertical}", // how to orient children
"max_height": integer, // maximum height in px
"max_width": integer, // maximum width in px
"margin": "left,top,right,bootom",
"item_margin": "<horizontal>,<vertical>", // margin in px
"item_size": "<horizontal>,<vertical>", // 3=default=32, 4=48, other TBD, 10+=size in pixels
"item_h_alignment": "{left,right,center,stretch}", // align image inside item; PopTracker since 0.19.1
"item_v_alignment": "{top,bottom,center,stretch}", // as above; stretch is not implemented for either
"dropshadow": bool // enable/disable drop shadow, not implemented yet
}
Type:
"container"
: has a single child (because that's how containers work IRL)"dock"
: like array, but uses"dock"
to place children"array"
: like dock, but uses"orientation"
instead of"dock"
to place children"tabbed"
: tabs that switch between multiple children, has"tabs": [ {"title":"...","content":{...}} ]
"group"
: has a single child + a header ("header": "text"
)"item"
: a single item ("item": "item_code"
, )"itemgrid"
: has"rows"
as an array of rows, each being an array ofitem_code
strings"map"
: has optional"maps"
which is array of map ids, if missing all maps are added"layout"
: pastes a different named object here ("key": "name_of_layout"
)"recentpins"
: pinned items, uses{"style":"{wrapped,?}","compact":bool}
"text"
: has property"text": "string"
to display a string"canvas"
: has width, height and content - children have width, height, canvas_top and canvas_left; since 0.21.1
Margin:
Margin can alternatively be specified as "x,y" or single int and is an offset of the widget's position and size. Margin defaults to 0 for items and "inner arrays" (array inside array), 5 for everything else.
Instead of allowing Lua direct access to the UI/Widgets, there is a "Hints" interface. See global Tracker.
"ActivateTab"
: value = tab name, since 0.11.0