| |
| const HAIR = { |
| player: "#5d5b86", brad: "#7a4626", stacey: "#9a5a32", |
| kevin: "#33324a", janet: "#241a30", derek: "#6f6a52", |
| }; |
| const COLOR = { |
| player: "var(--bds-white)", brad: "var(--bds-brad)", |
| stacey: "var(--bds-stacey)", kevin: "var(--bds-kevin)", |
| janet: "var(--bds-janet)", derek: "var(--bds-derek)", |
| }; |
|
|
| export function charColor(id) { return COLOR[id] || "var(--bds-grey)"; } |
|
|
| |
| export function makeChar(parent, id, x, y, opts = {}) { |
| const root = document.createElement("div"); |
| root.style.cssText = |
| `position:absolute;left:${x}px;top:${y}px;width:0;height:0;z-index:5;`; |
| parent.appendChild(root); |
|
|
| |
| const feet = document.createElement("div"); |
| feet.style.cssText = `position:absolute;left:-9px;top:0px;width:18px; |
| height:5px;background:rgba(58,61,73,.30);border-radius:50%;z-index:1;`; |
| root.appendChild(feet); |
|
|
| const obj = { |
| id, x, y, root, sprite: null, pose: null, facing: "down", dim: false, |
| setPose(pose, facing = this.facing) { |
| if (pose === this.pose && facing === this.facing && this.sprite) return; |
| this.pose = pose; this.facing = facing; |
| if (this.sprite) this.sprite.remove(); |
| this.sprite = window.BDSChibi.topSprite({ |
| who: id, pose, still: pose === "still", facing, dim: this.dim, |
| }); |
| this.sprite.style.left = "-14px"; |
| this.sprite.style.top = "-30px"; |
| root.insertBefore(this.sprite, root.firstChild); |
| }, |
| setPos(nx, ny) { |
| this.x = nx; this.y = ny; |
| root.style.left = `${nx}px`; root.style.top = `${ny}px`; |
| }, |
| setDim(v) { if (v !== this.dim) { this.dim = v; const p = this.pose; |
| this.pose = null; this.setPose(p); } }, |
| remove() { root.remove(); }, |
| }; |
|
|
| if (opts.desk) root.appendChild(window.BDSChibi.desk({ dark: opts.darkDesk })); |
| if (opts.tag !== false) |
| root.appendChild(window.BDSChibi.tag(id.toUpperCase(), COLOR[id], { top: 6 })); |
| obj.setPose(opts.pose || "idle", opts.facing || "down"); |
| return obj; |
| } |
|
|
| |
|
|
| |
| const CRISIS_EXPRESSION = { |
| brad: { armPose: "out", mouth: "worried", sweat: true }, |
| stacey: { armPose: "wring", mouth: "worried" }, |
| kevin: { armPose: "point", mouth: "smirk" }, |
| janet: { armPose: "open", mouth: "open" }, |
| derek: { mouth: "flat" }, |
| player: { mouth: "neutral" }, |
| }; |
|
|
| |
| const OUTCOME_EXPRESSION = { |
| npc_happy: { eyes: "happy", mouth: "smile", armPose: "open" }, |
| npc_celebrating: { eyes: "happy", mouth: "open", armPose: "open", anim: "a-bounce" }, |
| npc_angry: { mouth: "frown", armPose: "hips", anim: "a-shiver" }, |
| npc_confused: { mouth: "wavy", tilt: 8 }, |
| npc_devastated: { eyes: "closed", mouth: "frown", tilt: 5 }, |
| npc_crying: { tears: true, mouth: "frown" }, |
| npc_smug: { mouth: "smirk", armPose: "behindhead" }, |
| npc_suspicious: { mouth: "flat", armPose: "crossed", tilt: -5 }, |
| npc_hiding: { mouth: "worried", sweat: true }, |
| npc_grateful: { eyes: "happy", mouth: "smile", blush: true }, |
| heart_float: { eyes: "heart", mouth: "smile", blush: true }, |
| disaster_flash: { eyes: "wide", mouth: "wavy", sweat: true }, |
| revenue_rain: { eyes: "happy", mouth: "open", armPose: "open" }, |
| }; |
|
|
| |
| |
| export function chibiInBox(id, opts = {}, boxW = 72, boxH = 66) { |
| const box = document.createElement("div"); |
| box.style.cssText = `position:relative;width:${boxW}px;height:${boxH}px; |
| flex:none;overflow:visible;`; |
| const el = window.BDSChibi.chibi(id, opts.state || "idle", opts); |
| |
| |
| const realH = parseInt(el.style.height, 10) || 150; |
| const scale = opts.fit || boxH / realH; |
| const wrap = document.createElement("div"); |
| wrap.style.cssText = `position:absolute;left:50%;bottom:0; |
| transform-origin:bottom center; |
| transform:translateX(-50%) scale(${scale})` + |
| (opts.tilt ? ` rotate(${opts.tilt}deg)` : "") + ";"; |
| wrap.appendChild(el); |
| box.appendChild(wrap); |
| return box; |
| } |
|
|
| export function crisisPortrait(id) { |
| return chibiInBox(id, { ...CRISIS_EXPRESSION[id] }); |
| } |
|
|
| export function outcomePortrait(id, animation) { |
| const expr = OUTCOME_EXPRESSION[animation] || CRISIS_EXPRESSION[id] || {}; |
| return chibiInBox(id, { ...expr }); |
| } |
|
|