218 lines
8.1 KiB
Lua
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
|