update: toolchan

This commit is contained in:
Vick Scarlet
2025-04-05 17:27:00 +08:00
parent 6b58fa99cf
commit 2eaf7a1ba2
65 changed files with 2119 additions and 189372 deletions

29
.github/workflows/deploy.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: Build and Deploy
on:
push:
branches: [main]
permissions:
contents: write
jobs:
build-and-deploy:
concurrency: ci-${{ github.ref }} # Recommended if you intend to make multiple deployments in quick succession.
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built.
run: |
pnpm install
pnpm xlsx2json
pnpm build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: template # The folder the action should deploy.

View File

@@ -1,31 +0,0 @@
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Node.js CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 16.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm install
- run: npm run build --if-present
- run: npm test

3
.gitignore vendored
View File

@@ -108,3 +108,6 @@ utils/xlsxTransform-*
/.idea /.idea
__localStorage.json __localStorage.json
template/public
public/data

29
.vscode/launch.json vendored
View File

@@ -4,40 +4,15 @@
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{
"name": "Launch Chrome",
"request": "launch",
"type": "pwa-chrome",
"url": "http://127.0.0.1:8000/public/index.html",
"webRoot": "${workspaceFolder}"
},
{ {
"type": "node", "type": "node",
"request": "launch", "request": "launch",
"name": "test", "name": "test",
"program": "${workspaceFolder}/test", "program": "${workspaceFolder}/test",
"skipFiles": [ "skipFiles": [
"<node_internals>/**" "<node_internals>/**",
"**/node_modumes/**"
] ]
}, },
{
"type": "node",
"request": "launch",
"name": "xlsx2json",
"program": "${workspaceFolder}/node_modules/v-transform/src/index.js",
"args": ["transform", "-s", "4", "-d", "public", "data/**/*.xlsx"],
"skipFiles": [
"<node_internals>/**"
]
},
{
"name": "Attach by Process ID",
"processId": "${command:PickProcess}",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node"
},
] ]
} }

View File

@@ -1,5 +0,0 @@
{
"cSpell.words": [
"Laya"
]
}

View File

@@ -17,8 +17,6 @@
<meta http-equiv="Cache-Control" content="no-siteapp"/> <meta http-equiv="Cache-Control" content="no-siteapp"/>
<font-face font-family="方正像素12" src="fonts/方正像素12.ttf"/> <font-face font-family="方正像素12" src="fonts/方正像素12.ttf"/>
<title>Life Restart</title> <title>Life Restart</title>
</head>
<body style="background:black">
<!--以下引用了常用类库,如果不使用,可以删除--> <!--以下引用了常用类库,如果不使用,可以删除-->
<!--核心包,封装了显示对象渲染,事件,时间管理,时间轴动画,缓动,消息交互,socket本地存储鼠标触摸声音加载颜色滤镜位图字体等--> <!--核心包,封装了显示对象渲染,事件,时间管理,时间轴动画,缓动,消息交互,socket本地存储鼠标触摸声音加载颜色滤镜位图字体等-->
@@ -67,8 +65,8 @@
<!-- 物理引擎matter.js --> <!-- 物理引擎matter.js -->
<!--自定义的js(src文件夹下)文件自动添加到下面jsfile模块标签里面里js的顺序可以手动修改修改后保留修改的顺序新增加的js会默认依次追加到标签里--> <!--自定义的js(src文件夹下)文件自动添加到下面jsfile模块标签里面里js的顺序可以手动修改修改后保留修改的顺序新增加的js会默认依次追加到标签里-->
<!--删除标签ide不会自动添加js文件请谨慎操作--> <!--删除标签ide不会自动添加js文件请谨慎操作-->
<!--jsfile--startTag-->
<script type="module" src="../src/index.js"></script> <script type="module" src="src/index.js"></script>
<!--jsfile--endTag--> </head>
</body> <body style="background:black"></body>
</html> </html>

View File

@@ -1,24 +1,19 @@
{ {
"name": "life_restart", "name": "life_restart",
"type": "module", "type": "module",
"bin": "repl/index.js", "main": "repl/index.js",
"version": "2.0.0", "version": "2.1.0",
"author": "Vick Scarlet <vick@syaro.io>",
"scripts": { "scripts": {
"test": "node test", "xlsx2json": "vt transform -d public data/**/*.xlsx",
"xlsxTransform": "vt transform data", "dev": "vite",
"xlsx2json": "vt transform -s 4 -d public data/**/*.xlsx", "build": "vite build",
"dev": "webpack serve --open /public/dev.html", "start": "vite preview",
"build": "webpack --mode production" "test": "vitest"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.15.4",
"@babel/preset-env": "^7.15.4",
"babel-loader": "^8.2.2",
"core-js": "^3.17.2",
"html-webpack-plugin": "^5.5.0",
"v-transform": "^2.0.1", "v-transform": "^2.0.1",
"webpack": "^5.64.4", "vite": "^6.2.5",
"webpack-cli": "^4.8.0", "vitest": "^3.1.1"
"webpack-dev-server": "^4.1.0"
} }
} }

1059
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><meta name="description" content="やり直すんだ。そして、次はうまくやる。"/><meta name="keywords" content="人生重开模拟器 liferestart life restart remake 人生重来"/><meta name="renderer" content="webkit"/><meta name="apple-mobile-web-app-capable" content="yes"/><meta name="full-screen" content="true"/><meta name="x5-fullscreen" content="true"/><meta name="360-fullscreen" content="true"/><meta name="theme-color" content="#157878"/><meta name="laya" screenorientation="landscape"/><meta http-equiv="expires" content="0"/><meta http-equiv="Cache-Control" content="no-siteapp"/><title>Life Restart</title><script src="libs/laya/min/laya.core.min.js"></script><script src="libs/laya/min/laya.webgl.min.js"></script><script src="libs/laya/min/laya.filter.min.js"></script><script src="libs/laya/min/laya.particle.min.js"></script><script src="libs/laya/min/laya.ui.min.js"></script><script defer="defer" src="chunk/main.32999.js"></script></head><body style="background:black"></body></html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,40 @@
import App from './app.js'; import { fileURLToPath } from 'url'
import { readFile, writeFile } from 'fs/promises'; import { dirname } from 'path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
import App from './app.js'
import { readFile, writeFile } from 'fs/promises'
async function main() { async function main() {
try { try {
globalThis.localStorage = JSON.parse(await readFile('__localStorage.json')); globalThis.localStorage = JSON.parse(
} catch (e) { await readFile(__dirname + '/__localStorage.json')
globalThis.localStorage = {};
}
localStorage.getItem = key => localStorage[key]===void 0? null: localStorage[key];
localStorage.setItem = (key, value) => (localStorage[key] = value);
globalThis.dumpLocalStorage = async ()=>await writeFile('__localStorage.json', JSON.stringify( global.localStorage))
const app = new App();
app.io(
repl => process.stdin.on('data', data=>repl(data.toString().trim())),
(data, isRepl) => process.stdout.write(`${data}${isRepl?'\n>':''}`),
code=>process.exit(code)
) )
await app.initial(); } catch (e) {
globalThis.localStorage = {}
}
localStorage.getItem = key =>
localStorage[key] === void 0 ? null : localStorage[key]
localStorage.setItem = (key, value) => (localStorage[key] = value)
globalThis.dumpLocalStorage = async () =>
await writeFile(
__dirname + '/__localStorage.json',
JSON.stringify(global.localStorage)
)
const app = new App()
app.io(
repl => process.stdin.on('data', data => repl(data.toString().trim())),
(data, isRepl) => process.stdout.write(`${data}${isRepl ? '\n>' : ''}`),
code => process.exit(code)
)
await app.initial()
} }
main(); main()
// process.stdin.setRawMode(true); // process.stdin.setRawMode(true);

View File

@@ -43,7 +43,7 @@ function parseCondition(condition) {
return conditions; return conditions;
} }
function checkCondition(property, condition) { export function checkCondition(property, condition) {
const conditions = parseCondition(condition); const conditions = parseCondition(condition);
return checkParsedConditions(property, conditions); return checkParsedConditions(property, conditions);
} }
@@ -113,7 +113,7 @@ function checkProp(property, condition) {
} }
} }
function extractMaxTriggers(condition) { export function extractMaxTriggers(condition) {
// Assuming only age related talents can be triggered multiple times. // Assuming only age related talents can be triggered multiple times.
const RE_AGE_CONDITION = /AGE\?\[([0-9\,]+)\]/; const RE_AGE_CONDITION = /AGE\?\[([0-9\,]+)\]/;
const match_object = RE_AGE_CONDITION.exec(condition); const match_object = RE_AGE_CONDITION.exec(condition);
@@ -125,5 +125,3 @@ function extractMaxTriggers(condition) {
const age_list = match_object[1].split(","); const age_list = match_object[1].split(",");
return age_list.length; return age_list.length;
} }
export { checkCondition, extractMaxTriggers };

View File

@@ -0,0 +1,103 @@
import { expect, test, describe } from 'vitest'
import { checkCondition } from './condition'
function withProp(prop) {
const p = {
get(key) {
return prop[key]
},
}
return condition => checkCondition(p, condition)
}
describe('condition', () => {
const check = withProp({
n1: 0,
n2: -10,
n3: 10,
nl1: [1, 2, 3],
nl2: [0],
nl3: [],
})
test('gt(>)', () => {
expect(check('n3>11')).toBe(false)
expect(check('n3>10')).toBe(false)
expect(check('n3>9')).toBe(true)
})
test('gte(>=)', () => {
expect(check('n3>=11')).toBe(false)
expect(check('n3>=10')).toBe(true)
expect(check('n3>=9')).toBe(true)
})
test('lt(<)', () => {
expect(check('n3<9')).toBe(false)
expect(check('n3<10')).toBe(false)
expect(check('n3<11')).toBe(true)
})
test('lte(<=)', () => {
expect(check('n3<=9')).toBe(false)
expect(check('n3<=10')).toBe(true)
expect(check('n3<=11')).toBe(true)
})
test('eq(=)', () => {
expect(check('n3=9')).toBe(false)
expect(check('n3=10')).toBe(true)
expect(check('n3=11')).toBe(false)
expect(check('nl1=0')).toBe(false)
expect(check('nl1=1')).toBe(true)
expect(check('nl1=2')).toBe(true)
expect(check('nl1=3')).toBe(true)
})
test('ne(!=)', () => {
expect(check('n3!=9')).toBe(true)
expect(check('n3!=10')).toBe(false)
expect(check('n3!=11')).toBe(true)
expect(check('nl1!=0')).toBe(true)
expect(check('nl1!=1')).toBe(false)
expect(check('nl1!=2')).toBe(false)
expect(check('nl1!=3')).toBe(false)
})
test('in(?)', () => {
expect(check('n3?[1,2,3]')).toBe(false)
expect(check('n3?[10,11,12]')).toBe(true)
expect(check('nl1?[0,1]')).toBe(true)
expect(check('nl2?[1,2,3]')).toBe(false)
expect(check('nl3?[1,2,3]')).toBe(false)
expect(check('nl2?[]')).toBe(false)
expect(check('nl3?[]')).toBe(false)
})
test('notin(!)', () => {
expect(check('n3![1,2,3]')).toBe(true)
expect(check('n3![10,11,12]')).toBe(false)
expect(check('nl1![0,1]')).toBe(false)
expect(check('nl2![1,2,3]')).toBe(true)
expect(check('nl3![1,2,3]')).toBe(true)
expect(check('nl2![]')).toBe(true)
expect(check('nl3![]')).toBe(true)
})
test('and(&)', () => {
expect(check('n1>=0&n2<0')).toBe(true)
expect(check('n2>0&n3>0')).toBe(false)
expect(check('n2<0&n3<0')).toBe(false)
expect(check('n2<0&n3>0')).toBe(true)
expect(check('n1=0&n2<0&n3>0')).toBe(true)
expect(check('n1=0&n2>0&n3>0')).toBe(false)
})
test('or(|)', () => {
expect(check('n1>=0|n2<0')).toBe(true)
expect(check('n2>0|n3>0')).toBe(true)
expect(check('n2<0|n3<0')).toBe(true)
expect(check('n2<0|n3>0')).toBe(true)
expect(check('n2>0|n3<0')).toBe(false)
expect(check('n1=0|n2<0|n3>0')).toBe(true)
expect(check('n1=0|n2>0|n3>0')).toBe(true)
expect(check('n1!=0|n2>0|n3<0')).toBe(false)
})
test('mix', () => {
expect(check('(n1=0|n2<0|n3>0)&(n1=0|n2>0|n3>0)')).toBe(true)
expect(check('(n1=0|n2<0|n3>0)&(n1!=0|n2>0|n3<0)')).toBe(false)
expect(check('n1=0|n2<0|n3>0&n1!=0|n2>0|n3<0')).toBe(true)
expect(check('(n1>0|n1?[-10,0])&(n2>0|n3![0,1])')).toBe(true)
expect(check('(n1>0&n1?[-10,0])|(n2<0&n3![0,1])')).toBe(true)
})
})

View File

@@ -54,7 +54,7 @@ class Life {
this.#specialThanks = specialThanks; this.#specialThanks = specialThanks;
const total = { const total = {
[this.PropertyTypes.TACEV]: this.#achievement.initial({achievements}), [this.PropertyTypes.TACHV]: this.#achievement.initial({achievements}),
[this.PropertyTypes.TEVT]: this.#event.initial({events}), [this.PropertyTypes.TEVT]: this.#event.initial({events}),
[this.PropertyTypes.TTLT]: this.#talent.initial({talents}), [this.PropertyTypes.TTLT]: this.#talent.initial({talents}),
}; };

View File

@@ -1,19 +1,19 @@
import Views from './themes/views.js'; import Views from './views.js'
export default class UIManager { export default class UIManager {
constructor(stage) { constructor(stage) {
UIManager.#views = Views; UIManager.#views = Views
if(!stage) { if (!stage) {
stage = Laya.stage; stage = Laya.stage
} }
this.#stage = stage; this.#stage = stage
stage.addChild(this.#viewLayer); stage.addChild(this.#viewLayer)
this.#viewLayer.zOrder = 1; this.#viewLayer.zOrder = 1
stage.addChild(this.#dialogLayer); stage.addChild(this.#dialogLayer)
this.#dialogLayer.zOrder = 2; this.#dialogLayer.zOrder = 2
stage.addChild(this.#popupLayer); stage.addChild(this.#popupLayer)
this.#popupLayer.zOrder = 3; this.#popupLayer.zOrder = 3
this.#viewLayer.top = this.#viewLayer.top =
this.#viewLayer.bottom = this.#viewLayer.bottom =
this.#viewLayer.left = this.#viewLayer.left =
@@ -29,332 +29,369 @@ export default class UIManager {
this.#dialogMask.top = this.#dialogMask.top =
this.#dialogMask.bottom = this.#dialogMask.bottom =
this.#dialogMask.left = this.#dialogMask.left =
this.#dialogMask.right = 0; this.#dialogMask.right =
this.#dialogMask.graphics.drawRect(0, 0, 5000, 5000, '#000000'); 0
this.#dialogMask.alpha = 0.4; this.#dialogMask.graphics.drawRect(0, 0, 5000, 5000, '#000000')
this.#dialogMask.on(Laya.Event.CLICK, this, ()=>{ this.#dialogMask.alpha = 0.4
this.#dialogStack[this.#dialogStack.length - 1]?.close?.(); this.#dialogMask.on(Laya.Event.CLICK, this, () => {
this.#dialogStack[this.#dialogStack.length - 1]?.close?.()
}) })
} }
static #instance = {}; static #instance = {}
static #views; static #views
#stage; #stage
#loading; #loading
#currentView; #currentView
#viewLayer = new Laya.Panel(); #viewLayer = new Laya.Panel()
#dialogLayer = new Laya.Panel(); #dialogLayer = new Laya.Panel()
#popupLayer = new Laya.Panel(); #popupLayer = new Laya.Panel()
#dialogMask = new Laya.Sprite(); #dialogMask = new Laya.Sprite()
#viewMap = new Map(); #viewMap = new Map()
#class = new Map(); #class = new Map()
#dialogStack = []; #dialogStack = []
static get inst() { static get inst() {
return this.getInstance(); return this.getInstance()
} }
static getInstance(name="default") { static getInstance(name = 'default') {
return this.#instance[name] || (this.#instance[name] = new UIManager()); return this.#instance[name] || (this.#instance[name] = new UIManager())
} }
static get pages() { static get pages() {
return this.#views.pages; return this.#views.pages
} }
static get popups() { static get popups() {
return this.#views.popups; return this.#views.popups
} }
static theme(theme, prop) { static theme(theme, prop) {
return this.#views.themes[theme][prop]; return this.#views.themes[theme][prop]
} }
async setLoading(loading) { async setLoading(loading) {
const className = this.#pages[loading]; const className = this.#pages[loading]
const view = await this.getView(className, null, null, loading); const view = await this.getView(className, null, null, loading)
view.top = view.bottom = view.left = view.right = 0; view.top = view.bottom = view.left = view.right = 0
view.zOrder = 4; view.zOrder = 4
this.#loading = view; this.#loading = view
} }
async switchView(viewName, args, actions) { async switchView(viewName, args, actions) {
const className = this.#pages[viewName]; const className = this.#pages[viewName]
// get view instance // get view instance
const view = await this.getView(className, args, actions?.load, viewName, 'pages'); const view = await this.getView(
className,
args,
actions?.load,
viewName,
'pages'
)
view.top = view.bottom = view.left = view.right = 0; view.top = view.bottom = view.left = view.right = 0
// close current view // close current view
this.clearAllDialog(); this.clearAllDialog()
await this.#currentView?.__close?.(view); await this.#currentView?.__close?.(view)
await this.#currentView?.close?.(view); await this.#currentView?.close?.(view)
this.#viewLayer.removeChildren(); this.#viewLayer.removeChildren()
// open new view // open new view
await view.init?.(args); await view.init?.(args)
this.#currentView = view; this.#currentView = view
this.#viewLayer.addChild(view); this.#viewLayer.addChild(view)
view.__close = actions?.close; view.__close = actions?.close
await actions?.open?.(view); await actions?.open?.(view)
await view.show?.(); await view.show?.()
} }
async getView(className, args, preload, viewName, type) { async getView(className, args, preload, viewName, type) {
// check if view is already loaded // check if view is already loaded
let view = await this.#viewMap.get(className); let view = await this.#viewMap.get(className)
let timeout; let timeout
if(this.#loading) { if (this.#loading) {
timeout = setTimeout( timeout = setTimeout(
()=>this.#stage.addChild(this.#loading), () => this.#stage.addChild(this.#loading),
3000 3000
); )
} }
const onProgress = this.#loading?.onProgress; const onProgress = this.#loading?.onProgress
if(!view) { if (!view) {
// load view // load view
const ViewClass = await this.loadView(className); const ViewClass = await this.loadView(className)
const resourceList = await ViewClass.load?.(args); const resourceList = await ViewClass.load?.(args)
const scanedResourceList = this.#loading? this.scanResource(ViewClass.uiView): []; const scanedResourceList = this.#loading
if(preload) { ? this.scanResource(ViewClass.uiView)
preload = [].concat(preload).concat(scanedResourceList); : []
if (preload) {
preload = [].concat(preload).concat(scanedResourceList)
} else { } else {
preload = scanedResourceList; preload = scanedResourceList
} }
await this.loadRes(resourceList, preload, onProgress); await this.loadRes(resourceList, preload, onProgress)
// create view // create view
view = new ViewClass(); view = new ViewClass()
// add view to map // add view to map
this.#viewMap.set(className, view); this.#viewMap.set(className, view)
} else { } else {
// load resource // load resource
const resourceList = await view.constructor.load?.(args); const resourceList = await view.constructor.load?.(args)
await this.loadRes(resourceList, preload, onProgress); await this.loadRes(resourceList, preload, onProgress)
} }
if(timeout) clearTimeout(timeout); if (timeout) clearTimeout(timeout)
this.#loading?.removeSelf(); this.#loading?.removeSelf()
this.#config(view, viewName, type); this.#config(view, viewName, type)
// return view // return view
return view; return view
} }
async loadView(className) { async loadView(className) {
// load view // load view
if(this.#class.has(className)) return this.#class.get(className); if (this.#class.has(className)) return this.#class.get(className)
const c = (await import(`./themes/${className}.js`)).default; const views = import.meta.glob('./themes/**/*.js')
this.#class.set(className, c); const view = (await views[`./themes/${className}.js`]()).default
return c; this.#class.set(className, view)
return view
} }
async loadRes(resourceList, preload, onProgress) { async loadRes(resourceList, preload, onProgress) {
const cnt = (resourceList?.length || 0) const cnt = (resourceList?.length || 0) + (preload?.length || 0)
+(preload?.length || 0); if (resourceList && resourceList.length) {
if(resourceList && resourceList.length) { const s = resourceList.length / cnt
const s = resourceList.length / cnt; await Laya.promises.loader.load(
await Laya.promises.loader.load(resourceList, Laya.Handler.create(null, prg=>onProgress?.(prg*s))); resourceList,
Laya.Handler.create(null, prg => onProgress?.(prg * s))
)
} }
if(preload && preload.length) { if (preload && preload.length) {
const s = 1 - preload.length / cnt; const s = 1 - preload.length / cnt
const l = preload.length / cnt; const l = preload.length / cnt
await Laya.promises.loader.load(preload, Laya.Handler.create(null, prg=>onProgress?.(prg*l+s))); await Laya.promises.loader.load(
preload,
Laya.Handler.create(null, prg => onProgress?.(prg * l + s))
)
} }
} }
#showDialogStack() { #showDialogStack() {
if(this.#dialogStack.length == 0) { if (this.#dialogStack.length == 0) {
this.#dialogLayer.visible = false; this.#dialogLayer.visible = false
return; return
} }
this.#dialogLayer.visible = true; this.#dialogLayer.visible = true
this.#dialogStack.forEach((dialog, i)=>{ this.#dialogStack.forEach((dialog, i) => {
this.#dialogLayer.addChild(dialog); this.#dialogLayer.addChild(dialog)
dialog.zOrder = i; dialog.zOrder = i
}) })
this.#dialogLayer.addChild(this.#dialogMask); this.#dialogLayer.addChild(this.#dialogMask)
const l = this.#dialogStack.length; const l = this.#dialogStack.length
this.#dialogMask.zOrder = l -1; this.#dialogMask.zOrder = l - 1
this.#dialogStack[l -1].zOrder = l; this.#dialogStack[l - 1].zOrder = l
} }
async showDialog(dialogName, args, actions) { async showDialog(dialogName, args, actions) {
const className = this.#pages[dialogName]; const className = this.#pages[dialogName]
const dialog = await this.getView(className, args, actions?.load, dialogName, 'pages'); const dialog = await this.getView(
className,
args,
actions?.load,
dialogName,
'pages'
)
const index = this.#dialogStack.indexOf(dialog); const index = this.#dialogStack.indexOf(dialog)
if(index != -1) { if (index != -1) {
this.#dialogStack.splice(index, 1); this.#dialogStack.splice(index, 1)
} }
this.#dialogStack.push(dialog); this.#dialogStack.push(dialog)
dialog.init?.(args); dialog.init?.(args)
dialog.centerX = dialog.centerY = 0; dialog.centerX = dialog.centerY = 0
this.#showDialogStack(); this.#showDialogStack()
const open = actions?.open || (async () => { const open =
dialog.scaleX = 0; actions?.open ||
dialog.scaleY = 0; (async () => {
await Laya.promises.Tween.to(dialog, { scaleX: 1, scaleY: 1 }, 300, Laya.Ease.backOut); dialog.scaleX = 0
}); dialog.scaleY = 0
await open(dialog); await Laya.promises.Tween.to(
dialog.mouseThrough = true; dialog,
dialog.mouseEnabled = true; { scaleX: 1, scaleY: 1 },
dialog.close = async ()=>{ 300,
if(actions?.close) { Laya.Ease.backOut
await actions.close(); )
})
await open(dialog)
dialog.mouseThrough = true
dialog.mouseEnabled = true
dialog.close = async () => {
if (actions?.close) {
await actions.close()
} else { } else {
await Laya.promises.Tween.to(dialog, { scaleX: 0, scaleY: 0 }, 300, Laya.Ease.strongIn); await Laya.promises.Tween.to(
dialog,
{ scaleX: 0, scaleY: 0 },
300,
Laya.Ease.strongIn
)
} }
const index = this.#dialogStack.indexOf(dialog); const index = this.#dialogStack.indexOf(dialog)
if(index != -1) { if (index != -1) {
this.#dialogStack.splice(index, 1); this.#dialogStack.splice(index, 1)
} }
this.#showDialogStack(); this.#showDialogStack()
} }
this.#dialogLayer.addChild(dialog); this.#dialogLayer.addChild(dialog)
} }
async popup(type, args) { async popup(type, args) {
const className = this.#popups[type]; const className = this.#popups[type]
const popup = await this.getView(className, args, null, type, 'popups'); const popup = await this.getView(className, args, null, type, 'popups')
this.#popupLayer.addChild(popup); this.#popupLayer.addChild(popup)
await popup.popup(args, this.#popupLayer); await popup.popup(args, this.#popupLayer)
this.#popupLayer.removeChild(popup); this.#popupLayer.removeChild(popup)
} }
clearAllDialog() { clearAllDialog() {
this.#dialogStack = []; this.#dialogStack = []
this.#showDialogStack(); this.#showDialogStack()
} }
#config(view, key, type) { #config(view, key, type) {
const config = this.#configs?.[type]?.[key]; const config = this.#configs?.[type]?.[key]
if(!config) return; if (!config) return
if(view.config && view.config(config)) return; if (view.config && view.config(config)) return
const applyConfig = (target, config) => { const applyConfig = (target, config) => {
if(!target) return; if (!target) return
if(typeof config == 'string') { if (typeof config == 'string') {
config = this.#configs?.class?.[config]; config = this.#configs?.class?.[config]
}
$_.deepMapSet(target, config)
} }
$_.deepMapSet(target, config);
};
if(config.names) if (config.names)
for(const name in config.names) for (const name in config.names)
this.#deepGetChildsByName(view, name) this.#deepGetChildsByName(view, name).forEach(child =>
.forEach(child => applyConfig(child, config.names[name])); applyConfig(child, config.names[name])
)
if(config.vars)
for(const key in config.vars)
applyConfig(view[key], config.vars[key]);
if (config.vars)
for (const key in config.vars)
applyConfig(view[key], config.vars[key])
} }
#deepGetChildsByName(parent, name) { #deepGetChildsByName(parent, name) {
const list = []; const list = []
if(!parent || !parent._childs) return list; if (!parent || !parent._childs) return list
for(const child of parent._childs) { for (const child of parent._childs) {
if(child.name == name) list.push(child); if (child.name == name) list.push(child)
if(child._childs) list.push(...this.#deepGetChildsByName(child, name)); if (child._childs)
list.push(...this.#deepGetChildsByName(child, name))
} }
return list; return list
} }
#cutPath(path) { #cutPath(path) {
path = ''+path; path = '' + path
let index = path.length; let index = path.length
do { do {
index --; index--
if(path[index] == '.') { if (path[index] == '.') {
break; break
} }
} while (index>0) } while (index > 0)
return [ return [path.substring(0, index), path.substring(index, path.length)]
path.substring(0, index),
path.substring(index, path.length)
];
} }
#subSkin(skin, type) { #subSkin(skin, type) {
if(!skin || !skin.replace(/\s/g, '')) return []; if (!skin || !skin.replace(/\s/g, '')) return []
switch (type) { switch (type) {
case 'ProgressBar': case 'ProgressBar':
return [ skin, ...this.#progressBarSkin(skin) ]; return [skin, ...this.#progressBarSkin(skin)]
case 'ScrollBar': case 'ScrollBar':
return [ skin, ...this.#scrollBarSkin(skin) ]; return [skin, ...this.#scrollBarSkin(skin)]
default: default:
return [skin] return [skin]
} }
} }
#progressBarSkin(skin) { #progressBarSkin(skin) {
if(!skin.replace(/\s/g, '')) return []; if (!skin.replace(/\s/g, '')) return []
let p = this.#cutPath(skin); let p = this.#cutPath(skin)
return [`${p[0]}$bar${p[1]}`]; return [`${p[0]}$bar${p[1]}`]
} }
#scrollBarSkin(skin) { #scrollBarSkin(skin) {
if(!skin.replace(/\s/g, '')) return []; if (!skin.replace(/\s/g, '')) return []
let p = this.#cutPath(skin); let p = this.#cutPath(skin)
return [ return [
`${p[0]}$bar${p[1]}`, `${p[0]}$bar${p[1]}`,
`${p[0]}$up${p[1]}`, `${p[0]}$up${p[1]}`,
`${p[0]}$down${p[1]}` `${p[0]}$down${p[1]}`,
]; ]
} }
scanResource(uiView) { scanResource(uiView) {
if(!uiView) return []; if (!uiView) return []
const resourceList = []; const resourceList = []
resourceList.push(...this.#subSkin(uiView.props?.skin, uiView.type)); resourceList.push(...this.#subSkin(uiView.props?.skin, uiView.type))
resourceList.push(...this.#subSkin(uiView.props?.hScrollBarSkin, 'ScrollBar')); resourceList.push(
resourceList.push(...this.#subSkin(uiView.props?.vScrollBarSkin, 'ScrollBar')); ...this.#subSkin(uiView.props?.hScrollBarSkin, 'ScrollBar')
)
resourceList.push(
...this.#subSkin(uiView.props?.vScrollBarSkin, 'ScrollBar')
)
uiView.child?.forEach(child => { uiView.child?.forEach(child => {
resourceList.push(...this.scanResource(child)); resourceList.push(...this.scanResource(child))
}); })
return resourceList; return resourceList
} }
get currentView() { get currentView() {
return this.#currentView; return this.#currentView
} }
get currentDialog() { get currentDialog() {
return this.#dialogStack[this.#dialogStack.length -1]; return this.#dialogStack[this.#dialogStack.length - 1]
} }
get theme() { get theme() {
return localStorage.getItem('theme'); return localStorage.getItem('theme')
} }
set theme(value) { set theme(value) {
localStorage.setItem('theme', value); localStorage.setItem('theme', value)
this.#stage.bgColor = this.#configs.bgColor; this.#stage.bgColor = this.#configs.bgColor
document?.querySelector?.('meta[name="theme-color"]')?.setAttribute?.('content', this.#configs.bgColor); document
?.querySelector?.('meta[name="theme-color"]')
?.setAttribute?.('content', this.#configs.bgColor)
} }
get #pages() { get #pages() {
return UIManager.theme(this.theme, 'pages'); return UIManager.theme(this.theme, 'pages')
} }
get #popups() { get #popups() {
return UIManager.theme(this.theme, 'popups'); return UIManager.theme(this.theme, 'popups')
} }
get #configs() { get #configs() {
return UIManager.theme(this.theme, 'configs'); return UIManager.theme(this.theme, 'configs')
} }
get common() { get common() {
return this.#configs.common; return this.#configs.common
} }
gradeColor(grade) { gradeColor(grade) {
return this.common.grade[grade]; return this.common.grade[grade]
} }
gradeFilter(grade) { gradeFilter(grade) {
return this.common.filter[grade]; return this.common.filter[grade]
} }
} }

View File

@@ -10,32 +10,32 @@ const pages = {
THEMES: 'THEMES', THEMES: 'THEMES',
SAVELOAD: 'SAVELOAD', SAVELOAD: 'SAVELOAD',
MODE: 'MODE', MODE: 'MODE',
CELEBRITY: 'CELEBRITY' CELEBRITY: 'CELEBRITY',
}; }
const popups = { const popups = {
ACHIEVEMENT: 'POPUP_ACHIEVEMENT', ACHIEVEMENT: 'POPUP_ACHIEVEMENT',
MESSAGE: 'POPUP_MESSAGE', MESSAGE: 'POPUP_MESSAGE',
}; }
const cyber = { const cyber = {
pages: { pages: {
[pages.LOADING]: "loading", [pages.LOADING]: 'loading',
[pages.MAIN]: "cyber/main", [pages.MAIN]: 'cyber/main',
[pages.TALENT]: "cyber/talent", [pages.TALENT]: 'cyber/talent',
[pages.PROPERTY]: "cyber/property", [pages.PROPERTY]: 'cyber/property',
[pages.TRAJECTORY]: "cyber/trajectory", [pages.TRAJECTORY]: 'cyber/trajectory',
[pages.SUMMARY]: "cyber/summary", [pages.SUMMARY]: 'cyber/summary',
[pages.ACHIEVEMENT]: "cyber/achievement", [pages.ACHIEVEMENT]: 'cyber/achievement',
[pages.THANKS]: "default/thanks", [pages.THANKS]: 'default/thanks',
[pages.THEMES]: 'themes', [pages.THEMES]: 'themes',
[pages.SAVELOAD]: 'saveload', [pages.SAVELOAD]: 'saveload',
[pages.MODE]: 'cyber/mode', [pages.MODE]: 'cyber/mode',
[pages.CELEBRITY]: 'cyber/celebrity', [pages.CELEBRITY]: 'cyber/celebrity',
}, },
popups: { popups: {
[popups.ACHIEVEMENT]: "cyber/popup/achievementPopup", [popups.ACHIEVEMENT]: 'cyber/popup/achievementPopup',
[popups.MESSAGE]: "message", [popups.MESSAGE]: 'message',
}, },
configs: { configs: {
bgColor: '#04131f', bgColor: '#04131f',
@@ -47,18 +47,8 @@ const cyber = {
hoverStroke: '#ffa500', hoverStroke: '#ffa500',
}, },
defaultFontColor: '#cccccc', defaultFontColor: '#cccccc',
grade: [ grade: ['#cccccc', '#55fffe', '#b17cff', '#ffce45'],
'#cccccc', filter: ['#ccccccff', '#55fffeff', '#b17cffff', '#ffce45ff'],
'#55fffe',
'#b17cff',
'#ffce45',
],
filter: [
'#ccccccff',
'#55fffeff',
'#b17cffff',
'#ffce45ff',
],
gradeBlk: [ gradeBlk: [
{ {
visible: false, visible: false,
@@ -78,7 +68,7 @@ const cyber = {
hoverColor: '#ffce45', hoverColor: '#ffce45',
visible: true, visible: true,
}, },
] ],
}, },
pages: { pages: {
[pages.MAIN]: { [pages.MAIN]: {
@@ -97,7 +87,7 @@ const cyber = {
lineWidth: 0, lineWidth: 0,
radius: 100, radius: 100,
}, },
} },
}, },
[pages.THANKS]: { [pages.THANKS]: {
vars: { vars: {
@@ -147,7 +137,7 @@ const cyber = {
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
radius: 80, radius: 80,
}, },
} },
}, },
[pages.SAVELOAD]: { [pages.SAVELOAD]: {
vars: { vars: {
@@ -184,31 +174,31 @@ const cyber = {
radius: 80, radius: 80,
defaultLabel: '#ffffff', defaultLabel: '#ffffff',
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
}
}
}, },
} },
} },
},
},
} }
const dark = { const dark = {
pages: { pages: {
[pages.LOADING]: "loading", [pages.LOADING]: 'loading',
[pages.MAIN]: "default/main", [pages.MAIN]: 'default/main',
[pages.TALENT]: "default/talent", [pages.TALENT]: 'default/talent',
[pages.PROPERTY]: "default/property", [pages.PROPERTY]: 'default/property',
[pages.TRAJECTORY]: "default/trajectory", [pages.TRAJECTORY]: 'default/trajectory',
[pages.SUMMARY]: "default/summary", [pages.SUMMARY]: 'default/summary',
[pages.ACHIEVEMENT]: "default/achievement", [pages.ACHIEVEMENT]: 'default/achievement',
[pages.THANKS]: "default/thanks", [pages.THANKS]: 'default/thanks',
[pages.THEMES]: 'themes', [pages.THEMES]: 'themes',
[pages.SAVELOAD]: 'saveload', [pages.SAVELOAD]: 'saveload',
[pages.MODE]: 'default/mode', [pages.MODE]: 'default/mode',
[pages.CELEBRITY]: 'default/celebrity', [pages.CELEBRITY]: 'default/celebrity',
}, },
popups: { popups: {
[popups.ACHIEVEMENT]: "default/popup/achievementPopup", [popups.ACHIEVEMENT]: 'default/popup/achievementPopup',
[popups.MESSAGE]: "message", [popups.MESSAGE]: 'message',
}, },
configs: { configs: {
bgColor: '#222831', bgColor: '#222831',
@@ -248,18 +238,8 @@ const dark = {
hoverColor: '#ffc500', hoverColor: '#ffc500',
hoverStroke: '#ffa500', hoverStroke: '#ffa500',
}, },
grade: [ grade: ['#cccccc', '#55fffe', '#b17cff', '#ffce45'],
'#cccccc', filter: ['#ccccccff', '#55fffeff', '#b17cffff', '#ffce45ff'],
'#55fffe',
'#b17cff',
'#ffce45',
],
filter: [
'#ccccccff',
'#55fffeff',
'#b17cffff',
'#ffce45ff',
],
card: [ card: [
{ {
normal: { normal: {
@@ -281,7 +261,7 @@ const dark = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
} },
}, },
{ {
normal: { normal: {
@@ -303,7 +283,7 @@ const dark = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
} },
}, },
{ {
normal: { normal: {
@@ -325,7 +305,7 @@ const dark = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
} },
}, },
{ {
normal: { normal: {
@@ -347,8 +327,8 @@ const dark = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
} },
} },
], ],
summary: [ summary: [
{ {
@@ -360,7 +340,8 @@ const dark = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 2, lineWidth: 2,
radius: 0, radius: 0,
},{ },
{
defaultColor: '#6495ed', defaultColor: '#6495ed',
defaultStroke: '#f8f8f8', defaultStroke: '#f8f8f8',
defaultLabel: '#eeeeee', defaultLabel: '#eeeeee',
@@ -369,7 +350,8 @@ const dark = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 2, lineWidth: 2,
radius: 0, radius: 0,
},{ },
{
defaultColor: '#e2a7ff', defaultColor: '#e2a7ff',
defaultStroke: '#f8f8f8', defaultStroke: '#f8f8f8',
defaultLabel: '#eeeeee', defaultLabel: '#eeeeee',
@@ -388,7 +370,7 @@ const dark = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 2, lineWidth: 2,
radius: 0, radius: 0,
} },
], ],
achievement: [ achievement: [
{ {
@@ -400,7 +382,8 @@ const dark = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 4, lineWidth: 4,
radius: 0, radius: 0,
},{ },
{
defaultColor: '#6495ed', defaultColor: '#6495ed',
defaultStroke: '#f8f8f8', defaultStroke: '#f8f8f8',
defaultLabel: '#eeeeee', defaultLabel: '#eeeeee',
@@ -409,7 +392,8 @@ const dark = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 4, lineWidth: 4,
radius: 0, radius: 0,
},{ },
{
defaultColor: '#e2a7ff', defaultColor: '#e2a7ff',
defaultStroke: '#f8f8f8', defaultStroke: '#f8f8f8',
defaultLabel: '#eeeeee', defaultLabel: '#eeeeee',
@@ -428,7 +412,7 @@ const dark = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 4, lineWidth: 4,
radius: 0, radius: 0,
} },
], ],
characterItem: { characterItem: {
name: { name: {
@@ -488,7 +472,7 @@ const dark = {
}, },
font_default: { font_default: {
color: '#eeeeee', color: '#eeeeee',
} },
}, },
pages: { pages: {
[pages.MAIN]: { [pages.MAIN]: {
@@ -512,14 +496,14 @@ const dark = {
names: { names: {
title: 'title', title: 'title',
btnSmall: 'btn_small', btnSmall: 'btn_small',
} },
}, },
[pages.TALENT]: { [pages.TALENT]: {
vars: { vars: {
btnDrawCard: 'btn_main', btnDrawCard: 'btn_main',
btnNext: 'btn_main', btnNext: 'btn_main',
title: 'title', title: 'title',
} },
}, },
[pages.PROPERTY]: { [pages.PROPERTY]: {
vars: { vars: {
@@ -530,9 +514,9 @@ const dark = {
names: { names: {
font_default: 'font_default', font_default: 'font_default',
property: { property: {
colorFilter: '#eeeeeeff' colorFilter: '#eeeeeeff',
} },
} },
}, },
[pages.TRAJECTORY]: { [pages.TRAJECTORY]: {
vars: { vars: {
@@ -548,8 +532,8 @@ const dark = {
radius: 4, radius: 4,
}, },
boxSpeed: { boxSpeed: {
colorFilter: '#ffffffff' colorFilter: '#ffffffff',
} },
}, },
names: { names: {
propertyBox: { propertyBox: {
@@ -571,8 +555,8 @@ const dark = {
hoverLabel: '#222831', hoverLabel: '#222831',
lineWidth: 0, lineWidth: 0,
radius: 4, radius: 4,
} },
} },
}, },
[pages.SUMMARY]: { [pages.SUMMARY]: {
vars: { vars: {
@@ -581,7 +565,7 @@ const dark = {
}, },
names: { names: {
font_default: 'font_default', font_default: 'font_default',
} },
}, },
[pages.ACHIEVEMENT]: { [pages.ACHIEVEMENT]: {
vars: { vars: {
@@ -591,7 +575,7 @@ const dark = {
names: { names: {
font_default: 'font_default', font_default: 'font_default',
title: 'title', title: 'title',
} },
}, },
[pages.THANKS]: { [pages.THANKS]: {
vars: { vars: {
@@ -632,7 +616,7 @@ const dark = {
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
radius: 80, radius: 80,
}, },
} },
}, },
[pages.SAVELOAD]: { [pages.SAVELOAD]: {
vars: { vars: {
@@ -669,20 +653,20 @@ const dark = {
radius: 80, radius: 80,
defaultLabel: '#ffffff', defaultLabel: '#ffffff',
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
} },
} },
}, },
[pages.MODE]: { [pages.MODE]: {
names: { names: {
font_default: 'font_default', font_default: 'font_default',
btn: 'btn_main', btn: 'btn_main',
} },
}, },
[pages.CELEBRITY]: { [pages.CELEBRITY]: {
vars: { vars: {
btnRetry: 'btn_main', btnRetry: 'btn_main',
btnNext: 'btn_main2', btnNext: 'btn_main2',
} },
}, },
}, },
popups: { popups: {
@@ -693,31 +677,31 @@ const dark = {
defaultStroke: '#84ff55', defaultStroke: '#84ff55',
hoverColor: '#292a28', hoverColor: '#292a28',
hoverStroke: '#84ff55', hoverStroke: '#84ff55',
} },
} },
} },
} },
} },
} }
const light = { const light = {
pages: { pages: {
[pages.LOADING]: "loading", [pages.LOADING]: 'loading',
[pages.MAIN]: "default/main", [pages.MAIN]: 'default/main',
[pages.TALENT]: "default/talent", [pages.TALENT]: 'default/talent',
[pages.PROPERTY]: "default/property", [pages.PROPERTY]: 'default/property',
[pages.TRAJECTORY]: "default/trajectory", [pages.TRAJECTORY]: 'default/trajectory',
[pages.SUMMARY]: "default/summary", [pages.SUMMARY]: 'default/summary',
[pages.ACHIEVEMENT]: "default/achievement", [pages.ACHIEVEMENT]: 'default/achievement',
[pages.THANKS]: "default/thanks", [pages.THANKS]: 'default/thanks',
[pages.THEMES]: 'themes', [pages.THEMES]: 'themes',
[pages.SAVELOAD]: 'saveload', [pages.SAVELOAD]: 'saveload',
[pages.MODE]: 'default/mode', [pages.MODE]: 'default/mode',
[pages.CELEBRITY]: 'default/celebrity', [pages.CELEBRITY]: 'default/celebrity',
}, },
popups: { popups: {
[popups.ACHIEVEMENT]: "default/popup/achievementPopup", [popups.ACHIEVEMENT]: 'default/popup/achievementPopup',
[popups.MESSAGE]: "message", [popups.MESSAGE]: 'message',
}, },
configs: { configs: {
bgColor: '#ffffff', bgColor: '#ffffff',
@@ -757,18 +741,8 @@ const light = {
hoverColor: '#ffc500', hoverColor: '#ffc500',
hoverStroke: '#ffa500', hoverStroke: '#ffa500',
}, },
grade: [ grade: ['#000000', '#55fffe', '#b17cff', '#ffce45'],
'#000000', filter: ['#000000ff', '#55fffeff', '#b17cffff', '#ffce45ff'],
'#55fffe',
'#b17cff',
'#ffce45',
],
filter: [
'#000000ff',
'#55fffeff',
'#b17cffff',
'#ffce45ff',
],
card: [ card: [
{ {
normal: { normal: {
@@ -790,7 +764,7 @@ const light = {
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
} },
}, },
{ {
normal: { normal: {
@@ -812,7 +786,7 @@ const light = {
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
} },
}, },
{ {
normal: { normal: {
@@ -834,7 +808,7 @@ const light = {
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
} },
}, },
{ {
normal: { normal: {
@@ -856,8 +830,8 @@ const light = {
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
} },
} },
], ],
summary: [ summary: [
{ {
@@ -869,7 +843,8 @@ const light = {
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
},{ },
{
defaultColor: '#6495ed', defaultColor: '#6495ed',
defaultStroke: '#f8f8f8', defaultStroke: '#f8f8f8',
defaultLabel: '#ffffff', defaultLabel: '#ffffff',
@@ -878,7 +853,8 @@ const light = {
hoverLabel: '#666666', hoverLabel: '#666666',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
},{ },
{
defaultColor: '#e2a7ff', defaultColor: '#e2a7ff',
defaultStroke: '#f8f8f8', defaultStroke: '#f8f8f8',
defaultLabel: '#ffffff', defaultLabel: '#ffffff',
@@ -887,7 +863,8 @@ const light = {
hoverLabel: '#666666', hoverLabel: '#666666',
lineWidth: 4, lineWidth: 4,
radius: 4, radius: 4,
},{ },
{
defaultColor: '#ffa07a', defaultColor: '#ffa07a',
defaultStroke: '#f8f8f8', defaultStroke: '#f8f8f8',
defaultLabel: '#ffffff', defaultLabel: '#ffffff',
@@ -908,7 +885,8 @@ const light = {
hoverLabel: '#efefef', hoverLabel: '#efefef',
lineWidth: 4, lineWidth: 4,
radius: 0, radius: 0,
},{ },
{
defaultColor: '#6495ed', defaultColor: '#6495ed',
defaultStroke: '#cccccc', defaultStroke: '#cccccc',
defaultLabel: '#eeeeee', defaultLabel: '#eeeeee',
@@ -917,7 +895,8 @@ const light = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 4, lineWidth: 4,
radius: 0, radius: 0,
},{ },
{
defaultColor: '#e2a7ff', defaultColor: '#e2a7ff',
defaultStroke: '#cccccc', defaultStroke: '#cccccc',
defaultLabel: '#eeeeee', defaultLabel: '#eeeeee',
@@ -926,7 +905,8 @@ const light = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 4, lineWidth: 4,
radius: 0, radius: 0,
},{ },
{
defaultColor: '#ffa07a', defaultColor: '#ffa07a',
defaultStroke: '#cccccc', defaultStroke: '#cccccc',
defaultLabel: '#eeeeee', defaultLabel: '#eeeeee',
@@ -935,7 +915,7 @@ const light = {
hoverLabel: '#3b3b3b', hoverLabel: '#3b3b3b',
lineWidth: 4, lineWidth: 4,
radius: 0, radius: 0,
} },
], ],
characterItem: { characterItem: {
name: { name: {
@@ -995,7 +975,7 @@ const light = {
}, },
font_default: { font_default: {
color: '#000000', color: '#000000',
} },
}, },
pages: { pages: {
[pages.MAIN]: { [pages.MAIN]: {
@@ -1019,14 +999,14 @@ const light = {
names: { names: {
title: 'title', title: 'title',
btnSmall: 'btn_small', btnSmall: 'btn_small',
} },
}, },
[pages.TALENT]: { [pages.TALENT]: {
vars: { vars: {
btnDrawCard: 'btn_main', btnDrawCard: 'btn_main',
btnNext: 'btn_main', btnNext: 'btn_main',
title: 'title', title: 'title',
} },
}, },
[pages.PROPERTY]: { [pages.PROPERTY]: {
vars: { vars: {
@@ -1037,9 +1017,9 @@ const light = {
names: { names: {
font_default: 'font_default', font_default: 'font_default',
property: { property: {
colorFilter: '#000000ff' colorFilter: '#000000ff',
} },
} },
}, },
[pages.TRAJECTORY]: { [pages.TRAJECTORY]: {
vars: { vars: {
@@ -1055,8 +1035,8 @@ const light = {
radius: 4, radius: 4,
}, },
boxSpeed: { boxSpeed: {
colorFilter: '#666666ff' colorFilter: '#666666ff',
} },
}, },
names: { names: {
propertyBox: { propertyBox: {
@@ -1078,8 +1058,8 @@ const light = {
hoverLabel: '#222831', hoverLabel: '#222831',
lineWidth: 0, lineWidth: 0,
radius: 4, radius: 4,
} },
} },
}, },
[pages.SUMMARY]: { [pages.SUMMARY]: {
vars: { vars: {
@@ -1088,7 +1068,7 @@ const light = {
}, },
names: { names: {
font_default: 'font_default', font_default: 'font_default',
} },
}, },
[pages.ACHIEVEMENT]: { [pages.ACHIEVEMENT]: {
vars: { vars: {
@@ -1098,7 +1078,7 @@ const light = {
names: { names: {
font_default: 'font_default', font_default: 'font_default',
title: 'title', title: 'title',
} },
}, },
[pages.THANKS]: { [pages.THANKS]: {
vars: { vars: {
@@ -1120,7 +1100,7 @@ const light = {
hoverStroke: '#dc76a9', hoverStroke: '#dc76a9',
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
radius: 4, radius: 4,
} },
}, },
}, },
[pages.THEMES]: { [pages.THEMES]: {
@@ -1139,7 +1119,7 @@ const light = {
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
radius: 80, radius: 80,
}, },
} },
}, },
[pages.SAVELOAD]: { [pages.SAVELOAD]: {
vars: { vars: {
@@ -1176,20 +1156,20 @@ const light = {
radius: 80, radius: 80,
defaultLabel: '#ffffff', defaultLabel: '#ffffff',
hoverLabel: '#ffffff', hoverLabel: '#ffffff',
} },
} },
}, },
[pages.MODE]: { [pages.MODE]: {
names: { names: {
font_default: 'font_default', font_default: 'font_default',
btn: 'btn_main', btn: 'btn_main',
} },
}, },
[pages.CELEBRITY]: { [pages.CELEBRITY]: {
vars: { vars: {
btnRetry: 'btn_main', btnRetry: 'btn_main',
btnNext: 'btn_main2', btnNext: 'btn_main2',
} },
}, },
}, },
popups: { popups: {
@@ -1201,14 +1181,13 @@ const light = {
hoverColor: '#ffffff', hoverColor: '#ffffff',
hoverStroke: '#84ff55', hoverStroke: '#84ff55',
lineWidth: 1, lineWidth: 1,
} },
} },
} },
},
} },
}
} }
const themes = { default: dark, cyber, dark, light }; const themes = { default: dark, cyber, dark, light }
export default { themes, pages, popups }; export default { themes, pages, popups }

View File

@@ -2,10 +2,7 @@
<html lang="{{ site.lang | default: "en-US" }}"> <html lang="{{ site.lang | default: "en-US" }}">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<script data-ad-client="ca-pub-9857163863537600" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
{% seo %} {% seo %}
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap" as="style" type="text/css" crossorigin>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#157878"> <meta name="theme-color" content="#157878">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
@@ -18,8 +15,7 @@
<header class="page-header" role="banner"> <header class="page-header" role="banner">
<h1 class="project-name">{{ page.title | default: site.title | default: site.github.repository_name }}</h1> <h1 class="project-name">{{ page.title | default: site.title | default: site.github.repository_name }}</h1>
<h2 class="project-tagline">{{ page.description | default: site.description | default: site.github.project_tagline }}</h2> <h2 class="project-tagline">{{ page.description | default: site.description | default: site.github.project_tagline }}</h2>
<a href="/view/" class="btn">RESTART</a> <a href="/public/" class="btn">RESTART</a>
<a href="/view/test.html" class="btn">Source Version</a>
{% if site.github.is_project_page %} {% if site.github.is_project_page %}
<a href="{{ site.github.repository_url }}" class="btn">View on GitHub</a> <a href="{{ site.github.repository_url }}" class="btn">View on GitHub</a>
{% endif %} {% endif %}

View File

@@ -1,26 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta name="description" content="やり直すんだ。そして、次はうまくやる。"/>
<meta name="keywords" content="人生重开模拟器 liferestart life restart remake 人生重来"/>
<meta name="renderer" content="webkit"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="full-screen" content="true"/>
<meta name="x5-fullscreen" content="true"/>
<meta name="360-fullscreen" content="true"/>
<meta name="theme-color" content="#157878"/>
<meta name="laya" screenorientation ="landscape"/>
<meta http-equiv="expires" content="0"/>
<meta http-equiv="Cache-Control" content="no-siteapp"/>
<title>Life Restart</title>
<script type="text/javascript" src="libs/laya/min/laya.core.min.js"></script>
<script type="text/javascript" src="libs/laya/min/laya.webgl.min.js"></script>
<script type="text/javascript" src="libs/laya/min/laya.filter.min.js"></script>
<script type="text/javascript" src="libs/laya/min/laya.particle.min.js"></script>
<script type="text/javascript" src="libs/laya/min/laya.ui.min.js"></script>
</head>
<body style="background:black"></body>
</html>

View File

@@ -7,10 +7,8 @@
<meta name="description" content="やり直すんだ。そして、次はうまくやる。"/> <meta name="description" content="やり直すんだ。そして、次はうまくやる。"/>
<meta name="keywords" content="人生重开模拟器 liferestart life restart remake 人生重来"/> <meta name="keywords" content="人生重开模拟器 liferestart life restart remake 人生重来"/>
<title>Life Restart</title> <title>Life Restart</title>
</head>
<body>
<script language="javascript" type="text/javascript"> <script language="javascript" type="text/javascript">
window.location.href="/public/index.html"; window.location.href="/public/index.html";
</script> </script>
</body> </head>
</html> </html>

View File

@@ -1,253 +0,0 @@
import { readFile } from 'fs/promises';
import Life from '../src/modules/life.js'
globalThis.localStorage = {};
localStorage.getItem = key => localStorage[key]===void 0? null: localStorage[key];
localStorage.setItem = (key, value) => (localStorage[key] = value);
globalThis.$$eventMap = new Map();
globalThis.$$event = (tag, data) => {
const listener = $$eventMap.get(tag);
if(listener) listener.forEach(fn=>fn(data));
}
globalThis.$$on = (tag, fn) => {
let listener = $$eventMap.get(tag);
if(!listener) {
listener = new Set();
$$eventMap.set(tag, listener);
}
listener.add(fn);
}
globalThis.$$off = (tag, fn) => {
const listener = $$eventMap.get(tag);
if(listener) listener.delete(fn);
}
async function debug(config) {
const core = new Life();
core.config(config);
await core.initial(
async fileName => JSON.parse(await readFile(`public/data/zh-cn/${fileName}.json`)),
async fileName => JSON.parse(await readFile(`public/data/${fileName}.json`)),
);
core.remake(
core.talentRandom()
.splice(0,3)
.map(({id})=>id)
);
let pts = core.getPropertyPoints();
const limit = core.propertyAllocateLimit;
const arr = new Array(4).fill(limit[1]);
while (pts > 0) {
const sub = Math.round(Math.random() * (Math.min(pts, limit[1]) - 1)) + 1;
while(true) {
const select = Math.floor(Math.random() * 4) % 4;
if(arr[select] - sub <0) continue;
arr[select] -= sub;
pts -= sub;
break;
}
}
core.start({
CHR: limit[1] - arr[0], // 颜值 charm CHR
INT: limit[1] - arr[1], // 智力 intelligence INT
STR: limit[1] - arr[2], // 体质 strength STR
MNY: limit[1] - arr[3], // 家境 money MNY
});
const lifeTrajectory = [];
let trajectory;
do{
try{
trajectory = core.next();
} catch(e) {
console.error(e);
// debugger
throw e;
}
lifeTrajectory.push(trajectory);
const { age, content } = trajectory;
console.debug(
`---------------------------------`,
`\n-- ${age}\n `,
content.map(
({type, description, rate, name, postEvent}) => {
switch(type) {
case 'TLT':
return `天赋【${name}】发动:${description}`;
case 'EVT':
return description + (postEvent?`\n ${postEvent}`:'');
}
}
).join('\n ')
);
// if(age == 60) debugger
} while(!trajectory.isEnd)
// debugger;
}
debug({
defaultPropertyPoints: 20, // default number of points for a property
talentSelectLimit: 3, // max number of talents that can be selected
propertyAllocateLimit: [0, 10], // scoop of properties that can be allocated,
defaultPropertys: { SPR: 5 }, // default properties
talentConfig: { // config for talent
talentPullCount: 10, // number of talents to pull from the talent pool
talentRate: { 1:100, 2:10, 3:1, total: 1000 }, // rate of talent pull
additions: {
TMS: [
[ 10, { 2: 1 }],
[ 30, { 2: 2 }],
[ 50, { 2: 3 }],
[ 70, { 2: 4 }],
[100, { 2: 5 }],
],
CACHV: [
[ 10, { 2: 1 }],
[ 30, { 2: 2 }],
[ 50, { 2: 3 }],
[ 70, { 2: 4 }],
[100, { 2: 5 }],
]
},
},
propertyConfig: { // config for property
judge: {
// type: [min, grade, judge]
RTLT: [
[ 0, 0],
[ 0.3, 1],
[ 0.6, 2],
[ 0.9, 3],
],
REVT: [
[ 0, 0],
[ 0.2, 1],
[ 0.4, 2],
[ 0.6, 3],
],
TMS: [
[ 0, 0, 'UI_Remake_Times_Judge_Level_0'],
[ 10, 1, 'UI_Remake_Times_Judge_Level_1'],
[ 30, 1, 'UI_Remake_Times_Judge_Level_2'],
[ 50, 2, 'UI_Remake_Times_Judge_Level_3'],
[ 70, 2, 'UI_Remake_Times_Judge_Level_4'],
[ 100, 3, 'UI_Remake_Times_Judge_Level_5'],
],
CACHV: [
[ 0, 0, 'UI_Achievement_Count_Judge_Level_0'],
[ 10, 1, 'UI_Achievement_Count_Judge_Level_1'],
[ 30, 1, 'UI_Achievement_Count_Judge_Level_2'],
[ 50, 2, 'UI_Achievement_Count_Judge_Level_3'],
[ 70, 2, 'UI_Achievement_Count_Judge_Level_4'],
[ 100, 3, 'UI_Achievement_Count_Judge_Level_5'],
],
HCHR: [
[ 0, 0, 'UI_Judge_Level_0'],
[ 1, 0, 'UI_Judge_Level_1'],
[ 2, 0, 'UI_Judge_Level_2'],
[ 4, 0, 'UI_Judge_Level_3'],
[ 7, 1, 'UI_Judge_Level_4'],
[ 9, 2, 'UI_Judge_Level_5'],
[ 11, 3, 'UI_Judge_Level_6'],
],
HMNY: [
[ 0, 0, 'UI_Judge_Level_0'],
[ 1, 0, 'UI_Judge_Level_1'],
[ 2, 0, 'UI_Judge_Level_2'],
[ 4, 0, 'UI_Judge_Level_3'],
[ 7, 1, 'UI_Judge_Level_4'],
[ 9, 2, 'UI_Judge_Level_5'],
[ 11, 3, 'UI_Judge_Level_6'],
],
HSPR: [
[ 0, 0, 'UI_Spirit_Judge_Level_0'],
[ 1, 0, 'UI_Spirit_Judge_Level_1'],
[ 2, 0, 'UI_Spirit_Judge_Level_2'],
[ 4, 0, 'UI_Spirit_Judge_Level_3'],
[ 7, 1, 'UI_Spirit_Judge_Level_4'],
[ 9, 2, 'UI_Spirit_Judge_Level_5'],
[ 11, 3, 'UI_Spirit_Judge_Level_6'],
],
HINT: [
[ 0, 0, 'UI_Judge_Level_0'],
[ 1, 0, 'UI_Judge_Level_1'],
[ 2, 0, 'UI_Judge_Level_2'],
[ 4, 0, 'UI_Judge_Level_3'],
[ 7, 1, 'UI_Judge_Level_4'],
[ 9, 2, 'UI_Judge_Level_5'],
[ 11, 3, 'UI_Judge_Level_6'],
[ 21, 3, 'UI_Intelligence_Judge_Level_7'],
[ 131, 3, 'UI_Intelligence_Judge_Level_8'],
[ 501, 3, 'UI_Intelligence_Judge_Level_9'],
],
HSTR: [
[ 0, 0, 'UI_Judge_Level_0'],
[ 1, 0, 'UI_Judge_Level_1'],
[ 2, 0, 'UI_Judge_Level_2'],
[ 4, 0, 'UI_Judge_Level_3'],
[ 7, 1, 'UI_Judge_Level_4'],
[ 9, 2, 'UI_Judge_Level_5'],
[ 11, 3, 'UI_Judge_Level_6'],
[ 21, 3, 'UI_Strength_Judge_Level_7'],
[ 101, 3, 'UI_Strength_Judge_Level_8'],
[ 401, 3, 'UI_Strength_Judge_Level_9'],
[1001, 3, 'UI_Strength_Judge_Level_10'],
[2001, 3, 'UI_Strength_Judge_Level_11'],
],
HAGE: [
[ 0, 0, 'UI_AGE_Judge_Level_0'],
[ 1, 0, 'UI_AGE_Judge_Level_1'],
[ 10, 0, 'UI_AGE_Judge_Level_2'],
[ 18, 0, 'UI_AGE_Judge_Level_3'],
[ 40, 0, 'UI_AGE_Judge_Level_4'],
[ 60, 1, 'UI_AGE_Judge_Level_5'],
[ 70, 1, 'UI_AGE_Judge_Level_6'],
[ 80, 2, 'UI_AGE_Judge_Level_7'],
[ 90, 2, 'UI_AGE_Judge_Level_8'],
[ 95, 3, 'UI_AGE_Judge_Level_9'],
[ 100, 3, 'UI_AGE_Judge_Level_10'],
[ 500, 3, 'UI_AGE_Judge_Level_11'],
],
SUM: [
[ 0, 0, 'UI_Judge_Level_0'],
[ 41, 0, 'UI_Judge_Level_1'],
[ 50, 0, 'UI_Judge_Level_2'],
[ 60, 0, 'UI_Judge_Level_3'],
[ 80, 1, 'UI_Judge_Level_4'],
[ 100, 2, 'UI_Judge_Level_5'],
[ 110, 3, 'UI_Judge_Level_6'],
[ 120, 3, 'UI_Judge_Level_7'],
],
},
},
characterConfig: { // config for character
characterPullCount: 3,
rateableKnife: 10,
propertyWeight: [
[ 0, 1],
[ 1, 2],
[ 2, 3],
[ 3, 4],
[ 4, 5],
[ 5, 6],
[ 6, 5],
[ 7, 4],
[ 8, 3],
[ 9, 2],
[10, 1],
],
talentWeight: [
[ 1, 1],
[ 2, 2],
[ 3, 3],
[ 4, 2],
[ 5, 1],
],
},
});

6
vite.config.js Normal file
View File

@@ -0,0 +1,6 @@
/** @type {import('vite').UserConfig} */
export default {
build: {
outDir: 'template/public',
},
}

View File

@@ -1,57 +0,0 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'production',
entry: './src/index.js',
devtool: 'eval-cheap-module-source-map',
devServer: {
static: [
{
directory: path.join(__dirname, 'public'),
publicPath: '/public',
},
{
directory: path.join(__dirname, 'view'),
publicPath: '/view',
},
{
directory: path.join(__dirname, 'src'),
publicPath: '/src',
},
],
allowedHosts: "all",
},
output: {
path: path.resolve(__dirname, 'public/chunk'),
filename: '[name].[chunkhash:5].js',
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
template: 'template/index.html',
filename: '../index.html',
}),
],
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
"targets": "> 0.25%, not dead",
"useBuiltIns": "usage",
"corejs": "3.8.3",
}
]
]
}
}
}]
}
};

3782
yarn.lock

File diff suppressed because it is too large Load Diff