diff --git a/backgrounds/gm_construct/1.jpg b/backgrounds/gm_construct/1.jpg
new file mode 100644
index 0000000..26e96bd
Binary files /dev/null and b/backgrounds/gm_construct/1.jpg differ
diff --git a/backgrounds/gm_construct/2.jpg b/backgrounds/gm_construct/2.jpg
new file mode 100644
index 0000000..7e3bc62
Binary files /dev/null and b/backgrounds/gm_construct/2.jpg differ
diff --git a/config.json b/config.json
new file mode 100644
index 0000000..012028f
--- /dev/null
+++ b/config.json
@@ -0,0 +1,23 @@
+{
+ "map": {
+ "gm_construct": {
+ "images": [
+ "/backgrounds/gm_construct/1.jpg",
+ "/backgrounds/gm_construct/2.jpg"
+ ],
+ "music": [
+ "/music/gm_construct/1.mp3"
+ ]
+ },
+ "gm_flatgrass": {
+ "images": [
+ "/backgrounds/gm_flatgrass/1.jpg",
+ "/backgrounds/gm_flatgrass/2.jpg"
+ ],
+ "music": [
+ "/music/gm_flatgrass/1.mp3",
+ "/music/gm_flatgrass/2.mp3"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/effects.js b/effects.js
new file mode 100644
index 0000000..378b711
--- /dev/null
+++ b/effects.js
@@ -0,0 +1,62 @@
+let currentImage = 1, prevImage = 0;
+let bgObj;
+
+// Certified MDN Classic
+function getRandomInt(max)
+{
+ return Math.floor(Math.random() * max);
+}
+
+async function GameDetails( servername, serverurl, mapname, maxplayers, steamid, gamemode, volume, language )
+{
+ const config = await (await fetch("/config.json")).json();
+ const audioplayer = document.getElementById("audioplayer");
+
+ let imgArray = [];
+
+ for (let i = 0; i < config.map[mapname].images.length; i++)
+ {
+ imgArray[i] = new Image();
+ imgArray[i].src = config.map[mapname].images[i];
+
+ let obj = document.createElement("img");
+ obj.classList.add("bgImage");
+ obj.src = imgArray[i].src;
+ document.getElementsByClassName("backgroundImages")[0].appendChild(obj);
+ }
+
+ bgObj = document.getElementsByClassName("bgImage");
+
+ document.getElementsByClassName("mapName")[0].innerHTML = "
" + mapname.toUpperCase() + "
";
+ document.getElementsByClassName("gamemodeName")[0].textContent = gamemode;
+
+ let autoCycleImages = setInterval(() => {
+
+ if (bgObj[prevImage].classList.contains("blendInAnimation"))
+ {
+ bgObj[prevImage].classList.remove("blendInAnimation");
+ }
+
+ bgObj[prevImage].classList.add("blendOutAnimation");
+
+ if (bgObj[currentImage].classList.contains("blendOutAnimation"))
+ {
+ bgObj[currentImage].classList.remove("blendOutAnimation");
+ }
+
+ bgObj[currentImage].classList.add("blendInAnimation");
+
+ prevImage = currentImage;
+ currentImage++;
+
+ if (currentImage >= imgArray.length)
+ currentImage = 0;
+ }, 5000)
+
+ audioplayer.volume = 0;
+ let autoAdjustVolume = setInterval(() => { if (audioplayer.volume > 0.9) { clearInterval(autoAdjustVolume); return; } audioplayer.volume += 0.01}, 40);
+ audioplayer.src = config.map[mapname].music[getRandomInt(config.map[mapname].music.length)];
+ audioplayer.play();
+
+ document.getElementsByClassName("loadingEntry")[0].classList.add("blendInAnimation");
+}
\ No newline at end of file
diff --git a/fonts/Purista.ttf b/fonts/Purista.ttf
new file mode 100644
index 0000000..f6ba541
Binary files /dev/null and b/fonts/Purista.ttf differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..de34fbf
--- /dev/null
+++ b/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+ GMod BF4 Loading Screen
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Map Name
+
+
+
+
▶ Gamemode Info line 1
+
▶ Gamemode Info line 2
+
▶ Gamemode Info line 3
+
+
+
Server Info line 1
+
Server Info line 2
+
Server Info line 3
+
+
+
\ No newline at end of file
diff --git a/music/gm_construct/1.mp3 b/music/gm_construct/1.mp3
new file mode 100644
index 0000000..2d7ecf5
Binary files /dev/null and b/music/gm_construct/1.mp3 differ
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..fc67ba5
--- /dev/null
+++ b/style.css
@@ -0,0 +1,109 @@
+/* purista-regular - latin */
+@font-face
+{
+ font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
+ font-family: 'Purista';
+ font-style: normal;
+ font-weight: 400;
+ src: url('/fonts/Purista.ttf') format('truetype'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
+}
+
+*
+{
+ margin: 0;
+ font-family: Purista;
+}
+
+.bgImage
+{
+ background-color: black;
+
+ position: fixed;
+
+ width: 100vw;
+ height: 100vh;
+}
+
+.loadingEntry
+{
+ z-index: 1;
+ position: fixed;
+ width: 100vw;
+ height: 100vh;
+ background-color: black;
+}
+
+.blendInAnimation
+{
+ animation-fill-mode: forwards;
+ animation-name: blendIn;
+ animation-duration: 2s;
+}
+
+.blendOutAnimation
+{
+ animation-fill-mode: forwards;
+ animation-name: blendOut;
+ animation-duration: 2s;
+}
+
+.mapName
+{
+ background-color: rgba(0, 0, 0, 0.4);
+ color: white;
+ font-size: 20pt;
+ padding: 10px;
+ position: fixed;
+ top: 50px;
+ left: 100px;
+}
+
+.gamemodeName
+{
+ background-color: rgba(0, 0, 0, 0.4);
+ color: white;
+ font-size: 20pt;
+ padding: 10px;
+ position: fixed;
+ top: 140px;
+ left: 100px;
+}
+
+.gamemodeInfo
+{
+ color: white;
+ font-size: 20pt;
+ padding: 10px;
+ position: fixed;
+ top: 280px;
+ left: 90px;
+}
+
+.gamemodeInfo > p
+{
+ margin-bottom: 10px;
+}
+
+.serverInfo
+{
+ background-color: rgba(0, 0, 0, 0.4);
+ color: white;
+ font-size: 20pt;
+ padding: 10px;
+ max-width: 700px;
+ position: fixed;
+ bottom: 110px;
+ right: 100px;
+}
+
+@keyframes blendIn
+{
+ from {opacity: 1;}
+ to {opacity: 0;}
+}
+
+@keyframes blendOut
+{
+ from {opacity: 0;}
+ to {opacity: 1;}
+}
\ No newline at end of file