Files
2026-05-29 15:11:31 +07:00

227 lines
8.6 KiB
Lua

local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local Map = ____lualib.Map
local __TS__New = ____lualib.__TS__New
local __TS__Iterator = ____lualib.__TS__Iterator
local ____exports = {}
____exports.CrystalCurrency = __TS__Class()
local CrystalCurrency = ____exports.CrystalCurrency
CrystalCurrency.name = "CrystalCurrency"
CrystalCurrency.____file_path = "scripts/vscripts/crystal_currency.lua"
function CrystalCurrency.prototype.____constructor(self)
self.playerCrystals = __TS__New(Map)
self.playerTotalSpentCrystals = __TS__New(Map)
self.animationTimers = __TS__New(Map)
self.spendListeners = __TS__New(Map)
self.nextSpendListenerId = 1
self:initializePlayers()
self:setupEventListeners()
end
function CrystalCurrency.getInstance(self)
if not ____exports.CrystalCurrency.instance then
____exports.CrystalCurrency.instance = __TS__New(____exports.CrystalCurrency)
end
return ____exports.CrystalCurrency.instance
end
function CrystalCurrency.prototype.initializePlayers(self)
do
local i = 0
while i < DOTA_MAX_TEAM_PLAYERS do
if PlayerResource:IsValidPlayer(i) then
self.playerCrystals:set(i, 0)
self.playerTotalSpentCrystals:set(i, 0)
self:updateCrystalDisplay(i)
end
i = i + 1
end
end
end
function CrystalCurrency.prototype.setupEventListeners(self)
end
function CrystalCurrency.prototype.cleanupPlayerTimers(self, playerId)
local timerId = self.animationTimers:get(playerId)
if timerId then
GameRules:GetGameModeEntity():SetContextThink(
"crystal_animate_" .. tostring(playerId),
nil,
0
)
self.animationTimers:delete(playerId)
end
end
function CrystalCurrency.prototype.getCrystals(self, playerId)
return self.playerCrystals:get(playerId) or 0
end
function CrystalCurrency.prototype.addCrystals(self, playerId, amount)
if amount <= 0 then
return false
end
local currentCrystals = self:getCrystals(playerId)
local newAmount = currentCrystals + amount
self.playerCrystals:set(playerId, newAmount)
local existingTimer = self.animationTimers:get(playerId)
if existingTimer then
GameRules:GetGameModeEntity():SetContextThink(
"crystal_animate_" .. tostring(playerId),
nil,
0
)
end
local timerId = GameRules:GetGameModeEntity():SetContextThink(
"crystal_animate_" .. tostring(playerId),
function()
local player = PlayerResource:GetPlayer(playerId)
if player then
CustomGameEventManager:Send_ServerToPlayer(player, "crystal_animate", {amount = newAmount, added = amount})
end
self.animationTimers:delete(playerId)
return -1
end,
0.1
)
self.animationTimers:set(playerId, timerId)
GameRules:GetGameModeEntity():SetContextThink(
"crystal_net_table_" .. tostring(playerId),
function()
self:updateCrystalDisplay(playerId)
return -1
end,
0.2
)
self:sendCrystalNotification(playerId, amount, "crystal_gained")
return true
end
function CrystalCurrency.prototype.removeCrystals(self, playerId, amount)
if amount <= 0 then
return false
end
local currentCrystals = self:getCrystals(playerId)
if currentCrystals < amount then
print((((("[CRYSTAL] removeCrystals FAIL: player=" .. tostring(playerId)) .. ", need=") .. tostring(amount)) .. ", have=") .. tostring(currentCrystals))
return false
end
local newAmount = currentCrystals - amount
local totalSpent = (self.playerTotalSpentCrystals:get(playerId) or 0) + amount
self.playerCrystals:set(playerId, newAmount)
self.playerTotalSpentCrystals:set(playerId, totalSpent)
print((((((((("[CRYSTAL] removeCrystals OK: player=" .. tostring(playerId)) .. ", spent=") .. tostring(amount)) .. ", before=") .. tostring(currentCrystals)) .. ", after=") .. tostring(newAmount)) .. ", totalSpent=") .. tostring(totalSpent))
local existingTimer = self.animationTimers:get(playerId)
if existingTimer then
GameRules:GetGameModeEntity():SetContextThink(
"crystal_animate_" .. tostring(playerId),
nil,
0
)
end
local timerId = GameRules:GetGameModeEntity():SetContextThink(
"crystal_animate_" .. tostring(playerId),
function()
local player = PlayerResource:GetPlayer(playerId)
if player then
CustomGameEventManager:Send_ServerToPlayer(player, "crystal_animate", {amount = newAmount, added = -amount})
end
self.animationTimers:delete(playerId)
return -1
end,
0.1
)
self.animationTimers:set(playerId, timerId)
self:updateCrystalDisplay(playerId)
self:notifyCrystalsSpent(playerId, amount, newAmount, totalSpent)
return true
end
function CrystalCurrency.prototype.setCrystals(self, playerId, amount)
if amount < 0 then
return false
end
self.playerCrystals:set(playerId, amount)
self:updateCrystalDisplay(playerId)
return true
end
function CrystalCurrency.prototype.canAfford(self, playerId, cost)
return self:getCrystals(playerId) >= cost
end
function CrystalCurrency.prototype.getTotalSpentCrystals(self, playerId)
return self.playerTotalSpentCrystals:get(playerId) or 0
end
function CrystalCurrency.prototype.addSpendListener(self, callback)
local ____self_0, ____nextSpendListenerId_1 = self, "nextSpendListenerId"
local ____self_nextSpendListenerId_2 = ____self_0[____nextSpendListenerId_1]
____self_0[____nextSpendListenerId_1] = ____self_nextSpendListenerId_2 + 1
local id = ____self_nextSpendListenerId_2
self.spendListeners:set(id, callback)
print((("[CRYSTAL] addSpendListener: id=" .. tostring(id)) .. ", listeners=") .. tostring(self.spendListeners.size))
return id
end
function CrystalCurrency.prototype.removeSpendListener(self, listenerId)
self.spendListeners:delete(listenerId)
print((("[CRYSTAL] removeSpendListener: id=" .. tostring(listenerId)) .. ", listeners=") .. tostring(self.spendListeners.size))
end
function CrystalCurrency.prototype.notifyCrystalsSpent(self, playerId, spentAmount, newTotal, totalSpent)
print((((((((("[CRYSTAL] notifyCrystalsSpent: player=" .. tostring(playerId)) .. ", spent=") .. tostring(spentAmount)) .. ", newTotal=") .. tostring(newTotal)) .. ", totalSpent=") .. tostring(totalSpent)) .. ", listeners=") .. tostring(self.spendListeners.size))
for ____, callback in __TS__Iterator(self.spendListeners:values()) do
callback(
nil,
playerId,
spentAmount,
newTotal,
totalSpent
)
end
end
function CrystalCurrency.prototype.updateCrystalDisplay(self, playerId)
local crystals = self:getCrystals(playerId)
local key = "crystals_" .. tostring(playerId)
local data = {amount = crystals}
CustomNetTables:SetTableValue("crystal_currency", key, data)
end
function CrystalCurrency.prototype.sendCrystalNotification(self, playerId, amount, ____type)
local player = PlayerResource:GetPlayer(playerId)
if player then
CustomGameEventManager:Send_ServerToPlayer(
player,
"crystal_currency_changed",
{
amount = amount,
type = ____type,
total = self:getCrystals(playerId)
}
)
end
end
function CrystalCurrency.prototype.giveCrystalsForKill(self, _playerId, _unitName)
end
function CrystalCurrency.prototype.convertGoldToCrystals(self, playerId, goldAmount)
local hero = PlayerResource:GetSelectedHeroEntity(playerId)
if not hero then
return false
end
local currentGold = PlayerResource:GetGold(playerId)
if currentGold < goldAmount then
return false
end
local crystalAmount = math.floor(goldAmount / 100)
if crystalAmount <= 0 then
return false
end
hero:ModifyGold(-goldAmount, true, 0)
self:addCrystals(playerId, crystalAmount)
return true
end
function CrystalCurrency.prototype.convertCrystalsToGold(self, playerId, crystalAmount)
if not self:canAfford(playerId, crystalAmount) then
return false
end
local goldAmount = crystalAmount * 100
self:removeCrystals(playerId, crystalAmount)
local hero = PlayerResource:GetSelectedHeroEntity(playerId)
if hero then
hero:ModifyGold(goldAmount, true, 0)
end
return true
end
function ____exports.GetCrystalCurrency(self)
return ____exports.CrystalCurrency:getInstance()
end
return ____exports