Created
March 17, 2026 14:13
-
-
Save pnkfelix/2fac6da2f9f462c187680842fa7ef989 to your computer and use it in GitHub Desktop.
botc token tiles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Blood on the Clocktower - Token Storage Tile (Square) | |
| // Parametric single-piece layered holder for 3D printing | |
| // Printer: Snapmaker U1, Slicer: Snapmaker Orca | |
| /* ── Token dimensions (official + tolerance) ── */ | |
| role_token_dia = 44.5; | |
| reminder_token_dia = 25.5; | |
| token_tolerance = 0.8; // ~0.4mm clearance per side | |
| role_cavity_dia = role_token_dia + token_tolerance; // 45.3mm | |
| reminder_cavity_dia = reminder_token_dia + token_tolerance; // 26.3mm | |
| role_r = role_cavity_dia / 2; // 22.65 | |
| reminder_r = reminder_cavity_dia / 2; // 13.15 | |
| /* ── Layer thicknesses ── */ | |
| base_thickness = 1.25; // 0.25 first layer + 5×0.2 | |
| reminder_depth = 1.8; // 9×0.2 | |
| role_depth = 2.0; // 10×0.2 | |
| total_height = base_thickness + reminder_depth + role_depth; // 5.2mm | |
| /* ── Structural ── */ | |
| wall_min = 1.2; // min wall from cavity to tile edge | |
| cavity_wall_min = 0.8; // min wall between adjacent reminder cavities | |
| finger_scoop_dia = 10; // finger notch between reminder cavities | |
| /* ── Reminder layout ── */ | |
| num_reminders = 2; | |
| corner_r = 2.0; // outer edge rounding | |
| // Two reminders along the diagonal of the square. | |
| // Center-to-center distance must be >= reminder_cavity_dia + cavity_wall_min. | |
| min_center_dist = reminder_cavity_dia + cavity_wall_min; // 27.1mm | |
| half_dist = min_center_dist / 2; // 13.55mm | |
| // Each reminder center is at (±half_dist/sqrt(2), ±half_dist/sqrt(2)) | |
| diag_offset = half_dist / sqrt(2); // ~9.58mm | |
| // Tile half-size: must contain reminders AND role cavity | |
| tile_half_for_reminders = diag_offset + reminder_r + wall_min; // ~23.93 | |
| tile_half_for_role = role_r + wall_min; // ~23.85 | |
| tile_half = max(tile_half_for_reminders, tile_half_for_role); | |
| tile_size = 2 * tile_half; | |
| // Reminder positions along the diagonal | |
| reminder_pos = [[ diag_offset, diag_offset], // top-right | |
| [-diag_offset, -diag_offset]]; // bottom-left | |
| /* ── Rounded square helper ── */ | |
| module rounded_square(size, height, r) { | |
| linear_extrude(height) | |
| offset(r = r) | |
| square([size - 2*r, size - 2*r], center = true); | |
| } | |
| /* ── Main geometry ── */ | |
| module tile() { | |
| difference() { | |
| // Solid body: rounded square | |
| rounded_square(tile_size, total_height, corner_r); | |
| // Role token cavity: centered, top layer | |
| translate([0, 0, base_thickness + reminder_depth]) | |
| cylinder(d = role_cavity_dia, h = role_depth + 0.01, $fn = 80); | |
| // Reminder token cavities: bottom layer, along diagonal | |
| for (pos = reminder_pos) { | |
| translate([pos[0], pos[1], base_thickness]) | |
| cylinder(d = reminder_cavity_dia, h = reminder_depth + 0.01, $fn = 60); | |
| } | |
| // Pass-through holes: cut through role layer above each reminder | |
| for (pos = reminder_pos) { | |
| translate([pos[0], pos[1], base_thickness + reminder_depth - 0.01]) | |
| cylinder(d = reminder_cavity_dia, h = role_depth + 0.02, $fn = 60); | |
| } | |
| // Finger scoop: small notch at the midpoint between the two | |
| // reminder cavities, cut from base through the full height, | |
| // so you can get a fingertip under a token edge | |
| translate([0, 0, base_thickness]) | |
| cylinder(d = finger_scoop_dia, h = total_height, $fn = 40); | |
| } | |
| } | |
| tile(); | |
| // ── Console diagnostics ── | |
| echo(str("Tile size: ", tile_size, "mm square")); | |
| echo(str("Total height: ", total_height, "mm")); | |
| echo(str("Diagonal offset: ", diag_offset, "mm per axis")); | |
| echo(str("Reminder center-to-center: ", min_center_dist, "mm")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment