mirror of
https://github.com/thepaperpilot/The-Modding-Tree.git
synced 2025-01-31 15:41:35 +00:00
Merge remote-tracking branch 'upstream/master' into kronos
This commit is contained in:
commit
df17445891
24 changed files with 411 additions and 186 deletions
15
changelog.md
15
changelog.md
|
@ -1,5 +1,20 @@
|
|||
# The Modding Tree changelog:
|
||||
|
||||
# v2.5.5 - 5/12/21
|
||||
- Added grids! They are a grid of buttons which behave the same, but have their own data. Good for inventory grids, map tiles, and more!
|
||||
- Added "marked" feature to add a mark to a node. Can be an image instead of a star. (Originally by Jacorb)
|
||||
- Added "layer-proxy" component that lets you use components from another layer.
|
||||
- Added the ability to display non-whole numbers in main-display.
|
||||
|
||||
# v2.5.4 - 5/10/21
|
||||
- Added a setting to always use single-tab mode.
|
||||
- Added directMult, which multiplies prestige gain after exponents and softcaps. It actually multiplies gain for static layers.
|
||||
- Added onEnter and onExit for challenges.
|
||||
- Improved displaying numbers between 0.0001 and 0.1.
|
||||
- Added documentation on how gainMult/Exp work for static layers.
|
||||
- Fixed a visual issue on mobile, thanks to thepaperpilot.
|
||||
- Improved documentation in general.
|
||||
|
||||
# v2.5.3 - 5/8/21
|
||||
- Improved performance of tab formats and bars.
|
||||
- Respec confirmation settings are now kept on resets.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# The-Modding-Tree
|
||||
|
||||
The main way to add content is through creating layers. You can either add a layer directly in the layers object in [layerSupport.js](/js/layerSupport.js), or declare it in another file and register it by calling `addLayer(layername, layerdata)`. There is an example layer registration in [layers.js](/js/layers.js) showing the recommended method. It is just an example and can be freely deleted. You can also use it as a reference or a base for your own layers.
|
||||
Making a game in The Modding Tree mostly involves defining parameters or functions on objects. If you aren't following the [getting started guide](getting-started.md), you should start by [setting up your basic mod info](main-mod-info.md) in [mod.js](/js/mod.js). It's important to set a mod id to ensure saving works properly.
|
||||
|
||||
The first thing you need to do is fill out the modInfo object at the top of [mod.js](/js/mod.js) to set your mod's name, ID (a string), and other information. A unique modId will prevent your mod's saves from conflicting with other mods. Note that changing this after people have started playing will reset their saves.
|
||||
Beyond that, the main way to add content is through creating layers, often in [layers.js](/js/layers.js). You can add new layers by calling `addLayer(layername, layerdata)`. There is an example of a basic layer in [layers.js](/js/layers.js) showing the recommended method. It is just an example and can be freely deleted. You can also use it as a reference or a base for your own layers.
|
||||
|
||||
Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to, for example to add new Vue components in [v.js](/js/v.js).
|
||||
Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to, for example to add new Vue components in [components.js](/js/components.js).
|
||||
|
||||
The Modding Tree uses [break\_eternity.js](https://github.com/Patashu/break_eternity.js) to store large values. This means that many numbers are `Decimal` objects, and must be treated differently. For example, you have to use `new Decimal(x)` to create a `Decimal` value instead of a plain number, and perform operations on them by calling functions. e.g, instead of `x = x + y`, use `x = x.add(y)`. Keep in mind this also applies to comparison operators, which should be replaced with calling the `.gt`, `.gte`, `.lt`, `.lte`, `.eq`, and `.neq` functions. See the [break\_eternity.js](https://github.com/Patashu/break_eternity.js) docs for more details on working with `Decimal` values.
|
||||
|
||||
|
@ -39,6 +39,7 @@ While reading this documentation, the following key will be used when describing
|
|||
- [Milestones](milestones.md): How to create milestones for a layer.
|
||||
- [Buyables](buyables.md): Create rebuyable upgrades for your layer (with the option to make them respec-able). Can be used to make Enhancers or Space Buildings.
|
||||
- [Clickables](clickables.md): A more generalized variant of buyables, for any kind of thing that is sometimes clickable. Between these and Buyables, you can do just about anything.
|
||||
- [Achievements](achievements.md): How to create achievements for a layer (or for the whole game).
|
||||
|
||||
### Other components and features
|
||||
|
||||
|
@ -46,6 +47,6 @@ While reading this documentation, the following key will be used when describing
|
|||
- [Bars](bars.md): Display some information as a progress bar, gauge, or similar. They are highly customizable, and can be horizontal and vertical as well.
|
||||
- [Subtabs and Microtabs](subtabs-and-microtabs.md): Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs.
|
||||
You can even use them to embed a layer inside another layer!
|
||||
- [Achievements](achievements.md): How to create achievements for a layer (or for the whole game).
|
||||
- [Grids][grids.md]: Create a group buttons that behave the same, but have their own data. Good for map tiles, an inventory grid, and more!
|
||||
- [Infoboxes](infoboxes.md): Boxes containing text that can be shown or hidden.
|
||||
- [Trees](trees-and-tree-customization.md): Make your own trees. You can make non-layer button nodes too!
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Achievements
|
||||
|
||||
Achievements are awarded to the player when they meet a certain goal, and optionally give some benefit. Currently they are pretty basic, but additional features will be added later to help.
|
||||
Achievements are awarded to the player when they meet a certain goal, and optionally give some benefit.
|
||||
|
||||
You can make global achievements by putting them in a side layer by making its row equal to "side" instead of a number.
|
||||
|
||||
|
|
|
@ -29,6 +29,10 @@ addLayer("p", {
|
|||
return new Decimal(1)
|
||||
},
|
||||
|
||||
layerShown() { return true } // Returns a bool for if this layer's node should be visible in the tree.
|
||||
layerShown() { return true }, // Returns a bool for if this layer's node should be visible in the tree.
|
||||
|
||||
upgrades: {
|
||||
// Look in the upgrades docs to see what goes here!
|
||||
},
|
||||
})
|
||||
```
|
||||
|
|
|
@ -15,7 +15,7 @@ challenges: {
|
|||
11: {
|
||||
name: "Ouch",
|
||||
challengeDescription: "description of ouchie",
|
||||
goal: new Decimal(100),
|
||||
canComplete: function() {return player.points.gte(100)},
|
||||
etc
|
||||
},
|
||||
etc
|
||||
|
@ -48,6 +48,10 @@ Individual Challenges can have these features:
|
|||
|
||||
- onComplete() - **optional**. this function will be called when the challenge is completed when previously incomplete.
|
||||
|
||||
- onEnter() - **optional**. this function will be called when entering the challenge
|
||||
|
||||
- onExit() - **optional**. this function will be called when exiting the challenge in any way
|
||||
|
||||
- countsAs: **optional**. If a challenge combines the effects of other challenges in this layer, you can use this. An array of challenge ids. The player is effectively in all of those challenges when in the current one.
|
||||
|
||||
- completionLimit: **optional**. the amount of times you can complete this challenge. Default is 1 completion.
|
||||
|
|
|
@ -6,10 +6,10 @@ DO NOT USE THESE TO MAKE THINGS THAT YOU CLICK REPEATEDLY FOR A BONUS BECAUSE TH
|
|||
|
||||
There are several differences between the two. One is that a buyable's saved data is its amount as a `Decimal`, while Clickables store a "state" which can be a number or string, but not `Decimal`, array, or object). Buyables have a number of extra features which you can see on their page. Clickables also have a smaller default size.
|
||||
|
||||
Useful functions for dealing with achievements and implementing their effects:
|
||||
Useful functions for dealing with clickables and implementing their effects:
|
||||
|
||||
- getClickableState(layer, id): get the state of the clickable the player has
|
||||
- setClickableState(layer, id, state): set the state of the buyable the player has
|
||||
- setClickableState(layer, id, state): set the state of the clickable the player has
|
||||
- clickableEffect(layer, id): Returns the current effects of the clickable, if any.
|
||||
|
||||
Clickables should be formatted like this:
|
||||
|
@ -36,7 +36,7 @@ Features:
|
|||
|
||||
- canClick(): A function returning a bool to determine if you can click the clickable.
|
||||
|
||||
- onClick(): A function that implements clicking one of the clickable.
|
||||
- onClick(): A function that implements clicking the clickable.
|
||||
|
||||
- onHold(): **optional** A function that is called 20x/sec when the button is held for at least 0.25 seconds.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Custom tab layouts
|
||||
|
||||
Note: If you are using subtabs, `tabFormat` is used differently, but you still use the same format within each subtabs. [See here for more on subtabs](subtabs-and-microtabs.md).
|
||||
Note: If you are using subtabs, `tabFormat` is used differently, but the same format is used for defining their layouts. [See here for more on subtabs](subtabs-and-microtabs.md).
|
||||
|
||||
Custom tab layouts can be used to do basically anything in a tab window, especially combined with the "style" layer feature. The `tabFormat` feature is an array of things, like this:
|
||||
|
||||
|
@ -35,12 +35,19 @@ These are the existing components, but you can create more in [components.js](/j
|
|||
|
||||
- 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.
|
||||
- main-display: The text that displays the main currency for the layer and its effects. The argument is the amount of precision to use, allowing it to display non-whole numbers.
|
||||
|
||||
- resource-display: The text that displays the currency that this layer is based on, as well as the best and/or total values for this layer's prestige currency (if they are put in `startData` for this layer).
|
||||
|
||||
- prestige-button: The argument is a string that the prestige button should say before the amount of currency you will gain. It can also be a function that returns updating text.
|
||||
|
||||
- text-input: A text input box. The argument is the name of the variable in player[layer] that the input is for, player[layer][argument]
|
||||
(Works with strings, numbers, and Decimals!)
|
||||
|
||||
- slider: Lets the user input a value with a slider. The argument a 3-element array: [name, min, max].
|
||||
The name is the name of the variable in player[layer] that the input that the input is for, and min and max are the limits of the slider.
|
||||
(Does not work for Decimal values)
|
||||
|
||||
- upgrades: The layer's upgrades. The argument is optional, and is a the list of rows this component should include, if it doesn't have all of them.
|
||||
|
||||
- milestones, challenges, achievements: Display the upgrades, milestones, and challenges for a layer, as appropriate.
|
||||
|
@ -56,19 +63,15 @@ These are the existing components, but you can create more in [components.js](/j
|
|||
- tree: Displays a tree. The argument is an array of arrays containing the names of the nodes in the tree (first by row, then by column)
|
||||
[See here for more information on tree layouts and nodes!](trees-and-tree-customization.md)
|
||||
|
||||
- toggle: A toggle button that toggles a bool value. The argument is a pair that identifies what bool to toggle, e.g. `[layer, id]`
|
||||
- toggle: A toggle button that toggles a bool value. The argument is a pair that identifies the location in player of the bool to toggle, e.g. `[layer, id]`. 'layer' also affects the color of the toggle.
|
||||
|
||||
- text-input: A text input box. The argument is the name of the variable in player[layer] that the input is for, player[layer][argument]
|
||||
(Works with strings, numbers, and Decimals!)
|
||||
- grid: Displays the gridable grid for the layer. If you need more than one grid, use a layer proxy.
|
||||
|
||||
- slider: Lets the user input a value with a slider. The argument a 3-element array: [name, min, max].
|
||||
The name is the name of the variable in player[layer] that the input that the input is for, and min and max are the limits of the slider.
|
||||
(Does not work for Decimal values)
|
||||
|
||||
- layer-proxy: Lets you use components from another layer. The argument is a pair, `[layer, data]`, consisting of the id of the layer to proxy from, and the tabFormat for the components to show.
|
||||
|
||||
The rest of the components are sub-components. They can be used just like other components, but are typically part of another component.
|
||||
|
||||
- upgrade, milestone, challenge, buyable, clickable, achievement: An individual upgrade, challenge, etc. The argument is the id. This can be used if you want to have upgrades split up across multiple subtabs, for example.
|
||||
- upgrade, milestone, challenge, buyable, clickable, achievement, gridable: An individual upgrade, challenge, etc. The argument is the id. This can be used if you want to have upgrades split up across multiple subtabs, for example.
|
||||
|
||||
- respec-button, master-button: The respec and master buttons for buyables and clickables, respectively.
|
||||
|
||||
|
|
0
docs/decimals.md
Normal file
0
docs/decimals.md
Normal file
68
docs/grids.md
Normal file
68
docs/grids.md
Normal file
|
@ -0,0 +1,68 @@
|
|||
# Grids
|
||||
|
||||
Grids are an easier way of making a group of similar clickables. They all have the same behavior, but are different based on their data.
|
||||
|
||||
**NOTE: Gridables are similar to clickables in some respects, but are fundamentally different from normal TMT components in quite a few ways. Be sure to keep these in mind:**
|
||||
- Gridable ids use base 100 instead of base 10, so you can have more than 10 tiles in a row. This means that a grid might look like this:
|
||||
101 102
|
||||
201 202
|
||||
- Individual gridables are not defined individually. All properties go directly into the "grid" object. Functions are called with arguments for the id of the gridables and its associated data, so you can give them the appropriate appearance and properties based on that.
|
||||
- If you need two unrelated grids in a layer, you'll need to use a layer proxy component.
|
||||
|
||||
Useful functions for dealing with grids:
|
||||
|
||||
- getGridData(layer, id): get the data for the chosen gridable
|
||||
- setGridData(layer, id, state): set the data for the chosen gridable
|
||||
- gridEffect(layer, id): get the effect for the chosen gridable
|
||||
|
||||
The grid should be formatted like this:
|
||||
|
||||
```js
|
||||
grid: {
|
||||
rows: 4, // If these are dynamic make sure to have a max value as well!
|
||||
cols: 5,
|
||||
getStartData(id) {
|
||||
return 0
|
||||
},
|
||||
getUnlocked(id) { // Default
|
||||
return true
|
||||
},
|
||||
getCanClick(data, id) {
|
||||
return true
|
||||
},
|
||||
onClick(data, id) {
|
||||
player[this.layer].grid[id]++
|
||||
},
|
||||
getDisplay(data, id) {
|
||||
return data
|
||||
},
|
||||
|
||||
etc
|
||||
}
|
||||
```
|
||||
|
||||
Features:
|
||||
|
||||
- rows, cols: The amount of rows and columns of gridable to display.
|
||||
|
||||
- maxRows, maxCols: **sometimes needed**. If rows or cols are dynamic, you need to define the maximum amount that there can be (you can increase it when you update the game though). These CANNOT be dynamic.
|
||||
|
||||
- getStartData(id): Creates the default data for the gridable at this position. This can be an object, or a regular value.
|
||||
|
||||
- getUnlocked(id): **optional**. Returns true if the gridable at this position should be visible.
|
||||
|
||||
- getTitle(data, id): **optional**. Returns text that should displayed at the top in a larger font, based on the position and data of the gridable.
|
||||
|
||||
- getDisplay(data, id): **optional**. Returns everything that should be displayed on the gridable after the title, based on the position and data of the gridable.
|
||||
|
||||
- getStyle(data, id): **optional**. Returns CSS to apply to this gridable, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).
|
||||
|
||||
- getCanClick(data, id): **optional**. A function returning a bool to determine if you can click a gridable, based on its data and position. If absent, you can always click it.
|
||||
|
||||
- onClick(data, id): A function that implements clicking on the gridable, based on its position and data.
|
||||
|
||||
- onHold(data, id): **optional** A function that is called 20x/sec when the button is held for at least 0.25 seconds.
|
||||
|
||||
- getEffect(data, id): **optional**. A function that calculates and returns a gridable's effect, based on its position and data. (Whatever that means for a gridable)
|
||||
|
||||
- layer: **assigned automagically**. It's the same value as the name of this layer, so you can do `player[this.layer].points` or similar.
|
|
@ -60,7 +60,7 @@ You can make almost any value dynamic by using a function in its place, includin
|
|||
|
||||
## Big features (all optional)
|
||||
|
||||
- upgrades: A grid of one-time purchases which can have unique upgrade conditions, currency costs, and bonuses. [See here for more info.](upgrades.md)
|
||||
- upgrades: A set of one-time purchases which can have unique upgrade conditions, currency costs, and bonuses. [See here for more info.](upgrades.md)
|
||||
|
||||
- milestones: A list of bonuses gained upon reaching certain thresholds of a resource. Often used for automation/QOL. [See here for more info.](milestones.md)
|
||||
|
||||
|
@ -76,9 +76,11 @@ You can make almost any value dynamic by using a function in its place, includin
|
|||
|
||||
- achievements: Kind of like milestones, but with a different display style and some other differences. Extra features are on the way at a later date! [See here for more info.](achievements.md)
|
||||
|
||||
- achievementPopups, milestonePopups: **optional**, If false, disables popup message when you get the achievement/milestone. True by default.
|
||||
|
||||
- infoboxes: Displays some text in a box that can be shown or hidden. [See here for more info.](infoboxes.md)
|
||||
|
||||
- achievementPopups, milestonePopups: **optional**, If false, disables popup message when you get the achievement/milestone. True by default.
|
||||
- grid: A grid of buttons that behave the same, but have their own data.[See here for more info.](grids.md)
|
||||
|
||||
## Prestige formula features
|
||||
|
||||
|
@ -101,7 +103,10 @@ You can make almost any value dynamic by using a function in its place, includin
|
|||
|
||||
- roundUpCost: **optional**. a bool, which is true if the resource cost needs to be rounded up. (use if the base resource is a "static" currency.)
|
||||
|
||||
- gainMult(), gainExp(): **optional**. Functions that calculate the multiplier and exponent on resource gain from upgrades and boosts and such. Plug in any bonuses here.
|
||||
- gainMult(), gainExp(): **optional**. For normal layers, these functions calculate the multiplier and exponent on resource gain from upgrades and boosts and such. Plug in most bonuses here.
|
||||
For static layers, they instead divide and root the cost of the resource.
|
||||
|
||||
- directMult(): **optional**. Directly multiplies the resource gain, after exponents and softcaps. For static layers, actually multiplies resource gain instead of reducing the cost.
|
||||
|
||||
- softcap, softcapPower: **optional**. For normal layers, gain beyond [softcap] points is put to the [softcapPower]th power
|
||||
Default for softcap is e1e7, and for power is 0.5.
|
||||
|
@ -137,6 +142,8 @@ You can make almost any value dynamic by using a function in its place, includin
|
|||
- tooltip() / tooltipLocked(): **optional**. Functions that return text, which is the tooltip for the node when the layer is unlocked or locked, respectively. By default the tooltips behave the same as in the original Prestige Tree.
|
||||
If the value is "", the tooltip will be disabled.
|
||||
|
||||
- marked: **optional** Adds a mark to the corner of the node. If it's "true" it will be a star, but it can also be an image URL.
|
||||
|
||||
## Other features
|
||||
|
||||
- doReset(resettingLayer): **optional**. Is triggered when a layer on a row greater than or equal to this one does a reset. The default behavior is to reset everything on the row, but only if it was triggered by a layer in a higher row. `doReset` is always called for side layers, but for these the default behavior is to reset nothing.
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
# mod.js
|
||||
|
||||
All of the non-layer code and data that you're likely to edit is here in [mod.js](/js/mod.js)! Everything in [mod.js](/js/mod.js) will not be altered by updates, besides the addition of new things.
|
||||
Most of the non-layer code and data that you're likely to edit is here in [mod.js](/js/mod.js).
|
||||
Everything in [mod.js](/js/mod.js) will not be altered by updates, besides the addition of new things.
|
||||
|
||||
Here's a breakdown of what's in it:
|
||||
|
||||
- modInfo is where most of the basic configuration for the mod is. It contains:
|
||||
- name: The name of your mod. (a string)
|
||||
- id: The id for your mod, a unique string that is used to determine savefile location. Setting it is important!
|
||||
- id: The id for your mod, a unique string that is used to determine savefile location. Be sure to set it when you start making a mod, and don't change it later because it will erase all saves.
|
||||
- author: The name of the author, displayed in the info tab.
|
||||
- pointsName: This changes what is displayed instead of "points" for the main currency. (It does not affect it in the code.)
|
||||
- discordName, discordLink: If you have a Discord server or other discussion place, you can add a link to it.
|
||||
|
@ -25,7 +26,7 @@ Here's a breakdown of what's in it:
|
|||
|
||||
- changelog is the HTML displayed in the changelog tab.
|
||||
|
||||
- doNotCallTheseFunctionsEveryTick is very important. TMT calls every function anywhere in "layers" every tick to store the result, unless specifically told not to. Functions that have are used to do an action need to be identified. "Official" functions (those in the documentation) are all fine, but if you make any new ones, add their names to this array.
|
||||
- doNotCallTheseFunctionsEveryTick is very important, if you are adding non-standard functions. TMT calls every function anywhere in "layers" every tick to store the result, unless specifically told not to. Functions that have are used to do an action need to be identified. "Official" functions (those in the documentation) are all fine, but if you make any new ones, add their names to this array.
|
||||
|
||||
```js
|
||||
// (The ones here are examples, all official functions are already taken care of)
|
||||
|
@ -53,4 +54,6 @@ function addedPlayerData() { return {
|
|||
|
||||
Less important things beyond this point!
|
||||
|
||||
- maxTickLength(): Returns the maximum tick length, in milliseconds. Only really useful if you have something that reduces over time, which long ticks mess up (usually a challenge).
|
||||
- maxTickLength(): Returns the maximum tick length, in milliseconds. Only really useful if you have something that reduces over time, which long ticks mess up (usually a challenge).
|
||||
|
||||
- fixOldSave(): Can be used to modify a save file when loading into a new version of the game. Use this to undo inflation, never forcibly hard reset your players.
|
|
@ -6,6 +6,7 @@ addLayer("c", {
|
|||
name: "Candies", // This is optional, only used in a few places, If absent it just uses the layer id.
|
||||
symbol: "C", // This appears on the layer's node. Default is the id with the first letter capitalized
|
||||
position: 0, // Horizontal position within a row. By default it uses the layer id and sorts in alphabetical order
|
||||
marked: "discord.png",
|
||||
startData() { return {
|
||||
unlocked: true,
|
||||
points: new Decimal(0),
|
||||
|
@ -95,7 +96,10 @@ addLayer("c", {
|
|||
rewardDisplay() { return format(this.rewardEffect())+"x" },
|
||||
countsAs: [12, 21], // Use this for if a challenge includes the effects of other challenges. Being in this challenge "counts as" being in these.
|
||||
rewardDescription: "Says hi",
|
||||
onComplete() {console.log("hiii")} // Called when you complete the challenge
|
||||
onComplete() {console.log("hiii")}, // Called when you successfully complete the challenge
|
||||
onEnter() {console.log("So challenging")},
|
||||
onExit() {console.log("Sweet freedom!")},
|
||||
|
||||
},
|
||||
},
|
||||
upgrades: {
|
||||
|
@ -315,7 +319,7 @@ addLayer("c", {
|
|||
["buyables", ""], "blank",
|
||||
["row", [
|
||||
["toggle", ["c", "beep"]], ["blank", ["30px", "10px"]], // Width, height
|
||||
["display-text", function() {return "Beep"}], "blank", ["v-line", "200px"],
|
||||
["layer-proxy", ["f", ["prestige-button"]]], "blank", ["v-line", "200px"],
|
||||
["column", [
|
||||
["prestige-button", "", {'width': '150px', 'height': '80px'}],
|
||||
["prestige-button", "", {'width': '100px', 'height': '150px'}],
|
||||
|
@ -395,7 +399,8 @@ addLayer("f", {
|
|||
exponent: 0.5,
|
||||
base: 3,
|
||||
roundUpCost: true,
|
||||
canBuyMax() {return hasAchievement('a', 13)},
|
||||
canBuyMax() {return false},
|
||||
//directMult() {return new Decimal(player.c.otherThingy)},
|
||||
|
||||
row: 1,
|
||||
layerShown() {return true},
|
||||
|
@ -422,6 +427,7 @@ addLayer("f", {
|
|||
canReset() {
|
||||
return tmp[this.layer].baseAmount.gte(tmp[this.layer].nextAt)
|
||||
},
|
||||
|
||||
// This is also non minimal, a Clickable!
|
||||
clickables: {
|
||||
|
||||
|
@ -520,5 +526,32 @@ addLayer("a", {
|
|||
onComplete() {console.log("Bork bork bork!")}
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
grid: {
|
||||
maxRows: 3,
|
||||
rows: 2,
|
||||
cols: 2,
|
||||
getStartData(id) {
|
||||
return id
|
||||
},
|
||||
getUnlocked(id) { // Default
|
||||
return true
|
||||
},
|
||||
getCanClick(data, id) {
|
||||
return true
|
||||
},
|
||||
getStyle(data, id) {
|
||||
return {'background-color': '#'+ (data*1234%999999)}
|
||||
},
|
||||
onClick(data, id) { // Don't forget onHold
|
||||
player[this.layer].grid[id]++
|
||||
},
|
||||
getTitle(data, id) {
|
||||
return "Gridable #" + id
|
||||
},
|
||||
getDisplay(data, id) {
|
||||
return data
|
||||
},
|
||||
} ,
|
||||
midsection: ["grid", "blank"]
|
||||
}
|
||||
)
|
|
@ -11,7 +11,7 @@ let modInfo = {
|
|||
|
||||
// Set your version in num and name
|
||||
let VERSION = {
|
||||
num: "2.5.3",
|
||||
num: "2.5.5",
|
||||
name: "Dreams Really Do Come True",
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,19 @@ function loadVue() {
|
|||
`
|
||||
});
|
||||
|
||||
// data [other layer, tabformat for within proxy]
|
||||
Vue.component('layer-proxy', {
|
||||
props: ['layer', 'data'],
|
||||
computed: {
|
||||
key() {return this.$vnode.key}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<column :layer="data[0]" :data="data[1]" :key="key + 'col'"></column>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
|
||||
Vue.component("infobox", {
|
||||
props: ["layer", "data"],
|
||||
template: `
|
||||
|
@ -276,7 +289,7 @@ function loadVue() {
|
|||
|
||||
// Displays the main resource for the layer
|
||||
Vue.component("main-display", {
|
||||
props: ["layer"],
|
||||
props: ["layer", "data"],
|
||||
template: `<div class="sticky">
|
||||
<div class="upgTable instant">
|
||||
<div class="upgRow">
|
||||
|
@ -287,7 +300,7 @@ function loadVue() {
|
|||
<div class="instant" style="width: 8px; height: 17px;"></div>
|
||||
<span v-if="player[layer].points.lt('1e1000')">You have </span>
|
||||
<h2 v-bind:style="{'color': tmp[layer].color, 'text-shadow': '0px 0px 10px ' + tmp[layer].color}">
|
||||
{{ formatWhole(player[layer].points) }}</h2> {{ tmp[layer].resource }}<span
|
||||
{{ data ? format(player[layer].points, data) : formatWhole(player[layer].points) }}</h2> {{ tmp[layer].resource }}<span
|
||||
v-if="layers[layer].effectDescription">, <span v-html="run(layers[layer].effectDescription, layers[layer])"></span></span>
|
||||
</div>
|
||||
`
|
||||
|
@ -436,6 +449,57 @@ function loadVue() {
|
|||
`
|
||||
});
|
||||
|
||||
|
||||
// data = button size, in px
|
||||
Vue.component('grid', {
|
||||
props: ['layer', 'data'],
|
||||
template: `
|
||||
<div v-if="tmp[layer].grid" class="upgTable">
|
||||
<div v-for="row in tmp[layer].grid.rows" class="upgRow">
|
||||
<div v-for="col in tmp[layer].grid.cols"><div v-if="run(layers[layer].grid.getUnlocked, layers[layer].grid, row*100+col)"
|
||||
class="upgAlign" v-bind:style="{'margin': '1px', 'height': 'inherit',}">
|
||||
<gridable :layer = "layer" :data = "row*100+col" v-bind:style="tmp[layer].componentStyles.gridable"></gridable>
|
||||
</div></div>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
|
||||
Vue.component('gridable', {
|
||||
props: ['layer', 'data'],
|
||||
template: `
|
||||
<button
|
||||
v-if="tmp[layer].grid && player[layer].grid[data]!== undefined && run(layers[layer].grid.getUnlocked, layers[layer].grid, data)"
|
||||
v-bind:class="{ tile: true, can: canClick, locked: !canClick}"
|
||||
v-bind:style="[canClick ? {'background-color': tmp[layer].color} : {}, gridRun(layer, 'getStyle', player[this.layer].grid[this.data], this.data)]"
|
||||
v-on:click="clickGrid(layer, data)" @mousedown="start" @mouseleave="stop" @mouseup="stop" @touchstart="start" @touchend="stop" @touchcancel="stop">
|
||||
<span v-if= "layers[layer].grid.getTitle"><h3 v-html="gridRun(this.layer, 'getTitle', player[this.layer].grid[this.data], this.data)"></h3><br></span>
|
||||
<span v-bind:style="{'white-space': 'pre-line'}" v-html="gridRun(this.layer, 'getDisplay', player[this.layer].grid[this.data], this.data)"></span>
|
||||
</button>
|
||||
`,
|
||||
data() { return { interval: false, time: 0,}},
|
||||
computed: {
|
||||
canClick() {
|
||||
return gridRun(this.layer, 'getCanClick', player[this.layer].grid[this.data], this.data)}
|
||||
},
|
||||
methods: {
|
||||
start() {
|
||||
if (!this.interval && layers[this.layer].grid.onHold) {
|
||||
this.interval = setInterval((function() {
|
||||
if(this.time >= 5 && gridRun(this.layer, 'getCanClick', player[this.layer].grid[this.data], this.data)) {
|
||||
gridRun(this.layer, 'onHold', player[this.layer].grid[this.data], this.data) }
|
||||
this.time = this.time+1
|
||||
}).bind(this), 50)}
|
||||
},
|
||||
stop() {
|
||||
clearInterval(this.interval)
|
||||
this.interval = false
|
||||
this.time = 0
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
// data = button size, in px
|
||||
Vue.component("microtabs", {
|
||||
props: ["layer", "data"],
|
||||
|
@ -588,7 +652,7 @@ function loadVue() {
|
|||
});
|
||||
|
||||
// SYSTEM COMPONENTS
|
||||
|
||||
Vue.component('node-mark', systemComponents['node-mark'])
|
||||
Vue.component('tab-buttons', systemComponents['tab-buttons'])
|
||||
Vue.component('tree-node', systemComponents['tree-node'])
|
||||
Vue.component('layer-tab', systemComponents['layer-tab'])
|
||||
|
|
27
js/game.js
27
js/game.js
|
@ -5,7 +5,7 @@ let gameEnded = false;
|
|||
|
||||
// Don't change this
|
||||
const TMT_VERSION = {
|
||||
tmtNum: "2.5.3",
|
||||
tmtNum: "2.5.5",
|
||||
tmtName: "Dreams Really Do Come True"
|
||||
}
|
||||
|
||||
|
@ -18,30 +18,32 @@ function getResetGain(layer, useType = null) {
|
|||
}
|
||||
}
|
||||
if (tmp[layer].type === "none") {
|
||||
return new Decimal(0);
|
||||
return new decimalZero;
|
||||
}
|
||||
if (tmp[layer].gainExp.eq(0)) {
|
||||
return new Decimal(0);
|
||||
return new decimalZero;
|
||||
}
|
||||
if (type === "static") {
|
||||
if ((!tmp[layer].canBuyMax) || tmp[layer].baseAmount.lt(tmp[layer].requires)) {
|
||||
return new Decimal(1);
|
||||
}
|
||||
let gain = tmp[layer].baseAmount.div(tmp[layer].requires).div(tmp[layer].gainMult).max(1).log(tmp[layer].base).times(tmp[layer].gainExp).pow(Decimal.pow(tmp[layer].exponent, -1));
|
||||
gain = gain.times(tmp[layer].directMult);
|
||||
return gain.floor().sub(player[layer].points).add(1).max(1);
|
||||
} else if (type === "normal") {
|
||||
if (tmp[layer].baseAmount.lt(tmp[layer].requires)) {
|
||||
return new Decimal(0);
|
||||
return decimalZero;
|
||||
}
|
||||
let gain = tmp[layer].baseAmount.div(tmp[layer].requires).pow(tmp[layer].exponent).times(tmp[layer].gainMult).pow(tmp[layer].gainExp);
|
||||
if (gain.gte(tmp[layer].softcap)) {
|
||||
gain = gain.pow(tmp[layer].softcapPower).times(tmp[layer].softcap.pow(decimalOne.sub(tmp[layer].softcapPower)));
|
||||
}
|
||||
gain = gain.times(tmp[layer].directMult);
|
||||
return gain.floor().max(0);
|
||||
} else if (type === "custom") {
|
||||
return layers[layer].getResetGain();
|
||||
} else {
|
||||
return new Decimal(0);
|
||||
return decimalZero;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +71,7 @@ function getNextAt(layer, canMax = false, useType = null) {
|
|||
if (!tmp[layer].canBuyMax) {
|
||||
canMax = false;
|
||||
}
|
||||
let amt = player[layer].points.plus((canMax && tmp[layer].baseAmount.gte(tmp[layer].nextAt)) ? tmp[layer].resetGain : 0);
|
||||
let amt = player[layer].points.plus((canMax && tmp[layer].baseAmount.gte(tmp[layer].nextAt)) ? tmp[layer].resetGain : 0).div(tmp[layer].directMult);
|
||||
let extraCost = Decimal.pow(tmp[layer].base, amt.pow(tmp[layer].exponent).div(tmp[layer].gainExp)).times(tmp[layer].gainMult);
|
||||
let cost = extraCost.times(tmp[layer].requires).max(tmp[layer].requires);
|
||||
if (tmp[layer].roundUpCost) {
|
||||
|
@ -77,7 +79,7 @@ function getNextAt(layer, canMax = false, useType = null) {
|
|||
}
|
||||
return cost;
|
||||
} else if (type === "normal") {
|
||||
let next = tmp[layer].resetGain.add(1);
|
||||
let next = tmp[layer].resetGain.add(1).div(tmp[layer].directMult);
|
||||
if (next.gte(tmp[layer].softcap)) {
|
||||
next = next.div(tmp[layer].softcap.pow(decimalOne.sub(tmp[layer].softcapPower))).pow(decimalOne.div(tmp[layer].softcapPower));
|
||||
}
|
||||
|
@ -89,7 +91,7 @@ function getNextAt(layer, canMax = false, useType = null) {
|
|||
} else if (type === "custom") {
|
||||
return layers[layer].getNextAt(canMax);
|
||||
} else {
|
||||
return new Decimal(0);
|
||||
return decimalZero;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,7 +199,7 @@ function resetBuyables(layer) {
|
|||
if (layers[layer].buyables) {
|
||||
player[layer].buyables = getStartBuyables(layer);
|
||||
}
|
||||
player[layer].spentOnBuyables = new Decimal(0);
|
||||
player[layer].spentOnBuyables = decimalZero;
|
||||
}
|
||||
|
||||
|
||||
|
@ -264,7 +266,7 @@ function doReset(layer, force = false) {
|
|||
}
|
||||
}
|
||||
|
||||
tmp[layer].baseAmount = new Decimal(0); // quick fix
|
||||
tmp[layer].baseAmount = decimalZero; // quick fix
|
||||
}
|
||||
|
||||
if (tmp[layer].resetsNothing) {
|
||||
|
@ -279,7 +281,7 @@ function doReset(layer, force = false) {
|
|||
}
|
||||
|
||||
prevOnReset = {...player}; //Deep Copy
|
||||
player.points = (row === 0 ? new Decimal(0) : getStartPoints());
|
||||
player.points = (row === 0 ? decimalZero : getStartPoints());
|
||||
|
||||
for (let x = row; x >= 0; x--) {
|
||||
rowReset(x, layer);
|
||||
|
@ -307,6 +309,7 @@ function startChallenge(layer, x) {
|
|||
doReset(layer, true);
|
||||
if (enter) {
|
||||
player[layer].activeChallenge = x;
|
||||
run(layers[layer].challenges[x].onEnter, layers[layer].challenges[x]);
|
||||
}
|
||||
|
||||
updateChallengeTemp(layer);
|
||||
|
@ -346,6 +349,7 @@ function completeChallenge(layer) {
|
|||
let completions = canCompleteChallenge(layer, x);
|
||||
if (!completions) {
|
||||
player[layer].activeChallenge = null;
|
||||
run(layers[layer].challenges[x].onExit, layers[layer].challenges[x]);
|
||||
return;
|
||||
}
|
||||
if (player[layer].challenges[x] < tmp[layer].challenges[x].completionLimit) {
|
||||
|
@ -357,6 +361,7 @@ function completeChallenge(layer) {
|
|||
}
|
||||
}
|
||||
player[layer].activeChallenge = null;
|
||||
run(layers[layer].challenges[x].onExit, layers[layer].challenges[x]);
|
||||
updateChallengeTemp(layer);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,10 +53,7 @@ function achievementStyle(layer, id){
|
|||
function updateWidth() {
|
||||
var screenWidth = window.innerWidth
|
||||
var splitScreen = screenWidth >= 1024
|
||||
if (player.splitMode === "disabled") splitScreen = false
|
||||
if (player.splitMode === "enabled") splitScreen = true
|
||||
|
||||
|
||||
if (player.forceOneTab) splitScreen = false
|
||||
tmp.other.screenWidth = screenWidth
|
||||
tmp.other.splitScreen = splitScreen
|
||||
tmp.other.lastPoints = player.points
|
||||
|
|
|
@ -155,6 +155,15 @@ function setupLayer(layer){
|
|||
layers[layer].infoboxes[thing].unlocked = true
|
||||
}
|
||||
}
|
||||
|
||||
if (layers[layer].grid) {
|
||||
layers[layer].grid.layer = layer
|
||||
if (layers[layer].grid.getUnlocked === undefined)
|
||||
layers[layer].grid.getUnlocked = true
|
||||
if (layers[layer].grid.getCanClick === undefined)
|
||||
layers[layer].grid.getCanClick = true
|
||||
|
||||
}
|
||||
|
||||
if (layers[layer].startData) {
|
||||
let data = layers[layer].startData()
|
||||
|
@ -165,8 +174,9 @@ function setupLayer(layer){
|
|||
if(!layers[layer].componentStyles) layers[layer].componentStyles = {}
|
||||
if(layers[layer].symbol === undefined) layers[layer].symbol = layer.charAt(0).toUpperCase() + layer.slice(1)
|
||||
if(layers[layer].unlockOrder === undefined) layers[layer].unlockOrder = []
|
||||
if(layers[layer].gainMult === undefined) layers[layer].gainMult = new Decimal(1)
|
||||
if(layers[layer].gainExp === undefined) layers[layer].gainExp = new Decimal(1)
|
||||
if(layers[layer].gainMult === undefined) layers[layer].gainMult = decimalOne
|
||||
if(layers[layer].gainExp === undefined) layers[layer].gainExp = decimalOne
|
||||
if(layers[layer].directMult === undefined) layers[layer].directMult = decimalOne
|
||||
if(layers[layer].type === undefined) layers[layer].type = "none"
|
||||
if(layers[layer].base === undefined || layers[layer].base <= 1) layers[layer].base = 2
|
||||
if(layers[layer].softcap === undefined) layers[layer].softcap = new Decimal("e1e7")
|
||||
|
|
|
@ -53,6 +53,7 @@ const systemComponents = {
|
|||
tmp[layer].canClick ? (tmp[layer].tooltip ? tmp[layer].tooltip : 'I am a button!')
|
||||
: (tmp[layer].tooltipLocked ? tmp[layer].tooltipLocked : 'I am a button!')
|
||||
)"></tooltip>
|
||||
<node-mark :layer='layer' :data='layers[layer].marked'></node-mark></span>
|
||||
</button>
|
||||
`
|
||||
},
|
||||
|
@ -181,6 +182,8 @@ const systemComponents = {
|
|||
<tr>
|
||||
<td><button class="opt" onclick="adjustMSDisp()">Show Milestones: {{ MS_DISPLAYS[MS_SETTINGS.indexOf(player.msDisplay)]}}</button></td>
|
||||
<td><button class="opt" onclick="toggleOpt('hqTree')">High-Quality Tree: {{ player.hqTree?"ON":"OFF" }}</button></td>
|
||||
<td><button class="opt" onclick="toggleOpt('forceOneTab'); needsCanvasUpdate = true">Single-Tab Mode: {{ player.forceOneTab?"ALWAYS":"AUTO" }}</button></td>
|
||||
</tr>
|
||||
</table>`
|
||||
},
|
||||
|
||||
|
@ -195,5 +198,14 @@ const systemComponents = {
|
|||
props: ['text'],
|
||||
template: `<div class="tooltip" v-html="text"></div>
|
||||
`
|
||||
},
|
||||
|
||||
'node-mark': {
|
||||
props: ['layer', 'data'],
|
||||
template: `<div v-if='data'>
|
||||
<div v-if='data === true' class='star' style='position: absolute; left: -10px; top: -10px;'></div>
|
||||
<img v-else class='mark' style='position: absolute; left: -25px; top: -10px;' v-bind:src="data"></div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ const activeFunctions = [
|
|||
"sellOne", "sellAll", "pay", "actualCostFunction", "actualEffectFunction",
|
||||
"effectDescription", "display", "fullDisplay", "effectDisplay", "rewardDisplay",
|
||||
"tabFormat", "content",
|
||||
"onComplete", "onPurchase", "onEnter", "onExit",
|
||||
"getUnlocked", "getStyle", "getCanClick", "getTitle", "getDisplay"
|
||||
];
|
||||
|
||||
const noCall = doNotCallTheseFunctionsEveryTick;
|
||||
|
@ -42,19 +44,11 @@ function setupTemp() {
|
|||
}
|
||||
|
||||
tmp.other = {
|
||||
screenWidth: window.innerWidth,
|
||||
splitScreen: window.innerWidth >=1024,
|
||||
lastPoints: player.points || new Decimal(0),
|
||||
oomps: new Decimal(0),
|
||||
|
||||
held: {
|
||||
time: null,
|
||||
id: null,
|
||||
layer: null,
|
||||
type: null,
|
||||
}
|
||||
lastPoints: player.points || decimalZero,
|
||||
oomps: decimalZero,
|
||||
}
|
||||
|
||||
updateWidth()
|
||||
|
||||
temp = tmp
|
||||
}
|
||||
|
@ -82,11 +76,11 @@ function setupTempData(layerData, tmpData, funcsData) {
|
|||
}
|
||||
else { // noinspection JSUnfilteredForInLoop
|
||||
if (isFunction(layerData[item]) && !activeFunctions.includes(item)){
|
||||
funcsData[item] = layerData[item]
|
||||
tmpData[item] = new Decimal(1) // The safest thing to put probably?
|
||||
} else {
|
||||
tmpData[item] = layerData[item]
|
||||
}
|
||||
funcsData[item] = layerData[item]
|
||||
tmpData[item] = decimalOne // The safest thing to put probably?
|
||||
} else {
|
||||
tmpData[item] = layerData[item]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
34
js/utils.js
34
js/utils.js
|
@ -63,6 +63,15 @@ function setClickableState(layer, id, state) {
|
|||
player[layer].clickables[id] = state;
|
||||
}
|
||||
|
||||
|
||||
function getGridData(layer, id) {
|
||||
return (player[layer].grid[id])
|
||||
}
|
||||
|
||||
function setGridData(layer, id, data) {
|
||||
player[layer].grid[id] = data
|
||||
}
|
||||
|
||||
function upgradeEffect(layer, id) {
|
||||
return (tmp[layer].upgrades[id].effect);
|
||||
}
|
||||
|
@ -83,6 +92,11 @@ function achievementEffect(layer, id) {
|
|||
return (tmp[layer].achievements[id].effect);
|
||||
}
|
||||
|
||||
function gridEffect(layer, id) {
|
||||
return (gridRun(layer, 'getEffect', player[layer].grid[id], id))
|
||||
}
|
||||
|
||||
|
||||
function canAffordPurchase(layer, thing, cost) {
|
||||
|
||||
if (thing.currencyInternalName) {
|
||||
|
@ -202,11 +216,22 @@ function clickClickable(layer, id) {
|
|||
if (tmp[layer].clickables[id].canClick === false) {
|
||||
return;
|
||||
}
|
||||
if (tmp[layer].clickables[id].getCanClick === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
run(layers[layer].clickables[id].onClick, layers[layer].clickables[id]);
|
||||
updateClickableTemp(layer);
|
||||
}
|
||||
|
||||
function clickGrid(layer, id) {
|
||||
if (!player[layer].unlocked) return
|
||||
if (!run(layers[layer].grid.getUnlocked, layers[layer].grid, id)) return
|
||||
if (!gridRun(layer, 'getCanClick', player[layer].grid[id], id)) return
|
||||
|
||||
gridRun(layer, 'onClick', player[layer].grid[id], id)
|
||||
}
|
||||
|
||||
// Function to determine if the player is in a challenge
|
||||
function inChallenge(layer, id) {
|
||||
let challenge = player[layer].activeChallenge;
|
||||
|
@ -522,3 +547,12 @@ function run(func, target, args = null) {
|
|||
return func;
|
||||
}
|
||||
}
|
||||
|
||||
function gridRun(layer, func, data, id) {
|
||||
if (isFunction(layers[layer].grid[func])) {
|
||||
let bound = layers[layer].grid[func].bind(layers[layer].grid)
|
||||
return bound(data, id)
|
||||
} else {
|
||||
return layers[layer].grid[func];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
|
||||
function exponentialFormat(num, precision, mantissa = true) {
|
||||
let e = num.log10().floor()
|
||||
let m = num.div(Decimal.pow(10, e))
|
||||
if (m.toStringWithDecimalPlaces(precision) == 10) {
|
||||
m = new Decimal(1)
|
||||
e = e.add(1)
|
||||
}
|
||||
e = (e.gte(1e9) ? format(e, 1) : (e.gte(10000) ? commaFormat(e, 0) : e.toStringWithDecimalPlaces(0)))
|
||||
if (mantissa)
|
||||
return m.toStringWithDecimalPlaces(precision) + "e" + e
|
||||
else return "e" + e
|
||||
}
|
||||
|
||||
function commaFormat(num, precision) {
|
||||
if (num === null || num === undefined) return "NaN"
|
||||
if (num.mag < 0.001) return (0).toFixed(precision)
|
||||
return num.toStringWithDecimalPlaces(precision).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")
|
||||
}
|
||||
|
||||
|
||||
function regularFormat(num, precision) {
|
||||
if (num === null || num === undefined) return "NaN"
|
||||
if (num.mag < 0.001) return (0).toFixed(precision)
|
||||
if (num.mag < 0.01) precision = 3
|
||||
return num.toStringWithDecimalPlaces(precision)
|
||||
}
|
||||
|
||||
function fixValue(x, y = 0) {
|
||||
return x || new Decimal(y)
|
||||
}
|
||||
|
||||
function sumValues(x) {
|
||||
x = Object.values(x)
|
||||
if (!x[0]) return new Decimal(0)
|
||||
return x.reduce((a, b) => Decimal.add(a, b))
|
||||
}
|
||||
|
||||
function format(decimal, precision = 2, small) {
|
||||
small = small || modInfo.allowSmall
|
||||
decimal = new Decimal(decimal)
|
||||
if (isNaN(decimal.sign) || isNaN(decimal.layer) || isNaN(decimal.mag)) {
|
||||
player.hasNaN = true;
|
||||
return "NaN"
|
||||
}
|
||||
if (decimal.sign < 0) return "-" + format(decimal.neg(), precision)
|
||||
if (decimal.mag == Number.POSITIVE_INFINITY) return "Infinity"
|
||||
if (decimal.gte("eeee1000")) {
|
||||
var slog = decimal.slog()
|
||||
if (slog.gte(1e6)) return "F" + format(slog.floor())
|
||||
else return Decimal.pow(10, slog.sub(slog.floor())).toStringWithDecimalPlaces(3) + "F" + commaFormat(slog.floor(), 0)
|
||||
}
|
||||
else if (decimal.gte("1e100000")) return exponentialFormat(decimal, 0, false)
|
||||
else if (decimal.gte("1e1000")) return exponentialFormat(decimal, 0)
|
||||
else if (decimal.gte(1e9)) return exponentialFormat(decimal, precision)
|
||||
else if (decimal.gte(1e3)) return commaFormat(decimal, 0)
|
||||
else if (decimal.gte(0.001) || !small) return regularFormat(decimal, precision)
|
||||
else if (decimal.eq(0)) return (0).toFixed(precision)
|
||||
|
||||
decimal = invertOOM(decimal)
|
||||
let val = ""
|
||||
if (decimal.lt("1e1000")){
|
||||
val = exponentialFormat(decimal, precision)
|
||||
return val.replace(/([^(?:e|F)]*)$/, '-$1')
|
||||
}
|
||||
else
|
||||
return format(decimal, precision) + "⁻¹"
|
||||
|
||||
}
|
||||
|
||||
function formatWhole(decimal) {
|
||||
decimal = new Decimal(decimal)
|
||||
if (decimal.gte(1e9)) return format(decimal, 2)
|
||||
if (decimal.lte(0.98) && !decimal.eq(0)) return format(decimal, 2)
|
||||
return format(decimal, 0)
|
||||
}
|
||||
|
||||
function formatTime(s) {
|
||||
if (s < 60) return format(s) + "s"
|
||||
else if (s < 3600) return formatWhole(Math.floor(s / 60)) + "m " + format(s % 60) + "s"
|
||||
else if (s < 86400) return formatWhole(Math.floor(s / 3600)) + "h " + formatWhole(Math.floor(s / 60) % 60) + "m " + format(s % 60) + "s"
|
||||
else if (s < 31536000) return formatWhole(Math.floor(s / 86400) % 365) + "d " + formatWhole(Math.floor(s / 3600) % 24) + "h " + formatWhole(Math.floor(s / 60) % 60) + "m " + format(s % 60) + "s"
|
||||
else return formatWhole(Math.floor(s / 31536000)) + "y " + formatWhole(Math.floor(s / 86400) % 365) + "d " + formatWhole(Math.floor(s / 3600) % 24) + "h " + formatWhole(Math.floor(s / 60) % 60) + "m " + format(s % 60) + "s"
|
||||
}
|
||||
|
||||
function toPlaces(x, precision, maxAccepted) {
|
||||
x = new Decimal(x)
|
||||
let result = x.toStringWithDecimalPlaces(precision)
|
||||
if (new Decimal(result).gte(maxAccepted)) {
|
||||
result = new Decimal(maxAccepted - Math.pow(0.1, precision)).toStringWithDecimalPlaces(precision)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Will also display very small numbers
|
||||
function formatSmall(x, precision=2) {
|
||||
return format(x, precision, true)
|
||||
}
|
||||
|
||||
function invertOOM(x){
|
||||
let e = x.log10().ceil()
|
||||
let m = x.div(Decimal.pow(10, e))
|
||||
e = e.neg()
|
||||
x = new Decimal(10).pow(e).times(m)
|
||||
|
||||
return x
|
||||
}
|
|
@ -3,7 +3,7 @@ function exponentialFormat(num, precision, mantissa = true) {
|
|||
let e = num.log10().floor();
|
||||
let m = num.div(Decimal.pow(10, e));
|
||||
if(m.toStringWithDecimalPlaces(precision) === 10) {
|
||||
m = new Decimal(1);
|
||||
m = decimalOne;
|
||||
e = e.add(1);
|
||||
}
|
||||
e = (e.gte(1e9) ? format(e, 1) : (e.gte(10000) ? commaFormat(e, 0) : e.toStringWithDecimalPlaces(0)))
|
||||
|
@ -39,11 +39,11 @@ function regularFormat(num, precision) {
|
|||
if (num === null || num === undefined) {
|
||||
return "NaN";
|
||||
}
|
||||
if (num.eq(0)) {
|
||||
if (num.mag < 0.0001) {
|
||||
return (0).toFixed(precision);
|
||||
}
|
||||
if (num.mag < 0.01) {
|
||||
precision = 3;
|
||||
if (num.mag < 0.1 && precision !== 0) {
|
||||
precision = 4;
|
||||
}
|
||||
return num.toStringWithDecimalPlaces(precision);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ function startPlayerBase() {
|
|||
hasNaN: false,
|
||||
hideChallenges: false,
|
||||
showStory: true,
|
||||
forceOneTab: false,
|
||||
points: modInfo.initialStartPoints,
|
||||
subtabs: {},
|
||||
lastSafeTab: (layoutInfo.showTree ? "none" : layoutInfo.startTab)
|
||||
|
@ -72,10 +73,10 @@ function getStartLayerData(layer) {
|
|||
layerdata.unlocked = true;
|
||||
}
|
||||
if (layerdata.total === undefined) {
|
||||
layerdata.total = new Decimal(0);
|
||||
layerdata.total = decimalZero;
|
||||
}
|
||||
if (layerdata.best === undefined) {
|
||||
layerdata.best = new Decimal(0);
|
||||
layerdata.best = decimalZero;
|
||||
}
|
||||
if (layerdata.resetTime === undefined) {
|
||||
layerdata.resetTime = 0;
|
||||
|
@ -91,12 +92,13 @@ function getStartLayerData(layer) {
|
|||
if (layerdata.clickables === undefined) {
|
||||
layerdata.clickables = getStartClickables(layer);
|
||||
}
|
||||
layerdata.spentOnBuyables = new Decimal(0);
|
||||
layerdata.spentOnBuyables = decimalZero;
|
||||
layerdata.upgrades = [];
|
||||
layerdata.milestones = [];
|
||||
layerdata.lastMilestone = null;
|
||||
layerdata.achievements = [];
|
||||
layerdata.challenges = getStartChallenges(layer);
|
||||
layerdata.grid = getStartGrid(layer);
|
||||
return layerdata;
|
||||
}
|
||||
function getStartBuyables(layer) {
|
||||
|
@ -104,7 +106,7 @@ function getStartBuyables(layer) {
|
|||
if (layers[layer].buyables) {
|
||||
for (let id in layers[layer].buyables) {
|
||||
if (isPlainObject(layers[layer].buyables[id])) {
|
||||
data[id] = new Decimal(0);
|
||||
data[id] = decimalZero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,10 +134,23 @@ function getStartChallenges(layer) {
|
|||
}
|
||||
return data;
|
||||
}
|
||||
function getStartGrid(layer) {
|
||||
let data = {};
|
||||
if (! layers[layer].grid) return data
|
||||
if (layers[layer].grid.maxRows === undefined) layers[layer].grid.maxRows=layers[layer].grid.rows
|
||||
if (layers[layer].grid.maxCols === undefined) layers[layer].grid.maxCols=layers[layer].grid.cols
|
||||
|
||||
for (let y = 1; y <= layers[layer].grid.maxRows; y++) {
|
||||
for (let x = 1; x <= layers[layer].grid.maxCols; x++) {
|
||||
data[100*y + x] = layers[layer].grid.getStartData(100*y + x)
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
function fixSave() {
|
||||
let defaultData = getStartPlayer();
|
||||
fixData(defaultData, player);
|
||||
setBuyableAmount("distill", "retort", (getBuyableAmount("distill", "retort") || new Decimal(0)).max(5));
|
||||
setBuyableAmount("distill", "retort", (getBuyableAmount("distill", "retort") || decimalZero).max(5));
|
||||
player.sands.chipping = false;
|
||||
player.rituals.rituals = getRituals();
|
||||
|
||||
|
|
65
style.css
65
style.css
|
@ -283,7 +283,22 @@ h1, h2, h3, b, input {
|
|||
font-size: 10px;
|
||||
}
|
||||
|
||||
/*noinspection CssUnusedSymbol*/
|
||||
.tile {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
border-radius: 15%;
|
||||
border: 2px solid;
|
||||
border-color: rgba(0, 0, 0, 0.125);
|
||||
font-size: 10px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.tile.can:hover {
|
||||
box-shadow: 0 0 10px var(--points);
|
||||
transform: scale(1.1, 1.1);
|
||||
z-index: 7;
|
||||
}
|
||||
|
||||
.upgBig {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
|
@ -1179,3 +1194,51 @@ b, h3 {
|
|||
.ps__rail-y {
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.mark {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
z-index: 10000;
|
||||
margin-left: 0.9em;
|
||||
margin-right: 0.9em;
|
||||
margin-bottom: 1.2em;
|
||||
border-right: 0.3em solid transparent;
|
||||
border-bottom: 0.7em solid transparent;
|
||||
border-left: 0.3em solid transparent;
|
||||
font-size: 10px;
|
||||
overflow:auto
|
||||
}
|
||||
|
||||
.star {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
z-index: 10000;
|
||||
margin-left: 0.9em;
|
||||
margin-right: 0.9em;
|
||||
margin-bottom: 1.2em;
|
||||
border-right: 0.3em solid transparent;
|
||||
border-bottom: 0.7em solid #ffcc00;
|
||||
border-left: 0.3em solid transparent;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.star:before, .star:after {
|
||||
content: "";
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
top: .6em;
|
||||
left: -1em;
|
||||
border-right: 1em solid transparent;
|
||||
border-bottom: 0.7em solid #ffcc00;
|
||||
border-left: 1em solid transparent;
|
||||
transform: rotate(-35deg);
|
||||
}
|
||||
|
||||
.star:after {
|
||||
transform: rotate(35deg);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue