Flowr QoL

A QoL script for Flowr!

  1. // ==UserScript==
  2. // @name Flowr QoL
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0.0
  5. // @description A QoL script for Flowr!
  6. // @author Suprinister
  7. // @match https://flowr.fun/*
  8. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  9. // @license Apache-2.0
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. Colors.rarities[9] = {"name":"Fabled","color":"#ff5500","border":"#cf4500","fancy":{"border":"#cf4500","hue":10,"light":60,"sat":95,"spread":20,"period":1.5}};
  17.  
  18. const ogColors = JSON.parse(JSON.stringify(Colors.rarities));
  19.  
  20. let pressedG = false;
  21.  
  22. window.addEventListener('keydown', event => {
  23. if (event.code === 'KeyG') {
  24. pressedG = true;
  25. };
  26. });
  27.  
  28. window.addEventListener('keyup', event => {
  29. if (event.code === 'KeyG') {
  30. pressedG = false;
  31. };
  32. });
  33.  
  34. let performanceMode = (localStorage.getItem('performanceMode') ?? 'false') === 'false' ? false : true;
  35.  
  36. if (performanceMode) {
  37. for (let i = 0; i < Colors.rarities.length; i++) {
  38. delete Colors.rarities[i].fancy;
  39. };
  40.  
  41. blendAmount = function(p) {
  42. return 0;
  43. };
  44. };
  45.  
  46. for (let i = 7; i <= 12; i++) {
  47. settingsMenu.options[i].screenPosition.y += 50;
  48. };
  49.  
  50. settingsMenu.options.splice(7, 0, {
  51. changeTime: 0,
  52. name: 'Performance mode',
  53. screenPosition: {
  54. x: 125,
  55. y: 386,
  56. w: 28,
  57. h: 28
  58. },
  59. state: performanceMode,
  60. toggleFn(state) {
  61. performanceMode = state;
  62. localStorage.setItem('performanceMode', state);
  63.  
  64. if (state) {
  65. for (let i = 0; i < Colors.rarities.length; i++) {
  66. delete Colors.rarities[i].fancy;
  67. };
  68.  
  69. blendAmount = function(p) {
  70. return 0;
  71. };
  72. } else {
  73. Colors.rarities = JSON.parse(JSON.stringify(ogColors));
  74.  
  75. blendAmount = function(p) {
  76. return Math.max(0, 1 - p.ticksSinceLastDamaged / 166.5);
  77. };
  78. };
  79. },
  80. type: 'toggle'
  81. });
  82.  
  83. settingsMenu.h += 50;
  84. settingsMenu.offset = -settingsMenu.h - 40;
  85. settingsMenu.targetOffset = -settingsMenu.h - 40;
  86.  
  87. Flower.prototype.draw = function() {
  88. if(this.id !== window.selfId){
  89. this.updateInterpolate();
  90. }
  91.  
  92. this.updatePetsAndProjectiles();
  93.  
  94. for(let i = 0; i < this.deadProjectiles.length; i++){
  95. if(toRender({x: this.deadProjectiles[i].render.x, y: this.deadProjectiles[i].render.y, radius: this.deadProjectiles[i].radius}, window.camera) === true){
  96. this.deadProjectiles[i].draw();
  97. }
  98. this.deadProjectiles[i].updateTimer();
  99. }
  100.  
  101.  
  102. this.ticksSinceLastDamaged += dt;
  103. if(this.ticksSinceLastDamaged > 666){
  104. this.beforeStreakHp = this.hp;
  105. }
  106. renderHpBar({
  107. x: this.render.headX,
  108. y: this.render.headY - this.render.radius / 3,
  109. radius: this.render.radius,
  110. hp: this.render.hp,
  111. maxHp: this.maxHp,
  112. shield: this.render.shield,
  113. beforeStreakHp: this.render.beforeStreakHp,
  114. flowerName: this.name,
  115. flowerUsername: this.username
  116. },this);
  117.  
  118. if(this.petalAlpha !== undefined){
  119. ctx.globalAlpha = this.petalAlpha;
  120. }
  121.  
  122. if (this.id == window.selfId){
  123. petalReloadData = {};
  124. petalHpData = {};
  125. }
  126. for(let i = 0; i < this.petals.length; i++){
  127. let petal = this.petals[i];
  128. if(toRender({x: petal.render.x, y: petal.render.y, radius: petal.radius}, window.camera) === true){
  129. if (!petal.dead && pressedG) {
  130. ctx.beginPath();
  131.  
  132. ctx.font = '900 12px Ubuntu';
  133. ctx.lineWidth = 5;
  134. ctx.globalAlpha = 1;
  135. ctx.fillStyle = Colors.rarities[petal.rarity].color;
  136. ctx.strokeStyle = 'black';
  137. ctx.strokeText(Colors.rarities[petal.rarity].name, petal.render.x, petal.render.y + petal.radius * 1.75 + 7);
  138. ctx.fillText(Colors.rarities[petal.rarity].name, petal.render.x, petal.render.y + petal.radius * 1.75 + 7);
  139.  
  140. ctx.globalAlpha = 0.5;
  141. ctx.arc(petal.render.x, petal.render.y, petal.radius * 1.75, 0, 2 * Math.PI);
  142. ctx.fill();
  143.  
  144. ctx.globalAlpha = 1;
  145.  
  146. ctx.closePath();
  147. };
  148. petal.draw();
  149. }
  150. if (this.id == window.selfId){
  151. let containerId = petal.petalContainerId;
  152. if (!petalReloadData[containerId]){
  153. if (petal.dead){
  154. petalReloadData[containerId] = {
  155. reload: petal.render.reload/petal.maxReload
  156. }
  157. }
  158. }
  159. else{
  160. if (petalReloadData[containerId].reload < petal.render.reload/petal.maxReload && petal.dead){
  161. petalReloadData[containerId].reload = petal.render.reload/petal.maxReload;
  162. }
  163. }
  164.  
  165. if (!petalHpData[containerId]){
  166. if (!petal.dead){
  167. petalHpData[containerId] = {
  168. hp: petal.render.hp/petal.maxHp,
  169. count: 1
  170. }
  171. }
  172. }
  173. else{
  174. if(!petal.dead){
  175. petalHpData[containerId].hp = (petalHpData[containerId].count * petalHpData[containerId].hp + petal.render.hp/petal.maxHp)/(petalHpData[containerId].count+1);
  176. petalHpData[containerId].count++;
  177. }
  178. }
  179. }
  180. petal.updateTimer();
  181. }
  182. ctx.globalAlpha = 1;
  183. if(toRender({x: this.render.headX, y: this.render.headY, radius: this.render.radius}, window.camera) === true){
  184. this.drawFlower(this.render.headX, this.render.headY, this.radius);
  185. }
  186. if (this.lightnings){
  187. if (this.lightnings.length > 0){
  188. this.lightnings = this.lightnings.filter((e) => time < (e.time+600))
  189. ctx.strokeStyle = "#97f0ea";
  190. ctx.lineWidth = 3;
  191. for(let i of this.lightnings){
  192. ctx.globalAlpha = (1-(time-i.time)/700);
  193. ctx.beginPath();
  194. for(let j = 0; j < i.renderData.length; j++){
  195. ctx.lineTo(i.renderData[j].x, i.renderData[j].y);
  196. }
  197. ctx.stroke();
  198. ctx.closePath();
  199. }
  200. }
  201. }
  202. }
  203.  
  204. PetalContainer.prototype.draw = function(inGame, number, crafting = false) {
  205. this.updateInterpolate();
  206.  
  207. if(this.toOscillate === true && toRender({x: this.render.x, y: this.render.y, radius: this.radius}, window.camera) === false && this.toSkipCulling !== true){
  208. return;
  209. }
  210.  
  211. const renderAnimationTimer = smoothstep(this.spawnAnimation);
  212.  
  213. let scale = 1;
  214. let rotation = 0;
  215.  
  216. ctx.lastTransform = ctx.getTransform();
  217. ctx.translate(this.render.x, this.render.y);
  218. scale *= renderAnimationTimer * this.render.w / 50;
  219.  
  220. rotation -= (1 - renderAnimationTimer) * Math.PI * 3;
  221. if(this.isDraggingPetalContainer === true){
  222. if(this.draggingTimer === undefined)this.draggingTimer = 0;
  223. this.draggingTimer += 1000 / 30 * dt/16.66;
  224. rotation += Math.sin(this.draggingTimer / 280) * 0.28;
  225. if(this !== draggingPetalContainer){
  226. this.isDraggingPetalContainer = false;
  227. this.undraggingPetalContainerTimer = 30;
  228. this.lastDraggingAngle = Math.sin(this.draggingTimer / 280) * 0.28;
  229. }
  230. } else if(this.undraggingPetalContainerTimer !== undefined){
  231. if(this.interval === undefined){
  232. this.lastDraggingAngle = interpolate(this.lastDraggingAngle, 0, 0.15);
  233. rotation += this.lastDraggingAngle;
  234. this.undraggingPetalContainerTimer--;
  235. if(this.undraggingPetalContainerTimer < 0){
  236. delete this.undraggingPetalContainerTimer;
  237. delete this.lastDraggingAngle;
  238. delete this.draggingTimer;
  239. }
  240. }
  241. }
  242.  
  243. if(this.toOscillate === true){
  244. scale *= 1+Math.sin(performance.now()/ 1000 / .076)/52;
  245. rotation += this.angleOffset;
  246. }
  247.  
  248. if(rotation !== 0)ctx.rotate(rotation);
  249. if(scale !== 1)ctx.scale(scale, scale);
  250. if(this.toOscillate === true && this.isDisplayPetalContainer !== true){
  251. ctx.globalAlpha = 0.3;
  252. ctx.fillStyle = 'black';
  253. ctx.beginPath();
  254. ctx.roundRect(-30, -30, 60, 60, 5);
  255. ctx.fill();
  256. ctx.closePath();
  257. ctx.globalAlpha = 1;
  258. }
  259.  
  260. ctx.lineWidth = 4.5;
  261.  
  262. currentBiome = biomeManager.getCurrentBiome();
  263. this.greyed = (this.customBiome !== undefined && window.officialBiomes.includes(currentBiome) === true) || (crafting && this.amount < 5);
  264. if(this.type === 'soccer petal' && currentBiome !== 'Soccer!') this.greyed = true;
  265. if(this.greyed){
  266. ctx.globalAlpha = 0.3;
  267. ctx.fillStyle = "#525252";
  268. ctx.strokeStyle = "#404040";
  269. } else {
  270. ctx.fillStyle = Colors.rarities[this.rarity].color;
  271. ctx.strokeStyle = Colors.rarities[this.rarity].border;
  272. }
  273.  
  274. if((currentBiome === '1v1' && this.generatedIn1v1 === false) || (currentBiome !== '1v1' && this.generatedIn1v1 === true)){
  275. if(pregeneratedPvpStats === undefined) generatePvpStats();
  276. let statsToTake;
  277. if(currentBiome === '1v1'){
  278. statsToTake = pregeneratedPvpStats;
  279. } else {
  280. statsToTake = Stats;
  281. }
  282.  
  283. if(this.petals.length !== 0 && this.petals[0].team !== undefined){
  284. statsToTake = statsToTake.enemies;
  285. } else {
  286. statsToTake = statsToTake.petals;
  287. }
  288.  
  289. let petalAmount = 0;
  290. if(statsToTake[this.type] !== undefined && statsToTake[this.type][this.rarity] !== undefined){
  291. const petalLayout = statsToTake[this.type][this.rarity].petalLayout;
  292. if(petalLayout === undefined) petalAmount = 1;
  293. else {
  294. for(let i = 0; i < petalLayout.length; i++){
  295. for(let j = 0; j < petalLayout[i].length; j++){
  296. petalAmount++;
  297. }
  298. }
  299. }
  300. } else {
  301. petalAmount = 1;
  302. }
  303.  
  304. if(petalAmount < this.petals.length){
  305. this.petals.length = petalAmount;
  306. } else {
  307. while(this.petals.length < petalAmount){
  308. this.petals.push(new Petal(this.petals[Math.floor(Math.random() * this.petals.length)]));
  309. }
  310. }
  311. this.generatedIn1v1 = !this.generatedIn1v1;
  312. }
  313.  
  314. if (Colors.rarities[this.rarity].fancy !== undefined){
  315. const gradientFill = ctx.createLinearGradient(-30, -30, 30, 30);
  316. createFancyGradient(gradientFill, this.rarity);
  317. ctx.fillStyle = gradientFill;
  318. ctx.strokeStyle = Colors.rarities[this.rarity].fancy.border;
  319. }
  320.  
  321. ctx.beginPath();
  322. ctx.roundRect(-25, -25, 50, 50, .25);
  323. ctx.fill();
  324. ctx.stroke();
  325. ctx.closePath();
  326.  
  327. if(Colors.rarities[this.rarity].fancy !== undefined && Colors.rarities[this.rarity].fancy.stars !== undefined){
  328. ctx.save();
  329. if(!this.stars){
  330. this.stars = [];
  331. for(let starnum = 0; starnum < Colors.rarities[this.rarity].fancy.stars; starnum++){
  332. this.stars.push({x: Math.random()*50 - 25, y: Math.random()*50 - 25})
  333. }
  334. }
  335. ctx.shadowBlur = 20;
  336. ctx.shadowColor = "white";
  337. ctx.fillStyle = "#ffffff";
  338. for(let star of this.stars){
  339. star.x+=0.1;
  340. star.y+=0.1;
  341. if(star.x >30 || star.y >30){
  342. star.x = Math.random()*800 - 20 - 30;
  343. star.y = -30;
  344.  
  345. }
  346.  
  347. if(star.x < -30 || star.x > 30 || star.y < -30 || star.y > 30){
  348. continue;
  349. }
  350. ctx.beginPath();
  351.  
  352. var grad = ctx.createRadialGradient(star.x, star.y,15,star.x, star.y,0);
  353. grad.addColorStop(0,"transparent");
  354. grad.addColorStop(0.8,`rgba(255,255,255,${(Math.cos(Date.now()/600+ star.x/30 + star.y/30) + 1)*0.8})`);
  355. grad.addColorStop(1,"white");
  356.  
  357. ctx.fillStyle = grad;
  358. ctx.globalAlpha = 0.3;
  359.  
  360. ctx.fillRect(-20.5, -20.5, 41,41);
  361. ctx.globalAlpha = 1;
  362. if(star.x < 20.5 && star.x > -20.5 && star.y < 20.5 && star.y > -20.5){
  363.  
  364. ctx.fillStyle = "#fff";
  365.  
  366. ctx.arc(star.x, star.y, 1, 0, 2*Math.PI);
  367. ctx.fill();
  368. }
  369. ctx.closePath();
  370. }
  371. ctx.restore();
  372. }
  373.  
  374. if (inGame){
  375. if (petalReloadData[number]){
  376. if (petalReloadData[number].reload > 0.001 && petalReloadData[number].reload < 0.999){
  377. ctx.save();
  378. ctx.beginPath();
  379. ctx.roundRect(-25, -25, 50, 50, .25);
  380. ctx.clip();
  381.  
  382. ctx.globalAlpha = 0.3;
  383. ctx.lineCap = "butt";
  384.  
  385. let offset = (1-Math.pow(petalReloadData[number].reload, 0.7))*Math.PI*6 + this.randomAngle;
  386.  
  387. ctx.strokeStyle = "#000000";
  388. ctx.lineWidth = 50;
  389. ctx.beginPath();
  390. ctx.arc(0, 0, 25, offset - Math.PI * 2 * smoothstep(petalReloadData[number].reload), offset);
  391. ctx.stroke();
  392. ctx.closePath();
  393.  
  394. ctx.restore();
  395. }
  396. }else if(petalHpData[number]){
  397. if (petalHpData[number].hp > 0.001 && petalHpData[number].hp < 0.999){
  398. ctx.save();
  399. ctx.beginPath();
  400. ctx.roundRect(-23, -23, 46, 46, .25);
  401. ctx.clip();
  402.  
  403. ctx.globalAlpha = 0.3;
  404. ctx.lineCap = "butt";
  405.  
  406. ctx.fillStyle = "#000000";
  407. ctx.beginPath();
  408. ctx.rect(-25, -25, 50, 50 * (1-petalHpData[number].hp));
  409. ctx.fill();
  410. ctx.closePath();
  411.  
  412. ctx.restore();
  413. }
  414.  
  415. }
  416. }
  417.  
  418. if(this.greyed)ctx.globalAlpha = 1;
  419.  
  420. if(this.toRenderText === false){
  421. ctx.translate(0, 3.5);
  422. }
  423.  
  424. if(this.type === 'Wing'){
  425. ctx.translate(0, -1.8);
  426. }
  427.  
  428. if(this.petals.length === 1){
  429. this.petals[0].render.x = 0
  430. this.petals[0].render.y = 0
  431.  
  432. let scaleMult = .8;
  433. if(this.petals[0].radius * .8 > 13.25/2){
  434. scaleMult = 13.25/(this.petals[0].radius*.8)/2;
  435. }
  436. if(petalContainerRenderSizeMultsMap[this.petals[0].type] !== undefined){
  437. if (typeof petalContainerRenderSizeMultsMap[this.petals[0].type] == "object"){
  438. if (petalContainerRenderSizeMultsMap[this.petals[0].type][this.petals[0].rarity]){
  439. scaleMult *= petalContainerRenderSizeMultsMap[this.petals[0].type][this.petals[0].rarity];
  440. }
  441. }
  442. else{
  443. scaleMult *= petalContainerRenderSizeMultsMap[this.petals[0].type];
  444. }
  445. }
  446.  
  447. let individualRotate = false;
  448. if(petalContainerIndividualRotate[this.petals[0].type] !== undefined){
  449. if (typeof petalContainerIndividualRotate[this.petals[0].type] == "object"){
  450. if (petalContainerIndividualRotate[this.petals[0].type][this.petals[0].rarity]){
  451. individualRotate = petalContainerIndividualRotate[this.petals[0].type][this.petals[0].rarity];
  452. }
  453. }
  454. else{
  455. individualRotate = petalContainerIndividualRotate[this.petals[0].type];
  456. }
  457. }
  458.  
  459. let last = {y: this.petals[0].render.y, selfAngle: this.petals[0].selfAngle};
  460. this.petals[0].render.y -= 4;
  461. this.petals[0].scaleMult = scaleMult;
  462. if(individualRotate !== false)this.petals[0].selfAngle += individualRotate;
  463.  
  464. if(this.greyed === true)window.alphaMult = 0.4;
  465. this.petals[0].draw();
  466. this.petals[0].render.y = last.y;
  467. delete this.petals[0].scaleMult;
  468. this.petals[0].selfAngle = last.selfAngle;
  469. } else {
  470. let petalRadius = (this.petals[0] ?? {radius: 0}).radius;
  471. if((this.petals[0] ?? {type: 'not peas'}).type === 'Peas'){
  472. petalRadius -= 0.2;
  473. }
  474. let radius = Math.min(petalRadius * 1.16, 25 - petalRadius);
  475.  
  476. let greaterThanMargin = petalRadius * .8 + radius - 13.25;
  477. if(greaterThanMargin > 0){
  478. radius -= greaterThanMargin;
  479. if(radius < 8){
  480. greaterThanMargin = 8-radius;
  481. radius = 8;
  482. petalRadius *= 1 / (greaterThanMargin/13.25+1);
  483. for(let i = 0; i < this.petals.length; i++){
  484. this.petals[i].radius = petalRadius;
  485. }
  486. }
  487. }
  488. if (petalContainerMultPetalRadiusMap[this.petals[0].type] !== undefined){
  489. if (typeof petalContainerMultPetalRadiusMap[this.petals[0].type] == "object"){
  490. if (petalContainerMultPetalRadiusMap[this.petals[0].type][this.petals[0].rarity]){
  491. radius *= petalContainerMultPetalRadiusMap[this.petals[0].type][this.petals[0].rarity];
  492. }
  493. }
  494. else{
  495. radius *= petalContainerMultPetalRadiusMap[this.petals[0].type];
  496. }
  497. }
  498. let toPointToCenter = ['Stinger'].includes((this.petals[0] ?? {type: "Basic"}).type) && (this.petals[0] ?? {rarity: 0}).rarity > 5;
  499. if (toPointToCenter == true){
  500. toPointToCenter = 0;
  501. }
  502. if (pointToCenterPetals[this.petals[0].type] !== undefined){
  503. if (typeof pointToCenterPetals[this.petals[0].type] == "object"){
  504. if (pointToCenterPetals[this.petals[0].type][this.petals[0].rarity]){
  505. toPointToCenter = pointToCenterPetals[this.petals[0].type][this.petals[0].rarity];
  506. }
  507. }
  508. else{
  509. toPointToCenter = pointToCenterPetals[this.petals[0].type];
  510. }
  511. }
  512. for(let i = 0; i < this.petals.length; i++){
  513. let rotateOffset = 0;
  514. if (petalContainerRotateMap[this.petals[0].type]){
  515. rotateOffset = petalContainerRotateMap[this.petals[0].type];
  516. }
  517. const angle = Math.PI * 2 * i / this.petals.length + rotateOffset;
  518. this.petals[i].render.x = 0
  519. this.petals[i].render.y = 0
  520.  
  521. let scaleMult = .8;
  522. if(petalContainerRenderSizeMultsMap[this.petals[0].type] !== undefined){
  523. if (typeof petalContainerRenderSizeMultsMap[this.petals[0].type] == "object"){
  524. if (petalContainerRenderSizeMultsMap[this.petals[0].type][this.petals[0].rarity]){
  525. scaleMult *= petalContainerRenderSizeMultsMap[this.petals[0].type][this.petals[0].rarity];
  526. }
  527. }
  528. else{
  529. scaleMult *= petalContainerRenderSizeMultsMap[this.petals[0].type];
  530. }
  531. }
  532.  
  533. let last = {x: this.petals[i].render.x, y: this.petals[i].render.y, selfAngle: this.petals[i].selfAngle};
  534. this.petals[i].render.x += Math.cos(angle) * radius * scaleMult/.8;
  535. this.petals[i].render.y += Math.sin(angle) * radius * scaleMult/.8 - 4;
  536. this.petals[i].scaleMult = scaleMult;
  537. if(toPointToCenter !== false)this.petals[i].selfAngle += angle+Math.PI+toPointToCenter;
  538. if(this.greyed === true)window.alphaMult = 0.4;
  539. this.petals[i].draw();
  540. this.petals[i].render.x = last.x;
  541. this.petals[i].render.y = last.y;
  542. delete this.petals[i].scaleMult;
  543. this.petals[i].selfAngle = last.selfAngle;
  544. }
  545. }
  546.  
  547. if(this.type === 'Wing'){
  548. ctx.translate(0, 1.8);
  549. }
  550.  
  551. if(this.toRenderText === false){
  552. ctx.translate(0, -3.5);
  553. }
  554.  
  555. if(this.toRenderText === undefined){
  556. if(this.type === "Dandelion" || this.type === "Neutron Star" || this.type === "Mini Flower"){
  557. ctx.font = '900 8.5px Ubuntu';
  558. ctx.letterSpacing = "-.1px";
  559. } else if(this.type === "Lightning" || this.type === "Pentagon" || this.type === "Hexagon" || this.type == "Plastic Egg"){
  560. ctx.font = '900 9.5px Ubuntu';
  561. ctx.letterSpacing = "-.1px";
  562. } else {
  563. ctx.font = '900 11px Ubuntu';
  564. ctx.letterSpacing = "-.05px";
  565. }
  566. ctx.textBaseline = 'middle';
  567. ctx.textAlign = 'center';
  568. ctx.fillStyle = 'white';
  569. ctx.strokeStyle = 'black';
  570. ctx.lineWidth = 1.35;
  571.  
  572. ctx.fontKerning = "none";
  573.  
  574. let type = this.type;
  575. if (type == "Fire Missile"){
  576. type = "Missile";
  577. }
  578. if (type == "Dark Compass"){
  579. type = "Compass";
  580. }
  581. if (type == "Waterlogged Compass"){
  582. type = "Compass"
  583. }
  584. if (type == "Plastic Egg"){
  585. type = "Egg";
  586. }
  587. if (type == "Jellyfish Egg"){
  588. type = "Egg";
  589. }
  590. if (type == "Oranges" && this.rarity >= 12){
  591. type = "Orange";
  592. }
  593.  
  594. if(this.greyed) ctx.globalAlpha = 0.3;
  595. ctx.strokeText(type, 0, 13.25);
  596. ctx.fillText(type, 0, 13.25);
  597. ctx.globalAlpha = 1;
  598. }
  599.  
  600. if(scale !== 1)ctx.scale(1/scale, 1/scale);
  601. if(rotation !== 0)ctx.rotate(-rotation);
  602.  
  603. if(this.amount !== 1 || (performance.now() - this.lastAmountChangedTime < 240)){
  604. if(performance.now() - this.lastAmountChangedTime < 240){
  605. ctx.globalAlpha = smoothstep((performance.now() - this.lastAmountChangedTime) / 240);
  606. }
  607. if(this.amount === 1){
  608. ctx.globalAlpha = 1 - ctx.globalAlpha;
  609. }
  610. ctx.font = `600 ${13 * scale}px Ubuntu`;
  611. ctx.letterSpacing = "1px";
  612. ctx.textBaseline = 'middle';
  613. ctx.textAlign = 'right';
  614. ctx.fillStyle = 'white';
  615. ctx.strokeStyle = 'black';
  616. ctx.lineWidth = 2;
  617. ctx.translate((70/(2.5) + .5) * scale, (-42/(2.5) + .5) * scale);
  618. ctx.rotate(Math.PI / 9.1);
  619. if(this.greyed) ctx.globalAlpha *= 0.3;
  620. ctx.strokeText('x' + (this.amount === 1 ? 2 : formatAmount(this.amount)), 0, 0);
  621. ctx.fillText('x' + (this.amount === 1 ? 2 : formatAmount(this.amount)), 0, 0);
  622. ctx.globalAlpha = 1;
  623. }
  624. ctx.setTransform(ctx.lastTransform);
  625. delete ctx.lastTransform;
  626. };
  627.  
  628. craftingMenu.drawInventory = function(alpha = 1) {
  629. this.render.scroll = interpolate(this.render.scroll, this.scroll, 0.0070 * dt);
  630.  
  631. if (alpha !== 1) {
  632. ctx.globalAlpha = alpha;
  633. }
  634. let translation = 0;
  635. if (time - this.lastCloseTime < 160) {
  636. translation += this.h * easeOutCubic((time - this.lastCloseTime) / 160);
  637. }
  638. if (time - this.lastOpenTime < 160) {
  639. translation += (this.h + 40) - (this.h + 40) * easeOutCubic((time - this.lastOpenTime) / 160);
  640. }
  641. if (translation !== 0) {
  642. ctx.translate(0, translation);
  643. }
  644.  
  645. ctx.translate(130, canvas.h - this.h - 20);
  646. ctx.fillStyle = this.getMainFill();
  647. ctx.strokeStyle = this.getMainStroke();
  648. ctx.lineWidth = 8;
  649.  
  650. ctx.beginPath()
  651. ctx.roundRect(0, 0, this.w, this.h, 3);
  652. ctx.fill();
  653. ctx.stroke();
  654. ctx.closePath();
  655.  
  656. ctx.fillStyle = '#f0f0f0';
  657. ctx.strokeStyle = 'black';
  658. ctx.lineWidth = 3.75;
  659. ctx.textAlign = 'center';
  660. ctx.textBaseline = 'middle';
  661. ctx.font = `900 32px Ubuntu`;
  662. ctx.strokeText("Craft", this.w / 2, 29);
  663. ctx.fillText("Craft", this.w / 2, 29);
  664.  
  665. if (this.craftingAnimationState === true) {
  666. this.runCraftingAnimation();
  667. }
  668. if (this.craftingAnimationState === "display") {
  669. this.displayPetalContainer.x = this.craftingPetalSlotsDimensions.x + this.displayPetalContainer.render.w * .35;
  670. this.displayPetalContainer.y = this.craftingPetalSlotsDimensions.y + this.displayPetalContainer.render.h * .35;
  671. this.displayPetalContainer.render.x = this.displayPetalContainer.x;
  672. this.displayPetalContainer.render.y = this.displayPetalContainer.y;
  673. this.displayPetalContainer.draw();
  674. } else {
  675. for (let i = 0; i < this.craftingPetalSlots.length; i++) {
  676. ctx.fillStyle = '#b17f49';
  677. ctx.beginPath();
  678. ctx.roundRect(this.craftingPetalSlots[i].x, this.craftingPetalSlots[i].y, this.craftingPetalSlots[i].w, this.craftingPetalSlots[i].h, 8);
  679. ctx.fill();
  680. ctx.closePath();
  681.  
  682. if (this.craftingPetalContainers[i] !== undefined) {
  683. const pc = this.craftingPetalContainers[i];
  684. pc.x = this.craftingPetalSlots[i].x + this.craftingPetalSlots[i].w / 2;
  685. pc.y = this.craftingPetalSlots[i].y + this.craftingPetalSlots[i].h / 2;
  686. pc.draw();
  687. }
  688. }
  689. }
  690.  
  691. if (mouseInBox({ x: mouse.canvasX, y: mouse.canvasY }, { x: this.craftingButton.x - this.craftingButton.w / 2 + 130, y: this.craftingButton.y - this.craftingButton.h / 2 + canvas.h - this.h - 20, w: this.craftingButton.w, h: this.craftingButton.h }) === true && this.craftingAnimationState === false) {
  692. this.hoveringOverCraftButton = true;
  693. } else {
  694. this.hoveringOverCraftButton = false;
  695. }
  696. ctx.letterSpacing = "0px";
  697. let fillcolor = "#777777"
  698. let strokecolor = "#555555";
  699. if (this.craftingPetalContainers[0] !== undefined) {
  700. if (Colors.rarities[this.craftingPetalContainers[0].rarity + 1]) {
  701. fillcolor = Colors.rarities[this.craftingPetalContainers[0].rarity + 1].color;
  702. strokecolor = Colors.rarities[this.craftingPetalContainers[0].rarity + 1].border;
  703.  
  704. if (this.hoveringOverCraftButton) {
  705. fillcolor = blendColor(fillcolor, "#ffffff", 0.1);
  706. strokecolor = blendColor(strokecolor, "#ffffff", 0.03)
  707. }
  708. }
  709. }
  710. ctx.lineWidth = 7;
  711. ctx.fillStyle = fillcolor;
  712. ctx.strokeStyle = strokecolor;
  713. ctx.beginPath();
  714. ctx.roundRect(this.craftingButton.x - this.craftingButton.w / 2, this.craftingButton.y - this.craftingButton.h / 2, this.craftingButton.w, this.craftingButton.h, 4);
  715. ctx.fill();
  716. ctx.stroke();
  717. ctx.closePath();
  718.  
  719. ctx.fillStyle = '#f0f0f0';
  720. ctx.strokeStyle = 'black';
  721. ctx.lineWidth = 2.25;
  722. ctx.textAlign = 'center';
  723. ctx.textBaseline = 'middle';
  724. ctx.font = `900 22px Ubuntu`;
  725. ctx.strokeText("Craft", this.craftingButton.x, this.craftingButton.y);
  726. ctx.fillText("Craft", this.craftingButton.x, this.craftingButton.y);
  727. if (this.craftingPetalContainers[0]) {
  728. ctx.fillStyle = '#f0f0f0';
  729. ctx.strokeStyle = 'black';
  730. ctx.lineWidth = 2.25;
  731. ctx.textAlign = 'center';
  732. ctx.textBaseline = 'middle';
  733. ctx.font = `900 12px Ubuntu`;
  734.  
  735. let attempt = this.craftingPetalContainers[0].attempt;
  736. if (attempt == undefined) {
  737. attempt = 0;
  738. }
  739. let chance = calculateChance(attempt, this.craftingPetalContainers[0].rarity)
  740. if (this.craftingAnimationTimer > 3000 && this.craftingAnimationData.successAmount > 0) {
  741. ctx.fillStyle = "#00ff00"
  742. ctx.strokeText("Success (-" + this.craftingAnimationData.lost + ")", this.craftingButton.x, this.craftingButton.y + 40);
  743. ctx.fillText("Success (-" + this.craftingAnimationData.lost + ")", this.craftingButton.x, this.craftingButton.y + 40);
  744. }
  745. else {
  746. ctx.strokeText("Attempt " + (attempt + 1), this.craftingButton.x, this.craftingButton.y + 60);
  747. ctx.fillText("Attempt " + (attempt + 1), this.craftingButton.x, this.craftingButton.y + 60);
  748.  
  749. if (this.craftingPetalContainers[0].rarity >= 12){
  750. ctx.strokeText(Math.floor(chance * 100) / 100 + "% success chance", this.craftingButton.x, this.craftingButton.y + 40);
  751. ctx.fillText(Math.floor(chance * 100) / 100 + "% success chance", this.craftingButton.x, this.craftingButton.y + 40);
  752. }
  753. else{
  754. ctx.strokeText(Math.floor(chance * 10) / 10 + "% success chance", this.craftingButton.x, this.craftingButton.y + 40);
  755. ctx.fillText(Math.floor(chance * 10) / 10 + "% success chance", this.craftingButton.x, this.craftingButton.y + 40);
  756. }
  757. }
  758.  
  759. }
  760.  
  761. if (this.hoveringOverCraftButton === true || this.draggingHorizontalScrollBar === true || this.draggingScrollBar === true || this.hoveringOverHorizontalScrollBar === true || this.hoveringOverScrollBar === true) {
  762. setCursor('pointer');
  763. }
  764.  
  765. ctx.save();
  766.  
  767. ctx.beginPath();
  768. ctx.rect(this.inventorySpace.x, this.inventorySpace.y, this.fillingHorizontal ? this.inventorySpace.w + 24 : this.inventorySpace.w, this.inventorySpace.h);
  769. ctx.clip();
  770. ctx.closePath();
  771.  
  772. this.firstPetalContainer = null;
  773. this.lastPetalContainer = null;
  774.  
  775. const firstRarityX = this.petalContainerSize / 2 + this.inventorySpace.x + (this.petalContainerSize + 12) * 0 + 3;
  776. const lastRarityX = this.petalContainerSize / 2 + this.inventorySpace.x + (this.petalContainerSize + 12) * this.maxRarity - 6;
  777. this.totalPetalWidth = lastRarityX - firstRarityX;
  778.  
  779. let maxTypeIndex = 0;
  780. for (let typeKey in this.petalContainers) {
  781. for (let i = 0; i <= Math.max(5, this.maxRarity); i++) {
  782. const rarityKey = i;
  783. const pcX = this.petalContainerSize / 2 + this.inventorySpace.x + (this.petalContainerSize + 12) * rarityKey + 3 - this.render.horizontalScroll * (this.totalPetalWidth - this.inventorySpace.h);
  784. const pcY = 5 + this.petalContainerSize / 2 + this.typeIndexes[typeKey] * (this.petalContainerSize + 12) + 5 + this.inventorySpace.y - this.render.scroll * (this.totalPetalHeight - this.inventorySpace.h);
  785. if (this.typeIndexes[typeKey] > maxTypeIndex) {
  786. maxTypeIndex = this.typeIndexes[typeKey];
  787. }
  788. if (this.fillerPetalSlots[typeKey] === undefined) {
  789. this.fillerPetalSlots[typeKey] = {};
  790. }
  791. if (this.fillerPetalSlots[typeKey][rarityKey] === undefined) {
  792. this.fillerPetalSlots[typeKey][rarityKey] = { render: { x: pcX, y: pcY } };
  793. }
  794.  
  795. const fpc = this.fillerPetalSlots[typeKey][rarityKey];
  796. fpc.x = pcX;
  797. fpc.y = pcY;
  798. fpc.render.x = interpolate(fpc.render.x, fpc.x, 0.00672 * dt);
  799. fpc.render.y = interpolate(fpc.render.y, fpc.y, 0.00672 * dt);
  800. ctx.fillStyle = '#b17f49';
  801.  
  802. if (this.petalContainers[typeKey][rarityKey] === undefined && fpc.render.x + this.petalContainerSize / 2 > this.inventorySpace.x * 0.9 && fpc.render.x + this.petalContainerSize / 2 < (this.inventorySpace.x + this.inventorySpace.w) * 1.2 && fpc.render.y + this.petalContainerSize / 2 > this.inventorySpace.y * 0.9 && fpc.render.y + this.petalContainerSize / 2 < (this.inventorySpace.y + this.inventorySpace.h) * 1.1) {
  803. ctx.beginPath();
  804. ctx.roundRect(fpc.render.x - this.petalContainerSize / 2, fpc.render.y - this.petalContainerSize / 2, this.petalContainerSize, this.petalContainerSize, 8);
  805. ctx.fill();
  806. ctx.closePath();
  807. }
  808.  
  809. if (this.petalContainers[typeKey] !== undefined && this.petalContainers[typeKey][rarityKey] !== undefined) {
  810. const pc = this.petalContainers[typeKey][rarityKey];
  811. pc.x = pcX;
  812. pc.y = pcY;
  813.  
  814. if (pc.render.x + pc.w / 2 > this.inventorySpace.x * 0.9 && pc.render.x - pc.w / 2 < (this.inventorySpace.x + this.inventorySpace.w) * 1.1 && pc.render.y + pc.w / 2 > this.inventorySpace.y * 0.9 && pc.render.y - pc.w / 2 < (this.inventorySpace.y + this.inventorySpace.h) * 1.1) {
  815. pc.draw(undefined, undefined, true);
  816. } else {
  817. pc.render.x = interpolate(pc.render.x, pc.x, 0.00672 * dt)
  818. pc.render.y = interpolate(pc.render.y, pc.y, 0.00672 * dt)
  819. }
  820.  
  821. if (this.firstPetalContainer === null) {
  822. this.firstPetalContainer = pc;
  823. }
  824. this.lastPetalContainer = pc;
  825. } else {
  826. if (this.firstPetalContainer === null) {
  827. this.firstPetalContainer = fpc;
  828. }
  829. this.lastPetalContainer = fpc;
  830. }
  831. }
  832. }
  833.  
  834. if (Object.keys(this.petalContainers).length < 5) {
  835. this.fillingHorizontal = true;
  836. for (let j = Object.keys(this.petalContainers).length; j < 5; j++) {
  837. const typeKey = "filler" + j;
  838. for (let i = 0; i <= Math.max(5, this.maxRarity); i++) {
  839. const rarityKey = i;
  840. const pcX = this.petalContainerSize / 2 + this.inventorySpace.x + (this.petalContainerSize + 12) * rarityKey + 3 - this.render.horizontalScroll * (this.totalPetalWidth - this.inventorySpace.h);
  841. const pcY = 5 + this.petalContainerSize / 2 + (maxTypeIndex + j - Object.keys(this.petalContainers).length + 1) * (this.petalContainerSize + 12) + 5 + this.inventorySpace.y - this.render.scroll * (this.totalPetalHeight - this.inventorySpace.h);
  842.  
  843. if (this.fillerPetalSlots[typeKey] === undefined) {
  844. this.fillerPetalSlots[typeKey] = {};
  845. }
  846. if (this.fillerPetalSlots[typeKey][rarityKey] === undefined) {
  847. this.fillerPetalSlots[typeKey][rarityKey] = { render: { x: pcX, y: pcY } };
  848. }
  849. const fpc = this.fillerPetalSlots[typeKey][rarityKey];
  850. fpc.x = pcX;
  851. fpc.y = pcY;
  852. fpc.render.x = interpolate(fpc.render.x, fpc.x, 0.00672 * dt);
  853. fpc.render.y = interpolate(fpc.render.y, fpc.y, 0.00672 * dt);
  854. ctx.fillStyle = '#b17f49';
  855. ctx.beginPath();
  856. ctx.roundRect(fpc.render.x - this.petalContainerSize / 2, fpc.render.y - this.petalContainerSize / 2, this.petalContainerSize, this.petalContainerSize, 8);
  857. ctx.fill();
  858. ctx.closePath();
  859. }
  860. }
  861. } else {
  862. this.fillingHorizontal = false;
  863. }
  864.  
  865. if (this.lastPetalContainer !== null) {
  866. const petalDimensions = {
  867. start: this.firstPetalContainer.y - this.petalContainerSize / 2 - 6,
  868. end: this.lastPetalContainer.y + this.petalContainerSize / 2 + 6
  869. }
  870. petalDimensions.length = petalDimensions.end - petalDimensions.start;
  871. this.totalPetalHeight = petalDimensions.length;
  872. }
  873.  
  874. ctx.restore();
  875.  
  876. let needsFilter = false;
  877. for (let i = 0; i < this.fadingPetalContainers.length; i++) {
  878. if (this.fadingPetalContainers[i].spawnTime < 0.001) {
  879. this.fadingPetalContainers[i].toRemove = true;
  880. needsFilter = true;
  881. }
  882. this.fadingPetalContainers[i].draw();
  883. }
  884. if (needsFilter === true) {
  885. this.fadingPetalContainers = this.fadingPetalContainers.filter(p => p.toRemove !== true);
  886. }
  887. if (this.fillingHorizontal === false) {
  888. this.render.scroll = interpolate(this.render.scroll, this.scroll, 0.0070 * dt);
  889. if (this.render.scroll < -.1) {
  890. this.render.scroll = -.1;
  891. } else if (this.render.scroll > 1.1) {
  892. this.render.scroll = 1.1;
  893. }
  894.  
  895. this.scrollbar.pos = interpolate(this.scrollbar.start, this.scrollbar.end, this.render.scroll);
  896. this.scrollbar.bottom = this.scrollbar.pos + this.scrollbar.length / 2;
  897. this.scrollbar.top = this.scrollbar.pos - this.scrollbar.length / 2;
  898.  
  899. this.scrollbar.renderTop = interpolate(this.scrollbar.renderTop, this.scrollbar.top, this.draggingScrollBar ? 0.28 : 0.08);
  900. this.scrollbar.renderBottom = interpolate(this.scrollbar.renderBottom, this.scrollbar.bottom, this.draggingScrollBar ? 0.28 : 0.08);
  901. }
  902.  
  903. if (this.maxRarity >= 5) {
  904. this.render.horizontalScroll = interpolate(this.render.horizontalScroll, this.horizontalScroll, 0.0070 * dt);
  905.  
  906. this.horizontalScrollBar.pos = interpolate(this.horizontalScrollBar.start, this.horizontalScrollBar.end, this.render.horizontalScroll);
  907. this.horizontalScrollBar.right = this.horizontalScrollBar.pos + this.horizontalScrollBar.length / 2;
  908. this.horizontalScrollBar.left = this.horizontalScrollBar.pos - this.horizontalScrollBar.length / 2;
  909.  
  910. this.horizontalScrollBar.renderRight = interpolate(this.horizontalScrollBar.renderRight, this.horizontalScrollBar.right, this.draggingHorizontalScrollBar ? 0.28 : 0.08);
  911. this.horizontalScrollBar.renderLeft = interpolate(this.horizontalScrollBar.renderLeft, this.horizontalScrollBar.left, this.draggingHorizontalScrollBar ? 0.28 : 0.08);
  912. }
  913.  
  914. if (this.scroll < 0) {
  915. this.scroll = 0;
  916. } else if (this.scroll > 1) {
  917. this.scroll = 1;
  918. }
  919.  
  920. ctx.strokeStyle = this.getMainStroke();
  921. ctx.lineWidth = 8;
  922. ctx.lineCap = 'round';
  923. ctx.beginPath();
  924. ctx.moveTo(this.w - 16, (this.scrollbar.renderTop));
  925. ctx.lineTo(this.w - 16, (this.scrollbar.renderBottom));
  926. ctx.stroke();
  927. ctx.closePath();
  928.  
  929. ctx.beginPath();
  930. ctx.moveTo(this.horizontalScrollBar.renderRight, this.h - 16);
  931. ctx.lineTo(this.horizontalScrollBar.renderLeft, this.h - 16);
  932. ctx.stroke();
  933. ctx.closePath();
  934.  
  935. if (this.menuActive === true && translation === 0) {
  936. if (mouse.canvasX > 130 + this.w - 7.5 - 30 - 3 && mouse.canvasY > canvas.h - this.h - 20 + 7.5 + 3 && mouse.canvasX < 130 + this.w - 7.5 - 3 && mouse.canvasY < canvas.h - this.h - 20 + 7.5 + 30 + 3) {
  937. ctx.fillStyle = "#c16666";
  938. setCursor('pointer');
  939. this.hoveringOverX = true;
  940. } else {
  941. this.hoveringOverX = false;
  942. ctx.fillStyle = '#c1565e';
  943. }
  944. } else {
  945. ctx.fillStyle = '#c1565e';
  946. this.hoveringOverX = false;
  947. }
  948. ctx.translate(-3, 3);
  949. ctx.strokeStyle = '#90464b';
  950. ctx.lineWidth = 5;
  951. ctx.beginPath();
  952. ctx.roundRect(this.w - 7.5 - 30, 7.5, 30, 30, 6);
  953. ctx.fill();
  954. ctx.stroke();
  955. ctx.closePath();
  956.  
  957. ctx.lineWidth = 4.75;
  958. ctx.lineCap = 'round';
  959. ctx.strokeStyle = '#cccccc';
  960. ctx.beginPath();
  961. ctx.moveTo(this.w - 30, 30);
  962. ctx.lineTo(this.w - 7.5 * 2, 7.5 + 7.5);
  963. ctx.stroke();
  964. ctx.closePath();
  965. ctx.beginPath();
  966. ctx.moveTo(this.w - 7.5 * 2, 30);
  967. ctx.lineTo(this.w - 30, 7.5 + 7.5);
  968. ctx.stroke();
  969. ctx.closePath();
  970. ctx.translate(3, -3);
  971.  
  972. const mouseX = mouse.x * canvas.w / window.innerWidth;
  973. const mouseY = mouse.y * canvas.h / window.innerHeight;
  974.  
  975. if (mouseX > 130 && mouseX < 130 + this.w - 20 && mouseY > canvas.h - this.h - 20 && mouseY < canvas.h - 20) {
  976. ctx.lastTransform5 = ctx.getTransform();
  977. for (let typeKey in this.petalContainers) {
  978. for (let i = 0; i <= this.maxRarity; i++) {
  979. if (this.petalContainers[typeKey] === undefined) continue;
  980. const rarityKey = i;
  981. const pc = this.petalContainers[typeKey][rarityKey];
  982. if (pc === undefined) continue;
  983.  
  984. if (pc.render.x + pc.w / 2 > this.inventorySpace.x * 0.9 && pc.render.x - pc.w / 2 < (this.inventorySpace.x + this.inventorySpace.w) * 1.1 && pc.render.y + pc.w / 2 > this.inventorySpace.y * 0.9 && pc.render.y - pc.w / 2 < (this.inventorySpace.y + this.inventorySpace.h) * 1.1) {
  985. if (mouseInBox({ x: mouseX, y: mouseY }, { x: pc.render.x - pc.w / 2 + 130, y: pc.render.y - pc.h / 2 + canvas.h - this.h - 20, w: pc.w, h: pc.h }) === true) {
  986. pc.isHovered = true;
  987. }
  988. pc.drawStatsBox();
  989. }
  990. }
  991. }
  992.  
  993. if (this.craftingAnimationState === "display") {
  994. const pc = this.displayPetalContainer;
  995. if (mouseInBox({ x: mouseX, y: mouseY }, { x: pc.render.x - pc.w / 2 + 130, y: pc.render.y - pc.h / 2 + canvas.h - this.h - 20, w: pc.w, h: pc.h }) === true) {
  996. pc.isHovered = true;
  997. }
  998. pc.drawStatsBox();
  999. } else {
  1000. for (let i = 0; i < this.craftingPetalSlots.length; i++) {
  1001. if (this.craftingPetalContainers[i] !== undefined) {
  1002. const pc = this.craftingPetalContainers[i];
  1003. if (mouseInBox({ x: mouseX, y: mouseY }, { x: pc.render.x - pc.w / 2 + 130, y: pc.render.y - pc.h / 2 + canvas.h - this.h - 20, w: pc.w, h: pc.h }) === true) {
  1004. pc.isHovered = true;
  1005. }
  1006. pc.drawStatsBox();
  1007. }
  1008. }
  1009. }
  1010. ctx.setTransform(ctx.lastTransform5);
  1011. delete ctx.lastTransform5;
  1012. }
  1013.  
  1014. ctx.translate(-130, -(canvas.h - this.h - 20));
  1015.  
  1016. if (translation !== 0) {
  1017. ctx.translate(0, -translation);
  1018. }
  1019. ctx.globalAlpha = 1;
  1020. }
  1021.  
  1022. renderHpBar = function({x,y,radius,hp,maxHp,beforeStreakHp,givenAlpha,flowerName,flowerUsername,shield,team},entity={fadeState: undefined, fadeTime: 0, lastHp: hp}, rarity, isBoss){
  1023. if(entity.fadeState === undefined){
  1024. if(Math.ceil(entity.hp) === maxHp && !shield){
  1025. entity.fadeState = 'invisible';
  1026. entity.fadeTime = -220;
  1027. } else {
  1028. entity.fadeTime = time;
  1029. entity.fadeState = 'fadeIn';
  1030. }
  1031. }
  1032. if(entity.lastHp === undefined){
  1033. entity.lastHp = entity.hp;
  1034. }
  1035. if(entity.lastShield === undefined){
  1036. entity.lastShield = entity.shield;
  1037. }
  1038. let fadeAlphaMult = 1;
  1039.  
  1040. if(entity.dead !== true){
  1041. if(Math.ceil(entity.lastHp) < maxHp && Math.ceil(entity.hp) === maxHp && entity.shield == 0){
  1042. entity.fadeTime = time;
  1043. entity.fadeState = 'fadeOut';
  1044. } else if((Math.ceil(entity.lastHp) === maxHp && Math.ceil(entity.hp) < maxHp) || (entity.shield != 0 && entity.lastShield == 0)){
  1045. entity.fadeTime = time;
  1046. entity.fadeState = 'fadeIn';
  1047. }
  1048. }
  1049. entity.lastShield = entity.shield;
  1050. entity.lastHp = entity.hp;
  1051. toResetFadeState = false;
  1052. if (givenAlpha){
  1053. if (givenAlpha > 0){
  1054. toResetFadeState = entity.fadeState;
  1055. entity.fadeState = "visible";
  1056. }
  1057. }
  1058. if(entity.fadeState === 'fadeOut'){
  1059. fadeAlphaMult = 1 - (time - entity.fadeTime) / 180;
  1060. if(fadeAlphaMult < 0){
  1061. fadeAlphaMult = 0;
  1062. entity.fadeState = 'invisible';
  1063. }
  1064. } else if(entity.fadeState === 'fadeIn'){
  1065. fadeAlphaMult = (time - entity.fadeTime) / 180;
  1066. if(fadeAlphaMult > 1){
  1067. fadeAlphaMult = 1;
  1068. entity.fadeState = 'visible';
  1069. }
  1070. } else if(entity.fadeState === 'invisible'){
  1071. return;
  1072. }
  1073. if(entity.dead === true)fadeAlphaMult *= ((10 - entity.deadAnimationTimer) / 166) ** 3;
  1074.  
  1075. if (givenAlpha){
  1076. fadeAlphaMult = givenAlpha;
  1077. }
  1078. const barDimensions = {
  1079. w: (radius/25)**1.2*25*3.2+.33,
  1080. h: (radius/25)**1.2*25*0.39+.33,
  1081. borderRadius: (radius/25)**1.2*25*0.25,
  1082. innerPadding: (radius/25)**1.05*1.8-.1
  1083. }
  1084. ctx.globalAlpha = fadeAlphaMult;
  1085. hp = Math.max(hp, 0);
  1086. beforeStreakHp = Math.max(beforeStreakHp, 0);
  1087.  
  1088. if(rarity){
  1089. let rarName = Colors.rarities[rarity].name;
  1090. if(isBoss){
  1091. ctx.fillStyle = `hsl(${(time/10) % 360}, 50%, 40%)`;
  1092. rarName = 'Boss';
  1093. } else {
  1094. ctx.fillStyle = Colors.rarities[rarity].color;
  1095. };
  1096. ctx.beginPath();
  1097. ctx.roundRect(x - barDimensions.w/2 - barDimensions.innerPadding, y + radius*1.775 - barDimensions.innerPadding, (barDimensions.w - barDimensions.borderRadius * 1.5) + barDimensions.borderRadius * 1.5 + barDimensions.innerPadding * 2, barDimensions.h + barDimensions.innerPadding * 2, barDimensions.borderRadius * barDimensions.h / (barDimensions.h - barDimensions.innerPadding * 2));
  1098. ctx.fill();
  1099. ctx.closePath();
  1100.  
  1101. ctx.font = '900 36px Ubuntu';
  1102. ctx.lineWidth = 5;
  1103. ctx.strokeStyle = 'black';
  1104. ctx.strokeText(rarName, x - barDimensions.w/2 + barDimensions.w / 2, y + radius*2.5 + barDimensions.innerPadding);
  1105. ctx.fillText(rarName, x - barDimensions.w/2 + barDimensions.w / 2, y + radius*2.5 + barDimensions.innerPadding);
  1106. }
  1107.  
  1108. ctx.fillStyle = '#333333';
  1109. ctx.beginPath();
  1110. ctx.roundRect(x - barDimensions.w/2, y + radius*1.775, barDimensions.w, barDimensions.h, barDimensions.borderRadius);
  1111. ctx.fill();
  1112. ctx.closePath();
  1113. if(flowerName !== undefined && entity.id !== window.selfId){
  1114. ctx.globalAlpha = 1;
  1115. ctx.fillStyle = 'white';
  1116. ctx.strokeStyle = 'black';
  1117. ctx.lineWidth = 2.25;
  1118. ctx.textAlign = 'center';
  1119. ctx.textBaseline = 'top';
  1120. ctx.font = `900 22px Ubuntu`;
  1121. if (window.usernames === true) {
  1122. ctx.strokeText(flowerName, x, y - radius * 2.75 + barDimensions.h + 2);
  1123. ctx.fillText(flowerName, x, y - radius * 2.75 + barDimensions.h + 2);
  1124. ctx.font = `900 10px Ubuntu`;
  1125. ctx.fillStyle = '#bbbbbb';
  1126. ctx.strokeText(flowerUsername, x, y - radius * 2 + barDimensions.h + 2);
  1127. ctx.fillText(flowerUsername, x, y - radius * 2 + barDimensions.h + 2);
  1128. } else {
  1129. ctx.strokeText(flowerName, x, y - radius * 2.375 + barDimensions.h + 2);
  1130. ctx.fillText(flowerName, x, y - radius * 2.375 + barDimensions.h + 2);
  1131. }
  1132. }
  1133. if(beforeStreakHp < maxHp / 10){
  1134. ctx.globalAlpha = Math.max(0,hp * .95 / (maxHp / 10) + 0.05) * fadeAlphaMult;
  1135. }
  1136. if(beforeStreakHp > 0){
  1137. ctx.fillStyle = '#dd3434'
  1138. ctx.beginPath();
  1139. const paddingMult = 1.4;
  1140. ctx.roundRect(x - barDimensions.w/2 + barDimensions.innerPadding * paddingMult, y + radius*1.775 + barDimensions.innerPadding * paddingMult, (barDimensions.w - barDimensions.borderRadius * 1.5) * Math.min(1,beforeStreakHp / maxHp) + barDimensions.borderRadius * 1.5 - barDimensions.innerPadding * 2 * paddingMult, barDimensions.h - barDimensions.innerPadding * paddingMult * 2, barDimensions.borderRadius * barDimensions.h / (barDimensions.h + barDimensions.innerPadding * 2));
  1141. ctx.fill();
  1142. ctx.closePath();
  1143. }
  1144. ctx.globalAlpha = fadeAlphaMult;
  1145. if(hp < maxHp / 10){
  1146. ctx.globalAlpha = Math.max(0,hp * .95 / (maxHp / 10) + 0.05) * fadeAlphaMult;
  1147. }
  1148. if(hp > 0){
  1149. ctx.fillStyle = '#75dd34'
  1150. if (team == "flower"){
  1151. ctx.fillStyle = "#b5aa31"
  1152. }
  1153. ctx.beginPath();
  1154. ctx.roundRect(x - barDimensions.w/2 + barDimensions.innerPadding, y + radius*1.775 + barDimensions.innerPadding, (barDimensions.w - barDimensions.borderRadius * 1.5) * Math.min(1, hp / maxHp) + barDimensions.borderRadius * 1.5 - barDimensions.innerPadding * 2, barDimensions.h - barDimensions.innerPadding * 2, barDimensions.borderRadius * barDimensions.h / (barDimensions.h + barDimensions.innerPadding * 2));
  1155. ctx.fill();
  1156. ctx.closePath();
  1157. }
  1158. if (shield){
  1159. if (shield > maxHp * 0.005){
  1160. ctx.fillStyle = 'white'
  1161. ctx.beginPath();
  1162. ctx.roundRect(x - barDimensions.w/2 + barDimensions.innerPadding, y + radius*1.805 + barDimensions.innerPadding, (barDimensions.w - barDimensions.borderRadius * 1.5) * Math.min(1, shield / maxHp) + barDimensions.borderRadius * 1.5 - barDimensions.innerPadding * 2, barDimensions.h - barDimensions.innerPadding * 3, barDimensions.borderRadius * barDimensions.h / (barDimensions.h + barDimensions.innerPadding * 3));
  1163. ctx.fill();
  1164. ctx.closePath();
  1165. }
  1166. }
  1167. ctx.globalAlpha = 1;
  1168. if(toResetFadeState !== false){
  1169. entity.fadeState = toResetFadeState;
  1170. }
  1171. }
  1172.  
  1173. enemyRenderMapText = function(e) {
  1174. renderHpBar({
  1175. x: 0,
  1176. y: 0,
  1177. radius: e.render.radius * 0.8,
  1178. hp: e.render.hp,
  1179. maxHp: e.maxHp,
  1180. beforeStreakHp: e.render.beforeStreakHp,
  1181. team: e.team
  1182. }, e, e.rarity, e.isBoss);
  1183. if (!window.isEditor === true && window.damageCounter) {
  1184. renderDamageCounter({
  1185. radius: e.render.radius,
  1186. timeAlive: e.ticksSinceLastDamaged,
  1187. totalDamage: e.damageCount,
  1188. })
  1189. }
  1190. }
  1191.  
  1192. inventory.draw = function(alpha = 1) {
  1193. if(this.fadingPetalContainer !== null){
  1194. const temp = {x: this.fadingPetalContainer.render.x, y: this.fadingPetalContainer.render.y};
  1195. this.fadingPetalContainer.render.x = this.fadingPetalContainer.x;
  1196. this.fadingPetalContainer.render.y = this.fadingPetalContainer.y;
  1197. const animationTime = 1 - (time - this.fadingPetalContainer.fadeTime) / 200;
  1198. ctx.globalAlpha = Math.max(0,Math.min(1,animationTime));
  1199. ctx.save();
  1200. ctx.translate(this.fadingPetalContainer.x, this.fadingPetalContainer.y);
  1201. ctx.scale(2 - animationTime, 2 - animationTime);
  1202. ctx.translate(-this.fadingPetalContainer.x, -this.fadingPetalContainer.y);
  1203. this.fadingPetalContainer.draw(alpha);
  1204. ctx.restore();
  1205. this.fadingPetalContainer.render.x = temp.x;
  1206. this.fadingPetalContainer.render.y = temp.y;
  1207. if(time - this.fadingPetalContainer.fadeTime > 200){
  1208. this.fadingPetalContainer = null;
  1209. }
  1210. }
  1211.  
  1212. for(let i = 0; i < this.topPetalSlots.length; i++){
  1213. this.topPetalSlots[i].draw(alpha);
  1214. }
  1215. for(let i = 0; i < this.bottomPetalSlots.length; i++){
  1216. this.bottomPetalSlots[i].draw(alpha);
  1217. }
  1218. for(let key in this.topPetalContainers){
  1219. const tpc = this.topPetalContainers[key];
  1220. let showTimer = false;
  1221. let rarity;
  1222. if (tpc.type == 'Egg' || tpc.type == 'Plastic Egg') {
  1223. if (petalReloadData[key] && Math.abs(petalReloadData[key].reload - 1) >= 1e-12) {
  1224. tpc.respawnTimer = tpc.petalStats.hatchTime + tpc.petalStats.reload * petalReloadData[key].reload;
  1225. showTimer = true;
  1226. } else if (tpc.hasOwnProperty('respawnTimer')) {
  1227. tpc.respawnTimer -= dt / 1000;
  1228. showTimer = true;
  1229. if (tpc.respawnTimer <= 0) {
  1230. delete tpc.respawnTimer;
  1231. showTimer = false;
  1232. };
  1233. };
  1234. rarity = tpc.petalStats.spawnRarity;
  1235. } else if (tpc.type == 'Stick') {
  1236. if (petalReloadData[key]) {
  1237. tpc.respawnTimer = [];
  1238. tpc.respawnTimer.push(tpc.petalStats.spawnSystem[1] + tpc.petalStats.reload * petalReloadData[key].reload);
  1239. tpc.respawnTimer.push(tpc.petalStats.spawnSystem[1] * 2 + tpc.petalStats.reload * petalReloadData[key].reload);
  1240. showTimer = true;
  1241. } else if (tpc.hasOwnProperty('respawnTimer')) {
  1242. tpc.respawnTimer[0] -= dt / 1000;
  1243. tpc.respawnTimer[1] -= dt / 1000;
  1244. showTimer = true;
  1245. if (tpc.respawnTimer[1] <= 0) {
  1246. delete tpc.respawnTimer;
  1247. showTimer = false;
  1248. } else if (tpc.respawnTimer[0] <= 0) {
  1249. tpc.respawnTimer[0] = 0;
  1250. };
  1251. };
  1252. rarity = tpc.petalStats.spawnSystem[0];
  1253. };
  1254. tpc.draw(true, key);
  1255. if (showTimer) {
  1256. ctx.save();
  1257. ctx.lineWidth = 4.5;
  1258. ctx.translate(tpc.x, tpc.y - tpc.h * 1.15);
  1259. ctx.scale(tpc.w / 50, tpc.h / 50);
  1260.  
  1261. if (Colors.rarities[rarity].fancy !== undefined){
  1262. const gradientFill = ctx.createLinearGradient(-30, -30, 30, 30);
  1263. createFancyGradient(gradientFill, rarity);
  1264. ctx.fillStyle = gradientFill;
  1265. ctx.strokeStyle = Colors.rarities[rarity].fancy.border;
  1266. } else {
  1267. ctx.fillStyle = Colors.rarities[rarity].color;
  1268. ctx.strokeStyle = Colors.rarities[rarity].border;
  1269. }
  1270. ctx.beginPath();
  1271. ctx.roundRect(-25, -25, 50, 50, .25);
  1272. ctx.fill();
  1273. ctx.stroke();
  1274. ctx.closePath();
  1275.  
  1276. ctx.restore();
  1277.  
  1278. ctx.font = '900 24px Ubuntu';
  1279. ctx.lineWidth = 5;
  1280. ctx.strokeStyle = 'black';
  1281. ctx.fillStyle = 'white';
  1282. let timer = tpc.type == 'Stick' ? (tpc.respawnTimer[0] == 0 ? tpc.respawnTimer[1] : tpc.respawnTimer[0]) : tpc.respawnTimer;
  1283. ctx.strokeText(Math.round(timer * 100) / 100 + 's', tpc.x, tpc.y - tpc.h * 1.15);
  1284. ctx.fillText(Math.round(timer * 100) / 100 + 's', tpc.x, tpc.y - tpc.h * 1.15);
  1285. };
  1286. }
  1287. for(let key in this.bottomPetalContainers){
  1288. this.bottomPetalContainers[key].draw();
  1289. }
  1290.  
  1291. if(this === menuInventory){
  1292. const mouseX = mouse.x * canvas.w / window.innerWidth;
  1293. const mouseY = mouse.y * canvas.h / window.innerHeight;
  1294. const offsetMouseY = mouseY - this.translateY;
  1295. ctx.lastTransform8 = ctx.getTransform();
  1296. for(let key in this.topPetalContainers){
  1297. const pc = this.topPetalContainers[key];
  1298.  
  1299. if(mouseX > pc.x - pc.w/2 && mouseX < pc.x + pc.w/2 && offsetMouseY > pc.y - pc.h/2 && offsetMouseY < pc.y + pc.h/2){
  1300. pc.isHovered = true;
  1301. }
  1302. pc.drawStatsBox(true);
  1303. }
  1304.  
  1305. for(let key in this.bottomPetalContainers){
  1306. const pc = this.bottomPetalContainers[key];
  1307.  
  1308. if(mouseX > pc.x - pc.w/2 && mouseX < pc.x + pc.w/2 && offsetMouseY > pc.y - pc.h/2 && offsetMouseY < pc.y + pc.h/2){
  1309. pc.isHovered = true;
  1310. }
  1311. pc.drawStatsBox(true);
  1312. }
  1313. ctx.setTransform(ctx.lastTransform8);
  1314. delete ctx.lastTransform8;
  1315. }
  1316. }
  1317. })();