Fixed achievements' gridables being broken

This commit is contained in:
thepaperpilot 2021-06-22 07:17:22 -05:00
parent ae9578ad3a
commit 97f40bf4a2
8 changed files with 44 additions and 54 deletions

View file

@ -2,7 +2,7 @@
<div v-if="buyable.unlocked" style="display: grid"> <div v-if="buyable.unlocked" style="display: grid">
<button :style="style" @click="buyable.buy" @mousedown="start" @mouseleave="stop" @mouseup="stop" @touchstart="start" <button :style="style" @click="buyable.buy" @mousedown="start" @mouseleave="stop" @mouseup="stop" @touchstart="start"
:class="{ feature: true, [layer || tab.layer]: true, buyable: true, can: buyable.canBuy, locked: !buyable.canAfford, bought }" :class="{ feature: true, [layer || tab.layer]: true, buyable: true, can: buyable.canBuy, locked: !buyable.canAfford, bought }"
@touchend="stop" @touchcancel="stop"> @touchend="stop" @touchcancel="stop" :disabled="!buyable.canBuy">
<div v-if="title"> <div v-if="title">
<component :is="title" /> <component :is="title" />
</div> </div>

View file

@ -2,7 +2,7 @@
<div v-if="clickable.unlocked"> <div v-if="clickable.unlocked">
<button :class="{ feature: true, [layer || tab.layer]: true, can: clickable.canClick, locked: !clickable.canClick }" :style="style" <button :class="{ feature: true, [layer || tab.layer]: true, can: clickable.canClick, locked: !clickable.canClick }" :style="style"
@click="clickable.click" @mousedown="start" @mouseleave="stop" @mouseup="stop" @touchstart="start" @click="clickable.click" @mousedown="start" @mouseleave="stop" @mouseup="stop" @touchstart="start"
@touchend="stop" @touchcancel="stop"> @touchend="stop" @touchcancel="stop" :disabled="!clickable.canClick">
<div v-if="titleDisplay"> <div v-if="titleDisplay">
<component :is="titleDisplay" /> <component :is="titleDisplay" />
</div> </div>

View file

@ -1,7 +1,7 @@
<template> <template>
<button v-if="gridable.unlocked" :class="{ feature: true, tile: true, can: gridable.canClick, locked: !gridable.canClick}" <button v-if="gridable.unlocked" :class="{ feature: true, tile: true, can: canClick, locked: !canClick}"
:style="style" @click="gridable.click" @mousedown="start" @mouseleave="stop" @mouseup="stop" @touchstart="start" :style="style" @click="gridable.click" @mousedown="start" @mouseleave="stop" @mouseup="stop" @touchstart="start"
@touchend="stop" @touchcancel="stop"> @touchend="stop" @touchcancel="stop" :disabled="!canClick">
<div v-if="title"><component :is="title" /></div> <div v-if="title"><component :is="title" /></div>
<component :is="display" style="white-space: pre-line;" /> <component :is="display" style="white-space: pre-line;" />
<branch-node :branches="gridable.branches" :id="id" featureType="gridable" /> <branch-node :branches="gridable.branches" :id="id" featureType="gridable" />
@ -33,9 +33,12 @@ export default {
gridable() { gridable() {
return layers[this.layer || this.tab.layer].grids[this.id][this.cell]; return layers[this.layer || this.tab.layer].grids[this.id][this.cell];
}, },
canClick() {
return this.gridable.canClick;
},
style() { style() {
return [ return [
this.gridable.canClick ? { 'background-color': layers[this.layer || this.tab.layer].color } : {}, this.canClick ? { 'background-color': layers[this.layer || this.tab.layer].color } : {},
layers[this.layer || this.tab.layer].componentStyles?.gridable, layers[this.layer || this.tab.layer].componentStyles?.gridable,
this.gridable.style this.gridable.style
]; ];

View file

@ -7,7 +7,7 @@
can: upgrade.canAfford && !upgrade.bought, can: upgrade.canAfford && !upgrade.bought,
locked: !upgrade.canAfford && !upgrade.bought, locked: !upgrade.canAfford && !upgrade.bought,
bought: upgrade.bought bought: upgrade.bought
}"> }" :disabled="!upgrade.canAfford && !upgrade.bought">
<component v-if="fullDisplay" :is="fullDisplay" /> <component v-if="fullDisplay" :is="fullDisplay" />
<default-upgrade-display v-else :id="id" /> <default-upgrade-display v-else :id="id" />
<branch-node :branches="upgrade.branches" :id="id" featureType="upgrade" /> <branch-node :branches="upgrade.branches" :id="id" featureType="upgrade" />

View file

@ -55,7 +55,7 @@ export default {
if (typeof branch === 'string') { if (typeof branch === 'string') {
return branch.includes('@') ? branch : `${this.featureType}@${branch}`; return branch.includes('@') ? branch : `${this.featureType}@${branch}`;
} }
if (!branch.target.includes('@')) { if (!branch.target?.includes('@')) {
return { ...branch, target: `${branch.featureType || this.featureType}@${branch.target}` }; return { ...branch, target: `${branch.featureType || this.featureType}@${branch.target}` };
} }
return branch; return branch;

View file

@ -12,7 +12,7 @@
small small
}"> }">
<LayerProvider :index="tab.index" :layer="id"> <LayerProvider :index="tab.index" :layer="id">
<button v-if="layer.shown" @click="clickTab" :style="style"> <button v-if="layer.shown" @click="clickTab" :style="style" :disabled="!unlocked">
<component :is="display" /> <component :is="display" />
<branch-node :branches="layer.branches" :id="id" featureType="tree-node" /> <branch-node :branches="layer.branches" :id="id" featureType="tree-node" />
</button> </button>

View file

@ -1,16 +1,19 @@
import Vue from 'vue'; import Vue from 'vue';
import clone from 'lodash.clonedeep'; import clone from 'lodash.clonedeep';
import { isFunction, isPlainObject } from '../util/common'; import { isFunction, isPlainObject } from '../util/common';
import { createProxy, createGridProxy, player } from './proxies'; import { createProxy, createGridProxy, player as playerProxy } from './proxies';
import Decimal from '../util/bignum'; import Decimal from '../util/bignum';
import store from './index'; import store from './index';
import { noCache, getStartingBuyables, getStartingClickables, getStartingChallenges, defaultLayerProperties } from '../util/layers'; import { noCache, getStartingBuyables, getStartingClickables, getStartingChallenges, defaultLayerProperties } from '../util/layers';
import { applyPlayerData } from '../util/save';
export const layers = {}; export const layers = {};
export const hotkeys = []; export const hotkeys = [];
window.layers = layers; window.layers = layers;
export function addLayer(layer) { export function addLayer(layer, player = null) {
player = player || playerProxy;
// Check for required properties // Check for required properties
if (!('id' in layer)) { if (!('id' in layer)) {
console.error(`Cannot add layer without a "id" property!`, layer); console.error(`Cannot add layer without a "id" property!`, layer);
@ -27,6 +30,18 @@ export function addLayer(layer) {
// Clone object to prevent modifying the original // Clone object to prevent modifying the original
layer = clone(layer); layer = clone(layer);
player[layer.id] = applyPlayerData({
upgrades: [],
achievements: [],
milestones: [],
infoboxes: {},
buyables: getStartingBuyables(layer),
clickables: getStartingClickables(layer),
challenges: getStartingChallenges(layer),
grids: {},
...layer.startData?.()
}, player[layer.id]);
// Set default property values // Set default property values
layer = Object.assign({}, defaultLayerProperties, layer); layer = Object.assign({}, defaultLayerProperties, layer);
layer.layer = layer.id; layer.layer = layer.id;
@ -53,9 +68,6 @@ export function addLayer(layer) {
} }
} }
if (layer.upgrades) { if (layer.upgrades) {
if (player[layer.id].upgrades == undefined) {
player[layer.id].upgrades = [];
}
for (let id in layer.upgrades) { for (let id in layer.upgrades) {
if (isPlainObject(layer.upgrades[id])) { if (isPlainObject(layer.upgrades[id])) {
layer.upgrades[id].bought = function() { layer.upgrades[id].bought = function() {
@ -128,9 +140,6 @@ export function addLayer(layer) {
} }
} }
if (layer.achievements) { if (layer.achievements) {
if (player[layer.id].achievements == undefined) {
player[layer.id].achievements = [];
}
for (let id in layer.achievements) { for (let id in layer.achievements) {
if (isPlainObject(layer.achievements[id])) { if (isPlainObject(layer.achievements[id])) {
layer.achievements[id].earned = function() { layer.achievements[id].earned = function() {
@ -140,9 +149,6 @@ export function addLayer(layer) {
} }
} }
if (layer.challenges) { if (layer.challenges) {
if (player[layer.id].challenges == undefined) {
player[layer.id].challenges = getStartingChallenges(layer);
}
for (let id in layer.challenges) { for (let id in layer.challenges) {
if (isPlainObject(layer.challenges[id])) { if (isPlainObject(layer.challenges[id])) {
if (layer.challenges[id].onComplete != undefined) { if (layer.challenges[id].onComplete != undefined) {
@ -229,9 +235,6 @@ export function addLayer(layer) {
} }
} }
if (layer.buyables) { if (layer.buyables) {
if (player[layer.id].buyables == undefined) {
player[layer.id].buyables = getStartingBuyables(layer);
}
if (layer.buyables.reset == undefined) { if (layer.buyables.reset == undefined) {
layer.buyables.reset = noCache(function() { layer.buyables.reset = noCache(function() {
player[this.layer].buyables = getStartingBuyables(layer); player[this.layer].buyables = getStartingBuyables(layer);
@ -272,9 +275,6 @@ export function addLayer(layer) {
} }
} }
if (layer.clickables) { if (layer.clickables) {
if (player[layer.id].clickables == undefined) {
player[layer.id].clickables = getStartingClickables(layer);
}
for (let id in layer.clickables) { for (let id in layer.clickables) {
if (isPlainObject(layer.clickables[id])) { if (isPlainObject(layer.clickables[id])) {
layer.clickables[id].state = function() { layer.clickables[id].state = function() {
@ -287,9 +287,6 @@ export function addLayer(layer) {
} }
} }
if (layer.milestones) { if (layer.milestones) {
if (player[layer.id].milestones == undefined) {
player[layer.id].milestones = [];
}
for (let id in layer.milestones) { for (let id in layer.milestones) {
if (isPlainObject(layer.milestones[id])) { if (isPlainObject(layer.milestones[id])) {
layer.milestones[id].shown = function() { layer.milestones[id].shown = function() {
@ -319,10 +316,10 @@ export function addLayer(layer) {
} }
} }
if (layer.grids) { if (layer.grids) {
if (player[layer.id].grids == undefined) {
player[layer.id].grids = {};
}
for (let id in layer.grids) { for (let id in layer.grids) {
if (player[layer.id].grids[id] == undefined) {
player[layer.id].grids[id] = {};
}
if (isPlainObject(layer.grids[id])) { if (isPlainObject(layer.grids[id])) {
if (player[layer.id].grids[id] == undefined) { if (player[layer.id].grids[id] == undefined) {
player[layer.id].grids[id] = {}; player[layer.id].grids[id] = {};

View file

@ -1,6 +1,5 @@
import modInfo from '../data/modInfo'; import modInfo from '../data/modInfo';
import { getStartingData, getInitialLayers, fixOldSave } from '../data/mod'; import { getStartingData, getInitialLayers, fixOldSave } from '../data/mod';
import { getStartingBuyables, getStartingClickables, getStartingChallenges } from './layers';
import { player } from '../store/proxies'; import { player } from '../store/proxies';
import Decimal from './bignum'; import Decimal from './bignum';
@ -11,7 +10,7 @@ export const IMPORTING_WRONG_ID = "WRONG_ID";
export const IMPORTING_FORCE = "FORCE"; export const IMPORTING_FORCE = "FORCE";
export function getInitialStore(playerData = {}) { export function getInitialStore(playerData = {}) {
playerData = applyPlayerData({ return applyPlayerData({
id: `${modInfo.id}-0`, id: `${modInfo.id}-0`,
name: "Default Save", name: "Default Save",
tabs: modInfo.initialTabs.slice(), tabs: modInfo.initialTabs.slice(),
@ -40,22 +39,6 @@ export function getInitialStore(playerData = {}) {
saveToImport: "", saveToImport: "",
saveToExport: "" saveToExport: ""
}, playerData); }, playerData);
Object.assign(playerData, getInitialLayers(playerData).reduce((acc, layer) => {
acc[layer.id] = applyPlayerData({
upgrades: [],
achievements: [],
milestones: [],
infoboxes: {},
buyables: getStartingBuyables(layer),
clickables: getStartingClickables(layer),
challenges: getStartingChallenges(layer),
...layer.startData?.()
}, playerData[layer.id]);
return acc;
}, {}));
return playerData;
} }
export function save() { export function save() {
@ -121,7 +104,7 @@ export async function loadSave(playerData) {
for (let layer in layers) { for (let layer in layers) {
removeLayer(layer); removeLayer(layer);
} }
getInitialLayers(playerData).forEach(addLayer); getInitialLayers(playerData).forEach(layer => addLayer(layer, playerData));
playerData = getInitialStore(playerData); playerData = getInitialStore(playerData);
if (playerData.offlineProd) { if (playerData.offlineProd) {
@ -136,24 +119,31 @@ export async function loadSave(playerData) {
Object.assign(player, playerData); Object.assign(player, playerData);
for (let prop in player) { for (let prop in player) {
if (!(prop in playerData)) { if (!(prop in playerData) && !(prop in layers)) {
delete player[prop]; delete player[prop];
} }
} }
} }
function applyPlayerData(target, source) { export function applyPlayerData(target, source, destructive = false) {
for (let prop in source) { for (let prop in source) {
if (target[prop] == null) { if (target[prop] == null) {
target[prop] = source[prop]; target[prop] = source[prop];
} else if (target[prop] instanceof Decimal) { } else if (target[prop] instanceof Decimal) {
target[prop] = new Decimal(source[prop]); target[prop] = new Decimal(source[prop]);
} else if (Array.isArray(target[prop]) || typeof target[prop] === 'object') { } else if (Array.isArray(target[prop]) || typeof target[prop] === 'object') {
target[prop] = applyPlayerData(target[prop], source[prop]); target[prop] = applyPlayerData(target[prop], source[prop], destructive);
} else { } else {
target[prop] = source[prop]; target[prop] = source[prop];
} }
} }
if (destructive) {
for (let prop in target) {
if (!(prop in source)) {
delete target[prop];
}
}
}
return target; return target;
} }