mirror of
https://github.com/VickScarlet/lifeRestart.git
synced 2026-04-10 01:57:51 +08:00
add unique character
This commit is contained in:
@@ -160,11 +160,7 @@ class App{
|
||||
globalThis.$ui = UIManager.getInstance();
|
||||
|
||||
if(theme=='default') {
|
||||
if(!localStorage.getItem('__')) {
|
||||
localStorage.setItem('__', 1);
|
||||
localStorage.setItem('theme', 'cyber');
|
||||
}
|
||||
theme = localStorage.getItem('theme');
|
||||
theme = localStorage.getItem('theme') || 'default';
|
||||
}
|
||||
|
||||
$ui.theme = theme;
|
||||
|
||||
0
src/functions/unique.js
Normal file
0
src/functions/unique.js
Normal file
@@ -141,9 +141,14 @@ export default ({
|
||||
UI_CelebrityMode: 'Celebrity',
|
||||
UI_CelebrityModeDescription: 'Past life is celebrity\nRebirth to modern',
|
||||
UI_AllNot: '↻All Not',
|
||||
UI_UniqueWaTaShi: 'Unique of mine',
|
||||
UI_UniqueWaTaShiContent: '\nUnique character card different from other 60 million player\nAll property, All talent, All random\nAll has only one chance',
|
||||
UI_GenerateNow: 'Generate Now',
|
||||
|
||||
|
||||
M_NoRank: 'There is no rank',
|
||||
M_PleaseSelectOne: 'Please Select One',
|
||||
M_UnGenerate: 'Unique Character no generate',
|
||||
M_DisableExtendTalent: 'Celebrity mode can\'t extends talent',
|
||||
|
||||
F_RemakeTimes: 'Remake {0} Times',
|
||||
|
||||
@@ -143,10 +143,13 @@ export default ({
|
||||
UI_CelebrityMode: '名人模式',
|
||||
UI_CelebrityModeDescription: '前世是古代名人\n重开到了现代',
|
||||
UI_AllNot: '↻都不是',
|
||||
|
||||
UI_UniqueWaTaShi: '独一无二的我',
|
||||
UI_UniqueWaTaShiContent: '\n6000万玩家中独一无二的角色卡\n所有属性 所有天赋 随机生成\n 每人只能生成一次',
|
||||
UI_GenerateNow: '立即生成',
|
||||
|
||||
M_NoRank: '别卷了,没有排行榜',
|
||||
M_PleaseSelectOne: '请选择一个名人',
|
||||
M_UnGenerate: '独一无二的我还没有生成',
|
||||
M_DisableExtendTalent: '名人模式不能继承天赋',
|
||||
|
||||
F_RemakeTimes: '已重开{0}次',
|
||||
|
||||
24
src/index.js
24
src/index.js
@@ -196,5 +196,29 @@ core.config({
|
||||
],
|
||||
},
|
||||
},
|
||||
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],
|
||||
],
|
||||
},
|
||||
});
|
||||
game.start(query);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { clone } from '../functions/util.js';
|
||||
import { checkCondition } from '../functions/condition.js';
|
||||
|
||||
class Achievement {
|
||||
constructor() {}
|
||||
constructor(system) {
|
||||
this.#system = system;
|
||||
}
|
||||
|
||||
// 时机
|
||||
Opportunity = {
|
||||
@@ -12,6 +11,7 @@ class Achievement {
|
||||
END: "END", // 游戏完成,点击重开 重开次数在这之后才会+1
|
||||
};
|
||||
|
||||
#system;
|
||||
#achievements;
|
||||
|
||||
initial({achievements}) {
|
||||
@@ -23,7 +23,11 @@ class Achievement {
|
||||
return Object.keys(this.#achievements).length;
|
||||
}
|
||||
|
||||
list(property) {
|
||||
get #prop() {
|
||||
return this.#system.request(this.#system.Module.PROPERTY);
|
||||
}
|
||||
|
||||
list() {
|
||||
return Object
|
||||
.values(this.#achievements)
|
||||
.map(({
|
||||
@@ -32,34 +36,34 @@ class Achievement {
|
||||
})=>({
|
||||
id, name, opportunity,
|
||||
description, hide, grade,
|
||||
isAchieved: this.isAchieved(id, property),
|
||||
isAchieved: this.isAchieved(id, this.#prop),
|
||||
}));
|
||||
}
|
||||
|
||||
get(achievementId) {
|
||||
const achievement = this.#achievements[achievementId];
|
||||
if(!achievement) throw new Error(`[ERROR] No Achievement[${achievementId}]`);
|
||||
return clone(achievement);
|
||||
return this.#system.clone(achievement);
|
||||
}
|
||||
|
||||
check(achievementId, property) {
|
||||
check(achievementId) {
|
||||
const { condition } = this.get(achievementId);
|
||||
return checkCondition(property, condition);
|
||||
return this.#system.check(condition);
|
||||
}
|
||||
|
||||
isAchieved(achievementId, property) {
|
||||
for(const [achieved] of (property.get(property.TYPES.ACHV)||[]))
|
||||
isAchieved(achievementId) {
|
||||
for(const [achieved] of (this.#prop.get(this.#prop.TYPES.ACHV)||[]))
|
||||
if(achieved == achievementId) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
achieve(opportunity, property) {
|
||||
this.list(property)
|
||||
achieve(opportunity) {
|
||||
this.list()
|
||||
.filter(({isAchieved})=>!isAchieved)
|
||||
.filter(({opportunity: o})=>o==opportunity)
|
||||
.filter(({id})=>this.check(id, property))
|
||||
.filter(({id})=>this.check(id, this.#prop))
|
||||
.forEach(({id})=>{
|
||||
property.achieve(property.TYPES.ACHV, id)
|
||||
this.#prop.achieve(this.#prop.TYPES.ACHV, id)
|
||||
$$event('achievement', this.get(id))
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
import { clone, weightRandom } from '../functions/util.js';
|
||||
|
||||
class Character {
|
||||
constructor() {}
|
||||
constructor(system) {
|
||||
this.#system = system;
|
||||
}
|
||||
|
||||
#system;
|
||||
#characters;
|
||||
#characterPullCount;
|
||||
#rateableKnife;
|
||||
#rate;
|
||||
#pipe = [];
|
||||
#uniqueWaTaShi;
|
||||
#propertyWeight;
|
||||
#talentWeight
|
||||
|
||||
initial({characters}) {
|
||||
this.#characters = characters;
|
||||
const uniqueWaTaShi = localStorage.getItem('uniqueWaTaShi');
|
||||
if(uniqueWaTaShi != null || uniqueWaTaShi != 'undefined')
|
||||
this.#uniqueWaTaShi = JSON.parse(uniqueWaTaShi);
|
||||
return this.count;
|
||||
}
|
||||
|
||||
@@ -20,16 +28,70 @@ class Character {
|
||||
config({
|
||||
characterPullCount = 3,
|
||||
rateableKnife = 10,
|
||||
propertyWeight,
|
||||
talentWeight,
|
||||
} = {}) {
|
||||
this.#characterPullCount = characterPullCount;
|
||||
this.#rateableKnife = rateableKnife;
|
||||
this.#propertyWeight = propertyWeight;
|
||||
this.#talentWeight = talentWeight;
|
||||
}
|
||||
|
||||
get #unique() {
|
||||
if(this.#uniqueWaTaShi) {
|
||||
return this.#system.clone(this.#uniqueWaTaShi);
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
this.#pipe.push(now);
|
||||
if(this.#pipe.length < 10) return null;
|
||||
const time = this.#pipe.shift();
|
||||
if(now - time > 10000) return null;
|
||||
return {unique: true, generate: false};
|
||||
}
|
||||
|
||||
set #unique(data) {
|
||||
this.#uniqueWaTaShi = this.#system.clone(data);
|
||||
this.#uniqueWaTaShi.unique = true;
|
||||
this.#uniqueWaTaShi.generate = true;
|
||||
localStorage.setItem(
|
||||
'uniqueWaTaShi',
|
||||
JSON.stringify(this.#uniqueWaTaShi)
|
||||
);
|
||||
}
|
||||
|
||||
get #weightRandom() {
|
||||
return this.#system.function(this.#system.Function.UTIL).weightRandom;
|
||||
}
|
||||
|
||||
generateUnique() {
|
||||
if(this.#uniqueWaTaShi) return this.#unique;
|
||||
const weightRandom = this.#weightRandom;
|
||||
const {CHR, INT, STR, MNY} = this.#system.PropertyTypes;
|
||||
|
||||
this.#unique = {
|
||||
property: {
|
||||
[CHR]: weightRandom(this.#propertyWeight),
|
||||
[INT]: weightRandom(this.#propertyWeight),
|
||||
[STR]: weightRandom(this.#propertyWeight),
|
||||
[MNY]: weightRandom(this.#propertyWeight),
|
||||
},
|
||||
talent: this.#system
|
||||
.request(this.#system.Module.TALENT)
|
||||
.random(weightRandom(this.#talentWeight)),
|
||||
}
|
||||
|
||||
return this.#unique;
|
||||
}
|
||||
|
||||
random() {
|
||||
return this.rateable();
|
||||
return {
|
||||
unique: this.#unique,
|
||||
normal: this.#rateable(),
|
||||
}
|
||||
}
|
||||
|
||||
rateable() {
|
||||
#rateable() {
|
||||
if(!this.#rate) {
|
||||
this.#rate = {};
|
||||
for(const id in this.#characters) {
|
||||
@@ -38,6 +100,7 @@ class Character {
|
||||
}
|
||||
|
||||
const r = [];
|
||||
const weightRandom = this.#weightRandom;
|
||||
new Array(this.#characterPullCount)
|
||||
.fill(0)
|
||||
.forEach(()=>{
|
||||
@@ -63,7 +126,7 @@ class Character {
|
||||
this.#rate[id] -= this.#rateableKnife;
|
||||
}
|
||||
}
|
||||
return r.map(id=>clone(this.#characters[id]));
|
||||
return r.map(id=>this.#system.clone(this.#characters[id]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { clone } from '../functions/util.js';
|
||||
import { checkCondition } from '../functions/condition.js';
|
||||
|
||||
class Event {
|
||||
constructor() {}
|
||||
constructor(system) {
|
||||
this.#system = system;
|
||||
}
|
||||
|
||||
#system;
|
||||
#events;
|
||||
|
||||
initial({events}) {
|
||||
@@ -24,18 +24,18 @@ class Event {
|
||||
return Object.keys(this.#events).length;
|
||||
}
|
||||
|
||||
check(eventId, property) {
|
||||
check(eventId) {
|
||||
const { include, exclude, NoRandom } = this.get(eventId);
|
||||
if(NoRandom) return false;
|
||||
if(exclude && checkCondition(property, exclude)) return false;
|
||||
if(include) return checkCondition(property, include);
|
||||
if(exclude && this.#system.check(exclude)) return false;
|
||||
if(include) return this.#system.check(include);
|
||||
return true;
|
||||
}
|
||||
|
||||
get(eventId) {
|
||||
const event = this.#events[eventId];
|
||||
if(!event) throw new Error(`[ERROR] No Event[${eventId}]`);
|
||||
return clone(event);
|
||||
return this.#system.clone(event);
|
||||
}
|
||||
|
||||
information(eventId) {
|
||||
@@ -43,11 +43,11 @@ class Event {
|
||||
return { description };
|
||||
}
|
||||
|
||||
do(eventId, property) {
|
||||
do(eventId) {
|
||||
const { effect, branch, event: description, postEvent, grade } = this.get(eventId);
|
||||
if(branch)
|
||||
for(const [cond, next] of branch)
|
||||
if(checkCondition(property, cond))
|
||||
if(this.#system.check(cond))
|
||||
return { effect, next, description, grade };
|
||||
return { effect, postEvent, description, grade };
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { clone, weightRandom, getListValuesMap, getConvertedMap } from '../functions/util.js'
|
||||
import * as util from '../functions/util.js';
|
||||
import * as fCondition from '../functions/condition.js';
|
||||
|
||||
import Property from './property.js';
|
||||
import Event from './event.js';
|
||||
import Talent from './talent.js';
|
||||
@@ -7,11 +9,24 @@ import Character from './character.js';
|
||||
|
||||
class Life {
|
||||
constructor() {
|
||||
this.#property = new Property();
|
||||
this.#event = new Event();
|
||||
this.#talent = new Talent();
|
||||
this.#achievement = new Achievement();
|
||||
this.#character = new Character();
|
||||
this.#property = new Property(this);
|
||||
this.#event = new Event(this);
|
||||
this.#talent = new Talent(this);
|
||||
this.#achievement = new Achievement(this);
|
||||
this.#character = new Character(this);
|
||||
}
|
||||
|
||||
Module = {
|
||||
PROPERTY: 'PROPERTY',
|
||||
TALENT: 'TALENT',
|
||||
EVENT: 'EVENT',
|
||||
ACHIEVEMENT: 'ACHIEVEMENT',
|
||||
CHARACTER: 'CHARACTER',
|
||||
}
|
||||
|
||||
Function = {
|
||||
CONDITION: 'CONDITION',
|
||||
UTIL: 'UTIL',
|
||||
}
|
||||
|
||||
#property;
|
||||
@@ -65,24 +80,47 @@ class Life {
|
||||
this.#character.config(characterConfig);
|
||||
}
|
||||
|
||||
request(module) {
|
||||
switch (module) {
|
||||
case this.Module.ACHIEVEMENT: return this.#achievement;
|
||||
case this.Module.CHARACTER: return this.#character;
|
||||
case this.Module.EVENT: return this.#event;
|
||||
case this.Module.PROPERTY: return this.#property;
|
||||
case this.Module.TALENT: return this.#talent;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
function(type) {
|
||||
switch (type) {
|
||||
case this.Function.CONDITION: return fCondition;
|
||||
case this.Function.UTIL: return util;
|
||||
}
|
||||
}
|
||||
|
||||
check(condition) {
|
||||
return fCondition.checkCondition(this.#property,condition);
|
||||
}
|
||||
|
||||
clone(...args) {
|
||||
return util.clone(...args);
|
||||
}
|
||||
|
||||
remake(talents) {
|
||||
this.#initialData = clone(this.#defaultPropertys);
|
||||
this.#initialData.TLT = clone(talents);
|
||||
this.#initialData = util.clone(this.#defaultPropertys);
|
||||
this.#initialData.TLT = util.clone(talents);
|
||||
this.#triggerTalents = {};
|
||||
return this.talentReplace(this.#initialData.TLT);
|
||||
}
|
||||
|
||||
start(allocation) {
|
||||
for(const key in allocation) {
|
||||
this.#initialData[key] = clone(allocation[key]);
|
||||
this.#initialData[key] = util.clone(allocation[key]);
|
||||
}
|
||||
this.#property.restart(this.#initialData);
|
||||
this.doTalent()
|
||||
this.#property.restartLastStep();
|
||||
this.#achievement.achieve(
|
||||
this.AchievementOpportunity.START,
|
||||
this.#property
|
||||
);
|
||||
this.#achievement.achieve(this.AchievementOpportunity.START);
|
||||
}
|
||||
|
||||
getPropertyPoints() {
|
||||
@@ -102,10 +140,7 @@ class Life {
|
||||
const isEnd = this.#property.isEnd();
|
||||
|
||||
const content = [talentContent, eventContent].flat();
|
||||
this.#achievement.achieve(
|
||||
this.AchievementOpportunity.TRAJECTORY,
|
||||
this.#property
|
||||
)
|
||||
this.#achievement.achieve(this.AchievementOpportunity.TRAJECTORY);
|
||||
return { age, content, isEnd };
|
||||
}
|
||||
|
||||
@@ -131,7 +166,7 @@ class Life {
|
||||
|
||||
const contents = [];
|
||||
for(const talentId of talents) {
|
||||
const result = this.#talent.do(talentId, this.#property);
|
||||
const result = this.#talent.do(talentId);
|
||||
if(!result) continue;
|
||||
this.#triggerTalents[talentId] = this.getTalentCurrentTriggerCount(talentId) + 1;
|
||||
const { effect, name, description, grade } = result;
|
||||
@@ -148,7 +183,7 @@ class Life {
|
||||
}
|
||||
|
||||
doEvent(eventId) {
|
||||
const { effect, next, description, postEvent, grade } = this.#event.do(eventId, this.#property);
|
||||
const { effect, next, description, postEvent, grade } = this.#event.do(eventId);
|
||||
this.#property.change(this.PropertyTypes.EVT, eventId);
|
||||
this.#property.effect(effect);
|
||||
const content = {
|
||||
@@ -162,7 +197,7 @@ class Life {
|
||||
}
|
||||
|
||||
random(events) {
|
||||
return weightRandom(
|
||||
return util.weightRandom(
|
||||
events.filter(
|
||||
([eventId])=>this.#event.check(eventId, this.#property)
|
||||
)
|
||||
@@ -181,11 +216,12 @@ class Life {
|
||||
|
||||
characterRandom() {
|
||||
const characters = this.#character.random();
|
||||
characters.forEach(
|
||||
v=>v.talent=v.talent.map(
|
||||
id=>this.#talent.get(id)
|
||||
)
|
||||
const replaceTalent = v=>v.talent=v.talent.map(
|
||||
id=>this.#talent.get(id)
|
||||
);
|
||||
characters.normal.forEach(replaceTalent);
|
||||
if(characters.unique && characters.unique.talent)
|
||||
replaceTalent(characters.unique);
|
||||
return characters;
|
||||
}
|
||||
|
||||
@@ -197,12 +233,16 @@ class Life {
|
||||
return this.#talent.exclude(talents, exclusive);
|
||||
}
|
||||
|
||||
generateUnique() {
|
||||
this.#character.generateUnique();
|
||||
}
|
||||
|
||||
#getJudges(...types) {
|
||||
return getListValuesMap(types.flat(), key => this.#property.judge(key));
|
||||
return util.getListValuesMap(types.flat(), key => this.#property.judge(key));
|
||||
}
|
||||
|
||||
#getPropertys(...types) {
|
||||
return getListValuesMap(types.flat(), key => this.#property.get(key));
|
||||
return util.getListValuesMap(types.flat(), key => this.#property.get(key));
|
||||
}
|
||||
|
||||
get lastExtendTalent() {
|
||||
@@ -210,10 +250,7 @@ class Life {
|
||||
}
|
||||
|
||||
get summary() {
|
||||
this.#achievement.achieve(
|
||||
this.AchievementOpportunity.SUMMARY,
|
||||
this.#property
|
||||
)
|
||||
this.#achievement.achieve(this.AchievementOpportunity.SUMMARY);
|
||||
|
||||
const pt = this.PropertyTypes;
|
||||
|
||||
@@ -259,16 +296,13 @@ class Life {
|
||||
get PropertyTypes() { return this.#property.TYPES; }
|
||||
get AchievementOpportunity() { return this.#achievement.Opportunity; }
|
||||
get talentSelectLimit() { return this.#talentSelectLimit; }
|
||||
get propertyAllocateLimit() { return clone(this.#propertyAllocateLimit); }
|
||||
get propertyAllocateLimit() { return util.clone(this.#propertyAllocateLimit); }
|
||||
|
||||
get propertys() { return this.#property.getPropertys(); }
|
||||
get times() { return this.#property.get(this.PropertyTypes.TMS) || 0; }
|
||||
set times(v) {
|
||||
this.#property.set(this.PropertyTypes.TMS, v);
|
||||
this.#achievement.achieve(
|
||||
this.AchievementOpportunity.END,
|
||||
this.#property
|
||||
)
|
||||
this.#achievement.achieve(this.AchievementOpportunity.END);
|
||||
}
|
||||
get specialThanks() { return this.#specialThanks; }
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { max, min, sum, clone, listRandom } from '../functions/util.js';
|
||||
|
||||
class Property {
|
||||
constructor() {}
|
||||
constructor(system) {
|
||||
this.#system = system;
|
||||
}
|
||||
|
||||
TYPES = {
|
||||
// 本局
|
||||
@@ -70,11 +70,16 @@ class Property {
|
||||
]
|
||||
}
|
||||
|
||||
#system;
|
||||
#ageData;
|
||||
#data = {};
|
||||
#total;
|
||||
#judge;
|
||||
|
||||
get #util() {
|
||||
return this.#system.function(this.#system.Function.UTIL);
|
||||
}
|
||||
|
||||
initial({age, total}) {
|
||||
this.#ageData = age;
|
||||
for(const a in age) {
|
||||
@@ -151,6 +156,7 @@ class Property {
|
||||
}
|
||||
|
||||
get(prop) {
|
||||
const util = this.#util;
|
||||
switch(prop) {
|
||||
case this.TYPES.AGE:
|
||||
case this.TYPES.CHR:
|
||||
@@ -161,14 +167,14 @@ class Property {
|
||||
case this.TYPES.LIF:
|
||||
case this.TYPES.TLT:
|
||||
case this.TYPES.EVT:
|
||||
return clone(this.#data[prop]);
|
||||
return util.clone(this.#data[prop]);
|
||||
case this.TYPES.LAGE:
|
||||
case this.TYPES.LCHR:
|
||||
case this.TYPES.LINT:
|
||||
case this.TYPES.LSTR:
|
||||
case this.TYPES.LMNY:
|
||||
case this.TYPES.LSPR:
|
||||
return min(
|
||||
return util.min(
|
||||
this.#data[prop],
|
||||
this.get(this.fallback(prop))
|
||||
);
|
||||
@@ -178,7 +184,7 @@ class Property {
|
||||
case this.TYPES.HSTR:
|
||||
case this.TYPES.HMNY:
|
||||
case this.TYPES.HSPR:
|
||||
return max(
|
||||
return util.max(
|
||||
this.#data[prop],
|
||||
this.get(this.fallback(prop))
|
||||
);
|
||||
@@ -189,7 +195,7 @@ class Property {
|
||||
const HSTR = this.get(this.TYPES.HSTR);
|
||||
const HMNY = this.get(this.TYPES.HMNY);
|
||||
const HSPR = this.get(this.TYPES.HSPR);
|
||||
return Math.floor(sum(HCHR, HINT, HSTR, HMNY, HSPR)*2 + HAGE/2);
|
||||
return Math.floor(util.sum(HCHR, HINT, HSTR, HMNY, HSPR)*2 + HAGE/2);
|
||||
case this.TYPES.TMS:
|
||||
return this.lsget('times') || 0;
|
||||
case this.TYPES.EXT:
|
||||
@@ -253,7 +259,7 @@ class Property {
|
||||
case this.TYPES.LIF:
|
||||
case this.TYPES.TLT:
|
||||
case this.TYPES.EVT:
|
||||
this.hl(prop, this.#data[prop] = clone(value));
|
||||
this.hl(prop, this.#data[prop] = this.#system.clone(value));
|
||||
this.achieve(prop, value);
|
||||
return;
|
||||
case this.TYPES.TMS:
|
||||
@@ -267,7 +273,7 @@ class Property {
|
||||
}
|
||||
|
||||
getPropertys() {
|
||||
return clone({
|
||||
return this.#system.clone({
|
||||
[this.TYPES.AGE]: this.get(this.TYPES.AGE),
|
||||
[this.TYPES.CHR]: this.get(this.TYPES.CHR),
|
||||
[this.TYPES.INT]: this.get(this.TYPES.INT),
|
||||
@@ -315,7 +321,8 @@ class Property {
|
||||
|
||||
hookSpecial(prop) {
|
||||
switch(prop) {
|
||||
case this.TYPES.RDM: return listRandom(this.SPECIAL.RDM);
|
||||
case this.TYPES.RDM:
|
||||
return this.#util.listRandom(this.SPECIAL.RDM);
|
||||
default: return prop;
|
||||
}
|
||||
}
|
||||
@@ -334,15 +341,6 @@ class Property {
|
||||
const d = this.#judge[prop];
|
||||
let length = d.length;
|
||||
|
||||
// progress judge
|
||||
// const p = 1/length;
|
||||
// const progress = () => {
|
||||
// const min = d[length][0] || 0;
|
||||
// const max = d[length+1]?.[0] || value;
|
||||
// if(max == min) return 1;
|
||||
// return p * (length + (value - min) / (max - min));
|
||||
// }
|
||||
|
||||
const progress = () => Math.max(Math.min(value, 10), 0) / 10;
|
||||
|
||||
while(length--) {
|
||||
@@ -363,7 +361,7 @@ class Property {
|
||||
}
|
||||
|
||||
getAgeData(age) {
|
||||
return clone(this.#ageData[age]);
|
||||
return this.#system.clone(this.#ageData[age]);
|
||||
}
|
||||
|
||||
hl(prop, value) {
|
||||
@@ -378,8 +376,8 @@ class Property {
|
||||
default: return;
|
||||
}
|
||||
const [l, h] = keys;
|
||||
this.#data[l] = min(this.#data[l], value);
|
||||
this.#data[h] = max(this.#data[h], value);
|
||||
this.#data[l] = this.#util.min(this.#data[l], value);
|
||||
this.#data[h] = this.#util.max(this.#data[h], value);
|
||||
}
|
||||
|
||||
achieve(prop, newData) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { clone, weightRandom } from '../functions/util.js';
|
||||
import { checkCondition, extractMaxTriggers } from '../functions/condition.js';
|
||||
|
||||
class Talent {
|
||||
constructor() {}
|
||||
constructor(system) {
|
||||
this.#system = system;
|
||||
}
|
||||
|
||||
#system;
|
||||
#talents;
|
||||
#talentPullCount;
|
||||
#talentRate;
|
||||
@@ -11,11 +11,12 @@ class Talent {
|
||||
|
||||
initial({talents}) {
|
||||
this.#talents = talents;
|
||||
const emt = this.#system.function(this.#system.Function.CONDITION).extractMaxTriggers;
|
||||
for(const id in talents) {
|
||||
const talent = talents[id];
|
||||
talent.id= Number(id);
|
||||
talent.grade = Number(talent.grade);
|
||||
talent.max_triggers = extractMaxTriggers(talent.condition);
|
||||
talent.max_triggers = emt(talent.condition);
|
||||
if(talent.replacement) {
|
||||
for(let key in talent.replacement) {
|
||||
const obj = {};
|
||||
@@ -34,6 +35,10 @@ class Talent {
|
||||
return Object.keys(this.#talents).length;
|
||||
}
|
||||
|
||||
get #prop() {
|
||||
return this.#system.request(this.#system.Module.PROPERTY);
|
||||
}
|
||||
|
||||
config({
|
||||
talentPullCount = 10, // number of talents to pull from the talent pool
|
||||
talentRate = { 1:100, 2:10, 3:1, total: 1000 }, // rate of talent pull
|
||||
@@ -45,15 +50,15 @@ class Talent {
|
||||
}
|
||||
|
||||
|
||||
check(talentId, property) {
|
||||
check(talentId) {
|
||||
const { condition } = this.get(talentId);
|
||||
return checkCondition(property, condition);
|
||||
return this.#system.check(this.#prop, condition);
|
||||
}
|
||||
|
||||
get(talentId) {
|
||||
const talent = this.#talents[talentId];
|
||||
if(!talent) throw new Error(`[ERROR] No Talent[${talentId}]`);
|
||||
return clone(talent);
|
||||
return this.#system.clone(talent);
|
||||
}
|
||||
|
||||
information(talentId) {
|
||||
@@ -81,7 +86,7 @@ class Talent {
|
||||
}
|
||||
|
||||
getRate(additionValues = {}) {
|
||||
const rate = clone(this.#talentRate);
|
||||
const rate = this.#system.clone(this.#talentRate);
|
||||
const addition = { 1:1, 2:1, 3:1, };
|
||||
|
||||
Object.keys(additionValues).forEach(key => {
|
||||
@@ -131,6 +136,19 @@ class Talent {
|
||||
});
|
||||
}
|
||||
|
||||
random(count) {
|
||||
const talents = Object
|
||||
.keys(this.#talents)
|
||||
.filter(id=>!this.#talents[id].exclusive);
|
||||
return new Array(count)
|
||||
.fill(1)
|
||||
.map(()=>talents.splice(
|
||||
Math.floor(Math.random()*talents.length)%talents.length,
|
||||
1
|
||||
)[0]
|
||||
);
|
||||
}
|
||||
|
||||
allocationAddition(talents) {
|
||||
if(Array.isArray(talents)) {
|
||||
let addition = 0;
|
||||
@@ -141,9 +159,9 @@ class Talent {
|
||||
return Number(this.get(talents).status) || 0;
|
||||
}
|
||||
|
||||
do(talentId, property) {
|
||||
do(talentId) {
|
||||
const { effect, condition, grade, name, description } = this.get(talentId);
|
||||
if(condition && !checkCondition(property, condition))
|
||||
if(condition && !this.#system.check(condition))
|
||||
return null;
|
||||
return { effect, grade, name, description };
|
||||
}
|
||||
@@ -154,7 +172,8 @@ class Talent {
|
||||
if(!replacement) return null;
|
||||
const list = [];
|
||||
if(replacement.grade) {
|
||||
this.forEach(({id, grade})=>{
|
||||
this.forEach(({id, grade, exclusive})=>{
|
||||
if(exclusive) return;
|
||||
if(!replacement.grade[grade]) return;
|
||||
if(this.exclude(talents, id)) return;
|
||||
list.push([id, replacement.grade[grade]]);
|
||||
@@ -170,16 +189,17 @@ class Talent {
|
||||
return list;
|
||||
}
|
||||
|
||||
const wr = this.#system.function(this.#system.Function.UTIL).weightRandom;
|
||||
const replace = (talent, talents) => {
|
||||
const replaceList = getReplaceList(talent, talents);
|
||||
if(!replaceList) return talent;
|
||||
const rand = weightRandom(replaceList);
|
||||
const rand = wr(replaceList);
|
||||
return replace(
|
||||
rand, talents.concat(rand)
|
||||
);
|
||||
}
|
||||
|
||||
const newTalents = clone(talents);
|
||||
const newTalents = this.#system.clone(talents);
|
||||
const result = {};
|
||||
for(const talent of talents) {
|
||||
const replaceId = replace(talent, newTalents);
|
||||
@@ -194,7 +214,7 @@ class Talent {
|
||||
forEach(callback) {
|
||||
if(typeof callback != 'function') return;
|
||||
for(const id in this.#talents)
|
||||
callback(clone(this.#talents[id]), id);
|
||||
callback(this.#system.clone(this.#talents[id]), id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,14 +1,13 @@
|
||||
export default class CyberCelebrity extends ui.view.CyberTheme.CelebrityUI {
|
||||
constructor() {
|
||||
super();
|
||||
this.btnRetry.on(Laya.Event.CLICK, this, this.random);
|
||||
this.btnRetry.on(Laya.Event.CLICK, this, ()=>this.random());
|
||||
this.btnNext.on(Laya.Event.CLICK, this, this.next);
|
||||
this.panelCharacter.vScrollBar.elasticDistance = 150;
|
||||
}
|
||||
|
||||
#characters;
|
||||
#selected;
|
||||
static #createComponent = Laya.plugin.extractComponents(CyberCelebrity.uiView, ['boxCharacter','boxTalent']);
|
||||
static #createComponent = Laya.plugin.extractComponents(CyberCelebrity.uiView, ['boxCharacter','boxTalent','boxUniqueUnGenerate']);
|
||||
#createCharacterItem(dataSource, click) {
|
||||
const {name, property, talent} = dataSource;
|
||||
const item = CyberCelebrity.#createComponent('boxCharacter');
|
||||
@@ -45,6 +44,30 @@ export default class CyberCelebrity extends ui.view.CyberTheme.CelebrityUI {
|
||||
if(click) item.click(click);
|
||||
return item;
|
||||
}
|
||||
#createUniqueUnGenerateItem(generate) {
|
||||
const item = CyberCelebrity.#createComponent('boxUniqueUnGenerate');
|
||||
const boxName = item.getChildByName('boxName');
|
||||
const vboxStates = item.getChildByName('vboxStates');
|
||||
const label = vboxStates.getChildByName('label');
|
||||
const boxBtn = vboxStates.getChildByName('boxBtn');
|
||||
const btn = boxBtn.getChildByName('btn');
|
||||
|
||||
label.event(Laya.Event.RESIZE);
|
||||
vboxStates.scaleY = 0;
|
||||
item.dataSource = false;
|
||||
item.switch = showDetails => vboxStates.scaleY = !!showDetails?1:0;
|
||||
item.click = (cb, caller) => {
|
||||
boxName.offAll(Laya.Event.CLICK);
|
||||
boxName.on(Laya.Event.CLICK, caller || this, cb);
|
||||
}
|
||||
item.generate = (cb, caller) => {
|
||||
btn.offAll(Laya.Event.CLICK);
|
||||
btn.on(Laya.Event.CLICK, caller || this, cb);
|
||||
}
|
||||
if(generate) item.generate(generate);
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
init() {
|
||||
this.random();
|
||||
@@ -55,27 +78,47 @@ export default class CyberCelebrity extends ui.view.CyberTheme.CelebrityUI {
|
||||
this.vboxCharacter.destroyChildren(true);
|
||||
}
|
||||
|
||||
random() {
|
||||
random(g) {
|
||||
this.#selected = null;
|
||||
this.vboxCharacter.destroyChildren(true);
|
||||
this.#characters = core.characterRandom();
|
||||
this.#characters.forEach(character => {
|
||||
const item = this.#createCharacterItem(character);
|
||||
const {unique, normal} = core.characterRandom();
|
||||
const items = [];
|
||||
const uniqueItem = this.generateUnique(unique, ()=>{
|
||||
core.generateUnique();
|
||||
this.random(normal);
|
||||
|
||||
});
|
||||
if(uniqueItem) items.push(uniqueItem);
|
||||
(g||normal).forEach(character => items.push(this.#createCharacterItem(character)));
|
||||
|
||||
items.forEach((item, i) => {
|
||||
item.y = i;
|
||||
this.vboxCharacter.addChild(item);
|
||||
item.click(()=>{
|
||||
if(this.#selected) this.#selected.switch(false);
|
||||
this.#selected = item;
|
||||
item.switch(true);
|
||||
item.event(Laya.Event.RESIZE);
|
||||
});
|
||||
})
|
||||
});
|
||||
if(g&&uniqueItem) {
|
||||
this.#selected = uniqueItem;
|
||||
uniqueItem.switch(true);
|
||||
uniqueItem.event(Laya.Event.RESIZE);
|
||||
}
|
||||
}
|
||||
|
||||
generateUnique(data, generate) {
|
||||
if(!data) return null;
|
||||
if(!data.generate) return this.#createUniqueUnGenerateItem(generate);
|
||||
data.name = $lang.UI_UniqueWaTaShi;
|
||||
return this.#createCharacterItem(data);
|
||||
}
|
||||
|
||||
next() {
|
||||
if(!this.#selected) {
|
||||
$$event('message', ['M_PleaseSelectOne']);
|
||||
return;
|
||||
}
|
||||
if(!this.#selected) return $$event('message', ['M_PleaseSelectOne']);
|
||||
if(!this.#selected.dataSource) return $$event('message', ['M_UnGenerate']);
|
||||
|
||||
const {property: propertyAllocate, talent: talents} = this.#selected.dataSource;
|
||||
const replace = core.remake(talents.map(talent => talent.id));
|
||||
if(replace.length > 0) {
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
export default class Celebrity extends ui.view.DefaultTheme.CelebrityUI {
|
||||
constructor() {
|
||||
super();
|
||||
this.btnRetry.on(Laya.Event.CLICK, this, this.random);
|
||||
this.btnRetry.on(Laya.Event.CLICK, this, ()=>this.random());
|
||||
this.btnNext.on(Laya.Event.CLICK, this, this.next);
|
||||
this.panelCharacter.vScrollBar.elasticDistance = 150;
|
||||
}
|
||||
|
||||
#characters;
|
||||
#selected;
|
||||
static #createComponent = Laya.plugin.extractComponents(Celebrity.uiView, ['boxCharacter','boxTalent']);
|
||||
static #createComponent = Laya.plugin.extractComponents(Celebrity.uiView, ['boxCharacter','boxTalent','boxUniqueUnGenerate']);
|
||||
#createCharacterItem(dataSource, click) {
|
||||
const {name, property, talent} = dataSource;
|
||||
const style = $ui.common.characterItem;
|
||||
@@ -47,6 +46,35 @@ export default class Celebrity extends ui.view.DefaultTheme.CelebrityUI {
|
||||
if(click) item.click(click);
|
||||
return item;
|
||||
}
|
||||
#createUniqueUnGenerateItem(generate) {
|
||||
const style = $ui.common.characterItem;
|
||||
const item = Celebrity.#createComponent('boxUniqueUnGenerate');
|
||||
const boxName = item.getChildByName('boxName');
|
||||
const vboxStates = item.getChildByName('vboxStates');
|
||||
const label = vboxStates.getChildByName('label');
|
||||
const boxBtn = vboxStates.getChildByName('boxBtn');
|
||||
const btn = boxBtn.getChildByName('btn');
|
||||
|
||||
$_.deepMapSet(boxName, style.name);
|
||||
$_.deepMapSet(vboxStates, style.state);
|
||||
$_.deepMapSet(btn, style.name);
|
||||
|
||||
boxBtn.y = label.height + vboxStates.space;
|
||||
label.event(Laya.Event.RESIZE);
|
||||
vboxStates.scaleY = 0;
|
||||
item.dataSource = false;
|
||||
item.switch = showDetails => vboxStates.scaleY = !!showDetails?1:0;
|
||||
item.click = (cb, caller) => {
|
||||
boxName.offAll(Laya.Event.CLICK);
|
||||
boxName.on(Laya.Event.CLICK, caller || this, cb);
|
||||
}
|
||||
item.generate = (cb, caller) => {
|
||||
btn.offAll(Laya.Event.CLICK);
|
||||
btn.on(Laya.Event.CLICK, caller || this, cb);
|
||||
}
|
||||
if(generate) item.generate(generate);
|
||||
return item;
|
||||
}
|
||||
|
||||
init() {
|
||||
this.random();
|
||||
@@ -57,27 +85,47 @@ export default class Celebrity extends ui.view.DefaultTheme.CelebrityUI {
|
||||
this.vboxCharacter.destroyChildren(true);
|
||||
}
|
||||
|
||||
random() {
|
||||
random(g) {
|
||||
this.#selected = null;
|
||||
this.vboxCharacter.destroyChildren(true);
|
||||
this.#characters = core.characterRandom();
|
||||
this.#characters.forEach(character => {
|
||||
const item = this.#createCharacterItem(character);
|
||||
const {unique, normal} = core.characterRandom();
|
||||
const items = [];
|
||||
const uniqueItem = this.generateUnique(unique, ()=>{
|
||||
core.generateUnique();
|
||||
this.random(normal);
|
||||
|
||||
});
|
||||
if(uniqueItem) items.push(uniqueItem);
|
||||
(g||normal).forEach(character => items.push(this.#createCharacterItem(character)));
|
||||
|
||||
items.forEach((item, i) => {
|
||||
item.y = i;
|
||||
this.vboxCharacter.addChild(item);
|
||||
item.click(()=>{
|
||||
if(this.#selected) this.#selected.switch(false);
|
||||
this.#selected = item;
|
||||
item.switch(true);
|
||||
item.event(Laya.Event.RESIZE);
|
||||
});
|
||||
})
|
||||
});
|
||||
if(g&&uniqueItem) {
|
||||
this.#selected = uniqueItem;
|
||||
uniqueItem.switch(true);
|
||||
uniqueItem.event(Laya.Event.RESIZE);
|
||||
}
|
||||
}
|
||||
|
||||
generateUnique(data, generate) {
|
||||
if(!data) return null;
|
||||
if(!data.generate) return this.#createUniqueUnGenerateItem(generate);
|
||||
data.name = $lang.UI_UniqueWaTaShi;
|
||||
return this.#createCharacterItem(data);
|
||||
}
|
||||
|
||||
next() {
|
||||
if(!this.#selected) {
|
||||
$$event('message', ['M_PleaseSelectOne']);
|
||||
return;
|
||||
}
|
||||
if(!this.#selected) return $$event('message', ['M_PleaseSelectOne']);
|
||||
if(!this.#selected.dataSource) return $$event('message', ['M_UnGenerate']);
|
||||
|
||||
const {property: propertyAllocate, talent: talents} = this.#selected.dataSource;
|
||||
const replace = core.remake(talents.map(talent => talent.id));
|
||||
if(replace.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user