diff --git a/assets/characters/ing-tozzi.json b/assets/characters/ing-tozzi.json new file mode 100644 index 0000000..d27868d --- /dev/null +++ b/assets/characters/ing-tozzi.json @@ -0,0 +1,70 @@ +{ + "image": "ing-tozzi.png", + "height": 120, + "frames": { + "stand": { + "x": 0, + "y": 0, + "w": 53, + "h": 120, + "ax": 27.9, + "ay": 120 + }, + "blink": { + "x": 55, + "y": 0, + "w": 54, + "h": 120, + "ax": 27.8, + "ay": 120 + }, + "talk": { + "x": 111, + "y": 0, + "w": 77, + "h": 119, + "ax": 29.9, + "ay": 119 + }, + "explain": { + "x": 190, + "y": 0, + "w": 58, + "h": 119, + "ax": 30.8, + "ay": 119 + }, + "laugh": { + "x": 250, + "y": 0, + "w": 53, + "h": 119, + "ax": 28.2, + "ay": 119 + }, + "chalk": { + "x": 305, + "y": 0, + "w": 52, + "h": 119, + "ax": 24.1, + "ay": 119 + }, + "shrug": { + "x": 359, + "y": 0, + "w": 87, + "h": 120, + "ax": 43.9, + "ay": 120 + }, + "cheer": { + "x": 448, + "y": 0, + "w": 56, + "h": 123, + "ax": 30.9, + "ay": 123 + } + } +} diff --git a/assets/characters/ing-tozzi.png b/assets/characters/ing-tozzi.png new file mode 100644 index 0000000..b9d29ca Binary files /dev/null and b/assets/characters/ing-tozzi.png differ diff --git a/assets/voices/andrea-127a90af53.mp3 b/assets/voices/andrea-127a90af53.mp3 new file mode 100644 index 0000000..76b8d03 Binary files /dev/null and b/assets/voices/andrea-127a90af53.mp3 differ diff --git a/assets/voices/andrea-8f63435d69.mp3 b/assets/voices/andrea-8f63435d69.mp3 new file mode 100644 index 0000000..95d2c87 Binary files /dev/null and b/assets/voices/andrea-8f63435d69.mp3 differ diff --git a/assets/voices/andrea-c43b158842.mp3 b/assets/voices/andrea-c43b158842.mp3 new file mode 100644 index 0000000..e4bc2c7 Binary files /dev/null and b/assets/voices/andrea-c43b158842.mp3 differ diff --git a/assets/voices/andrea-dbcf4d1083.mp3 b/assets/voices/andrea-dbcf4d1083.mp3 new file mode 100644 index 0000000..2eed30e Binary files /dev/null and b/assets/voices/andrea-dbcf4d1083.mp3 differ diff --git a/assets/voices/index.json b/assets/voices/index.json index 8d75b08..c14a982 100644 --- a/assets/voices/index.json +++ b/assets/voices/index.json @@ -655,13 +655,9 @@ "file": "andrea-2d04be65fb.mp3", "sec": 5.97 }, - "ing_tozzi|Una partita ai birilli? Si va a venti.": { - "file": "ing_tozzi-7aef4a5420.mp3", - "sec": 3.3 - }, - "andrea|Gnamo.": { - "file": "andrea-a496b0aca9.mp3", - "sec": 0.58 + "andrea|Il tavolo è dell'Ingegnere: prima gli chiedo una partita.": { + "file": "andrea-c43b158842.mp3", + "sec": 3.27 }, "ing_tozzi|Si parla col panno, qui. Prendi la stecca.": { "file": "ing_tozzi-4814e97759.mp3", @@ -671,6 +667,10 @@ "file": "andrea-98b3e4a969.mp3", "sec": 3.49 }, + "andrea|L'Ing. Tozzi, il campione del circolo. Occhiali scuri anche al chiuso: dice che così non vede le biglie degli altri.": { + "file": "andrea-127a90af53.mp3", + "sec": 9.37 + }, "andrea|Le stecche del circolo, in fila. Ognuna ha il suo proprietario, e guai a sbagliare.": { "file": "andrea-1eae1a8577.mp3", "sec": 6.1 @@ -1823,6 +1823,26 @@ "file": "mariano-1c9cd0c325.mp3", "sec": 5.96 }, + "andrea|Ingegnere, una partita ai birilli?": { + "file": "andrea-dbcf4d1083.mp3", + "sec": 2.49 + }, + "andrea|Arrivederci, Ingegnere.": { + "file": "andrea-8f63435d69.mp3", + "sec": 1.38 + }, + "ing_tozzi|Una partita ai birilli? Si va a venti.": { + "file": "ing_tozzi-7aef4a5420.mp3", + "sec": 3.3 + }, + "andrea|Gnamo.": { + "file": "andrea-a496b0aca9.mp3", + "sec": 0.58 + }, + "ing_tozzi|Ci mancherebbe. Stavolta guardo bene.": { + "file": "ing_tozzi-37404495f7.mp3", + "sec": 3.13 + }, "andrea|Sono bloccato. Mi dai un consiglio?": { "file": "andrea-42b02eb9ea.mp3", "sec": 3.9 diff --git a/assets/voices/ing_tozzi-37404495f7.mp3 b/assets/voices/ing_tozzi-37404495f7.mp3 new file mode 100644 index 0000000..8ef84c9 Binary files /dev/null and b/assets/voices/ing_tozzi-37404495f7.mp3 differ diff --git a/src/story/story.js b/src/story/story.js index 4afc3fe..fd8d4a9 100644 --- a/src/story/story.js +++ b/src/story/story.js @@ -186,7 +186,7 @@ export const story = { tosca: { name: 'La Tosca', color: '#ffb0d0' }, arcu: { name: 'L\'Arcu', color: '#7fb2ff', sprite: 'assets/characters/arcu.json' }, // L'Ing. Tozzi, il campione del biliardo al Circolo 4 Maggio (sprite da fare con Codex: prompts/personaggi/ing-tozzi-sheet.txt). - ing_tozzi: { name: 'L\'Ing. Tozzi', color: '#d9c48a' }, + ing_tozzi: { name: 'L\'Ing. Tozzi', color: '#d9c48a', sprite: 'assets/characters/ing-tozzi.json' }, tozzino: { name: 'Il Tozzino', color: '#c8f5b0', sprite: 'assets/characters/tozzino.json' }, barondeduke: { name: 'Il BaronDeDuke', color: '#e0c090', sprite: 'assets/characters/barondeduke.json' }, mariano: { name: 'Mariano', color: '#ffb0a3', sprite: 'assets/characters/mariano.json' }, @@ -1058,24 +1058,29 @@ export const story = { background: 'assets/scenes/circolo-4-maggio.png', indoor: true, walk: [[0, 360], [0, 356], [90, 350], [175, 330], [236, 316], [318, 300], [334, 240], [402, 236], [480, 232], [520, 214], [600, 190], [640, 190], [640, 360]], - depth: [[190, 0.95], [360, 1.95]], + depth: [[190, 1.2], [360, 2.5]], entry: [590, 202], - speakers: { ing_tozzi: [420, 150] }, + speakers: { ing_tozzi: [452, 150] }, + // L'Ing. Tozzi aspetta accanto al primo tavolo, con la stecca: si parla con lui per giocare, come con Mariano. + people: [{ who: 'ing_tozzi', at: [452, 296], facing: 1, idle: 'stand', talk: ['talk', 'explain'], blink: 'blink', every: 4.4 }], enter: [{ if: '!circolo_visto', then: [{ set: 'circolo_visto' }, { say: 'La sala dei biliardi. Qui dentro si parla piano, e si gioca forte.' }] }], hotspots: [ { id: 'biliardo', name: 'biliardo', box: [0, 120, 358, 230], at: [380, 300], face: 'left', default: 'use', actions: { look: [{ say: 'Il primo tavolo: il panno verde, il castello di birilli in mezzo, le biglie già pronte.' }, { say: 'L\'Ing. Tozzi gli gira intorno con la stecca in mano, come se aspettasse qualcuno.' }], - use: [ - { say: 'Una partita ai birilli? Si va a venti.', who: 'ing_tozzi' }, - { say: 'Gnamo.' }, - { closeup: 'biliardo' }, - ], + use: [{ say: 'Il tavolo è dell\'Ingegnere: prima gli chiedo una partita.' }], talk: [{ say: 'Si parla col panno, qui. Prendi la stecca.', who: 'ing_tozzi' }], take: [{ say: 'Una biglia in tasca? Mi sbattono fuori dal circolo.' }], }, }, + { + id: 'ing_tozzi', name: 'l\'Ing. Tozzi', box: [432, 196, 40, 100], at: [410, 304], face: 'right', default: 'talk', + actions: { + look: [{ say: 'L\'Ing. Tozzi, il campione del circolo. Occhiali scuri anche al chiuso: dice che così non vede le biglie degli altri.' }], + talk: [{ dialogue: 'ing_tozzi' }], + }, + }, { id: 'stecche', name: 'rastrelliera delle stecche', box: [140, 0, 60, 110], at: [150, 352], face: 'up', actions: { @@ -2263,6 +2268,24 @@ export const story = { }, }, }, + ing_tozzi: { + nodes: { + start: { + options: [ + { + text: 'Ingegnere, una partita ai birilli?', when: '!biliardo_vinto', next: 'end', + then: [ + { say: 'Una partita ai birilli? Si va a venti.', who: 'ing_tozzi', pose: 'chalk' }, + { say: 'Gnamo.' }, + { closeup: 'biliardo' }, + ], + }, + { text: 'La rivincita?', when: 'biliardo_vinto', next: 'end', then: [{ say: 'Ci mancherebbe. Stavolta guardo bene.', who: 'ing_tozzi', pose: 'explain' }, { closeup: 'biliardo' }] }, + { text: 'Arrivederci, Ingegnere.', next: 'end' }, + ], + }, + }, + }, // Lo "psicologo": il castello ascolta e risponde con un indizio su quello che manca. castello: { nodes: { diff --git a/tests/biliardo.test.mjs b/tests/biliardo.test.mjs index 593f486..c11061c 100644 --- a/tests/biliardo.test.mjs +++ b/tests/biliardo.test.mjs @@ -124,7 +124,9 @@ test('al Circolo 4 Maggio: dal portone in piazza si entra nella sala, e al tavol assert.ok(g.act('walk', 'circolo')); settle(g); assert.equal(g.state.scene, 'circolo_4_maggio'); - assert.ok(g.act('use', 'biliardo')); + assert.ok(g.act('talk', 'ing_tozzi')); + settle(g); + g.choose(g.options().findIndex(o => o.text === 'Ingegnere, una partita ai birilli?')); const before = settle(g).map(s => s.text); assert.ok(before.some(t => t.includes('Si va a venti'))); assert.equal(g.closeup?.id, 'biliardo'); @@ -143,7 +145,9 @@ test('al Circolo 4 Maggio: dal portone in piazza si entra nella sala, e al tavol assert.ok(after.some(t => t.startsWith('ing_tozzi: Venti. Hai vinto te'))); assert.ok(g.state.flags.biliardo_vinto); // Lasciare a metà non segna niente. - g.act('use', 'biliardo'); settle(g); + g.act('talk', 'ing_tozzi'); settle(g); + assert.ok(g.options().some(o => o.text === 'La rivincita?'), 'vinto, si chiede la rivincita'); + g.choose(g.options().findIndex(o => o.text === 'La rivincita?')); settle(g); assert.equal(g.closeup?.id, 'biliardo'); assert.ok(g.closeupClose()); assert.ok(settle(g).some(s => s.text.startsWith('Lasci a metà?'))); diff --git a/tests/browser.mjs b/tests/browser.mjs index 13b4455..07e2dc2 100644 --- a/tests/browser.mjs +++ b/tests/browser.mjs @@ -402,7 +402,9 @@ try { await settle(b); await b.waitForTimeout(1500); // la dissolvenza del cambio scena await b.screenshot({ path: `${OUT}/03d-circolo.png` }); - await clickScene(b, await hotspotCenter(b, 'biliardo')); + await clickScene(b, await hotspotCenter(b, 'ing_tozzi')); + await b.waitForFunction(() => game.dialogue && !game.busy, null, { timeout: 20000 }); + await b.locator('#choices li', { hasText: 'una partita ai birilli' }).click(); await b.waitForFunction(() => game.closeup?.id === 'biliardo' && game.closeup.step === 'aim' && !game.speech, null, { timeout: 30000 }); const r = await b.locator('#scene').boundingBox(); const [tx, ty] = await b.evaluate(() => { const c = game.closeup, V = c.balls.cpu; return [57 + V.x * 1.85, 78 + V.y * 1.85]; });