From 19e9115a145dbc2fa3b3586b4983879e9c1e6072 Mon Sep 17 00:00:00 2001
From: Harley White <acamaeda@gmail.com>
Date: Sat, 11 Sep 2021 20:42:59 -0400
Subject: [PATCH] Improved prestige types

---
 changelog.md                     |  1 +
 docs/layer-features.md           |  4 ++-
 js/Demo/layers/c.js              |  3 +-
 js/incrementum.js                | 16 +++++++----
 js/mechanics/prestigeFormulas.js | 48 +++++++++++++++++++++++++++++---
 js/technical/displays.js         | 10 +++++--
 js/utils.js                      |  9 ++++--
 7 files changed, 72 insertions(+), 19 deletions(-)

diff --git a/changelog.md b/changelog.md
index bf1f99a..5d14bbe 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,6 +1,7 @@
 # Incrementum changelog:
 
 - Changed the name to "Incrementum" and replaced all instances of "mod" with "game". game.js has been renamed incrementum.js, and mod.js is now game.js.
+- Added linear and quadratic prestige types, improved the prestige type system.
 - Upgrade effectDisplay and grid tooltip no longer display if they return "".
 
 
diff --git a/docs/layer-features.md b/docs/layer-features.md
index bcf0b11..39876eb 100644
--- a/docs/layer-features.md
+++ b/docs/layer-features.md
@@ -87,6 +87,8 @@ You can make almost any value dynamic by using a function in its place, includin
 - type: **optional**. Determines which prestige formula you use. Defaults to "none".
 
     - "normal": The amount of currency you gain is independent of its current amount (like Prestige). The formula before bonuses is based on `baseResource^exponent`
+    - "linear": The cost is dependent on the total after reset, and increases by `costStep` each time.
+    - "polynomial": The cost is dependent on the total after reset, the cost for the xth point is `quadraticStep*x^2 + linearStep*x + requires`.
     - "static": The cost is dependent on your total after reset. The formula before bonuses is based on `base^(x^exponent)`
     - "custom": You can define everything, from the calculations to the text on the button, yourself. (See more at the bottom)
     - "none": This layer does not prestige, and therefore does not need any of the other features in this section.
@@ -99,7 +101,7 @@ You can make almost any value dynamic by using a function in its place, includin
 
 - exponent: Used as described above.
 
-- base: **sometimes required**. required for "static" layers, used as described above. If absent, defaults to 2. Must be greater than 1.
+- base: **static layers only**. required for "static" layers, used as described above. If absent, defaults to 2. Must be greater than 1.
 
 - 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.)
 
diff --git a/js/Demo/layers/c.js b/js/Demo/layers/c.js
index 5ab4685..79df9fe 100644
--- a/js/Demo/layers/c.js
+++ b/js/Demo/layers/c.js
@@ -24,13 +24,12 @@ addLayer("c", {
         baseAmount() {return player.points}, // Get the current amount of baseResource
         type: "normal", // normal: cost to gain currency depends on amount gained. static: cost depends on how much you already have
         exponent: 0.5, // Prestige currency exponent
-        base: 5, // Only needed for static layers, base of the formula (b^(x^exp))
         roundUpCost: false, // True if the cost needs to be rounded up (use when baseResource is static?)
 
         // For normal layers, gain beyond [softcap] points is put to the [softcapPower]th power
         softcap: new Decimal(1e100), 
         softcapPower: new Decimal(0.5), 
-        canBuyMax() {}, // Only needed for static layers with buy max
+        canBuyMax: true, // Only needed for non-normal layers with buy max
         gainMult() { // Calculate the multiplier for main currency from bonuses
             mult = new Decimal(1)
             if (hasUpgrade(this.layer, 166)) mult = mult.times(2) // These upgrades don't exist
diff --git a/js/incrementum.js b/js/incrementum.js
index f678987..380e4af 100644
--- a/js/incrementum.js
+++ b/js/incrementum.js
@@ -50,12 +50,16 @@ function canReset(layer)
 {	
 	if (layers[layer].canReset!== undefined)
 		return run(layers[layer].canReset, layers[layer])
-	else if(tmp[layer].type == "normal")
-		return tmp[layer].baseAmount.gte(tmp[layer].requires)
-	else if(tmp[layer].type== "static")
-		return tmp[layer].baseAmount.gte(tmp[layer].nextAt) 
-	else 
+	
+	let type = PRESTIGE_TYPES[tmp[layer].type]
+	if (type === undefined)
 		return false
+	if(type.total === false)
+		return tmp[layer].baseAmount.gte(tmp[layer].requires)
+	if (type.total === true)
+		return tmp[layer].baseAmount.gte(tmp[layer].nextAt) 
+
+	return false
 }
 
 function rowReset(row, layer) {
@@ -113,7 +117,7 @@ function doReset(layer, force=false) {
 		
 		if (tmp[layer].baseAmount.lt(tmp[layer].requires)) return;
 		let gain = tmp[layer].resetGain
-		if (tmp[layer].type=="static") {
+		if (PRESTIGE_TYPES[tmp[layer].type] && PRESTIGE_TYPES[tmp[layer].type].total) {
 			if (tmp[layer].baseAmount.lt(tmp[layer].nextAt)) return;
 			gain =(tmp[layer].canBuyMax ? gain : 1)
 		} 
diff --git a/js/mechanics/prestigeFormulas.js b/js/mechanics/prestigeFormulas.js
index cc0dbb8..fd49cc9 100644
--- a/js/mechanics/prestigeFormulas.js
+++ b/js/mechanics/prestigeFormulas.js
@@ -23,7 +23,7 @@ function getNextAt(layer, canMax=false, useType = null) {
 	if (tmp[layer].gainMult.lte(0)) return new Decimal(Infinity)
 	if (tmp[layer].gainExp.lte(0)) return new Decimal(Infinity)
 	
-	if (PRESTIGE_TYPES[type]) return PRESTIGE_TYPES[type].nextAt(layer)
+	if (PRESTIGE_TYPES[type]) return PRESTIGE_TYPES[type].nextAt(layer, canMax)
 	return new Decimal (Infinity)	
 
 }
@@ -37,14 +37,15 @@ const PRESTIGE_TYPES = {
 			gain = gain.times(tmp[layer].directMult)
 			return gain.floor().sub(player[layer].points).add(1).max(1);
 		},
-		nextAt(layer) {
+		nextAt(layer, canMax=false) {
 			if (!tmp[layer].canBuyMax) canMax = false
 			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) cost = cost.ceil()
 			return cost;	
-		}
+		},
+		total: true,
 	},
 	normal: {
 		gain(layer) {
@@ -60,7 +61,45 @@ const PRESTIGE_TYPES = {
 			next = next.root(tmp[layer].gainExp).div(tmp[layer].gainMult).root(tmp[layer].exponent).times(tmp[layer].requires).max(tmp[layer].requires)
 			if (tmp[layer].roundUpCost) next = next.ceil()
 			return next;	
-		}
+		},
+		total: false,
+
+	},
+	linear: {
+		gain(layer) {
+			if ((!tmp[layer].canBuyMax) || tmp[layer].baseAmount.lt(tmp[layer].requires)) return decimalOne
+			let gain = tmp[layer].baseAmount.sub(tmp[layer].requires).div(tmp[layer].costStep).floor().plus(1)
+			gain = gain.times(tmp[layer].gainMult).pow(tmp[layer].gainExp).times(tmp[layer].directMult)
+			return gain.floor().sub(player[layer].points).add(1).max(1);
+		},
+		nextAt(layer, canMax=false) {
+			if (!tmp[layer].canBuyMax) canMax = false
+			let next = player[layer].points.plus((canMax&&tmp[layer].baseAmount.gte(tmp[layer].nextAt))?tmp[layer].resetGain:1).div(tmp[layer].directMult)
+			console.log(format(next))
+			next = next.root(tmp[layer].gainExp).div(tmp[layer].gainMult)
+			return tmp[layer].requires.add(next.sub(1).times(tmp[layer].costStep))
+		},
+		total: true,
+	},
+	quadratic: {
+		gain(layer) {
+			if ((!tmp[layer].canBuyMax) || tmp[layer].baseAmount.lt(tmp[layer].requires)) return decimalOne
+			let c = tmp[layer].requires.sub(tmp[layer].baseAmount)
+			let b = tmp[layer].linearStep
+			let a = tmp[layer].quadraticStep
+			let gain = (b.times(-1).add((b.pow(2).sub(a.times(c).times(4))).sqrt())).div(2).div(a).add(1)
+			gain = gain.times(tmp[layer].gainMult).pow(tmp[layer].gainExp).times(tmp[layer].directMult)
+			return gain.floor().sub(player[layer].points).add(1).max(1);
+		},
+		nextAt(layer, canMax=false) {
+			if (!tmp[layer].canBuyMax) canMax = false
+			let next = player[layer].points.plus((canMax&&tmp[layer].baseAmount.gte(tmp[layer].nextAt))?tmp[layer].resetGain:1).div(tmp[layer].directMult)
+			next = next.root(tmp[layer].gainExp).div(tmp[layer].gainMult)
+			next=next.sub(1)
+			return tmp[layer].requires.add(next.times(tmp[layer].linearStep)).add(next.pow(2).times(tmp[layer].quadraticStep))
+		},
+		total: true,
+
 	},
 	custom: {
 		gain(layer) {
@@ -69,6 +108,7 @@ const PRESTIGE_TYPES = {
 		nextAt(layer) {
 			return layers[layer].getNextAt(canMax)
 		}
+
 	},
 }
 
diff --git a/js/technical/displays.js b/js/technical/displays.js
index 28c8cff..077a8fc 100644
--- a/js/technical/displays.js
+++ b/js/technical/displays.js
@@ -1,12 +1,16 @@
 function prestigeButtonText(layer) {
 	if (layers[layer].prestigeButtonText !== undefined)
 		return run(layers[layer].prestigeButtonText(), layers[layer])
-	if (tmp[layer].type == "normal")
+	let type = PRESTIGE_TYPES[tmp[layer].type]
+	if (type === undefined)
+		return "You need prestige button text!"
+
+	if (type.total === false)
 		return `${player[layer].points.lt(1e3) ? (tmp[layer].resetDescription !== undefined ? tmp[layer].resetDescription : "Reset for ") : ""}+<b>${formatWhole(tmp[layer].resetGain)}</b> ${tmp[layer].resource} ${tmp[layer].resetGain.lt(100) && player[layer].points.lt(1e3) ? `<br><br>Next at ${(tmp[layer].roundUpCost ? formatWhole(tmp[layer].nextAt) : format(tmp[layer].nextAt))} ${tmp[layer].baseResource}` : ""}`
-	if (tmp[layer].type == "static")
+	if (type.total === true)
 		return `${tmp[layer].resetDescription !== undefined ? tmp[layer].resetDescription : "Reset for "}+<b>${formatWhole(tmp[layer].resetGain)}</b> ${tmp[layer].resource}<br><br>${player[layer].points.lt(30) ? (tmp[layer].baseAmount.gte(tmp[layer].nextAt) && (tmp[layer].canBuyMax !== undefined) && tmp[layer].canBuyMax ? "Next:" : "Req:") : ""} ${formatWhole(tmp[layer].baseAmount)} / ${(tmp[layer].roundUpCost ? formatWhole(tmp[layer].nextAtDisp) : format(tmp[layer].nextAtDisp))} ${tmp[layer].baseResource}		
 		`
-	if (tmp[layer].type == "none")
+	if (tmp[layer].type === "none")
 		return ""
     
         return "You need prestige button text"
diff --git a/js/utils.js b/js/utils.js
index 014ad59..859ec57 100644
--- a/js/utils.js
+++ b/js/utils.js
@@ -208,9 +208,12 @@ function prestigeNotify(layer) {
 		}
 	}
 	if (tmp[layer].autoPrestige || tmp[layer].passiveGeneration) return false
-	else if (tmp[layer].type == "static") return tmp[layer].canReset
-	else if (tmp[layer].type == "normal") return (tmp[layer].canReset && (tmp[layer].resetGain.gte(player[layer].points.div(10))))
-	else return false
+
+	let type = PRESTIGE_TYPES[tmp[layer].type]
+	if (type === undefined) return false
+	if (type.total === true) return tmp[layer].canReset
+	if (type.total === false) return (tmp[layer].canReset && (tmp[layer].resetGain.gte(player[layer].points.div(10))))
+	return false
 }
 
 function notifyLayer(name) {