Skip to content

Instantly share code, notes, and snippets.

@boneskull
Last active March 2, 2020 20:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save boneskull/fb08f25bf790e27fd69639ef7806db90 to your computer and use it in GitHub Desktop.
Save boneskull/fb08f25bf790e27fd69639ef7806db90 to your computer and use it in GitHub Desktop.
HexFiend template for Terraria .wld files
proc tile_entity {} {
set tile_entity_type [uint8]
int32 "ID"
int16 "x"
int16 "y"
if {$tile_entity_type == 0} {
int16 "Target Dummy"
} elseif {$tile_entity_type == 1} {
itemstack ""
} elseif {$tile_entity_type == 2} {
section "Logic Sensor" {
uint8 "Logic Check"
bool "Enabled"
}
} else {
entry "Type" "(unknown)" 1
}
}
proc itemstack {index} {
set qty [int16]
if {$qty > 0} {
section "Stack $index" {
entry "Qty." $qty 1
int32 "Item ID"
set modifier [uint8]
if {$modifier != 0} {
entry "Modifier" $modifier 1
}
}
}
}
proc chest {max_items} {
position "Position"
tstr "Name"
for {set i 0} {$i < $max_items} {incr i} {
itemstack $i
}
}
proc quadrant args {
foreach arg $args {
section $arg {
int32 "Left X-coord"
int32 "Center X-coord"
int32 "Right X-coord"
int32 "Quadrant 1"
int32 "Quadrant 2"
int32 "Quadrant 3"
int32 "Quadrdant 4"
}
}
}
proc tstr args {
set result [uleb128]
foreach arg $args {
if {$result > 0} {
str $result "ascii" $arg
} else {
entry $arg "(empty string)" 1
}
}
}
proc hardmode_ore args {
set ore [int32]
if {$ore == 107} {
set ore "Cobalt"
} elseif {$ore == 108} {
set ore "Mythril"
} elseif {$ore == 111} {
set ore "Adamantite"
} elseif {$ore == 221} {
set ore "Palladium"
} elseif {$ore == 222} {
set ore "Orichalcum"
} elseif {$ore == 223} {
set ore "Titanium"
} else {
set ore "Unknown"
}
foreach arg $args {
entry $arg $ore 1
}
return $ore
}
proc position args {
foreach arg $args {
section $arg {
int32 "X"
int32 "Y"
}
}
}
proc bool args {
set byte [uint8]
set result [expr {$byte == 0 ? "False" : "True"}]
foreach arg $args {
entry $arg $result 1
}
return $result
}
proc uleb128 args {
set result 0
set shift 0
set count 0
while {true} {
set byte [uint8]
if {$shift == 63 && $byte != 0 && $byte != 1} {
break
}
set result [expr {$result | (($byte & -129) << $shift)}]
incr count
incr shift 7
if {$byte < 128} {
break
}
}
foreach arg $args {
entry $arg $result $count
}
return $result
}
little_endian
section "Header" {
int32 "Version"
str 7 "ascii" "Signature"
uint8 "Savefile Type"
uint32 "Revision"
uint64 "Favorite"
int16 "Offset Count"
section "Offsets" {
set header_offset [int32 "Header"]
set tiles_offset [int32 "Tiles"]
set chests_offset [int32 "Chests"]
set signs_offset [int32 "Signs"]
set npcs_offset [int32 "NPCs"]
set tile_entities_offset [int32 "Tile Entities"]
set pressure_plates_offset [int32 "Pressure Plates"]
set town_manager_offset [int32 "Town Manager"]
set footer_offset [int32 "Footer"]
# garbage
int32
}
section "Properties" {
set tile_frame_importances_size [int16]
set tile_frame_importances [list]
section "Tile Frame Importances" {
for {set i 0} {$i < [expr {ceil($tile_frame_importances_size / 8.0)} ]} {incr i} {
lappend tile_frame_importances [uint8 "TFI $i"]
}
}
set world_name [tstr "World Name"]
section "Generator" {
tstr "Seed"
uint64 "Version"
}
uuid "UUID"
set world_id [int32 "ID"]
section "Bounds" {
int32 "Left"
int32 "Right"
int32 "Top"
int32 "Bottom"
}
set world_height [int32 "World Height"]
set world_width [int32 "World Width"]
bool "Expert"
uint64 "Created On"
section "Style Info" {
uint8 "Moon"
quadrant "Trees"
quadrant "Moss"
int32 "Underground Snow"
int32 "Underground Jungle"
int32 "Hell"
}
position "Spawn Point"
double "Underground Level"
double "Cavern Level"
double "Current Time"
bool "Daytime"
uint32 "Moon Phase"
bool "Blood Moon"
bool "Eclipse"
position "Dungeon Entrance"
set evil_type [uint8]
entry "Evil Type" [expr {$evil_type != 0 ? "Crimson" : "Corruption"}] 1
section "Bosses Killed" {
bool "Eye of Cthulhu"
bool "Eater of Worlds"
bool "Skeletron"
bool "Queen Bee"
bool "The Twins"
bool "The Destroyer"
bool "Skeletron Prime"
bool "Mechanical Boss"
bool "Plantera"
bool "Golem"
bool "King Slime"
}
section "Saved NPCs" {
bool "Goblin Tinkerer"
bool "Wizard"
bool "Mechanic"
}
section "Events Completed" {
bool "Goblin Army"
bool "Clown Killed"
bool "Frost Moon"
bool "Pirate Invasion"
}
section "Shadow Orb" {
bool "Smashed"
bool "Meteorite Spawned"
int32 "Smash Counter"
}
int32 "Smashed Altar Count"
bool "Hardmode"
section "Invasion Status" {
int32 "Delay"
int32 "Size"
set invasion_type [int32]
set invasion_type [expr {$invasion_type == 0 ? "None" : $invasion_type == 1 ? "Goblin" : $invasion_type == 2 ? "Frost" : $invasion_type == 3 ? "Pirate" : "Martian Madness"}]
entry "Invasion Type" $invasion_type 1
double "Position"
double "Slime Rain Time Left"
}
uint8 "Sundial Cooldown"
section "Rain Status" {
bool "Active"
int32 "Time Left"
float "Max Rain"
}
section "Hardmode Ores" {
hardmode_ore "Hardmode Ore 1"
hardmode_ore "Hardmode Ore 2"
hardmode_ore "Hardmode Ore 3"
}
section "Backgrounds" {
uint8 "Forest"
uint8 "Corruption"
uint8 "Jungle"
uint8 "Snow"
uint8 "Hallow"
uint8 "Crimson"
uint8 "Desert"
uint8 "Ocean"
}
section "Clouds" {
int32 "Background"
int16 "Count"
float "Wind Speed"
}
section "Angler Quests" {
set players_count [uint8]
for {set i 0} {$i < $players_count} {incr i} {
tstr "Player $i Quest Complete"
}
bool "Angler Saved"
int32 "Quest Fish ID"
}
bool "Stylist NPC Saved"
bool "Tax Collector NPC Saved"
int32 "Invasion Size Start"
int32 "Cultist Delay"
section "Mob Kill Counts" {
set mob_kill_count [int16]
for {set i 0} {$i < $mob_kill_count} {incr i} {
set count [int32]
if {$count > 0} {
entry "Mob ID $i" $count 1
}
}
}
bool "Fast-Forward Time"
section "More Bosses Slain" {
bool "Duke Fishron"
bool "Martian Saucer"
bool "Lunatic Cultist"
bool "Moon Lord"
bool "Pumpking"
bool "Mourning Wood"
bool "Ice Queen"
bool "Santa-NK1"
bool "Everscream"
bool "Solar Pillar"
bool "Vortex Pillar"
bool "Nebula Pillar"
bool "Stardust Pillar"
}
section "Lunar Events" {
bool "Solar"
bool "Vortex"
bool "Nebula"
bool "Stardust"
bool "Active"
}
section "Party" {
bool "Party Center Active"
bool "Natural Party Active"
int32 "Party Cooldown"
set partying_npc_count [int32]
if {$partying_npc_count > 0} {
section "Partying NPCs" {
for {set i 0} {$i < $partying_npc_count} {incr i} {
int32 "Partying NPC $i"
}
}
}
}
section "Sandstorm" {
bool "Active"
int32 "Time Left"
float "Severity"
float "Intended Severity"
}
bool "Bartender Saved"
section "Old One's Army" {
bool "Tier 1"
bool "Tier 2"
bool "Tier 3"
}
}
}
# skip tiles; it takes too long to compute
goto $chests_offset
section "Chests" {
set chests_count [int16 "Chest Count"]
set chest_max_items [int16 "Max Items per Chest"]
for {set i 0} {$i < $chests_count} {incr i} {
section "Chest $i" {
chest $chest_max_items
}
}
}
goto $signs_offset
section "Signs" {
set signs_count [uint16 "Sign Count"]
for {set i 0} {$i < $signs_count} {incr i} {
section "Sign $i" {
tstr "Text"
position "Position"
}
}
}
goto $npcs_offset
section "NPCs" {
set has_more_npcs [bool]
set i 0
while {$has_more_npcs} {
section "NPC $i" {
int32 "Entity ID"
tstr "Name"
float "x"
float "y"
set is_homeless [bool "Homeless"]
if {!$is_homeless} {
position "Home Position"
}
}
set has_more_npcs [bool]
incr i
}
}
section "Mobs" {
set has_more_npcs [bool]
set i 0
while {$has_more_npcs} {
section "NPC $i" {
int32 "Entity ID"
float "x"
float "y"
}
set has_more_npcs [bool]
incr i
}
}
goto $tile_entities_offset
section "Tile Entities" {
set tile_entities_count [int32 "Tile Entities Count"]
for {set i 0} {$i < $tile_entities_count} {incr i} {
section "Tile Entity $i" {
tile_entity
}
}
}
goto $pressure_plates_offset
section "Pressure Plates" {
set pressure_plate_count [uint32 "Pressure Plate Count"]
for {set i 0} {$i < $pressure_plate_count} {incr i} {
position "Pressure Plate $i"
}
}
goto $town_manager_offset
section "Towns" {
set house_count [uint32 "House Count"]
for {set i 0} {$i < $house_count} {incr i} {
section "Room $i" {
int32 "NPC ID"
position "Position"
}
}
}
goto $footer_offset
section "Footer" {
bool "OK"
set name [tstr "Name"]
set id [int32 "ID"]
entry "Valid Name" [expr {$name == $world_name ? "True" : "False"}] 1
entry "Valid ID" [expr {$id == $world_id ? "True" : "False"}] 1
}
@boneskull
Copy link
Author

This template breaks out the non-tile data in a Terraria v1.3.5.3 World (.wld) file, for ease of inspection & comparison.

Usage:

  1. Get HexFiend
  2. Copy this file into your templates directory (~/Library/Application Support/com.ridiculousfish.HexFiend/Templates/)
  3. Open a Terraria .wld file
  4. Show the template pane via Views > Binary Templates
  5. Select the terraria-wld template from the pane's dropdown (if already selected, choose "refresh")

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