(bones: CompanionBones, frame = 0)
| 452 | } |
| 453 | |
| 454 | export function renderSprite(bones: CompanionBones, frame = 0): string[] { |
| 455 | const frames = BODIES[bones.species] |
| 456 | const body = frames[frame % frames.length]!.map(line => |
| 457 | line.replaceAll('{E}', bones.eye), |
| 458 | ) |
| 459 | const lines = [...body] |
| 460 | // Only replace with hat if line 0 is empty (some fidget frames use it for smoke etc) |
| 461 | if (bones.hat !== 'none' && !lines[0]!.trim()) { |
| 462 | lines[0] = HAT_LINES[bones.hat] |
| 463 | } |
| 464 | // Drop blank hat slot — wastes a row in the Card and ambient sprite when |
| 465 | // there's no hat and the frame isn't using it for smoke/antenna/etc. |
| 466 | // Only safe when ALL frames have blank line 0; otherwise heights oscillate. |
| 467 | if (!lines[0]!.trim() && frames.every(f => !f[0]!.trim())) lines.shift() |
| 468 | return lines |
| 469 | } |
| 470 | |
| 471 | export function spriteFrameCount(species: Species): number { |
| 472 | return BODIES[species].length |
no test coverage detected