// DVD SEIA
// -------------- INFORMATION --------------
// ------- HOW DO I USE IT?
// --- One time use
// 1) Copy this entire thing (there should be a copy button on top right of this page).
// 2) Go to the 4chan thread.
// 3) Open your browser dev tools.
// 4) Go to the "Console" tab.
// 5) Paste it. (If the browser doesn't allow you to paste anything then just type "allow pasting" first)
// 6) Press "Enter".
// --- Always Available
// 0) Make sure you have a Tampermonke/Violentmonkey/Greasemonkey extension installed. (howto assumes tamper but it should be the same)
// 1) Copy this entire thing (there should be a copy button on top right of this page).
// 2) Open your dashboard.
// 3) [+] (Add a new script)
// 4) Paste it.
// 5) Save.
// Optional) You can turn on updates in the settings to make sure the script is updated whenever somethine new is added.
//
// ------- WHAT DOES IT DO?
// --- Adds a few funny widgets to the 4chan page like:
// 1) Some buttons for spawning seias all over the thread.
// 2) Two clock that displays the time in the timezones both global and JP servers use.
// 3) Lists upcoming character birthdays.
//
// ------- IS IT SAFE?
// Code is all below, feel free to take a look.
//
// -------------- START OF CODE --------------
// ==UserScript==
// @name DVDoom
// @namespace http://tampermonkey.net/
// @version 2.1.1
// @description Changes in 2.1.1: Changed the birthday source to use the short string instead of the long string.
// @author Seianon and Mimorianon
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @namespace rccom
// @match *://boards.4chan.org/*/thread/*
// @grant none
// @connect 4chan.org
// @connect 4channel.org
// @updateURL https://rentry.org/DVDoomSCRIPT/raw
// @downloadURL https://rentry.org/DVDoomSCRIPT/raw
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js
// ==/UserScript==
// The rest of the script and all that here, I'm including it so you know where it is
(async function () {
// Create a style element
const style = document.createElement('style');
style.innerHTML = `
.image-container {
display: flex;
align-items: center;
justify-content: center;
height: 60px;
margin: auto;
}
.image-container img {
max-width: 100%;
max-height: 100%;
display: block;
}
.centered-text {
text-align: center;
margin: 0;
font-size: 14px;
line-height: 20px;
height: 20px;
overflow: hidden;
}
.student-name {
display: block;
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
`;
// Insert the style element into the head of the document, so... the very start
document.head.appendChild(style);
const SEIA_ENCLOSURE = document.createElement('div');
SEIA_ENCLOSURE.id = 'seiaEnclosure';
document.getElementsByClassName("thread")[0].appendChild(SEIA_ENCLOSURE);
document.getElementById("op").insertAdjacentHTML('afterend', '<div id="DVDoomParent" style="display: flex; justify-content: space-between;"></div><hr/>');
///////////
const DEFAULT_SIZE = 75;
const DEFAULT_SPEED = 2;
const MAX_TRAIL_LENGTH = 25;
let screenHeight = document.body.clientHeight;
let screenWidth = document.body.clientWidth;
let EOS = false;
const SEIA_TYPE_MAP = new Map();
const SEIA_STRING_ENUM = {};
///////////
class DVDoom {
constructor(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing) {
this.elementSize = elementSize;
this.positionX = positionX;
this.positionY = positionY;
this.directionX = directionX;
this.directionY = directionY;
this.speed = speed;
this.hue = hue;
this.background = background;
this.htmlElement = document.createElement('div');
this.htmlElement.className = 'doomvdoom';
this.facing = facing
let filterType = (hue === null) ? `grayscale(1)` : `hue-rotate(`+ hue +`deg)`;
this.htmlElement.style.cssText = `
transform: scaleX(`+ facing +`);
position: absolute;
left: `+ positionX +`px;
top: `+ positionY +`px;
height: `+ elementSize +`px;
width: `+ elementSize +`px;
-webkit-filter: `+ filterType +`;
background: url("`+ background +`");
pointer-events: none;
background-size: `+ elementSize +`px;
mask-mode: luminance;
`;
this.valid = true;
}
adjust() {
return true;
}
destroy() {
this.htmlElement.remove();
this.valid = false;
}
static make() {
return null;
}
}
class DVDoomRE extends DVDoom {
adjust() {
if (((this.positionY + (this.elementSize * 1.3)) >= screenHeight) && this.directionY > 0) {
this.directionY = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * -1;
this.directionX = (2 - Math.abs(this.directionY)) * (this.directionX > 0 ? 1 : -1);
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+Math.floor(Math.random() * 360)+'deg)';
} else if ((this.positionY < 0) && this.directionY < 0) {
this.directionY = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * 1;
this.directionX = (2 - Math.abs(this.directionY)) * (this.directionX > 0 ? 1 : -1);
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+Math.floor(Math.random() * 360)+'deg)';
}
if (((this.positionX + (this.elementSize * 1.3)) >= screenWidth) && this.directionX > 0) {
this.directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * -1;
this.directionY = (2 - Math.abs(this.directionX)) * (this.directionY > 0 ? 1 : -1);
this.htmlElement.style["transform"] = 'scaleX(-1)';
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+Math.floor(Math.random() * 360)+'deg)';
} else if ((this.positionX < 0)&& this.directionX < 0) {
this.directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * 1;
this.directionY = (2 - Math.abs(this.directionX)) * (this.directionY > 0 ? 1 : -1);
this.htmlElement.style["transform"] = 'scaleX(1)';
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+Math.floor(Math.random() * 360)+'deg)';
}
this.positionX += this.directionX * this.speed;
this.positionY += this.directionY * this.speed;
this.htmlElement.style.left = this.positionX + "px";
this.htmlElement.style.top = this.positionY + "px";
return true;
}
static make() {
let sizeMultiplier = ((Math.random() * 0.75) + 0.5);
let elementSize = DEFAULT_SIZE * sizeMultiplier;
let positionX = Math.floor(Math.random() * ((screenWidth * 0.99) - elementSize));
let positionY = Math.floor(Math.random() * ((screenHeight * 0.99) - elementSize));
let directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * ((Math.random() >= 0.5)? 1 : -1);
let directionY = (2 - Math.abs(directionX)) * ((Math.random() >= 0.5)? 1 : -1);
let speed = DEFAULT_SPEED * (Math.random() + 0.5);
let hue = Math.floor(Math.random() * 360);
let facing = (directionX > 0 ? 1 : -1);
if (Math.random() < 0.001) {
let background = 'https://files.catbox.moe/p23xa2.gif';
return new DVDoomREShiny(elementSize, positionX, positionY, directionX, directionY, speed, 0, background, facing, sizeMultiplier);
} else {
let background = 'https://files.catbox.moe/ph1rgd.gif';
return new DVDoomRE(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing);
}
}
}
class DVDoomREShiny extends DVDoomRE {
constructor(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing, sizeMultiplier) {
super(elementSize, positionX, positionY, directionX, directionY, speed, 60, background, facing);
this.htmlElement.style.cssText = `
transform: scaleX(`+ facing +`);
position: absolute;
left: `+ positionX +`px;
top: `+ positionY +`px;
height: `+ elementSize +`px;
width: `+ elementSize +`px;
-webkit-filter: drop-shadow(0px 0px `+ 15 * sizeMultiplier +`px #ffd000) contrast(130%); brightness(150%);
background: url("https://files.catbox.moe/p23xa2.gif");
pointer-events: none;
background-size: `+ elementSize +`px;
mask-mode: luminance;
`;
}
adjust() {
if (((this.positionY + (this.elementSize * 1.3)) >= screenHeight) && this.directionY > 0) {
this.directionY = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * -1;
this.directionX = (2 - Math.abs(this.directionY)) * (this.directionX > 0 ? 1 : -1);
} else if ((this.positionY < 0) && this.directionY < 0) {
this.directionY = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * 1;
this.directionX = (2 - Math.abs(this.directionY)) * (this.directionX > 0 ? 1 : -1);
}
if (((this.positionX + (this.elementSize * 1.3)) >= screenWidth) && this.directionX > 0) {
this.directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * -1;
this.directionY = (2 - Math.abs(this.directionX)) * (this.directionY > 0 ? 1 : -1);
this.htmlElement.style["transform"] = 'scaleX(-1)';
} else if ((this.positionX < 0)&& this.directionX < 0) {
this.directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * 1;
this.directionY = (2 - Math.abs(this.directionX)) * (this.directionY > 0 ? 1 : -1);
this.htmlElement.style["transform"] = 'scaleX(1)';
}
this.positionX += this.directionX * this.speed;
this.positionY += this.directionY * this.speed;
this.htmlElement.style.left = this.positionX + "px";
this.htmlElement.style.top = this.positionY + "px";
return true;
}
}
class DVDoomClassic extends DVDoom {
adjust() {
if (((this.positionY + (this.elementSize * 1.3)) >= screenHeight) && this.directionY > 0) {
this.directionY = -1;
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+Math.floor(Math.random() * 360)+'deg)';
} else if ((this.positionY < 0) && this.directionY < 0) {
this.directionY = 1;
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+Math.floor(Math.random() * 360)+'deg)';
}
if (((this.positionX + (this.elementSize * 1.3)) >= screenWidth) && this.directionX > 0) {
this.directionX = -1;
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+Math.floor(Math.random() * 360)+'deg)';
} else if ((this.positionX < 0)&& this.directionX < 0) {
this.directionX = 1;
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+Math.floor(Math.random() * 360)+'deg)';
}
this.positionX += this.directionX * this.speed;
this.positionY += this.directionY * this.speed;
this.htmlElement.style.left = this.positionX + "px";
this.htmlElement.style.top = this.positionY + "px";
return true;
}
static make() {
let elementSize = DEFAULT_SIZE;
let positionX = Math.floor(Math.random() * ((screenWidth * 0.99) - elementSize));
let positionY = Math.floor(Math.random() * ((screenHeight * 0.99) - elementSize));
let directionX = (Math.random() >= 0.5)? 1 : -1;
let directionY = (Math.random() >= 0.5)? 1 : -1;
let speed = DEFAULT_SPEED;
let hue = Math.floor(Math.random() * 360);
let facing = 1;
let background = 'https://files.catbox.moe/ph1rgd.gif';
return new DVDoomRE(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing, background);
}
}
class DvDoomAuxStationary extends DVDoom {
}
class DVDoomTrailing extends DVDoom {
constructor(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing) {
super(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing);
this.trail = [];
this.lastSpawn = 0;
}
adjust() {
if (this.lastSpawn > 10) {
let newTrailSeia = new DvDoomAuxStationary(
this.elementSize,
this.positionX,
this.positionY,
this.directionX,
this.directionY,
this.speed,
this.hue,
this.background,
(this.directionX > 0 ? 1 : -1)
);
this.trail.push(newTrailSeia);
SEIA_ENCLOSURE.insertBefore(newTrailSeia.htmlElement, this.htmlElement);
this.lastSpawn = 0;
}
this.lastSpawn += 1;
for (let index = 0; index < this.trail.length; index++) {
let currentTrailElement = this.trail[index].htmlElement;
currentTrailElement.style['opacity'] = (index) / MAX_TRAIL_LENGTH;
}
if (this.trail.length > MAX_TRAIL_LENGTH) {
this.trail[0].destroy();
this.trail.splice(0, 1);
}
if (((this.positionY + (this.elementSize * 1.3)) >= screenHeight) && this.directionY > 0) {
this.directionY = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * -1;
this.directionX = (2 - Math.abs(this.directionY)) * (this.directionX > 0 ? 1 : -1);
} else if ((this.positionY < 0) && this.directionY < 0) {
this.directionY = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * 1;
this.directionX = (2 - Math.abs(this.directionY)) * (this.directionX > 0 ? 1 : -1);
}
if (((this.positionX + (this.elementSize * 1.3)) >= screenWidth) && this.directionX > 0) {
this.directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * -1;
this.directionY = (2 - Math.abs(this.directionX)) * (this.directionY > 0 ? 1 : -1);
this.htmlElement.style["transform"] = 'scaleX(-1)';
} else if ((this.positionX < 0) && this.directionX < 0) {
this.directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * 1;
this.directionY = (2 - Math.abs(this.directionX)) * (this.directionY > 0 ? 1 : -1);
this.htmlElement.style["transform"] = 'scaleX(1)';
}
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+this.hue+'deg)';
this.hue = ((this.hue + 1) % 360);
this.positionX += this.directionX * this.speed;
this.positionY += this.directionY * this.speed;
this.htmlElement.style.left = this.positionX + "px";
this.htmlElement.style.top = this.positionY + "px";
return true;
}
destroy() {
for (let index = this.trail.length - 1; index >= 0; index--) {
let currentTrailElement = this.trail[index];
currentTrailElement.destroy();
this.trail.splice(index, 1);
}
this.htmlElement.remove();
}
static make() {
let elementSize = DEFAULT_SIZE;
let positionX = Math.floor(Math.random() * ((screenWidth * 0.99) - elementSize));
let positionY = Math.floor(Math.random() * ((screenHeight * 0.99) - elementSize));
let directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * ((Math.random() >= 0.5)? 1 : -1);
let directionY = (2 - Math.abs(directionX)) * ((Math.random() >= 0.5)? 1 : -1);
let speed = DEFAULT_SPEED;
let hue = Math.floor(Math.random() * 360);
let facing = (directionX > 0 ? 1 : -1);
let background = 'https://files.catbox.moe/ph1rgd.gif';
return new DVDoomTrailing(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing, background);
}
}
class DVDoomFractal extends DVDoom {
splitSeia(wallHit) {
let elementSize = Math.floor(this.elementSize * 0.75);
if (elementSize < 12) {
return;
}
const documentfragment = document.createDocumentFragment();
let directionY1;
let directionX1;
let directionY2;
let directionX2;
if (wallHit) {
directionX1 = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * (this.directionX > 0 ? -1 : 1);
directionY1 = (2 - Math.abs(directionX1)) * ((Math.random() >= 0.5) ? 1 : -1);
directionX2 = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * (this.directionX > 0 ? -1 : 1);
directionY2 = (2 - Math.abs(directionX2)) * ((Math.random() >= 0.5) ? 1 : -1);
} else {
directionY1 = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * (this.directionY > 0 ? -1 : 1);
directionX1 = (2 - Math.abs(directionY1)) * ((Math.random() >= 0.5) ? 1 : -1);
directionY2 = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * (this.directionY > 0 ? -1 : 1);
directionX2 = (2 - Math.abs(directionY2)) * ((Math.random() >= 0.5) ? 1 : -1);
}
let positionX1 = this.positionX + (directionX1 * this.speed);
let positionY1 = this.positionY + (directionY1 * this.speed);
let positionX2 = this.positionX + (directionX2 * this.speed);
let positionY2 = this.positionY + (directionY2 * this.speed);
let childSeia1 = new DVDoomFractal(
elementSize,
positionX1,
positionY1,
directionX1,
directionY1,
this.speed,
Math.floor(Math.random() * 360),
this.background,
(directionX1 > 0 ? 1 : -1)
);
SEIA_TYPE_MAP.get(DVDoomFractal).push(childSeia1);
documentfragment.appendChild(childSeia1.htmlElement);
let childSeia2 = new DVDoomFractal(
elementSize,
positionX2,
positionY2,
directionX2,
directionY2,
this.speed,
Math.floor(Math.random() * 360),
this.background,
(directionX2 > 0 ? 1 : -1)
);
SEIA_TYPE_MAP.get(DVDoomFractal).push(childSeia2);
documentfragment.appendChild(childSeia2.htmlElement);
SEIA_ENCLOSURE.appendChild(documentfragment);
}
adjust() {
if (((this.positionY + (this.elementSize * 1.3)) >= screenHeight) && this.directionY > 0) {
this.splitSeia(false);
return false;
} else if ((this.positionY < 0) && this.directionY < 0) {
this.splitSeia(false);
return false;
}
if (((this.positionX + (this.elementSize * 1.3)) >= screenWidth) && this.directionX > 0) {
this.splitSeia(true);
return false;
} else if ((this.positionX < 0)&& this.directionX < 0) {
this.splitSeia(true);
return false;
}
this.positionX += this.directionX * this.speed;
this.positionY += this.directionY * this.speed;
this.htmlElement.style.left = this.positionX + "px";
this.htmlElement.style.top = this.positionY + "px";
return true;
}
static make() {
let elementSize = DEFAULT_SIZE * 2.5;
let positionX = Math.floor(Math.random() * ((screenWidth * 0.99) - elementSize));
let positionY = Math.floor(Math.random() * ((screenHeight * 0.99) - elementSize));
let directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * ((Math.random() >= 0.5)? 1 : -1);
let directionY = (2 - Math.abs(directionX)) * ((Math.random() >= 0.5)? 1 : -1);
let speed = DEFAULT_SPEED;
let hue = Math.floor(Math.random() * 360);
let facing = (directionX > 0 ? 1 : -1);
let background = 'https://files.catbox.moe/ph1rgd.gif';
return new DVDoomFractal(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing, background);
}
}
class DVDoomPlayer extends DVDoom {
constructor(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing) {
super(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing);
this.trail = [];
this.maxTrailSize = 0;
this.lastSpawn = 0;
this.customEventListener = (event) => {
switch(event.key) {
case 'a':
if(this.directionX == 0){
this.directionY = 0;
this.directionX = -1;
this.htmlElement.style["transform"] = 'scaleX(-1)';
}
break;
case 'd':
if(this.directionX == 0){
this.directionY = 0;
this.directionX = 1;
this.htmlElement.style["transform"] = 'scaleX(1)';
}
break;
case 'w':
if(this.directionY == 0){
this.directionX = 0;
this.directionY = -1;
}
break;
case 's':
if(this.directionY == 0){
this.directionX = 0;
this.directionY = 1;
}
break;
default:
break;
}
}
window.addEventListener(
"keydown",
this.customEventListener,
true,
);
}
adjust() {
for (let index = this.trail.length - 4; index > 0; index--) {
let currentSeiaHunter = this.trail[index];
if(
((this.positionX + (this.elementSize * 0.15)) < (currentSeiaHunter.positionX + currentSeiaHunter.elementSize))
&&
((this.positionX + (this.elementSize * 0.85)) > currentSeiaHunter.positionX)
&&
((this.positionY + (this.elementSize * 0.15)) < (currentSeiaHunter.positionY + currentSeiaHunter.elementSize))
&&
((this.positionY + (this.elementSize * 0.85)) > (currentSeiaHunter.positionY))
) {
for (let index = this.trail.length - 1; index >= 0; index--) {
this.trail[index].destroy();
this.trail.splice(index, 1);
}
return false;
}
}
if (
(this.positionY + (this.elementSize * 1.3) >= screenHeight) ||
(this.positionY < 0) ||
(this.positionX + (this.elementSize * 1.3) >= screenWidth) ||
(this.positionX < 0)
) {
for (let index = this.trail.length - 1; index >= 0; index--) {
this.trail[index].destroy();
this.trail.splice(index, 1);
}
return false;
}
if (this.lastSpawn > 18 && this.maxTrailSize > 0) {
if (this.trail.length === this.maxTrailSize) {
this.trail[0].destroy();
this.trail.splice(0, 1);
}
let newTrailSeia = new DvDoomAuxStationary(
this.elementSize,
this.positionX,
this.positionY,
this.directionX,
this.directionY,
this.speed,
this.hue,
this.background,
(this.directionX > 0 ? 1 : -1)
);
this.trail.push(newTrailSeia);
SEIA_ENCLOSURE.insertBefore(newTrailSeia.htmlElement, this.htmlElement);
this.lastSpawn = 0;
}
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+this.hue+'deg)';
this.hue = ((this.hue + 1) % 360);
this.lastSpawn += 1;
this.positionX += this.directionX * this.speed;
this.positionY += this.directionY * this.speed;
this.htmlElement.style.left = this.positionX + "px";
this.htmlElement.style.top = this.positionY + "px";
return true;
}
destroy() {
for (let index = this.trail.length - 1; index >= 0; index--) {
let currentTrailElement = this.trail[index];
currentTrailElement.destroy();
this.trail.splice(index, 1);
}
window.removeEventListener('keydown', this.customEventListener);
super.destroy();
}
static make() {
let elementSize = DEFAULT_SIZE * 0.8;
let positionX = Math.floor(((screenWidth * 0.5) - elementSize));
let positionY = Math.floor(elementSize * 2);
let directionX = 0;
let directionY = 1;
let speed = DEFAULT_SPEED * 1.5;
let hue = Math.floor(Math.random() * 360);
let facing = 1;
let background = 'https://files.catbox.moe/p23xa2.gif';
return new DVDoomPlayer(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing, background);
}
}
class DVDoomPlayerPoint extends DVDoom {
constructor(elementSize, positionX, positionY, directionX, directionY, speed, background, facing) {
super(elementSize, positionX, positionY, directionX, directionY, speed, null, background, facing);
this.pointMode = null;
}
changeMode() {
switch((Math.random() * 3) << 0) {
case 2:
case 1:
this.hue = 60;
this.pointMode = true;
break;
case 0:
this.hue = 300;
this.pointMode = false;
break;
default:
this.hue = 0;
this.pointMode = null;
break;
}
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+this.hue+'deg)';
}
adjust() {
let seiaPlayers = SEIA_TYPE_MAP.get(DVDoomPlayer);
if(this.pointMode != null) {
for (let index = seiaPlayers.length - 1; index >= 0; index--) {
let currentSeiaHunter = seiaPlayers[index];
if(
((this.positionX) < (currentSeiaHunter.positionX + currentSeiaHunter.elementSize))
&&
((this.positionX + (this.elementSize)) > currentSeiaHunter.positionX)
&&
((this.positionY) < (currentSeiaHunter.positionY + currentSeiaHunter.elementSize))
&&
((this.positionY + (this.elementSize)) > (currentSeiaHunter.positionY))
) {
if(this.pointMode) {
currentSeiaHunter.maxTrailSize += 1;
} else {
currentSeiaHunter.destroy();
}
return false;
}
}
}
if (((this.positionY + (this.elementSize * 1.3)) >= screenHeight) && this.directionY > 0) {
this.directionY = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * -1;
this.directionX = (2 - Math.abs(this.directionY)) * (this.directionX > 0 ? 1 : -1);
this.changeMode();
} else if ((this.positionY < 0) && this.directionY < 0) {
this.directionY = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * 1;
this.directionX = (2 - Math.abs(this.directionY)) * (this.directionX > 0 ? 1 : -1);
this.changeMode();
}
if (((this.positionX + (this.elementSize * 1.3)) >= screenWidth) && this.directionX > 0) {
this.directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * -1;
this.directionY = (2 - Math.abs(this.directionX)) * (this.directionY > 0 ? 1 : -1);
this.htmlElement.style["transform"] = 'scaleX(-1)';
this.changeMode();
} else if ((this.positionX < 0)&& this.directionX < 0) {
this.directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * 1;
this.directionY = (2 - Math.abs(this.directionX)) * (this.directionY > 0 ? 1 : -1);
this.htmlElement.style["transform"] = 'scaleX(1)';
this.changeMode();
}
this.positionX += this.directionX * this.speed;
this.positionY += this.directionY * this.speed;
this.htmlElement.style.left = this.positionX + "px";
this.htmlElement.style.top = this.positionY + "px";
return true;
}
static make() {
let sizeMultiplier = 0.5;
let elementSize = DEFAULT_SIZE * sizeMultiplier;
let positionX = Math.floor(Math.random() * ((screenWidth * 0.99) - elementSize));
let positionY = Math.floor(Math.random() * ((screenHeight * 0.99) - elementSize));
let directionX = ((Math.random() * 2 * 0.8) + (2 * 0.2)) * ((Math.random() >= 0.5)? 1 : -1);
let directionY = (2 - Math.abs(directionX)) * ((Math.random() >= 0.5)? 1 : -1);
let speed = DEFAULT_SPEED * (Math.random() * 0.5) + 0.5;
let facing = (directionX > 0 ? 1 : -1);
let background = 'https://files.catbox.moe/p23xa2.gif';
return new DVDoomPlayerPoint(elementSize, positionX, positionY, directionX, directionY, speed, background, facing, background);
}
}
class DVDoomRain extends DVDoom {
constructor(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing, opacity) {
super(elementSize, positionX, positionY, directionX, directionY, speed, hue, background, facing);
let filterType = (hue === null) ? `grayscale(1)` : `hue-rotate(`+ hue +`deg)`;
this.opacity = opacity;
this.htmlElement.style.cssText = `
transform: scaleX(`+ facing +`);
position: absolute;
left: `+ positionX +`px;
top: `+ positionY +`px;
height: `+ elementSize +`px;
width: `+ elementSize * 0.35 +`px;
-webkit-filter: `+ filterType +`;
background: url("`+ background +`");
pointer-events: none;
background-size: 100% 100%;
background-repeat: no-repeat;
mask-mode: luminance;
opacity: ` + opacity + `;
`;
}
adjust() {
if (((this.positionY + (this.elementSize * 1.3)) >= screenHeight) && this.directionY > 0) {
this.directionY = Math.random() + 1;
this.positionY = this.elementSize;
this.htmlElement.style["-webkit-filter"] = 'hue-rotate('+Math.floor(Math.random() * 360)+'deg)';
this.htmlElement.style["transform"] = 'scaleX('+(Math.random() > 0.5 ? 1 : -1)+')';
this.speed = DEFAULT_SPEED * (Math.random() + 1);
}
this.positionY += this.directionY * this.speed;
this.htmlElement.style.left = this.positionX + "px";
this.htmlElement.style.top = this.positionY + "px";
return true;
}
static make() {
let sizeMultiplier = ((Math.random() * 0.5) + 0.5);
let elementSize = DEFAULT_SIZE * sizeMultiplier;
let positionX = Math.floor(Math.random() * (screenWidth - elementSize));
let positionY = Math.floor(Math.random() * ((screenHeight * 0.99) - elementSize));
let directionY = Math.random() + 1;
let speed = DEFAULT_SPEED * (Math.random() + 1);
let hue = Math.floor(Math.random() * 360);
let facing = (Math.random() > 0.5 ? 1 : -1);
let background = 'https://files.catbox.moe/p23xa2.gif';
let opacity = (Math.random() * 0.4) + 0.3;
return new DVDoomRain(elementSize, positionX, positionY, 0, directionY, speed, hue, background, facing, opacity);
}
}
///////////
function addNewSeia(seiaCountToAdd, seiaTypeString, clearPrevious) {
const seiaType = SEIA_STRING_ENUM[seiaTypeString];
const seiaTypeList = SEIA_TYPE_MAP.get(seiaType);
if(clearPrevious) {
for (let index = seiaTypeList.length - 1; index >= 0; index--) {
let currentSeia = seiaTypeList[index];
seiaTypeList.splice(index, 1);
currentSeia.destroy();
}
}
const documentfragment = document.createDocumentFragment();
const existingSeiaCount = seiaTypeList.length;
for (let index = existingSeiaCount; index < existingSeiaCount + seiaCountToAdd; index++) {
let seiaToBeAdded = seiaType.make();
seiaTypeList[index] = seiaToBeAdded;
documentfragment.appendChild(seiaToBeAdded.htmlElement);
}
SEIA_ENCLOSURE.appendChild(documentfragment);
}
function animateSEIAS() {
screenHeight = document.body.clientHeight;
screenWidth = document.body.clientWidth;
for (const [seiaType, seiaTypeList] of SEIA_TYPE_MAP) {
for (let index = seiaTypeList.length - 1; index >= 0; index--) {
let currentSeia = seiaTypeList[index];
if(currentSeia.valid) {
let result = currentSeia.adjust();
if (result === false) {
currentSeia.htmlElement.remove();
seiaTypeList.splice(index, 1);
}
} else {
seiaTypeList.splice(index, 1);
}
}
}
if (EOS) {
for (const [seiaType, seiaTypeList] of SEIA_TYPE_MAP) {
for (let index = seiaTypeList.length - 1; index >= 0; index--) {
let currentSeia = seiaTypeList[index];
currentSeia.destroy();
seiaTypeList.splice(index, 1);
}
}
EOS = false;
}
window.requestAnimationFrame(animateSEIAS);
}
[
DVDoomRE,
DVDoomClassic,
DVDoomFractal,
DVDoomTrailing,
DVDoomRain,
DVDoomPlayer,
DVDoomPlayerPoint
].forEach((seiaType) => {
SEIA_TYPE_MAP.set(seiaType, []);
SEIA_STRING_ENUM[seiaType.name] = seiaType;
});
///////////
window.addNewSeia = addNewSeia;
window.forceEoS = () => { EOS = true; }
document.getElementById("DVDoomParent").insertAdjacentHTML('afterbegin',`
<table style="margin-left: 5%; margin-right: 5%;" border="1">
<tr>
<th style="color:red; padding: 8px">Seia</th>
<td style="padding: 8px; text-align: center;">[<a id=\"addSeia1\" style=\"color:red; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(1, \'DVDoomRE\')\"> +1 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a id=\"addSeia10\" style=\"color:red; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(10, \'DVDoomRE\')\"> +10 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a id=\"addSeia100\" style=\"color:red; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(100, \'DVDoomRE\')\"> +100 </a>]</td>
</tr>
<tr>
<th style="color:limegreen; padding: 8px">Seia (Classic)</th>
<td style="padding: 8px; text-align: center;">[<a style=\"color:limegreen; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(1, \'DVDoomClassic\')\"> +1 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a style=\"color:limegreen; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(10, \'DVDoomClassic\')\"> +10 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a style=\"color:limegreen; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(100, \'DVDoomClassic\')\"> +100 </a>]</td>
</tr>
<tr>
<th style="color:blue; padding: 8px">Seia (Fractal)</th>
<td style="padding: 8px; text-align: center;">[<a style=\"color:blue; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(1, \'DVDoomFractal\')\"> +1 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a style=\"color:blue; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(2, \'DVDoomFractal\')\"> +2 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a style=\"color:blue; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(3, \'DVDoomFractal\')\"> +3 </a>]</td>
</tr>
<tr>
<th style="color:sandybrown; padding: 8px">Seia (Trailing)</th>
<td style="padding: 8px; text-align: center;">[<a style=\"color:sandybrown; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(1, \'DVDoomTrailing\')\"> +1 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a style=\"color:sandybrown; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(2, \'DVDoomTrailing\')\"> +2 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a style=\"color:sandybrown; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(3, \'DVDoomTrailing\')\"> +3 </a>]</td>
</tr>
<tr>
<th style="color:cornflowerblue; padding: 8px">Seia (Rain)</th>
<td style="padding: 8px; text-align: center;">[<a style=\"color:cornflowerblue ; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(1, \'DVDoomRain\')\"> +1 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a style=\"color:cornflowerblue; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(10, \'DVDoomRain\')\"> +10 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a style=\"color:cornflowerblue; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(100, \'DVDoomRain\')\"> +100 </a>]</td>
</tr>
<th style="color:indigo; padding: 8px">Seia (Game)</th>
<td style="padding: 8px; text-align: center;">[<a style=\"color:indigo; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(50, \'DVDoomPlayerPoint\')\"> +50 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a style=\"color:indigo; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(100, \'DVDoomPlayerPoint\')\"> +100 </a>]</td>
<td style="padding: 8px; text-align: center;">[<a style=\"color:indigo; font-weight: bold; cursor: pointer;\" onclick=\"addNewSeia(1, \'DVDoomPlayer\', true)\"> Start </a>]</td>
</tr>
<tr>
<th colspan="4" style="padding: 8px; text-align: center; padding: 8px">[<a style=\"font-weight: bold; cursor: pointer;\" onclick=\"forceEoS()\"> EoS </a>]</th>
</tr>
</table>
`);
animateSEIAS();
//////////////////////////////////////////////////
// Mimori was here
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
let fullStringTop = "";
let fullStringBottom = "";
// Function to add days to a date
function addDays(date, days) {
const copy = new Date(Number(date));
copy.setDate(date.getDate() + days);
return copy;
}
// Fetch birthdays data from the API (Don't worry, I asked for permission to use this API for this purpose. It's fine.)
async function fetchBirthdays() {
const response = await fetch('https://schale.gg/data/en/students.json');
const data = await response.json();
// This is assuming that the fetched JSON data is an array directly.
// If the actual data is an object with a property that holds the array, you'll need to adjust the code to match that structure.
// But for now, it will work with the current structure of the fetched data. In case it changes, it probably won't, adjust this code accordingly.
return data.reduce((acc, student) => {
// Extract the month and day from the birthday, considering the suffixes
const birthdayMatch = student.BirthDay.match(/(\d+)\/(\d+)/);
if (!birthdayMatch) return acc; // Skip if the birthday doesn't match the expected format (This shouldn't be an issue, but let's keep it here just in case)
const monthNumber = parseInt(birthdayMatch[1], 10);
const day = parseInt(birthdayMatch[2], 10);
if (!acc[monthNumber]) {
acc[monthNumber] = {};
}
if (!acc[monthNumber][day]) {
acc[monthNumber][day] = [];
}
// Last name, first name
const studentFullName = `${student.FamilyName} ${student.PersonalName}`;
// Find an existing student entry for this day
let studentEntry = acc[monthNumber][day].find(char => char.name === studentFullName);
// If found, push the new image to this student's image array (In other words, if this student has an alt)
if (studentEntry) {
if (!studentEntry.images.includes(`https://schale.gg/images/student/collection/${student.Id}.webp`)) {
studentEntry.images.push(`https://schale.gg/images/student/collection/${student.Id}.webp`);
}
} else {
// If not found, create a new entry for this student
acc[monthNumber][day].push({
name: studentFullName,
images: [`https://schale.gg/images/student/collection/${student.Id}.webp`]
});
}
return acc;
}, {});
}
const birthdays = await fetchBirthdays();
const baseDate = new Date();
// This loop checks for birthdays today and up to the next 7 days
for (let i = 0; i <= 6; i++) {
const currentDate = addDays(baseDate, i);
const month = currentDate.getMonth() + 1;
const day = currentDate.getDate();
const studentsByBirthday = birthdays[month]?.[day];
if (studentsByBirthday) {
fullStringTop += `<td style="font-weight: bold; padding: 8px; text-align: center;">${months[currentDate.getMonth()]} ${day}</td>`;
fullStringBottom += `<td style="font-weight: bold; text-align: center;">`;
for (const student of studentsByBirthday) {
fullStringBottom += `<div style="display: inline-block; padding: 8px;">
<div style="position: relative; text-align: justify;">
<center>${student.name}</center>
<center class="image-container" data-images="${student.images.join(',')}" style="width:60px;height:60px;">
<img src="${student.images[0]}" alt="${student.name}" style="width:60px;height:60px;">
</center>
</div>
</div>`;
}
fullStringBottom += `</td>`;
}
}
// To Seia: I sort of want to change this. Might do it at a later date. Might.
let finalString = `<table border="1"><tr><th colspan="100%" style="font-weight: bold; padding: 8px">[ Student Birthdays ]</th></tr><tr>` + fullStringTop + `</tr><tr>` + fullStringBottom +
`</tr><tr><th id="clockJST" colspan="100%" style="width: 100%; font-size: 18px; font-weight: bold; padding: 12px">JST TIME</th></tr>`+
`</tr><tr><th id="clockUTC" colspan="100%" style="width: 100%; font-size: 18px; font-weight: bold; padding: 12px">UTC TIME</th></tr></table>`
document.getElementById("DVDoomParent").insertAdjacentHTML(
'afterbegin',
`<div style="flex-grow: 1; flex-basis: 0; align-items: center; justify-content: center; display: flex;">` + (fullStringTop != "" ? finalString : "") + `</div>`
);
// To Seia: It's en-US but I'll leave it as such. I just wanted to change how the birhdays we're pulled because you hardcoding it...
const clockJST = document.getElementById("clockJST");
const clockUTC = document.getElementById("clockUTC");
const clockStyle = {hour: "numeric", minute: "numeric", second: "numeric", weekday: "short", month: "long", day: "numeric", hourCycle: 'h23'}
setInterval(() => {
const dateToUpdate = new Date();
clockJST.textContent = dateToUpdate.toLocaleString('en-US', {...clockStyle, ...{timeZone: 'Japan'}}).replace(' at', ',') + ' JST';
clockUTC.textContent = dateToUpdate.toLocaleString('en-US', {...clockStyle, ...{timeZone: 'UTC'}}).replace(' at', ',') + ' UTC';
}, 1000);
//////////////////////////////////////////////////
document.getElementById("DVDoomParent").insertAdjacentHTML('beforeend', `
<div style="flex-grow: 1; flex-basis: 0;"></div>
`);
document.querySelectorAll('.image-container').forEach(container => {
let images = container.dataset.images.split(',');
let currentImageIndex = 0;
// Remove duplicates from the images array; shouldn't be an issue but just in case
images = [...new Set(images)];
// Set an interval only if there are multiple images to cycle through
// I'll be honest, I REALLY hope this works with 2-alt students like Haruna
if (images.length > 1) {
setInterval(() => {
currentImageIndex = (currentImageIndex + 1) % images.length; // Loop back to the first image
container.querySelector('img').src = images[currentImageIndex]; // Update the image source
}, 5000); // Change image every 5 seconds (5000 is 5000 milliseconds)
}
});
})();