Skip to content

feat: plot Midtown breakables on the current minimap - #460

Open
kai8484 wants to merge 17 commits into
developfrom
new-midtown-breakables-map
Open

kai8484 wants to merge 17 commits into
developfrom
new-midtown-breakables-map

Conversation

@kai8484

@kai8484 kai8484 commented Oct 6, 2026 •

Copy link
Copy Markdown

Summary

The crate and golden statue maps were still drawn on the pre-rework Midtown minimap. This moves the breakables plots onto the current street map and adds heavy crates and healing snacks.

  • New base map: assets/minimap_midtown.png, the newest minimap_midtown_mid texture from pak01, used at its native 1024x1024. Deadbot only downloads dl_midtown.vpk, not pak01, so the image is committed. scripts/update_minimap.py regenerates it from a local Deadlock install whenever the map changes.
  • Categories: crates, buff containers (golden statues), heavy crates (citadel_breakable_prop_tough_crate) and healing snacks (citadel_pickup_floating_health). Each gets its own map, plus breakables_map.png with all of them on one map.
  • Rendering: one colour per category, with a thin dark outline so neighbouring dots stay distinct, and a compact legend showing per-category counts. The new drawing methods are place_dots and add_compact_legend on MapPlotter, which now also accepts an output_size.
  • Metadata: midtown-metadata.json gains heavy_crate_count and healing_snack_count.

Output names

The existing output names are unchanged: crate_map.png, golden_statues_map.png, shops_map.png. This PR adds heavy_crate_map.png, healing_snack_map.png and breakables_map.png. All three new files are registered in IMAGE_FILE_MAP, so they will be uploaded as new File: pages.

Behaviour changes

  • The crate and statue maps no longer colour-code subtypes: vent access, glitched, and mid-boss/T2 spawns that appear after 10 minutes. Each category is a single colour.
  • The shops map is untouched and still uses the old minimap_midtown_mid_opaque.png. Upscaling the transparent new texture to 2000px rendered badly, so moving shops onto the new map is left for a follow-up.

Testing

Ran locally against client version 6753:

deadbot.py -d -p --parse_map -u --dry_run --english-only
  • The run completed and wrote all six PNGs to output/assets/.
  • The dry-run upload listed all six File: targets.
  • Counts: crate 423, golden statues 166, heavy crate 73, healing snack 36.
  • ruff check . passes with the pinned ruff 0.15.22.

The legend font falls back to DejaVu Sans Bold on the Linux image, so legend text will look slightly different from local Windows renders.

🤖 Generated with Claude Code

Parsed data in deadlock-data PR - Reopen deadbot PR or run deploy workflow for this branch here to reparse the data

kai8484 and others added 2 commits October 6, 2026 15:51
The breakables plots were drawn on the pre-rework Midtown minimap. They now use
the current street map (extracted from pak01 by scripts/update_minimap.py, since
deadbot only downloads dl_midtown.vpk) at its native 1024x1024 resolution, with
one dot colour per category and a compact legend with per-category counts.

Adds heavy crates and healing snacks alongside crates and buff containers
(golden statues), plus a combined breakables map. Existing output names
(crate_map.png, golden_statues_map.png, shops_map.png) are unchanged; the new
ones are heavy_crate_map.png, healing_snack_map.png and breakables_map.png.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@LVL1024

LVL1024 commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator

Not a full code review (I'l leave that to hassayag), but a few things I noticed:

  • The breakables maps have a corner caption like main 1024x1024 markers=423. Looks like a leftover debug note, I'd remove it or replace it with a plain title like Crates or Healing Snacks. (The shops map doesn't have it.)
  • There's some dead helper code: create_circle_marker, place_circle_markers, and add_circle_legend don't appear to be used anymore.
  • Is there a reason for dropping the sub-types on the crate and buff-container maps?
  • Would it make more sense to fold heavy crates into the crate map rather than a separate map?
  • On the font: the server image doesn't have the font the code looks for, so it silently falls back to Pillow's built-in font instead of the bold one.

- Split each breakable kind by its first spawn time (3:00, 5:00, 10:00), read
  from each entity's breakable_spawn_group, which indexes
  m_BreakableSpawnTimeDesc in generic_data. initial_spawn_time_override is -1
  on every breakable now, so it no longer identifies late spawns.
- Add per-spawn-time maps for each kind and for all breakables together
  (e.g. crate_5min_map.png, everything_10min_map.png), plus all_crates_map.png
  and everything_map.png. midtown-metadata.json gets per-kind spawn counts.
- Replace the debug caption with a map title and a divider above the legend.
- Remove the now unused circle marker helpers from MapPlotter.
- Install fonts-dejavu-core in the Docker image so legends use DejaVu Sans
  Bold instead of falling back to Pillow's built-in font.
- Add [[Category:Maps]] to map file pages: as the description of new
  uploads, and appended to existing file pages that lack it.
- Fix GenericParser._remove_prefixes renaming keys inside lists of the shared
  generic_data in place, which broke parsers that run after it.
  generic-data.json output is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kai8484

kai8484 commented Oct 6, 2026

Copy link
Copy Markdown
Author

Thanks for the review! I've worked through each point:

1. Corner caption. Replaced the debug-style caption with a plain title for each map, e.g. "Crates" or "All breakables spawning at 5:00". Each legend row below it is just a colour swatch, the name and the count.

2. Dead helpers. Removed create_circle_marker, place_circle_markers and add_circle_legend.

3. Sub-types. The old fields stopped working:

  • initial_spawn_time_override is -1 on every breakable now.
  • None of the hardcoded "glitched" coordinates exist on the reworked map.

Spawn timing now comes from each entity's breakable_spawn_group. That's an index into m_BreakableSpawnTimeDesc in generic_data, so nothing is hardcoded:

3:00 5:00 10:00
Crate 338 83 2
Heavy crate 59 8 6
Buff container 148 10 8

4. Heavy crates. There are now separate crate and heavy crate maps plus all_crates_map.png with both. There are also per-spawn-time maps for each kind and for everything together (crate_5min_map.png, everything_10min_map.png, etc.).

5. Font. Good catch. Added fonts-dejavu-core to the Dockerfile. I built the image and ran the map parser inside it with the Linux entity helper: it now uses DejaVu Sans Bold and gives the same counts as on Windows. This also fixes the shops legend, which had the same fallback problem.

Also, all uploaded map files now get [[Category:Maps]] on their file page. New files get it on upload, and existing file pages get it added if it's missing.

All tested locally with a full -p --parse_map -u --dry_run run and the pinned ruff.

@hassayag

hassayag commented Oct 7, 2026

Copy link
Copy Markdown
Member

This looks pretty good on the output side, so can't complain. I'm not that familiar with the source code though so I'll give the map master @ThePyrotechnic a chance to look at this first

@ThePyrotechnic

Copy link
Copy Markdown
Contributor

Of course I missed a major update while away on a trip… luckily I’m on the plane home now so I’ll check it out today 👍

@ThePyrotechnic

ThePyrotechnic commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Question @kai8484
What do you think of this styling? I increased the font size for the legend and added a background to the new map. The scaling looks solid, the issues you were seeing were probably a result of the transparency. If you think the markers should be larger we can do that, too. The cost is that there will be more overlap, but not a deal-breaker. At the current scale, zooming to 100% yields a very readable map.
all_crates_map

@ThePyrotechnic ThePyrotechnic left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've also checked the updated map with the shops, and everything looks good. Pending your feedback on the style I suggested and my inline comments below I'll push a commit to your branch with the style + shop changes
(new values for the base shops):

{'origin': [-1280.0, -10000.0, 100]},  # Hidden King base shop
{'origin': [1280.0, 10000.0, 100]},  # Archmother base shop

Comment thread src/parser/parsers/game_map/__main__.py
Comment thread src/parser/parsers/game_map/__main__.py Outdated
- Plot breakables and shops on minimap_midtown_opaque.png at the default
  2000px output size instead of the transparent map at native resolution.
- Enlarge the breakables legend and switch it to a white background with
  black text.
- Move the base shop markers to their positions on the current map.
place_dots repeated the world-to-pixel maths to keep sub-pixel precision.
_world_to_pixel now returns floats, and place_image_markers truncates them
to ints as before. Output is pixel-identical.
The category check read every File: page from the wiki even on dry runs.
Restore the early continue so dry runs make no wiki calls for assets.
Remove the unused swatch_dy offset and its commented-out value, and drop
"dark" from the docstring now that the legend has a white background.
_breakables_plot read self.spawn_order, which only run() set, so calling it
on its own raised AttributeError. run() now keeps the spawn order local and
passes it in.
MAPS repeated each kind's file stem and title from BREAKABLES. Each kind's
own map is now built from BREAKABLES, and MAPS is renamed to COMBINED_MAPS
and keeps only the maps that plot several kinds together. Output is
unchanged.
Lists every map file stem the parser can generate, including one per
breakable spawn time, so the wiki uploader can derive its file list
instead of hardcoding it.
IMAGE_FILE_MAP hardcoded the map file names and spawn times, and had
drifted from the parser: the combined maps are now written as
all_breakables*_map.png but were uploaded as everything*_map.png.

The uploader now builds the list from map_file_stems, using the spawn
times in the parsed generic-data.json. Missing map files are logged at
trace level, since not every stem is generated on every run.
output_size now defaults to None, which uses the base map without
resampling. The Midtown maps pass MAP_OUTPUT_SIZE (2048), an exact 2x
upscale of the 1024px base map, instead of the old 2000px default.
place_dots took the radius in pixels, tuned for the 1024px map, so dots
shrank relative to the map when upscaled. The radius is now a fraction of
the output width, matching place_image_markers' size, and keeps 3.45px at
1024px (6.9px on the 2048px maps). The outline stays 1px.
Log a warning when a spawn time has no colour left and reuses its kind's
last one, or when a kind has entities both with and without a spawn time.
The fallback colours are unchanged.
@ThePyrotechnic

Copy link
Copy Markdown
Contributor

@kai8484 I've pushed a handful of mostly smaller tweaks - feel free to tweak any them, or we can discuss further. Here's what I did:

Shop/map png update

  • e48e250: breakables and shops maps drawn on minimap_midtown_opaque.png, bigger white legend, base shop markers moved to their current spots.
  • I am looking to replace the python map updator with an extractor in DeadlockEntityHelper, that way we don't need to maintain our own parser (DeadlockEntityHelper uses the S2V library). For now I committed the opaque map

Plotting

  • 9b08822: place_dots reuses _world_to_pixel; output pixel-identical.
  • 78ea39e: MapPlotter's output_size defaults to None, meaning the base map is used without resampling. Both callers pass MAP_OUTPUT_SIZE = 2048, so maps are 2048px instead of 2000px.
  • 5737ac7: the dot radius is now a fraction of the output width, so this should be closer to your intended size
  • One problem is that the legend on the "all_breakables" map now overlaps the map itself, so I'll figure out a simple way to split the legend to the left and right to avoid this

Parser structure

  • ceafb27: spawn_order is passed into _breakables_plot instead of read from self.
  • e26930d: single-kind maps are built from BREAKABLES, and MAPS is now COMBINED_MAPS. This is mainly to avoid duplicating the title text to make maintenance a bit easier.
  • ecdfcc6: logs a warning when map colours fall back to a shared colour; the colours themselves are unchanged.

Upload

  • 9adc9bb: dry runs no longer contact the wiki for map files; the Maps category handling is kept for real runs.
  • e5e6076, d8eeb2a, 8483609: game_map exports map_file_stems, and the uploader gets map file names from it plus the spawn times in generic-data.json. Missing map files are now logged at trace level. This avoids us needing to adjust the uploader for new maps.

@kai8484

kai8484 commented Oct 11, 2026

Copy link
Copy Markdown
Author

Thanks @ThePyrotechnic, these look great. I ran the branch locally (full parse + dry-run upload) and all 19 maps generate and upload fine. Building the upload list from map_file_stems is much better than my hardcoded one.

One small thing, not blocking: file size roughly doubled (~700 KB per map, 13 MB total). Palette PNGs (quantize) would probably halve it, if you think it's worth it.

Sorry for the Claude-written reply, I'm not at my PC but wanted to get back to you reasonably soon.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants