TimberWoods / src /ServerScriptService /MarketManager.server.lua
algorembrant's picture
Upload 88 files
0712d5f verified
-- src/ServerScriptService/MarketManager.server.lua
local CollectionService = game:GetService("CollectionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local EconomyConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("EconomyConfig"))
local NotificationEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("NotificationEvent")
local MarketUpdateEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("MarketUpdateEvent")
local SoundEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("SoundEvent")
-- Global current market multipliers
local currentMarketRates = {}
-- Initialize base rates for all wood types
for woodType, _ in pairs(EconomyConfig.WoodBaseValues) do
currentMarketRates[woodType] = 1.0
end
local function updateMarketRates()
for woodType, _ in pairs(currentMarketRates) do
local randShift = (math.random(-10, 10) / 100)
local newRate = currentMarketRates[woodType] + randShift
currentMarketRates[woodType] = math.clamp(
newRate,
EconomyConfig.MarketFluctuations.MaxDecrease,
EconomyConfig.MarketFluctuations.MaxIncrease
)
end
-- Broadcast updated rates to all clients
for _, player in ipairs(Players:GetPlayers()) do
MarketUpdateEvent:FireClient(player, currentMarketRates)
end
end
-- Start Market Cycle
task.spawn(function()
if EconomyConfig.MarketFluctuations.Enabled then
while true do
task.wait(EconomyConfig.MarketFluctuations.UpdateInterval)
updateMarketRates()
end
end
end)
local function getPartVolume(part)
return part.Size.X * part.Size.Y * part.Size.Z
end
local function calculateWoodValue(logPart)
local treeType = logPart:GetAttribute("TreeType")
local state = logPart:GetAttribute("ProcessState") or "Raw"
if not treeType or not EconomyConfig.WoodBaseValues[treeType] then return 0 end
local baseValue = EconomyConfig.WoodBaseValues[treeType]
local marketMult = currentMarketRates[treeType] or 1.0
local processMult = EconomyConfig.ProcessingMultipliers[state] or 1.0
local degradedMult = logPart:GetAttribute("DegradedMult") or 1.0
local volume = getPartVolume(logPart)
-- Formula: Volume * BaseValue * ProcessingState * MarketDemand * Degradation
return math.floor(volume * baseValue * processMult * marketMult * degradedMult)
end
local function rewardPlayer(player, amount)
if not player then return end
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats then
local cash = leaderstats:FindFirstChild("Cash")
if cash then
cash.Value = cash.Value + amount
end
end
-- Track total earned
if _G.IncrementStat then
_G.IncrementStat(player, "TotalEarned", amount)
end
-- Progress quests
if _G.ProgressQuest then
_G.ProgressQuest(player, "Sell", 1)
_G.ProgressQuest(player, "EarnCash", amount)
end
-- Check achievements
if _G.CheckAchievements then
task.defer(function() _G.CheckAchievements(player) end)
end
end
local function bindDropoffZone(zonePart)
local debounce = {}
zonePart.Touched:Connect(function(hit)
if CollectionService:HasTag(hit, "TreeSegment") then
if not debounce[hit] then
debounce[hit] = true
local woodValue = calculateWoodValue(hit)
local ownerId = hit:GetAttribute("OwnerId")
local playerToReward = nil
if ownerId then
playerToReward = Players:GetPlayerByUserId(ownerId)
else
pcall(function()
playerToReward = hit:GetNetworkOwner()
end)
end
if playerToReward and woodValue > 0 then
rewardPlayer(playerToReward, woodValue)
-- Notification with value
local treeType = hit:GetAttribute("TreeType") or "Unknown"
local state = hit:GetAttribute("ProcessState") or "Raw"
NotificationEvent:FireClient(playerToReward, "Sale", "Sold " .. state .. " " .. treeType .. " for $" .. tostring(woodValue))
SoundEvent:FireClient(playerToReward, "CashRegister", nil)
end
hit:Destroy()
end
end
end)
end
CollectionService:GetInstanceAddedSignal("MarketDropoff"):Connect(bindDropoffZone)
for _, zone in pairs(CollectionService:GetTagged("MarketDropoff")) do
bindDropoffZone(zone)
end
-- Expose market rates for billboard GUI
_G.GetMarketRates = function()
return currentMarketRates
end
-- Send initial market rates to new players
Players.PlayerAdded:Connect(function(player)
task.delay(5, function()
if player.Parent then
MarketUpdateEvent:FireClient(player, currentMarketRates)
end
end)
end)