WIP: Feature Rewrite #87
18 changed files with 81 additions and 73 deletions
1
.eslintignore
Normal file
1
.eslintignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.eslintrc.cjs
|
|
@ -5,15 +5,22 @@ module.exports = {
|
||||||
env: {
|
env: {
|
||||||
node: true
|
node: true
|
||||||
},
|
},
|
||||||
extends: [
|
parser: '@typescript-eslint/parser',
|
||||||
"plugin:vue/vue3-essential",
|
plugins: ["@typescript-eslint"],
|
||||||
"@vue/eslint-config-typescript/recommended",
|
overrides: [
|
||||||
"@vue/eslint-config-prettier"
|
{
|
||||||
|
files: ['*.ts', '*.tsx'],
|
||||||
|
extends: [
|
||||||
|
"plugin:vue/vue3-essential",
|
||||||
|
"@vue/eslint-config-typescript/recommended",
|
||||||
|
"@vue/eslint-config-prettier"
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
project: "./tsconfig.json"
|
||||||
|
},
|
||||||
|
}
|
||||||
],
|
],
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 2020,
|
|
||||||
project: "tsconfig.json"
|
|
||||||
},
|
|
||||||
ignorePatterns: ["src/lib"],
|
ignorePatterns: ["src/lib"],
|
||||||
rules: {
|
rules: {
|
||||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||||
|
|
11
package.json
11
package.json
|
@ -43,13 +43,14 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ivanv/vue-collapse-transition": "^1.0.2",
|
"@ivanv/vue-collapse-transition": "^1.0.2",
|
||||||
"@rushstack/eslint-patch": "^1.1.0",
|
"@rushstack/eslint-patch": "^1.7.2",
|
||||||
"@types/lz-string": "^1.5.0",
|
"@types/lz-string": "^1.5.0",
|
||||||
"@vue/eslint-config-prettier": "^7.0.0",
|
"@typescript-eslint/parser": "^7.2.0",
|
||||||
"@vue/eslint-config-typescript": "^10.0.0",
|
"@vue/eslint-config-prettier": "^9.0.0",
|
||||||
"eslint": "^8.6.0",
|
"@vue/eslint-config-typescript": "^13.0.0",
|
||||||
|
"eslint": "^8.57.0",
|
||||||
"jsdom": "^24.0.0",
|
"jsdom": "^24.0.0",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^3.2.5",
|
||||||
"typescript": "^5.4.2",
|
"typescript": "^5.4.2",
|
||||||
"vitest": "^1.4.0",
|
"vitest": "^1.4.0",
|
||||||
"vue-tsc": "^2.0.6"
|
"vue-tsc": "^2.0.6"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
"title": "Profectus",
|
"title": "Profectus",
|
||||||
"description": "A project made in Profectus",
|
"description": "A project made in Profectus",
|
||||||
"id": "",
|
"id": "321",
|
||||||
"author": "",
|
"author": "",
|
||||||
"discordName": "",
|
"discordName": "",
|
||||||
"discordLink": "",
|
"discordLink": "",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { computed } from "@vue/reactivity";
|
import { computed } from "vue";
|
||||||
import { isArray } from "@vue/shared";
|
|
||||||
import Select from "components/fields/Select.vue";
|
import Select from "components/fields/Select.vue";
|
||||||
import AchievementComponent from "features/achievements/Achievement.vue";
|
import AchievementComponent from "features/achievements/Achievement.vue";
|
||||||
import { GenericDecorator } from "features/decorators/common";
|
import { GenericDecorator } from "features/decorators/common";
|
||||||
|
@ -275,7 +274,7 @@ export function createAchievement<T extends AchievementOptions>(
|
||||||
const requirements = [
|
const requirements = [
|
||||||
createVisibilityRequirement(genericAchievement),
|
createVisibilityRequirement(genericAchievement),
|
||||||
createBooleanRequirement(() => !genericAchievement.earned.value),
|
createBooleanRequirement(() => !genericAchievement.earned.value),
|
||||||
...(isArray(achievement.requirements)
|
...(Array.isArray(achievement.requirements)
|
||||||
? achievement.requirements
|
? achievement.requirements
|
||||||
: [achievement.requirements])
|
: [achievement.requirements])
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { isArray } from "@vue/shared";
|
|
||||||
import ClickableComponent from "features/clickables/Clickable.vue";
|
import ClickableComponent from "features/clickables/Clickable.vue";
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
|
@ -157,7 +156,7 @@ export function createAction<T extends ActionOptions>(
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
const originalStyle = unref(style);
|
const originalStyle = unref(style);
|
||||||
if (isArray(originalStyle)) {
|
if (Array.isArray(originalStyle)) {
|
||||||
currStyle.push(...originalStyle);
|
currStyle.push(...originalStyle);
|
||||||
} else if (originalStyle != null) {
|
} else if (originalStyle != null) {
|
||||||
currStyle.push(originalStyle);
|
currStyle.push(originalStyle);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { isArray } from "@vue/shared";
|
|
||||||
import Toggle from "components/fields/Toggle.vue";
|
import Toggle from "components/fields/Toggle.vue";
|
||||||
import ChallengeComponent from "features/challenges/Challenge.vue";
|
import ChallengeComponent from "features/challenges/Challenge.vue";
|
||||||
import { GenericDecorator } from "features/decorators/common";
|
import { GenericDecorator } from "features/decorators/common";
|
||||||
|
@ -348,7 +347,7 @@ export function createActiveChallenge(
|
||||||
export function isAnyChallengeActive(
|
export function isAnyChallengeActive(
|
||||||
challenges: GenericChallenge[] | Ref<GenericChallenge | null>
|
challenges: GenericChallenge[] | Ref<GenericChallenge | null>
|
||||||
): Ref<boolean> {
|
): Ref<boolean> {
|
||||||
if (isArray(challenges)) {
|
if (Array.isArray(challenges)) {
|
||||||
challenges = createActiveChallenge(challenges);
|
challenges = createActiveChallenge(challenges);
|
||||||
}
|
}
|
||||||
return computed(() => (challenges as Ref<GenericChallenge | null>).value != null);
|
return computed(() => (challenges as Ref<GenericChallenge | null>).value != null);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { isArray } from "@vue/shared";
|
|
||||||
import ClickableComponent from "features/clickables/Clickable.vue";
|
import ClickableComponent from "features/clickables/Clickable.vue";
|
||||||
import type {
|
import type {
|
||||||
CoercableComponent,
|
CoercableComponent,
|
||||||
|
@ -162,7 +161,7 @@ export function createRepeatable<T extends RepeatableOptions>(
|
||||||
canMaximize: true
|
canMaximize: true
|
||||||
} as const;
|
} as const;
|
||||||
const visibilityRequirement = createVisibilityRequirement(repeatable as GenericRepeatable);
|
const visibilityRequirement = createVisibilityRequirement(repeatable as GenericRepeatable);
|
||||||
if (isArray(repeatable.requirements)) {
|
if (Array.isArray(repeatable.requirements)) {
|
||||||
repeatable.requirements.unshift(visibilityRequirement);
|
repeatable.requirements.unshift(visibilityRequirement);
|
||||||
repeatable.requirements.push(limitRequirement);
|
repeatable.requirements.push(limitRequirement);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { isArray } from "@vue/shared";
|
|
||||||
import { GenericDecorator } from "features/decorators/common";
|
import { GenericDecorator } from "features/decorators/common";
|
||||||
import type {
|
import type {
|
||||||
CoercableComponent,
|
CoercableComponent,
|
||||||
|
@ -151,7 +150,7 @@ export function createUpgrade<T extends UpgradeOptions>(
|
||||||
};
|
};
|
||||||
|
|
||||||
const visibilityRequirement = createVisibilityRequirement(upgrade as GenericUpgrade);
|
const visibilityRequirement = createVisibilityRequirement(upgrade as GenericUpgrade);
|
||||||
if (isArray(upgrade.requirements)) {
|
if (Array.isArray(upgrade.requirements)) {
|
||||||
upgrade.requirements.unshift(visibilityRequirement);
|
upgrade.requirements.unshift(visibilityRequirement);
|
||||||
} else {
|
} else {
|
||||||
upgrade.requirements = [visibilityRequirement, upgrade.requirements];
|
upgrade.requirements = [visibilityRequirement, upgrade.requirements];
|
||||||
|
|
|
@ -48,6 +48,7 @@ export interface InternalFormula<T extends [FormulaSource] | FormulaSource[]> {
|
||||||
invertIntegral?(value: DecimalSource): DecimalSource;
|
invertIntegral?(value: DecimalSource): DecimalSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
||||||
export abstract class InternalFormula<T extends [FormulaSource] | FormulaSource[]> {
|
export abstract class InternalFormula<T extends [FormulaSource] | FormulaSource[]> {
|
||||||
readonly inputs: T;
|
readonly inputs: T;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { isArray } from "@vue/shared";
|
|
||||||
import { globalBus } from "game/events";
|
import { globalBus } from "game/events";
|
||||||
import type { GenericLayer } from "game/layers";
|
import type { GenericLayer } from "game/layers";
|
||||||
import { addingLayers, persistentRefs } from "game/layers";
|
import { addingLayers, persistentRefs } from "game/layers";
|
||||||
|
@ -341,7 +340,7 @@ globalBus.on("addLayer", (layer: GenericLayer, saveData: Record<string, unknown>
|
||||||
// Show warning for persistent values inside arrays
|
// Show warning for persistent values inside arrays
|
||||||
// TODO handle arrays better
|
// TODO handle arrays better
|
||||||
if (foundPersistentInChild) {
|
if (foundPersistentInChild) {
|
||||||
if (isArray(value) && !isArray(obj)) {
|
if (Array.isArray(value) && !Array.isArray(obj)) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"Found array that contains persistent values when adding layer. Keep in mind changing the order of elements in the array will mess with existing player saves.",
|
"Found array that contains persistent values when adding layer. Keep in mind changing the order of elements in the array will mess with existing player saves.",
|
||||||
ProxyState in obj
|
ProxyState in obj
|
||||||
|
|
|
@ -36,12 +36,12 @@ export type LayerData<T> = {
|
||||||
[P in keyof T]?: T[P] extends (infer U)[]
|
[P in keyof T]?: T[P] extends (infer U)[]
|
||||||
? Record<string, LayerData<U>>
|
? Record<string, LayerData<U>>
|
||||||
: T[P] extends Record<string, never>
|
: T[P] extends Record<string, never>
|
||||||
? never
|
? never
|
||||||
: T[P] extends Ref<infer S>
|
: T[P] extends Ref<infer S>
|
||||||
? S
|
? S
|
||||||
: T[P] extends object
|
: T[P] extends object
|
||||||
? LayerData<T[P]>
|
? LayerData<T[P]>
|
||||||
: T[P];
|
: T[P];
|
||||||
};
|
};
|
||||||
|
|
||||||
const player = reactive<Player>({
|
const player = reactive<Player>({
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { isArray } from "@vue/shared";
|
|
||||||
import {
|
import {
|
||||||
CoercableComponent,
|
CoercableComponent,
|
||||||
isVisible,
|
isVisible,
|
||||||
|
@ -270,7 +269,7 @@ export function createBooleanRequirement(
|
||||||
* @param requirements The 1+ requirements to check
|
* @param requirements The 1+ requirements to check
|
||||||
*/
|
*/
|
||||||
export function requirementsMet(requirements: Requirements): boolean {
|
export function requirementsMet(requirements: Requirements): boolean {
|
||||||
if (isArray(requirements)) {
|
if (Array.isArray(requirements)) {
|
||||||
return requirements.every(requirementsMet);
|
return requirements.every(requirementsMet);
|
||||||
}
|
}
|
||||||
const reqsMet = unref(requirements.requirementMet);
|
const reqsMet = unref(requirements.requirementMet);
|
||||||
|
@ -282,7 +281,7 @@ export function requirementsMet(requirements: Requirements): boolean {
|
||||||
* @param requirements The 1+ requirements to check
|
* @param requirements The 1+ requirements to check
|
||||||
*/
|
*/
|
||||||
export function maxRequirementsMet(requirements: Requirements): DecimalSource {
|
export function maxRequirementsMet(requirements: Requirements): DecimalSource {
|
||||||
if (isArray(requirements)) {
|
if (Array.isArray(requirements)) {
|
||||||
return requirements.map(maxRequirementsMet).reduce(Decimal.min);
|
return requirements.map(maxRequirementsMet).reduce(Decimal.min);
|
||||||
}
|
}
|
||||||
const reqsMet = unref(requirements.requirementMet);
|
const reqsMet = unref(requirements.requirementMet);
|
||||||
|
@ -300,13 +299,13 @@ export function maxRequirementsMet(requirements: Requirements): DecimalSource {
|
||||||
* @param amount The amount of levels earned to be displayed
|
* @param amount The amount of levels earned to be displayed
|
||||||
*/
|
*/
|
||||||
export function displayRequirements(requirements: Requirements, amount: DecimalSource = 1) {
|
export function displayRequirements(requirements: Requirements, amount: DecimalSource = 1) {
|
||||||
if (isArray(requirements)) {
|
if (Array.isArray(requirements)) {
|
||||||
requirements = requirements.filter(r => isVisible(r.visibility));
|
requirements = requirements.filter(r => isVisible(r.visibility));
|
||||||
if (requirements.length === 1) {
|
if (requirements.length === 1) {
|
||||||
requirements = requirements[0];
|
requirements = requirements[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isArray(requirements)) {
|
if (Array.isArray(requirements)) {
|
||||||
requirements = requirements.filter(r => "partialDisplay" in r);
|
requirements = requirements.filter(r => "partialDisplay" in r);
|
||||||
const withCosts = requirements.filter(r => unref(r.requiresPay));
|
const withCosts = requirements.filter(r => unref(r.requiresPay));
|
||||||
const withoutCosts = requirements.filter(r => !unref(r.requiresPay));
|
const withoutCosts = requirements.filter(r => !unref(r.requiresPay));
|
||||||
|
@ -344,7 +343,7 @@ export function displayRequirements(requirements: Requirements, amount: DecimalS
|
||||||
* @param amount How many levels to pay for
|
* @param amount How many levels to pay for
|
||||||
*/
|
*/
|
||||||
export function payRequirements(requirements: Requirements, amount: DecimalSource = 1) {
|
export function payRequirements(requirements: Requirements, amount: DecimalSource = 1) {
|
||||||
if (isArray(requirements)) {
|
if (Array.isArray(requirements)) {
|
||||||
requirements.filter(r => unref(r.requiresPay)).forEach(r => r.pay?.(amount));
|
requirements.filter(r => unref(r.requiresPay)).forEach(r => r.pay?.(amount));
|
||||||
} else if (unref(requirements.requiresPay)) {
|
} else if (unref(requirements.requiresPay)) {
|
||||||
requirements.pay?.(amount);
|
requirements.pay?.(amount);
|
||||||
|
|
|
@ -16,8 +16,8 @@ export function exponentialFormat(num: DecimalSource, precision: number, mantiss
|
||||||
const eString = e.gte(1e9)
|
const eString = e.gte(1e9)
|
||||||
? format(e, Math.max(Math.max(precision, 3), projInfo.defaultDecimalsShown))
|
? format(e, Math.max(Math.max(precision, 3), projInfo.defaultDecimalsShown))
|
||||||
: e.gte(10000)
|
: e.gte(10000)
|
||||||
? commaFormat(e, 0)
|
? commaFormat(e, 0)
|
||||||
: e.toStringWithDecimalPlaces(0);
|
: e.toStringWithDecimalPlaces(0);
|
||||||
if (mantissa) {
|
if (mantissa) {
|
||||||
return m.toStringWithDecimalPlaces(precision) + "e" + eString;
|
return m.toStringWithDecimalPlaces(precision) + "e" + eString;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,9 +8,8 @@ export type OptionalKeys<T> = {
|
||||||
export type OmitOptional<T> = Pick<T, RequiredKeys<T>>;
|
export type OmitOptional<T> = Pick<T, RequiredKeys<T>>;
|
||||||
export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
|
export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
|
||||||
|
|
||||||
export type ArrayElements<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer S>
|
export type ArrayElements<T extends ReadonlyArray<unknown>> =
|
||||||
? S
|
T extends ReadonlyArray<infer S> ? S : never;
|
||||||
: never;
|
|
||||||
|
|
||||||
// Reference:
|
// Reference:
|
||||||
// https://stackoverflow.com/questions/7225407/convert-camelcasetext-to-sentence-case-text
|
// https://stackoverflow.com/questions/7225407/convert-camelcasetext-to-sentence-case-text
|
||||||
|
@ -36,5 +35,6 @@ export enum Direction {
|
||||||
Down = "Down",
|
Down = "Down",
|
||||||
Left = "Left",
|
Left = "Left",
|
||||||
Right = "Right",
|
Right = "Right",
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
|
||||||
Default = "Up"
|
Default = "Up"
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ export type ProcessedComputable<T> = T | Ref<T>;
|
||||||
export type GetComputableType<T> = T extends { [DoNotCache]: true }
|
export type GetComputableType<T> = T extends { [DoNotCache]: true }
|
||||||
? T
|
? T
|
||||||
: T extends () => infer S
|
: T extends () => infer S
|
||||||
? Ref<S>
|
? Ref<S>
|
||||||
: undefined extends T
|
: undefined extends T
|
||||||
? undefined
|
? undefined
|
||||||
: T;
|
: T;
|
||||||
export type GetComputableTypeWithDefault<T, S> = undefined extends T
|
export type GetComputableTypeWithDefault<T, S> = undefined extends T
|
||||||
? S
|
? S
|
||||||
: GetComputableType<NonNullable<T>>;
|
: GetComputableType<NonNullable<T>>;
|
||||||
|
|
|
@ -5,28 +5,30 @@ import Decimal from "util/bignum";
|
||||||
export const ProxyState = Symbol("ProxyState");
|
export const ProxyState = Symbol("ProxyState");
|
||||||
export const ProxyPath = Symbol("ProxyPath");
|
export const ProxyPath = Symbol("ProxyPath");
|
||||||
|
|
||||||
export type ProxiedWithState<T> = NonNullable<T> extends Record<PropertyKey, unknown>
|
export type ProxiedWithState<T> =
|
||||||
? NonNullable<T> extends Decimal
|
NonNullable<T> extends Record<PropertyKey, unknown>
|
||||||
? T
|
? NonNullable<T> extends Decimal
|
||||||
: {
|
? T
|
||||||
[K in keyof T]: ProxiedWithState<T[K]>;
|
: {
|
||||||
} & {
|
[K in keyof T]: ProxiedWithState<T[K]>;
|
||||||
[ProxyState]: T;
|
} & {
|
||||||
[ProxyPath]: string[];
|
[ProxyState]: T;
|
||||||
}
|
[ProxyPath]: string[];
|
||||||
: T;
|
}
|
||||||
|
: T;
|
||||||
|
|
||||||
export type Proxied<T> = NonNullable<T> extends Record<PropertyKey, unknown>
|
export type Proxied<T> =
|
||||||
? NonNullable<T> extends Persistent<infer S>
|
NonNullable<T> extends Record<PropertyKey, unknown>
|
||||||
? NonPersistent<S>
|
? NonNullable<T> extends Persistent<infer S>
|
||||||
: NonNullable<T> extends Decimal
|
? NonPersistent<S>
|
||||||
? T
|
: NonNullable<T> extends Decimal
|
||||||
: {
|
? T
|
||||||
[K in keyof T]: Proxied<T[K]>;
|
: {
|
||||||
} & {
|
[K in keyof T]: Proxied<T[K]>;
|
||||||
[ProxyState]: T;
|
} & {
|
||||||
}
|
[ProxyState]: T;
|
||||||
: T;
|
}
|
||||||
|
: T;
|
||||||
|
|
||||||
// Takes a function that returns an object and pretends to be that object
|
// Takes a function that returns an object and pretends to be that object
|
||||||
// Note that the object is lazily calculated
|
// Note that the object is lazily calculated
|
||||||
|
|
|
@ -245,8 +245,11 @@ export function trackHover(element: VueFeature): Ref<boolean> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function kebabifyObject(object: Record<string, unknown>) {
|
export function kebabifyObject(object: Record<string, unknown>) {
|
||||||
return Object.keys(object).reduce((acc, curr) => {
|
return Object.keys(object).reduce(
|
||||||
acc[camelToKebab(curr)] = object[curr];
|
(acc, curr) => {
|
||||||
return acc;
|
acc[camelToKebab(curr)] = object[curr];
|
||||||
}, {} as Record<string, unknown>);
|
return acc;
|
||||||
|
},
|
||||||
|
{} as Record<string, unknown>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue