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

218 lines
8.1 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__StringIncludes = ____lualib.__TS__StringIncludes
local __TS__Iterator = ____lualib.__TS__Iterator
local ____exports = {}
local ____entity_radius = require("utils.entity_radius")
local findAllByClassnameInRadius = ____entity_radius.findAllByClassnameInRadius
____exports.ItemDetector = __TS__Class()
local ItemDetector = ____exports.ItemDetector
ItemDetector.name = "ItemDetector"
ItemDetector.____file_path = "scripts/vscripts/item_detector.lua"
function ItemDetector.prototype.____constructor(self)
self.lastKnownItems = __TS__New(Map)
self.lastKnownItems = __TS__New(Map)
self:InitializeItemDetection()
ListenToGameEvent(
"entity_killed",
function(event) return self:OnItemPickup(event) end,
nil
)
end
function ItemDetector.Initialize(self)
if not ____exports.ItemDetector.instance then
____exports.ItemDetector.instance = __TS__New(____exports.ItemDetector)
end
end
function ItemDetector.prototype.InitializeItemDetection(self)
GameRules:GetGameModeEntity():SetThink(
function()
self:ScanForNearbyItems()
return 0.25
end,
"ScanForNearbyItemsThink",
"0",
nil
)
end
function ItemDetector.prototype.snapshotFromUpdate(self, u)
return {
distanceRounded = math.floor(u.distance + 0.5),
cost = u.cost,
currencyType = u.currencyType,
rarity = u.rarity
}
end
function ItemDetector.prototype.snapshotsEqual(self, a, b)
return a.distanceRounded == b.distanceRounded and a.cost == b.cost and a.currencyType == b.currencyType and a.rarity == b.rarity
end
function ItemDetector.prototype.tryBuildNearbyUpdate(self, heroPos, itemEntity, detectionRadius)
local containedItem = itemEntity:GetContainedItem()
if containedItem == nil or containedItem == nil then
return nil
end
local itemName = containedItem:GetAbilityName()
local itemPos = itemEntity:GetAbsOrigin()
local distance = (heroPos - itemPos):Length2D()
if distance > detectionRadius then
return nil
end
local itemCost = containedItem:GetCost()
local currencyType
local rarity
if __TS__StringIncludes(itemName, "item_blackshop_") then
local blackShop = require("blackshop").BlackShop:getInstance()
local shopItem = blackShop:getItemInfo(itemName)
if shopItem then
itemCost = shopItem.cost
currencyType = "crystal"
repeat
local ____switch15 = shopItem.quality
local ____cond15 = ____switch15 == 0
if ____cond15 then
rarity = "common"
break
end
____cond15 = ____cond15 or ____switch15 == 1
if ____cond15 then
rarity = "rare"
break
end
____cond15 = ____cond15 or ____switch15 == 2
if ____cond15 then
rarity = "epic"
break
end
____cond15 = ____cond15 or ____switch15 == 3
if ____cond15 then
rarity = "legendary"
break
end
____cond15 = ____cond15 or ____switch15 == 4
if ____cond15 then
rarity = "cursed"
break
end
____cond15 = ____cond15 or ____switch15 == 5
if ____cond15 then
rarity = "heavenly"
break
end
do
rarity = "common"
break
end
until true
end
else
currencyType = "gold"
end
return {
itemName = itemName,
distance = distance,
cost = itemCost,
currencyType = currencyType,
rarity = rarity
}
end
function ItemDetector.prototype.ScanForNearbyItems(self)
local heroes = HeroList:GetAllHeroes()
local detectionRadius = 400
for ____, hero in ipairs(heroes) do
do
if not IsValidEntity(hero) or not hero:IsRealHero() then
goto __continue18
end
local heroPos = hero:GetAbsOrigin()
local playerID = hero:GetPlayerOwnerID()
if playerID == -1 then
goto __continue18
end
local player = PlayerResource:GetPlayer(playerID)
if not player then
goto __continue18
end
local nearbyItems = findAllByClassnameInRadius("dota_item_drop", heroPos, detectionRadius)
local currentMap = __TS__New(Map)
for ____, item in ipairs(nearbyItems) do
do
if not IsValidEntity(item) then
goto __continue22
end
local itemEntity = item
if not itemEntity then
goto __continue22
end
local update = self:tryBuildNearbyUpdate(heroPos, itemEntity, detectionRadius)
if update then
currentMap:set(update.itemName, update)
end
end
::__continue22::
end
local lastMap = self.lastKnownItems:get(playerID) or __TS__New(Map)
for ____, ____value in __TS__Iterator(lastMap) do
local name = ____value[1]
if not currentMap:has(name) then
CustomGameEventManager:Send_ServerToPlayer(player, "nearby_item_remove", {itemName = name})
end
end
for ____, ____value in __TS__Iterator(currentMap) do
local name = ____value[1]
local update = ____value[2]
local nextSnap = self:snapshotFromUpdate(update)
local prev = lastMap:get(name)
if prev == nil then
CustomGameEventManager:Send_ServerToPlayer(player, "nearby_item_update", update)
elseif not self:snapshotsEqual(prev, nextSnap) then
CustomGameEventManager:Send_ServerToPlayer(player, "nearby_item_update", update)
end
end
local nextKnown = __TS__New(Map)
for ____, ____value in __TS__Iterator(currentMap) do
local u = ____value[2]
nextKnown:set(
u.itemName,
self:snapshotFromUpdate(u)
)
end
self.lastKnownItems:set(playerID, nextKnown)
end
::__continue18::
end
end
function ItemDetector.prototype.OnItemPickup(self, event)
local killedUnit = EntIndexToHScript(event.entindex_killed)
if killedUnit and killedUnit:GetClassname() == "dota_item_drop" then
local itemEntity = killedUnit
local containedItem = itemEntity:GetContainedItem()
if containedItem ~= nil and containedItem ~= nil then
local itemName = containedItem:GetAbilityName()
for ____, ____value in __TS__Iterator(self.lastKnownItems) do
local playerID = ____value[1]
local map = ____value[2]
do
if not map:has(itemName) then
goto __continue40
end
map:delete(itemName)
local player = PlayerResource:GetPlayer(playerID)
if player then
CustomGameEventManager:Send_ServerToPlayer(player, "nearby_item_remove", {itemName = itemName})
end
end
::__continue40::
end
end
end
end
function ItemDetector.getInstance(self)
if not ____exports.ItemDetector.instance then
____exports.ItemDetector.instance = __TS__New(____exports.ItemDetector)
end
return ____exports.ItemDetector.instance
end
return ____exports