# PaintMyKI5 A Project Zomboid Build 42 mod that lets players repaint supported KI5 vehicles in singleplayer, hosted multiplayer, and dedicated servers. ## Painting vehicles Stand outside a supported, stopped vehicle and right-click it, then choose **Paint vehicle**. The window shows every scanned skin, its raw texture preview, and the paint available in your carried inventory (including nested bags). When sibling texture filenames share a prefix, the skin list shows only the distinct suffix (`Green`, `Seafoam`, and so on); other entries keep their full filename as a fallback. Every repaint costs exactly one full B42 paint bucket worth of material. B42 paint buckets use `UseDelta = 0.1`, giving 10 uses per bucket. Those 10 uses are split fractionally across the selected texture's scanned colors. A 60% gray/20% green/20% white skin therefore costs 6 gray, 2 green, and 2 white uses. Small color percentages are retained rather than rounded away. Painting uses a networked timed action. On multiplayer servers, the server rechecks the vehicle, selected skin, distance, movement, unchanged starting skin, and the acting player's paint immediately before it consumes anything. The server then applies and broadcasts the skin. The painting action never accepts costs or inventory totals supplied by the client. This protects the mod's normal painting flow. Build 42 also contains a generic vanilla `vehicle/setSkinIndex` command used by other game tooling; hardening or removing that unrelated base-game command is outside this mod's scope. ## Vehicle color scanner The scanner: - searches `D:\SteamLibrary\steamapps\workshop\content\108600` by default; - deduplicates root and versioned `mod.info` files requiring `damnlib`; - selects the newest installed `42.x` content layer; - identifies self-propelled cars from their vehicle scripts; - maps each `skin` texture to its exact in-game ID, such as `Base.92nissanGTR`; and - discovers the 15 full paint buckets from the installed B42 game data; - prints pixel-derived percentages using exact item IDs such as `Base.PaintGreen`, `Base.PaintGrey`, and `Base.PaintWhite`; and - writes the exact proportional use requirements consumed by the in-game menu. The tool reads the authoritative palette from `ISPaintMenu.lua` and verifies each entry against the bucket definitions in `drainable.txt`. Empty buckets and spray paint are excluded. The scanner compares sibling skins with matching UV layouts to isolate body-sized areas that actually change between paints, which removes fixed glass, trim, grilles, and interiors from the mix. Within those areas it preserves hue through dark shading; single skins and small livery-only differences retain the conservative perceptual Lab fallback. The development tool and its tests live under [`scanner/`](scanner/). Install Python 3.11 or newer, then run it from the repository root: ```powershell python -m pip install -r scanner/requirements.txt python -m scanner --quiet ``` By default it writes the complete runtime data table to: ```text 42.20/media/lua/shared/PaintMyKI5/PaintMyKI5VehiclePaintData.lua ``` The in-game menu reads `PaintMyKI5.VehiclePaintData`. The generated table contains the palette, 10-use bucket capacity, exact vehicle IDs, zero-based skin indices, texture references, Workshop/mod metadata, paint item IDs, percentages, and proportional uses. It excludes local absolute paths and timestamps, so identical inputs produce identical Lua. To scan another Steam library: ```powershell python -m scanner --quiet --workshop-root "E:\SteamLibrary\steamapps\workshop\content\108600" ``` If Project Zomboid itself is installed elsewhere, pass both locations: ```powershell python -m scanner --quiet ` --game-root "E:\SteamLibrary\steamapps\common\ProjectZomboid" ` --workshop-root "E:\SteamLibrary\steamapps\workshop\content\108600" ``` Run the tests with: ```powershell python -m unittest discover -s scanner/tests -v ``` The headless Lua logic and syntax checks use Lupa without adding a runtime dependency to the mod: ```powershell uv run --with lupa python scanner/tests/run_lua_tests.py ```