Skip to content

Instantly share code, notes, and snippets.


hatrat/ Secret

Last active Dec 24, 2020
What would you like to do?
Breaking down the features provided by PyTK or TMXL that work just by having those mods installed.


PyTK and TMXL both offer various passive features for maps, which require only that the mod providing the feature be installed. A "passive" feature here from TMXL could be used in a map loaded by Content Patcher or SMAPI as long as TMXL is installed, for example, and does not need to be in a TMXL pack specifically.

This allows mappers to do things like add additional layers, change the color of water in a location, or use image layers with parallax effects in their maps, while still using their framework of choice for loading their map.


extra layers

Additional layers you add with a map editor (such as Tiled) are not normally rendered in game. A new layer property is enough to make it appear as long as PyTK is installed, without additional side effects if PyTK is absent.

  • Create your additional layer. It can be named whatever you like, be in any order, and does not need a corresponding object layer if you don't want to make one.
  • Add a new property to the layer called either DrawAbove or DrawBefore, with the value being the name of the layer you want yours to drawn above or before.

Here's an example that will be drawn between the Back and Buildings layer. (Remember that this is not because of the position of the layer in the list on the right, which is just for viewing how it will look in-game. The property is what determines the order.)

Image Layers


draw conditions

If you only want your new layer drawn sometimes and not all the time, you can tell PyTK to only render it once certain requirements are met. It just takes one more new property called DrawConditions. It accepts all event preconditions, and can also use Lua conditions if needed. Here's an example of a layer that's drawn underneath the Back layer, but only if you've married Abigail. See conditions for a more detailed breakdown of possible conditions in PyTK-based mods. (aka TODO)

@LoadWater (bool)

  • Add a new map property to your map
  • Make it a bool type
  • Check the box
  • (Alternatively, you can make it a string and give it a value of T.)

The game's animated water tiles are partly made up of the sprites on your tilesheet, and partly from the wavy overlay that gets rendered over it. This overlay is only rendered in non-desert areas flagged as Outdoors, in the Sewers, and in the Submarine. This property will try to force the game to render water as if it were outside.

@WaterColor (color)

Mappers are not normally able to change the tint of water tiles without editing a water overlay in LooseSprites. Even then, the way they are mixed may give a result you didn't intend and lead to some trial and error. @WaterColor is a map property that lets you change the color of all water tiles for a specific map.

Color (color)

Layers and tiles can be tinted, too. Add a new layer or tile property called @Color of the color type, then use the color picker to choose how you want it tinted. (todo add screenshots)

Background Color (color)

Background Color is a standard map property in Tiled that can be read by PyTK. It changes the color you see past map boundaries or under transparent/missing tiles.



PyTK allows you to use higher resolution textures for things that would otherwise need to be a fixed size, just by adding a json file next to the png you want to use. If your png is called mytilesheet.png, then your json file should be named mytilesheet.pytk.json. An example:

  "Scale": 4,

Here's a sample-pack that uses Content Patcher to edit the trees in spring_outdoorsTileSheet to replace them with higher resolution ones provided. It only uses Scale inside the json, because it's not animated.
(TODO: replace sample pack with one specifically for that)

Lua Scripts


crop layers

Ever wanted to make an NPC garden that actually grew crops? Crop layers can even be harvestable.

some parsnips that will go through growth phases in game

  • Create a new layer in Tiled. It needs to be prefixed with either all_Crops or <season>_Crops, like spring_Crops_yay
  • Add the Maps/springobjects.png tilesheet to your map, if it's not already there. Don't forget to put a z in front of the name in Tiled (not the file name).
  • Find the crop you want to plant (or its seeds) and paint those tiles onto your crops layer.
  • Add layer or tile properties. Here are the properties you can use:
    • AutoWater: (bool). Sets whether or not these need to be watered like farm crops. (You might check this box for an NPC garden that is taken care of by the owner, for example.)
    • CanBeHarvested: (bool). Checking the box allows you to harvest the crops once they are ready. Leaving this unchecked will call HarvestAction when clicking crops (if defined).
    • Conditions: (string) Set conditions for this crop layer, such as year or event seen. Takes event preconditions and Lua conditions like other PyTK condition fields. (Example: O Abigail for when married to Abigail.)
    • HarvestAction: (string) Tile action to call when you attempt to harvest non-harvestable crops. (Example: Say These aren't your crops!)
    • HideSoil: (bool) When checked, crops will grow without the tilled dirt graphics under them.
    • IgnoreSeason: (bool) When checked, crops placed in out-of-season layers (or an all_Crops layer) will grow out of season instead of dying.
    • StartPhase: (int or string) Sets the initial growth stage of the crops.

Can I grow JSON Assets crops? Yes! Paint any tiles down where you want your JA crop to grow, and then add a tile property of Name and set it to the exact name of the JA crop.

additional tile actions

TMXL adds several new tile actions you can use in your maps. Unless otherwise specified, they also work as TouchActions.


Calls a vanilla tile action. Occasionally useful to make an otherwise vanilla action conditional, which only works with custom actions. Usage: Action|Game Warp 76 9 Mountain


Warp the player to a map at the specified coordinates. NPCs will not use this for pathing. Usage Action|LoadMap Name X Y


Invokes the tile action specified by a Success property if the active object is a specified amount (at minimum) of the specified object ID. Requires further properties on the same tile:
Success Action triggered when using the right object in at least the right amount
Failure Action triggered when using the wrong object or not enough
Default Action triggered when holding no object

Action|Lock 5 388 [persist] [recall]
Default|Say Default (show text 'default' when no object is in hand)
Failure|Say Failure (show text 'failure' when either the active object is not the correct item, or there is not enough of it)
Success|Say Success (show text 'success' when you're holding at least the required amount of the right item, and remove that number - in this case 5 pieces of wood)
recall|Say recall (optional - show text 'recall' every time you click on it after the initial success. persists through game reload)
(Note that Say is used here just as an example - you can trigger any tile action at any stage, including custom ones.)



Usage: Action|Say your text here

Say Dwarvish

Usage: Action|Say Dwarvish your text here


Usage: Action|SwitchLayers Layer1:Layer2

SwitchLayers with tile ranges

SwitchLayers Layer1:Layer2:14:17 Switches only the specified Tile between layers x:y

SwichLayers Layer1:Layer2:1-5:5-7 Switches the specified Area between layers x1-x2:y1-y2

SwitchLayers Actions can be combined by just writting them one after the other exp: SwitchLayers Buildings:BuildingsOpen:4:6-9 Buildings:BuildingsOpen:9:5 Front:FrontOpen:4:6-9 AlwaysFront:AlwaysFrontOpen:4:6-9

conditional tile actions

custom tile actions


Tiled will not allow you to save your map as a tbin if you use the color property. If for some reason you can't use the more fully featured tmx format, you can instead add this property as a string, then write your color in hex using either #RGB or #ARGB format. (Example: #86000 or #C786000 for a red color.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment