diff --git a/docs/!general-info.md b/docs/!general-info.md index f5a7287..ceb90dd 100644 --- a/docs/!general-info.md +++ b/docs/!general-info.md @@ -39,4 +39,5 @@ All display text can be basic HTML instead (But you can't use most Vue features - [Custom Tab Layouts](custom-tab-layouts.md): An optional way to give your tabs a different layout. You can even create entirely new components to use. - [Subtabs and Microtabs](subtabs-and-microtabs.md): Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs. +- [Achievements](milestones.md): How to create achievements for a layer (or for the whole game). - [Updating TMT](updating-tmt.md): Using Github Desktop to update your mod's version of TMT. diff --git a/docs/achievements.md b/docs/achievements.md new file mode 100644 index 0000000..b03d2c5 --- /dev/null +++ b/docs/achievements.md @@ -0,0 +1,55 @@ +#Achievements + +Achievements are awarded to the player when they meet a certain goal, and give some benefit. +Currently, they are pretty basic, but additional features will be added later to help. + +You can make global achievements by putting them in a side layer (make its row "side" instead of a number) + +Useful functions for dealing with achievements and implementing their effects: + +- hasAchievement(layer, id): determine if the player has the Achievement +- achievementEffect(layer, id): Returns the current effects of the achievement, if any + + +Achievements should be formatted like this: + +```js + achievements: { + rows: # of rows + cols: # of columns + 11: { + name: "Blah", + more features + } + etc + } +``` + +Each achievement should have an id where the first digit is the row and the second digit is the column. +Individual achievement can have these features: + +- name: **optional**, displayed at the top of the achievement. The only visible text. + It can also be a function that returns updating text. Can use basic HTML. + +- 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. + +- 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. + +- unlocked(): **optional**, A function returning a bool to determine if the achievement is visible or not. Default is unlocked. + +- onComplete() - **optional**, this function will be called when the achievement is completed. + +- style: **Optional**, Applies CSS to this achievement, in the form of an object where the keys are CSS attributes, + and the values are the values for those attributes (both as strings) + +- 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. \ No newline at end of file diff --git a/docs/custom-tab-layouts.md b/docs/custom-tab-layouts.md index b387dbb..c97016a 100644 --- a/docs/custom-tab-layouts.md +++ b/docs/custom-tab-layouts.md @@ -36,14 +36,14 @@ These are the existing components, but you can create more in v.js: - 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. -- upgrades, milestones, challs: Display the upgrades, milestones, and challenges for a layer, as appropriate. +- upgrades, milestones, challs, achievements: Display the upgrades, milestones, and challenges for a layer, as appropriate. - buyables, clickables: Display all of the buyables/clickables for this layer, as appropriate. The argument optional, and is the size of the boxes in pixels. - microtabs: Display a set of subtabs for an area. The argument is the name of the set of microtabs in the "microtabs" feature. -- upgrade, milestone, chall, buyable: An individual upgrade, challenge, etc. The argument is the id. +- upgrade, milestone, chall, 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. - bar: Display a bar. The argument is the id of the bar to display. diff --git a/docs/layer-features.md b/docs/layer-features.md index ef8368c..646d1d5 100644 --- a/docs/layer-features.md +++ b/docs/layer-features.md @@ -90,6 +90,10 @@ Key: - bars: Display some information as a progress bar, gague, or similar. They are highly customizable, and can be vertical as well. [Explanations are in a separate file.](bars.md) +- 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! + [Explanations are in a separate file.](achievements.md) + + # Prestige formula features - baseResource: The name of the resource that determines how much of the main currency you gain on reset. diff --git a/docs/milestones.md b/docs/milestones.md index 615abab..ff36b7e 100644 --- a/docs/milestones.md +++ b/docs/milestones.md @@ -1,6 +1,6 @@ #Milestones -Milestones should be formatted like this: +Milestones are awarded to the player when they meet a certain goal, and give some benefit. Milestones should be formatted like this: ```js milestones: { @@ -21,7 +21,7 @@ Milestone features: - effectDesc: A string describing the reward for having the milestone. *You will have to implement the reward elsewhere.* It can also be a function that returns updating text. Can use basic HTML. -- done(): A function returning a boolean to determine if the milestone has been fulfilled. +- done(): A function returning a boolean to determine if the milestone should be awarded. - toggles: *optional*, Creates toggle buttons that appear on the milestone when it is unlocked. The toggles can toggle a given boolean value in a layer. diff --git a/docs/upgrades.md b/docs/upgrades.md index 0784210..ce47011 100644 --- a/docs/upgrades.md +++ b/docs/upgrades.md @@ -1,7 +1,5 @@ # Upgrades -Upgrades are stored in the following format: - Useful functions for dealing with Upgrades and implementing their effects: - hasUpgrade(layer, id): determine if the player has the upgrade @@ -9,6 +7,7 @@ Useful functions for dealing with Upgrades and implementing their effects: Hint: Basic point gain is calculated in game.js's "getPointGain". +Upgrades are stored in the following format: ```js upgrades: { diff --git a/js/game.js b/js/game.js index 1762c09..0b799f9 100644 --- a/js/game.js +++ b/js/game.js @@ -17,9 +17,9 @@ let modInfo = { // Set your version in num and name, but leave the tmt values so people know what version it is let VERSION = { num: "2.0", - name: "Finally making some progress!", + name: "Pinnacle of Achievement Mountain", tmtNum: "2.0", - tmtName: "Finally making some progress!" + tmtName: "Pinnacle of Achievement Mountain" } // Determines if it should show points/sec @@ -182,6 +182,7 @@ function doReset(layer, force=false) { addPoints(layer, gain) updateMilestones(layer) + updateAchievements(layer) if (!player[layer].unlocked) { player[layer].unlocked = true; @@ -312,6 +313,7 @@ function gameLoop(diff) { for (layer in layers){ if (layers[layer].milestones) updateMilestones(layer); + if (layers[layer].achievements) updateAchievements(layer) } if (player.hasNaN&&!NaNalert) { diff --git a/js/layerSupport.js b/js/layerSupport.js index f5d4383..8aa1cc2 100644 --- a/js/layerSupport.js +++ b/js/layerSupport.js @@ -52,6 +52,16 @@ function updateLayers(){ } } } + if (layers[layer].achievements){ + for (thing in layers[layer].achievements){ + if (!isNaN(thing)){ + layers[layer].achievements[thing].id = thing + layers[layer].achievements[thing].layer = layer + if (layers[layer].achievements[thing].unlocked === undefined) + layers[layer].achievements[thing].unlocked = true + } + } + } if (layers[layer].challenges){ for (thing in layers[layer].challenges){ if (!isNaN(thing)){ diff --git a/js/layers.js b/js/layers.js index 6401378..b760785 100644 --- a/js/layers.js +++ b/js/layers.js @@ -576,8 +576,8 @@ addLayer("a", { }}, color: "yellow", requires: new Decimal (1), - resource: "idk", - baseResource: "candies", + resource: "achievement power", + baseResource: "achievements", baseAmount() {return player.points}, type: "normal", // A "Custom" type which is effectively static exponent: 0.5, @@ -589,9 +589,35 @@ addLayer("a", { }, row: "side", layerShown() {return true}, - tooltipUnlocked() { // Optional, tooltip displays when the layer is locked - return ("YEETS") + tooltip() { // Optional, tooltip displays when the layer is locked + return ("Achievements") }, + achievements: { + rows: 2, + cols: 3, + 11: { + name: "Get me!", + done() {return true}, // This one is a freebie + goalTooltip: "How did this happen?", // Shows when achievement is not completed + doneTooltip: "You did it!", // Showed when the achievement is completed + }, + 12: { + name: "Impossible!", + done() {return false}, + goalTooltip: "Mwahahaha!", // Shows when achievement is not completed + doneTooltip: "HOW????", // Showed when the achievement is completed + }, + 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.", // Showed when the achievement is completed + onComplete() {console.log("Bork bork bork!")} + }, + }, + tabFormat: [ + "main-display", "blank", "blank", "achievements", + ] }, ) diff --git a/js/utils.js b/js/utils.js index c53f421..aff4914 100644 --- a/js/utils.js +++ b/js/utils.js @@ -93,6 +93,7 @@ function getStartPlayer() { playerdata[layer].spentOnBuyables = new Decimal(0) playerdata[layer].upgrades = [] playerdata[layer].milestones = [] + playerdata[layer].achievements = [] playerdata[layer].challenges = getStartChallenges(layer) if (layers[layer].tabFormat && !Array.isArray(layers[layer].tabFormat)) { playerdata.subtabs[layer] = {} @@ -368,6 +369,10 @@ function hasMilestone(layer, id){ return (player[layer].milestones.includes(toNumber(id)) || player[layer].milestones.includes(id.toString())) } +function hasAchievement(layer, id){ + return (player[layer].achievements.includes(toNumber(id)) || player[layer].achievements.includes(id.toString())) +} + function hasChallenge(layer, id){ return (player[layer].challenges[id]) } @@ -404,6 +409,9 @@ function buyableEffect(layer, id){ return (tmp[layer].buyables[id].effect) } +function achievementEffect(layer, id){ + return (tmp[layer].achievements[id].effect) +} function canAffordPurchase(layer, thing, cost) { if (thing.currencyInternalName){ @@ -540,6 +548,15 @@ function updateMilestones(layer){ } } +function updateAchievements(layer){ + for (id in layers[layer].achievements){ + if (!isNaN(id) && !(player[layer].achievements.includes(id)) && layers[layer].achievements[id].done()) { + player[layer].achievements.push(id) + if (layers[layer].achievements[id].onComplete) layers[layer].achievements[id].onComplete() + } + } +} + function addTime(diff, layer) { let data = player let time = data.timePlayed diff --git a/js/v.js b/js/v.js index 7c8cdb1..2fa7637 100644 --- a/js/v.js +++ b/js/v.js @@ -291,6 +291,36 @@ function loadVue() { }) + Vue.component('achievements', { + props: ['layer'], + template: ` +