diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..47d2ec7
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,14 @@
+{
+ "recommendations": [
+ "ritwickdey.LiveServer",
+ "esbenp.prettier-vscode",
+ "dbaeumer.vscode-eslint",
+ "formulahendry.auto-rename-tag",
+ "christian-kohler.path-intellisense",
+ "usernamehw.errorlens",
+ "streetsidesoftware.code-spell-checker",
+ "bradlc.vscode-tailwindcss",
+ "yoavbls.pretty-ts-errors",
+ "ms-vscode.vscode-typescript-next"
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..c25e780
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,29 @@
+{
+ "editor.tabSize": 2,
+ "editor.insertSpaces": true,
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+
+ "files.autoSave": "afterDelay",
+ "files.autoSaveDelay": 800,
+
+ "emmet.includeLanguages": {
+ "javascript": "javascriptreact"
+ },
+
+ "editor.linkedEditing": true,
+
+ "liveServer.settings.donotShowInfoMsg": true,
+
+ "prettier.singleQuote": true,
+ "prettier.semi": true,
+
+ "eslint.validate": ["javascript", "javascriptreact"],
+
+ "editor.suggestOnTriggerCharacters": true,
+ "editor.quickSuggestions": {
+ "strings": true
+ },
+
+ "workbench.startupEditor": "none"
+}
\ No newline at end of file
diff --git a/404.html b/404.html
new file mode 100644
index 0000000..0e63ae9
--- /dev/null
+++ b/404.html
@@ -0,0 +1,100 @@
+
+
+
+
+
+
frequently asked questions
+
this also serves as a tutorial for auth's RNG :)
+
+
+
+
search what you need help with (beta)
+
+
basics
+
+
+
how do i roll?
+
press the roll button above the "total rolls: X" counter, or press auto roll if you're lazy.
+
+
+
+
why is there a big counter on the screen?
+
every 100 rolls, you get x4 luck for a minute. its nothing to worry about, its only good, no bad.
+
+
+
+
what are anomalies?
+
anomalies are little rare things where you can "consume" them for a 0.5x permanent luck boost that can build up overtime. this is great for getting rarities that are usually impossible with just raw luck. you get them every time you roll a rarity above 1/10,000.
+
+
+
shop system
+
+
+
how do i get points?
+
+ double-click any rarity in your inventory to "sell it out" for points. you keep the rarity, but it gets marked as sold. the rarer it is, the more points you get!
+
+ formula: rarity number ÷ 3 (rounded up)
+ example: a 1/90 rarity gives you 30 points
+ if you have duplicates, you sell all unsold copies at once for more points
+
+
+
+
+
+
what happens when i sell out?
+
the rarity gets a "sold" marker, meaning you can't sell it again until you get another duplicate. once you roll another copy, the sold marker disappears and you can sell the new copies.
+
+
+
+
what are the shop upgrades?
+
+
luck boost: increases your luck multiplier by 1.1x per level (stacks multiplicatively). max level 100. costs 50 points + (level × 25).
+
+
roll speed: decreases roll animation time by 0.2 seconds per level. max level 3 (minimum 0.25s roll time). costs 100 points + (level × 50).
+
+
point multiplier: decreases the divisor used to calculate points by 0.2 per level. starts at ÷3, eventually becomes ÷1 (meaning you get full rarity value as points). max level 10. costs 150 points + (level × 75).
+
+ legendary 1/90 with no upgrades: 90 ÷ 3 = 30 points
+ with 5 point multiplier upgrades: 90 ÷ 2 = 45 points
+ at max level: 90 ÷ 1 = 90 points!
+
+
+
rarity magnet: each level you get a 1.1x luck boost to get rarities you haven't got before. max level 5.
+
+
point printer: its basically the kinda upgrade you see in most incremental games. every second you get +1 points and depending on how much levels you have on it you can either get 30/sec on level 30, or 300/sec on level 300. there is no max level.
+
+
duplicate chance: every level you get a 1% chance that stacks. every roll yoou're essentially getting a chance to clone that rarity you got into 2. so lets say you rolled common and you get a popup saying that you got a duplicate, you now got 2 commons from that roll. max level 10.
+
+
the potions are simple. you dont need help on potions trust me.
+
+
+
+
gauntlets system
+
+
what are gauntlets?
+
they are a niche feature with auth's RNG! gauntlets are split into tiers, and each require you to get certain rarities. when you acquire all of those rarities you can choose a reward for yourself! sometimes you need multiple of those rarities, sometimes you need this rarity, but it's mainly to reward you of grinding and idling.
+
+
+
+
what is the global gauntlet?
+
that's a gauntlet! (obviously) but it is special because it is GLOBAL. every 2 days the rarities needed to get rewards get rotated, so one day it could be really easy-to-get rarities, but in the next 2 days, it could get to very hard-to-gey rarities. the rarities needed are usually in the medium - hard tiers to let anyone claim a reward from the global gauntlet easily, but not easily at the same time.
+
+
+
other features
+
+
+
do the rarities do anything?
+
not right now. they're mostly so you can collect them, kinda like pokemon cards.
+
+
+
+
do achievements do anything?
+
no. its mostly there to give a sense of progression at the start. they dont do anything.
+
+
+
+
what are run cards?
+
run cards can be generated with the button under "reset data...". when you press the button it generates a summary of your current stats. your rolls, your playtime, your run id, and your rarities. these numbers may not be accurate as the run card logic is held together by duct tape.
+
+
+
+
what are the daily and weekly features?
+
its supposed to keep you on the site HAHAHAHA but the streaks don't do anything, it's just to keep you awfully addicted to the game
+
+
+
+
what does the wishing well do?
+
the wishing well is a bonus feature in auth's RNG. you can trust your luck and get a chance to double the amount of points you put in. you can only put in the amount of points you have. when you throw points into the wishing well, theres a 40% chance that the amount of points you put in will double, and theres a 60% chance that the amount of points you put in will not be doubled. if the points get doubled, you get the final amount. if the points don't get doubled, you dont get anything and you lose the amount of points you put in.
+
+
+
+
what are the keybinds?
+
A and Left Arrow to move pages to left. D and Right Arrow to move pages to right. W to click (just hover your mouse onto something and press W)
+
+
+
ranked mode
+
+
+
what is ranked mode?
+
ranked mode is a way to challenge your friends with pure raw luck! you type out your friend's user id and your friend types out your user id, then you guys battle.
+
+
+
+
do i get anything if i win
+
you get 1 win and get placed on the leaderboard. the leaderboard is for people with the most wins
+
+
+
+
do i lose anything if i lose
+
...no
+
+
+
+
i thought neocities was a static web host? how did you even manage to add servers?
+
i made a service called "haze" as the advanced backend for auth's RNG. i then just made the link a constant to fetch from.
+
+
+
+
why the ranked system?
+
fun
+
+
+
txt
+
+
+
what is txt?
+
txt is a social media platform service purely for auth's RNG players and normal people alike! it's a great way to interact with the community if you dont have discord. you can also link your auth's RNG client TO your txt account to show off that you gamble for fun
+
+
+
+
what does linking do
+
it just puts a badge on your profile in the words of "auth's RNG linked!". it doesnt do anything other than that
+
+
+
+
why txt?
+
because i said so. now go make an account please please please
+
+
+
troubleshooting
+
+
+
i took a daily/weekly and it reset my streak to 1. is it bugged?
+
no, you just missed a day or a week and you lost your streak because of it.
+
+
+
+
i left the tab on auto roll. why didnt i get anything?
+
its almost definitely not auth's RNG itself and its definitely your browser. if you have a browser like Microsoft Edge or Opera GX, those browsers really like to sleep tabs when inactive or not opened for a bit. either stay on the tab where you're playing auth's RNG or change a setting in your browser. look for something like "battery saver" or "sleep tabs" or "resource saving" or "CPU/RAM limiter" and turn them/it off.
+
+
+
+
my file size is under 10 megabytes, why cant i upload it? (custom music)
+
sometimes localStorage gets a bit too aggressive. try compressing it down to under 3 MB so it can upload safely.
+
+
+
+
why isnt music playing?
+
you probably clicked the "mute music" option in settings. uncheck it and music will most definitely work. if music doesnt play still, its your browser. try moving to a different browser like chrome or firefox.
+
+
+
+
why isnt ranked mode working?
+
it may be a CSP or CORS issue, check the console and open an issue in the github repository or post in the nerimity or discord server!
+
+
+
+
why isnt some things working?
+
you found a bug. join the nerimity server linked in the "links and more" page and report in "bugs". or join the discord server and report in #bugs or email me at auth24d@proton.me --- however i may not be active on my email. you can also open a github issue.
+
+
+
← back to game
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 29cf66e..8394219 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,43 @@
# auth's RNG
the repository for auth's RNG!
-all the magic happens in the nightly branch. this branch is for the stable releases for auth's RNG.
+
+
+
+
-https://authsrng.xyz -- stable site
-https://nightly.authsrng.xyz -- bleeding edge, unstable nightly site
+main branch: https://authsrng.xyz (main stable site)
+
+nightly branch: https://nightly.authsrng.xyz (unstable testing branch, but contains the latest pre-versions)
+
+---
+
+# about auth's RNG
+
+auth's RNG can be described as "a web-based, incremental RNG game!"
+
+it has many features, many depths of gameplay, and is overall decently addicting!
+
+roll for rarities, sell-out those rarities, buy upgrades, wish upon the wishing well, and collect the most rarities possible!
+
+auth's RNG is inspired by RNG games on the platform Roblox, such as Sol's RNG and Juke's RNG
+
+---
+
+# versioning notes
+
+this repository starts at version `9.1`. however, the game has been updated since 1.0 beta.
+
+- site archives can be found at https://archive.org with the wayback machine. search https://authsrng.neocities.org - plus possible later archives can be found at https://authsrng.w3spaces.com
+
+- and personal, found archives are at https://archive.org/details/@skunko_lee
+
+the earliest archive can be found on version `5.5`, which is when auth's RNG became open source.
+
+---
+
+# contributing notes
+
+the `.github/workflows` part should NOT be changed or else they change how the development process work. if you do, i will hunt you down with a shovel
+
+refer to `documentation/CONTRIBUTING.md` for further instructions!
diff --git a/_headers b/_headers
new file mode 100644
index 0000000..1564feb
--- /dev/null
+++ b/_headers
@@ -0,0 +1 @@
+Cache-Control: public, max-age=31536000, immutable
\ No newline at end of file
diff --git a/_security b/_security
new file mode 100644
index 0000000..1e22d96
--- /dev/null
+++ b/_security
@@ -0,0 +1 @@
+Contact: mailto:skunkolee@gmail.com
\ No newline at end of file
diff --git a/assets/audio/dayjays.wav b/assets/audio/dayjays.wav
new file mode 100644
index 0000000..61aba8a
Binary files /dev/null and b/assets/audio/dayjays.wav differ
diff --git a/assets/audio/moonlight.mp3 b/assets/audio/moonlight.mp3
new file mode 100644
index 0000000..5efcd11
Binary files /dev/null and b/assets/audio/moonlight.mp3 differ
diff --git a/assets/audio/nocturne.mp3 b/assets/audio/nocturne.mp3
new file mode 100644
index 0000000..7e63d3f
Binary files /dev/null and b/assets/audio/nocturne.mp3 differ
diff --git a/assets/audio/wavelocity.mp3 b/assets/audio/wavelocity.mp3
new file mode 100644
index 0000000..91f8ba3
Binary files /dev/null and b/assets/audio/wavelocity.mp3 differ
diff --git a/assets/audio/welcomecity.mp3 b/assets/audio/welcomecity.mp3
new file mode 100644
index 0000000..984d98e
Binary files /dev/null and b/assets/audio/welcomecity.mp3 differ
diff --git a/assets/images/authsRNG.png b/assets/images/authsRNG.png
new file mode 100644
index 0000000..3b313d7
Binary files /dev/null and b/assets/images/authsRNG.png differ
diff --git a/assets/scripts/main.js b/assets/scripts/main.js
new file mode 100644
index 0000000..6c7c9f4
--- /dev/null
+++ b/assets/scripts/main.js
@@ -0,0 +1,2759 @@
+(function () {
+ var s = document.createElement('script');
+ s.src = 'legacy-polyfills.js';
+ s.async = false;
+ document.head.appendChild(s);
+})();
+
+const rollBtn = document.getElementById('rollBtn'),
+ spinner = document.getElementById('spinner'),
+ inventoryList = document.getElementById('inventoryList'),
+ resetBtn = document.getElementById('resetBtn'),
+ totalRollsEl = document.getElementById('totalRolls'),
+ achievementsContainer = document.getElementById('achievementsContainer');
+
+const POINTS_KEY = 'shopPoints';
+const SHOP_UPGRADES_KEY = 'shopUpgrades';
+const SOLD_OUT_KEY = 'soldOutRarities';
+
+let points = 0;
+let shopUpgrades = {
+ luck: 0,
+ speed: 0,
+ pointMult: 0,
+ magnet: 0,
+ printer: 0,
+ duplicate: 0,
+};
+let soldOutRarities = new Map();
+let rollSpeed = 1.0;
+let shopLuckMultiplier = 1.0;
+let pointDivisor = 3.0;
+
+const STORAGE_KEY = 'rarityInventory',
+ TOTAL_ROLLS_KEY = 'totalRolls',
+ ACHIEVEMENTS_KEY = 'achievementsUnlocked';
+
+const ANOMALIES_KEY = 'anomalies';
+const ANOMALIES_USED_KEY = 'anomaliesUsed';
+let anomalies = 0;
+let anomaliesUsed = 0;
+
+const POTIONS_KEY = 'playerPotions';
+const ACTIVE_POTIONS_KEY = 'activePotions';
+
+let playerPotions = {
+ luck2x: 0,
+ luck4x: 0,
+ luck10x: 0,
+ luck50x: 0,
+ luck100x: 0,
+ luck150x: 0,
+ luck250x: 0,
+ luck300x: 0,
+ duplicate: 0,
+};
+
+let activePotions = [];
+let potionLuckMultiplier = 1;
+let duplicateRollsLeft = 0;
+
+const potionData = {
+ luck2x: {
+ name: '2x luck',
+ mult: 2,
+ duration: 30000,
+ cost: 2000,
+ emoji: '✨',
+ },
+ luck4x: {
+ name: '4x luck',
+ mult: 4,
+ duration: 30000,
+ cost: 5000,
+ emoji: '💫',
+ },
+ luck10x: {
+ name: '10x luck',
+ mult: 10,
+ duration: 30000,
+ cost: 15000,
+ emoji: '🌟',
+ },
+ luck50x: {
+ name: '50x luck',
+ mult: 50,
+ duration: 30000,
+ cost: 30000,
+ emoji: '⭐',
+ },
+ luck100x: {
+ name: '100x luck',
+ mult: 100,
+ duration: 30000,
+ cost: 45000,
+ emoji: '🔥',
+ },
+ luck150x: {
+ name: '150x luck',
+ mult: 150,
+ duration: 30000,
+ cost: 60000,
+ emoji: '💥',
+ },
+ luck250x: {
+ name: '250x luck',
+ mult: 250,
+ duration: 30000,
+ cost: 80000,
+ emoji: '⚡',
+ },
+ luck300x: {
+ name: 'OMEGA LUCK',
+ mult: 300,
+ duration: 30000,
+ cost: 150000,
+ emoji: '💎',
+ },
+ duplicate: { name: 'duplicate', rolls: 10, cost: 5000, emoji: '🎭' },
+};
+
+function calculateRarityPoints(rarity) {
+ const denom = Math.round(1 / rarity.chance);
+ return Math.ceil(denom / pointDivisor);
+}
+
+function updatePointsDisplay() {
+ document.getElementById('pointsValue').textContent = points;
+}
+
+function updateShopUI() {
+ document.getElementById('luckLevel').textContent = shopUpgrades.luck;
+ document.getElementById('speedLevel').textContent = shopUpgrades.speed;
+ document.getElementById('pointLevel').textContent = shopUpgrades.pointMult;
+
+ const luckCost = Math.floor(25 + shopUpgrades.luck * shopUpgrades.luck * 15);
+ const speedCost = Math.floor(
+ 50 + shopUpgrades.speed * shopUpgrades.speed * 55,
+ );
+ const pointCost = Math.floor(
+ 100 + shopUpgrades.pointMult * shopUpgrades.pointMult * 35,
+ );
+
+ // Update button text to show costs
+ const luckBtn = document.getElementById('buyLuckBtn');
+ const speedBtn = document.getElementById('buySpeedBtn');
+ const pointBtn = document.getElementById('buyPointBtn');
+
+ if (luckBtn) luckBtn.textContent = `buy luck upgrade (${luckCost} pts)`;
+ if (speedBtn) speedBtn.textContent = `buy speed upgrade (${speedCost} pts)`;
+ if (pointBtn) pointBtn.textContent = `buy points upgrade (${pointCost} pts)`;
+
+ // Disable buttons if can't afford or maxed out
+ if (luckBtn) luckBtn.disabled = points < luckCost || shopUpgrades.luck >= 100;
+ if (speedBtn)
+ speedBtn.disabled = points < speedCost || shopUpgrades.speed >= 3;
+ if (pointBtn)
+ pointBtn.disabled = points < pointCost || shopUpgrades.pointMult >= 10;
+
+ const magnetLevelEl = document.getElementById('magnetLevel');
+ const printerLevelEl = document.getElementById('printerLevel');
+ const dupeLevelEl = document.getElementById('dupeLevel');
+
+ if (magnetLevelEl) magnetLevelEl.textContent = shopUpgrades.magnet || 0;
+ if (printerLevelEl) printerLevelEl.textContent = shopUpgrades.printer || 0;
+ if (dupeLevelEl) dupeLevelEl.textContent = shopUpgrades.duplicate || 0;
+
+ const magnetCost = 500 + (shopUpgrades.magnet || 0) * 1000;
+ const printerCost =
+ 1000 + (shopUpgrades.printer || 0) * (shopUpgrades.printer || 0) * 500;
+ const dupeCost =
+ 800 + (shopUpgrades.duplicate || 0) * (shopUpgrades.duplicate || 0) * 400;
+
+ const magnetBtn = document.getElementById('buyMagnetBtn');
+ const printerBtn = document.getElementById('buyPrinterBtn');
+ const dupeBtn = document.getElementById('buyDupeBtn');
+
+ if (magnetBtn) {
+ magnetBtn.textContent = `upgrade (${magnetCost} pts)`;
+ magnetBtn.disabled = points < magnetCost || (shopUpgrades.magnet || 0) >= 5;
+ }
+ if (printerBtn) {
+ printerBtn.textContent = `upgrade (${printerCost} pts)`;
+ printerBtn.disabled = points < printerCost;
+ }
+ if (dupeBtn) {
+ dupeBtn.textContent = `upgrade (${dupeCost} pts)`;
+ dupeBtn.disabled = points < dupeCost || (shopUpgrades.duplicate || 0) >= 10;
+ }
+}
+
+function updatePotionUI() {
+ for (const [key, count] of Object.entries(playerPotions)) {
+ const countEl = document.getElementById(`potion-${key}-count`);
+ if (countEl) countEl.textContent = count;
+ }
+}
+
+function buyPotion(potionType) {
+ const data = potionData[potionType];
+ if (!data) return;
+
+ if (points >= data.cost) {
+ points -= data.cost;
+ playerPotions[potionType]++;
+ updatePointsDisplay();
+ updatePotionUI();
+ saveAllData();
+ showAnomalyPopup(`bought ${data.emoji} ${data.name}!`);
+ } else {
+ alert(`need ${data.cost} points!`);
+ }
+}
+
+function usePotion(potionType) {
+ if (playerPotions[potionType] <= 0) {
+ alert(`you don't have any ${potionData[potionType].name} potions!`);
+ return;
+ }
+
+ const data = potionData[potionType];
+
+ if (potionType === 'duplicate') {
+ duplicateRollsLeft = data.rolls;
+ playerPotions[potionType]--;
+ updatePotionUI();
+ saveAllData();
+ showAnomalyPopup(`${data.emoji} next ${data.rolls} rolls will be x2!`);
+ return;
+ }
+
+ // Luck potions
+ const endTime = Date.now() + data.duration;
+ activePotions.push({
+ type: potionType,
+ endTime: endTime,
+ multiplier: data.mult,
+ });
+
+ playerPotions[potionType]--;
+ recalcPotionLuck();
+ updatePotionUI();
+ updateActivePotionsDisplay();
+ saveAllData();
+ showAnomalyPopup(`${data.emoji} ${data.name} activated!`);
+}
+
+function recalcPotionLuck() {
+ potionLuckMultiplier = 1;
+ activePotions = activePotions.filter((p) => p.endTime > Date.now());
+
+ activePotions.forEach((p) => {
+ potionLuckMultiplier *= p.multiplier;
+ });
+
+ updateLuckDisplay();
+}
+
+function updateActivePotionsDisplay() {
+ const display = document.getElementById('activePotionsDisplay');
+ const list = document.getElementById('activePotionsList');
+
+ if (!display || !list) return;
+
+ if (activePotions.length === 0 && duplicateRollsLeft === 0) {
+ display.style.display = 'none';
+ return;
+ }
+
+ display.style.display = 'block';
+ list.innerHTML = '';
+
+ activePotions.forEach((p) => {
+ const data = potionData[p.type];
+ const timeLeft = Math.ceil((p.endTime - Date.now()) / 1000);
+
+ const div = document.createElement('div');
+ div.className = 'active-potion';
+ div.innerHTML = `
+