initial commit
This commit is contained in:
@@ -0,0 +1,599 @@
|
||||
local ____lualib = require("lualib_bundle")
|
||||
local __TS__Class = ____lualib.__TS__Class
|
||||
local Set = ____lualib.Set
|
||||
local __TS__New = ____lualib.__TS__New
|
||||
local __TS__ArrayFind = ____lualib.__TS__ArrayFind
|
||||
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
|
||||
local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
|
||||
local __TS__ArrayFrom = ____lualib.__TS__ArrayFrom
|
||||
local ____exports = {}
|
||||
local ____entity_radius = require("utils.entity_radius")
|
||||
local findAllByClassnameInRadius = ____entity_radius.findAllByClassnameInRadius
|
||||
local ____CardSystem = require("cards.CardSystem")
|
||||
local ShowCardSelectionToPlayer = ____CardSystem.ShowCardSelectionToPlayer
|
||||
local ____crystal_currency = require("crystal_currency")
|
||||
local CrystalCurrency = ____crystal_currency.CrystalCurrency
|
||||
local ____black_shop_teleport = require("black_shop_teleport")
|
||||
local isBlackShopTeleportDestination = ____black_shop_teleport.isBlackShopTeleportDestination
|
||||
local resolveBlackShopTeleportPosition = ____black_shop_teleport.resolveBlackShopTeleportPosition
|
||||
local BLACKSHOP_GOLD_TO_CRYSTAL_RATE = 100
|
||||
local BLACKSHOP_CRYSTAL_TO_GOLD_RATE = 25
|
||||
local ItemQuality = ItemQuality or ({})
|
||||
ItemQuality.COMMON = 0
|
||||
ItemQuality[ItemQuality.COMMON] = "COMMON"
|
||||
ItemQuality.RARE = 1
|
||||
ItemQuality[ItemQuality.RARE] = "RARE"
|
||||
ItemQuality.EPIC = 2
|
||||
ItemQuality[ItemQuality.EPIC] = "EPIC"
|
||||
ItemQuality.LEGENDARY = 3
|
||||
ItemQuality[ItemQuality.LEGENDARY] = "LEGENDARY"
|
||||
ItemQuality.CURSED = 4
|
||||
ItemQuality[ItemQuality.CURSED] = "CURSED"
|
||||
ItemQuality.HEAVENLY = 5
|
||||
ItemQuality[ItemQuality.HEAVENLY] = "HEAVENLY"
|
||||
____exports.BlackShop = __TS__Class()
|
||||
local BlackShop = ____exports.BlackShop
|
||||
BlackShop.name = "BlackShop"
|
||||
BlackShop.____file_path = "scripts/vscripts/blackshop.lua"
|
||||
function BlackShop.prototype.____constructor(self)
|
||||
self.shopItems = {}
|
||||
self.spawnPoints = {}
|
||||
self.purchasedUniqueItems = __TS__New(Set)
|
||||
self.isUniqueItemSpawned = false
|
||||
self.cardPurchaseBaseCost = 5
|
||||
self.cardPurchaseCostByPlayer = {}
|
||||
self:initializeItems()
|
||||
self:findSpawnPoints()
|
||||
self:SpawnItems()
|
||||
end
|
||||
function BlackShop.getInstance(self)
|
||||
if not ____exports.BlackShop.instance then
|
||||
____exports.BlackShop.instance = __TS__New(____exports.BlackShop)
|
||||
end
|
||||
return ____exports.BlackShop.instance
|
||||
end
|
||||
function BlackShop.prototype.initializeItems(self)
|
||||
self.shopItems = {
|
||||
{name = "item_blackshop_common_bonus_stats_str", cost = 5, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_bonus_stats_int", cost = 5, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_bonus_stats_agi", cost = 5, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_injector", cost = 3, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_king_crown", cost = 10, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_manaflare", cost = 5, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_spell_mask", cost = 7, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_stone_armor", cost = 10, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_boo_stuff", cost = 5, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_vigor_tincture", cost = 4, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_wind_dust", cost = 4, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_common_blue_tallow", cost = 5, quality = ItemQuality.COMMON},
|
||||
{name = "item_blackshop_rare_damage_dagger", cost = 7, quality = ItemQuality.RARE},
|
||||
{name = "item_blackshop_rare_agility_cape", cost = 14, quality = ItemQuality.RARE},
|
||||
{name = "item_blackshop_rare_egg_of_death", cost = 10, quality = ItemQuality.RARE},
|
||||
{name = "item_blackshop_rare_granite_badge", cost = 12, quality = ItemQuality.RARE},
|
||||
{name = "item_blackshop_rare_iron_resolve", cost = 13, quality = ItemQuality.RARE},
|
||||
{name = "item_blackshop_rare_silver_eye", cost = 12, quality = ItemQuality.RARE, uniqueItem = true},
|
||||
{name = "item_blackshop_rare_critical_havoc", cost = 11, quality = ItemQuality.RARE, uniqueItem = true},
|
||||
{name = "item_blackshop_epic_power_of_grow", cost = 15, quality = ItemQuality.EPIC, uniqueItem = true},
|
||||
{name = "item_blackshop_epic_critical_paladin_sword", cost = 8, quality = ItemQuality.EPIC, uniqueItem = true},
|
||||
{name = "item_blackshop_epic_trinity_seal", cost = 20, quality = ItemQuality.EPIC, uniqueItem = true},
|
||||
{name = "item_blackshop_epic_bulwark_plate", cost = 22, quality = ItemQuality.EPIC, uniqueItem = true},
|
||||
{name = "item_blackshop_legendary_fire_summoner", cost = 18, quality = ItemQuality.LEGENDARY, uniqueItem = true},
|
||||
{name = "item_blackshop_legendary_primordial_shard", cost = 32, quality = ItemQuality.LEGENDARY},
|
||||
{
|
||||
name = "item_blackshop_legendary_restock",
|
||||
cost = 12,
|
||||
quality = ItemQuality.LEGENDARY,
|
||||
uniqueItem = true,
|
||||
nonRefundable = true
|
||||
},
|
||||
{
|
||||
name = "item_blackshop_legendary_twilight_mirror",
|
||||
cost = 38,
|
||||
quality = ItemQuality.LEGENDARY,
|
||||
uniqueItem = true,
|
||||
nonRefundable = true
|
||||
},
|
||||
{
|
||||
name = "item_blackshop_legendary_astral_anchor",
|
||||
cost = 36,
|
||||
quality = ItemQuality.LEGENDARY,
|
||||
uniqueItem = true,
|
||||
nonRefundable = true
|
||||
},
|
||||
{name = "item_blackshop_legendary_fated_die", cost = 26, quality = ItemQuality.LEGENDARY},
|
||||
{
|
||||
name = "item_blackshop_cursed_the_hand_of_gluttony",
|
||||
cost = 60,
|
||||
quality = ItemQuality.CURSED,
|
||||
uniqueItem = true,
|
||||
nonRefundable = true
|
||||
},
|
||||
{name = "item_blackshop_cursed_martyrs_brand", cost = 52, quality = ItemQuality.CURSED},
|
||||
{name = "item_blackshop_cursed_widow_chain", cost = 50, quality = ItemQuality.CURSED},
|
||||
{name = "item_blackshop_cursed_glass_pact", cost = 46, quality = ItemQuality.CURSED},
|
||||
{
|
||||
name = "item_blackshop_heavenly_reset_to_zero",
|
||||
cost = 15,
|
||||
quality = ItemQuality.HEAVENLY,
|
||||
uniqueItem = true,
|
||||
nonRefundable = true
|
||||
},
|
||||
{
|
||||
name = "item_blackshop_heavenly_font_of_mercy",
|
||||
cost = 48,
|
||||
quality = ItemQuality.HEAVENLY,
|
||||
uniqueItem = true,
|
||||
nonRefundable = true
|
||||
},
|
||||
{name = "item_blackshop_heavenly_sanctuary_veil", cost = 32, quality = ItemQuality.HEAVENLY, uniqueItem = true},
|
||||
{name = "item_blackshop_heavenly_dawn_chorus", cost = 34, quality = ItemQuality.HEAVENLY, uniqueItem = true}
|
||||
}
|
||||
end
|
||||
function BlackShop.prototype.findSpawnPoints(self)
|
||||
self.spawnPoints = {}
|
||||
do
|
||||
local i = 1
|
||||
while i <= 5 do
|
||||
local entity = Entities:FindByName(
|
||||
nil,
|
||||
"blackshop_item_point_" .. tostring(i)
|
||||
)
|
||||
if entity and not entity:IsNull() then
|
||||
local position = entity:GetOrigin()
|
||||
local ____self_spawnPoints_0 = self.spawnPoints
|
||||
____self_spawnPoints_0[#____self_spawnPoints_0 + 1] = position
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
function BlackShop.prototype.SpawnItems(self)
|
||||
self.isUniqueItemSpawned = false
|
||||
__TS__ArrayForEach(
|
||||
self.spawnPoints,
|
||||
function(____, point, index)
|
||||
local itemsNearby = findAllByClassnameInRadius("dota_item_drop", point, 100)
|
||||
__TS__ArrayForEach(
|
||||
itemsNearby,
|
||||
function(____, entity)
|
||||
if entity and not entity:IsNull() then
|
||||
local containerItem = entity
|
||||
local actualItem = containerItem:GetContainedItem()
|
||||
if actualItem ~= nil and actualItem ~= nil then
|
||||
local itemName = actualItem:GetAbilityName()
|
||||
local shopItem = __TS__ArrayFind(
|
||||
self.shopItems,
|
||||
function(____, i) return i.name == itemName end
|
||||
)
|
||||
if shopItem and shopItem.uniqueItem then
|
||||
self.isUniqueItemSpawned = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
if #itemsNearby == 0 then
|
||||
local availableItems = __TS__ArrayFilter(
|
||||
self.shopItems,
|
||||
function(____, item)
|
||||
if item.uniqueItem then
|
||||
local isAvailable = not self.purchasedUniqueItems:has(item.name) and not self.isUniqueItemSpawned
|
||||
return isAvailable
|
||||
end
|
||||
return not self.purchasedUniqueItems:has(item.name)
|
||||
end
|
||||
)
|
||||
if #availableItems == 0 then
|
||||
return
|
||||
end
|
||||
local randomItem = availableItems[RandomInt(0, #availableItems - 1) + 1]
|
||||
if randomItem.uniqueItem then
|
||||
self.isUniqueItemSpawned = true
|
||||
end
|
||||
local item = CreateItem(randomItem.name, nil, nil)
|
||||
local drop = CreateItemOnPositionForLaunch(point, item)
|
||||
drop:SetAbsOrigin(point)
|
||||
drop:SetAngles(0, 0, 0)
|
||||
local particleName
|
||||
repeat
|
||||
local ____switch21 = randomItem.quality
|
||||
local ____cond21 = ____switch21 == ItemQuality.COMMON
|
||||
if ____cond21 then
|
||||
particleName = "particles/units/heroes/hero_ancient_apparition/ancient_apparition_freeze_stacks_smoke_b.vpcf"
|
||||
break
|
||||
end
|
||||
____cond21 = ____cond21 or ____switch21 == ItemQuality.RARE
|
||||
if ____cond21 then
|
||||
particleName = "particles/units/heroes/hero_ancient_apparition/ancient_apparition_ice_blast_main.vpcf"
|
||||
break
|
||||
end
|
||||
____cond21 = ____cond21 or ____switch21 == ItemQuality.EPIC
|
||||
if ____cond21 then
|
||||
particleName = "particles/econ/items/lanaya/lanaya_epit_trap/templar_assassin_epit_trap.vpcf"
|
||||
break
|
||||
end
|
||||
____cond21 = ____cond21 or ____switch21 == ItemQuality.LEGENDARY
|
||||
if ____cond21 then
|
||||
particleName = "particles/econ/items/templar_assassin/ta_2022_immortal/ta_2022_immortal_trap_gold.vpcf"
|
||||
break
|
||||
end
|
||||
____cond21 = ____cond21 or ____switch21 == ItemQuality.CURSED
|
||||
if ____cond21 then
|
||||
particleName = "particles/econ/items/shadow_fiend/sf_desolation/sf_base_attack_desolation.vpcf"
|
||||
break
|
||||
end
|
||||
____cond21 = ____cond21 or ____switch21 == ItemQuality.HEAVENLY
|
||||
if ____cond21 then
|
||||
particleName = "particles/econ/items/templar_assassin/ta_2022_immortal/ta_2022_immortal_trap_crimson.vpcf"
|
||||
break
|
||||
end
|
||||
do
|
||||
particleName = "particles/default_item.vpcf"
|
||||
end
|
||||
until true
|
||||
local particle = ParticleManager:CreateParticle(particleName, PATTACH_ABSORIGIN_FOLLOW, drop)
|
||||
ParticleManager:SetParticleControl(particle, 0, point)
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
function BlackShop.prototype.RefreshShop(self)
|
||||
__TS__ArrayForEach(
|
||||
self.spawnPoints,
|
||||
function(____, point, index)
|
||||
local itemsNearby = findAllByClassnameInRadius("dota_item_drop", point, 100)
|
||||
__TS__ArrayForEach(
|
||||
itemsNearby,
|
||||
function(____, item)
|
||||
if item and not item:IsNull() then
|
||||
local containerItem = item
|
||||
local actualItem = containerItem:GetContainedItem()
|
||||
if not actualItem or not actualItem._wasPurchased then
|
||||
UTIL_Remove(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
)
|
||||
self:SpawnItems()
|
||||
end
|
||||
function BlackShop.prototype.OnItemPickup(self, item, player)
|
||||
local itemName = item:GetAbilityName()
|
||||
local shopItem = __TS__ArrayFind(
|
||||
self.shopItems,
|
||||
function(____, i) return i.name == itemName end
|
||||
)
|
||||
if not shopItem then
|
||||
return false
|
||||
end
|
||||
if shopItem.uniqueItem then
|
||||
self.purchasedUniqueItems:add(shopItem.name)
|
||||
end
|
||||
item._wasPurchased = true
|
||||
return true
|
||||
end
|
||||
function BlackShop.prototype.getItemInfo(self, itemName)
|
||||
return __TS__ArrayFind(
|
||||
self.shopItems,
|
||||
function(____, item) return item.name == itemName end
|
||||
)
|
||||
end
|
||||
function BlackShop.prototype.getItemCost(self, itemName)
|
||||
local item = self:getItemInfo(itemName)
|
||||
return item and item.cost or 0
|
||||
end
|
||||
function BlackShop.prototype.OnItemPurchased(self, itemName)
|
||||
local shopItem = __TS__ArrayFind(
|
||||
self.shopItems,
|
||||
function(____, i) return i.name == itemName end
|
||||
)
|
||||
if shopItem and shopItem.uniqueItem then
|
||||
self.purchasedUniqueItems:add(itemName)
|
||||
end
|
||||
end
|
||||
function BlackShop.prototype.ResetUniqueItems(self)
|
||||
local currentItems = __TS__ArrayFrom(self.purchasedUniqueItems)
|
||||
__TS__ArrayForEach(
|
||||
currentItems,
|
||||
function(____, itemName)
|
||||
local item = __TS__ArrayFind(
|
||||
self.shopItems,
|
||||
function(____, i) return i.name == itemName end
|
||||
)
|
||||
if item and not item.nonRefundable then
|
||||
self.purchasedUniqueItems:delete(itemName)
|
||||
elseif item and item.nonRefundable then
|
||||
end
|
||||
end
|
||||
)
|
||||
self.isUniqueItemSpawned = false
|
||||
self:RefreshShop()
|
||||
end
|
||||
function BlackShop.prototype.getCardPurchaseCost(self, playerId)
|
||||
local currentCost = self.cardPurchaseCostByPlayer[playerId]
|
||||
if currentCost ~= nil and currentCost > 0 then
|
||||
return currentCost
|
||||
end
|
||||
self.cardPurchaseCostByPlayer[playerId] = self.cardPurchaseBaseCost
|
||||
return self.cardPurchaseBaseCost
|
||||
end
|
||||
function BlackShop.prototype.buyCardForPlayer(self, playerId)
|
||||
local player = PlayerResource:GetPlayer(playerId)
|
||||
local hero = player and player:GetAssignedHero()
|
||||
local currentCost = self:getCardPurchaseCost(playerId)
|
||||
if not player or not hero then
|
||||
return {success = false, spentCost = currentCost, nextCost = currentCost, errorMessage = "black_shop_not_enough_crystals"}
|
||||
end
|
||||
local crystalCurrency = CrystalCurrency:getInstance()
|
||||
local currentCrystals = crystalCurrency:getCrystals(playerId)
|
||||
if currentCrystals < currentCost then
|
||||
return {success = false, spentCost = currentCost, nextCost = currentCost, errorMessage = "black_shop_not_enough_crystals"}
|
||||
end
|
||||
crystalCurrency:removeCrystals(playerId, currentCost)
|
||||
ShowCardSelectionToPlayer(nil, playerId, 3, "black_shop_buy_card")
|
||||
local nextCost = currentCost * 2
|
||||
self.cardPurchaseCostByPlayer[playerId] = nextCost
|
||||
return {success = true, spentCost = currentCost, nextCost = nextCost}
|
||||
end
|
||||
function BlackShop.prototype.SpawnItemAtPosition(self, position)
|
||||
local availableItems = __TS__ArrayFilter(
|
||||
self.shopItems,
|
||||
function(____, item)
|
||||
if item.uniqueItem then
|
||||
return not self.purchasedUniqueItems:has(item.name) and not self.isUniqueItemSpawned
|
||||
end
|
||||
return not self.purchasedUniqueItems:has(item.name)
|
||||
end
|
||||
)
|
||||
if #availableItems == 0 then
|
||||
return
|
||||
end
|
||||
local randomItem = availableItems[RandomInt(0, #availableItems - 1) + 1]
|
||||
if randomItem.uniqueItem then
|
||||
self.isUniqueItemSpawned = true
|
||||
end
|
||||
local item = CreateItem(randomItem.name, nil, nil)
|
||||
local drop = CreateItemOnPositionForLaunch(position, item)
|
||||
drop:SetAbsOrigin(position)
|
||||
drop:SetAngles(0, 0, 0)
|
||||
local particleName
|
||||
repeat
|
||||
local ____switch52 = randomItem.quality
|
||||
local ____cond52 = ____switch52 == ItemQuality.COMMON
|
||||
if ____cond52 then
|
||||
particleName = "particles/common_item.vpcf"
|
||||
break
|
||||
end
|
||||
____cond52 = ____cond52 or ____switch52 == ItemQuality.RARE
|
||||
if ____cond52 then
|
||||
particleName = "particles/rare_item.vpcf"
|
||||
break
|
||||
end
|
||||
____cond52 = ____cond52 or ____switch52 == ItemQuality.EPIC
|
||||
if ____cond52 then
|
||||
particleName = "particles/epic_item.vpcf"
|
||||
break
|
||||
end
|
||||
____cond52 = ____cond52 or ____switch52 == ItemQuality.LEGENDARY
|
||||
if ____cond52 then
|
||||
particleName = "particles/legendary_item.vpcf"
|
||||
break
|
||||
end
|
||||
____cond52 = ____cond52 or ____switch52 == ItemQuality.CURSED
|
||||
if ____cond52 then
|
||||
particleName = "particles/cursed_item.vpcf"
|
||||
break
|
||||
end
|
||||
____cond52 = ____cond52 or ____switch52 == ItemQuality.HEAVENLY
|
||||
if ____cond52 then
|
||||
particleName = "particles/heavenly_item_effect.vpcf"
|
||||
break
|
||||
end
|
||||
do
|
||||
particleName = "particles/default_item.vpcf"
|
||||
end
|
||||
until true
|
||||
local particle = ParticleManager:CreateParticle(particleName, PATTACH_ABSORIGIN_FOLLOW, drop)
|
||||
ParticleManager:SetParticleControl(particle, 0, position)
|
||||
end
|
||||
--- Регистрация CGE для блекшопа — только из GameMode.Activate (или иного позднего входа).
|
||||
-- При require() из addon_init CustomGameEventManager ещё nil — нельзя вызывать в main chunk.
|
||||
function ____exports.registerBlackShopCustomGameEvents(self)
|
||||
if not IsServer() then
|
||||
return
|
||||
end
|
||||
CustomGameEventManager:RegisterListener(
|
||||
"black_shop_refresh_request",
|
||||
function(_, event)
|
||||
local playerId = event.PlayerID
|
||||
local ____opt_9 = PlayerResource:GetPlayer(playerId)
|
||||
local hero = ____opt_9 and ____opt_9:GetAssignedHero()
|
||||
local refreshCost = 50
|
||||
if not hero then
|
||||
return
|
||||
end
|
||||
local currentGold = hero:GetGold()
|
||||
if currentGold >= refreshCost then
|
||||
PlayerResource:SpendGold(playerId, refreshCost, DOTA_ModifyGold_AbilityGold)
|
||||
____exports.BlackShop:getInstance():RefreshShop()
|
||||
CustomGameEventManager:Send_ServerToAllClients("black_shop_refresh", {success = true})
|
||||
else
|
||||
CustomGameEventManager:Send_ServerToPlayer(
|
||||
PlayerResource:GetPlayer(playerId),
|
||||
"CreateIngameErrorMessage",
|
||||
{gold = refreshCost - currentGold, message = "black_shop_not_enough_gold"}
|
||||
)
|
||||
end
|
||||
end
|
||||
)
|
||||
CustomGameEventManager:RegisterListener(
|
||||
"black_shop_request_card_price",
|
||||
function(_, event)
|
||||
local playerId = event.PlayerID
|
||||
local player = PlayerResource:GetPlayer(playerId)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local cost = ____exports.BlackShop:getInstance():getCardPurchaseCost(playerId)
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "black_shop_card_cost_update", {cost = cost})
|
||||
end
|
||||
)
|
||||
CustomGameEventManager:RegisterListener(
|
||||
"black_shop_buy_card_request",
|
||||
function(_, event)
|
||||
local playerId = event.PlayerID
|
||||
local player = PlayerResource:GetPlayer(playerId)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local result = ____exports.BlackShop:getInstance():buyCardForPlayer(playerId)
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "black_shop_card_cost_update", {cost = result.nextCost})
|
||||
if not result.success then
|
||||
local crystalCurrency = CrystalCurrency:getInstance()
|
||||
local currentCrystals = crystalCurrency:getCrystals(playerId)
|
||||
CustomGameEventManager:Send_ServerToPlayer(
|
||||
player,
|
||||
"CreateIngameErrorMessage",
|
||||
{
|
||||
crystals = math.max(0, result.spentCost - currentCrystals),
|
||||
message = result.errorMessage or "black_shop_not_enough_crystals"
|
||||
}
|
||||
)
|
||||
return
|
||||
end
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "black_shop_card_purchased", {success = true})
|
||||
end
|
||||
)
|
||||
CustomGameEventManager:RegisterListener(
|
||||
"black_shop_teleport_request",
|
||||
function(_, event)
|
||||
local playerId = event.PlayerID
|
||||
if playerId == nil then
|
||||
return
|
||||
end
|
||||
local player = PlayerResource:GetPlayer(playerId)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local dest = event.destination
|
||||
if not isBlackShopTeleportDestination(nil, dest) then
|
||||
return
|
||||
end
|
||||
local hero = player:GetAssignedHero()
|
||||
if not hero or hero:IsNull() then
|
||||
return
|
||||
end
|
||||
if not hero:IsAlive() then
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "black_shop_teleport_result", {success = false})
|
||||
return
|
||||
end
|
||||
local teleportGoldCost = 100
|
||||
local currentGold = hero:GetGold()
|
||||
if currentGold < teleportGoldCost then
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "CreateIngameErrorMessage", {gold = teleportGoldCost - currentGold, message = "black_shop_not_enough_gold"})
|
||||
return
|
||||
end
|
||||
local pos = resolveBlackShopTeleportPosition(nil, dest)
|
||||
if not pos then
|
||||
return
|
||||
end
|
||||
PlayerResource:SpendGold(playerId, teleportGoldCost, DOTA_ModifyGold_AbilityGold)
|
||||
FindClearSpaceForUnit(hero, pos, true)
|
||||
local teleportFx = "particles/econ/events/compendium_2023/compendium_2023_teleport_lvl1.vpcf"
|
||||
local origin = hero:GetAbsOrigin()
|
||||
local pfx = ParticleManager:CreateParticle(teleportFx, PATTACH_WORLDORIGIN, hero)
|
||||
ParticleManager:SetParticleControl(pfx, 0, origin)
|
||||
Timers:CreateTimer(
|
||||
0.5,
|
||||
function()
|
||||
ParticleManager:DestroyParticle(pfx, true)
|
||||
ParticleManager:ReleaseParticleIndex(pfx)
|
||||
end
|
||||
)
|
||||
EmitSoundOn("DOTA_Item.BlinkDagger.Activate", hero)
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "black_shop_teleport_result", {success = true})
|
||||
end
|
||||
)
|
||||
CustomGameEventManager:RegisterListener(
|
||||
"black_shop_exchange_request",
|
||||
function(_, event)
|
||||
local playerId = event.PlayerID or event.player_id
|
||||
if playerId == nil then
|
||||
return
|
||||
end
|
||||
local player = PlayerResource:GetPlayer(playerId)
|
||||
local hero = player and player:GetAssignedHero()
|
||||
if not player or not hero then
|
||||
return
|
||||
end
|
||||
local direction = event.direction
|
||||
local crystals = math.floor(tonumber(event.crystals) or 0)
|
||||
if not direction or crystals <= 0 then
|
||||
return
|
||||
end
|
||||
local crystalCurrency = CrystalCurrency:getInstance()
|
||||
if direction == "gold_to_crystal" then
|
||||
local goldAmount = crystals * BLACKSHOP_GOLD_TO_CRYSTAL_RATE
|
||||
local currentGold = hero:GetGold()
|
||||
if currentGold < goldAmount then
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "CreateIngameErrorMessage", {gold = goldAmount - currentGold, message = "black_shop_not_enough_gold"})
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "black_shop_exchange_result", {success = false})
|
||||
return
|
||||
end
|
||||
PlayerResource:SpendGold(playerId, goldAmount, DOTA_ModifyGold_AbilityGold)
|
||||
crystalCurrency:addCrystals(playerId, crystals)
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "black_shop_exchange_result", {success = true, direction = direction, crystals = crystals, gold = goldAmount})
|
||||
else
|
||||
local goldAmount = crystals * BLACKSHOP_CRYSTAL_TO_GOLD_RATE
|
||||
local currentCrystals = crystalCurrency:getCrystals(playerId)
|
||||
if currentCrystals < crystals then
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "CreateIngameErrorMessage", {crystals = crystals - currentCrystals, message = "black_shop_not_enough_crystals"})
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "black_shop_exchange_result", {success = false})
|
||||
return
|
||||
end
|
||||
local removed = crystalCurrency:removeCrystals(playerId, crystals)
|
||||
if not removed then
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "black_shop_exchange_result", {success = false})
|
||||
return
|
||||
end
|
||||
hero:ModifyGold(goldAmount, true, DOTA_ModifyGold_AbilityGold)
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "black_shop_exchange_result", {success = true, direction = direction, crystals = crystals, gold = goldAmount})
|
||||
end
|
||||
end
|
||||
)
|
||||
CustomGameEventManager:RegisterListener(
|
||||
"black_shop_exchange_sync_request",
|
||||
function(_, event)
|
||||
local playerId = event.PlayerID or event.player_id
|
||||
if playerId == nil then
|
||||
return
|
||||
end
|
||||
local player = PlayerResource:GetPlayer(playerId)
|
||||
local hero = player and player:GetAssignedHero()
|
||||
if not player or not hero then
|
||||
return
|
||||
end
|
||||
local crystalCurrency = CrystalCurrency:getInstance()
|
||||
CustomGameEventManager:Send_ServerToPlayer(
|
||||
player,
|
||||
"black_shop_exchange_sync",
|
||||
{
|
||||
gold = hero:GetGold(),
|
||||
crystals = crystalCurrency:getCrystals(playerId)
|
||||
}
|
||||
)
|
||||
end
|
||||
)
|
||||
end
|
||||
--- Превью дропа / эффекты редкости предметов
|
||||
function ____exports.precacheBlackshopParticles(self, context)
|
||||
PrecacheResource("particle", "particles/econ/events/compendium_2023/compendium_2023_teleport_lvl1.vpcf", context)
|
||||
PrecacheResource("particle", "particles/units/heroes/hero_ancient_apparition/ancient_apparition_freeze_stacks_smoke_b.vpcf", context)
|
||||
PrecacheResource("particle", "particles/units/heroes/hero_ancient_apparition/ancient_apparition_ice_blast_main.vpcf", context)
|
||||
PrecacheResource("particle", "particles/econ/items/lanaya/lanaya_epit_trap/templar_assassin_epit_trap.vpcf", context)
|
||||
PrecacheResource("particle", "particles/econ/items/templar_assassin/ta_2022_immortal/ta_2022_immortal_trap_gold.vpcf", context)
|
||||
PrecacheResource("particle", "particles/econ/items/shadow_fiend/sf_desolation/sf_base_attack_desolation.vpcf", context)
|
||||
PrecacheResource("particle", "particles/econ/items/templar_assassin/ta_2022_immortal/ta_2022_immortal_trap_crimson.vpcf", context)
|
||||
end
|
||||
return ____exports
|
||||
Reference in New Issue
Block a user