File size: 4,622 Bytes
0712d5f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | -- 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)
|