Workers P2: Räume nach kind, Pokal-Seiten, graue Räume, Gebäudehülle
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fb331de1a6
commit
8555453a74
3 files changed
+660
No files matched your search
@@ -0,0 +1,114 @@
|
||||
// Gebäudehülle des Hustler-Hochhauses: Boden und Erde, Dach, Aufzugschacht, Etagenböden und -wände, Schachttüren mit Lampen,
|
||||
// Etagenschilder rechts außen und der Pausenschleier.
|
||||
// Portiert aus entwuerfe/scene-turm.js (drawOutside Z. 99-111, drawBuilding Z. 118-172) auf 10 Etagen. Die Stadtsilhouette,
|
||||
// das Rohrpost-Rohr und die Welle der Vorlage entfallen. Die Räume selbst zeichnet rooms.js (danach, über der Rückwand).
|
||||
// Etagenmaße kommen aus dem Layout, die Hüllenmaße (Turm x 14..230, Räume x 42..228) stehen hier. Kein React, kein Appwrite,
|
||||
// kein window/document.
|
||||
|
||||
import { px, tint, label, PAL, TEAM } from './sprites.js'
|
||||
import { WORLD } from './layout.js'
|
||||
|
||||
const GROUND_Y = 224 // Bodenlinie = Boden der Tresor-Etage (Erdgeschoss); darunter liegt der Keller
|
||||
const ROOF_Y = 4 // Oberkante der Dachlinie
|
||||
const HULL_X0 = 14 // Turm: linke Außenkante
|
||||
const HULL_W = 216 // Turm: Breite (x 14..230)
|
||||
const WALL_W = 2 // Wandstärke
|
||||
const SHAFT_X = 16 // Aufzugschacht x 16..40
|
||||
const SHAFT_W = 24
|
||||
const SHAFT_WALL_X = 40 // Trennwand zwischen Schacht und Räumen
|
||||
const ROOMS_X0 = 42
|
||||
const ROOMS_W = 186
|
||||
const DOOR_H = 18 // Schachttür: Sturz 18 über dem Boden
|
||||
const LAMP_X = 43
|
||||
const SIGN_DOT_X = 230 // Etagenschild: Punkt rechts neben der Außenwand, Text bei x 234
|
||||
const SIGN_X = 234
|
||||
const SIDE_DOOR_X = 225
|
||||
|
||||
const C = {
|
||||
wall: '#aab2c0',
|
||||
back: '#f3f4f7',
|
||||
strip: '#e6e9ef',
|
||||
shaft: '#e4e8ef',
|
||||
rail: '#d3d8e1',
|
||||
frame: PAL.metal2,
|
||||
mute: PAL.mute,
|
||||
lampOff: '#c3cad6',
|
||||
ground: PAL.metal,
|
||||
earth: '#f7f4f0',
|
||||
speck: '#e8e2da',
|
||||
post: '#d5dae3',
|
||||
doorWood: '#a8825f',
|
||||
}
|
||||
|
||||
// Erdflecken: [x, Abstand unter der Bodenlinie]; die mittleren liegen unter dem Keller und sind verdeckt
|
||||
const SPECKS = [[4, 7], [9, 15], [6, 25], [244, 9], [262, 17], [290, 8], [306, 19], [300, 26], [60, 28], [140, 30], [210, 27]]
|
||||
|
||||
// Boden, Erde, Dachlinie mit Fahne und eine Laterne links. Wird vor dem Turm gezeichnet.
|
||||
export function drawOutside(ctx) {
|
||||
px(ctx, 0, GROUND_Y + 1, WORLD.w, WORLD.h - GROUND_Y - 1, C.earth)
|
||||
px(ctx, 0, GROUND_Y, WORLD.w, 1, C.ground)
|
||||
for (const [x, dy] of SPECKS) px(ctx, x, GROUND_Y + dy, 2, 1, C.speck)
|
||||
// Laterne
|
||||
px(ctx, 6, GROUND_Y - 19, 1, 19, C.post)
|
||||
px(ctx, 4, GROUND_Y - 21, 5, 2, C.post)
|
||||
px(ctx, 5, GROUND_Y - 19, 3, 1, '#fff3c4')
|
||||
// Dachlinie und Fahne
|
||||
px(ctx, HULL_X0, ROOF_Y, HULL_W, 2, C.frame)
|
||||
px(ctx, 60, 0, 1, 4, C.frame)
|
||||
px(ctx, 61, 0, 4, 2, TEAM.freigabe)
|
||||
}
|
||||
|
||||
// Hülle, Schacht, Rückwände, Böden, Schachttüren mit Lampen (grün: Kabine steht auf der Etage) und die Etagenschilder.
|
||||
// t ist im Aufruf vorgesehen (Takt der Szene), die Hülle bewegt sich heute nicht.
|
||||
export function drawTower(ctx, layout, t, lift) {
|
||||
const floors = layout.floors
|
||||
if (floors.length === 0) return
|
||||
const topY = floors[0].top
|
||||
const bottom = floors[floors.length - 1].floorY
|
||||
// Schacht mit Schienen
|
||||
px(ctx, SHAFT_X, topY, SHAFT_W, bottom - topY, C.shaft)
|
||||
px(ctx, SHAFT_X, topY, 1, bottom - topY, C.rail)
|
||||
px(ctx, SHAFT_X + SHAFT_W - 1, topY, 1, bottom - topY, C.rail)
|
||||
// Rückwand und Bodenstreifen jeder Etage
|
||||
for (const f of floors) {
|
||||
px(ctx, ROOMS_X0, f.top, ROOMS_W, f.h, C.back)
|
||||
px(ctx, ROOMS_X0, f.floorY - 3, ROOMS_W, 3, C.strip)
|
||||
}
|
||||
// Trennwand zum Schacht mit Türöffnung je Etage, Sturz und Etagenlampe
|
||||
px(ctx, SHAFT_WALL_X, topY, WALL_W, bottom - topY, C.back)
|
||||
floors.forEach((f, i) => {
|
||||
px(ctx, SHAFT_WALL_X, f.top, WALL_W, f.h - DOOR_H, C.wall)
|
||||
px(ctx, SHAFT_WALL_X, f.floorY - DOOR_H, WALL_W, 1, C.frame)
|
||||
px(ctx, LAMP_X, f.floorY - 14, 2, 2, lift.at(i) ? PAL.green : C.lampOff)
|
||||
})
|
||||
// Etagenböden, Fundament und Seitenwände
|
||||
for (const f of floors) px(ctx, HULL_X0, f.floorY, HULL_W, 1, C.wall)
|
||||
px(ctx, HULL_X0, bottom, HULL_W, 2, C.frame)
|
||||
px(ctx, HULL_X0, ROOF_Y, WALL_W, bottom + 2 - ROOF_Y, C.wall)
|
||||
px(ctx, ROOMS_X0 + ROOMS_W, ROOF_Y, WALL_W, bottom + 2 - ROOF_Y, C.wall)
|
||||
// Seitentür im Erdgeschoss (Tresor-Etage): hier gehen die Scouts in die Stadt
|
||||
const ground = floors.find((f) => f.id === 'tresor')
|
||||
if (ground) {
|
||||
const g = ground.floorY
|
||||
px(ctx, ROOMS_X0 + ROOMS_W, g - 14, WALL_W, 11, C.back)
|
||||
px(ctx, ROOMS_X0 + ROOMS_W, g - 3, WALL_W, 3, C.strip)
|
||||
px(ctx, SIDE_DOOR_X, g - 16, 8, 2, C.doorWood)
|
||||
px(ctx, SIDE_DOOR_X, g - 14, 2, 14, C.doorWood)
|
||||
px(ctx, SIDE_DOOR_X + 6, g - 14, 2, 14, C.doorWood)
|
||||
}
|
||||
// Schachtkopf mit Rolle
|
||||
px(ctx, 23, topY, 11, 3, C.frame)
|
||||
px(ctx, 24, topY + 1, 9, 1, C.ground)
|
||||
// Etagenschilder rechts außen: Punkt in der Teamfarbe des ersten Raums, Titel aus dem Layout
|
||||
for (const f of floors) {
|
||||
px(ctx, SIGN_DOT_X, f.top + 2, 2, 2, TEAM[f.rooms[0]?.team] ?? C.wall)
|
||||
label(ctx, f.title, SIGN_X, f.top + 1, { size: 11, color: C.mute, weight: 600 })
|
||||
}
|
||||
}
|
||||
|
||||
// Weißer Schleier mit „Pausiert“ über der ganzen Welt; nur bei look.paused
|
||||
export function drawPauseVeil(ctx, look) {
|
||||
if (!look.paused) return
|
||||
tint(ctx, -2, -2, WORLD.w + 4, WORLD.h + 4, PAL.w, 0.45)
|
||||
label(ctx, 'Pausiert', WORLD.w / 2, WORLD.h / 2 - 5, { size: 28, color: PAL.ink, weight: 700, align: 'center', bg: PAL.w })
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
// Räume des Hustler-Hochhauses: eine Zeichnung je Raumart (kind), Pokal-Seiten, graue Räume und die Anzeigewerte `look`.
|
||||
// Portiert aus entwuerfe/scene-turm.js (drawBridge ... drawArchive, Z. 182-314) auf die Raumtabelle des Layouts: alle Maße
|
||||
// relativ zu room.x und zum Boden der Etage, Schriften nur über label(). Rückwand und Boden zeichnet building.js davor.
|
||||
// Kein React, kein Appwrite, kein window/document.
|
||||
|
||||
import { px, tint, label, drawPaper, PAL, TEAM } from './sprites.js'
|
||||
import { drawDesk, drawMonitor, drawCabinet, drawPlant, drawTray, drawTrophy, drawStamp, drawRadar, drawMailbox, drawVault, drawScale, drawSign, drawIcon } from './props.js'
|
||||
|
||||
const TROPHIES_PER_PAGE = 8
|
||||
const TINT_ALPHA = 0.10 // Teamfarbton über jedem Raum
|
||||
const GREY_ALPHA = 0.45
|
||||
const GREY_TINT = '#9aa3b2'
|
||||
const DIVIDER = '#e1e5ec'
|
||||
const SIGN_TEXT = 'noch nicht angeschlossen'
|
||||
const SIGN_MAX_W = 60
|
||||
const STEP_COLORS = [TEAM.radar, TEAM.bewertung, TEAM.werkstatt, TEAM.pruefung, TEAM.freigabe] // Stationen der Pipeline-Tafel
|
||||
const FEED_ROWS = [8, 5, 9] // Breiten der durchlaufenden Zeilen im Feed-Schirm
|
||||
const MAX_PAGE_DOTS = 19
|
||||
|
||||
// Anzeigewerte der Räume. Die Regie (director.js) schreibt sie, die Zeichnung liest sie nur.
|
||||
// greyRooms: nicht angeschlossene Räume, busyRooms: Räume, deren Worker gerade arbeitet (dort laufen die Monitore).
|
||||
export function createLook() {
|
||||
return {
|
||||
greyRooms: new Set(),
|
||||
busyRooms: new Set(),
|
||||
pultOpen: 0,
|
||||
dealsMonth: 0,
|
||||
botLeads: 0,
|
||||
trophyPage: 0, // gezeigte Pokal-Seite
|
||||
pageT: 0, // Zeit seit der letzten Blätterung (Sekunden)
|
||||
trophyPop: 0, // Restzeit des Aufblinkens des neuesten Pokals
|
||||
vaultFlash: 0, // Restzeit des Tresor-Blitzes
|
||||
paused: false,
|
||||
}
|
||||
}
|
||||
|
||||
// Pokal-Seiten: perPage je Seite, die Seite wird auf 0..pages-1 geklemmt; ungültige Werte zählen als 0
|
||||
export function trophyPaging(total, page, perPage = TROPHIES_PER_PAGE) {
|
||||
const size = Number.isFinite(perPage) && perPage >= 1 ? Math.floor(perPage) : TROPHIES_PER_PAGE
|
||||
const n = whole(total)
|
||||
const pages = Math.max(1, Math.ceil(n / size))
|
||||
const p = Number.isFinite(page) ? Math.min(pages - 1, Math.max(0, Math.floor(page))) : 0
|
||||
const from = p * size
|
||||
return { shown: Math.min(size, n - from), page: p, pages, from }
|
||||
}
|
||||
|
||||
// Zähler als ganze Zahl >= 0
|
||||
function whole(value) {
|
||||
return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0
|
||||
}
|
||||
|
||||
// ---------- Hilfen für die Raumzeichnungen ----------
|
||||
|
||||
// r = { room, x, w, top, g, tp, busy, grey, color, look }: g = Boden der Etage, tp = Zeit mit Versatz je Raum (Monitore blinken nicht im Gleichschritt)
|
||||
const deskAt = (ctx, r, dx, w) => drawDesk(ctx, r.x + dx, r.g - 11, w, r.color)
|
||||
const monitorAt = (ctx, r, dx, color = r.color) => drawMonitor(ctx, r.x + dx, r.g - 21, r.tp, color, r.busy)
|
||||
const hop = (r) => (r.busy && Math.floor(r.tp * 2) % 2 === 0 ? 3 : 0) // Stempel springt im Takt, solange gearbeitet wird
|
||||
|
||||
// Monitor mit Schreib-Animation: erste Zeile wächst, dann die zweite, dazu eine blinkende Schreibmarke
|
||||
function drawTypingMonitor(ctx, r, dx) {
|
||||
const x = r.x + dx
|
||||
const y = r.g - 21
|
||||
drawMonitor(ctx, x, y, r.tp, r.color, false)
|
||||
if (!r.busy) return
|
||||
const n = Math.floor(r.tp * 4) % 9
|
||||
const first = Math.min(6, n + 1)
|
||||
const second = Math.max(0, n - 5)
|
||||
px(ctx, x + 2, y + 2, first, 1, r.color)
|
||||
if (second > 0) px(ctx, x + 2, y + 4, second, 1, r.color)
|
||||
if (n % 2 === 0) px(ctx, x + 2 + (second > 0 ? second : first), y + (second > 0 ? 4 : 2), 1, 1, PAL.w)
|
||||
}
|
||||
|
||||
// Pappkarton 15 × 8 mit Etikett
|
||||
function drawBox(ctx, x, y) {
|
||||
px(ctx, x, y, 15, 8, PAL.wood)
|
||||
px(ctx, x, y, 15, 1, PAL.wood2)
|
||||
px(ctx, x + 5, y + 3, 5, 2, '#efe3d2')
|
||||
}
|
||||
|
||||
// ---------- Raumarten ----------
|
||||
|
||||
export const ROOM_DRAWERS = Object.freeze({
|
||||
// Kommandobrücke: Konsole mit 2 Monitoren, Pipeline-Tafel, Fenster in die Nacht, Pflanze
|
||||
bruecke(ctx, r) {
|
||||
const { x, top, g, tp } = r
|
||||
px(ctx, x + 62, top + 3, 104, 22, PAL.metal2)
|
||||
px(ctx, x + 63, top + 4, 102, 20, '#e8ebf9')
|
||||
px(ctx, x + 63, top + 16, 102, 8, '#dfe3f5')
|
||||
for (const [dx, dy, w, h] of [[66, 18, 6, 6], [74, 14, 5, 10], [82, 17, 8, 7], [128, 15, 6, 9], [138, 18, 9, 6], [152, 13, 5, 11]]) px(ctx, x + dx, top + dy, w, h, '#cdd3ee')
|
||||
const stars = [[70, 6], [86, 9], [99, 5], [130, 7], [144, 5], [156, 10], [108, 8], [78, 16]]
|
||||
stars.forEach(([dx, dy], i) => {
|
||||
if ((Math.floor(tp * 1.3) + i) % 3 !== 0) px(ctx, x + dx, top + dy, 1, 1, '#b3bbec')
|
||||
})
|
||||
px(ctx, x + 150, top + 7, 5, 5, '#f6dc7a')
|
||||
px(ctx, x + 152, top + 6, 4, 4, '#e8ebf9')
|
||||
px(ctx, x + 113, top + 4, 2, 20, PAL.metal2)
|
||||
px(ctx, x + 60, top + 25, 108, 2, '#aab2c0')
|
||||
// Konsole
|
||||
drawDesk(ctx, x + 6, g - 11, 30, r.color)
|
||||
drawMonitor(ctx, x + 10, g - 21, tp, '#b7a4f0', r.busy)
|
||||
drawMonitor(ctx, x + 24, g - 21, tp + 1, '#7fb2ff', r.busy)
|
||||
// Pipeline-Tafel
|
||||
px(ctx, x + 42, top + 5, 18, 14, PAL.metal2)
|
||||
px(ctx, x + 43, top + 6, 16, 12, PAL.w)
|
||||
px(ctx, x + 45, top + 10, 12, 1, PAL.metal)
|
||||
STEP_COLORS.forEach((color, i) => px(ctx, x + 44 + 3 * i, top + 9, 2, 2, color))
|
||||
px(ctx, x + 45, top + 13, 3, 3, '#ffe28a')
|
||||
px(ctx, x + 50, top + 13, 3, 3, '#bde5c9')
|
||||
px(ctx, x + 55, top + 13, 3, 3, '#f6b9b9')
|
||||
drawPlant(ctx, x + 174, g - 9)
|
||||
},
|
||||
|
||||
// Netz-Radar: Radar auf dem Boden, Tisch daneben
|
||||
radar(ctx, r) {
|
||||
deskAt(ctx, r, 2, 14)
|
||||
drawRadar(ctx, r.x + 31, r.g - 15, r.busy ? r.tp : 0)
|
||||
},
|
||||
|
||||
// Kleinanzeigen: Tisch mit Monitor, Eingangskorb auf dem Wandbrett (voll, solange gearbeitet wird)
|
||||
inbox(ctx, r) {
|
||||
deskAt(ctx, r, 2, 14)
|
||||
monitorAt(ctx, r, 4)
|
||||
px(ctx, r.x + 31, r.g - 11, 12, 1, PAL.wood2)
|
||||
drawTray(ctx, r.x + 32, r.g - 15, r.busy)
|
||||
},
|
||||
|
||||
// Portale: Tisch mit Monitor, Wandschirm mit durchlaufenden Zeilen
|
||||
feed(ctx, r) {
|
||||
deskAt(ctx, r, 2, 14)
|
||||
monitorAt(ctx, r, 4)
|
||||
const sx = r.x + 31
|
||||
const sy = r.g - 18
|
||||
px(ctx, sx, sy, 14, 10, PAL.o)
|
||||
px(ctx, sx + 1, sy + 1, 12, 8, PAL.screen)
|
||||
if (!r.busy) return
|
||||
const shift = Math.floor(r.tp * 3) % FEED_ROWS.length
|
||||
for (let i = 0; i < FEED_ROWS.length; i++) px(ctx, sx + 2, sy + 2 + i * 2, FEED_ROWS[(i + shift) % FEED_ROWS.length], 1, r.color)
|
||||
},
|
||||
|
||||
// Foren: Tisch mit Monitor, Tafel mit zwei Sprechblasen
|
||||
board(ctx, r) {
|
||||
deskAt(ctx, r, 2, 14)
|
||||
monitorAt(ctx, r, 4)
|
||||
const bx = r.x + 31
|
||||
const by = r.g - 19
|
||||
px(ctx, bx, by, 14, 11, PAL.wood2)
|
||||
px(ctx, bx + 1, by + 1, 12, 9, '#eadfcf')
|
||||
px(ctx, bx + 2, by + 2, 6, 3, PAL.w)
|
||||
px(ctx, bx + 3, by + 5, 1, 1, PAL.w)
|
||||
px(ctx, bx + 6, by + 6, 6, 3, r.color)
|
||||
px(ctx, bx + 10, by + 9, 1, 1, r.color)
|
||||
},
|
||||
|
||||
// Branchen-Scout: Tisch in der Teamfarbe, Monitor, Branchen-Icon an der Wand (Icon = Raumkennung)
|
||||
scout(ctx, r) {
|
||||
deskAt(ctx, r, 2, 14)
|
||||
monitorAt(ctx, r, 4)
|
||||
drawIcon(ctx, r.room.id, r.x + r.w - 10, r.top + 8, r.color)
|
||||
},
|
||||
|
||||
// Waage: Waage links der Figur (schwankt beim Bewerten), Tisch mit Papieren rechts
|
||||
waage(ctx, r) {
|
||||
drawScale(ctx, r.x + 62, r.g - 16, r.busy ? Math.round(Math.sin(r.tp * 6) * 2.4) : 0)
|
||||
deskAt(ctx, r, 104, 22)
|
||||
drawPaper(ctx, r.x + 109, r.g - 18)
|
||||
drawPaper(ctx, r.x + 117, r.g - 18)
|
||||
},
|
||||
|
||||
// Mail-Stube: Tisch, Monitor, Briefstapel auf einem Beistelltisch
|
||||
mail(ctx, r) {
|
||||
deskAt(ctx, r, 2, 14)
|
||||
monitorAt(ctx, r, 4)
|
||||
px(ctx, r.x + 31, r.g - 7, 12, 1, PAL.wood2)
|
||||
px(ctx, r.x + 32, r.g - 6, 1, 6, PAL.wood2)
|
||||
px(ctx, r.x + 41, r.g - 6, 1, 6, PAL.wood2)
|
||||
for (let i = 0; i < 3; i++) {
|
||||
px(ctx, r.x + 32, r.g - 9 - i * 2, 10, 2, PAL.w)
|
||||
px(ctx, r.x + 32, r.g - 9 - i * 2, 10, 1, PAL.g)
|
||||
}
|
||||
},
|
||||
|
||||
// Forum-Stube: Tisch, Monitor mit Schreib-Animation
|
||||
schreiber(ctx, r) {
|
||||
deskAt(ctx, r, 2, 14)
|
||||
drawTypingMonitor(ctx, r, 4)
|
||||
},
|
||||
|
||||
// Posteingang: Tisch, Regal mit drei Ablagekörben (Eingang voll, Mitte beim Sortieren, Ausgang leer)
|
||||
sortier(ctx, r) {
|
||||
deskAt(ctx, r, 2, 14)
|
||||
const rx = r.x + 31
|
||||
px(ctx, rx, r.g - 20, 1, 18, PAL.wood2)
|
||||
px(ctx, rx + 11, r.g - 20, 1, 18, PAL.wood2)
|
||||
const filled = [true, r.busy, false]
|
||||
filled.forEach((full, i) => drawTray(ctx, rx + 1, r.g - 19 + i * 6, full))
|
||||
},
|
||||
|
||||
// Abschluss: Tisch, Vertrag, Stempel (springt beim Arbeiten)
|
||||
vertrag(ctx, r) {
|
||||
deskAt(ctx, r, 2, 14)
|
||||
drawPaper(ctx, r.x + 3, r.g - 18)
|
||||
drawStamp(ctx, r.x + 10, r.g - 16 - hop(r), true)
|
||||
},
|
||||
|
||||
// Werkbank: Tisch, Monitor
|
||||
tisch(ctx, r) {
|
||||
deskAt(ctx, r, 6, 18)
|
||||
monitorAt(ctx, r, 10)
|
||||
},
|
||||
|
||||
// Prüftisch: Tisch mit zwei Stempeln, Handy auf einem Sockel (zeigt beim Prüfen wechselnde Bilder)
|
||||
pruefung(ctx, r) {
|
||||
deskAt(ctx, r, 60, 22)
|
||||
drawStamp(ctx, r.x + 66, r.g - 16, false)
|
||||
drawStamp(ctx, r.x + 73, r.g - 16 - hop(r), true)
|
||||
const sx = r.x + 108
|
||||
px(ctx, sx, r.g - 5, 10, 5, PAL.wood)
|
||||
px(ctx, sx, r.g - 5, 10, 1, PAL.wood2)
|
||||
px(ctx, sx + 2, r.g - 15, 6, 10, PAL.o)
|
||||
const shot = Math.floor(r.tp * 2) % 2 === 0 ? '#cfe3ff' : '#bde5c9'
|
||||
px(ctx, sx + 3, r.g - 14, 4, 7, r.busy ? shot : PAL.screen)
|
||||
px(ctx, sx + 4, r.g - 7, 2, 1, PAL.mute)
|
||||
},
|
||||
|
||||
// Dein Pult: der Briefkasten in der Mitte; Zahl der offenen Einträge daneben (keine bei 0)
|
||||
pult(ctx, r) {
|
||||
const open = whole(r.look.pultOpen)
|
||||
const cx = r.x + r.w / 2
|
||||
drawMailbox(ctx, cx - 6, r.g - 15, open)
|
||||
if (open > 0) label(ctx, open > 99 ? '99+' : String(open), cx + 15, r.g - 19, { size: 11, color: PAL.w, weight: 700, align: 'center', bg: PAL.red })
|
||||
},
|
||||
|
||||
// Tresor: Pokalbrett (eine Seite zu 8), Tresortür, Zähler der Deals dieses Monats
|
||||
tresor(ctx, r) {
|
||||
const { look } = r
|
||||
const total = whole(look.dealsMonth)
|
||||
const pg = trophyPaging(total, look.trophyPage)
|
||||
const shelf = r.g - 9
|
||||
px(ctx, r.x + 24, shelf, 78, 2, PAL.wood2)
|
||||
px(ctx, r.x + 26, shelf + 2, 2, 3, PAL.wood2)
|
||||
px(ctx, r.x + 98, shelf + 2, 2, 3, PAL.wood2)
|
||||
for (let i = 0; i < pg.shown; i++) {
|
||||
const newest = pg.from + i === total - 1
|
||||
if (newest && look.trophyPop > 0 && Math.floor(look.trophyPop * 10) % 2) continue
|
||||
drawTrophy(ctx, r.x + 26 + 9 * i, shelf - 9)
|
||||
}
|
||||
// Seitenpunkte, wenn mehr als eine Seite da ist
|
||||
for (let p = 0; p < Math.min(pg.pages, MAX_PAGE_DOTS); p++) px(ctx, r.x + 24 + p * 4, shelf + 6, 2, 2, p === pg.page ? TEAM.tresor : PAL.metal)
|
||||
drawVault(ctx, r.x + 110, r.g - 21, r.tp)
|
||||
if (look.vaultFlash > 0) tint(ctx, r.x + 110, r.g - 21, 22, 20, PAL.gold, 0.3 * Math.min(1, look.vaultFlash * 2))
|
||||
label(ctx, `${total} Deals`, r.x + 138, r.g - 15, { size: 11, color: PAL.ink, weight: 600 })
|
||||
},
|
||||
|
||||
// Archiv & Register: Kartons links, vier Aktenschränke rechts der Figur (beim Arbeiten springt je eine Schublade auf), Zähler der Bot-Leads
|
||||
archiv(ctx, r) {
|
||||
drawBox(ctx, r.x + 14, r.g - 9)
|
||||
drawBox(ctx, r.x + 31, r.g - 9)
|
||||
drawBox(ctx, r.x + 22, r.g - 17)
|
||||
const open = Math.floor(r.tp * 1.5) % 4
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const x = r.x + 100 + 14 * i
|
||||
const y = r.g - 20
|
||||
drawCabinet(ctx, x, y, 3)
|
||||
if (r.busy && i === open) {
|
||||
px(ctx, x + 1, y + 7, 10, 5, '#fafbfd')
|
||||
px(ctx, x + 2, y + 9, 8, 2, PAL.p)
|
||||
px(ctx, x + 3, y + 6, 6, 1, PAL.w)
|
||||
}
|
||||
}
|
||||
label(ctx, `${whole(r.look.botLeads)} Bot-Leads`, r.x + r.w - 2, r.g - 15, { size: 11, color: PAL.ink, weight: 600, align: 'right' })
|
||||
},
|
||||
})
|
||||
|
||||
// ---------- Zeichnen ----------
|
||||
|
||||
function drawRoom(ctx, room, floor, index, t, look) {
|
||||
// Räume ohne Worker (pult, tresor) werden nie grau
|
||||
const grey = room.workerId != null && look.greyRooms.has(room.id)
|
||||
const r = {
|
||||
room,
|
||||
x: room.x,
|
||||
w: room.w,
|
||||
top: floor.top,
|
||||
g: floor.floorY,
|
||||
tp: t + room.x * 0.05,
|
||||
busy: !grey && look.busyRooms.has(room.id),
|
||||
grey,
|
||||
color: TEAM[room.team] ?? PAL.metal2,
|
||||
look,
|
||||
}
|
||||
if (!grey) tint(ctx, room.x, floor.top, room.w, floor.h, r.color, TINT_ALPHA)
|
||||
if (index > 0) px(ctx, room.x, floor.top, 1, floor.h, DIVIDER)
|
||||
// Das Schild steht oben mittig und verdrängt den Titel; Name und Branche erkennt man an Möbeln und Icon
|
||||
if (!grey) label(ctx, room.title, room.x + 2, floor.top + 1, { size: 10, color: PAL.mute, weight: 500 })
|
||||
if (Object.hasOwn(ROOM_DRAWERS, room.kind)) ROOM_DRAWERS[room.kind](ctx, r)
|
||||
if (grey) {
|
||||
tint(ctx, room.x, floor.top, room.w, floor.h, GREY_TINT, GREY_ALPHA)
|
||||
const w = Math.min(room.w - 2, SIGN_MAX_W)
|
||||
drawSign(ctx, room.x + (room.w - w) / 2, floor.top + 1, w, SIGN_TEXT)
|
||||
}
|
||||
}
|
||||
|
||||
// Alle Räume aller Etagen. Vorher: drawOutside, drawTower. Nachher: Aufzug hinten, Figuren, Aufzug vorn.
|
||||
export function drawRooms(ctx, layout, t, look) {
|
||||
for (const floor of layout.floors) floor.rooms.forEach((room, index) => drawRoom(ctx, room, floor, index, t, look))
|
||||
}
|
||||
Reference in new issue
Block a user