cookie clicker but bigger
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

380 line
8.5 KiB

  1. "use strict";
  2. let belongings = {};
  3. let ownedUpgrades = {};
  4. let remainingUpgrades = [];
  5. let resources = {};
  6. let updateRate = 60;
  7. function calculateProductivity() {
  8. let productivity = 0;
  9. for (const [key, value] of Object.entries(belongings)) {
  10. productivity += productivityOf(key);
  11. }
  12. return productivity;
  13. }
  14. // here's where upgrades will go :3
  15. function productivityMultiplierOf(type) {
  16. let base = 1;
  17. for (const [key, value] of Object.entries(upgrades)) {
  18. if (!ownedUpgrades[key]) {
  19. continue;
  20. }
  21. if (value.effect.type == "prod-2x") {
  22. if (value.effect.target == type) {
  23. base *= 2;
  24. }
  25. }
  26. }
  27. return base;
  28. }
  29. function productivityOf(type) {
  30. let baseProd = buildings[type].prod;
  31. let prod = baseProd * productivityMultiplierOf(type);
  32. return prod * belongings[type].count;
  33. }
  34. function costOfBuilding(type) {
  35. let baseCost = buildings[type].cost
  36. let countCost = baseCost * Math.pow(1.15, belongings[type].count);
  37. return Math.round(countCost);
  38. }
  39. function buyBuilding(type) {
  40. let cost = costOfBuilding(type);
  41. if (resources.food >= cost) {
  42. belongings[type].count += 1;
  43. resources.food -= cost;
  44. }
  45. }
  46. // update stuff
  47. function updateResources() {
  48. addResources();
  49. displayResources();
  50. displayBuildings();
  51. displayUpgrades();
  52. setTimeout(updateResources, 1000/updateRate);
  53. }
  54. function addResources() {
  55. resources.food += calculateProductivity() * 1 / updateRate;
  56. }
  57. function displayResources() {
  58. document.getElementById("resource-food").innerText = "Food: " + render(resources.food);
  59. document.getElementById("productivity").innerText = (Math.round(calculateProductivity() * 10) / 10) + " food/sec";
  60. }
  61. function displayBuildings() {
  62. for (const [key, value] of Object.entries(belongings)) {
  63. let button = document.querySelector("#building-" + key);
  64. document.querySelector("#building-" + key + " > .building-button-name").innerText = value.count + " " + (value.count == 1 ? buildings[key].name : buildings[key].plural);
  65. document.querySelector("#building-" + key + " > .building-button-cost").innerText = costOfBuilding(key) + " food";
  66. if (costOfBuilding(key) > resources.food) {
  67. button.classList.add("building-button-disabled");
  68. } else {
  69. button.classList.remove("building-button-disabled");
  70. }
  71. }
  72. }
  73. function canAfford(cost) {
  74. for (const [resource, amount] of Object.entries(cost)) {
  75. if (resources[resource] < amount) {
  76. return false;
  77. }
  78. }
  79. return true;
  80. }
  81. function spend(cost) {
  82. for (const [resource, amount] of Object.entries(cost)) {
  83. resources[resource] -= amount;
  84. }
  85. }
  86. function displayUpgrades() {
  87. for (let id of remainingUpgrades) {
  88. let button = document.querySelector("#upgrade-" + id);
  89. if (ownedUpgrades[id]) {
  90. button.style.display = "none";
  91. continue;
  92. }
  93. if (upgradeAvailable(id)) {
  94. button.classList.remove("upgrade-button-inactive");
  95. } else {
  96. button.classList.add("upgrade-button-inactive");
  97. }
  98. }
  99. // now we throw out stuff
  100. for (let i = remainingUpgrades.length-1; i >= 0; i--) {
  101. if (ownedUpgrades[remainingUpgrades[i]]) {
  102. remainingUpgrades.splice(i, 1);
  103. }
  104. }
  105. }
  106. function buyUpgrade(id) {
  107. if (ownedUpgrades[id]) {
  108. return;
  109. }
  110. let upgrade = upgrades[id];
  111. if (!canAfford(upgrade.cost)) {
  112. return;
  113. }
  114. spend(upgrade.cost);
  115. ownedUpgrades[id] = true;
  116. }
  117. function eatMicro() {
  118. resources.food += productivityMultiplierOf("micro");
  119. }
  120. // setup stuff lol
  121. // we'll initialize the dict of buildings we can own
  122. function setup() {
  123. initializeData();
  124. createButtons();
  125. createDisplays();
  126. registerListeners();
  127. }
  128. function initializeData() {
  129. for (const [key, value] of Object.entries(buildings)) {
  130. belongings[key] = {};
  131. belongings[key].count = 0;
  132. }
  133. for (const [key, value] of Object.entries(upgrades)) {
  134. ownedUpgrades[key] = false;
  135. }
  136. }
  137. function registerListeners() {
  138. document.querySelectorAll(".building-button").forEach(function(button) {
  139. let id = button.id.replace("building-", "");
  140. button.addEventListener("click", function() { buyBuilding(id); });
  141. });
  142. document.querySelector("#tasty-micro").addEventListener("click", eatMicro);
  143. }
  144. function createButtons() {
  145. createBuildings();
  146. createUpgrades();
  147. }
  148. function createBuildings() {
  149. let container = document.querySelector("#buildings-area");
  150. for (const [key, value] of Object.entries(buildings)) {
  151. let button = document.createElement("div");
  152. button.classList.add("building-button");
  153. button.id = "building-" + key;
  154. let buttonName = document.createElement("div");
  155. buttonName.classList.add("building-button-name");
  156. let buttonCost = document.createElement("div");
  157. buttonCost.classList.add("building-button-cost");
  158. button.appendChild(buttonName);
  159. button.appendChild(buttonCost);
  160. container.appendChild(button);
  161. }
  162. }
  163. function upgradeAvailable(id) {
  164. if (ownedUpgrades[id]) {
  165. return false;
  166. }
  167. if (!canAfford(upgrades[id].cost)) {
  168. return false;
  169. }
  170. for (const [type, reqs] of Object.entries(upgrades[id].prereqs)) {
  171. if (type == "buildings") {
  172. for (const [building, amount] of Object.entries(upgrades[id].prereqs[type])) {
  173. if (belongings[building].count < amount) {
  174. return false;
  175. }
  176. }
  177. }
  178. }
  179. return true;
  180. }
  181. function createUpgrades() {
  182. let container = document.querySelector("#upgrades-list");
  183. for (const [key, value] of Object.entries(upgrades)) {
  184. remainingUpgrades.push(key);
  185. let button = document.createElement("div");
  186. button.classList.add("upgrade-button");
  187. button.id = "upgrade-" + key;
  188. let buttonName = document.createElement("div");
  189. buttonName.classList.add("upgrade-button-name");
  190. buttonName.innerText = value.name;
  191. button.appendChild(buttonName);
  192. button.addEventListener("mousemove", function(e) { upgradeTooltip(key, e); });
  193. button.addEventListener("mouseleave", function() { upgradeTooltipRemove(); });
  194. button.addEventListener("click", function() { buyUpgrade(key); });
  195. container.appendChild(button);
  196. }
  197. }
  198. function createDisplays() {
  199. let resourceList = document.querySelector("#resource-list");
  200. for (const [key, value] of Object.entries(resourceTypes)) {
  201. resources[key] = 0;
  202. let line = document.createElement("div");
  203. line.id = "resource-" + key;
  204. resourceList.appendChild(line);
  205. }
  206. }
  207. function renderLine(line) {
  208. let div = document.createElement("div");
  209. div.innerText = line.text;
  210. if (line.valid !== undefined) {
  211. if (line.valid) {
  212. div.classList.add("cost-met");
  213. } else {
  214. div.classList.add("cost-unmet");
  215. }
  216. }
  217. return div;
  218. }
  219. function renderLines(lines) {
  220. let divs = [];
  221. for (let line of lines) {
  222. divs.push(renderLine(line));
  223. }
  224. return divs;
  225. }
  226. function renderCost(cost) {
  227. let list = [];
  228. list.push({
  229. "text": "Cost:"
  230. });
  231. for (const [key, value] of Object.entries(cost)) {
  232. list.push({
  233. "text": value + " " + resourceTypes[key].name,
  234. "valid": resources[key] >= value
  235. });
  236. }
  237. return renderLines(list);
  238. }
  239. function renderPrereqs(prereqs) {
  240. let list = [];
  241. list.push({
  242. "text": "Own:"
  243. });
  244. for (const [key, value] of Object.entries(prereqs)) {
  245. if (key == "buildings") {
  246. for (const [id, amount] of Object.entries(prereqs.buildings)) {
  247. list.push({
  248. "text": buildings[id].name + " x" + amount,
  249. "valid": belongings[id].count >= amount
  250. });
  251. }
  252. }
  253. }
  254. return renderLines(list);
  255. }
  256. function upgradeTooltip(id, event) {
  257. let tooltip = document.querySelector("#upgrade-tooltip");
  258. tooltip.style.setProperty("display", "inline-block");
  259. let tooltipDesc = document.querySelector("#upgrade-tooltip-desc");
  260. tooltipDesc.innerText = upgrades[id].desc;
  261. let tooltipEffect = document.querySelector("#upgrade-tooltip-effect");
  262. tooltipEffect.innerText = upgrade_types[upgrades[id].effect.type].desc(buildings[upgrades[id].effect.target].name);
  263. let tooltipCost = document.querySelector("#upgrade-tooltip-cost");
  264. replaceChildren(tooltipCost, renderCost(upgrades[id].cost));
  265. let tooltipPrereqs = document.querySelector("#upgrade-tooltip-prereqs");
  266. replaceChildren(tooltipPrereqs, renderPrereqs(upgrades[id].prereqs));
  267. let yOffset = tooltip.parentElement.getBoundingClientRect().y;
  268. let yTrans = Math.round(event.clientY - yOffset);
  269. tooltip.style.setProperty("transform", "translate(-220px, " + yTrans + "px)");
  270. }
  271. function upgradeTooltipRemove() {
  272. let tooltip = document.querySelector("#upgrade-tooltip");
  273. tooltip.style.setProperty("display", "none");
  274. }
  275. window.onload = function() {
  276. setup();
  277. setTimeout(updateResources, 1000/updateRate);
  278. }