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: {
|
||||
node: true
|
||||
},
|
||||
extends: [
|
||||
"plugin:vue/vue3-essential",
|
||||
"@vue/eslint-config-typescript/recommended",
|
||||
"@vue/eslint-config-prettier"
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ["@typescript-eslint"],
|
||||
overrides: [
|
||||
{
|
||||
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"],
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
|
|
11
package.json
11
package.json
|
@ -43,13 +43,14 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@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",
|
||||
"@vue/eslint-config-prettier": "^7.0.0",
|
||||
"@vue/eslint-config-typescript": "^10.0.0",
|
||||
"eslint": "^8.6.0",
|
||||
"@typescript-eslint/parser": "^7.2.0",
|
||||
"@vue/eslint-config-prettier": "^9.0.0",
|
||||
"@vue/eslint-config-typescript": "^13.0.0",
|
||||
"eslint": "^8.57.0",
|
||||
"jsdom": "^24.0.0",
|
||||
"prettier": "^2.5.1",
|
||||
"prettier": "^3.2.5",
|
||||
"typescript": "^5.4.2",
|
||||
"vitest": "^1.4.0",
|
||||
"vue-tsc": "^2.0.6"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
"title": "Profectus",
|
||||
"description": "A project made in Profectus",
|
||||
"id": "",
|
||||
"id": "321",
|
||||
"author": "",
|
||||
"discordName": "",
|
||||
"discordLink": "",
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { computed } from "@vue/reactivity";
|
||||
import { isArray } from "@vue/shared";
|
||||
import { computed } from "vue";
|
||||
import Select from "components/fields/Select.vue";
|
||||
import AchievementComponent from "features/achievements/Achievement.vue";
|
||||
import { GenericDecorator } from "features/decorators/common";
|
||||
|
@ -275,7 +274,7 @@ export function createAchievement<T extends AchievementOptions>(
|
|||
const requirements = [
|
||||
createVisibilityRequirement(genericAchievement),
|
||||
createBooleanRequirement(() => !genericAchievement.earned.value),
|
||||
...(isArray(achievement.requirements)
|
||||
...(Array.isArray(achievement.requirements)
|
||||
? achievement.requirements
|
||||
: [achievement.requirements])
|
||||
];
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { isArray } from "@vue/shared";
|
||||
import ClickableComponent from "features/clickables/Clickable.vue";
|
||||
import {
|
||||
Component,
|
||||
|
@ -157,7 +156,7 @@ export function createAction<T extends ActionOptions>(
|
|||
}
|
||||
];
|
||||
const originalStyle = unref(style);
|
||||
if (isArray(originalStyle)) {
|
||||
if (Array.isArray(originalStyle)) {
|
||||
currStyle.push(...originalStyle);
|
||||
} else if (originalStyle != null) {
|
||||
currStyle.push(originalStyle);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { isArray } from "@vue/shared";
|
||||
import Toggle from "components/fields/Toggle.vue";
|
||||
import ChallengeComponent from "features/challenges/Challenge.vue";
|
||||
import { GenericDecorator } from "features/decorators/common";
|
||||
|
@ -348,7 +347,7 @@ export function createActiveChallenge(
|
|||
export function isAnyChallengeActive(
|
||||
challenges: GenericChallenge[] | Ref<GenericChallenge | null>
|
||||
): Ref<boolean> {
|
||||
if (isArray(challenges)) {
|
||||
if (Array.isArray(challenges)) {
|
||||
challenges = createActiveChallenge(challenges);
|
||||
}
|
||||
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 type {
|
||||
CoercableComponent,
|
||||
|
@ -162,7 +161,7 @@ export function createRepeatable<T extends RepeatableOptions>(
|
|||
canMaximize: true
|
||||
} as const;
|
||||
const visibilityRequirement = createVisibilityRequirement(repeatable as GenericRepeatable);
|
||||
if (isArray(repeatable.requirements)) {
|
||||
if (Array.isArray(repeatable.requirements)) {
|
||||
repeatable.requirements.unshift(visibilityRequirement);
|
||||
repeatable.requirements.push(limitRequirement);
|
||||
} else {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { isArray } from "@vue/shared";
|
||||
import { GenericDecorator } from "features/decorators/common";
|
||||
import type {
|
||||
CoercableComponent,
|
||||
|
@ -151,7 +150,7 @@ export function createUpgrade<T extends UpgradeOptions>(
|
|||
};
|
||||
|
||||
const visibilityRequirement = createVisibilityRequirement(upgrade as GenericUpgrade);
|
||||
if (isArray(upgrade.requirements)) {
|
||||
if (Array.isArray(upgrade.requirements)) {
|
||||
upgrade.requirements.unshift(visibilityRequirement);
|
||||
} else {
|
||||
upgrade.requirements = [visibilityRequirement, upgrade.requirements];
|
||||
|
|
|
@ -48,6 +48,7 @@ export interface InternalFormula<T extends [FormulaSource] | FormulaSource[]> {
|
|||
invertIntegral?(value: DecimalSource): DecimalSource;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
||||
export abstract class InternalFormula<T extends [FormulaSource] | FormulaSource[]> {
|
||||
readonly inputs: T;
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { isArray } from "@vue/shared";
|
||||
import { globalBus } from "game/events";
|
||||
import type { GenericLayer } 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
|
||||
// TODO handle arrays better
|
||||
if (foundPersistentInChild) {
|
||||
if (isArray(value) && !isArray(obj)) {
|
||||
if (Array.isArray(value) && !Array.isArray(obj)) {
|
||||
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.",
|
||||
ProxyState in obj
|
||||
|
|
|
@ -36,12 +36,12 @@ export type LayerData<T> = {
|
|||
[P in keyof T]?: T[P] extends (infer U)[]
|
||||
? Record<string, LayerData<U>>
|
||||
: T[P] extends Record<string, never>
|
||||
? never
|
||||
: T[P] extends Ref<infer S>
|
||||
? S
|
||||
: T[P] extends object
|
||||
? LayerData<T[P]>
|
||||
: T[P];
|
||||
? never
|
||||
: T[P] extends Ref<infer S>
|
||||
? S
|
||||
: T[P] extends object
|
||||
? LayerData<T[P]>
|
||||
: T[P];
|
||||
};
|
||||
|
||||
const player = reactive<Player>({
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { isArray } from "@vue/shared";
|
||||
import {
|
||||
CoercableComponent,
|
||||
isVisible,
|
||||
|
@ -270,7 +269,7 @@ export function createBooleanRequirement(
|
|||
* @param requirements The 1+ requirements to check
|
||||
*/
|
||||
export function requirementsMet(requirements: Requirements): boolean {
|
||||
if (isArray(requirements)) {
|
||||
if (Array.isArray(requirements)) {
|
||||
return requirements.every(requirementsMet);
|
||||
}
|
||||
const reqsMet = unref(requirements.requirementMet);
|
||||
|
@ -282,7 +281,7 @@ export function requirementsMet(requirements: Requirements): boolean {
|
|||
* @param requirements The 1+ requirements to check
|
||||
*/
|
||||
export function maxRequirementsMet(requirements: Requirements): DecimalSource {
|
||||
if (isArray(requirements)) {
|
||||
if (Array.isArray(requirements)) {
|
||||
return requirements.map(maxRequirementsMet).reduce(Decimal.min);
|
||||
}
|
||||
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
|
||||
*/
|
||||
export function displayRequirements(requirements: Requirements, amount: DecimalSource = 1) {
|
||||
if (isArray(requirements)) {
|
||||
if (Array.isArray(requirements)) {
|
||||
requirements = requirements.filter(r => isVisible(r.visibility));
|
||||
if (requirements.length === 1) {
|
||||
requirements = requirements[0];
|
||||
}
|
||||
}
|
||||
if (isArray(requirements)) {
|
||||
if (Array.isArray(requirements)) {
|
||||
requirements = requirements.filter(r => "partialDisplay" in r);
|
||||
const withCosts = 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
|
||||
*/
|
||||
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));
|
||||
} else if (unref(requirements.requiresPay)) {
|
||||
requirements.pay?.(amount);
|
||||
|
|
|
@ -16,8 +16,8 @@ export function exponentialFormat(num: DecimalSource, precision: number, mantiss
|
|||
const eString = e.gte(1e9)
|
||||
? format(e, Math.max(Math.max(precision, 3), projInfo.defaultDecimalsShown))
|
||||
: e.gte(10000)
|
||||
? commaFormat(e, 0)
|
||||
: e.toStringWithDecimalPlaces(0);
|
||||
? commaFormat(e, 0)
|
||||
: e.toStringWithDecimalPlaces(0);
|
||||
if (mantissa) {
|
||||
return m.toStringWithDecimalPlaces(precision) + "e" + eString;
|
||||
} else {
|
||||
|
|
|
@ -8,9 +8,8 @@ export type OptionalKeys<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 ArrayElements<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer S>
|
||||
? S
|
||||
: never;
|
||||
export type ArrayElements<T extends ReadonlyArray<unknown>> =
|
||||
T extends ReadonlyArray<infer S> ? S : never;
|
||||
|
||||
// Reference:
|
||||
// https://stackoverflow.com/questions/7225407/convert-camelcasetext-to-sentence-case-text
|
||||
|
@ -36,5 +35,6 @@ export enum Direction {
|
|||
Down = "Down",
|
||||
Left = "Left",
|
||||
Right = "Right",
|
||||
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
|
||||
Default = "Up"
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@ export type ProcessedComputable<T> = T | Ref<T>;
|
|||
export type GetComputableType<T> = T extends { [DoNotCache]: true }
|
||||
? T
|
||||
: T extends () => infer S
|
||||
? Ref<S>
|
||||
: undefined extends T
|
||||
? undefined
|
||||
: T;
|
||||
? Ref<S>
|
||||
: undefined extends T
|
||||
? undefined
|
||||
: T;
|
||||
export type GetComputableTypeWithDefault<T, S> = undefined extends T
|
||||
? S
|
||||
: GetComputableType<NonNullable<T>>;
|
||||
|
|
|
@ -5,28 +5,30 @@ import Decimal from "util/bignum";
|
|||
export const ProxyState = Symbol("ProxyState");
|
||||
export const ProxyPath = Symbol("ProxyPath");
|
||||
|
||||
export type ProxiedWithState<T> = NonNullable<T> extends Record<PropertyKey, unknown>
|
||||
? NonNullable<T> extends Decimal
|
||||
? T
|
||||
: {
|
||||
[K in keyof T]: ProxiedWithState<T[K]>;
|
||||
} & {
|
||||
[ProxyState]: T;
|
||||
[ProxyPath]: string[];
|
||||
}
|
||||
: T;
|
||||
export type ProxiedWithState<T> =
|
||||
NonNullable<T> extends Record<PropertyKey, unknown>
|
||||
? NonNullable<T> extends Decimal
|
||||
? T
|
||||
: {
|
||||
[K in keyof T]: ProxiedWithState<T[K]>;
|
||||
} & {
|
||||
[ProxyState]: T;
|
||||
[ProxyPath]: string[];
|
||||
}
|
||||
: T;
|
||||
|
||||
export type Proxied<T> = NonNullable<T> extends Record<PropertyKey, unknown>
|
||||
? NonNullable<T> extends Persistent<infer S>
|
||||
? NonPersistent<S>
|
||||
: NonNullable<T> extends Decimal
|
||||
? T
|
||||
: {
|
||||
[K in keyof T]: Proxied<T[K]>;
|
||||
} & {
|
||||
[ProxyState]: T;
|
||||
}
|
||||
: T;
|
||||
export type Proxied<T> =
|
||||
NonNullable<T> extends Record<PropertyKey, unknown>
|
||||
? NonNullable<T> extends Persistent<infer S>
|
||||
? NonPersistent<S>
|
||||
: NonNullable<T> extends Decimal
|
||||
? T
|
||||
: {
|
||||
[K in keyof T]: Proxied<T[K]>;
|
||||
} & {
|
||||
[ProxyState]: T;
|
||||
}
|
||||
: T;
|
||||
|
||||
// Takes a function that returns an object and pretends to be that object
|
||||
// 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>) {
|
||||
return Object.keys(object).reduce((acc, curr) => {
|
||||
acc[camelToKebab(curr)] = object[curr];
|
||||
return acc;
|
||||
}, {} as Record<string, unknown>);
|
||||
return Object.keys(object).reduce(
|
||||
(acc, curr) => {
|
||||
acc[camelToKebab(curr)] = object[curr];
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, unknown>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue