754 lines
28 KiB
Lua
754 lines
28 KiB
Lua
local ____lualib = require("lualib_bundle")
|
|
local __TS__Class = ____lualib.__TS__Class
|
|
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
|
|
local Map = ____lualib.Map
|
|
local __TS__New = ____lualib.__TS__New
|
|
local Set = ____lualib.Set
|
|
local __TS__ArrayIncludes = ____lualib.__TS__ArrayIncludes
|
|
local __TS__ArrayIsArray = ____lualib.__TS__ArrayIsArray
|
|
local __TS__ObjectEntries = ____lualib.__TS__ObjectEntries
|
|
local __TS__ObjectValues = ____lualib.__TS__ObjectValues
|
|
local __TS__ArrayEvery = ____lualib.__TS__ArrayEvery
|
|
local __TS__ArrayPushArray = ____lualib.__TS__ArrayPushArray
|
|
local __TS__Iterator = ____lualib.__TS__Iterator
|
|
local __TS__ArrayFrom = ____lualib.__TS__ArrayFrom
|
|
local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
|
|
local __TS__ArrayMap = ____lualib.__TS__ArrayMap
|
|
local ____exports = {}
|
|
local ____crystal_currency = require("crystal_currency")
|
|
local CrystalCurrency = ____crystal_currency.CrystalCurrency
|
|
local ____entity_radius = require("utils.entity_radius")
|
|
local findNearestByClassname = ____entity_radius.findNearestByClassname
|
|
local ____real_lobby_player = require("utils.real_lobby_player")
|
|
local collectStatsEligiblePlayerIds = ____real_lobby_player.collectStatsEligiblePlayerIds
|
|
local ____quest_reward_scaling = require("quests.quest_reward_scaling")
|
|
local getQuestRewardSplitCount = ____quest_reward_scaling.getQuestRewardSplitCount
|
|
local splitQuestTeamReward = ____quest_reward_scaling.splitQuestTeamReward
|
|
____exports.QuestType = QuestType or ({})
|
|
____exports.QuestType.KILL_UNIT = "KILL_UNIT"
|
|
____exports.QuestType.COLLECT_ITEM = "COLLECT_ITEM"
|
|
____exports.QuestType.REACH_LOCATION = "REACH_LOCATION"
|
|
____exports.QuestType.CUSTOM = "CUSTOM"
|
|
____exports.QuestState = QuestState or ({})
|
|
____exports.QuestState.AVAILABLE = 0
|
|
____exports.QuestState[____exports.QuestState.AVAILABLE] = "AVAILABLE"
|
|
____exports.QuestState.IN_PROGRESS = 1
|
|
____exports.QuestState[____exports.QuestState.IN_PROGRESS] = "IN_PROGRESS"
|
|
____exports.QuestState.COMPLETED = 2
|
|
____exports.QuestState[____exports.QuestState.COMPLETED] = "COMPLETED"
|
|
____exports.QuestState.LOCKED = 3
|
|
____exports.QuestState[____exports.QuestState.LOCKED] = "LOCKED"
|
|
____exports.QuestState.FAILED = 4
|
|
____exports.QuestState[____exports.QuestState.FAILED] = "FAILED"
|
|
____exports.QuestEvents = __TS__Class()
|
|
local QuestEvents = ____exports.QuestEvents
|
|
QuestEvents.name = "QuestEvents"
|
|
QuestEvents.____file_path = "scripts/vscripts/quests/QuestSystem.lua"
|
|
function QuestEvents.prototype.____constructor(self)
|
|
end
|
|
function QuestEvents.OnQuestAccepted(self, callback)
|
|
local ____self_onQuestAcceptedCallbacks_0 = self.onQuestAcceptedCallbacks
|
|
____self_onQuestAcceptedCallbacks_0[#____self_onQuestAcceptedCallbacks_0 + 1] = callback
|
|
end
|
|
function QuestEvents.OnQuestCompleted(self, callback)
|
|
local ____self_onQuestCompletedCallbacks_1 = self.onQuestCompletedCallbacks
|
|
____self_onQuestCompletedCallbacks_1[#____self_onQuestCompletedCallbacks_1 + 1] = callback
|
|
end
|
|
function QuestEvents.FireQuestAccepted(self, data)
|
|
__TS__ArrayForEach(
|
|
self.onQuestAcceptedCallbacks,
|
|
function(____, callback) return callback(nil, data) end
|
|
)
|
|
end
|
|
function QuestEvents.FireQuestCompleted(self, data)
|
|
__TS__ArrayForEach(
|
|
self.onQuestCompletedCallbacks,
|
|
function(____, callback) return callback(nil, data) end
|
|
)
|
|
end
|
|
QuestEvents.onQuestAcceptedCallbacks = {}
|
|
QuestEvents.onQuestCompletedCallbacks = {}
|
|
local DOTA_ModifyGold_Unspecified = 0
|
|
local DOTA_ModifyXP_Unspecified = 0
|
|
____exports.QuestSystem = __TS__Class()
|
|
local QuestSystem = ____exports.QuestSystem
|
|
QuestSystem.name = "QuestSystem"
|
|
QuestSystem.____file_path = "scripts/vscripts/quests/QuestSystem.lua"
|
|
function QuestSystem.prototype.____constructor(self)
|
|
self.quests = __TS__New(Map)
|
|
self.npcQuests = __TS__New(Map)
|
|
self.processedItems = __TS__New(Set)
|
|
self.questItems = __TS__New(Map)
|
|
self.initialized = false
|
|
self.questMenuOpenNpcByPlayer = __TS__New(Map)
|
|
self:initializeEventListeners()
|
|
end
|
|
function QuestSystem.getInstance(self)
|
|
if not ____exports.QuestSystem.instance then
|
|
____exports.QuestSystem.instance = __TS__New(____exports.QuestSystem)
|
|
end
|
|
return ____exports.QuestSystem.instance
|
|
end
|
|
function QuestSystem.prototype.registerQuest(self, quest)
|
|
self.quests:set(quest.id, quest)
|
|
self.initialized = true
|
|
end
|
|
function QuestSystem.prototype.linkQuestChains(self)
|
|
self.quests:forEach(function(____, quest)
|
|
if not quest.previousQuestId then
|
|
return
|
|
end
|
|
local previousQuest = self.quests:get(quest.previousQuestId)
|
|
if not previousQuest then
|
|
return
|
|
end
|
|
local questNpc = self:getNpcForQuest(quest.id)
|
|
local previousNpc = self:getNpcForQuest(previousQuest.id)
|
|
if questNpc and questNpc == previousNpc then
|
|
previousQuest.nextQuestId = quest.id
|
|
end
|
|
end)
|
|
end
|
|
function QuestSystem.prototype.initializeEventListeners(self)
|
|
CustomGameEventManager:RegisterListener(
|
|
"request_quests_data",
|
|
function(source, event)
|
|
local npcName = event.npcName
|
|
local player = PlayerResource:GetPlayer(event.PlayerID)
|
|
if not player then
|
|
return
|
|
end
|
|
if npcName then
|
|
local questsData = self:getQuestsForUI(npcName)
|
|
CustomGameEventManager:Send_ServerToPlayer(player, "quests_update", {quests = questsData, npcName = npcName, playerId = event.PlayerID})
|
|
return
|
|
end
|
|
local acceptedQuestsData = self:getAcceptedQuestsForUI()
|
|
CustomGameEventManager:Send_ServerToPlayer(player, "quests_update", {quests = acceptedQuestsData, playerId = event.PlayerID})
|
|
end
|
|
)
|
|
CustomGameEventManager:RegisterListener(
|
|
"quest_action",
|
|
function(source, event)
|
|
if event and event.questId and event.action == "accept" then
|
|
local playerId = event.PlayerID or source
|
|
if not PlayerResource:IsValidPlayerID(playerId) then
|
|
return
|
|
end
|
|
self:startQuest(playerId, event.questId)
|
|
local npcName = self:getNpcForQuest(event.questId)
|
|
if npcName then
|
|
local player = PlayerResource:GetPlayer(playerId)
|
|
if player then
|
|
local questsData = self:getQuestsForUI(npcName)
|
|
CustomGameEventManager:Send_ServerToPlayer(player, "quests_update", {quests = questsData, npcName = npcName, playerId = playerId})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
)
|
|
CustomGameEventManager:RegisterListener(
|
|
"quests_client_ui_state",
|
|
function(_source, event)
|
|
local playerId = event.PlayerID
|
|
if playerId == nil or playerId < 0 then
|
|
return
|
|
end
|
|
local open = event.open == 1 or event.open == true
|
|
local rawNpc = event.npcName or ""
|
|
if open then
|
|
self.questMenuOpenNpcByPlayer:set(playerId, rawNpc ~= "" and rawNpc or "*")
|
|
else
|
|
self.questMenuOpenNpcByPlayer:delete(playerId)
|
|
end
|
|
end
|
|
)
|
|
ListenToGameEvent(
|
|
"entity_killed",
|
|
function(event)
|
|
local unit = EntIndexToHScript(event.entindex_killed)
|
|
if unit and unit:IsBaseNPC() then
|
|
self:OnNpcKilled(unit)
|
|
end
|
|
end,
|
|
nil
|
|
)
|
|
ListenToGameEvent(
|
|
"dota_item_picked_up",
|
|
function(event)
|
|
self:OnItemPickedUp(event)
|
|
end,
|
|
nil
|
|
)
|
|
end
|
|
function QuestSystem.prototype.startQuest(self, playerId, questId)
|
|
local quest = self.quests:get(questId)
|
|
if not quest then
|
|
return
|
|
end
|
|
if not self:isQuestAvailable(questId) then
|
|
return
|
|
end
|
|
quest.state = ____exports.QuestState.IN_PROGRESS
|
|
____exports.QuestEvents:FireQuestAccepted({questId = questId, playerId = playerId})
|
|
local ____opt_4 = quest.events
|
|
local ____opt_2 = ____opt_4 and ____opt_4.onAccept
|
|
if ____opt_2 ~= nil then
|
|
____opt_2(____opt_4)
|
|
end
|
|
local npcName = self:getNpcForQuest(questId)
|
|
if npcName then
|
|
self:updateUI(npcName, playerId)
|
|
end
|
|
end
|
|
function QuestSystem.prototype.isPreviousQuestRequirementMet(self, quest)
|
|
if not quest.previousQuestId then
|
|
return true
|
|
end
|
|
local previousQuest = self.quests:get(quest.previousQuestId)
|
|
if not previousQuest then
|
|
return false
|
|
end
|
|
if previousQuest.state == ____exports.QuestState.COMPLETED then
|
|
return true
|
|
end
|
|
local ____temp_8 = previousQuest.state == ____exports.QuestState.AVAILABLE
|
|
if ____temp_8 then
|
|
local ____opt_6 = previousQuest.unlocksQuestIds
|
|
____temp_8 = ____opt_6 and __TS__ArrayIncludes(previousQuest.unlocksQuestIds, quest.id)
|
|
end
|
|
if ____temp_8 then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
function QuestSystem.prototype.isQuestAvailable(self, questId)
|
|
local quest = self.quests:get(questId)
|
|
if not quest or quest.state ~= ____exports.QuestState.AVAILABLE then
|
|
return false
|
|
end
|
|
return self:isPreviousQuestRequirementMet(quest)
|
|
end
|
|
function QuestSystem.prototype.updateQuestProgress(self, ____type, target, playerID, data)
|
|
self.quests:forEach(function(____, quest, questId)
|
|
if quest.state ~= ____exports.QuestState.IN_PROGRESS then
|
|
return
|
|
end
|
|
local questDirty = false
|
|
__TS__ArrayForEach(
|
|
__TS__ObjectEntries(quest.objectives),
|
|
function(____, ____bindingPattern0)
|
|
local objective
|
|
local objectiveId = ____bindingPattern0[1]
|
|
objective = ____bindingPattern0[2]
|
|
local objectiveChanged = false
|
|
if objective.type == ____exports.QuestType.CUSTOM and objective.customHandler then
|
|
objective.customHandler:onProgress(data)
|
|
objectiveChanged = true
|
|
elseif objective.type == ____type then
|
|
local ____Array_isArray_result_9
|
|
if __TS__ArrayIsArray(objective.target) then
|
|
____Array_isArray_result_9 = __TS__ArrayIncludes(objective.target, target)
|
|
else
|
|
____Array_isArray_result_9 = objective.target == target
|
|
end
|
|
local isTargetMatch = ____Array_isArray_result_9
|
|
if isTargetMatch and objective.current < objective.required then
|
|
objective.current = objective.current + 1
|
|
objectiveChanged = true
|
|
end
|
|
end
|
|
if objectiveChanged then
|
|
questDirty = true
|
|
self:checkQuestCompletion(quest)
|
|
end
|
|
end
|
|
)
|
|
if questDirty then
|
|
local npcName = self:getNpcForQuest(quest.id) or ""
|
|
if npcName ~= nil then
|
|
self:updateUI(npcName, playerID)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
function QuestSystem.prototype.checkQuestCompletion(self, quest)
|
|
local allCompleted = __TS__ArrayEvery(
|
|
__TS__ObjectValues(quest.objectives),
|
|
function(____, objective) return objective.current >= objective.required end
|
|
)
|
|
if allCompleted and quest.state == ____exports.QuestState.IN_PROGRESS then
|
|
quest.state = ____exports.QuestState.COMPLETED
|
|
print("[QuestSystem] FireQuestCompleted: questId=" .. quest.id)
|
|
____exports.QuestEvents:FireQuestCompleted({questId = quest.id, playerId = 0})
|
|
local ____opt_12 = quest.events
|
|
local ____opt_10 = ____opt_12 and ____opt_12.onComplete
|
|
if ____opt_10 ~= nil then
|
|
____opt_10(____opt_12)
|
|
end
|
|
self:giveRewards(quest)
|
|
self:clearCollectedItems(quest)
|
|
self:unlockLinkedQuests(quest)
|
|
end
|
|
end
|
|
function QuestSystem.prototype.unlockLinkedQuests(self, quest)
|
|
local npcsToUpdate = __TS__New(Set)
|
|
local questIdsToUnlock = {}
|
|
if quest.nextQuestId then
|
|
questIdsToUnlock[#questIdsToUnlock + 1] = quest.nextQuestId
|
|
end
|
|
if quest.unlocksQuestIds then
|
|
__TS__ArrayPushArray(questIdsToUnlock, quest.unlocksQuestIds)
|
|
end
|
|
for ____, questId in ipairs(questIdsToUnlock) do
|
|
local linkedQuest = self.quests:get(questId)
|
|
if linkedQuest and linkedQuest.state == ____exports.QuestState.LOCKED then
|
|
linkedQuest.state = ____exports.QuestState.AVAILABLE
|
|
local npcName = self:getNpcForQuest(questId)
|
|
if npcName then
|
|
npcsToUpdate:add(npcName)
|
|
end
|
|
end
|
|
end
|
|
for ____, npcName in __TS__Iterator(npcsToUpdate) do
|
|
self:updateUI(npcName, 0)
|
|
end
|
|
end
|
|
function QuestSystem.prototype.repairStuckQuestUnlocks(self)
|
|
self.quests:forEach(function(____, quest)
|
|
if quest.state ~= ____exports.QuestState.LOCKED or not quest.previousQuestId then
|
|
return
|
|
end
|
|
local previousQuest = self.quests:get(quest.previousQuestId)
|
|
if (previousQuest and previousQuest.state) == ____exports.QuestState.COMPLETED then
|
|
quest.state = ____exports.QuestState.AVAILABLE
|
|
end
|
|
end)
|
|
end
|
|
function QuestSystem.prototype.shouldShowQuestInNpcUI(self, quest)
|
|
repeat
|
|
local ____switch72 = quest.state
|
|
local previousQuest
|
|
local ____cond72 = ____switch72 == ____exports.QuestState.AVAILABLE
|
|
if ____cond72 then
|
|
return self:isPreviousQuestRequirementMet(quest)
|
|
end
|
|
____cond72 = ____cond72 or (____switch72 == ____exports.QuestState.IN_PROGRESS or ____switch72 == ____exports.QuestState.COMPLETED or ____switch72 == ____exports.QuestState.FAILED)
|
|
if ____cond72 then
|
|
return true
|
|
end
|
|
____cond72 = ____cond72 or ____switch72 == ____exports.QuestState.LOCKED
|
|
if ____cond72 then
|
|
if not quest.previousQuestId then
|
|
return false
|
|
end
|
|
previousQuest = self.quests:get(quest.previousQuestId)
|
|
return (previousQuest and previousQuest.state) == ____exports.QuestState.COMPLETED
|
|
end
|
|
do
|
|
return false
|
|
end
|
|
until true
|
|
end
|
|
function QuestSystem.prototype.resetQuest(self, questId)
|
|
local quest = self.quests:get(questId)
|
|
if not quest then
|
|
return
|
|
end
|
|
__TS__ArrayForEach(
|
|
__TS__ObjectValues(quest.objectives),
|
|
function(____, objective)
|
|
objective.current = 0
|
|
end
|
|
)
|
|
quest.state = ____exports.QuestState.AVAILABLE
|
|
local npcName = self:getNpcForQuest(questId) or ""
|
|
self:updateUI(npcName, 0)
|
|
end
|
|
function QuestSystem.prototype.getRewardPlayerIds(self)
|
|
local ids = collectStatsEligiblePlayerIds(nil)
|
|
if #ids > 0 then
|
|
return ids
|
|
end
|
|
do
|
|
local playerID = 0
|
|
while playerID < DOTA_MAX_TEAM_PLAYERS do
|
|
do
|
|
local pid = playerID
|
|
if not PlayerResource:IsValidPlayerID(pid) then
|
|
goto __continue79
|
|
end
|
|
if PlayerResource:GetTeam(pid) ~= DOTA_TEAM_GOODGUYS then
|
|
goto __continue79
|
|
end
|
|
return {pid}
|
|
end
|
|
::__continue79::
|
|
playerID = playerID + 1
|
|
end
|
|
end
|
|
return {}
|
|
end
|
|
function QuestSystem.prototype.giveRewards(self, quest)
|
|
local playerIds = self:getRewardPlayerIds()
|
|
local playerCount = math.max(1, #playerIds)
|
|
local goldSplitCount = getQuestRewardSplitCount(nil, playerCount)
|
|
local goldParts = splitQuestTeamReward(nil, quest.rewards.gold or 0, goldSplitCount)
|
|
local xpParts = splitQuestTeamReward(nil, quest.rewards.experience or 0, playerCount)
|
|
local crystalParts = splitQuestTeamReward(nil, quest.rewards.crystals or 0, playerCount)
|
|
local crystalCurrency = CrystalCurrency:getInstance()
|
|
do
|
|
local i = 0
|
|
while i < #playerIds do
|
|
local playerID = playerIds[i + 1]
|
|
local hero = PlayerResource:GetSelectedHeroEntity(playerID)
|
|
local gold = goldParts[i + 1] or 0
|
|
if gold > 0 and hero then
|
|
hero:ModifyGold(gold, true, DOTA_ModifyGold_Unspecified)
|
|
end
|
|
local xp = xpParts[i + 1] or 0
|
|
if xp > 0 and hero then
|
|
hero:AddExperience(xp, DOTA_ModifyXP_Unspecified, false, true)
|
|
end
|
|
local crystals = crystalParts[i + 1] or 0
|
|
if crystals > 0 then
|
|
crystalCurrency:addCrystals(playerID, crystals)
|
|
end
|
|
if hero then
|
|
local madstone = CreateItem("item_madstone_bundle", nil, hero)
|
|
if madstone then
|
|
hero:AddItem(madstone)
|
|
end
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
function QuestSystem.prototype.getVisibleQuests(self)
|
|
local visibleQuests = {}
|
|
local startingQuests = __TS__ArrayFilter(
|
|
__TS__ArrayFrom(self.quests:values()),
|
|
function(____, quest) return not quest.previousQuestId end
|
|
)
|
|
for ____, startQuest in ipairs(startingQuests) do
|
|
local currentQuest = startQuest
|
|
while currentQuest do
|
|
visibleQuests[#visibleQuests + 1] = currentQuest
|
|
if currentQuest.state ~= ____exports.QuestState.COMPLETED then
|
|
break
|
|
end
|
|
if currentQuest.nextQuestId then
|
|
currentQuest = self.quests:get(currentQuest.nextQuestId)
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
return visibleQuests
|
|
end
|
|
function QuestSystem.prototype.registerNpcQuests(self, npcName, questIds)
|
|
self.npcQuests:set(npcName, questIds)
|
|
end
|
|
function QuestSystem.prototype.getQuestsForNpc(self, npcName)
|
|
local questIds = self.npcQuests:get(npcName) or ({})
|
|
local quests = __TS__ArrayFilter(
|
|
__TS__ArrayMap(
|
|
questIds,
|
|
function(____, id)
|
|
local quest = self.quests:get(id)
|
|
return quest
|
|
end
|
|
),
|
|
function(____, quest)
|
|
return quest ~= nil and (quest.state == ____exports.QuestState.AVAILABLE or quest.state == ____exports.QuestState.LOCKED or quest.state == ____exports.QuestState.IN_PROGRESS or quest.state == ____exports.QuestState.COMPLETED)
|
|
end
|
|
)
|
|
return quests
|
|
end
|
|
function QuestSystem.prototype.getQuestsForUI(self, npcName)
|
|
local questsData = {}
|
|
if not self.initialized or not npcName then
|
|
return questsData
|
|
end
|
|
self:repairStuckQuestUnlocks()
|
|
local npcQuestIds = self.npcQuests:get(npcName) or ({})
|
|
for ____, questId in ipairs(npcQuestIds) do
|
|
local quest = self.quests:get(questId)
|
|
if quest and self:shouldShowQuestInNpcUI(quest) then
|
|
questsData[questId] = quest
|
|
end
|
|
end
|
|
return questsData
|
|
end
|
|
function QuestSystem.prototype.getAcceptedQuestsForUI(self)
|
|
local questsData = {}
|
|
if not self.initialized then
|
|
return questsData
|
|
end
|
|
self.quests:forEach(function(____, quest, id)
|
|
if quest.state == ____exports.QuestState.IN_PROGRESS or quest.state == ____exports.QuestState.COMPLETED then
|
|
questsData[id] = quest
|
|
end
|
|
end)
|
|
return questsData
|
|
end
|
|
function QuestSystem.prototype.getNpcForQuest(self, questId)
|
|
for ____, ____value in __TS__Iterator(self.npcQuests:entries()) do
|
|
local npcName = ____value[1]
|
|
local questIds = ____value[2]
|
|
if __TS__ArrayIncludes(questIds, questId) then
|
|
return npcName
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
function QuestSystem.prototype.updateUI(self, npcName, playerId)
|
|
if not npcName then
|
|
return
|
|
end
|
|
local questsData = self:getQuestsForUI(npcName)
|
|
do
|
|
local i = 0
|
|
while i < DOTA_MAX_TEAM_PLAYERS do
|
|
do
|
|
if not PlayerResource:IsValidPlayerID(i) or PlayerResource:IsFakeClient(i) then
|
|
goto __continue116
|
|
end
|
|
local openFor = self.questMenuOpenNpcByPlayer:get(i)
|
|
if openFor == nil then
|
|
goto __continue116
|
|
end
|
|
if openFor ~= "*" and openFor ~= npcName then
|
|
goto __continue116
|
|
end
|
|
local player = PlayerResource:GetPlayer(i)
|
|
if player then
|
|
CustomGameEventManager:Send_ServerToPlayer(player, "quests_update", {quests = questsData, npcName = npcName, playerId = i})
|
|
end
|
|
end
|
|
::__continue116::
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
function QuestSystem.prototype.OnNpcKilled(self, unit)
|
|
local unitName = unit:GetUnitName()
|
|
self:updateQuestProgress(____exports.QuestType.KILL_UNIT, unitName, 0)
|
|
end
|
|
function QuestSystem.prototype.OnItemPickedUp(self, event)
|
|
local itemEntity = EntIndexToHScript(event.ItemEntityIndex)
|
|
if not itemEntity then
|
|
return
|
|
end
|
|
local itemName = itemEntity:GetAbilityName()
|
|
local itemHandle = itemEntity:GetEntityHandle()
|
|
if self.processedItems:has(itemHandle) then
|
|
return
|
|
end
|
|
local targetQuestId
|
|
self.quests:forEach(function(____, quest, questId)
|
|
if quest.state == ____exports.QuestState.IN_PROGRESS then
|
|
__TS__ArrayForEach(
|
|
__TS__ObjectValues(quest.objectives),
|
|
function(____, objective)
|
|
if objective.type == ____exports.QuestType.COLLECT_ITEM and objective.target == itemName then
|
|
targetQuestId = questId
|
|
end
|
|
end
|
|
)
|
|
end
|
|
end)
|
|
if targetQuestId then
|
|
if not self.questItems:has(targetQuestId) then
|
|
self.questItems:set(
|
|
targetQuestId,
|
|
__TS__New(Set)
|
|
)
|
|
end
|
|
self.questItems:get(targetQuestId):add(itemEntity)
|
|
end
|
|
self:updateQuestProgress(____exports.QuestType.COLLECT_ITEM, itemName, 0)
|
|
self.processedItems:add(itemHandle)
|
|
end
|
|
function QuestSystem.prototype.clearCollectedItems(self, quest)
|
|
local items = self.questItems:get(quest.id)
|
|
if items then
|
|
items:forEach(function(____, item)
|
|
do
|
|
local ____try, ____hasReturned, ____returnValue = pcall(function()
|
|
if not item or item:IsNull() then
|
|
return true
|
|
end
|
|
local itemName
|
|
do
|
|
local function ____catch(e)
|
|
return true
|
|
end
|
|
local ____try, ____hasReturned, ____returnValue = pcall(function()
|
|
itemName = item:GetAbilityName()
|
|
end)
|
|
if not ____try then
|
|
____hasReturned, ____returnValue = ____catch(____hasReturned)
|
|
end
|
|
if ____hasReturned then
|
|
return true, ____returnValue
|
|
end
|
|
end
|
|
do
|
|
pcall(function()
|
|
local container = item:GetContainer()
|
|
if container and not container:IsNull() then
|
|
local hero = container:GetOwner()
|
|
if hero and not hero:IsNull() then
|
|
hero:RemoveItem(item)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
do
|
|
pcall(function()
|
|
if not item:IsNull() then
|
|
local itemPos = item:GetAbsOrigin()
|
|
if itemPos ~= nil then
|
|
local itemPhysical = findNearestByClassname("dota_item_drop", itemPos, 100)
|
|
if itemPhysical and not itemPhysical:IsNull() then
|
|
local containedItem = itemPhysical:GetContainedItem()
|
|
if containedItem and not containedItem:IsNull() and containedItem:GetEntityHandle() == item:GetEntityHandle() then
|
|
itemPhysical:RemoveSelf()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
do
|
|
pcall(function()
|
|
if not item:IsNull() then
|
|
item:RemoveSelf()
|
|
end
|
|
end)
|
|
end
|
|
end)
|
|
if ____try and ____hasReturned then
|
|
return ____returnValue
|
|
end
|
|
end
|
|
end)
|
|
self.questItems:delete(quest.id)
|
|
end
|
|
self.processedItems:clear()
|
|
end
|
|
function QuestSystem.prototype.triggerCustomProgress(self, questId, data)
|
|
local quest = self.quests:get(questId)
|
|
if not quest or quest.state ~= ____exports.QuestState.IN_PROGRESS then
|
|
return
|
|
end
|
|
self:updateQuestProgress(____exports.QuestType.CUSTOM, "", 0, data)
|
|
end
|
|
function QuestSystem.prototype.addQuestProgress(self, questId, objectiveId, amount)
|
|
if amount == nil then
|
|
amount = 1
|
|
end
|
|
local quest = self.quests:get(questId)
|
|
if not quest or quest.state ~= ____exports.QuestState.IN_PROGRESS then
|
|
return
|
|
end
|
|
local objective = quest.objectives[objectiveId]
|
|
if not objective then
|
|
return
|
|
end
|
|
local nextCurrent = math.min(objective.current + amount, objective.required)
|
|
if nextCurrent == objective.current then
|
|
return
|
|
end
|
|
objective.current = nextCurrent
|
|
self:checkQuestCompletion(quest)
|
|
self:updateUI(
|
|
self:getNpcForQuest(questId) or "",
|
|
0
|
|
)
|
|
end
|
|
function QuestSystem.prototype.setQuestProgress(self, questId, objectiveId, value, updateUI)
|
|
if updateUI == nil then
|
|
updateUI = true
|
|
end
|
|
local quest = self.quests:get(questId)
|
|
if not quest or quest.state ~= ____exports.QuestState.IN_PROGRESS then
|
|
return
|
|
end
|
|
local objective = quest.objectives[objectiveId]
|
|
if not objective then
|
|
return
|
|
end
|
|
local nextCurrent = math.min(
|
|
math.max(0, value),
|
|
objective.required
|
|
)
|
|
if nextCurrent == objective.current then
|
|
return
|
|
end
|
|
objective.current = nextCurrent
|
|
self:checkQuestCompletion(quest)
|
|
if updateUI then
|
|
self:updateUI(
|
|
self:getNpcForQuest(questId) or "",
|
|
0
|
|
)
|
|
end
|
|
end
|
|
function QuestSystem.prototype.setObjectiveRequired(self, questId, objectiveId, required, updateUI)
|
|
if updateUI == nil then
|
|
updateUI = true
|
|
end
|
|
local quest = self.quests:get(questId)
|
|
if not quest then
|
|
return
|
|
end
|
|
local objective = quest.objectives[objectiveId]
|
|
if not objective then
|
|
return
|
|
end
|
|
local nextRequired = math.max(
|
|
1,
|
|
math.floor(required)
|
|
)
|
|
objective.required = nextRequired
|
|
if objective.current > nextRequired then
|
|
objective.current = nextRequired
|
|
end
|
|
if updateUI then
|
|
self:updateUI(
|
|
self:getNpcForQuest(questId) or "",
|
|
0
|
|
)
|
|
end
|
|
end
|
|
function QuestSystem.prototype.failQuest(self, questId)
|
|
local quest = self.quests:get(questId)
|
|
if not quest or quest.state == ____exports.QuestState.COMPLETED then
|
|
return
|
|
end
|
|
quest.state = ____exports.QuestState.FAILED
|
|
local ____opt_18 = quest.events
|
|
if ____opt_18 and ____opt_18.onFail then
|
|
quest.events:onFail()
|
|
end
|
|
CustomGameEventManager:Send_ServerToAllClients("quest_failed", {questId = quest.id})
|
|
self:updateUI(
|
|
self:getNpcForQuest(questId) or "",
|
|
0
|
|
)
|
|
end
|
|
function QuestSystem.prototype.getQuestProgress(self, questId, objectiveId)
|
|
local quest = self.quests:get(questId)
|
|
if not quest then
|
|
return 0
|
|
end
|
|
local objective = quest.objectives[objectiveId]
|
|
if not objective then
|
|
return 0
|
|
end
|
|
return objective.current
|
|
end
|
|
return ____exports
|