mirror of
https://github.com/VickScarlet/lifeRestart.git
synced 2025-07-21 19:43:58 +08:00
251 lines
7.9 KiB
JavaScript
251 lines
7.9 KiB
JavaScript
import { clone, weightRandom } from '../functions/util.js'
|
|
import Property from './property.js';
|
|
import Event from './event.js';
|
|
import Talent from './talent.js';
|
|
import Achievement from './achievement.js';
|
|
|
|
class Life {
|
|
constructor() {
|
|
this.#property = new Property();
|
|
this.#event = new Event();
|
|
this.#talent = new Talent();
|
|
this.#achievement = new Achievement();
|
|
}
|
|
|
|
#property;
|
|
#event;
|
|
#talent;
|
|
#achievement;
|
|
#triggerTalents;
|
|
#defaultPropertyPoints;
|
|
#talentSelectLimit;
|
|
#propertyAllocateLimit;
|
|
#defaultPropertys;
|
|
|
|
async initial(loadJSON) {
|
|
const [age, talents, events, achievements] = await Promise.all([
|
|
loadJSON('age'),
|
|
loadJSON('talents'),
|
|
loadJSON('events'),
|
|
loadJSON('achievement'),
|
|
]);
|
|
this.#property.initial({age});
|
|
this.#talent.initial({talents});
|
|
this.#event.initial({events});
|
|
this.#achievement.initial({achievements});
|
|
}
|
|
|
|
config({
|
|
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 = {}, // default propertys
|
|
talentConfig, // config for talent
|
|
} = {}) {
|
|
this.#defaultPropertyPoints = defaultPropertyPoints;
|
|
this.#talentSelectLimit = talentSelectLimit;
|
|
this.#propertyAllocateLimit = propertyAllocateLimit;
|
|
this.#defaultPropertys = defaultPropertys;
|
|
this.#talent.config(talentConfig);
|
|
}
|
|
|
|
restart(allocation) {
|
|
const propertys = clone(this.#defaultPropertys);
|
|
for(const key in allocation) {
|
|
propertys[key] = clone(allocation[key]);
|
|
}
|
|
this.#triggerTalents = {};
|
|
const contents = this.talentReplace(propertys.TLT);
|
|
this.#property.restart(propertys);
|
|
this.doTalent()
|
|
this.#property.restartLastStep();
|
|
this.#achievement.achieve(
|
|
this.#achievement.Opportunity.START,
|
|
this.#property
|
|
)
|
|
return contents;
|
|
}
|
|
|
|
getPropertyPoints(selectedTalentIds) {
|
|
return this.#defaultPropertyPoints + this.#talent.allocationAddition(selectedTalentIds);
|
|
}
|
|
|
|
getTalentCurrentTriggerCount(talentId) {
|
|
return this.#triggerTalents[talentId] || 0;
|
|
}
|
|
|
|
next() {
|
|
const {age, event, talent} = this.#property.ageNext();
|
|
|
|
const talentContent = this.doTalent(talent);
|
|
const eventContent = this.doEvent(this.random(event));
|
|
|
|
const isEnd = this.#property.isEnd();
|
|
|
|
const content = [talentContent, eventContent].flat();
|
|
this.#achievement.achieve(
|
|
this.#achievement.Opportunity.TRAJECTORY,
|
|
this.#property
|
|
)
|
|
return { age, content, isEnd };
|
|
}
|
|
|
|
talentReplace(talents) {
|
|
const result = this.#talent.replace(talents);
|
|
const contents = [];
|
|
for(const id in result) {
|
|
talents.push(result[id]);
|
|
const source = this.#talent.get(id);
|
|
const target = this.#talent.get(result[id]);
|
|
contents.push({
|
|
type: 'talentReplace',
|
|
source, target
|
|
});
|
|
}
|
|
return contents;
|
|
}
|
|
|
|
doTalent(talents) {
|
|
if(talents) this.#property.change(this.#property.TYPES.TLT, talents);
|
|
talents = this.#property.get(this.#property.TYPES.TLT)
|
|
.filter(talentId => this.getTalentCurrentTriggerCount(talentId) < this.#talent.get(talentId).max_triggers);
|
|
|
|
const contents = [];
|
|
for(const talentId of talents) {
|
|
const result = this.#talent.do(talentId, this.#property);
|
|
if(!result) continue;
|
|
this.#triggerTalents[talentId] = this.getTalentCurrentTriggerCount(talentId) + 1;
|
|
const { effect, name, description, grade } = result;
|
|
contents.push({
|
|
type: this.#property.TYPES.TLT,
|
|
name,
|
|
grade,
|
|
description,
|
|
})
|
|
if(!effect) continue;
|
|
this.#property.effect(effect);
|
|
}
|
|
return contents;
|
|
}
|
|
|
|
doEvent(eventId) {
|
|
const { effect, next, description, postEvent } = this.#event.do(eventId, this.#property);
|
|
this.#property.change(this.#property.TYPES.EVT, eventId);
|
|
this.#property.effect(effect);
|
|
const content = {
|
|
type: this.#property.TYPES.EVT,
|
|
description,
|
|
postEvent,
|
|
}
|
|
if(next) return [content, this.doEvent(next)].flat();
|
|
return [content];
|
|
}
|
|
|
|
random(events) {
|
|
return weightRandom(
|
|
events.filter(
|
|
([eventId])=>this.#event.check(eventId, this.#property)
|
|
)
|
|
);
|
|
}
|
|
|
|
talentRandom() {
|
|
const times = this.#property.get(this.#property.TYPES.TMS);
|
|
const achievement = this.#property.get(this.#property.TYPES.CACHV);
|
|
return this.#talent.talentRandom(this.getLastExtendTalent(), { times, achievement });
|
|
}
|
|
|
|
talentExtend(talentId) {
|
|
this.#property.set(this.#property.TYPES.EXT, talentId);
|
|
}
|
|
|
|
getLastExtendTalent() {
|
|
return this.#property.get(this.#property.TYPES.EXT);
|
|
}
|
|
|
|
getSummary() {
|
|
this.#achievement.achieve(
|
|
this.#achievement.Opportunity.SUMMARY,
|
|
this.#property
|
|
)
|
|
return {
|
|
AGE: this.#property.get(this.#property.TYPES.HAGE),
|
|
CHR: this.#property.get(this.#property.TYPES.HCHR),
|
|
INT: this.#property.get(this.#property.TYPES.HINT),
|
|
STR: this.#property.get(this.#property.TYPES.HSTR),
|
|
MNY: this.#property.get(this.#property.TYPES.HMNY),
|
|
SPR: this.#property.get(this.#property.TYPES.HSPR),
|
|
SUM: this.#property.get(this.#property.TYPES.SUM),
|
|
};
|
|
}
|
|
|
|
getLastRecord() {
|
|
return this.#property.getLastRecord();
|
|
}
|
|
|
|
exclusive(talents, exclusive) {
|
|
return this.#talent.exclusive(talents, exclusive);
|
|
}
|
|
|
|
getAchievements() {
|
|
const ticks = {};
|
|
this.#property
|
|
.get(this.#property.TYPES.ACHV)
|
|
.forEach(([id, tick]) => ticks[id] = tick);
|
|
return this
|
|
.#achievement
|
|
.list(this.#property)
|
|
.sort((
|
|
{id: a, grade: ag, hide: ah},
|
|
{id: b, grade: bg, hide: bh}
|
|
)=>{
|
|
a = ticks[a];
|
|
b = ticks[b];
|
|
if(a&&b) return b - a;
|
|
if(!a&&!b) {
|
|
if(ah&&bh) return bg - ag;
|
|
if(ah) return 1;
|
|
if(bh) return -1;
|
|
return bg - ag;
|
|
}
|
|
if(!a) return 1;
|
|
if(!b) return -1;
|
|
});
|
|
}
|
|
|
|
getTotal() {
|
|
const TMS = this.#property.get(this.#property.TYPES.TMS);
|
|
const CACHV = this.#property.get(this.#property.TYPES.CACHV);
|
|
const CTLT = this.#property.get(this.#property.TYPES.CTLT);
|
|
const CEVT = this.#property.get(this.#property.TYPES.CEVT);
|
|
|
|
const totalTalent = this.#talent.count();
|
|
const totalEvent = this.#event.count();
|
|
|
|
return {
|
|
times: TMS,
|
|
achievement: CACHV,
|
|
talentRate: CTLT / totalTalent,
|
|
eventRate: CEVT / totalEvent,
|
|
}
|
|
}
|
|
|
|
get PropertyTypes() { return clone(this.#property.TYPES); }
|
|
|
|
get talentSelectLimit() { return this.#talentSelectLimit; }
|
|
get propertyAllocateLimit() { return clone(this.#propertyAllocateLimit); }
|
|
|
|
get propertys() { return this.#property.getPropertys(); }
|
|
get times() { return this.#property?.get(this.#property.TYPES.TMS) || 0; }
|
|
set times(v) {
|
|
this.#property?.set(this.#property.TYPES.TMS, v) || 0;
|
|
this.#achievement.achieve(
|
|
this.#achievement.Opportunity.END,
|
|
this.#property
|
|
)
|
|
}
|
|
}
|
|
|
|
export default Life;
|
|
|