it just works™️

pull/22/head
geese_suck 2022-11-26 20:26:48 -08:00
parent ae50cc2772
commit e3349605d4
Signed by: geese_suck
GPG Key ID: 4D09E4B0A7264746
66 changed files with 3117 additions and 9 deletions

66
events/__init__.py 100644
View File

@ -0,0 +1,66 @@
from os import path
import subprocess
from importlib import import_module
from files.__main__ import app, db_session, engine
from flask import g
from sqlalchemy import inspect
from files.helpers.const import AWARDS2, AWARDS_DISABLED
from .table import Event
from .columns import *
from events.classes import *
from events.helpers import *
from events.routes import *
def link_assets():
asset_dirs = { # We assume WD is always in root of repository
"files/assets/css": "../../../events/assets/css",
"files/assets/js": "../../../events/assets/js",
"files/assets/fonts": "../../../events/assets/fonts",
"files/assets/images": "../../../events/assets/images",
"files/assets/media": "../../../events/assets/media",
"files/templates": "../../events/templates",
}
print("[EVENT] Linking event assets...")
for link_dir in asset_dirs:
target = asset_dirs[link_dir]
link = link_dir + "/event"
try:
if path.exists(link):
subprocess.run(["rm", link])
subprocess.run(["ln", "-s", target, link])
print("[EVENT] Linked " + link + " -> " + target)
except Exception as e:
print(e)
def build_table():
if not inspect(engine).has_table("event", schema="public"):
print("[EVENT] Building event table...")
with app.app_context():
g.db = db_session()
Event.__table__.create(bind=g.db.bind, checkfirst=True)
g.db.commit()
def populate_awards():
temp = {x: AWARDS2[x] for x in AWARDS2 if x not in EVENT_AWARDS}
AWARDS2.clear()
AWARDS2.update(EVENT_AWARDS)
AWARDS2.update(temp)
for award in EVENT_AWARDS:
if award in AWARDS_DISABLED:
AWARDS_DISABLED.remove(award)
def init_event():
link_assets()
build_table()
populate_awards()

View File

@ -0,0 +1,224 @@
/* text */
#banner-halloween-title.life > tspan {
opacity: 1;
}
#banner-halloween-title-II {
text-shadow: 0 4px 10px #ff000060;
}
#banner-halloween-title.life > #banner-halloween-title-II {
animation: blinker 0.5s forwards;
}
@media (max-width: 767.98px) {
#banner-halloween-title {
transform: scale(1.4) translate(-90px, -120px);
animation:none !important;
}
#banner-halloween-presenting {
transform: scale(1.4) translate(-90px, -120px);
}
#banner-halloween-bats {
display:none;
}
}
@keyframes float {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-6px);
}
100% {
transform: translateY(0px);
}
}
@keyframes blinker {
10% {
opacity: 0;
}
,
30% {
opacity: 0.4;
}
,
60% {
opacity: 0.2;
}
,
85% {
opacity: 0.5;
}
,
100% {
opacity: 0.9;
}
}
/*days*/
:root {
/*sky*/
--sky-gradient-day1: radial-gradient(at bottom, #d43a27 25%, #761ab3 100%);
--sky-gradient-day2: radial-gradient(at bottom, #bf055c 25%, #6b007d 70%);
--sky-gradient-day3: radial-gradient(at bottom, #bf0583 5%, #560272 60%);
--sky-gradient-day4: radial-gradient(at bottom, #930184 -15%, #490272 60%);
--sky-gradient-day5: radial-gradient(at bottom, #800073 -55%, #400179 60%);
--sky-gradient-day6: radial-gradient(at bottom, #69017a 25%, #390271 70%);
--sky-gradient-day7: radial-gradient(at bottom, #69017a 25%, #2d005b 70%);
--sky-gradient-day8: radial-gradient(at bottom, #af00a6 -20%, #270146 70%);
--sky-gradient-day9: radial-gradient(at bottom, #69047b -10%, #1e0037 70%);
--sky-gradient-day10: radial-gradient(at bottom, #59047b 10%, #150026 70%);
/*moon*/
--moon-fill-day1:gold;
--moon-fill-day2:gold;
--moon-fill-day3:goldenrod;
--moon-fill-day4:none;
--moon-fill-day5:none;
--moon-fill-day6:#e4e4e4;
--moon-fill-day7:#e4e4e4;
--moon-fill-day8:#e4e4e4;
--moon-fill-day9:#e4e4e4;
--moon-fill-day10:#e4e4e4;
--moon-shadow-day1:drop-shadow(0px 0px 20px yellow);
--moon-shadow-day2:drop-shadow(0px 0px 20px yellow);
--moon-shadow-day3:drop-shadow(0px 0px 20px gold);
--moon-shadow-day4:none;
--moon-shadow-day5:none;
--moon-shadow-day6:drop-shadow(0px 0px 5px #deddcf);
--moon-shadow-day7:drop-shadow(0px 0px 10px #deddcf);
--moon-shadow-day8:drop-shadow(0px 0px 10px #deddcf);
--moon-shadow-day9:drop-shadow(0px 0px 10px #deddcf);
--moon-shadow-day10:drop-shadow(0px 0px 10px #deddcf);
--moon-position-day1:303;
--moon-position-day2:308;
--moon-position-day3:320;
--moon-position-day4:350;
--moon-position-day5:350;
--moon-position-day6:322;
--moon-position-day7:312;
--moon-position-day8:308;
--moon-position-day9:303;
--moon-position-day10:300;
/*ground*/
--ground-shadow-day1:#5818bd;
--ground-shadow-day2:#5818bd;
--ground-shadow-day3:#5818bd;
--ground-shadow-day4:#5818bd;
--ground-shadow-day5:#5818bd;
--ground-shadow-day6:#5818bd;
--ground-shadow-day7:#4e16a6;
--ground-shadow-day8:#51009a;
--ground-shadow-day9:#4b028c;
--ground-shadow-day10:#41017b;
--house-shadow-day1:#5818bd;
--house-shadow-day2:#5818bd;
--house-shadow-day3:#5818bd;
--house-shadow-day4:#5818bd;
--house-shadow-day5:#5818bd;
--house-shadow-day6:#5818bd;
--house-shadow-day7:#5818bd;
--house-shadow-day8:#4a149f;
--house-shadow-day9:#431290;
--house-shadow-day10:#3a1476;
--object-fill-day1:#240441;
--object-fill-day2:#240441;
--object-fill-day3:#240441;
--object-fill-day4:#240441;
--object-fill-day5:#240441;
--object-fill-day6:#240441;
--object-fill-day7:#240441;
--object-fill-day8:#1e0538;
--object-fill-day9:#18042c;
--object-fill-day10:#18042c;
--star-opacity-day1: 0;
--star-opacity-day2: 0;
--star-opacity-day3: 0;
--star-opacity-day4: 0.2;
--star-opacity-day5: 0.3;
--star-opacity-day6: 0.4;
--star-opacity-day7: 0.5;
--star-opacity-day8: 0.5;
--star-opacity-day9: 0.6;
--star-opacity-day10: 0.7;
}
/* stars */
.star {
animation: linear infinite alternate twinkle;
}
.star1 {
animation-duration: 3s;
}
.star2 {
animation-duration: 4s;
}
.star3 {
animation-duration: 3.5s;
}
.star4 {
animation-duration: 2s;
}
.star5 {
animation-duration: 4s;
}
.star1 circle {
r: 0.5;
}
.star2 circle {
r: 0.75;
}
.star3 circle {
r: 1.0;
}
.star4 circle {
r: 1.2;
}
.star5 circle {
r: 1.5;
}
@media (max-width: 767.98px) {
.star {
animation: none;
fill-opacity: 0.5;
}
.star1 circle {
r: 1;
}
.star2 circle {
r: 1.5;
}
.star3 circle {
r: 2;
}
.star4 circle {
r: 2;
}
.star5 circle {
r: 2.5;
}
}
@keyframes twinkle {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}

View File

@ -0,0 +1 @@
../../../events/assets/css

View File

@ -0,0 +1,872 @@
@charset "UTF-8";
/* Fonts */
@import url("https://fonts.googleapis.com/css2?family=Creepster&display=swap");
@font-face {
font-family: "DoubleFeature";
src: url("/assets/fonts/event/DoubleFeature.woff") format("woff");
}
@font-face {
font-family: "Jo_wrote_a_lovesong";
src: url("/assets/fonts/event/Jo_wrote_a_lovesong.woff") format("woff");
}
@font-face {
font-family: "XTypewriter-Regular";
src: url("/assets/fonts/event/XTypewriter-Regular.woff") format("woff");
}
@font-face {
font-family: "SpecialElite-Regular";
src: url("/assets/fonts/event/SpecialElite-Regular.woff") format("woff");
}
/* Halloween Theming */
:root {
--primary: #F66A3C;
--dark: #140224;
--secondary: #820263;
--white: #E1E1E1;
--black: #CFCFCF;
--light: #170535;
--muted: #E1E1E1;
--gray: #383838;
--gray-100: #E1E1E1;
--gray-200: #E1E1E1;
--gray-300: #291720;
--gray-400: #303030;
--gray-500: var(--dark);
--gray-600: var(--dark);
--gray-700: var(--dark);
--gray-800: var(--dark);
--gray-900: var(--dark);
--background: var(--dark);
}
body {
overflow-x: hidden;
}
#header--icon {
height: 33px;
width: 33px;
object-fit: contain;
}
* {
border-color: var(--primary);
}
a:hover.user-name {
cursor: url('/assets/images/event/machete.webp'), auto !important;
}
.border {
border-color: var(--primary) !important;
}
.form-control {
background: transparent;
border-color: var(--primary) !important;
}
.btn {
background: transparent;
border-color: var(--primary) !important;
border-width: 2px;
}
.form-control:disabled, .form-control[readonly] {
background: transparent;
border-color: var(--primary) !important;
}
.btn-success {
border-color: #38A169 !important;
}
.btn-danger {
border-color: #E53E3E !important;
}
#frontpage .pseudo-submit-form.card .card-body .form-control {
border-color: transparent !important;
}
.btn-lg {
border-color: transparent !important;
}
pre {
color: #CFCFCF;
}
.transparent {
background: None !important;
}
#frontpage .post-title a:visited {
color: #7a7a7a !important;
}
.post-title a, h1.post-title {
font-family: 'SpecialElite-Regular';
font-size: 1.25rem;
}
.arrow-up::before, .arrow-down::before {
content: '\f720';
width: 20px;
}
.arrow-down::before {
display: inline-block;
transform: rotate(180deg);
}
#thread .arrow-up::before, #thread .arrow-down::before {
content: '\f720';
width: 17px;
}
/* Cob Webs */
body::before {
content: '';
position: fixed;
background-image: url('/assets/images/event/cobweb-bl.webp');
background-size: contain;
background-repeat: no-repeat;
left: -1.5rem;
bottom: -1.5rem;
width: 170px;
height: 230px;
z-index: 10001;
pointer-events: none;
transform: rotate(180deg);
opacity: .5;
}
body::after {
content: '';
position: fixed;
background-image: url('/assets/images/event/cobweb-tr.webp');
background-size: contain;
background-repeat: no-repeat;
right: -1.5rem;
top: -1.5rem;
width: 160px;
height: 160px;
z-index: 10001;
pointer-events: none;
opacity: .45;
}
/* Blood Effect */
.blood::before {
content: '';
position: absolute;
background-image: url('/assets/images/event/blood-anim.webp');
width: 100%;
height: 55px;
background-repeat: repeat-x;
top: 0;
left: 0;
}
.blood {
position: relative;
}
.blood .comment-text {
color: #dc3545 !important;
font-family: 'DoubleFeature';
}
.sketch {
z-index: 10000;
position: fixed;
top: 0;
left: 0;
pointer-events: none;
}
/* Haunted Effect */
.haunt > div:not(.modal) {
animation: haunted 10s infinite;
}
@keyframes haunted {
0% {
backdrop-filter: brightness(20%);
}
1% {
backdrop-filter: brightness(20%);
}
2% {
backdrop-filter: sepia(0.8) contrast(1.5) brightness(200%);
}
3% {
backdrop-filter: sepia(0.8) contrast(1.5) brightness(20%);
}
4% {
backdrop-filter: brightness(300%);
}
7% {
backdrop-filter: brightness(1);
}
100% {
backdrop-filter: brightness(1);
}
}
@keyframes haunted-upsidedown {
0% {
backdrop-filter: brightness(20%) sepia(1) saturate(3) hue-rotate(180deg);
}
1% {
backdrop-filter: brightness(20%) sepia(1) saturate(3) hue-rotate(180deg);
}
2% {
backdrop-filter: sepia(1) contrast(1.5) brightness(200%) saturate(3) hue-rotate(180deg);
}
3% {
backdrop-filter: sepia(1) contrast(1.5) brightness(20%) saturate(3) hue-rotate(180deg);
}
4% {
backdrop-filter: brightness(300%) sepia(1) saturate(3) hue-rotate(180deg);
}
7% {
backdrop-filter: brightness(1) sepia(1) saturate(3) hue-rotate(180deg);
}
100% {
backdrop-filter: brightness(1) sepia(1) saturate(3) hue-rotate(180deg);
}
}
/* Spiders */
.spider:nth-child(odd) {
animation-name: swingFast;
}
.spider:nth-child(2) {
animation-delay: 250ms;
animation-duration: 2100ms;
left: 20%;
}
.spider:nth-child(3) {
animation-delay: 300ms;
animation-duration: 1600ms;
left: 30%;
}
.spider:nth-child(4) {
animation-delay: 400ms;
animation-duration: 1800ms;
left: 40%;
}
.spider:nth-child(5) {
animation-delay: 240ms;
animation-duration: 1900ms;
left: 50%;
}
.spider:nth-child(6) {
animation-delay: 250ms;
animation-duration: 2300ms;
left: 60%;
}
.spider:nth-child(7) {
animation-delay: 400ms;
animation-duration: 2100ms;
left: 70%;
}
.spider:nth-child(8) {
animation-delay: 4000ms;
animation-duration: 200ms;
left: 80%;
}
.spider {
z-index: 10;
position: fixed;
display: inline-block;
top: 0;
left: 10%;
animation: swing 2s infinite;
transform-origin: top;
transition: 0.8s ease-in-out;
pointer-events: none;
}
.spider:hover .body {
transform: rotate(20deg);
transition: 0.4s ease-in-out;
}
.spider:nth-child(odd):hover .body {
transform: rotate(-10deg);
transition: 0.2s ease-in-out;
}
.spider .spiderweb {
width: 2px;
height: 200px;
margin-left: 49px;
background: rgba(255, 255, 255, 0.7);
}
.spider .body {
width: 100px;
height: 80px;
background: #222;
position: relative;
border-radius: 50%;
}
.spider .body .eye {
width: 28px;
height: 28px;
position: absolute;
bottom: 24px;
background: #fff;
border-radius: 50%;
}
.spider .body .eye.left {
left: 20px;
}
.spider .body .eye.right {
right: 20px;
}
.spider .body .eye:after {
background: #222;
width: 7px;
height: 7px;
content: "";
display: block;
margin: 55%;
border-radius: 50%;
animation: look 4s infinite;
}
.spider:nth-child(8) .body .eye {
background-color: #FF0000;
background: radial-gradient(#FF9B9B, #FF0000);
}
.spider:nth-child(odd) .body .eye:after {
animation-delay: 1400ms;
animation-duration: 3600ms;
}
.spider .legs .leg {
width: 80px;
height: 40px;
margin-top: -20px;
border: 5px solid transparent;
border-top-color: #333;
border-radius: 40px 40px 0 0;
}
.spider .legs {
position: absolute;
bottom: -10%;
z-index: -1;
}
.spider .legs.left {
left: -70%;
}
.spider .legs.right {
right: -60%;
}
.legs.left .leg:nth-child(1) {
transform: rotate(10deg);
margin-left: 10px;
}
.legs.right .leg:nth-child(1) {
transform: rotate(-10deg);
margin-left: -10px;
}
.legs.left .leg:nth-child(2) {
transform: rotate(-20deg);
margin-left: 20px;
}
.legs.right .leg:nth-child(2) {
transform: rotate(20deg);
margin-left: -20px;
}
.legs.left .leg:nth-child(3) {
transform: rotate(-50deg);
margin-left: 30px;
}
.legs.right .leg:nth-child(3) {
transform: rotate(50deg);
margin-left: -30px;
}
@keyframes look {
0%,
40%,
100% {
transform: translateX(0);
}
45%,
95% {
transform: translateX(-100%);
}
}
@keyframes swing {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-24px);
}
}
@keyframes swingFast {
0%,
100% {
transform: translateY(0);
}
55% {
transform: translateY(-36px);
}
}
/* Fog effect */
.fog-effect {
opacity: 0.35;
}
#fog-effect {
pointer-events: none;
position:fixed;
bottom:0;
left: 0;
width:100%;
height: 100%;
z-index: 1031;
}
/* Eyes */
.eye {
position: relative;
width: 26px;
height: 26px;
}
/* Candy Corn */
.candy-corn {
--color3: #FBED21;
--color2: #F66A3C;
--color1: #FDFBDA;
font-family: "Open Sans", sans-serif;
background: repeating-linear-gradient(
45deg,
var(--color1),
var(--color1) 10px,
var(--color2) 20px,
var(--color2) 20px,
var(--color3) 60px,
var(--color3) 60px
);
background-clip: text;
color: transparent;
-webkit-background-clip: text;
animation: 32s linear 0s infinite candycorn-move;
}
.candy-corn:not(a) > p {
color: transparent !important;
}
#post-title > a.candy-corn {
color: transparent;
}
.candy-corn:hover {
animation-duration: 10s;
}
@keyframes candycorn-move {
from {
background-position: 0px;
}
to {
background-position: 1000px;
}
}
/* Ectoplasm */
.ectoplasm {
text-shadow: 0 0 20px #3AE63A;
}
.ectoplasm .comment-text > p, .ectoplasm .post-body, h1.ectoplasm {
font-family: 'Creepster';
color: #90ee90;
letter-spacing: 0.15em;
}
.ectoplasm .candy-corn {
--color3: rgb(140, 255, 0);
--color2: rgb(0, 111, 0);
--color1: rgb(131, 255, 131);
text-shadow: none;
}
.ectoplasm.blood .comment-text > p {
font-family: 'DoubleFeature';
letter-spacing: initial;
}
.ectoplasm .rainbow-text > p {
color: #90ee90 !important;
font-weight: initial;
}
.ectoplasm .comment-text, .ectoplasm .post-body, h1.ectoplasm {
overflow:visible !important;
}
/* Upsidedown */
#canvas {
position:absolute;
pointer-events:none;
}
/* Bones */
#animate{
margin-left:45%;
margin-top:-5%;
position: fixed;
z-index:999;
pointer-events: none;
opacity:0.9;
}
/* Pumpkin */
.fall-pumpkin {
color: #fff;
font-size: 1em;
font-family: Serif;
text-shadow: 0 0 1px #000;
pointer-events: none;
}
@-webkit-keyframes fall-pumpkins-fall {
0% {
top: -20%
}
100% {
top: 100%
}
}
@-webkit-keyframes fall-pumpkins-shake {
0% {
-webkit-transform: translateX(0px);
transform: translateX(0px)
}
50% {
-webkit-transform: translateX(80px);
transform: translateX(80px)
}
100% {
-webkit-transform: translateX(0px) rotate(360deg);
transform: translateX(0px) rotate(360deg);
}
}
@keyframes fall-pumpkins-fall {
0% {
top: -20%
}
100% {
top: 100%
}
}
@keyframes fall-pumpkins-shake {
0% {
transform: translateX(0px)
}
50% {
transform: translateX(80px)
}
100% {
transform: translateX(0px) rotate(360deg);
}
}
.fall-pumpkin {
position: fixed;
top: -20%;
z-index: 999;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: default;
-webkit-animation-name: fall-pumpkins-fall, fall-pumpkins-shake;
-webkit-animation-duration: 10s, 4s;
-webkit-animation-timing-function: linear, ease-in-out;
-webkit-animation-iteration-count: infinite, infinite;
-webkit-animation-play-state: running, running;
animation-name: fall-pumpkins-fall, fall-pumpkins-shake;
animation-duration: 10s, 4s;
animation-timing-function: linear, ease-in-out;
animation-iteration-count: infinite, infinite;
animation-play-state: running, running
}
.fall-pumpkin:nth-of-type(0) {
left: 1%;
-webkit-animation-delay: 0s, 0s;
animation-delay: 0s, 0s
}
.fall-pumpkin:nth-of-type(1) {
left: 10%;
-webkit-animation-delay: 1s, 1s;
animation-delay: 1s, 1s
}
.fall-pumpkin:nth-of-type(2) {
left: 20%;
-webkit-animation-delay: 6s, .5s;
animation-delay: 6s, .5s
}
.fall-pumpkin:nth-of-type(3) {
left: 30%;
-webkit-animation-delay: 4s, 2s;
animation-delay: 4s, 2s
}
.fall-pumpkin:nth-of-type(4) {
left: 40%;
-webkit-animation-delay: 2s, 2s;
animation-delay: 2s, 2s
}
.fall-pumpkin:nth-of-type(5) {
left: 50%;
-webkit-animation-delay: 8s, 3s;
animation-delay: 8s, 3s
}
.fall-pumpkin:nth-of-type(6) {
left: 60%;
-webkit-animation-delay: 6s, 2s;
animation-delay: 6s, 2s
}
.fall-pumpkin:nth-of-type(7) {
left: 70%;
-webkit-animation-delay: 2.5s, 1s;
animation-delay: 2.5s, 1s
}
.fall-pumpkin:nth-of-type(8) {
left: 80%;
-webkit-animation-delay: 1s, 0s;
animation-delay: 1s, 0s
}
.fall-pumpkin:nth-of-type(9) {
left: 90%;
-webkit-animation-delay: 3s, 1.5s;
animation delay: 3s, 1.5s
}
.fall-pumpkin:nth-of-type(10) {
left: 100%;
-webkit-animation-delay: 3s, 2s;
animation-delay: 3s, 2s
}
.fall-pumpkin:nth-of-type(11) {
left: 5%;
-webkit-animation-delay: 1s, 4s;
animation-delay: 1s, 4s
}
.fall-pumpkin:nth-of-type(12) {
left: 15%;
-webkit-animation-delay: 1s, 1.5s;
animation-delay: 1s, 1.5s
}
.fall-pumpkin:nth-of-type(13) {
left: 25%;
-webkit-animation-delay: 6s, 2.5s;
animation-delay: 6s, 2.5s
}
.fall-pumpkin:nth-of-type(14) {
left: 35%;
-webkit-animation-delay: 4s, 1s;
animation-delay: 4s, 1s
}
.fall-pumpkin:nth-of-type(15) {
left: 45%;
-webkit-animation-delay: 2s, 4s;
animation-delay: 2s, 4s
}
.fall-pumpkin:nth-of-type(16) {
left: 55%;
-webkit-animation-delay: 8s, 3s;
animation-delay: 8s, 3s
}
.fall-pumpkin:nth-of-type(17) {
left: 65%;
-webkit-animation-delay: 6s, 3s;
animation-delay: 6s, 3s
}
.fall-pumpkin:nth-of-type(18) {
left: 75%;
-webkit-animation-delay: 2.5s, 4s;
animation-delay: 2.5s, 4s
}
.fall-pumpkin:nth-of-type(19) {
left: 85%;
-webkit-animation-delay: 2s, 0s;
animation-delay: 2s, 0s
}
.fall-pumpkin:nth-of-type(20) {
left: 95%;
-webkit-animation-delay: 3s, 1.5s;
animation delay: 3s, 1.5s
}
.animate-spin {
animation: spin 5600ms linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
/* Trick or Treat */
#trick-or-treat {
font-family: Jo_wrote_a_lovesong;
font-size: 2rem;
letter-spacing: 0.5rem;
border-color: var(--primary) !important;
}
#trick-or-treat::before {
content:"";
background-image:url('/e/marseyface.webp'); ;
background-size: cover;
height:28px;
width:32px;
display:inline-block;
}
#trick-or-treat::after {
content:"";
background-image:url('/e/marseytrickortreat.webp'); ;
background-size: cover;
height:28px;
width:32px;
display:inline-block;
}
#jump-scare-img {
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
z-index: 9999;
object-fit: cover;
pointer-events: none;
}
/* progressbar */
.progress {
background-color: #1d9bf0;
background-image: linear-gradient(0deg, #1d9bf0 0%, #59b1ec 100%);
width: 270px;
height: 24px;
border-radius: 4px;
box-shadow: inset 0px 12px 2px #ffffff10;
backdrop-filter: blur(2px) brightness(101%);
margin-bottom: 40px;
}
.progress::before {
content: "\f48e";
font-family: "Font Awesome 6 Pro";
position: absolute;
left: 6px;
top: 2px;
font-size: 13px;
color: #fff;
}
.progress::after {
content: "\f780";
font-family: "Font Awesome 6 Pro";
position: absolute;
right: 6px;
top: 2px;
font-size: 13px;
color: #fff;
}
.progress > .legend {
display: flex;
justify-content: space-between;
margin-top: 6px;
padding: 0 6px;
color: #dc3545;
font-family: -apple-system,BlinkMacSystemFont,segoe ui,Helvetica,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;
font-size: 12px;
font-weight: bold;
}
.progress > .legend span:nth-child(1) {
color: #d3bc00;
}
.bar-left {
display: inline-block;
width: var(--width);
height: 24px;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
background-color: #d3bc00;
background-image: linear-gradient(180deg, #d3bc00 50%, #877800 100%);
box-shadow: inset 0px 12px 2px #ffffff20;
color: white;
text-align: center;
}
.bar-right {
display: inline-block;
width: var(--width);
height: 24px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
background-color: #dc3545;
background-image: linear-gradient(180deg, #dc3545 50%, #9e1b32 100%);
box-shadow: inset 2px 12px 0px #ffffff20;
color: white;
text-align: center;
position: absolute;
right: 0;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
../../../events/assets/fonts

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

View File

@ -0,0 +1 @@
../../../events/assets/images

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -0,0 +1,13 @@
const el = document.getElementById("banner-halloween-title");
function animateBannerText() {
const letters = el.getElementsByTagName("tspan");
for (let i = 0; i < letters.length; i++) {
letters.item(i).style.transition = `all 600ms ${600 + i * 40}ms`;
}
setTimeout(() => el.classList.add("life"), 1000);
}
animateBannerText();

View File

@ -0,0 +1,51 @@
/*
A Bloody Mess by Rob Glazebrook
By default, canvas does not clear between frames. I'm taking advantage of that to create the running blood effect.
This pen was inspired by Katy Decorah's BLOOD: https://codepen.io/katydecorah/pen/Lkogi
*/
var i = 0;
var blood = Sketch.create({autoclear: false, autopause: false}),
drops = [],
dropCount = stabs*10,
maxDrops = dropCount+1,
Drop = function() {
this.x = random(0,blood.width);
this.radius = random(10,20);
this.y = -this.radius - random(50,100);
this.vy = this.radius/6;
this.r = ~~random(240,255);
this.g = ~~random(0,20);
this.b = ~~random(0,20);
};
blood.update = function() {
var d = drops.length;
while(d < dropCount && i < maxDrops) {
var drop = new Drop();
drops.push(drop);
d++;
i++;
}
while(d-- && i < maxDrops) {
var drop = drops[d];
drop.y += drop.vy;
if(drop.y - drop.radius > blood.height) {
drops.splice(d,1);
}
}
}
blood.draw = function() {
var d = drops.length;
while(d-- && i < maxDrops) {
var drop = drops[d];
blood.beginPath();
blood.fillStyle = 'rgba('+drop.r+','+drop.g+','+drop.b+',.8)';
blood.arc(drop.x,drop.y,drop.radius,0,TWO_PI);
blood.fill();
}
}

View File

@ -0,0 +1,75 @@
function bones(number){
var container = document.getElementById('animate');
// Stackable
// With each award, append a new image to array
const sources = ['skeleton1.webp','skeleton2.webp','skeleton3.webp','skeleton4.webp','skeleton5.webp','skeleton6.webp'];
if(number > sources.length){
number = sources.length
}
const n = sources.length - number,
emoji = sources.slice(n),
pw = screen.availWidth/6
let circles = [];
for (var i = 0; i < 3; i++) {
addCircle(i * 150, [10 + 0, pw], emoji[Math.floor(Math.random() * emoji.length)]);
addCircle(i * 150, [10 + 0, -pw], emoji[Math.floor(Math.random() * emoji.length)]);
addCircle(i * 150, [10 - (0.5*pw), -pw], emoji[Math.floor(Math.random() * emoji.length)]);
addCircle(i * 150, [10 + (0.5*pw), pw], emoji[Math.floor(Math.random() * emoji.length)]);
addCircle(i * 150, [10 - (1.5*pw), -pw], emoji[Math.floor(Math.random() * emoji.length)]);
addCircle(i * 150, [10 + (1.5*pw), pw], emoji[Math.floor(Math.random() * emoji.length)]);
}
function addCircle(delay, range, color) {
setTimeout(function() {
var c = new Circle(range[0] + Math.random() * range[1], 80 + Math.random() * 4, color, {
x: -0.15 + Math.random() * 0.3,
y: 1 + Math.random() * 1
}, range);
circles.push(c);
}, delay);
}
function Circle(x, y, c, v, range) {
var _this = this;
this.x = x;
this.y = y;
this.color = c;
this.v = v;
this.range = range;
this.element = document.createElement('img');
/*this.element.style.display = 'block';*/
this.element.style.opacity = 0;
this.element.style.position = 'absolute';
this.element.style.height = '3rem';
this.element.src = "/assets/images/event/skeletons/"+c;
container.appendChild(this.element);
this.update = function() {
if (_this.y > window.innerHeight) {
_this.y = 80 + Math.random() * 4;
_this.x = _this.range[0] + Math.random() * _this.range[1];
}
_this.y += _this.v.y;
_this.x += _this.v.x;
this.element.style.opacity = 1;
this.element.style.transform = 'translate3d(' + _this.x + 'px, ' + _this.y + 'px, 0px)';
this.element.style.webkitTransform = 'translate3d(' + _this.x + 'px, ' + _this.y + 'px, 0px)';
this.element.style.mozTransform = 'translate3d(' + _this.x + 'px, ' + _this.y + 'px, 0px)';
};
}
function animate() {
for (var i in circles) {
circles[i].update();
}
requestAnimationFrame(animate);
}
animate();
}

View File

@ -0,0 +1,42 @@
if (innerWidth >= 992)
{
/*init*/
let sidebar = document.getElementById("main-content-row")
sidebar = sidebar.getElementsByClassName("sidebar")[0].firstElementChild
const eye_left = sidebar.getElementsByClassName("eye")[0],
eye_right = sidebar.getElementsByClassName("eye")[1]
/*eye movement*/
document.onmousemove = function(event) {
let click = {x: event.clientX, y: event.clientY},
/*recalculating eye position on every mousemove is less efficient
but ensures eyes track properly upon pageload even if script doesnt fire*/
eye_left_center = getCenter(eye_left),
eye_right_center = getCenter(eye_right)
eye_left.style.transform = 'rotate('+getAngle(click, eye_left_center)+'rad)'
eye_right.style.transform = 'rotate('+getAngle(click, eye_right_center)+'rad)'
}
function getCenter(element) {
const bounds = element.getBoundingClientRect()
let centerX = bounds["left"] + bounds["width"]/2,
centerY = bounds["top"] + bounds["height"]/2
return({x: centerX, y: centerY})
}
function getAngle(point1, point2) {
let x = point1["x"] - point2["x"],
y = point1["y"] - point2["y"],
angle = Math.atan(y/x)
if(point1["x"] < point2["x"]) {
angle += Math.PI
}
return(angle)
}
}

View File

@ -0,0 +1,30 @@
// Original codepen: https://codepen.io/Coding-Artist/pen/ExLyRJg
let mouseX = 0;
let mouseY = 0;
// Detect touch device
const isTouchDevice = () => {
try {
// We try to create TouchEvent (it would fail for desktops and throw error)
document.createEvent("TouchEvent");
return true;
} catch (e) {
return false;
}
};
function getMousePosition(e) {
try {
// Get position of mouse or touch
mouseX = !isTouchDevice() ? e.clientX : e.touches[0].clientX;
mouseY = !isTouchDevice() ? e.clientY : e.touches[0].clientY;
// Set the Xpos and Ypos variables to current mouse/touch position
document.getElementById("flashlight-effect").style.setProperty("--Xpos", mouseX + "px");
document.getElementById("flashlight-effect").style.setProperty("--Ypos", mouseY + "px");
} catch (e) {}
}
// Update mouse position on mouse move / touch move
document.addEventListener("mousemove", getMousePosition);
document.addEventListener("touchmove", getMousePosition);

View File

@ -0,0 +1,139 @@
console.clear();
canvasWidth = 1600;
canvasHeight = 200;
pCount = 0;
pCollection = new Array();
var puffs = 1;
var particlesPerPuff = 1000;
var img = '/assets/images/event/smoke.webp';
var smokeImage = new Image();
smokeImage.src = img;
for (var i1 = 0 ; i1 < puffs; i1++)
{
var puffDelay = i1 * 1500; //300 ms between puffs
for (var i2 = 0 ; i2 < particlesPerPuff; i2++)
{
addNewParticle((i2*50) + puffDelay);
}
}
draw(new Date().getTime(), 3000)
function addNewParticle(delay)
{
var p = {};
p.top = canvasHeight;
p.left = randBetween(-200,800);
p.start = new Date().getTime() + delay;
p.life = 16000;
p.speedUp = 30;
p.speedRight = randBetween(0,20);
p.rot = randBetween(-1,1);
p.red = Math.floor(randBetween(0,255));
p.blue = Math.floor(randBetween(0,255));
p.green = Math.floor(randBetween(0,255));
p.startOpacity = .3
p.newTop = p.top;
p.newLeft = p.left;
p.size = 200;
p.growth = 10;
pCollection[pCount] = p;
pCount++;
}
function draw(startT, totalT)
{
//Timing
var timeDelta = new Date().getTime() - startT;
var stillAlive = false;
//Grab and clear the canvas
var c=document.getElementById("fog-effect");
var ctx=c.getContext("2d");
ctx.clearRect(0, 0, c.width, c.height);
c.width = c.width;
//Loop through particles
for (var i= 0; i < pCount; i++)
{
//Grab the particle
var p = pCollection[i];
//Timing
var td = new Date().getTime() - p.start;
var frac = td/p.life
if (td > 0)
{
if (td <= p.life )
{ stillAlive = true; }
//attributes that change over time
var newTop = p.top - (p.speedUp * (td/1000));
var newLeft = p.left + (p.speedRight * (td/1000));
var newOpacity = Math.max(p.startOpacity * (1-frac),0);
var newSize = p.size + (p.growth * (td/1000));
p.newTop = newTop;
p.newLeft = newLeft;
//Draw!
ctx.fillStyle = 'rgba(150,150,150,' + newOpacity + ')';
ctx.globalAlpha = newOpacity;
ctx.drawImage(smokeImage, newLeft, newTop, newSize, newSize);
}
}
//Repeat if there's still a living particle
if (stillAlive)
{
requestAnimationFrame(function(){draw(startT,totalT);});
}
else
{
clog(timeDelta + ": stopped");
}
}
function randBetween(n1,n2)
{
var r = (Math.random() * (n2 - n1)) + n1;
return r;
}
function randOffset(n, variance)
{
//e.g. variance could be 0.1 to go between 0.9 and 1.1
var max = 1 + variance;
var min = 1 - variance;
var r = Math.random() * (max - min) + min;
return n * r;
}
function clog(s)
{
console.log(s);
}

View File

@ -0,0 +1,45 @@
const thunder1 = new Audio(`/assets/media/event/haunted/thunder1.mp3`),
thunder2 = new Audio(`/assets/media/event/haunted/thunder2.mp3`),
stylesheet_haunted = document.createElement("STYLE"),
is_upsidedown = localStorage.getItem('setting_upsidedown'),
div = document.getElementById("haunted-effect")
window.onload = function(){
temp = document.createTextNode("#banner-halloween-title {opacity:0;}#banner-halloween-text-evil {opacity:1!important;}img {filter: invert(1);}")
stylesheet_haunted.appendChild(temp)
document.head.appendChild(stylesheet_haunted)
stylesheet_haunted.disabled = true
thunder2.volume = 0.5
lightningStrike("normal")
}
setInterval(function(){
if(Math.floor(Math.random()*3) > 1){
lightningStrike("haunted")
} else {
lightningStrike("normal")
}
},14000)
function lightningStrike(strike) {
if(is_upsidedown == 'true'){
div.style.animation = "haunted-upsidedown 20s"
} else {
div.style.animation = "haunted 20s"
}
if(strike == "haunted"){
stylesheet_haunted.disabled = false
thunder2.play()
setTimeout(function(){
stylesheet_haunted.disabled = true
},700)
}
thunder1.play()
setTimeout(function(){
div.style.animation = "none"
},1000)
}

View File

@ -0,0 +1 @@
../../../events/assets/js

View File

@ -0,0 +1,14 @@
// Jump scare function
const scare = () => {
const image = document.getElementById("jump-scare-img");
jumpscare_audio.play();
image.style.display = "block";
// Hide image and reset sound
setTimeout(function () {
image.style.display = "none";
jumpscare_audio.pause()
jumpscare_audio.currentTime = 0;
}, 3000);
}

View File

@ -0,0 +1,630 @@
/* Copyright (C) 2013 Justin Windle, http://soulwire.co.uk */
(function ( root, factory ) {
if ( typeof exports === 'object' ) {
// CommonJS like
module.exports = factory(root, root.document);
} else if ( typeof define === 'function' && define.amd ) {
// AMD
define( function() { return factory( root, root.document ); });
} else {
// Browser global
root.Sketch = factory( root, root.document );
}
}( typeof window !== "undefined" ? window : this, function ( window, document ) {
"use strict";
/*
----------------------------------------------------------------------
Config
----------------------------------------------------------------------
*/
var MATH_PROPS = 'E LN10 LN2 LOG2E LOG10E PI SQRT1_2 SQRT2 abs acos asin atan ceil cos exp floor log round sin sqrt tan atan2 pow max min'.split( ' ' );
var HAS_SKETCH = '__hasSketch';
var M = Math;
var CANVAS = 'canvas';
var WEBGL = 'webgl';
var DOM = 'dom';
var doc = document;
var win = window;
var instances = [];
var defaults = {
fullscreen: true,
autostart: true,
autoclear: true,
autopause: true,
container: doc.body,
interval: 1,
globals: true,
retina: false,
type: CANVAS
};
var keyMap = {
8: 'BACKSPACE',
9: 'TAB',
13: 'ENTER',
16: 'SHIFT',
27: 'ESCAPE',
32: 'SPACE',
37: 'LEFT',
38: 'UP',
39: 'RIGHT',
40: 'DOWN'
};
/*
----------------------------------------------------------------------
Utilities
----------------------------------------------------------------------
*/
function isArray( object ) {
return Object.prototype.toString.call( object ) == '[object Array]';
}
function isFunction( object ) {
return typeof object == 'function';
}
function isNumber( object ) {
return typeof object == 'number';
}
function isString( object ) {
return typeof object == 'string';
}
function keyName( code ) {
return keyMap[ code ] || String.fromCharCode( code );
}
function extend( target, source, overwrite ) {
for ( var key in source )
if ( overwrite || !( key in target ) )
target[ key ] = source[ key ];
return target;
}
function proxy( method, context ) {
return function() {
method.apply( context, arguments );
};
}
function clone( target ) {
var object = {};
for ( var key in target ) {
if ( key === 'webkitMovementX' || key === 'webkitMovementY' )
continue;
if ( isFunction( target[ key ] ) )
object[ key ] = proxy( target[ key ], target );
else
object[ key ] = target[ key ];
}
return object;
}
/*
----------------------------------------------------------------------
Constructor
----------------------------------------------------------------------
*/
function constructor( context ) {
var request, handler, target, parent, bounds, index, suffix, clock, node, copy, type, key, val, min, max, w, h;
var counter = 0;
var touches = [];
var resized = false;
var setup = false;
var ratio = win.devicePixelRatio || 1;
var isDiv = context.type == DOM;
var is2D = context.type == CANVAS;
var mouse = {
x: 0.0, y: 0.0,
ox: 0.0, oy: 0.0,
dx: 0.0, dy: 0.0
};
var eventMap = [
context.eventTarget || context.element,
pointer, 'mousedown', 'touchstart',
pointer, 'mousemove', 'touchmove',
pointer, 'mouseup', 'touchend',
pointer, 'click',
pointer, 'mouseout',
pointer, 'mouseover',
doc,
keypress, 'keydown', 'keyup',
win,
active, 'focus', 'blur',
resize, 'resize'
];
var keys = {}; for ( key in keyMap ) keys[ keyMap[ key ] ] = false;
function trigger( method ) {
if ( isFunction( method ) )
method.apply( context, [].splice.call( arguments, 1 ) );
}
function bind( on ) {
for ( index = 0; index < eventMap.length; index++ ) {
node = eventMap[ index ];
if ( isString( node ) )
target[ ( on ? 'add' : 'remove' ) + 'EventListener' ].call( target, node, handler, false );
else if ( isFunction( node ) )
handler = node;
else target = node;
}
}
function update() {
cAF( request );
request = rAF( update );
if ( !setup ) {
trigger( context.setup );
setup = isFunction( context.setup );
}
if ( !resized ) {
trigger( context.resize );
resized = isFunction( context.resize );
}
if ( context.running && !counter ) {
context.dt = ( clock = +new Date() ) - context.now;
context.millis += context.dt;
context.now = clock;
trigger( context.update );
// Pre draw
if ( is2D ) {
if ( context.retina ) {
context.save();
if (context.autoclear) {
context.scale( ratio, ratio );
}
}
if ( context.autoclear )
context.clear();
}
// Draw
trigger( context.draw );
// Post draw
if ( is2D && context.retina )
context.restore();
}
counter = ++counter % context.interval;
}
function resize() {
target = isDiv ? context.style : context.canvas;
suffix = isDiv ? 'px' : '';
w = context.width;
h = context.height;
if ( context.fullscreen ) {
h = context.height = win.innerHeight;
w = context.width = win.innerWidth;
}
if ( context.retina && is2D && ratio ) {
target.style.height = h + 'px';
target.style.width = w + 'px';
w *= ratio;
h *= ratio;
}
if ( target.height !== h )
target.height = h + suffix;
if ( target.width !== w )
target.width = w + suffix;
if ( is2D && !context.autoclear && context.retina )
context.scale( ratio, ratio );
if ( setup ) trigger( context.resize );
}
function align( touch, target ) {
bounds = target.getBoundingClientRect();
touch.x = touch.pageX - bounds.left - (win.scrollX || win.pageXOffset);
touch.y = touch.pageY - bounds.top - (win.scrollY || win.pageYOffset);
return touch;
}
function augment( touch, target ) {
align( touch, context.element );
target = target || {};
target.ox = target.x || touch.x;
target.oy = target.y || touch.y;
target.x = touch.x;
target.y = touch.y;
target.dx = target.x - target.ox;
target.dy = target.y - target.oy;
return target;
}
function process( event ) {
event.preventDefault();
copy = clone( event );
copy.originalEvent = event;
if ( copy.touches ) {
touches.length = copy.touches.length;
for ( index = 0; index < copy.touches.length; index++ )
touches[ index ] = augment( copy.touches[ index ], touches[ index ] );
} else {
touches.length = 0;
touches[0] = augment( copy, mouse );
}
extend( mouse, touches[0], true );
return copy;
}
function pointer( event ) {
event = process( event );
min = ( max = eventMap.indexOf( type = event.type ) ) - 1;
context.dragging =
/down|start/.test( type ) ? true :
/up|end/.test( type ) ? false :
context.dragging;
while( min )
isString( eventMap[ min ] ) ?
trigger( context[ eventMap[ min-- ] ], event ) :
isString( eventMap[ max ] ) ?
trigger( context[ eventMap[ max++ ] ], event ) :
min = 0;
}
function keypress( event ) {
key = event.keyCode;
val = event.type == 'keyup';
keys[ key ] = keys[ keyName( key ) ] = !val;
trigger( context[ event.type ], event );
}
function active( event ) {
if ( context.autopause )
( event.type == 'blur' ? stop : start )();
trigger( context[ event.type ], event );
}
// Public API
function start() {
context.now = +new Date();
context.running = true;
}
function stop() {
context.running = false;
}
function toggle() {
( context.running ? stop : start )();
}
function clear() {
if ( is2D )
context.clearRect( 0, 0, context.width * ratio, context.height * ratio );
}
function destroy() {
parent = context.element.parentNode;
index = instances.indexOf( context );
if ( parent ) parent.removeChild( context.element );
if ( ~index ) instances.splice( index, 1 );
bind( false );
stop();
}
extend( context, {
touches: touches,
mouse: mouse,
keys: keys,
dragging: false,
running: false,
millis: 0,
now: NaN,
dt: NaN,
destroy: destroy,
toggle: toggle,
clear: clear,
start: start,
stop: stop
});
instances.push( context );
return ( context.autostart && start(), bind( true ), resize(), update(), context );
}
/*
----------------------------------------------------------------------
Global API
----------------------------------------------------------------------
*/
var element, context, Sketch = {
CANVAS: CANVAS,
WEB_GL: WEBGL,
WEBGL: WEBGL,
DOM: DOM,
instances: instances,
install: function( context ) {
if ( !context[ HAS_SKETCH ] ) {
for ( var i = 0; i < MATH_PROPS.length; i++ )
context[ MATH_PROPS[i] ] = M[ MATH_PROPS[i] ];
extend( context, {
TWO_PI: M.PI * 2,
HALF_PI: M.PI / 2,
QUARTER_PI: M.PI / 4,
random: function( min, max ) {
if ( isArray( min ) )
return min[ ~~( M.random() * min.length ) ];
if ( !isNumber( max ) )
max = min || 1, min = 0;
return min + M.random() * ( max - min );
},
lerp: function( min, max, amount ) {
return min + amount * ( max - min );
},
map: function( num, minA, maxA, minB, maxB ) {
return ( num - minA ) / ( maxA - minA ) * ( maxB - minB ) + minB;
}
});
context[ HAS_SKETCH ] = true;
}
},
create: function( options ) {
options = extend( options || {}, defaults );
if ( options.globals ) Sketch.install( self );
element = options.element = options.element || doc.createElement( options.type === DOM ? 'div' : 'canvas' );
context = options.context = options.context || (function() {
switch( options.type ) {
case CANVAS:
return element.getContext( '2d', options );
case WEBGL:
return element.getContext( 'webgl', options ) || element.getContext( 'experimental-webgl', options );
case DOM:
return element.canvas = element;
}
})();
( options.container || doc.body ).appendChild( element );
return Sketch.augment( context, options );
},
augment: function( context, options ) {
options = extend( options || {}, defaults );
options.element = context.canvas || context;
options.element.className += ' sketch';
extend( context, options, true );
return constructor( context );
}
};
/*
----------------------------------------------------------------------
Shims
----------------------------------------------------------------------
*/
var vendors = [ 'ms', 'moz', 'webkit', 'o' ];
var scope = self;
var then = 0;
var a = 'AnimationFrame';
var b = 'request' + a;
var c = 'cancel' + a;
var rAF = scope[ b ];
var cAF = scope[ c ];
for ( var i = 0; i < vendors.length && !rAF; i++ ) {
rAF = scope[ vendors[ i ] + 'Request' + a ];
cAF = scope[ vendors[ i ] + 'Cancel' + a ];
}
scope[ b ] = rAF = rAF || function( callback ) {
var now = +new Date();
var dt = M.max( 0, 16 - ( now - then ) );
var id = setTimeout( function() {
callback( now + dt );
}, dt );
then = now + dt;
return id;
};
scope[ c ] = cAF = cAF || function( id ) {
clearTimeout( id );
};
/*
----------------------------------------------------------------------
Output
----------------------------------------------------------------------
*/
return Sketch;
}));

View File

@ -0,0 +1,24 @@
function postToastTrickOrTreat(t, url) {
const xhr = createXhrWithFormKey(url);
xhr[0].onload = function() {
postToastLoadTrickOrTreat(xhr[0])
};
xhr[0].send(xhr[1]);
}
function postToastLoadTrickOrTreat(xhr) {
let data
try {
data = JSON.parse(xhr.response)
}
catch (e) {
console.log(e)
}
success = xhr.status >= 200 && xhr.status < 300;
showToast(success, getMessageFromJsonData(success, data));
if (data["result"] == 0){
scare()
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
../../../events/assets/media

Binary file not shown.

View File

18
events/columns.py 100644
View File

@ -0,0 +1,18 @@
from sqlalchemy import Column, Integer, Boolean
from .table import Event
Event.hw_zombie = Column(Integer, default=0, nullable=False)
Event.jumpscare = Column(Integer, default=0)
Event.hwmusic = Column(Boolean, default=False)
COLUMN_DEFAULTS = {
"hw_zombie": {
"default": 0
},
"jumpscare": {
"default": 0
},
"hwmusic": {
"default": False
},
}

View File

@ -0,0 +1,2 @@
from .const import *
from .jinja import *

View File

@ -0,0 +1,142 @@
EVENT_AWARDS = {
"jumpscare": {
"kind": "jumpscare",
"title": "Jumpscare",
"description": "",
"icon": "fas fa-coffin-cross",
"color": "text-purple",
"price": 600,
"deflectable": True,
"cosmetic": False
},
"hw-bite": {
"kind": "hw-bite",
"title": "Zombie Bite",
"description": "",
"icon": "fas fa-biohazard",
"color": "text-danger",
"price": 500,
"deflectable": True,
"cosmetic": False
},
"hw-vax": {
"kind": "hw-vax",
"title": "Vaxxmaxx",
"description": "",
"icon": "fas fa-syringe",
"color": "text-blue",
"price": 500,
"deflectable": True,
"cosmetic": False
},
"hw-grinch": {
"kind": "hw-grinch",
"title": "Hallowgrinch",
"description": "",
"icon": "fas fa-angry",
"color": "text-orange",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"haunt": {
"kind": "haunt",
"title": "Haunt",
"description": "",
"icon": "fas fa-book-dead",
"color": "text-warning",
"price": 500,
"deflectable": False,
"cosmetic": True
},
"stab": {
"kind": "stab",
"title": "Stab",
"description": "",
"icon": "fas fa-knife-kitchen",
"color": "text-danger",
"price": 300,
"deflectable": False,
"cosmetic": True
},
"spiders": {
"kind": "spiders",
"title": "Spiders",
"description": "",
"icon": "fas fa-spider-web",
"color": "text-black",
"price": 200,
"deflectable": False,
"cosmetic": True
},
"fog": {
"kind": "fog",
"title": "Fog",
"description": "",
"icon": "fas fa-smoke",
"color": "text-gray",
"price": 200,
"deflectable": False,
"cosmetic": True
},
"flashlight": {
"kind": "flashlight",
"title": "Flashlight",
"description": "",
"icon": "fas fa-flashlight",
"color": "text-black",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"candy-corn": {
"kind": "candy-corn",
"title": "Candy Corn",
"description": "",
"icon": "fas fa-candy-corn",
"color": "text-orange",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"ectoplasm": {
"kind": "ectoplasm",
"title": "Ectoplasm",
"description": "",
"icon": "fas fa-ghost",
"color": "text-success",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"test_award": {
"kind": "test_award",
"title": "TEST",
"description": "",
"icon": "fas fa-lights-holiday",
"color": "",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"bones": {
"kind": "bones",
"title": "Bones",
"description": "",
"icon": "fas fa-bone",
"color": "text-white",
"price": 500,
"deflectable": False,
"cosmetic": True
},
"pumpkin": {
"kind": "pumpkin",
"title": "Pumpkin",
"description": "",
"icon": "fas fa-jack-o-lantern",
"color": "text-orange",
"price": 200,
"deflectable": False,
"cosmetic": True
}
}

View File

@ -0,0 +1,26 @@
def bar_position():
"""
db = db_session()
vaxxed = db.execute(text("SELECT COUNT(*) FROM event WHERE hw_zombie > 0")).one()[0]
zombie = db.execute(text("SELECT COUNT(*) FROM event WHERE hw_zombie < 0")).one()[0]
total = db.execute(text("SELECT COUNT(*) FROM "
"(SELECT DISTINCT ON (author_id) author_id AS uid FROM comments "
"WHERE created_utc > 1666402200) AS q1 "
"FULL OUTER JOIN (SELECT id AS uid FROM event WHERE hw_zombie != 0) as q2 "
"ON q1.uid = q2.uid")).one()[0]
total = max(total, 1)
return [int((vaxxed * 100) / total), int((zombie * 100) / total), vaxxed, zombie]
"""
return [1,1,1,1]
EVENT_JINJA_CONST = {
"EVENT_BANNER": "banner_rDrama.html",
"EVENT_SIDEBAR": True,
"EVENT_STYLES": "spooky.css",
"EVENT_AWARDS": True,
"EVENT_MUSIC": "music.html",
"bar_position": bar_position()
}

View File

@ -0,0 +1,3 @@
from .routes import *
from .awards import *
from .jinja import *

View File

@ -0,0 +1,60 @@
from flask import g
from files.classes.award import AwardRelationship
from files.helpers.alerts import send_repeatable_notification
from files.helpers.useractions import badge_grant
from events import Event, COLUMN_DEFAULTS
def award_thing_event(v, kind, author):
def event_user(user):
event_user = g.db.get(Event, user.id)
if not event_user:
event_user = Event(id=user.id)
for column in COLUMN_DEFAULTS:
event_user.column = COLUMN_DEFAULTS[column]["default"]
g.db.add(event_user)
g.db.commit()
return event_user
event_author = event_user(author)
event_v = event_user(v)
if kind == "hw-bite":
if event_author.hw_zombie < 0:
event_author = event_v
if event_author.hw_zombie == 0:
event_author.hw_zombie = -1
badge_grant(user=author, badge_id=181)
award_object = AwardRelationship(user_id=author.id, kind='hw-bite')
g.db.add(award_object)
send_repeatable_notification(author.id,
"As the zombie virus washes over your mind, you feel the urge "
"to… BITE YUMMY BRAINS :marseyzombie:<br>"
"You receive a free **Zombie Bite** award: pass it on!")
elif event_author.hw_zombie > 0:
event_author.hw_zombie -= 1
if event_author.hw_zombie == 0:
send_repeatable_notification(author.id, "You are no longer **VAXXMAXXED**! Time for another booster!")
badge = author.has_badge(182)
if badge: g.db.delete(badge)
elif kind == "hw-vax":
if event_author.hw_zombie < 0:
event_author.hw_zombie = 0
send_repeatable_notification(author.id, "You are no longer **INFECTED**! Praise Fauci!")
badge = author.has_badge(181)
if badge: g.db.delete(badge)
elif event_author.hw_zombie >= 0:
event_author.hw_zombie += 2
event_author.hw_zombie = min(event_author.hw_zombie, 10)
badge_grant(user=author, badge_id=182)
elif kind == "jumpscare":
event_author.jumpscare += 1
g.db.add(event_author)

View File

@ -0,0 +1,6 @@
from files.__main__ import app
from events import EVENT_JINJA_CONST
@app.context_processor
def event_constants():
return EVENT_JINJA_CONST

View File

@ -0,0 +1,33 @@
from files.__main__ import *
@app.post("/trick-or-treat")
@limiter.limit("1/hour", key_func=lambda:f'{SITE}-{session.get("lo_user")}')
@auth_required
def trick_or_treat(v):
if v.client: abort(403, "Not allowed from the API")
result = random.choice([0,1])
if result == 0:
message = "Trick!"
else:
AWARDS = deepcopy(AWARDS2)
award = random.choice(["haunt", "stab", "spiders", "fog", "flashlight", "candy-corn", "ectoplasm", "bones", "pumpkin", "jumpscare", "hw-bite", "hw-vax"])
award_title = AWARDS[award]['title']
award_object = AwardRelationship(user_id=v.id, kind=award)
g.db.add(award_object)
g.db.add(v)
message = f"Treat! You got a {award_title} award!"
return {"message": f"{message}", "result": f"{result}"}
@app.post("/jumpscare")
@auth_required
def execute_jumpscare(v):
if v.client: abort(403, "Not allowed from the API")
if v.jumpscare > 0:
v.jumpscare -= 1
g.db.add(v)
return {}

15
events/table.py 100644
View File

@ -0,0 +1,15 @@
from sqlalchemy import *
from sqlalchemy.orm import relationship
from files.classes import Base
class Event(Base):
__tablename__ = "event"
id = Column(Integer, ForeignKey("users.id"), primary_key=True)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def __repr__(self):
return f"<Event(id={self.id})>"

View File

@ -0,0 +1,130 @@
<style>
.modal {
z-index:99999 !important;
}
</style>
{% if p.award_count("haunt", v) %}
<script src="{{'js/event/haunted.js' | asset}}" defer></script>
<div id="haunted-effect" class="fixed-top"></div>
<style>
#haunted-effect {
position: fixed;
width:100%;
height:100%;
pointer-events:none;
}
#haunt-bg{
position: fixed;
background-repeat: no-repeat;
width: 100%;
height: 100%;
pointer-events:none;
background-color: var(--background);
z-index:0;
}
</style>
{% endif %}
{% set stab = p.award_count("stab", v) %}
{% if stab %}
{% if stab > 3 %}
{% set stab = 3 %}
{% endif %}
<script src="{{'js/event/sketch.js' | asset}}" defer></script>
<script src="{{'js/event/blood.js' | asset}}" defer></script>
<script>let stabs = {{ stab }}</script>
<style>
canvas.sketch {
opacity: calc(0.1*{{ stab }});
}
</style>
{% endif %}
{% if p.award_count("spiders", v) %}
{% set spiders = p.award_count("spiders", v) %}
{% for i in range(spiders) %}
{% include "event/spider.html" %}
{% endfor %}
{% endif %}
{% if p.award_count("fog", v) %}
<canvas id="fog-effect" class="fog-effect"></canvas>
<script src="{{'js/event/fog.js' | asset}}" defer></script>
{% endif %}
{% if p.award_count("flashlight", v) %}
<style>
#flashlight-effect {
--Xpos: 50vw;
--Ypos: 50vh;
position: fixed;
width:100%;
height:100%;
z-index:1061;
pointer-events:none;
opacity:0.8;
/*looks better but is too expensive to justify :(*/
backdrop-filter: brightness(1.5);
background-color: rgba(256,256,256,0.06);
}
#flashlight-effect:before {
content: "";
display: block;
width: 100%;
height: 100%;
position: absolute;
pointer-events: none;
background: radial-gradient(
circle 30vmax at var(--Xpos) var(--Ypos),
rgba(0,0,0,0) 0%,
rgba(0,0,0,.5) 70%,
rgba(0,0,0,.93) 100%
);
z-index: 1061;
}
@media (max-width: 767.98px) {
#flashlight-effect::before {
background: radial-gradient(
circle 20em at 50% var(--Ypos),
rgba(0,0,0,0) 0%,
rgba(0,0,0,0) 80%,
rgba(0,0,0,.93) 100%
);
opacity:0.9;
pointer-events: none;
}
}
</style>
<div id="flashlight-effect" class="fixed-top"></div>
<script src="{{'js/event/flashlight.js' | asset}}"></script>
{% endif %}
{% if p.award_count("ectoplasm", v) %}
<style>
#banner-halloween-title {
text-shadow: 0 0 40px #3AE63A;
fill: #90ee90;
}
</style>
{% endif %}
{% if p.award_count("bones", v) %}
<div id="animate"></div>
<script src="{{'js/event/bones.js' | asset}}"></script>
<script defer>
bones({{ p.award_count("bones", v) }})
</script>
{% endif %}
{% if p.award_count("pumpkin", v) %}
{% set count = p.award_count("pumpkin", v) * 2 if p.award_count("pumpkin", v) <= 10 else 20 %}
<div class="fall-pumpkins">
{% for i in range(count) %}
<div class="fall-pumpkin">
<img src="/e/marseypumpking.webp" class="animate-spin" style="width: 40px; height: 40px;" alt="animate marsey pumpkin icon"/>
</div>
{% endfor %}
</div>
{% endif %}

View File

@ -0,0 +1,219 @@
<a rel="nofollow noopener noreferrer" href="{% if 'rama' in request.host %}https://youtu.be/3l7X94GLqSQ?t=16{% else %}/{% endif %}" style="text-decoration: none !important">
{% set banner_day = time.gmtime()[2]-21 %}
{% if banner_day < 1 %}
{% set banner_day = 1 %}
{% endif %}
<link rel="stylesheet" href="{{'css/event/banner.css' | asset}}">
{% if '/post/' not in request.path %}
<script defer src="{{'js/event/banner.js' | asset}}"></script>
<style>
#banner-halloween-title {
animation: float infinite 8s ease-in-out;
}
#banner-halloween-title > tspan {
opacity: 0;
}
</style>
{% endif %}
<svg id="banner-halloween-svg" style="background-image:var(--sky-gradient-day{{banner_day}})" viewBox="0 0 1558 340" width="100%" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<g id="banner-halloween-sky">
<rect fill="none" width="1558" height="379.12619" id="banner-halloween-skybox"/>
<g id="banner-halloween-stars" fill="white" style="opacity:var(--star-opacity-day{{banner_day}})" transform="translate(-68.499999,25.761047)">
<g class="star1 star">
<circle cx="354.34659" cy="51.486233" />
<circle cx="686.33435" cy="100.34389" />
<circle cx="1428.2604" cy="121.01141" />
<circle cx="142.41147" cy="57.083103" />
<circle cx="624.15045" cy="52.292145" />
<circle cx="261.05768" cy="197.4662" />
<circle cx="1586.7877" cy="232.13432" />
<circle cx="1457.4095" cy="193.31587" />
<circle cx="193.29951" cy="26.420403" />
<circle cx="1025.8184" cy="177.29558" />
<circle cx="1205.6655" cy="107.11586" />
<circle cx="988.62946" cy="115.36874" />
<circle cx="1418.1691" cy="174.45583" />
<circle cx="617.49738" cy="57.193687" />
<circle cx="299.98047" cy="121.33453" />
<circle cx="90.674393" cy="-0.54514796" />
<circle cx="1075.5156" cy="36.469925" />
<circle cx="1455.9106" cy="180.05734" />
<circle cx="646.97412" cy="132.32523" />
<circle cx="704.60657" cy="18.466848" />
</g>
<g class="star2 star">
<circle cx="1406.1763" cy="-5.5104017" />
<circle cx="536.49463" cy="103.55247" />
<circle cx="351.08881" cy="143.94203" />
<circle cx="1279.1542" cy="18.840036" />
<circle cx="221.29961" cy="28.242449" />
<circle cx="1603.348" cy="115.4075" />
<circle cx="921.06372" cy="107.46529" />
<circle cx="137.43065" cy="111.68105" />
<circle cx="505.65485" cy="-6.3819265" />
<circle cx="1577.0615" cy="171.6333" />
<circle cx="906.78802" cy="-1.5375607" />
<circle cx="860.159" cy="72.191864" />
<circle cx="212.81689" cy="112.77587" />
<circle cx="1451.5607" cy="91.880829" />
<circle cx="1153.7001" cy="79.335007" />
<circle cx="1235.9001" cy="93.177391" />
<circle cx="125.44918" cy="203.72043" />
<circle cx="1467.8811" cy="141.55785" />
<circle cx="87.268814" cy="115.13907" />
<circle cx="420.64523" cy="9.8289289" />
<circle cx="1078.9646" cy="156.93616" />
</g>
<g class="star3 star">
<circle cx="861.69922" cy="59.167252" />
<circle cx="92.081718" cy="186.95992" />
<circle cx="492.38992" cy="92.957916" />
<circle cx="782.71057" cy="55.074757" />
<circle cx="1569.3516" cy="207.68919" />
<circle cx="1553.7762" cy="173.45573" />
<circle cx="366.2016" cy="98.177361" />
<circle cx="158.98877" cy="182.29086" />
<circle cx="1566.6627" cy="-2.7730622" />
<circle cx="1032.2488" cy="99.917984" />
<circle cx="1442.6716" cy="16.022043" />
<circle cx="849.01971" cy="232.44159" />
<circle cx="572.78674" cy="28.079025" />
<circle cx="1265.6924" cy="208.07133" />
<circle cx="1321.8163" cy="167.11555" />
<circle cx="1203.9926" cy="204.14101" />
<circle cx="1074.4159" cy="7.6153278" />
<circle cx="1390.5989" cy="93.045151" />
<circle cx="1490.332" cy="123.14182" />
<circle cx="1130.7302" cy="150.13852" />
</g>
<g class="star4 star">
<circle cx="1235.1261" cy="183.63806" />
<circle cx="941.27423" cy="28.98748" />
<circle cx="1565.119" cy="39.94997" />
<circle cx="1320.7312" cy="197.81389" />
<circle cx="1330.1912" cy="94.380714" />
<circle cx="1501.6204" cy="193.72606" />
<circle cx="100.52748" cy="27.732065" />
<circle cx="1326.5785" cy="153.80927" />
<circle cx="840.51929" cy="5.7146263" />
<circle cx="1507.1639" cy="88.637108" />
<circle cx="1252.4867" cy="189.86913" />
<circle cx="433.59921" cy="12.135095" />
<circle cx="995.14679" cy="86.594627" />
<circle cx="1352.5358" cy="54.43977" />
<circle cx="581.47766" cy="97.300217" />
<circle cx="622.31262" cy="202.93999" />
<circle cx="988.44" cy="136.42937" />
<circle cx="224.8391" cy="136.87054" />
<circle cx="190.67062" cy="23.389349" />
<circle cx="378.93933" cy="215.09964" />
</g>
<g class="star5 star">
<circle cx="415.39145" cy="91.883652" />
<circle cx="1611.5449" cy="42.999901" />
<circle cx="1584.6263" cy="126.31186" />
<circle cx="794.80231" cy="62.717503" />
<circle cx="1451.3389" cy="16.653343" />
<circle cx="554.16071" cy="71.499649" />
<circle cx="314.88879" cy="183.24821" />
<circle cx="645.84845" cy="-4.3557439" />
<circle cx="1192.1021" cy="58.766937" />
<circle cx="1371.4421" cy="2.2274418" />
<circle cx="618.45569" cy="167.10979" />
<circle cx="254.45935" cy="81.400383" />
<circle cx="1514.1248" cy="198.7796" />
<circle cx="1352.1172" cy="150.42014" />
<circle cx="1365.3644" cy="28.673313" />
<circle cx="912.87531" cy="98.27787" />
<circle cx="350.54874" cy="81.523178" />
<circle cx="441.39749" cy="30.191652" />
<circle cx="169.44328" cy="10.935395" />
</g>
</g>
<ellipse id="banner-halloween-moon" fill="var(--moon-fill-day{{banner_day}}" style="cy:var(--moon-position-day{{banner_day}});filter:var(--moon-shadow-day{{banner_day}})" cx="802" rx="86" ry="74" />
</g>
<g id="banner-halloween-scene" transform="matrix(1,0,0,1.0023048,427.09249,-121.25261)">
<g id="banner-halloween-text" fill="#fff" transform="translate(-27.135979,1.5613725)" style="transform:rotate(-6deg) skewX(-12deg)">
<text id="banner-halloween-presenting" style="font-family:verdana,arial;text-transform:uppercase">
<tspan x="200" y="290">rDrama Presents</tspan>
</text>
<g style="font-size:80px;font-family:Creepster,arial;">
<text id="banner-halloween-title" y="370" fill-opacity="0.9">
<tspan x="200">H</tspan><tspan x="235">O</tspan><tspan x="270">M</tspan><tspan x="320">O</tspan>
<tspan x="355">W</tspan><tspan x="405">E</tspan><tspan x="440">E</tspan><tspan x="475">N</tspan>
<tspan x="540" id="banner-halloween-title-II" fill="#f00" fill-opacity="0.8">II</tspan>
</text>
</g>
<text id="banner-halloween-text-evil" style="opacity:0">
<tspan x="200" y="370" fill="white" style="font-size:72px;font-family:Jo_wrote_a_lovesong;">straggotween</tspan>
</text>
</g>
<g id="banner-halloween-house" transform="translate(-166.09098,3.8681347)">
<path id="banner-halloween-house-fill" fill="url(#house-fill-gradient)" d="m 227.4,354.9 c 0.4,-10 13.8,-34.6 13.8,-34.6 -7.1,1.4 -15.3,2.4 -23.6,3.1 l 3.2,-14.8 6.9,-0.3 c -9.2,-11.2 -10.4,-19 -10.4,-19 -4.4,0 -19.1,0.4 -24.8,0.5 l 1,-11.7 c 3.3,0.1 5.3,0.2 5.3,0.2 -10.4,-7.5 -18.4,-31.7 -20.7,-38.6 0,0 -1.7,7.8 -10.4,22.2 -1.4,2.3 -2.7,4.3 -4,6 -3.8,-4.3 -9.3,-12.1 -6.4,-18.6 l -7.1,-0.2 -0.3,-5.1 4.4,0.2 c -5.8,-3.3 -12.1,-15.6 -12.1,-15.6 0,0 -4,11.9 -8.8,14.6 l 3.6,0.2 -0.4,5.4 -43.4,-1 c 0,0 1.5,6.1 -0.4,10.8 -1.9,4.6 -13.4,14.2 -13.4,14.2 l 15,1.9 1,42.6 -29.8,-3.1 c 0,0 19.6,26.1 21.9,40.7 1.2,7.3 0.7,12.9 -0.1,16.6 l -29.9,14.1 h 182.8 l -14.7,-11.1 c 0.6,-3.9 1.5,-12.3 1.8,-19.6 z m -30.2,-38.7 5.8,0.2 v 6.1 c -3.3,-0.6 -6.4,-3 -5.8,-6.3 z m 12.8,1.1 c 0,0.1 0,0.1 0,0 0,3.5 -2.3,5 -4.9,5.3 -0.1,-1.6 -0.2,-3.9 -0.3,-6.2 l 5.1,0.1 c 0.1,0.3 0.1,0.6 0.1,0.8 z m -72.4,16.9 c 0,0 10.3,1 21.3,2 l -0.5,10.5 -18.8,0.2 c -0.5,-4.7 -1.2,-9.4 -2,-12.7 z m 32.2,-39.2 6,-0.3 -0.4,11 -6.1,-0.3 z m 10,51.4 -17.9,0.2 0.5,-10.2 c 7.2,0.6 14.2,1.1 18.4,1.2 z m -21.6,2.7 -0.8,15.5 c -6.6,-0.2 -13.1,-0.3 -16.4,-0.4 0,0 -0.4,-7.4 -1.2,-15.3 z m 3.6,0 17.7,0.2 -1.8,15.8 c 0,0 -7.9,-0.2 -16.6,-0.4 z m 30.2,0.1 0.4,-12.1 5.2,-0.1 -0.3,12.2 z m 10.1,0 0.4,-12.1 5.2,-0.1 -0.3,12.2 z m 14.6,0 h -5.3 l 0.4,-12.1 5.2,-0.1 z m -33.7,-43.1 -6,-0.3 0.6,-11.1 6.2,-0.3 z m 0.9,-12.9 -6.2,0.1 0.5,-9.7 h 6.4 z m -8,0.1 -6,0.1 0.4,-9.8 h 5.9 z m -59.3,72.3 -6.7,0.4 v -32.6 l 5.8,0.4 z m -18.3,-32.3 5.8,0.4 1,31.9 -6.7,0.4 v -32.7 z m 111.4,-17.7 c -1.3,0 -3.1,0 -4.9,-0.1 -0.1,-1.9 -0.1,-3.7 -0.2,-5 0.6,0.1 1.2,0.2 1.8,0.5 1.6,0.8 2.8,2.8 3.3,4.6 z m -6.7,-5 v 4.9 c -2.2,-0.1 -4.3,-0.2 -5.5,-0.2 0.3,-0.6 0.7,-1.2 1,-1.8 1.1,-1.7 2.7,-2.7 4.5,-2.9 z m -61.4,-6.6 -9.9,0.1 0.1,-13.2 h 10 c -0.3,5.4 -0.6,11.2 -0.2,13.1 z m -23.4,-13.1 h 10.7 l -1.1,13.2 -11.8,0.1 c 0,0 2,-4.4 2.2,-13.3 z m 23.8,-2.1 -10.2,0.2 0.1,-8.9 10.9,0.2 c 0,0 -0.4,3.9 -0.8,8.5 z m -12.2,-8.8 -0.8,9 -10.9,0.2 c 0,-2.8 -0.2,-6 -0.7,-9.5 z" />
<g id="banner-halloween-house-windows" fill="url(#banner-halloween-house-window-gradient)" style="filter: drop-shadow(0px 0px 10px #00a100);">
<!--window 1-->
<path d="m 158.9,336.2 c -11,-0.9 -21.3,-2 -21.3,-2 0.8,3.3 1.5,8 2,12.7 l 18.8,-0.2 z" />
<path d="m 157.4,364.6 0.8,-15.5 -18.4,-0.2 c 0.8,7.9 1.2,15.3 1.2,15.3 3.4,0.1 9.9,0.2 16.4,0.4 z" />
<path d="m 177.6,365 1.8,-15.8 -17.7,-0.2 -0.7,15.6 c 8.7,0.3 16.6,0.4 16.6,0.4 z" />
<path d="m 162.4,336.5 -0.5,10.2 17.9,-0.2 1,-8.8 c -4.3,-0.1 -11.3,-0.6 -18.4,-1.2 z" />
<!--window 2-->
<polygon points="197.7,336.9 192.5,337.1 192,349.2 197.4,349.2 " />
<polygon points="207.7,336.9 202.6,337.1 202.1,349.2 207.4,349.2 " />
<polygon points="211.8,337.1 211.3,349.2 216.7,349.2 217,336.9 " />
<!--window 3-->
<polygon points="109.8,333.3 109.8,366 116.6,365.6 115.6,333.7 " />
<polygon points="105,365.6 104.1,333.7 98.3,333.3 98.3,366 " />
<!--window 4-->
<path d="m 128.9,290.9 h -10.7 c -0.1,8.9 -2.2,13.3 -2.2,13.3 l 11.8,-0.1 z" />
<path d="m 131.9,289 10.2,-0.2 c 0.4,-4.6 0.8,-8.5 0.8,-8.5 L 132,280.1 Z" />
<path d="m 131.8,290.9 -0.1,13.2 9.9,-0.1 c -0.4,-1.9 -0.1,-7.7 0.2,-13.1 z" />
<path d="m 129.1,289.1 0.8,-9 -12.4,-0.3 c 0.5,3.6 0.7,6.8 0.7,9.5 z" />
<!--window 5-->
<polygon points="175.4,305.7 175.8,294.8 169.8,295 169.4,305.5 " />
<polygon points="170.3,283.6 169.9,293.4 175.9,293.3 176.2,283.6 " />
<polygon points="178.2,283.6 177.7,293.3 183.9,293.2 184.5,283.6 " />
<polygon points="183.8,294.4 177.6,294.7 177,305.8 183,306.1 " />
<!--window 6-->
<path d="m 204.8,315.5 c 1.8,0.1 3.6,0.1 4.9,0.1 -0.5,-1.9 -1.7,-3.8 -3.3,-4.5 -0.6,-0.3 -1.2,-0.4 -1.8,-0.5 0.1,1.2 0.1,3 0.2,4.9 z" />
<path d="m 203,322.5 v -6.1 l -5.8,-0.2 c -0.6,3.3 2.5,5.7 5.8,6.3 z" />
<path d="m 205.1,322.6 c 2.6,-0.2 4.9,-1.8 4.9,-5.2 0,0 0,0 0,-0.1 0,-0.2 0,-0.5 -0.1,-0.8 l -5.1,-0.1 c 0.1,2.3 0.2,4.6 0.3,6.2 z" />
<path d="m 203,315.5 v -4.9 c -1.8,0.2 -3.4,1.3 -4.5,2.8 -0.4,0.6 -0.8,1.2 -1,1.8 1.2,0.1 3.3,0.2 5.5,0.3 z" />
</g>
</g>
<path id="banner-halloween-ground" fill="url(#ground-gradient)" d="m 1033.896,367.2 c -77.89999,5.6 -117.16159,-0.1 -203.16319,1.7 -24.097,0.5 -48.6096,-0.7 -72.4989,0.5 -57.7499,2.9 -118.8235,3.8 -173.0419,10.8 -104.07437,13.4 -154.55357,8.3 -271.09197,3.1 -48.6096,-2.1 -127.1328,-1.3 -175.95013,-2.4 -126.09413,-2.8 -205.24053,9.3 -325.10267,1.8 -74.57626,-4.7 -136.4808,-3.8 -202.74773,-15.7 -12.04853,-2.1 -24.51253,-4.2 -37.392,-6 V 500.1 H 1130.9075 V 364.6 c -33.4451,3 -62.32,0.1 -97.0115,2.6 z" />
<g id="banner-halloween-objects" fill="var(--object-fill-day{{banner_day}})">
<g id="banner-halloween-bats" transform="translate(369.01441,-6.9206685)">
<path d="m 168,214.3 c -0.1,0 -4.2,-1.1 -5.1,2.9 0,0 -3.4,-1.7 -5,1.8 0,0 -2.9,-2.6 -5.2,1.2 0,0 -3.6,-2.8 -5.8,1.6 0,0 -4,-0.5 -3.1,4.6 -0.9,-5.1 -4.5,-3.3 -4.5,-3.3 -3.5,-3.4 -6,0.5 -6,0.5 -3.5,-2.9 -5.3,0.6 -5.3,0.6 -2.7,-2.7 -5.3,0 -5.3,0 -2.2,-3.5 -5.6,-1 -5.7,-1 3.1,-9.9 13.5,-10.9 13.5,-10.9 3.3,5.8 9.8,4.6 9.8,4.6 l -0.5,-2.6 2,0.9 1.6,-1.5 0.5,2.6 c 0,0 6.6,-1.2 7.7,-7.7 0,0.1 10,-2.6 16.4,5.7 z" class="banner-halloween-bat" />
<path d="m 210.1,229.7 c 0.1,0 2.5,-0.7 3,1.7 0,0 2,-1 3,1.1 0,0 1.7,-1.6 3.1,0.7 0,0 2.1,-1.7 3.4,0.9 0,0 2.4,-0.3 1.8,2.8 0.5,-3 2.7,-2 2.7,-2 2.1,-2 3.5,0.3 3.5,0.3 2.1,-1.7 3.2,0.4 3.2,0.4 1.6,-1.6 3.2,0 3.2,0 1.3,-2.1 3.4,-0.6 3.4,-0.6 -1.9,-5.9 -8,-6.5 -8,-6.5 -1.9,3.4 -5.9,2.7 -5.9,2.7 l 0.3,-1.6 -1.2,0.6 -0.9,-0.9 -0.3,1.6 c 0,0 -3.9,-0.7 -4.6,-4.6 0.1,0.1 -5.9,-1.5 -9.7,3.4 z" class="banner-halloween-bat" />
<path d="m 211.4,245.7 c 0,0 -1.4,-0.4 -1.7,1 0,0 -1.1,-0.6 -1.7,0.6 0,0 -1,-0.9 -1.7,0.4 0,0 -1.2,-0.9 -1.9,0.5 0,0 -1.3,-0.2 -1,1.5 -0.3,-1.7 -1.5,-1.1 -1.5,-1.1 -1.2,-1.1 -2,0.2 -2,0.2 -1.2,-1 -1.8,0.2 -1.8,0.2 -0.9,-0.9 -1.8,0 -1.8,0 -0.7,-1.2 -1.9,-0.3 -1.9,-0.3 1,-3.3 4.5,-3.6 4.5,-3.6 1.1,1.9 3.3,1.5 3.3,1.5 l -0.2,-0.9 0.7,0.3 0.5,-0.5 0.2,0.9 c 0,0 2.2,-0.4 2.6,-2.6 0,0 3.3,-0.8 5.4,1.9 z" class="banner-halloween-bat" />
</g>
<g id="banner-halloween-tombstones" transform="translate(401.83223,-17.586078)">
<path d="m 511.07106,391.70251 c 0,0 2.7,-37.3 13.3,-38 10.7,-0.7 24,3.3 12.7,37.7 z" />
<path d="m 473.03033,397.16784 c 0,0 -9.3,-22.6 -3.2,-26.1 6.1,-3.5 15,-5 18.4,18.4 z" />
<path d="m 261.40415,405.16163 c 0,0 0.1,-24.5 7.1,-25.4 6.9,-0.9 15.8,1.1 9.9,24 z" />
<path d="m 154.275,403.64299 c 0,0 0.1,-24.5 7.1,-25.4 6.9,-0.9 15.8,1.1 9.9,24 z" />
<path d="m 414.1,367.5 -0.6,-4.4 2.7,-0.6 -0.4,-2.8 -2.7,0.6 -0.5,-3.5 -3.1,0.5 0.5,3.7 -3.1,0.8 0.8,2.4 2.7,-0.6 0.6,4.4 c -0.2,0.1 -0.5,0.1 -0.7,0.2 -6.6,2.1 -2.3,26.2 -2.3,26.2 l 16.4,-4.4 c 1.4,-19.1 -4.4,-22.9 -10.3,-22.5 z" />
</g>
</g>
</g>
<g id="banner-halloween-gradients">
<linearGradient id="house-fill-gradient" gradientUnits="userSpaceOnUse" x1="149.4008" y1="260.50101" x2="149.4008" y2="546.78699">
<stop offset="0" style="stop-color:#0f021b"/>
<stop offset="1" style="stop-color:var(--house-shadow-day{{banner_day}})" id="house-fill-gradient-stop"/>
</linearGradient>
<radialGradient id="banner-halloween-house-window-gradient">
<stop offset="0" style="stop-color:#B3C691"/>
<stop offset="1" style="stop-color:#8DC39C"/>
</radialGradient>
<linearGradient id="ground-gradient" gradientUnits="userSpaceOnUse" x1="375" y1="451.8345" x2="375" y2="228.17931" gradientTransform="matrix(2.0773333,0,0,1,-427.09249,0)">
<stop offset="0" style="stop-color:#140224"/>
<stop offset="1" style="stop-color:var(--ground-shadow-day{{banner_day}})" id="ground-gradient-stop"/>
</linearGradient>
</g>
</svg>
</a>
<!--debug-->
{% if SITE == 'localhost' or SITE == 'devrama.net' %}
<script defer src="{{'js/event/banner-debug.js' | asset}}"></script>
{% endif %}

View File

@ -0,0 +1,24 @@
{% if not (v and v.poorcel) and not (v and v.hwmusic) and not (sub and sub.name == 'music') %}
{% if not song %}
{% set path = "assets/media/event/music" %}
{% set song = "/" + path + "/" + listdir('files/' + path)|random() + '?v=45' %}
{% endif %}
<script>
const audio = new Audio("{{song}}");
audio.loop=true;
function play() {
audio.play();
}
audio.loop=true;
window.addEventListener('load', function() {
audio.play();
document.getElementById('frontpage').addEventListener('click', () => {
if (audio.paused) audio.play();
}, {once : true});
prepare_to_pause(audio)
});
</script>
{% endif %}

View File

@ -0,0 +1,158 @@
<div class="col sidebar text-left {% if '/sidebar' not in request.path %}d-none d-lg-block{% endif %} pt-3 pb-5" {% if request.path != '/sidebar' %}id="sidebar-content"{% endif %}>
{% if sub %}
{% set image = sub.sidebar_url %}
{% else %}
{% set sidebar_path = "assets/images/event/sidebar" %}
{% set selected_image = listdir('files/' + sidebar_path)|random() %}
{% set image = "/" + sidebar_path + "/" + selected_image + '?v=45' %}
{% endif %}
{% if request.path != '/sidebar' %}
<a href="{{image}}" style="text-decoration:none">
<img class="mb-4" alt="sidebar image" onclick="expandDesktopImage()" loading="lazy" src="{{image}}" width=100%>
{% if not sub %}
{% set coordsLookup = ({
"1.webp":({
"left":({
"x":"72px",
"y":"-205px"
}),
"right":({
"x":"112px",
"y":"-209px"
})
}),
"2.webp":({
"left":({
"x":"35px",
"y":"-335px"
}),
"right":({
"x":"60px",
"y":"-337px"
})
}),
"3.webp":({
"left":({
"x":"88px",
"y":"-272px"
}),
"right":({
"x":"112px",
"y":"-276px"
})
}),
"4.webp":({
"left":({
"x":"28px",
"y":"-152px"
}),
"right":({
"x":"32px",
"y":"-152px"
})
}),
"5.webp":({
"left":({
"x":"58px",
"y":"-155px"
}),
"right":({
"x":"82px",
"y":"-160px"
})
}),
"6.webp":({
"left":({
"x":"125px",
"y":"-219px"
}),
"right":({
"x":"153px",
"y":"-219px"
})
})
}) %}
<div class="d-none d-lg-block" style="position:absolute">
<img id="left-eye" class="eye" src="/assets/images/event/eye.webp" loading="lazy" style="left:{{[coordsLookup][0][selected_image]['left']['x']}};top:{{[coordsLookup][0][selected_image]['left']['y']}}">
<img id="right-eye" class="eye" src="/assets/images/event/eye.webp" loading="lazy" style="left:{{[coordsLookup][0][selected_image]['right']['x']}};top:{{[coordsLookup][0][selected_image]['right']['y']}}">
</div>
{% endif %}
</a>
{% endif %}
<p class="text-center text-md mb-4">
<a class="sidebar-link" href="/marseys" data-bs-toggle="tooltip" data-bs-placement="top" title="Marseys"><i class="fas fa-cat"></i></a>
<a class="sidebar-link" href="/badges" data-bs-toggle="tooltip" data-bs-placement="top" title="Badges"><i class="fas fa-hexagon"></i></a>
<a class="sidebar-link" href="/admins" data-bs-toggle="tooltip" data-bs-placement="top" title="Admins"><i class="fas fa-crown"></i></a>
<a class="sidebar-link" href="/log" data-bs-toggle="tooltip" data-bs-placement="top" title="Moderation Log"><i class="fas fa-scroll-old"></i></a>
<a class="sidebar-link" href="/transfers" data-bs-toggle="tooltip" data-bs-placement="top" title="Transfers"><i class="fas fa-arrow-right-arrow-left"></i></a>
<a class="sidebar-link" href="/random_post" data-bs-toggle="tooltip" data-bs-placement="top" title="Random Post"><i class="fas fa-random"></i></a>
<span class="sidebar-link" onclick="if(localStorage.getItem('setting_upsidedown')=='true'){localStorage.setItem('setting_upsidedown', 'false')}else{localStorage.setItem('setting_upsidedown', 'true')};location.reload()" style="display:inline" data-bs-toggle="tooltip" data-bs-placement="top" title="???"><i class="fas fa-trees"></i></span>
</p>
{% set healthy = range(50,70) | random %}
<div class="progress">
<div style="--width:{{bar_position[0]}}%;" class="bar-left"></div>
<div style="--width:{{bar_position[1]}}%;" class="bar-right"></div>
<div class="legend">
<span title="{{bar_position[2]}}">{{bar_position[0]}}% Vaxxed</span>
<span title="{{bar_position[3]}}">{{bar_position[1]}}% Infected</span>
</div>
</div>
{% if sub %}
{% if sub.sidebar_html %}
<div class="mb-4">{{sub.sidebar_html|safe}}</div>
{% endif %}
{% if v %}
<a class="btn btn-primary btn-block mb-3" href="/holes">BROWSE {{HOLE_NAME|upper}}S</a>
{% if v.can_create_hole -%}
<a class="btn btn-primary btn-block mb-3" href="/create_hole">CREATE {{HOLE_NAME|upper}}</a>
{%- endif %}
<a class="btn btn-primary btn-block mb-3" href="/h/{{sub}}/log">{{HOLE_NAME|upper}} LOG</a>
{% if v.mods(sub.name) %}
<a class="btn btn-primary btn-block mb-3" href="/h/{{sub}}/settings">{{HOLE_NAME|upper}} SETTINGS</a>
{% endif %}
{% endif %}
<a class="btn btn-primary btn-block mb-3" href="/h/{{sub}}/mods">{{HOLE_NAME|upper}} MODS</a>
<a class="btn btn-primary btn-block mb-3" href="/h/{{sub}}/exilees">{{HOLE_NAME|upper}} EXILEES</a>
{% else %}
<a id="sidebar--directory--btn" class="btn btn-primary btn-block mb-3" href="/directory">
<span id="sidebar--directory--head">DIRECTORY</span>
<span id="sidebar--directory--subhead">Submit Marseys & Art | Info Megathreads</span>
</a>
<a class="btn btn-primary btn-block mb-3" href="/holes">BROWSE {{HOLE_NAME|upper}}S</a>
{% if v and v.can_create_hole -%}
<a class="btn btn-primary btn-block mb-3" href="/create_hole">CREATE {{HOLE_NAME|upper}}</a>
{%- endif %}
<div class="sidebar--rules">
<h3 class="sidebar--rules-head mt-4 mb-3">Rules</h3>
<ol class="sidebar--rules-list sidebar--rules-list--rdrama">
<li class="font-weight-bold" style="color: red"><a href="/post/19711/a-short-guide-on-how-to" style="color: inherit">NO RIGHTWING AGENDAPOSTING.</a></li>
<li>Don't post anything illegal.</li>
<li>No sexualizing minors even as a “joke”.</li>
<li>No doxing.</li>
<li>Using alts to game dramacoin will get you banned.</li>
<li>Supporting free speech is an immediate ban.</li>
<li class="font-weight-bold">Absolutely NO anti-CCP sentiment.</li>
</ol>
<p>All rules can and likely will be ignored at the discretion of the janitorial staff. Be funny, or at least compelling, and pretty much anything legal is welcome.</p>
<p style="color: hotpink">𝐜𝐚𝐫𝐩 𝐰𝐨𝐳 𝐞𝐫𝐞</p>
</div>
{% endif %}
<pre>
</pre>
</div>
<script defer src="{{'js/event/eye-tracking.js' | asset}}" ></script>

View File

@ -0,0 +1,17 @@
<div class="spider">
<div class="spiderweb"></div>
<div class="body">
<div class="eye left"></div>
<div class="eye right"></div>
</div>
<div class="legs left">
<div class="leg"></div>
<div class="leg"></div>
<div class="leg"></div>
</div>
<div class="legs right">
<div class="leg"></div>
<div class="leg"></div>
<div class="leg"></div>
</div>
</div>

View File

@ -0,0 +1 @@
../../events/templates

View File

@ -84,4 +84,8 @@ if "load_chat" in argv:
else:
from files.routes import *
if FEATURES['HOLIDAY_EVENT']:
from events import *
init_event()
stdout.flush()

View File

@ -0,0 +1 @@
../../../events/assets/css

View File

@ -0,0 +1 @@
../../../events/assets/fonts

View File

@ -0,0 +1 @@
../../../events/assets/images

View File

@ -0,0 +1 @@
../../../events/assets/js

View File

@ -0,0 +1 @@
../../../events/assets/media

View File

@ -305,6 +305,7 @@ FEATURES = {
'PATRON_ICONS': False,
'ASSET_SUBMISSIONS': False,
'STREAMERS': False,
'HOLIDAY_EVENT': True,
}
WERKZEUG_ERROR_DESCRIPTIONS = {

View File

@ -390,6 +390,10 @@ def award_thing(v, thing_type, id):
if author.spider: author.spider += 86400
else: author.spider = int(time.time()) + 86400
badge_grant(user=author, badge_id=179, notify=False)
elif FEATURES['HOLIDAY_EVENT']:
from events import EVENT_AWARDS, award_thing_event
if kind in EVENT_AWARDS:
award_thing_event(v, kind, author)
if author.received_award_count: author.received_award_count += 1
else: author.received_award_count = 1

View File

@ -6,15 +6,19 @@
{% include "modals/expanded_image.html" %}
{% if '@' not in request.path %}
{% if sub and SITE_NAME != WPD %}
{% set src = sub.banner_url %}
{% set alt = ['/h/', sub, 'banner']|join %}
{% set class = 'site-banner-hole' %}
{% elif SITE_NAME == "rDrama" %}
{% set href = "https://secure.transequality.org/site/Donation2?df_id=1480" %}
{% set expand = false %}
{% if EVENT_BANNER and not sub %}
{% include 'event/' + EVENT_BANNER %}
{% else %}
{% if sub and SITE_NAME != WPD %}
{% set src = sub.banner_url %}
{% set alt = ['/h/', sub, 'banner']|join %}
{% set class = 'site-banner-hole' %}
{% elif SITE_NAME == "rDrama" %}
{% set href = "https://secure.transequality.org/site/Donation2?df_id=1480" %}
{% set expand = false %}
{% endif %}
{{macros.banner(src, href, alt, expand, class)}}
{% endif %}
{{macros.banner(src, href, alt, expand, class)}}
{% endif %}
{% endblock %}
@ -32,7 +36,8 @@
</div>
{% block sidebar %}
{% if has_sidebar and (home or p) %}
{% include "sidebar_" + SITE_NAME + ".html" %}
{% set sidebar = "sidebar_" + SITE_NAME + ".html" %}
{% include sidebar if not EVENT_SIDEBAR else ['event/', sidebar]|join %}
{% endif %}
{% endblock %}
</div>

View File

@ -0,0 +1 @@
../../events/templates

View File

@ -148,6 +148,10 @@
<link rel="stylesheet" href="{{'css/rDrama.css' | asset}}">
{% endif %}
{% if EVENT_STYLES %}
<link rel="stylesheet" href="/assets/css/event/{{EVENT_STYLES}}">
{% endif %}
{% if 'chat' in request.path %}
{% if IS_LOCALHOST %}
<link rel="stylesheet" href="https://rdrama.net/assets/css/chat_done.css">