From db315616417cf5e549046f2fd4e97fc56244ca75 Mon Sep 17 00:00:00 2001 From: PRO100KatYT <67335438+PRO100KatYT@users.noreply.github.com> Date: Tue, 5 Sep 2023 17:24:52 +0200 Subject: [PATCH] Innovative feature: backend sided in-game events! --- Config/config.ini | 53 +++++++++++- README.md | 1 + structure/timeline.js | 197 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 216 insertions(+), 35 deletions(-) diff --git a/Config/config.ini b/Config/config.ini index 7e19f6f..eaf1335 100644 --- a/Config/config.ini +++ b/Config/config.ini @@ -18,4 +18,55 @@ bAllSTWEventsActivated=false # IP the matchmaker will use upon join. ip=127.0.0.1 # PORT the matchmaker will use upon join. -port=7777 \ No newline at end of file +port=7777 + +[Events] +# All dates must be specified using ISO date format only (UTC). +# *Requires a Gameserver connected to this LawinServer backend. Clients can use other backends. + +## The Rocket Start event. (v4.5 Only)* + +# If this is set to true, the event countdown will appear next to +# the Rocket and the event will start at the date below. +bEnableGeodeEvent=false +geodeEventStartDate=2020-01-01T00:00:00.000Z +# If this is set to true, the Crack will stay in the sky AFTER the event. +# The crack will fully expand after ~13.6 real days after the Rocket event start date. +bEnableCrackInTheSky=false + +## Eight mini-events which took the following objects from the map: (v4.5 Only)* +## 1. Lonely Lodge Sign, 2. Motel Sign, 3. Tomatohead Mascot, 4. NOMS Sign, 5. Durr Burger Mascot +## and brought the following objects to the map: +## 6. Ship Anchor, 7. Horse Carriage, 8. Dinosaur Skeleton. +## To see the exact locations, you can check out this video: https://youtu.be/NXL7rkiJVqM + +# If this is set to true, the blue rift effects will appear at places mentioned above. +bEnableS4OddityPrecursor=false +# If this is set to true, the mini-events will begin to start. (Adjust the options below) +bEnableS4OddityExecution=false +# Start date for the Season 4 mini-events. If you have the Rocket event enabled as +# well, then set this date to at least 4 minutes after your Rocket start date. +S4OddityEventStartDate=2020-01-01T00:00:00.000Z +# Time (in minutes) after which another mini-event (1-8) will occur. +# If set to 0, all mini-events will happen at once. +S4OddityEventsInterval=0 + +## Tomatohead Comeback mini-event. (v5.21 Only)* + +# When set to true, the blue rift effects will start appearing on +# top of the Tomato Town restaurant at the date specified below. +bEnableS5OddityPrecursor=false +S5OddityPrecursorDate=2020-01-01T00:00:00.000Z +# When set to true, Tomatohead will be rifted back to Tomato Town at the date specified below. +bEnableS5OddityExecution=false +S5OddityExecutionDate=2020-01-01T00:00:00.000Z + +## Lightning from the sky Crack and Cube Spawning Event. (v5.30 Only)* + +# When set to true, the crack will start shooting lightning bolts destroying +# cacti and eventually spawn the cube on the date specified below. +bEnableCubeLightning=false +cubeSpawnDate=2020-01-01T00:00:00.000Z + +## Blockbuster Contest winner video at Risky Reels event. (v5.30 Only)* +bEnableBlockbusterRiskyEvent=false diff --git a/README.md b/README.md index 3a14f47..e84dee3 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ - Seasonal Quests from Season 3 up to Season 21 (Can change) - Purchasable battle pass from Season 2 to Season 10 (Can change) - Discovery Tab +- Configurable backend sided in-game events - check out the Events seciton in config.ini for more details ## How to use? 1) Install [NodeJS](https://nodejs.org/en/) diff --git a/structure/timeline.js b/structure/timeline.js index 9cd87e8..a67417c 100644 --- a/structure/timeline.js +++ b/structure/timeline.js @@ -1090,7 +1090,7 @@ express.get("/fortnite/api/calendar/v1/timeline", async (req, res) => { }) } - if (24.3 <= memory.build <= 25) { + if (24.3 <= memory.build && memory.build <= 25) { activeEvents.push( { "eventType": "EventFlag.HordeV3", @@ -1188,25 +1188,174 @@ express.get("/fortnite/api/calendar/v1/timeline", async (req, res) => { "EventFlag.YarrrTwo" ] + var activeEventsSet = new Set(activeEvents.map(e => e.eventType)); for (var i = 0; i < Events.length; i++) { var Event = Events[i]; - var bAlreadyExists = false; - - for (var x = 0; x < activeEvents.length; x++) { - var ActiveEvent = activeEvents[x]; - if (ActiveEvent.eventType == Event) { - bAlreadyExists = true; - } - } - - if (bAlreadyExists == false) { - activeEvents.push( - { + if (!activeEventsSet.has(Event)) { + activeEvents.push({ "eventType": Event, "activeUntil": "9999-01-01T00:00:00.000Z", "activeSince": "2020-01-01T00:00:00.000Z" + }); + } + } + } + + const stateTemplate = { + "activeStorefronts": [], + "eventNamedWeights": {}, + "seasonNumber": memory.season, + "seasonTemplateId": `AthenaSeason:athenaseason${memory.season}`, + "matchXpBonusPoints": 0, + "seasonBegin": "2020-01-01T13:00:00Z", + "seasonEnd": "9999-01-01T14:00:00Z", + "seasonDisplayedEnd": "9999-01-01T07:30:00Z", + "weeklyStoreEnd": "9999-01-01T00:00:00Z", + "stwEventStoreEnd": "9999-01-01T00:00:00.000Z", + "stwWeeklyStoreEnd": "9999-01-01T00:00:00.000Z", + "sectionStoreEnds": { + "Featured": "9999-01-01T00:00:00.000Z" + }, + "dailyStoreEnd": "9999-01-01T00:00:00Z" + }; + + var states = [{ + validFrom: "2020-01-01T00:00:00.000Z", + activeEvents: activeEvents.slice(), + state: stateTemplate + }] + + if (memory.build == 4.5) { + if (config.Events.bEnableGeodeEvent == true) { + states[0].activeEvents.push({ + "eventType": "EventFlag.BR_S4_Geode_Countdown", + "activeUntil": config.Events.geodeEventStartDate + }) + + states.push({ + validFrom: config.Events.geodeEventStartDate, + activeEvents: activeEvents.slice(), + state: stateTemplate + }) + + var EventEndDate = new Date(new Date(config.Events.geodeEventStartDate).getTime() + 3 * 60000).toISOString(); + + states[1].activeEvents.push({ + "eventType": "EventFlag.BR_S4_Geode_Begin", + "activeUntil": EventEndDate + }) + + activeEvents.push({ + "eventType": "EventFlag.BR_S4_Geode_Over", + "activeUntil": "9999-01-01T00:00:00.000Z" + }) + + if (config.Events.bEnableCrackInTheSky == true) { + activeEvents.push({ + "eventType": "EventFlag.BR_S4_Rift_Growth", + "activeUntil": new Date(new Date(EventEndDate).getTime() + 13.6 * 24 * 60 * 60 * 1000).toISOString() // It takes 13.6 days for the crack to fully expand. }) } + + states.push({ + validFrom: EventEndDate, + activeEvents: activeEvents.slice(), + state: stateTemplate + }) + } + + if (config.Events.bEnableS4OddityPrecursor == true) { + for (var i = 1; i <= 8; i++) { + var StartDate = new Date(new Date(config.Events.S4OddityEventStartDate).getTime() + config.Events.S4OddityEventsInterval * (i-1) * 60000).toISOString(); + activeEvents.push({ + "eventType": `EventFlag.BR_S4_Oddity_0${i}_Tell`, + "activeUntil": StartDate + }) + } + states[states.length - 1].activeEvents = activeEvents.slice(); + } + if (config.Events.bEnableS4OddityExecution == true) { + for (var i = 1; i <= 8; i++) { + var StartDate = new Date(new Date(config.Events.S4OddityEventStartDate).getTime() + config.Events.S4OddityEventsInterval * (i-1) * 60000).toISOString(); + + activeEvents.push({ + "eventType": `EventFlag.BR_S4_Oddity_0${i}_Event`, + "activeUntil": "9999-01-01T00:00:00.000Z" + }) + + var index = activeEvents.findIndex(item => item.eventType === `EventFlag.BR_S4_Oddity_0${i}_Tell`); + if (index !== -1) { + activeEvents.splice(index, 1); + } + + states.push({ + validFrom: StartDate, + activeEvents: activeEvents.slice(), + state: stateTemplate + }) + } + } + } + + if (memory.build == 5.21) { + if (config.Events.bEnableS5OddityPrecursor == true) { + states.push({ + validFrom: config.Events.S5OddityPrecursorDate, + activeEvents: activeEvents.slice(), + state: stateTemplate + }) + + states[1].activeEvents.push( + { + "eventType": "EventFlag.BR_S5_Oddity_Tomato_Tell", + "activeUntil": "9999-01-01T00:00:00.000Z" + }) + } + if (config.Events.bEnableS5OddityExecution == true) { + states.push({ + validFrom: config.Events.S5OddityExecutionDate, + activeEvents: activeEvents.slice(), + state: stateTemplate + }) + + states[states.length - 1].activeEvents.push( + { + "eventType": "EventFlag.BR_S5_Oddity_Tomato_Event", + "activeUntil": "9999-01-01T00:00:00.000Z" + }) + } + } + + if (memory.build == 5.30) { + if (config.Events.bEnableBlockbusterRiskyEvent == true) { + activeEvents.push({ + "eventType": "EventFlag.BR_S5_RiskyReels_Event", + "activeUntil": "9999-01-01T00:00:00.000Z" + }) + states[0].activeEvents = activeEvents.slice(); + } + + if (config.Events.bEnableCubeLightning == true) { + states[0].activeEvents.push( + { + "eventType": "EventFlag.BR_S5_Rift_Corrupt", + "activeUntil": config.Events.cubeSpawnDate + }, + { + "eventType": "EventFlag.BR_S5_Cube_Lightning", + "activeUntil": config.Events.cubeSpawnDate + }) + + activeEvents.push({ + "eventType": "EventFlag.BR_S5_Cube_TurnOn", + "activeUntil": "9999-01-01T00:00:00.000Z" + }) + + states.push({ + validFrom: config.Events.cubeSpawnDate, + activeEvents: activeEvents.slice(), + state: stateTemplate + }) } } @@ -1217,27 +1366,7 @@ express.get("/fortnite/api/calendar/v1/timeline", async (req, res) => { "cacheExpire": "9999-01-01T22:28:47.830Z" }, "client-events": { - "states": [{ - "validFrom": "2020-01-01T20:28:47.830Z", - "activeEvents": activeEvents, - "state": { - "activeStorefronts": [], - "eventNamedWeights": {}, - "seasonNumber": memory.season, - "seasonTemplateId": `AthenaSeason:athenaseason${memory.season}`, - "matchXpBonusPoints": 0, - "seasonBegin": "2020-01-01T13:00:00Z", - "seasonEnd": "9999-01-01T14:00:00Z", - "seasonDisplayedEnd": "9999-01-01T07:30:00Z", - "weeklyStoreEnd": "9999-01-01T00:00:00Z", - "stwEventStoreEnd": "9999-01-01T00:00:00.000Z", - "stwWeeklyStoreEnd": "9999-01-01T00:00:00.000Z", - "sectionStoreEnds": { - "Featured": "9999-01-01T00:00:00.000Z" - }, - "dailyStoreEnd": "9999-01-01T00:00:00Z" - } - }], + "states": states, "cacheExpire": "9999-01-01T22:28:47.830Z" } },