diff --git a/src/dynamic_routes.py b/src/dynamic_routes.py index f66647b..cc99d18 100644 --- a/src/dynamic_routes.py +++ b/src/dynamic_routes.py @@ -1,7 +1,12 @@ # Imports -from flask import Blueprint, render_template, abort +from flask import Blueprint, render_template, abort, request import os, markdown +try: + from src.name import get_name +except ImportError: + from name import get_name + # Create blueprint bp = Blueprint('dynamic_routes', __name__) @@ -33,20 +38,22 @@ def catch_all(filename): return render_template( 'bases/directory.html', directory=filename + "/" if not filename.endswith('/') else filename, - pages=ListFiles(filename) + pages=ListFiles(filename), + name=get_name(request) ) - return render_template(f'pages/{filename}') + return render_template(f'pages/{filename}', name=get_name(request)) elif os.path.exists(get_path(filename + '.html')): - return render_template(f'pages/{filename}.html') + return render_template(f'pages/{filename}.html', name=get_name(request)) elif os.path.exists(get_path(filename + '.md')): output = markdown.markdown(open(get_path(filename + '.md'), "r").read()) return render_template( f'bases/md.html', title = filename.split("/")[-1], - markdown = output + markdown = output, + name=get_name(request) ) else: diff --git a/src/errors.py b/src/errors.py index 77abdf1..6e25401 100644 --- a/src/errors.py +++ b/src/errors.py @@ -1,6 +1,10 @@ -from flask import Blueprint, render_template +from flask import Blueprint, render_template, request from werkzeug.exceptions import HTTPException -from os import getenv as env + +try: + from src.name import get_name +except ImportError: + from name import get_name bp = Blueprint("errors", __name__) @@ -9,19 +13,19 @@ bp = Blueprint("errors", __name__) @bp.route('/500') @bp.app_errorhandler(500) def internal_server_error(error:HTTPException=None): - return render_template('errors/500.html', error=error), 500 + return render_template('errors/500.html', error=error, name=get_name(request)), 500 @bp.route('/404') @bp.app_errorhandler(404) def not_found(error:HTTPException=None): - return render_template('errors/404.html', error=error), 404 + return render_template('errors/404.html', error=error, name=get_name(request)), 404 @bp.route('/400') @bp.app_errorhandler(400) def bad_request(error:HTTPException=None): - return render_template('errors/400.html', error=error), 400 + return render_template('errors/400.html', error=error, name=get_name(request)), 400 @bp.route('/idk') @@ -35,5 +39,6 @@ def idk(error:HTTPException=None): 'errors/error.html', code = error.code, description = error.description, - name = error.name + err_name = error.name, + name=get_name(request) ), error.code \ No newline at end of file diff --git a/src/main.py b/src/main.py index c66e80d..47f1cde 100644 --- a/src/main.py +++ b/src/main.py @@ -1,5 +1,5 @@ # IMPORTS -from flask import Flask, render_template +from flask import Flask, render_template, request from os import getenv as env import logging @@ -7,8 +7,10 @@ try: import src.dynamic_routes as dynamic_routes import src.errors as errors import src.pg_log as pg_log + from src.name import get_name except ImportError: import dynamic_routes, errors, pg_log + from name import get_name from dotenv import load_dotenv load_dotenv() @@ -60,11 +62,16 @@ log.info("Blueprints registered.") # ROUTES @app.route("/") def index(): - return render_template("index.html") + return render_template("index.html", name=get_name(request)) @app.route("/toaster") def toaster(): - return render_template("toaster.html") + return render_template("toaster.html", name=get_name(request)) + +@app.route("/terminal") +def terminal(): + return render_template("terminal.html", name=get_name(request)) + # DEBUG (DONT RUN LIKE THIS IN PROD) diff --git a/src/name.py b/src/name.py new file mode 100644 index 0000000..d80b035 --- /dev/null +++ b/src/name.py @@ -0,0 +1,5 @@ +def get_name(req): + if req.headers.get("Host") == "proot.uk": + return "Toaster" + else: + return "Alfie King" \ No newline at end of file diff --git a/static/content/fonts/ultrakill-font-2.woff2 b/static/content/fonts/ultrakill-font-2.woff2 new file mode 100644 index 0000000..b3feb3b Binary files /dev/null and b/static/content/fonts/ultrakill-font-2.woff2 differ diff --git a/static/content/fonts/ultrakill-font.woff2 b/static/content/fonts/ultrakill-font.woff2 new file mode 100644 index 0000000..2ab5e93 Binary files /dev/null and b/static/content/fonts/ultrakill-font.woff2 differ diff --git a/static/content/smileos/KITR_Build.webp b/static/content/smileos/KITR_Build.webp new file mode 100644 index 0000000..ac4b552 Binary files /dev/null and b/static/content/smileos/KITR_Build.webp differ diff --git a/static/content/smileos/Shopmusic.ogx b/static/content/smileos/Shopmusic.ogx new file mode 100644 index 0000000..83bc1c2 Binary files /dev/null and b/static/content/smileos/Shopmusic.ogx differ diff --git a/static/content/smileos/SmileOS2.webp b/static/content/smileos/SmileOS2.webp new file mode 100644 index 0000000..4fab0cc Binary files /dev/null and b/static/content/smileos/SmileOS2.webp differ diff --git a/static/content/smileos/SmileOS2Click.ogx b/static/content/smileos/SmileOS2Click.ogx new file mode 100644 index 0000000..ab82a6f Binary files /dev/null and b/static/content/smileos/SmileOS2Click.ogx differ diff --git a/static/content/smileos/SmileOS2Startup.ogx b/static/content/smileos/SmileOS2Startup.ogx new file mode 100644 index 0000000..16b811b Binary files /dev/null and b/static/content/smileos/SmileOS2Startup.ogx differ diff --git a/static/content/smileos/SmileOS_2_Box.webp b/static/content/smileos/SmileOS_2_Box.webp new file mode 100644 index 0000000..359bdac Binary files /dev/null and b/static/content/smileos/SmileOS_2_Box.webp differ diff --git a/static/content/smileos/SmileOS_2_Button_Background.png b/static/content/smileos/SmileOS_2_Button_Background.png new file mode 100644 index 0000000..a3d4288 Binary files /dev/null and b/static/content/smileos/SmileOS_2_Button_Background.png differ diff --git a/static/content/smileos/SmileOS_2_Button_transparent.png b/static/content/smileos/SmileOS_2_Button_transparent.png new file mode 100644 index 0000000..62995bd Binary files /dev/null and b/static/content/smileos/SmileOS_2_Button_transparent.png differ diff --git a/static/content/smileos/SmileOS_2_Content.webp b/static/content/smileos/SmileOS_2_Content.webp new file mode 100644 index 0000000..328676a Binary files /dev/null and b/static/content/smileos/SmileOS_2_Content.webp differ diff --git a/static/content/smileos/SmileOS_2_Header.webp b/static/content/smileos/SmileOS_2_Header.webp new file mode 100644 index 0000000..2873ad6 Binary files /dev/null and b/static/content/smileos/SmileOS_2_Header.webp differ diff --git a/static/content/smileos/SmileOS_2_icon_smile.webp b/static/content/smileos/SmileOS_2_icon_smile.webp new file mode 100644 index 0000000..2a8490f Binary files /dev/null and b/static/content/smileos/SmileOS_2_icon_smile.webp differ diff --git a/static/content/smileos/SmileOS_2_icon_tip.webp b/static/content/smileos/SmileOS_2_icon_tip.webp new file mode 100644 index 0000000..30e52cc Binary files /dev/null and b/static/content/smileos/SmileOS_2_icon_tip.webp differ diff --git a/static/content/smileos/SmileOS_2_inset_panel.webp b/static/content/smileos/SmileOS_2_inset_panel.webp new file mode 100644 index 0000000..dec3df6 Binary files /dev/null and b/static/content/smileos/SmileOS_2_inset_panel.webp differ diff --git a/static/content/smileos/SmileOS_2_top_button_3.png b/static/content/smileos/SmileOS_2_top_button_3.png new file mode 100644 index 0000000..e6e760b Binary files /dev/null and b/static/content/smileos/SmileOS_2_top_button_3.png differ diff --git a/static/content/smileos/SmileOS_2_top_button_4.png b/static/content/smileos/SmileOS_2_top_button_4.png new file mode 100644 index 0000000..fa8ae73 Binary files /dev/null and b/static/content/smileos/SmileOS_2_top_button_4.png differ diff --git a/static/content/smileos/SmileOS_2_top_button_5.png b/static/content/smileos/SmileOS_2_top_button_5.png new file mode 100644 index 0000000..340a9ed Binary files /dev/null and b/static/content/smileos/SmileOS_2_top_button_5.png differ diff --git a/static/content/toaster/Toaster_v1.0_sticker.png b/static/content/toaster/Toaster_v1.0_sticker.png new file mode 100644 index 0000000..15506f9 Binary files /dev/null and b/static/content/toaster/Toaster_v1.0_sticker.png differ diff --git a/static/css/bases/base.css b/static/css/bases/base.css index f19b44f..536d500 100644 --- a/static/css/bases/base.css +++ b/static/css/bases/base.css @@ -11,6 +11,18 @@ font-weight:normal; font-style:normal; } +@font-face { + font-family:"Ultrafont"; + src:url("/static/content/fonts/ultrakill-font.woff2") format("woff2"); + font-weight:normal; + font-style:normal; +} +@font-face { + font-family:"Ultrafont2"; + src:url("/static/content/fonts/ultrakill-font-2.woff2") format("woff2"); + font-weight:normal; + font-style:normal; +} :root { --primary-color: #5cdd8b; @@ -24,6 +36,10 @@ --title-font: 'Roboto Mono', sans-serif; --irken-font: 'Irken'; --scratch-font: 'Scratch'; + --ultrafont-font: 'Ultrafont'; + --smileos2-box: url(/static/content/smileos/SmileOS_2_Box.webp) 17 3 3 fill / 51px 9px 9px; + --smileos2-font: 'Ultrafont2'; + --smileos2-emphasis: #FF4343; } body { @@ -227,6 +243,15 @@ main section a { text-decoration: none; } +.smileos { + border-image: var(--smileos2-box); + padding: 54px 15px 12px; + image-rendering: pixelated; + font-size: 1.25rem; + font-family: var(--smileos2-font); + color: #fff; +} + #furry { position: fixed; left: 0; @@ -255,6 +280,10 @@ main section a { font-family: var(--scratch-font); } +.ultrafont { + font-family: var(--ultrafont-font); +} + #alt-nav { display: none; backdrop-filter: blur(2px) brightness(0.6); diff --git a/static/css/terminal.css b/static/css/terminal.css new file mode 100644 index 0000000..752fb5d --- /dev/null +++ b/static/css/terminal.css @@ -0,0 +1,122 @@ +@font-face { + font-family:"Ultrafont2"; + src:url("/static/content/fonts/ultrakill-font-2.woff2") format("woff2"); + font-weight:normal; + font-style:normal; +} + +#terminal { + aspect-ratio: 4/3; + padding: 0; + font-family: "Ultrafont2"; + font-size: 1.2rem; + color: #ffffff; + border: none; +} + +.smileos-header { + height: 9%; + border-image: url(/static/content/smileos/SmileOS_2_Header.webp) 3 fill / 9px; + display: flex; + flex-direction: row; + align-items: center; + padding: 0; + font-size: 1.4rem; + font-weight: 900; + padding-left: 7px; + padding-right: 7px; + image-rendering: pixelated; +} + +.smileos-header img { + height: 100%; + object-fit: contain; +} + +#terminal-container { + border-image: url(/static/content/smileos/SmileOS_2_Content.webp) 1 3 3 fill / 3px 9px 9px; + height: 100%; + display: grid; + grid-template-areas: + "logo window" + "buttons window"; + grid-template-columns: 40% 1fr; + grid-template-rows: 25% 1fr; + padding: 15px; + box-sizing: border-box; + image-rendering: pixelated; +} + +#smileos-logo { + width: 250px; + grid-area: logo; + margin: auto; + image-rendering: pixelated; +} + +#terminal-window { + height: 100%; + grid-area: window; +} + +#window-container { + border-image: url(/static/content/smileos/SmileOS_2_Content.webp) 1 3 3 fill / 3px 9px 9px; + height: 91%; + padding: 35px; + box-sizing: border-box; + image-rendering: pixelated; +} + +#window-content { + border-image: url(/static/content/smileos/SmileOS_2_inset_panel.webp) 1 fill / 3px; + height: 100%; + box-sizing: border-box; + padding: 15px; + display: flex; + justify-content: center; + align-items: center; + text-align: center; + image-rendering: pixelated; +} + +.red { + color: #ff4343; +} + +#terminal-buttons { + grid-area: buttons; + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; +} + +.terminal-button { + border-image: url(/static/content/smileos/SmileOS_2_Button_transparent.png) 2 / 9px; + background: url(/static/content/smileos/SmileOS_2_Button_Background.png); + background-repeat: repeat-x; + background-size: 100% 100%; + border-radius: 15px; + height: 75px; + width: 270px; + image-rendering: pixelated; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + font-family: "Ultrafont2"; + font-size: 1.2rem; + color: #ffffff; +} + +.terminal-button:hover { + filter: contrast(110%); +} + +.terminal-button:active { + filter: contrast(125%); +} + +#smileos-window-content img { + width: 100%; +} \ No newline at end of file diff --git a/static/js/smileos.js b/static/js/smileos.js new file mode 100644 index 0000000..47debfe --- /dev/null +++ b/static/js/smileos.js @@ -0,0 +1,95 @@ +const tips_of_the_day = [ + `The Revolver deals locational damage.
A headshot deals 2x damage and a limbshot deals 1.5x damage.`, + `Dash: Fully invincible, costs stamina
Slide: Greater distance, no invincibility
Jump: Quickly out of melee range, less control`, + `Shotgun parries: A point-blank Shotgun shot to the torso right before an enemy attack lands will deal massive damage.`, + `Attack sound cues allow you to keep track of enemies who are off screen.`, + `Some enemies make idle sounds to make them easier to track.`, + `Use the ATTRACTOR NAILGUN's magnets to form concentrated orbs of nails that can be moved around using the pull force of other magnets.`, + `Enemies can hurt other enemy types. With quick thinking and positioning, powerful enemies can turn into powerful weapons.`, + `The ATTRACTOR NAILGUN's magnets can be attached to enemies to make mobile targets easy to hit with nails.`, + `Enemies scream when falling from a fatal height.`, + `SLAM BOUNCING: Jump immediately after landing from a ground slam to jump higher. The longer the ground slam fall, the higher the bounce.`, + `RAILCANNON variations all share the same cooldown. Choose wisely which variation best fits the situation.`, + `SLIDING will retain previous momentum for a short amount of time. Chaining quick SLIDE JUMPS after a DASH JUMP will give you incredible sustained speed.`, + `Environmental hazards such as harmful liquids will hurt enemies as well.`, + `If you're having trouble keeping up with a tough enemy, stand back and observe. Every enemy has its tells and patterns and learning those can be your key to victory.`, + `HITSCAN weapons can be used to hit the shotgun's CORE EJECT in mid-air to increase its damage and blast radius.`, + `POWER-UPS can be stacked.`, + `Hitting an enemy with only the edge of an explosion will launch them without dealing much damage, making it a risky but effective tool against Stalkers.`, + `Airborne coins can be shot with any hitscan weapon.`, + `Falling underwater is slow, but a ground slam allows for a quick return to the ground.`, + `Sliding onto water will cause one to skip across its surface.`, + `If an enemy is blessed by an Idol, a direct visible connection is formed between the two, allowing one to easily track down and destroy the protector.`, + `Explosions deflect projectiles.

If an explosion is caused right from where an enemy shoots a projectile, it can backfire and hit them instead.`, + `The space of a large arena can be used to one's advantage. Using the environment to break line-of-sight with enemies allows for some breathing room and time to consider target prioritization.`, + `DON'T WASTE STAMINA! Dashing needlessly while fighting very aggressive foes will quickly cause one to have none left when it is most needed.`, + `Homing projectiles may be more difficult to dodge, but their tracking and slower speed makes them much easier to parry.`, + `Mannequins can be hard to hit due to their speed, but they lose air control when launched or shot down from a surface, making them unable to move for a short moment.`, + `The Knuckleblaster's blast wave is also capable of breaking a Gutterman's shield, and is much easier to land in a chaotic scenario.`, + `A direct hit from the Knuckleblaster has extremely powerful knockback, making it extremely powerful for launching enemies into pits and other environmental hazards.`, + `Didn't expect me, huh?`, + `Magenta colored attacks can not be dashed through and must be avoided entirely.`, + `Blood Puppets do not grant kills or style points, but their blood can still heal.`, + `When facing down a difficult foe, it may be beneficial to first get rid of the fodder to reduce distractions.`, + `Sometimes it may be more beneficial to stay at a distance and wait for an opening before getting close.`, + `If you're having trouble with a specific encounter, take a moment to weigh your options.
There may be some trick, tool or alternative prioritization that will tip the scales in your favor.`, + `ENEMY STEP: Jump while in mid-air near an enemy to jump off the enemy. This resets the amount of available walljumps without needing to land.`, + `Parries can be used as a powerful healing tool.

Parrying any enemy projectile or melee attack will fully replenish your health up to the hard damage limit.`, + `H a v e   f u n .`, + `If blown too far off the arena, PUMP CHARGE's overcharge is a good way to get back.`, + `CHEATS can be enabled in other levels by inputting 🡡 🡡 🡣 🡣 🡠 🡢 🡠 🡢 B A Enabling cheats will disable ranks`, + `You can pick up the cut weapons on the second floor.` +] + + +var click = new Audio('/static/content/smileos/SmileOS2Click.ogx'); + +document.getElementById("smileos-about").addEventListener("click", function() { + click.play(); + document.getElementById("smileos-window-title").innerHTML = "About"; + document.getElementById("smileos-window-content").innerHTML = ` + SmileOS: is the operating system found on most digital interfaces found throughout + Hell. SmileOS 1.0 is employed on pannels despite its poor user and developer experience to conserve + blood after the war, while SmileOS 2.0 is used for terminals requireing higher blood consumption. + `; +}); + +document.getElementById("smileos-snake").addEventListener("click", function() { + click.play(); + document.getElementById("smileos-window-title").innerHTML = "Snake"; + document.getElementById("smileos-window-content").innerHTML = ` + under construction + `; +}); + +document.getElementById("smileos-leaderboard").addEventListener("click", function() { + click.play(); + document.getElementById("smileos-window-title").innerHTML = "Leaderboard"; + document.getElementById("smileos-window-content").innerHTML = ` + under construction + `; +}); + +document.getElementById("smileos-tip").addEventListener("click", function() { + click.play(); + document.getElementById("smileos-window-title").innerHTML = "Tip of the Day"; + document.getElementById("smileos-window-content").innerHTML = tips_of_the_day[Math.floor(Math.random() * tips_of_the_day.length)]; +}); + +async function playAudio(url) { + return new Promise((resolve) => { + const audio = new Audio(url); + audio.addEventListener('ended', resolve); // Resolve the promise when audio ends + audio.play(); + }); +} + +document.addEventListener("DOMContentLoaded", async function() { + document.getElementById("smileos-window-title").innerHTML = "Tip of the Day"; + document.getElementById("smileos-window-content").innerHTML = tips_of_the_day[Math.floor(Math.random() * tips_of_the_day.length)]; + await playAudio('/static/content/smileos/SmileOS2Startup.ogx'); + + var music = new Audio('/static/content/smileos/Shopmusic.ogx'); + music.loop = true; + music.play(); +}); \ No newline at end of file diff --git a/templates/bases/base.html b/templates/bases/base.html index a92e0a1..e640e13 100644 --- a/templates/bases/base.html +++ b/templates/bases/base.html @@ -3,7 +3,7 @@ - {% block title %}Alfie's basement{% endblock %} + {% block title %}{{ name }}'s basement{% endblock %} @@ -11,11 +11,11 @@ - - + + - + {% block head %} {% endblock %} @@ -28,6 +28,7 @@