snow/fortnite/arena.go
Eccentric 250e85732d feat: update to latest;
new shop system
more config options
arena & hype
per season stats
battle pass
better variant system
complete vbuck & starter pack store
fix bugs related to deleting account
update launcher endpoints
fixed gift loot not deleting
2024-03-10 18:16:42 +00:00

416 lines
13 KiB
Go

package fortnite
import (
"time"
"github.com/ectrc/snow/aid"
)
type ArenaScoringRule struct {
StatName string
MatchRule string
RewardTiers []struct{
Value int
Points int
Multiply bool
}
}
func NewScoringRule(stat, rule string) *ArenaScoringRule {
return &ArenaScoringRule{
StatName: stat,
MatchRule: rule,
RewardTiers: new(ArenaScoringRule).RewardTiers,
}
}
func (sr *ArenaScoringRule) AddTier(value, points int, multiply bool) *ArenaScoringRule {
sr.RewardTiers = append(sr.RewardTiers, struct{
Value int
Points int
Multiply bool
}{
Value: value,
Points: points,
Multiply: multiply,
})
return sr
}
func (sr *ArenaScoringRule) GenerateFortniteScoringRule() aid.JSON {
tiers := make([]aid.JSON, 0)
for _, tier := range sr.RewardTiers {
tiers = append(tiers, aid.JSON{
"keyValue": tier.Value,
"pointsEarned": tier.Points,
"multiplicative": tier.Multiply,
})
}
return aid.JSON{
"trackedStat": sr.StatName,
"matchRule": sr.MatchRule,
"rewardTiers": tiers,
}
}
type ArenaEventTemplate struct {
ID string
MatchLimit int
PlaylistID string
ScoringRules []*ArenaScoringRule
}
func NewEventTemplate(id string, limit int) *ArenaEventTemplate {
return &ArenaEventTemplate{
ID: id,
MatchLimit: limit,
ScoringRules: make([]*ArenaScoringRule, 0),
}
}
func (et *ArenaEventTemplate) AddScoringRule(rule ...*ArenaScoringRule) {
et.ScoringRules = append(et.ScoringRules, rule...)
}
func (et *ArenaEventTemplate) GenerateFortniteEventTemplate() aid.JSON {
rules := make([]aid.JSON, 0)
for _, rule := range et.ScoringRules {
rules = append(rules, rule.GenerateFortniteScoringRule())
}
return aid.JSON{
"gameId": "Fortnite",
"eventTemplateId": et.ID,
"playlistId": et.PlaylistID,
"persistentScoreId": "Hype",
"matchCap": et.MatchLimit,
"scoringRules": rules,
}
}
type ArenaEventWindow struct {
ID string
ParentEvent *Event
Template *ArenaEventTemplate
Round int
ToBeDetermined bool
CanLiveSpectate bool
Meta struct {
DivisionRank int
ThresholdToAdvanceDivision int
}
}
func NewEventWindow(id string, template *ArenaEventTemplate) *ArenaEventWindow {
return &ArenaEventWindow{
ID: id,
Meta: new(ArenaEventWindow).Meta,
Template: template,
}
}
func (ew *ArenaEventWindow) GenerateFortniteEventWindow() aid.JSON {
meta := aid.JSON{
"divisionRank": ew.Meta.DivisionRank,
"ThresholdToAdvanceDivision": ew.Meta.ThresholdToAdvanceDivision,
"RoundType": "Arena",
}
allTokens := []string{
"ARENA_S8_Division1",
"ARENA_S8_Division2",
"ARENA_S8_Division3",
"ARENA_S8_Division4",
"ARENA_S8_Division5",
"ARENA_S8_Division6",
"ARENA_S8_Division7",
}
requireAll := []string{}
requireNone := []string{}
for index, token := range allTokens {
if index == ew.Meta.DivisionRank {
requireAll = append(requireAll, token)
continue
}
requireNone = append(requireNone, token)
}
return aid.JSON{
"eventWindowId": ew.ID,
"eventTemplateId": ew.Template.ID,
"countdownBeginTime": "2023-06-15T15:00:00.000Z",
"beginTime": time.Now().Add(time.Hour * -24).Format(time.RFC3339),
"endTime": "9999-12-31T23:59:59.000Z",
"payoutDelay": 30,
"round": ew.Round,
"isTBD": ew.ToBeDetermined,
"canLiveSpectate": ew.CanLiveSpectate,
"visibility": "public",
"scoreLocations": []aid.JSON{},
"blackoutPeriods": []string{},
"requireAnyTokens": []string{},
"requireAllTokens": requireAll,
"requireAllTokensCaller": []string{},
"requireNoneTokensCaller": requireNone,
"requireAnyTokensCaller": []string{},
"additionalRequirements": []string{},
"teammateEligibility": "any",
"metadata": meta,
}
}
type Event struct {
ID string
DisplayID string
Windows []*ArenaEventWindow
}
func NewEvent(id string, displayId string) *Event {
return &Event{
ID: id,
DisplayID: displayId,
Windows: make([]*ArenaEventWindow, 0),
}
}
func (e *Event) AddWindow(window *ArenaEventWindow) {
window.ParentEvent = e
e.Windows = append(e.Windows, window)
}
func (e *Event) GenerateFortniteEvent() aid.JSON {
eventWindows := make([]aid.JSON, 0)
for _, window := range e.Windows {
eventWindows = append(eventWindows, window.GenerateFortniteEventWindow())
}
return aid.JSON{
"gameId": "Fortnite",
"eventId": e.ID,
"eventGroup": "",
"regions": []string{ "NAE", "ME", "NAW", "OCE", "ASIA", "EU", "BR", },
"regionMappings": aid.JSON{},
"platforms": []string{ "PS4", "XboxOne", "Switch", "Android", "IOS", "Windows", },
"platformMappings": aid.JSON{},
"displayDataId": e.DisplayID,
"eventWindows": eventWindows,
"appId": nil,
"link": nil,
"metadata": aid.JSON{
"minimumAccountLevel": 1,
"TrackedStats": []string{
"PLACEMENT_STAT_INDEX",
"TEAM_ELIMS_STAT_INDEX",
"MATCH_PLAYED_STAT",
},
},
"environment": nil,
"announcementTime": time.Now().Format(time.RFC3339),
"beginTime": time.Now().Add(time.Hour * -24).Format(time.RFC3339),
"endTime": "9999-12-31T23:59:59.000Z",
}
}
var (
ArenaEvents = make([]*Event, 0)
)
func PreloadEvents() {
if aid.Config.Fortnite.Season < 8 {
return
}
ArenaEvents = []*Event{
createDuoEvent(),
createSoloEvent(),
}
}
func createSoloEvent() *Event {
ArenaSolo := NewEvent("epicgames_Arena_S8_Solo", "SnowArenaSolo")
defaultPlacement := NewScoringRule("PLACEMENT_STAT_INDEX", "lte")
defaultPlacement.AddTier(1, 3, false)
defaultPlacement.AddTier(5, 2, false)
defaultPlacement.AddTier(15, 2, false)
defaultPlacement.AddTier(25, 3, false)
defaultEliminations := NewScoringRule("TEAM_ELIMS_STAT_INDEX", "gte")
defaultEliminations.AddTier(1, 1, true)
soloOpen1T := NewEventTemplate("eventTemplate_Arena_S8_Division1_Solo", 100)
soloOpen1T.PlaylistID = "Playlist_ShowdownAlt_Solo"
soloOpen1T.AddScoringRule(defaultPlacement, defaultEliminations)
soloOpen1W := NewEventWindow("Arena_S8_Division1_Solo", soloOpen1T)
soloOpen1W.ToBeDetermined = false
soloOpen1W.CanLiveSpectate = false
soloOpen1W.Round = 0
soloOpen1W.Meta.DivisionRank = 0
soloOpen1W.Meta.ThresholdToAdvanceDivision = 25
ArenaSolo.AddWindow(soloOpen1W)
soloOpen2T := NewEventTemplate("eventTemplate_Arena_S8_Division2_Solo", 100)
soloOpen2T.PlaylistID = "Playlist_ShowdownAlt_Solo"
soloOpen2T.AddScoringRule(defaultPlacement, defaultEliminations)
soloOpen2W := NewEventWindow("Arena_S8_Division2_Solo", soloOpen2T)
soloOpen2W.ToBeDetermined = false
soloOpen2W.CanLiveSpectate = false
soloOpen2W.Round = 1
soloOpen2W.Meta.DivisionRank = 1
soloOpen2W.Meta.ThresholdToAdvanceDivision = 75
ArenaSolo.AddWindow(soloOpen2W)
soloOpen3T := NewEventTemplate("eventTemplate_Arena_S8_Division3_Solo", 100)
soloOpen3T.PlaylistID = "Playlist_ShowdownAlt_Solo"
soloOpen3T.AddScoringRule(defaultPlacement, defaultEliminations)
soloOpen3W := NewEventWindow("Arena_S8_Division3_Solo", soloOpen3T)
soloOpen3W.Round = 2
soloOpen3W.ToBeDetermined = false
soloOpen3W.CanLiveSpectate = false
soloOpen3W.Meta.DivisionRank = 2
soloOpen3W.Meta.ThresholdToAdvanceDivision = 125
ArenaSolo.AddWindow(soloOpen3W)
soloContender4T := NewEventTemplate("eventTemplate_Arena_S8_Division4_Solo", 100)
soloContender4T.PlaylistID = "Playlist_ShowdownAlt_Solo"
soloContender4T.AddScoringRule(defaultPlacement, NewScoringRule("MATCH_PLAYED_STAT", "gtw").AddTier(1, -2, false), defaultEliminations)
soloConteder4W := NewEventWindow("Arena_S8_Division4_Solo", soloContender4T)
soloConteder4W.Round = 3
soloConteder4W.ToBeDetermined = false
soloConteder4W.CanLiveSpectate = false
soloConteder4W.Meta.DivisionRank = 3
soloConteder4W.Meta.ThresholdToAdvanceDivision = 175
ArenaSolo.AddWindow(soloConteder4W)
soloContender5T := NewEventTemplate("eventTemplate_Arena_S8_Division5_Solo", 100)
soloContender5T.PlaylistID = "Playlist_ShowdownAlt_Solo"
soloContender5T.AddScoringRule(defaultPlacement, NewScoringRule("MATCH_PLAYED_STAT", "gtw").AddTier(1, -4, false), defaultEliminations)
soloConteder5W := NewEventWindow("Arena_S8_Division5_Solo", soloContender5T)
soloConteder5W.Round = 4
soloConteder5W.ToBeDetermined = false
soloConteder5W.CanLiveSpectate = false
soloConteder5W.Meta.DivisionRank = 4
soloConteder5W.Meta.ThresholdToAdvanceDivision = 225
ArenaSolo.AddWindow(soloConteder5W)
soloContender6T := NewEventTemplate("eventTemplate_Arena_S8_Division6_Solo", 100)
soloContender6T.PlaylistID = "Playlist_ShowdownAlt_Solo"
soloContender6T.AddScoringRule(defaultPlacement, NewScoringRule("MATCH_PLAYED_STAT", "gtw").AddTier(1, -6, false), defaultEliminations)
soloConteder6W := NewEventWindow("Arena_S8_Division6_Solo", soloContender6T)
soloConteder6W.Round = 5
soloConteder6W.ToBeDetermined = false
soloConteder6W.CanLiveSpectate = false
soloConteder6W.Meta.DivisionRank = 5
soloConteder6W.Meta.ThresholdToAdvanceDivision = 300
ArenaSolo.AddWindow(soloConteder6W)
soloChampions7T := NewEventTemplate("eventTemplate_Arena_S8_Division7_Solo", 100)
soloChampions7T.PlaylistID = "Playlist_ShowdownAlt_Solo"
soloChampions7T.AddScoringRule(defaultPlacement, NewScoringRule("MATCH_PLAYED_STAT", "gtw").AddTier(1, -8, false), defaultEliminations)
soloChampions7W := NewEventWindow("Arena_S8_Division7_Solo", soloChampions7T)
soloChampions7W.Round = 6
soloChampions7W.ToBeDetermined = true
soloChampions7W.CanLiveSpectate = false
soloChampions7W.Meta.DivisionRank = 6
soloChampions7W.Meta.ThresholdToAdvanceDivision = 9999999999
ArenaSolo.AddWindow(soloChampions7W)
return ArenaSolo
}
func createDuoEvent() *Event {
ArenaDuo := NewEvent("epicgames_Arena_S8_Duos", "SnowArenaDuos")
defaultPlacement := NewScoringRule("PLACEMENT_STAT_INDEX", "lte")
defaultPlacement.AddTier(1, 3, false)
defaultPlacement.AddTier(3, 2, false)
defaultPlacement.AddTier(7, 2, false)
defaultPlacement.AddTier(12, 3, false)
defaultEliminations := NewScoringRule("TEAM_ELIMS_STAT_INDEX", "gte")
defaultEliminations.AddTier(1, 1, true)
duoOpen1T := NewEventTemplate("eventTemplate_Arena_S8_Division1_Duos", 100)
duoOpen1T.PlaylistID = "Playlist_ShowdownAlt_Duos"
duoOpen1T.AddScoringRule(defaultPlacement, defaultEliminations)
duoOpen1W := NewEventWindow("Arena_S8_Division1_Duos", duoOpen1T)
duoOpen1W.ToBeDetermined = false
duoOpen1W.CanLiveSpectate = false
duoOpen1W.Round = 0
duoOpen1W.Meta.DivisionRank = 0
duoOpen1W.Meta.ThresholdToAdvanceDivision = 25
ArenaDuo.AddWindow(duoOpen1W)
duoOpen2T := NewEventTemplate("eventTemplate_Arena_S8_Division2_Duos", 100)
duoOpen2T.PlaylistID = "Playlist_ShowdownAlt_Duos"
duoOpen2T.AddScoringRule(defaultPlacement, defaultEliminations)
duoOpen2W := NewEventWindow("Arena_S8_Division2_Duos", duoOpen2T)
duoOpen2W.ToBeDetermined = false
duoOpen2W.CanLiveSpectate = false
duoOpen2W.Round = 1
duoOpen2W.Meta.DivisionRank = 1
duoOpen2W.Meta.ThresholdToAdvanceDivision = 75
ArenaDuo.AddWindow(duoOpen2W)
duoOpen3T := NewEventTemplate("eventTemplate_Arena_S8_Division3_Duos", 100)
duoOpen3T.PlaylistID = "Playlist_ShowdownAlt_Duos"
duoOpen3T.AddScoringRule(defaultPlacement, defaultEliminations)
duoOpen3W := NewEventWindow("Arena_S8_Division3_Duos", duoOpen3T)
duoOpen3W.Round = 2
duoOpen3W.ToBeDetermined = false
duoOpen3W.CanLiveSpectate = false
duoOpen3W.Meta.DivisionRank = 2
duoOpen3W.Meta.ThresholdToAdvanceDivision = 125
ArenaDuo.AddWindow(duoOpen3W)
duoContender4T := NewEventTemplate("eventTemplate_Arena_S8_Division4_Duos", 100)
duoContender4T.PlaylistID = "Playlist_ShowdownAlt_Duos"
duoContender4T.AddScoringRule(defaultPlacement, NewScoringRule("MATCH_PLAYED_STAT", "gtw").AddTier(1, -2, false), defaultEliminations)
duoConteder4W := NewEventWindow("Arena_S8_Division4_Duos", duoContender4T)
duoConteder4W.Round = 3
duoConteder4W.ToBeDetermined = false
duoConteder4W.CanLiveSpectate = false
duoConteder4W.Meta.DivisionRank = 3
duoConteder4W.Meta.ThresholdToAdvanceDivision = 175
ArenaDuo.AddWindow(duoConteder4W)
duoContender5T := NewEventTemplate("eventTemplate_Arena_S8_Division5_Duos", 100)
duoContender5T.PlaylistID = "Playlist_ShowdownAlt_Duos"
duoContender5T.AddScoringRule(defaultPlacement, NewScoringRule("MATCH_PLAYED_STAT", "gtw").AddTier(1, -4, false), defaultEliminations)
duoConteder5W := NewEventWindow("Arena_S8_Division5_Duos", duoContender5T)
duoConteder5W.Round = 4
duoConteder5W.ToBeDetermined = false
duoConteder5W.CanLiveSpectate = false
duoConteder5W.Meta.DivisionRank = 4
duoConteder5W.Meta.ThresholdToAdvanceDivision = 225
ArenaDuo.AddWindow(duoConteder5W)
duoContender6T := NewEventTemplate("eventTemplate_Arena_S8_Division6_Duos", 100)
duoContender6T.PlaylistID = "Playlist_ShowdownAlt_Duos"
duoContender6T.AddScoringRule(defaultPlacement, NewScoringRule("MATCH_PLAYED_STAT", "gtw").AddTier(1, -6, false), defaultEliminations)
duoConteder6W := NewEventWindow("Arena_S8_Division6_Duos", duoContender6T)
duoConteder6W.Round = 5
duoConteder6W.ToBeDetermined = false
duoConteder6W.CanLiveSpectate = false
duoConteder6W.Meta.DivisionRank = 5
duoConteder6W.Meta.ThresholdToAdvanceDivision = 300
ArenaDuo.AddWindow(duoConteder6W)
duoChampions7T := NewEventTemplate("eventTemplate_Arena_S8_Division7_Duos", 100)
duoChampions7T.PlaylistID = "Playlist_ShowdownAlt_Duos"
duoChampions7T.AddScoringRule(defaultPlacement, NewScoringRule("MATCH_PLAYED_STAT", "gtw").AddTier(1, -8, false), defaultEliminations)
duoChampions7W := NewEventWindow("Arena_S8_Division7_Duos", duoChampions7T)
duoChampions7W.Round = 6
duoChampions7W.ToBeDetermined = true
duoChampions7W.CanLiveSpectate = false
duoChampions7W.Meta.DivisionRank = 6
duoChampions7W.Meta.ThresholdToAdvanceDivision = 9999999999
ArenaDuo.AddWindow(duoChampions7W)
return ArenaDuo
}