Skip to content

Commit cc4ab2c

Browse files
Merge pull request #535 from OpenWebGAL/dev
4.5.5
2 parents 4811d32 + 959185e commit cc4ab2c

File tree

19 files changed

+186
-98
lines changed

19 files changed

+186
-98
lines changed

packages/webgal/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "webgal",
33
"private": true,
4-
"version": "4.5.4",
4+
"version": "4.5.5",
55
"scripts": {
66
"dev": "vite --host --port 3000",
77
"build": "cross-env NODE_ENV=production tsc && vite build --base=./",

packages/webgal/public/game/scene/demo_zh_cn.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ miniAvatar:miniavatar.png;
1313
changeFigure:stand2.png -right -next;
1414
{egine} 是使用 Web 技术开发的引擎,因此在网页端有良好的表现。 -v2.wav;
1515
由于这个特性,如果你将 {egine} 部署到服务器或网页托管平台上,玩家只需要一串链接就可以开始游玩! -v3.wav;
16-
setAnimation:move-front-and-back -target=fig-left -next;
16+
setAnimation:move-front-and-back -target=fig-left -continue;
1717
听起来是不是非常吸引人? -v4.wav;
1818
changeFigure:none -right -next;
1919
setTransform:{"position": {"x": 500,"y": 0}} -target=fig-left -next;
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"name":"Default Template",
3-
"webgal-version":"4.5.4"
3+
"webgal-version":"4.5.5"
44
}

packages/webgal/src/Core/Modules/perform/performController.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,11 @@ export class PerformController {
3535
if (!perform.isHoldOn) {
3636
// 如果不是保持演出,清除
3737
this.unmountPerform(perform.performName);
38-
if (perform.goNextWhenOver) {
39-
// nextSentence();
40-
this.goNextWhenOver();
41-
}
4238
}
4339
}, perform.duration);
4440

41+
if (script.args.find((e) => e.key === 'continue' && e.value === true)) perform.goNextWhenOver = true;
42+
4543
this.performList.push(perform);
4644
}
4745

@@ -52,6 +50,10 @@ export class PerformController {
5250
if (!e.isHoldOn && e.performName === name) {
5351
e.stopFunction();
5452
clearTimeout(e.stopTimeout as unknown as number);
53+
if (e.goNextWhenOver) {
54+
// nextSentence();
55+
this.goNextWhenOver();
56+
}
5557
this.performList.splice(i, 1);
5658
i--;
5759
}
@@ -62,6 +64,10 @@ export class PerformController {
6264
if (e.performName === name) {
6365
e.stopFunction();
6466
clearTimeout(e.stopTimeout as unknown as number);
67+
if (e.goNextWhenOver) {
68+
// nextSentence();
69+
this.goNextWhenOver();
70+
}
6571
this.performList.splice(i, 1);
6672
i--;
6773
/**
@@ -89,7 +95,7 @@ export class PerformController {
8995

9096
private goNextWhenOver() {
9197
let isBlockingAuto = false;
92-
this.performList.forEach((e) => {
98+
this.performList?.forEach((e) => {
9399
if (e.blockingAuto())
94100
// 阻塞且没有结束的演出
95101
isBlockingAuto = true;

packages/webgal/src/Core/controller/gamePlay/nextSentence.ts

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export const nextSentence = () => {
7272
isGoNext = true;
7373
}
7474
if (!e.skipNextCollect) {
75+
// 由于提前结束使用的不是 unmountPerform 标准 API,所以不会触发两次 nextSentence
7576
e.stopFunction();
7677
clearTimeout(e.stopTimeout as unknown as number);
7778
WebGAL.gameplay.performController.performList.splice(i, 1);
@@ -80,6 +81,7 @@ export const nextSentence = () => {
8081
}
8182
}
8283
if (isGoNext) {
84+
// 由于不使用 unmountPerform 标准 API,这里需要手动收集一下 isGoNext
8385
nextSentence();
8486
}
8587
};

packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { logger } from '../../util/logger';
44
import { IStageState } from '@/store/stageInterface';
55
import { restoreScene } from '../scene/restoreScene';
66
import { webgalStore } from '@/store/store';
7-
import { getValueFromState } from '@/Core/gameScripts/setVar';
7+
import { getValueFromStateElseKey } from '@/Core/gameScripts/setVar';
88
import { strIf } from '@/Core/controller/gamePlay/strIf';
99
import { nextSentence } from '@/Core/controller/gamePlay/nextSentence';
1010
import cloneDeep from 'lodash/cloneDeep';
@@ -25,7 +25,7 @@ export const whenChecker = (whenValue: string | undefined): boolean => {
2525
if (e.match(/true/) || e.match(/false/)) {
2626
return e;
2727
}
28-
return getValueFromState(e).toString();
28+
return getValueFromStateElseKey(e);
2929
} else return e;
3030
})
3131
.reduce((pre, curr) => pre + curr, '');
@@ -59,8 +59,8 @@ export const scriptExecutor = () => {
5959

6060
if (contentExp !== null) {
6161
contentExp.forEach((e) => {
62-
const contentVarValue = getValueFromState(e.replace(/(?<!\\)\{(.*)\}/, '$1'));
63-
retContent = retContent.replace(e, contentVarValue ? contentVarValue.toString() : e);
62+
const contentVarValue = getValueFromStateElseKey(e.replace(/(?<!\\)\{(.*)\}/, '$1'));
63+
retContent = retContent.replace(e, contentVarValue);
6464
});
6565
}
6666
retContent = retContent.replace(/\\{/g, '{').replace(/\\}/g, '}');

packages/webgal/src/Core/controller/scene/restoreScene.ts

+16-6
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,21 @@ import { WebGAL } from '@/Core/WebGAL';
1111
* @param entry 场景入口
1212
*/
1313
export const restoreScene = (entry: ISceneEntry) => {
14+
if (WebGAL.sceneManager.lockSceneWrite) {
15+
return;
16+
}
17+
WebGAL.sceneManager.lockSceneWrite = true;
1418
// 场景写入到运行时
15-
sceneFetcher(entry.sceneUrl).then((rawScene) => {
16-
WebGAL.sceneManager.sceneData.currentScene = sceneParser(rawScene, entry.sceneName, entry.sceneUrl);
17-
WebGAL.sceneManager.sceneData.currentSentenceId = entry.continueLine + 1; // 重设场景
18-
logger.debug('现在恢复场景,恢复后场景:', WebGAL.sceneManager.sceneData.currentScene);
19-
nextSentence();
20-
});
19+
sceneFetcher(entry.sceneUrl)
20+
.then((rawScene) => {
21+
WebGAL.sceneManager.sceneData.currentScene = sceneParser(rawScene, entry.sceneName, entry.sceneUrl);
22+
WebGAL.sceneManager.sceneData.currentSentenceId = entry.continueLine + 1; // 重设场景
23+
logger.debug('现在恢复场景,恢复后场景:', WebGAL.sceneManager.sceneData.currentScene);
24+
WebGAL.sceneManager.lockSceneWrite = false;
25+
nextSentence();
26+
})
27+
.catch((e) => {
28+
logger.error('场景调用错误', e);
29+
WebGAL.sceneManager.lockSceneWrite = false;
30+
});
2131
};

packages/webgal/src/Core/gameScripts/intro.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ export const intro = (sentence: ISentence): IPerform => {
127127
if (!isHold) {
128128
timeout = setTimeout(() => {
129129
WebGAL.gameplay.performController.unmountPerform(performName);
130-
setTimeout(nextSentence, 0);
131130
}, baseDuration);
132131
}
133132
}

packages/webgal/src/Core/gameScripts/playVideo.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import React from 'react';
44
import ReactDOM from 'react-dom';
55
import styles from '@/Stage/FullScreenPerform/fullScreenPerform.module.scss';
66
import { webgalStore } from '@/store/store';
7-
import { nextSentence } from '@/Core/controller/gamePlay/nextSentence';
87
import { getRandomPerformName, PerformController } from '@/Core/Modules/perform/performController';
98
import { getSentenceArgByKey } from '@/Core/util/getSentenceArg';
109
import { WebGAL } from '@/Core/WebGAL';
@@ -55,7 +54,6 @@ export const playVideo = (sentence: ISentence): IPerform => {
5554
isOver = true;
5655
e.stopFunction();
5756
WebGAL.gameplay.performController.unmountPerform(e.performName);
58-
nextSentence();
5957
}
6058
}
6159
};

packages/webgal/src/Core/gameScripts/say.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { getRandomPerformName, PerformController } from '@/Core/Modules/perform/
88
import { getSentenceArgByKey } from '@/Core/util/getSentenceArg';
99
import { textSize, voiceOption } from '@/store/userDataInterface';
1010
import { WebGAL } from '@/Core/WebGAL';
11+
import { compileSentence } from '@/Stage/TextBox/TextBox';
1112

1213
/**
1314
* 进行普通对话的显示
@@ -50,7 +51,9 @@ export const say = (sentence: ISentence): IPerform => {
5051
// 计算延迟
5152
const textDelay = useTextDelay(userDataState.optionData.textSpeed);
5253
// 本句延迟
53-
const sentenceDelay = textDelay * sentence.content.length;
54+
const textNodes = compileSentence(sentence.content, 3);
55+
const len = textNodes.reduce((prev, curr) => prev + curr.length, 0);
56+
const sentenceDelay = textDelay * len;
5457

5558
for (const e of sentence.args) {
5659
if (e.key === 'fontSize') {

packages/webgal/src/Core/gameScripts/setVar.ts

+34-9
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,21 @@ export const setVar = (sentence: ISentence): IPerform => {
3939
// 将变量替换为变量的值,然后合成表达式字符串
4040
const valExp2 = valExpArr
4141
.map((e) => {
42-
if (e.match(/\$?[.a-zA-Z]/)) {
43-
return String(getValueFromState(e.trim()));
44-
} else return e;
42+
if (!e.trim().match(/^[a-zA-Z_$][a-zA-Z0-9_.]*$/)) {
43+
// 检查是否是变量名,不是就返回本身
44+
return e;
45+
}
46+
const _r = getValueFromStateElseKey(e.trim());
47+
return typeof _r === 'string' ? `'${_r}'` : _r;
4548
})
4649
.reduce((pre, curr) => pre + curr, '');
47-
const exp = compile(valExp2);
48-
const result = exp();
50+
let result = '';
51+
try {
52+
const exp = compile(valExp2);
53+
result = exp();
54+
} catch (e) {
55+
logger.error('expression compile error', e);
56+
}
4957
webgalStore.dispatch(targetReducerFunction({ key, value: result }));
5058
} else if (valExp.match(/true|false/)) {
5159
if (valExp.match(/true/)) {
@@ -54,11 +62,13 @@ export const setVar = (sentence: ISentence): IPerform => {
5462
if (valExp.match(/false/)) {
5563
webgalStore.dispatch(targetReducerFunction({ key, value: false }));
5664
}
65+
} else if (valExp.length === 0) {
66+
webgalStore.dispatch(targetReducerFunction({ key, value: '' }));
5767
} else {
5868
if (!isNaN(Number(valExp))) {
5969
webgalStore.dispatch(targetReducerFunction({ key, value: Number(valExp) }));
6070
} else {
61-
webgalStore.dispatch(targetReducerFunction({ key, value: valExp }));
71+
webgalStore.dispatch(targetReducerFunction({ key, value: getValueFromStateElseKey(valExp) }));
6272
}
6373
}
6474
if (setGlobal) {
@@ -79,10 +89,13 @@ export const setVar = (sentence: ISentence): IPerform => {
7989
};
8090
};
8191

82-
type BaseVal = string | number | boolean;
92+
type BaseVal = string | number | boolean | undefined;
8393

94+
/**
95+
* 取不到时返回 undefined
96+
*/
8497
export function getValueFromState(key: string) {
85-
let ret: any = 0;
98+
let ret: any;
8699
const stage = webgalStore.getState().stage;
87100
const userData = webgalStore.getState().userData;
88101
const _Merge = { stage, userData }; // 不要直接合并到一起,防止可能的键冲突
@@ -92,7 +105,19 @@ export function getValueFromState(key: string) {
92105
ret = userData.globalGameVar[key];
93106
} else if (key.startsWith('$')) {
94107
const propertyKey = key.replace('$', '');
95-
ret = get(_Merge, propertyKey, 0) as BaseVal;
108+
ret = get(_Merge, propertyKey, undefined) as BaseVal;
96109
}
97110
return ret;
98111
}
112+
113+
/**
114+
* 取不到时返回 key
115+
*/
116+
export function getValueFromStateElseKey(key: string) {
117+
const valueFromState = getValueFromState(key);
118+
if (valueFromState === null || valueFromState === undefined) {
119+
logger.warn('valueFromState result null, key = ' + key);
120+
return key;
121+
}
122+
return valueFromState;
123+
}

packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts

+21-12
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,28 @@ export const infoFetcher = (url: string) => {
3434
gameConfig.forEach((e) => {
3535
const { command, args } = e;
3636
if (args.length > 0) {
37-
let res: any = args[0].trim();
38-
if (/^(true|false)$/g.test(args[0])) {
39-
res = !!res;
40-
} else if (/^[0-9]+\.?[0-9]+$/g.test(args[0])) {
41-
res = Number(res);
42-
}
37+
if (args.length > 1) {
38+
dispatch(
39+
setGlobalVar({
40+
key: command,
41+
value: args.join('|'),
42+
}),
43+
);
44+
} else {
45+
let res: any = args[0].trim();
46+
if (/^(true|false)$/g.test(args[0])) {
47+
res = !!res;
48+
} else if (/^[0-9]+\.?[0-9]+$/g.test(args[0])) {
49+
res = Number(res);
50+
}
4351

44-
dispatch(
45-
setGlobalVar({
46-
key: command,
47-
value: res,
48-
}),
49-
);
52+
dispatch(
53+
setGlobalVar({
54+
key: command,
55+
value: res,
56+
}),
57+
);
58+
}
5059
}
5160
});
5261

packages/webgal/src/Stage/TextBox/IMSSTextbox.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ export default function IMSSTextbox(props: ITextboxProps) {
7171
let delay = allTextIndex * textDelay;
7272
allTextIndex++;
7373
let prevLength = currentConcatDialogPrev.length;
74-
if (currentConcatDialogPrev !== '' && index >= prevLength) {
74+
if (currentConcatDialogPrev !== '' && allTextIndex >= prevLength) {
7575
delay = delay - prevLength * textDelay;
7676
}
7777
const styleClassName = ' ' + css(style);
7878
const styleAllText = ' ' + css(style_alltext);
79-
if (index < prevLength) {
79+
if (allTextIndex < prevLength) {
8080
return (
8181
<span
8282
// data-text={e}

packages/webgal/src/Stage/TextBox/TextBox.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,12 @@ function parseString(input: string): Segment[] {
231231
const enhance = match[3];
232232
let parsedEnhanced: KeyValuePair[] = [];
233233
let ruby = '';
234-
if (enhance.match(/style=|tips=|ruby=/)) {
234+
if (enhance.match(/style=|tips=|ruby=|style-alltext=/)) {
235235
parsedEnhanced = parseEnhancedString(enhance);
236+
const rubyKvPair = parsedEnhanced.find((e) => e.key === 'ruby');
237+
if (rubyKvPair) {
238+
ruby = rubyKvPair.value;
239+
}
236240
} else {
237241
ruby = enhance;
238242
}

packages/webgal/src/UI/Logo/Logo.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const Logo: FC = () => {
3434
currentLogoIndex.set(0);
3535
currentTimeOutId.set(setTimeout(nextImg, animationDuration));
3636
}
37-
}, [isEnterGame, logoImage]);
37+
}, [isEnterGame]);
3838

3939
const currentLogoUrl = currentLogoIndex.value === -1 ? '' : logoImage[currentLogoIndex.value];
4040
return (

packages/webgal/src/config/info.ts

+2-17
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,6 @@
11
export const __INFO = {
2-
version: 'WebGAL 4.5.4',
2+
version: 'WebGAL 4.5.5',
33
contributors: [
4-
{ username: 'Mahiru', link: 'https://github.com/MakinoharaShoko' },
5-
{ username: 'Hoshinokinya', link: 'https://github.com/hshqwq' },
6-
{ username: 'Junbo Xiong', link: 'https://github.com/C6H5-NO2' },
7-
{ username: 'lykl', link: 'https://github.com/lykl' },
8-
{ username: 'SakuraSnow', link: 'https://github.com/sliyoxn' },
9-
{ username: 'bcqsd', link: 'https://github.com/bcqsd' },
10-
{ username: 'Yuji Sakai', link: 'https://github.com/generalfreed' },
11-
{ username: 'Iara', link: 'https://github.com/labiker' },
12-
{ username: '22', link: 'https://github.com/nini22P' },
13-
{ username: '德布罗煜', link: 'https://github.com/ch1ny' },
14-
{ username: 'Mike Zhou', link: 'https://github.com/mikezzb' },
15-
{ username: 'Murasame0721', link: 'https://github.com/Murasame0721' },
16-
{ username: 'loliko', link: 'https://github.com/loliko114514' },
17-
{ username: 'IdrilK', link: 'https://github.com/IdrilK' },
18-
{ username: 'callofblood', link: 'https://github.com/callofblood' },
19-
{ username: 'lyle', link: 'https://github.com/lylelove' },
4+
// 现在改为跳转到 GitHub 了
205
],
216
};

packages/webgal/src/hooks/useConfigData.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,13 @@ const useConfigData = () => {
2525
setEbg(titleUrl);
2626
break;
2727
}
28-
/**
29-
* TODO:Game_Logo 是个数组,并且改变后会造成进入游戏界面重新渲染,以后再考虑如何处理
30-
*/
31-
// case 'Game_Logo': {
32-
// const logoUrlList = [assetSetter(val, fileType.background)];
33-
// webgalStore.dispatch(setLogoImage(logoUrlList));
34-
// break;
35-
// }
28+
29+
case 'Game_Logo': {
30+
const logos = val.split('|');
31+
const logoUrlList = logos.map((val) => assetSetter(val, fileType.background));
32+
webgalStore.dispatch(setLogoImage(logoUrlList));
33+
break;
34+
}
3635

3736
case 'Title_bgm': {
3837
const bgmUrl = assetSetter(val, fileType.bgm);

0 commit comments

Comments
 (0)