This commit is contained in:
Acamaeda 2020-10-16 11:39:39 -04:00
parent 956f13370d
commit a3d65b72a7
12 changed files with 89 additions and 33 deletions

View file

@ -1,5 +1,13 @@
# The Modding Tree changelog:
### v2.0.3 - 10/16/20
- Fixed hotkeys not displaying in info.
- Fixed the game supressing all external hotkeys.
- You can use more things as currencies for upgrade costs and challenge goals using currencyLocation.
- Added maxTickLength, which can be used to prevent offline time or tab-switching from breaking time-limit based mechanics.
- Made buyable respec buttons, and clickable "master" buttons their own components, and gave them a hide/show feature.
### v2.0.2 - 10/15/20
- Branches are now dynamic (they can be functions).
- Fixed a crash related to offline time.

View file

@ -33,11 +33,9 @@ Individual achievement can have these features:
- done(): A function returning a boolean to determine if the achievement should be awarded.
- goalTooltip: Appears when the achievement is hovered over and locked. This is to display the goal (or a hint).
It can also be a function that returns updating text. Can use basic HTML.
- tooltip: Default tooltip for the achievement, appears when it is hovered over. Should convey the goal and any reward for
completing the achievement. It can also be a function that returns updating text. Can use basic HTML.
- doneTooltip: Appears when the achievement is hovered over and completed. This can display what the player achieved (the goal),
and the rewards, if any. It can also be a function that returns updating text. Can use basic HTML.
- effect(): **optional**, A function that calculates and returns the current values of any bonuses from the achievement.
Can return a value or an object containing multiple values.
@ -52,4 +50,12 @@ Individual achievement can have these features:
- layer: **Assigned automagically**. It's the same value as the name of this layer, so you can do player[this.layer].points or similar
- id: **Assigned automagically**. It's the "key" which the achievement was stored under, for convenient access.
The achievement in the example's id is 11.
The achievement in the example's id is 11.
- goalTooltip: **optional, depracated** Appears when the achievement is hovered over and locked, overrides the basic tooltip.
This is to display the goal (or a hint). It can also be a function that returns updating text. Can use basic HTML.
- doneTooltip: **optional, depracated** Appears when the achievement is hovered over and completed, overrides the basic tooltip.
This can display what the player achieved (the goal), and the rewards, if any.
It can also be a function that returns updating text. Can use basic HTML.

View file

@ -13,9 +13,10 @@ Buyables should be formatted like this:
buyables: {
rows: # of rows
cols: # of columns
respec() {}, **optional**, implement it to reset things and give back your currency.
Having this function makes a respec button appear
respecText: **optional**, text that appears on the respec button
respec() {}, //**optional**, implement it to reset things and give back your currency.
// Having this function makes a respec button appear
respecText:// **optional**, text that appears on the respec button
showRespecButton(){} //**optional**, a function determining whether or not to show the button. Defaults to true if absent.
11: {
display() {return "Blah"},
etc

View file

@ -53,7 +53,9 @@ By default, challenges use basic Points for the goal. You can change that using
- currencyDisplayName: **optional**, the name to display for the currency for the goal
- currencyInternalName: **optional**, the internal name for that currency
- currencyLayer: **optional**, the internal name of the layer that currency is stored in.
If it's part of a layer, omit.
If it's not in a layer, omit. If it's not stored directly in a layer, instead use the next feature.
- currencyLocation: **optional**, if your currency is stored in something inside a layer (e.g. a buyable's amount), you can access it this way.
This is a function returning the object in "player" that contains the value (like player[this.layer].buyables)
- completionLimit: **optional**, the amount of times you can complete this challenge. Default is 1 completion.

View file

@ -19,6 +19,7 @@ Clickables should be formatted like this:
masterButtonPress() // **optional** If this is present, an additional button will appear above the clickables.
// pressing it will call the function.
masterButtonText: "Press me!" // **optional** text to display on the Master Button
showMasterButton(){} //**optional**, a function determining whether or not to show the button. Defaults to true if absent.
11: {
display() {return "Blah"},
etc

View file

@ -31,6 +31,11 @@ These are the existing components, but you can create more in v.js:
If it's a single value (e.g. "20px"), that determines the height.
If you have a pair of arguments, the first is width and the second is height.
- row: Display a list of components horizontally. The argument is an array of components in the tab layout format.
- column: Display a list of components vertically. The argument is an array of components in the tab layout format.
This is useful to display columns within a row.
- main-display: The text that displays the main currency for the layer and its effects.
- prestige-button: The argument is a string that the prestige button should say before the amount of
@ -50,7 +55,4 @@ These are the existing components, but you can create more in v.js:
- toggle: A toggle button that toggles a bool value. The data is a pair that identifies what bool to toggle, [layer, id]
- row: Display a list of components horizontally. The argument is an array of components in the tab layout format.
- column: Display a list of components vertically. The argument is an array of components in the tab layout format.
This is useful to display columns within a row.
- respec-button, master-button: The respec and master buttons for buyables and clickables, respectively.

View file

@ -43,11 +43,13 @@ Individual upgrades can have these features:
- onPurchase() - **optional**, this function will be called when the upgrade is purchased.
Good for upgrades like "makes this layer act like it was unlocked first".
By default, upgrades use the main prestige currency for the layer. You can include these to change them:
By default, upgrades use the main prestige currency for the layer. You can include these to change them (but it needs to be a Decimal):
- currencyDisplayName: **optional**, the name to display for the currency for the upgrade
- currencyInternalName: **optional**, the internal name for that currency
- currencyLayer: **optional**, the internal name of the layer that currency is stored in.
If it's not in a layer (like Points), omit.
If it's not in a layer (like Points), omit. If it's not stored directly in a layer, instead use the next feature.
- currencyLocation: **optional**, if your currency is stored in something inside a layer (e.g. a buyable's amount), you can access it this way.
This is a function returning the object in "player" that contains the value (like player[this.layer].buyables)
- style: **Optional**, Applies CSS to this upgrade, in the form of an object where the keys are CSS attributes,
and the values are the values for those attributes (both as strings)

View file

@ -63,7 +63,7 @@
<br><br>
Time Played: {{ formatTime(player.timePlayed) }}<br><br>
<h3>Hotkeys</h3><br>
<span v-for="key in hotkeys" v-if="player[key.layer].unl"><br>{{key.description}}</span>
<span v-for="key in hotkeys" v-if="player[key.layer].unlocked"><br>{{key.description}}</span>
</div>
<div v-if="player.tab=='options'" class="col right">
<button class="back" onclick="showTab('tree')"></button><br>

View file

@ -37,7 +37,10 @@ function getPointGen() {
return gain
}
// You can change this if you have things that can be messed up by long tick lengths
function maxTickLength() {
return(3600000) // Default is 1 hour which is just arbitrarily large
}
function getResetGain(layer, useType = null) {
let type = useType
@ -256,11 +259,14 @@ function canCompleteChallenge(layer, x)
{
if (x != player[layer].activeChallenge) return
let challenge = layers[layer].challenges[x]
let challenge = tmp[layer].challenges[x]
if (challenge.currencyInternalName){
let name = challenge.currencyInternalName
if (challenge.currencyLayer){
if (challenge.currencyLocation){
return !(challenge.currencyLocation[name].lt(challenge.goal))
}
else if (challenge.currencyLayer){
let lr = challenge.currencyLayer
return !(player[lr][name].lt(readData(challenge.goal)))
}
@ -306,6 +312,10 @@ function gameLoop(diff) {
}
if (player.devSpeed) diff *= player.devSpeed
let limit = maxTickLength()
if(diff > limit)
diff = limit
addTime(diff)
player.points = player.points.add(tmp.pointGen.times(diff)).max(0)
for (layer in layers){

View file

@ -107,7 +107,7 @@ addLayer("c", {
cost: new Decimal(69),
currencyDisplayName: "candies", // Use if using a nonstandard currency
currencyInternalName: "points", // Use if using a nonstandard currency
currencyLayer: "", // Leave empty if not in a layer "e.g. points"
currencyLocation: "", // The object in player data that the currency is contained in
unlocked() { return (hasUpgrade(this.layer, 12))},
onPurchase() { // This function triggers when the upgrade is purchased
player[this.layer].unlockOrder = 0
@ -126,6 +126,10 @@ addLayer("c", {
22: {
title: "This upgrade doesn't exist",
description: "Or does it?.",
currencyLocation() {return player[this.layer].buyables}, // The object in player data that the currency is contained in
currencyDisplayName: "exhancers", // Use if using a nonstandard currency
currencyInternalName: 11, // Use if using a nonstandard currency
cost: new Decimal(3),
unlocked() { return player[this.layer].unlocked }, // The upgrade is only visible when this is true
},
@ -133,6 +137,7 @@ addLayer("c", {
buyables: {
rows: 1,
cols: 12,
showRespec: true,
respec() { // Optional, reset things and give back your currency. Having this function makes a respec button appear
player[this.layer].points = player[this.layer].points.add(player[this.layer].spentOnBuyables) // A built-in thing to keep track of this but only keeps a single value
resetBuyables(this.layer)
@ -186,8 +191,8 @@ addLayer("c", {
}, // Useful for if you gain secondary resources or have other interesting things happen to this layer when you reset it. You gain the currency after this function ends.
hotkeys: [
{key: "c", description: "C: reset for lollipops or whatever", onPress(){if (player[this.layer].unlocked) doReset(this.layer)}},
{key: "ctrl+c" + this.layer, description: "Ctrl+c: respec things", onPress(){if (player[this.layer].unlocked) respecBuyables(this.layer)}},
{key: "c", description: "C: reset for lollipops or whatever", onPress(){if (canReset(this.layer)) doReset(this.layer)}},
{key: "ctrl+c", description: "Ctrl+c: respec things", onPress(){if (player[this.layer].unlocked) respecBuyables(this.layer)}},
],
increaseUnlockOrder: [], // Array of layer names to have their order increased when this one is first unlocked
@ -485,8 +490,7 @@ addLayer("a", {
13: {
name: "EIEIO",
done() {return player.f.points.gte(1)},
goalTooltip: "Get a farm point.", // Shows when achievement is not completed
doneTooltip: "Get a farm point.\n\nReward: The dinosaur is now your friend (you can max Farm Points).", // Showed when the achievement is completed
tooltip: "Get a farm point.\n\nReward: The dinosaur is now your friend (you can max Farm Points).", // Showed when the achievement is completed
onComplete() {console.log("Bork bork bork!")}
},
},

View file

@ -356,7 +356,7 @@ function respecBuyables(layer) {
}
function canAffordUpgrade(layer, id) {
let upg = layers[layer].upgrades[id]
let upg = tmp[layer].upgrades[id]
let cost = tmp[layer].upgrades[id].cost
return canAffordPurchase(layer, upg, cost)
}
@ -414,9 +414,13 @@ function achievementEffect(layer, id){
}
function canAffordPurchase(layer, thing, cost) {
if (thing.currencyInternalName){
let name = thing.currencyInternalName
if (thing.currencyLayer){
if (thing.currencyLocation){
return !(thing.currencyLocation[name].lt(cost))
}
else if (thing.currencyLayer){
let lr = thing.currencyLayer
return !(player[lr][name].lt(cost))
}
@ -433,12 +437,16 @@ function buyUpg(layer, id) {
if (!player[layer].unlocked) return
if (!layers[layer].upgrades[id].unlocked) return
if (player[layer].upgrades.includes(id)) return
let upg = layers[layer].upgrades[id]
let upg = tmp[layer].upgrades[id]
let cost = tmp[layer].upgrades[id].cost
if (upg.currencyInternalName){
let name = upg.currencyInternalName
if (upg.currencyLayer){
if (upg.currencyLocation){
if (upg.currencyLocation[name].lt(cost)) return
upg.currencyLocation[name] = upg.currencyLocation[name].sub(cost)
}
else if (upg.currencyLayer){
let lr = upg.currencyLayer
if (player[lr][name].lt(cost)) return
player[lr][name] = player[lr][name].sub(cost)
@ -589,7 +597,7 @@ document.onkeydown = function(e) {
let key = e.key
if (ctrlDown) key = "ctrl+" + key
if (onFocused) return
if (ctrlDown && key != "-" && key != "_" && key != "+" && key != "=" && key != "r" && key != "R" && key != "F5") e.preventDefault()
if (ctrlDown && hotkeys[key]) e.preventDefault()
if(hotkeys[key]){
if (player[hotkeys[key].layer].unlocked)
hotkeys[key].onPress()

20
js/v.js
View file

@ -199,7 +199,7 @@ function loadVue() {
props: ['layer', 'data'],
template: `
<div v-if="layers[layer].buyables" class="upgTable">
<button v-if="tmp[layer].buyables.respec" v-on:click="respecBuyables(layer)" v-bind:class="{ longUpg: true, can: player[layer].unlocked, locked: !player[layer].unlocked }">{{tmp[layer].buyables.respecText ? tmp[layer].buyables.respecText : "Respec"}}</button><br>
<respec-button v-if="tmp[layer].buyables.respec && !(layers[layer].buyables.showRespec !== undefined && tmp[layer].buyables.showRespec == false)" :layer = "layer" v-bind:style="[{'margin-bottom': '12px'}, tmp[layer].componentStyles['respec-button']]"></respec-button>
<div v-for="row in tmp[layer].buyables.rows" class="upgRow">
<div v-for="col in tmp[layer].buyables.cols"><div v-if="layers[layer].buyables[row*10+col]!== undefined && tmp[layer].buyables[row*10+col].unlocked" class="upgAlign" v-bind:style="{'margin-left': '7px', 'margin-right': '7px', 'height': (data ? data : 'inherit'),}">
<buyable :layer = "layer" :data = "row*10+col" :size = "data" v-bind:style="tmp[layer].componentStyles.buyable"></buyable>
@ -225,13 +225,19 @@ function loadVue() {
`
})
Vue.component('respec-button', {
props: ['layer', 'data'],
template: `
<button v-if="layers[layer].buyables && tmp[layer].buyables.respec && !(layers[layer].buyables.showRespec !== undefined && tmp[layer].buyables.showRespec == false)" v-on:click="respecBuyables(layer)" v-bind:class="{ longUpg: true, can: player[layer].unlocked, locked: !player[layer].unlocked }">{{tmp[layer].buyables.respecText ? tmp[layer].buyables.respecText : "Respec"}}</button><br>
`
})
// data = button size, in px
Vue.component('clickables', {
props: ['layer', 'data'],
template: `
<div v-if="layers[layer].clickables" class="upgTable">
<button v-if="tmp[layer].clickables.masterButtonPress" v-on:click="layers[layer].clickables.masterButtonPress()" v-bind:class="{ longUpg: true, can: player[layer].unlocked, locked: !player[layer].unlocked }">{{tmp[layer].clickables.masterButtonText ? tmp[layer].clickables.masterButtonText : "Click me!"}}</button><br>
<master-button v-if="tmp[layer].clickables.masterButtonPress && !(layers[layer].clickables.showMasterButton !== undefined && tmp[layer].clickables.showMasterButton == false)" :layer = "layer" v-bind:style="[{'margin-bottom': '12px'}, tmp[layer].componentStyles['master-button']]"></master-button>
<div v-for="row in tmp[layer].clickables.rows" class="upgRow">
<div v-for="col in tmp[layer].clickables.cols"><div v-if="layers[layer].clickables[row*10+col]!== undefined && tmp[layer].clickables[row*10+col].unlocked" class="upgAlign" v-bind:style="{'margin-left': '7px', 'margin-right': '7px', 'height': (data ? data : 'inherit'),}">
<clickable :layer = "layer" :data = "row*10+col" :size = "data" v-bind:style="tmp[layer].componentStyles.clickable"></clickable>
@ -257,6 +263,12 @@ function loadVue() {
`
})
Vue.component('master-button', {
props: ['layer', 'data'],
template: `
<button v-if="tmp[layer].clickables && tmp[layer].clickables.masterButtonPress && !(layers[layer].clickables.showMasterButton !== undefined && tmp[layer].clickables.showMasterButton == false)" v-on:click="layers[layer].clickables.masterButtonPress()" v-bind:class="{ longUpg: true, can: player[layer].unlocked, locked: !player[layer].unlocked }">{{tmp[layer].clickables.masterButtonText ? tmp[layer].clickables.masterButtonText : "Click me!"}}</button><br>
`
})
// data = button size, in px
Vue.component('microtabs', {
@ -311,8 +323,8 @@ function loadVue() {
template: `
<div v-if="layers[layer].achievements && layers[layer].achievements[data]!== undefined && tmp[layer].achievements[data].unlocked" v-bind:class="{ [layer]: true, achievement: true, locked: !hasAchievement(layer, data), bought: hasAchievement(layer, data)}"
v-bind:tooltip="
hasAchievement(layer, data) ? (tmp[layer].achievements[data].doneTooltip ? tmp[layer].achievements[data].doneTooltip : 'You did it!')
: (tmp[layer].achievements[data].goalTooltip ? tmp[layer].achievements[data].goalTooltip : 'LOCKED')
hasAchievement(layer, data) ? (tmp[layer].achievements[data].doneTooltip ? tmp[layer].achievements[data].doneTooltip : (tmp[layer].achievements[data].tooltip ? tmp[layer].achievements[data].tooltip : 'You did it!'))
: (tmp[layer].achievements[data].goalTooltip ? tmp[layer].achievements[data].goalTooltip : (tmp[layer].achievements[data].tooltip ? tmp[layer].achievements[data].tooltip : 'LOCKED'))
"
v-bind:style="[(!tmp[layer].achievements[data].unlocked) ? {'visibility': 'hidden'} : {}, tmp[layer].achievements[data].style,]">