262 lines
9.4 KiB
Lua
262 lines
9.4 KiB
Lua
local ____lualib = require("lualib_bundle")
|
|
local __TS__Class = ____lualib.__TS__Class
|
|
local __TS__New = ____lualib.__TS__New
|
|
local __TS__ArrayFind = ____lualib.__TS__ArrayFind
|
|
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
|
|
local ____exports = {}
|
|
local ____DayNightCycleManager = require("DayNightCycleManager")
|
|
local DayNightCycleManager = ____DayNightCycleManager.DayNightCycleManager
|
|
____exports.RandomEventsManager = __TS__Class()
|
|
local RandomEventsManager = ____exports.RandomEventsManager
|
|
RandomEventsManager.name = "RandomEventsManager"
|
|
RandomEventsManager.____file_path = "scripts/vscripts/events/random_events.lua"
|
|
function RandomEventsManager.prototype.____constructor(self)
|
|
self.events = {}
|
|
self.gameTimer = 0
|
|
self.nextEventTime = 0
|
|
self:registerEvents()
|
|
self:startEventLoop()
|
|
end
|
|
function RandomEventsManager.getInstance(self)
|
|
if not ____exports.RandomEventsManager.instance then
|
|
____exports.RandomEventsManager.instance = __TS__New(____exports.RandomEventsManager)
|
|
end
|
|
return ____exports.RandomEventsManager.instance
|
|
end
|
|
function RandomEventsManager.prototype.registerEvents(self)
|
|
self.events = {
|
|
{
|
|
name = "gold_rush",
|
|
chance = 0.1,
|
|
minInterval = 600,
|
|
maxInterval = 3600,
|
|
duration = 45,
|
|
execute = function() return self:startGoldRush() end
|
|
},
|
|
{
|
|
name = "midas_hands",
|
|
chance = 0.1,
|
|
minInterval = 1200,
|
|
maxInterval = 2400,
|
|
duration = 25,
|
|
execute = function() return self:StartMidasHands() end
|
|
}
|
|
}
|
|
end
|
|
function RandomEventsManager.prototype.startEventLoop(self)
|
|
Timers:CreateTimer(function()
|
|
self.gameTimer = self.gameTimer + 1
|
|
if self.gameTimer % 60 == 0 then
|
|
local dayNightManager = DayNightCycleManager:getInstance()
|
|
local isDaytime = dayNightManager:IsDaytime()
|
|
if isDaytime then
|
|
self:triggerRandomEvent()
|
|
end
|
|
end
|
|
return 1
|
|
end)
|
|
end
|
|
function RandomEventsManager.prototype.checkAndTriggerEvents(self)
|
|
if self.gameTimer >= self.nextEventTime then
|
|
local dayNightManager = DayNightCycleManager:getInstance()
|
|
if dayNightManager:IsDaytime() then
|
|
self:triggerRandomEvent()
|
|
end
|
|
local randomEvent = self:getRandomEvent()
|
|
if randomEvent then
|
|
self.nextEventTime = self.gameTimer + RandomInt(randomEvent.minInterval, randomEvent.maxInterval)
|
|
end
|
|
end
|
|
end
|
|
function RandomEventsManager.prototype.getRandomEvent(self)
|
|
local roll = RandomInt(1, 100)
|
|
local chanceSum = 0
|
|
for ____, event in ipairs(self.events) do
|
|
chanceSum = chanceSum + event.chance
|
|
if roll <= chanceSum then
|
|
return event
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
function RandomEventsManager.prototype.triggerRandomEvent(self)
|
|
local event = self:getRandomEvent()
|
|
if event then
|
|
event:execute()
|
|
end
|
|
end
|
|
function RandomEventsManager.prototype.sendEventNotification(self, eventName, duration, description)
|
|
CustomGameEventManager:Send_ServerToAllClients("random_event_started", {event_name = eventName, duration = duration, description = description})
|
|
end
|
|
function RandomEventsManager.prototype.startGoldRush(self)
|
|
local event = __TS__ArrayFind(
|
|
self.events,
|
|
function(____, e) return e.name == "gold_rush" end
|
|
)
|
|
local duration = 45
|
|
self:sendEventNotification("#event_gold_rush", duration, "#event_gold_rush_description")
|
|
local numGoldPiles = 10 * PlayerResource:GetPlayerCountForTeam(DOTA_TEAM_GOODGUYS)
|
|
local currentPile = 0
|
|
local spawnNextGold
|
|
spawnNextGold = function()
|
|
if currentPile >= numGoldPiles then
|
|
return
|
|
end
|
|
local heroes = FindUnitsInRadius(
|
|
DOTA_TEAM_GOODGUYS,
|
|
Vector(0, 0, 0),
|
|
nil,
|
|
FIND_UNITS_EVERYWHERE,
|
|
DOTA_UNIT_TARGET_TEAM_FRIENDLY,
|
|
DOTA_UNIT_TARGET_HERO,
|
|
DOTA_UNIT_TARGET_FLAG_NONE,
|
|
FIND_ANY_ORDER,
|
|
false
|
|
)
|
|
if #heroes > 0 then
|
|
local randomHero = heroes[RandomInt(0, #heroes - 1) + 1]
|
|
local heroPos = randomHero:GetAbsOrigin()
|
|
local spawnDistance = RandomFloat(300, 800)
|
|
local randomAngle = RandomFloat(0, 2 * math.pi)
|
|
local randomX = heroPos.x + spawnDistance * math.cos(randomAngle)
|
|
local randomY = heroPos.y + spawnDistance * math.sin(randomAngle)
|
|
local location = Vector(randomX, randomY, 0)
|
|
local groundHeight = GetGroundHeight(location, nil)
|
|
local spawnPos = Vector(randomX, randomY)
|
|
local item = CreateItem("item_bag_of_gold", nil, nil)
|
|
if item ~= nil then
|
|
local container = CreateItemOnPositionSync(spawnPos, item)
|
|
local dropRadius = RandomFloat(50, 100)
|
|
item:LaunchLootInitialHeight(
|
|
false,
|
|
1000,
|
|
150,
|
|
1,
|
|
spawnPos + RandomVector(dropRadius)
|
|
)
|
|
if container ~= nil then
|
|
Timers:CreateTimer(
|
|
30,
|
|
function()
|
|
if IsValidEntity(container) then
|
|
container:RemoveSelf()
|
|
end
|
|
end
|
|
)
|
|
currentPile = currentPile + 1
|
|
Timers:CreateTimer(
|
|
duration / numGoldPiles,
|
|
function() return spawnNextGold(nil) end
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
spawnNextGold(nil)
|
|
GameRules:SendCustomMessage(
|
|
("Золотая лихорадка! (" .. tostring(duration)) .. " сек) Собирайте золото, пока оно не исчезло!",
|
|
0,
|
|
0
|
|
)
|
|
end
|
|
function RandomEventsManager.prototype.StartMidasHands(self)
|
|
local event = __TS__ArrayFind(
|
|
self.events,
|
|
function(____, e) return e.name == "midas_hands" end
|
|
)
|
|
local duration = event and event.duration or 180
|
|
self:sendEventNotification("#event_midas_hands", duration, "#event_midas_hands_description")
|
|
local eventHandler = ListenToGameEvent(
|
|
"entity_killed",
|
|
function(event)
|
|
local killedUnit = EntIndexToHScript(event.entindex_killed)
|
|
if killedUnit and killedUnit:GetTeamNumber() ~= DOTA_TEAM_GOODGUYS then
|
|
local position = killedUnit:GetAbsOrigin()
|
|
if RandomFloat(1, 100) <= 15 then
|
|
local item = CreateItem("item_bag_of_gold", nil, nil)
|
|
if item then
|
|
CreateItemOnPositionSync(position, item)
|
|
local dropRadius = RandomFloat(50, 100)
|
|
item:LaunchLootInitialHeight(
|
|
false,
|
|
0,
|
|
150,
|
|
0.5,
|
|
position + RandomVector(dropRadius)
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end,
|
|
nil
|
|
)
|
|
Timers:CreateTimer(
|
|
duration,
|
|
function()
|
|
StopListeningToGameEvent(eventHandler)
|
|
GameRules:SendCustomMessage("Благословение Мидаса закончилось!", 0, 0)
|
|
end
|
|
)
|
|
GameRules:SendCustomMessage(
|
|
("Благословение Мидаса! (" .. tostring(duration)) .. " сек) После убийства любого врага, вы получите мешок с золотом!",
|
|
0,
|
|
0
|
|
)
|
|
end
|
|
function RandomEventsManager.prototype.createHealingSprings(self)
|
|
local event = __TS__ArrayFind(
|
|
self.events,
|
|
function(____, e) return e.name == "healing_springs" end
|
|
)
|
|
local duration = event and event.duration or 120
|
|
local springLocations = Entities:FindAllByName("spring_point_*")
|
|
local springs = {}
|
|
__TS__ArrayForEach(
|
|
springLocations,
|
|
function(____, location)
|
|
local spring = CreateUnitByName(
|
|
"npc_healing_spring",
|
|
location:GetAbsOrigin(),
|
|
true,
|
|
nil,
|
|
nil,
|
|
DOTA_TEAM_NEUTRALS
|
|
)
|
|
springs[#springs + 1] = spring
|
|
end
|
|
)
|
|
Timers:CreateTimer(
|
|
duration,
|
|
function()
|
|
__TS__ArrayForEach(
|
|
springs,
|
|
function(____, spring)
|
|
if IsValidEntity(spring) then
|
|
spring:RemoveSelf()
|
|
end
|
|
end
|
|
)
|
|
GameRules:SendCustomMessage("Целебные источники иссякли!", 0, 0)
|
|
end
|
|
)
|
|
GameRules:SendCustomMessage(
|
|
("Появились целебные источники! (" .. tostring(duration)) .. " сек) Восстановите здоровье и ману!",
|
|
0,
|
|
0
|
|
)
|
|
end
|
|
function RandomEventsManager.prototype.triggerEvent(self, eventName)
|
|
local dayNightManager = DayNightCycleManager:getInstance()
|
|
if not dayNightManager:IsDaytime() then
|
|
return
|
|
end
|
|
local event = __TS__ArrayFind(
|
|
self.events,
|
|
function(____, e) return e.name == eventName end
|
|
)
|
|
if event then
|
|
event:execute()
|
|
end
|
|
end
|
|
return ____exports
|