Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #162 from Pluviolithic/dev
Browse files Browse the repository at this point in the history
Add monthly leaderboards
  • Loading branch information
Pluviolithic authored Mar 23, 2024
2 parents 37a8bdc + 6dc999e commit ca73f3b
Show file tree
Hide file tree
Showing 21 changed files with 294 additions and 13 deletions.
2 changes: 1 addition & 1 deletion aftman.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# To add a new tool, add an entry to this table.
[tools]
rojo = "rojo-rbx/rojo@7.3.0"
rojo = "rojo-rbx/rojo@7.4.0"
stylua = "JohnnyMorganz/[email protected]"
selene = "Kampfkarren/[email protected]"
wally = "UpliftGames/[email protected]"
Expand Down
15 changes: 12 additions & 3 deletions src/client/UI/BillboardShops/EggShop.lua
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,10 @@ local function handleShop(shop): ()
luck += 0.1 * selectors.getRebirthUpgradeLevel(store:getState(), player.Name, "Lucky")
end

if selectors.achievedMilestone(store:getState(), player.Name, "TopRebirths") then
luck += 3
end

if luck == 0 then
return
end
Expand Down Expand Up @@ -519,7 +523,7 @@ CollectionService:GetInstanceAddedSignal("EggShop"):Connect(handleShop)

local function updateFoundsDisplay(foundPets): ()
for petName in foundPets do
if petName:match "Evolved" or petName:match "Shiny" then
if petName:match "Evolved" or petName:match "Shiny" or not petAreas[petName] then
continue
end

Expand Down Expand Up @@ -564,8 +568,13 @@ playerStatePromise:andThen(function()
oldState,
player.Name
)["LuckBoost"]
or selectors.getRebirthUpgradeLevel(newState, player.Name, "Lucky")
~= selectors.getRebirthUpgradeLevel(oldState, player.Name, "Lucky")
or selectors.getRebirthUpgradeLevel(newState, player.Name, "Lucky") ~= selectors.getRebirthUpgradeLevel(
oldState,
player.Name,
"Lucky"
)
or selectors.achievedMilestone(newState, player.Name, "TopRebirths")
~= selectors.achievedMilestone(oldState, player.Name, "TopRebirths")
then
updateRarityListeners(selectors.getStat(newState, player.Name, "Luck"))
end
Expand Down
8 changes: 8 additions & 0 deletions src/client/UI/BuffsUI.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ local function updateBuffTray(state)
local friendCount = Count(selectors.getActiveFriendsWhoJoined(state, player.Name))
buffDisplay.Visible = friendCount > 0
buffDisplay.Amount.Text = `{15 * friendCount}%`
elseif buffDisplay.Name == "LeaderboardLuck" then
buffTray.Frame.LeaderboardLuck.Visible =
selectors.achievedMilestone(store:getState(), player.Name, "TopRebirths")
else
buffDisplay.Visible = isScared(state)
buffDisplay.Timer.Text = clockUtils.getFormattedRemainingTime(
Expand Down Expand Up @@ -116,6 +119,11 @@ buffTray.Frame.FriendBuff.Activated:Connect(function()
end
end)

buffTray.Frame.LeaderboardLuck.Activated:Connect(function()
playSoundEffect "UIButton"
RobuxShop:OpenSubShop "Boosts"
end)

interfaces[InviteUI] = true

playerStatePromise:andThen(function()
Expand Down
8 changes: 7 additions & 1 deletion src/client/UI/Shops/WeaponShop.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ local playerStatePromise = require(StarterPlayer.StarterPlayerScripts.Client.Sta
local playSoundEffect = require(StarterPlayer.StarterPlayerScripts.Client.GameAtmosphere.SoundEffects)

local weapons = ReplicatedStorage.Weapons
local leaderboardWeaponName = ReplicatedStorage.Config.Misc.LeaderboardWeapon.Value
local gamepassIDs = ReplicatedStorage.Config.GamepassData.IDs
local gamepassPrices = ReplicatedStorage.Config.GamepassData.Prices
local WeaponShop = CentralUI.new(player.PlayerGui:WaitForChild "WeaponShop")
Expand Down Expand Up @@ -149,7 +150,11 @@ function WeaponShop:_initialize(): ()
end
end)
else
if button:FindFirstChild "GamepassText" then
if button.Name == leaderboardWeaponName then
focusedDisplay.GreenButton.Visible = true
focusedDisplay.LeaderboardWeapon.Visible = true
focusedDisplay.GreenButton.Text.Text = "Monthly Leaderboard"
elseif button:FindFirstChild "GamepassText" then
focusedDisplay.RobuxPrice.Text = if button.Name == "Scythe"
then gamepassPrices.Scythe.Value
else gamepassPrices.VIP.Value
Expand Down Expand Up @@ -204,6 +209,7 @@ function WeaponShop:ClearFocusedDisplay()
focusedDisplay.DamageIcon.Visible = false

focusedDisplay.GreenButton.Visible = false
focusedDisplay.LeaderboardWeapon.Visible = false

if self._eventConnections["PurchaseButton"] then
self._eventConnections["PurchaseButton"]:Disconnect()
Expand Down
4 changes: 4 additions & 0 deletions src/server/Combat/Enemies/ApplyPlayerAnimations.lua
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ return function(player, enemy, info, janitor)

local playbackSpeed = random:NextNumber(0.9, 1.1)

if not player.Character:FindFirstChild(weapon) then
return
end

local sounds = player.Character[weapon]:FindFirstChild "Sounds"
while not sounds do
task.wait()
Expand Down
10 changes: 7 additions & 3 deletions src/server/Combat/Perks/Pets.lua
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ Remotes.Server:Get("EvolvePet"):Connect(function(player: Player, petName: string
return 0
end)

Remotes.Server:Get("EquipBestPets"):Connect(function(player: Player)
local function equipBestPets(player: Player)
local equippedPets = selectors.getEquippedPets(store:getState(), player.Name)
local lockedPets = selectors.getLockedPets(store:getState(), player.Name)
local ownedPets = selectors.getOwnedPets(store:getState(), player.Name)
Expand Down Expand Up @@ -198,7 +198,9 @@ Remotes.Server:Get("EquipBestPets"):Connect(function(player: Player)
store:dispatch(actions.lockPlayerPets(player.Name, bestPetsDict, true))

return 0
end)
end

Remotes.Server:Get("EquipBestPets"):Connect(equipBestPets)

Remotes.Server:Get("UnequipAllPets"):Connect(function(player: Player)
local equippedPets = selectors.getEquippedPets(store:getState(), player.Name)
Expand Down Expand Up @@ -249,4 +251,6 @@ Players.PlayerRemoving:Connect(function(player)
end
end)

return 0
return {
equipBestPets = equipBestPets,
}
13 changes: 13 additions & 0 deletions src/server/Commands/GameState/UpdateMonthlyTimestamp.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
return {
Name = "updatemonthlytimestamp",
Aliases = { "umt" },
Description = "Updates the monthly timestamp prefix to a value of your choice.",
Group = "DefaultAdmin",
Args = {
{
Type = "string",
Name = "Timestamp",
Description = "The string you want to set as the monthly timestamp prefix.",
},
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
local ReplicatedStorage = game:GetService "ReplicatedStorage"

local clockUtils = require(ReplicatedStorage.Common.Utils.ClockUtils)

return function(_, timestamp: string)
return clockUtils.setMonthlyTimestampOverride(timestamp)
end
167 changes: 167 additions & 0 deletions src/server/PlayerManager/GlobalLeaderboards.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ local CollectionService = game:GetService "CollectionService"
local ServerScriptService = game:GetService "ServerScriptService"

local store = require(ServerScriptService.Server.State.Store)
local actions = require(ServerScriptService.Server.State.Actions)
local pets = require(ServerScriptService.Server.Combat.Perks.Pets)
local formatter = require(ReplicatedStorage.Common.Utils.Formatter)
local selectors = require(ReplicatedStorage.Common.State.selectors)
local clockUtils = require(ReplicatedStorage.Common.Utils.ClockUtils)
local permissionList = require(ReplicatedStorage.Common.PermissionList)
local profiles = require(ServerScriptService.Server.PlayerManager.Profiles)

Expand All @@ -17,10 +20,31 @@ local globalLeaderboardStores = {
Rebirths = DataStoreService:GetOrderedDataStore "Rebirths",
}

local monthlyTopTen = {
Kills = {},
Strength = {},
Rebirths = {},
KillsLoaded = false,
StrengthLoaded = false,
RebirthsLoaded = false,
}

local _, podiums = next(CollectionService:GetTagged "Podiums")
local leaderboardEntry = ServerStorage.Templates.LeaderboardEntry
local playerNameTemplate = ReplicatedStorage.PlayerName:Clone()
local leaderboardPetName = ReplicatedStorage.Config.Misc.LeaderboardPet.Value
local leaderboardWeaponName = ReplicatedStorage.Config.Misc.LeaderboardWeapon.Value

local function awardPetsToPlayer(player: Player, petsDict: { [string]: number }): ()
store:dispatch(actions.givePlayerPets(player.Name, petsDict))
store:dispatch(actions.lockPlayerPets(player.Name, petsDict))

pets.equipBestPets(player)
end

local function updateGlobalLeaderboardDisplays(): ()
for statName, globalLeaderboardStore in globalLeaderboardStores do
local globalPodium = podiums:FindFirstChild("AllTime" .. statName .. "Podium")
local pages = globalLeaderboardStore:GetSortedAsync(false, 99)
local leaderboardDisplays = {}

Expand All @@ -44,7 +68,66 @@ local function updateGlobalLeaderboardDisplays(): ()
entry.Rank.Text = "#" .. rank
entry.Parent = leaderboardDisplay
end

if rank == 1 then
globalPodium.Rig.Humanoid:ApplyDescription(Players:GetHumanoidDescriptionFromUserId(score.key))
playerNameTemplate:Clone().Parent = globalPodium.Rig.Head
globalPodium.Rig.Head.PlayerName.Frame.PlayerName.Text = if success then playerName else score.key
end
end

task.wait(10)
end

local monthlyTimestamp = clockUtils.getMonthlyTimestamp()

local monthlyGlobalLeaderboardStores = {
Kills = DataStoreService:GetOrderedDataStore(monthlyTimestamp .. "MonthlyGlobalKills"),
Strength = DataStoreService:GetOrderedDataStore(monthlyTimestamp .. "MonthlyGlobalStrength"),
Rebirths = DataStoreService:GetOrderedDataStore(monthlyTimestamp .. "MonthlyRebirths"),
}

for statName, monthlyGlobalLeaderboardStore in monthlyGlobalLeaderboardStores do
local monthlyPodium = podiums:FindFirstChild("Monthly" .. statName .. "Podium")
local pages = monthlyGlobalLeaderboardStore:GetSortedAsync(false, 99)
local leaderboardDisplays = {}

for _, leaderboardDisplay in CollectionService:GetTagged "MonthlyGlobalLeaderboard" do
if leaderboardDisplay.Name == statName then
table.insert(leaderboardDisplays, leaderboardDisplay)
end
end

local newTopTen = {}
for rank, score in pages:GetCurrentPage() do
local success, playerName = pcall(Players.GetNameFromUserIdAsync, Players, tonumber(score.key))

for _, leaderboardDisplay in leaderboardDisplays do
local entry = leaderboardDisplay:FindFirstChild(tostring(rank))
if not entry then
entry = leaderboardEntry:Clone()
entry.Name = tostring(rank)
end
entry.PlayerName.Text = if success then playerName else score.key
entry.Amount.Text = formatter.formatNumberWithSuffix(score.value)
entry.Rank.Text = "#" .. rank
entry.Parent = leaderboardDisplay

if rank < 3 then
newTopTen[rank] = entry.PlayerName.Text
end

if rank == 1 then
monthlyPodium.Rig.Humanoid:ApplyDescription(Players:GetHumanoidDescriptionFromUserId(score.key))
playerNameTemplate:Clone().Parent = monthlyPodium.Rig.Head
monthlyPodium.Rig.Head.PlayerName.Frame.PlayerName.Text = if success then playerName else score.key
end
end
end
monthlyTopTen[statName .. "Loaded"] = true
monthlyTopTen[statName] = newTopTen

task.wait(10)
end
end

Expand All @@ -64,6 +147,26 @@ local function updateGlobalLeaderboardStores(): ()
math.floor(selectors.getStat(store:getState(), player.Name, statName))
)
end

local monthlyTimestamp = clockUtils.getMonthlyTimestamp()

local monthlyGlobalLeaderboardStores = {
Kills = DataStoreService:GetOrderedDataStore(monthlyTimestamp .. "MonthlyGlobalKills"),
Strength = DataStoreService:GetOrderedDataStore(monthlyTimestamp .. "MonthlyGlobalStrength"),
Rebirths = DataStoreService:GetOrderedDataStore(monthlyTimestamp .. "MonthlyRebirths"),
}

for statName, monthlyGlobalLeaderboard in monthlyGlobalLeaderboardStores do
if not selectors.isPlayerLoaded(store:getState(), player.Name) then
continue
end
pcall(
monthlyGlobalLeaderboard.SetAsync,
monthlyGlobalLeaderboard,
tostring(player.UserId),
math.floor(selectors.getStat(store:getState(), player.Name, statName .. monthlyTimestamp) or 0)
)
end
end
end

Expand All @@ -75,4 +178,68 @@ task.delay(10, function()
end
end)

local function checkPlayer(player: Player)
if not selectors.isPlayerLoaded(store:getState(), player.Name) then
return
end

if
table.find(monthlyTopTen.Kills, player.Name)
and not selectors.getOwnedPets(store:getState(), player.Name)[leaderboardPetName]
then
awardPetsToPlayer(player, { [leaderboardPetName] = 1 })
elseif
monthlyTopTen.KillsLoaded
and not table.find(monthlyTopTen.Kills, player.Name)
and selectors.getOwnedPets(store:getState(), player.Name)[leaderboardPetName]
then
store:dispatch(actions.deletePlayerPets(player.Name, { [leaderboardPetName] = 1 }))
if selectors.getEquippedPets(store:getState(), player.Name)[leaderboardPetName] then
store:dispatch(actions.unequipPlayerPets(player.Name, { [leaderboardPetName] = 1 }))
end
if selectors.getLockedPets(store:getState(), player.Name)[leaderboardPetName] then
store:dispatch(actions.unlockPlayerPets(player.Name, { [leaderboardPetName] = 1 }, true))
end
pets.equipBestPets(player)
end

if
table.find(monthlyTopTen.Strength, player.Name)
and not selectors.getOwnedWeapons(store:getState(), player.Name)[leaderboardWeaponName]
then
store:dispatch(actions.givePlayerWeapon(player.Name, leaderboardWeaponName))
store:dispatch(actions.equipWeapon(player.Name, leaderboardWeaponName))
elseif
monthlyTopTen.StrengthLoaded
and not table.find(monthlyTopTen.Strength, player.Name)
and selectors.getOwnedWeapons(store:getState(), player.Name)[leaderboardWeaponName]
then
store:dispatch(actions.takePlayerWeapon(player.Name, leaderboardWeaponName))
end

if
table.find(monthlyTopTen.Rebirths, player.Name)
and not selectors.achievedMilestone(store:getState(), player.Name, "TopRebirths")
then
store:dispatch(actions.achievedMilestone(player.Name, "TopRebirths"))
elseif
monthlyTopTen.RebirthsLoaded
and not table.find(monthlyTopTen.Rebirths, player.Name)
and selectors.achievedMilestone(store:getState(), player.Name, "TopRebirths")
then
store:dispatch(actions.removeMilestone(player.Name, "TopRebirths"))
end
end

task.spawn(function()
while true do
task.wait(15)
for _, player in Players:GetPlayers() do
checkPlayer(player)
end
end
end)

Players.PlayerAdded:Connect(checkPlayer)

return 0
1 change: 1 addition & 0 deletions src/server/PlayerManager/ProfileTemplate.lua
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ return {

MilestonesData = {
["100MStrength"] = false,
["TopRebirths"] = false,
},

GiftData = {
Expand Down
4 changes: 4 additions & 0 deletions src/server/Random/EggHatcher/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ local function getWeightedRandom(player: Player, weights: { [string]: { [string]
local luck = selectors.getStat(store:getState(), player.Name, "Luck")
local newWeights = {}

if selectors.achievedMilestone(store:getState(), player.Name, "TopRebirths") then
luck += 3
end

if selectors.getActiveBoosts(store:getState(), player.Name)["LuckBoost"] then
luck += 5
end
Expand Down
7 changes: 7 additions & 0 deletions src/server/State/Actions/MilestoneActions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,11 @@ return {
shouldSave = true,
}
end),
removeMilestone = makeActionCreator("removeMilestone", function(playerName: string, milestone: string)
return {
playerName = playerName,
milestone = milestone,
shouldSave = true,
}
end),
}
Loading

0 comments on commit ca73f3b

Please sign in to comment.