Releases: yhdgms1/novely
v0.47.2
Core
Function templateReplace
is now passed into custom actions.
Click to expand
const handler: CustomHandler = ({ state, templateReplace }) => {
const object = {
ru: 'Текст по-русски',
en: 'Text in English'
}
console.log(templateReplace(object, state()); // By default global data will be used instead of state, could be any object anyway
}
handler.id = 'my-custom-action';
handler.key = 'my-custom-action--1';
Each NovelyAsset
get's id
property. It's randomly generated at asset creation.
Click to expand
When NovelyAsset['source']
is accessed that asset will always use that value. NovelyAsset
is typically used to get best supported image/audio format that will weight less. For the simplicity the new id
property will help with asset determination.
const showSomething = (asset: NovelyAsset) => {
const handler: CustomHandler = () => {
// it's safe to access `source` now
asset.source;
}
handler.id = 'show-something';
handler.key = `show-something--${asset.id}`; //
return handler;
}
Added asset.image
and asset.audio
methods. Both accept always one argument, does not check for asset to be of certain type.
Click to expand
Sometimes we do not need to pick the best asset or get the resource type automatically. It just makes an asset with certain type.
import background_avif from './background.png?format=avif';
import background_webp from './background.png?format=webp';
import background_jpeg from './background.png?format=jpeg';
const background = import.meta.env.DEV ? asset.image(background_jpeg) : asset(background_avif, background_webp, background_jpeg);
Fixes playSound
. Now when restoring a save, sound only be played if there are no blocking actions ahead of it.
@novely/[email protected]
Characters and background now uses div
with background-image
property instead of canvas.
Custom showImage
and hideImage
actions were rewritten with some bugs fixed.
v0.46.0
- Dialog Overview implementation (disabled at current stage)
- Icons in
@novely/solid-renderer
are moved into HTML template.
How to migrate
Only thing that should be migrated is @novely/solid-renderer
's icons.
- Locate
index.html
- Add inside the
body
tag the following:
Click to expand
<!-- Icons are taken from https://phosphoricons.com/ -->
<svg style="display: none;" width="24" height="24" viewBox="0 0 256 256">
<path id="novely-save-icon" d="M219.31,72,184,36.69A15.86,15.86,0,0,0,172.69,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V83.31A15.86,15.86,0,0,0,219.31,72ZM168,208H88V152h80Zm40,0H184V152a16,16,0,0,0-16-16H88a16,16,0,0,0-16,16v56H48V48H172.69L208,83.31ZM160,72a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h56A8,8,0,0,1,160,72Z"></path>
<path id="novely-settings-icon" d="M128,80a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160Zm109.94-52.79a8,8,0,0,0-3.89-5.4l-29.83-17-.12-33.62a8,8,0,0,0-2.83-6.08,111.91,111.91,0,0,0-36.72-20.67,8,8,0,0,0-6.46.59L128,41.85,97.88,25a8,8,0,0,0-6.47-.6A112.1,112.1,0,0,0,54.73,45.15a8,8,0,0,0-2.83,6.07l-.15,33.65-29.83,17a8,8,0,0,0-3.89,5.4,106.47,106.47,0,0,0,0,41.56,8,8,0,0,0,3.89,5.4l29.83,17,.12,33.62a8,8,0,0,0,2.83,6.08,111.91,111.91,0,0,0,36.72,20.67,8,8,0,0,0,6.46-.59L128,214.15,158.12,231a7.91,7.91,0,0,0,3.9,1,8.09,8.09,0,0,0,2.57-.42,112.1,112.1,0,0,0,36.68-20.73,8,8,0,0,0,2.83-6.07l.15-33.65,29.83-17a8,8,0,0,0,3.89-5.4A106.47,106.47,0,0,0,237.94,107.21Zm-15,34.91-28.57,16.25a8,8,0,0,0-3,3c-.58,1-1.19,2.06-1.81,3.06a7.94,7.94,0,0,0-1.22,4.21l-.15,32.25a95.89,95.89,0,0,1-25.37,14.3L134,199.13a8,8,0,0,0-3.91-1h-.19c-1.21,0-2.43,0-3.64,0a8.08,8.08,0,0,0-4.1,1l-28.84,16.1A96,96,0,0,1,67.88,201l-.11-32.2a8,8,0,0,0-1.22-4.22c-.62-1-1.23-2-1.8-3.06a8.09,8.09,0,0,0-3-3.06l-28.6-16.29a90.49,90.49,0,0,1,0-28.26L61.67,97.63a8,8,0,0,0,3-3c.58-1,1.19-2.06,1.81-3.06a7.94,7.94,0,0,0,1.22-4.21l.15-32.25a95.89,95.89,0,0,1,25.37-14.3L122,56.87a8,8,0,0,0,4.1,1c1.21,0,2.43,0,3.64,0a8.08,8.08,0,0,0,4.1-1l28.84-16.1A96,96,0,0,1,188.12,55l.11,32.2a8,8,0,0,0,1.22,4.22c.62,1,1.23,2,1.8,3.06a8.09,8.09,0,0,0,3,3.06l28.6,16.29A90.49,90.49,0,0,1,222.9,142.12Z"></path>
<path id="novely-back-icon" d="M199.81,34a16,16,0,0,0-16.24.43L64,109.23V40a8,8,0,0,0-16,0V216a8,8,0,0,0,16,0V146.77l119.57,74.78A15.95,15.95,0,0,0,208,208.12V47.88A15.86,15.86,0,0,0,199.81,34ZM192,208,64.16,128,192,48.07Z"></path>
<path id="novely-book-open-icon" d="M232,48H160a40,40,0,0,0-32,16A40,40,0,0,0,96,48H24a8,8,0,0,0-8,8V200a8,8,0,0,0,8,8H96a24,24,0,0,1,24,24,8,8,0,0,0,16,0,24,24,0,0,1,24-24h72a8,8,0,0,0,8-8V56A8,8,0,0,0,232,48ZM96,192H32V64H96a24,24,0,0,1,24,24V200A39.81,39.81,0,0,0,96,192Zm128,0H160a39.81,39.81,0,0,0-24,8V88a24,24,0,0,1,24-24h64Z"></path>
<path id="novely-list-icon" d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128ZM40,72H216a8,8,0,0,0,0-16H40a8,8,0,0,0,0,16ZM216,184H40a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16Z"></path>
<path id="novely-x-icon" d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
<path id="novely-play-icon" d="M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z"></path>
<path id="novely-stop-icon" d="M200,40H56A16,16,0,0,0,40,56V200a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm0,160H56V56H200V200Z"></path>
<path id="novely-play-game-icon" d="M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm0,176H48V48H208ZM80,128a8,8,0,0,1,8-8h60.69l-18.35-18.34a8,8,0,0,1,11.32-11.32l32,32a8,8,0,0,1,0,11.32l-32,32a8,8,0,0,1-11.32-11.32L148.69,136H88A8,8,0,0,1,80,128Z"></path>
<path id="novely-file-plus-icon" d="M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Zm-40-64a8,8,0,0,1-8,8H136v16a8,8,0,0,1-16,0V160H104a8,8,0,0,1,0-16h16V128a8,8,0,0,1,16,0v16h16A8,8,0,0,1,160,152Z"></path>
<path id="novely-files-icon" d="M213.66,66.34l-40-40A8,8,0,0,0,168,24H88A16,16,0,0,0,72,40V56H56A16,16,0,0,0,40,72V216a16,16,0,0,0,16,16H168a16,16,0,0,0,16-16V200h16a16,16,0,0,0,16-16V72A8,8,0,0,0,213.66,66.34ZM168,216H56V72h76.69L168,107.31v84.53c0,.06,0,.11,0,.16s0,.1,0,.16V216Zm32-32H184V104a8,8,0,0,0-2.34-5.66l-40-40A8,8,0,0,0,136,56H88V40h76.69L200,75.31Zm-56-32a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h48A8,8,0,0,1,144,152Zm0,32a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h48A8,8,0,0,1,144,184Z"></path>
<path id="novely-caret-down-icon" d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"></path>
<path id="novely-globe-icon" d="M128 24a104 104 0 1 0 104 104A104.12 104.12 0 0 0 128 24Zm87.62 96h-39.83c-1.79-36.51-15.85-62.33-27.38-77.6a88.19 88.19 0 0 1 67.22 77.6ZM96.23 136h63.54c-2.31 41.61-22.23 67.11-31.77 77-9.55-9.9-29.46-35.4-31.77-77Zm0-16c2.31-41.61 22.23-67.11 31.77-77 9.55 9.93 29.46 35.43 31.77 77Zm11.36-77.6C96.06 57.67 82 83.49 80.21 120H40.37a88.19 88.19 0 0 1 67.22-77.6ZM40.37 136h39.84c1.82 36.51 15.85 62.33 27.38 77.6A88.19 88.19 0 0 1 40.37 136Zm108 77.6c11.53-15.27 25.56-41.09 27.38-77.6h39.84a88.19 88.19 0 0 1-67.18 77.6Z"/>
<path id="novely-typewriter-speed-icon" d="M87.24 52.59a8 8 0 0 0-14.48 0l-64 136a8 8 0 1 0 14.48 6.81L39.9 160h80.2l16.66 35.4a8 8 0 1 0 14.48-6.81ZM47.43 144 80 74.79 112.57 144ZM200 96c-12.76 0-22.73 3.47-29.63 10.32a8 8 0 0 0 11.26 11.36c3.8-3.77 10-5.68 18.37-5.68 13.23 0 24 9 24 20v3.22a42.76 42.76 0 0 0-24-7.22c-22.06 0-40 16.15-40 36s17.94 36 40 36a42.73 42.73 0 0 0 24-7.25 8 8 0 0 0 16-.75v-60c0-19.85-17.94-36-40-36Zm0 88c-13.23 0-24-9-24-20s10.77-20 24-20 24 9 24 20-10.77 20-24 20Z"/>
<path id="novely-music-volume-icon" d="M212.92 17.69a8 8 0 0 0-6.86-1.45l-128 32A8 8 0 0 0 72 56v110.08A36 36 0 1 0 88 196V62.25l112-28v99.83A36 36 0 1 0 216 164V24a8 8 0 0 0-3.08-6.31ZM52 216a20 20 0 1 1 20-20 20 20 0 0 1-20 20Zm128-32a20 20 0 1 1 20-20 20 20 0 0 1-20 20Z"/>
<path id="novely-sound-volume-icon" d="M163.51 24.81a8 8 0 0 0-8.42.88L85.25 80H40a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h45.25l69.84 54.31A8 8 0 0 0 168 224V32a8 8 0 0 0-4.49-7.19ZM152 207.64l-59.09-45.95A7.94 7.94 0 0 0 88 160H40V96h48a7.94 7.94 0 0 0 4.91-1.69L152 48.36ZM208 104v48a8 8 0 0 1-16 0v-48a8 8 0 0 1 16 0Zm32-16v80a8 8 0 0 1-16 0V88a8 8 0 0 1 16 0Z"/>
<path id="novely-voice-volume-icon" d="M144 165.68a68 68 0 1 0-71.9 0c-20.65 6.76-39.23 19.39-54.17 37.17a8 8 0 0 0 12.25 10.3C50.25 189.19 77.91 176 108 176s57.75 13.19 77.88 37.15a8 8 0 1 0 12.25-10.3c-14.95-17.78-33.53-30.41-54.13-37.17ZM56 108a52 52 0 1 1 52 52 52.06 52.06 0 0 1-52-52Zm151.36-42.4a108.36 108.36 0 0 1 0 84.8 8 8 0 0 1-7.36 4.86 8 8 0 0 1-7.36-11.15 92.26 92.26 0 0 0 0-72.22 8 8 0 0 1 14.72-6.29ZM248 108a139 139 0 0 1-11.29 55.15 8 8 0 0 1-14.7-6.3 124.43 124.43 0 0 0 0-97.7 8 8 0 1 1 14.7-6.3A139 139 0 0 1 248 108Z"/>
</svg>
How the final HTML template should look like: click
v0.38.0
v0.37.0 — Untitled
Core
getResourseType
function uses cache. Useful when http requests are made. By default file extension is used.preview
function that is passed to renderer now resolves object withassets
array — array of resources that was used in that preview.characterAssetSizes
setting is added. It is used to gave canvas size before image are loaded
const engine = novely({
characters: {
Peter: {
name: 'Peter',
color: '#c04931',
emotions: {
normal: peter_the_great
}
}
},
characterAssetSizes: {
Peter: {
width: 800,
height: 1200
}
}
})
v0.35.0
Custom Actions Update
Some arguments were renamed and regroupped.
// previously
const custom: CustomHandler = ({ preview, get }) => {
const { data, element } = get(true)
}
// now
const custom: CustomHandler = ({ data, flags: { preview }, getDomNodes }) => {
const { element } = getDomNodes(true)
}
Custom Actions to Core!
Some internal code was moved into @novely/core package instead of being necessary to write in renderers.
0.33.0
Extend Action
Extend action is a new functionality. Extending 0.31.0 version's engine actions functionality, now you can declare you'r own actions.
import { novely, extendAction, EN } from '@novely/core'
import { particles, hide as hideParticles } from '@novely/particles'
const engine = novely({ ... });
const action = extendAction(engine.action, {
particles: (options: Parameters<typeof particles>[0]) => {
return ['custom', particles(options)]
},
hideParticles: () => {
return ['custom', hideParticles()]
}
})
engine.script({
start: [
// using action object !
action.particles(config)
]
})
Extend Action creates a wrapper Proxy around original engine.action.
Fix GoingBack
Sometimes goingBack
flag was not set properly leading to unexpected behavior.
Optimized clearing of some actions
Before renderer should have been clear dialog or some other things by itself. This was made just before calling resolve
function which will make next actions execute. And this means, when two dialogs were going one after another, after first dialog is closed, it would be cleared, and then drawn again. Right now when action that requires user action is ran, other actions will be cleared.
v0.32.0
Multilingual Voices
engine.script({
start: [
engine.action.voice('./hello-en.mp3'),
// New !!
engine.action.voice({
en: './hello-en.mp3',
ko: undefined // may be undefined
})
]
})
You can pass empty object — then sound will not play. You can ignore audio for some languages.
v0.31.0
v0.30.0
Default emotions for characters
const engine = novely({
characters: {
Yuki: {
name: 'Yuki',
color: '#f595f6',
emotions: {
normal: './normal.png'
}
}
},
defaultEmotions: {
Yuki: 'normal'
}
})
engine.script({
start: [
// Without emotion!
engine.action.showCharacter('Yuki')
]
})
v0.28.0
Fix Saves
Before if the story was set to the following
script({
start: [
a.say('Character', 'Lyric One'),
a.say('Character', 'Lyric Two'),
]
})
When, however being on lyric two, player exit the game using exit button, game will be saved at lyric one.
Now game will be saved on lyric two. There were also some minor changes to the saves logic. Now Novely itself decides should save been overwritten or not.
Fix Action Double Call
Same story is used in this example.
script({
start: [
a.say('Character', 'Lyric One'),
a.say('Character', 'Lyric Two'),
]
})
Player save on lyric two. Basically you should expect, when restoring, first lyric one to run, and then lyric two to run.
But things was working differently. Firstly, lyric one was called, then lyric two, and then lyric two was called again, this time variables goingBack
and restoring
was false.
Now restoring working in expected way