edit | blame | history | raw
local Balance = require 'config.balance'

local M = {}

local current_area   = nil
local current_radius = nil
local shrink_timer   = nil
local damage_timer   = nil
local next_shrink_timer = nil

-- ---------------------------------------------------------
-- 启动
-- ---------------------------------------------------------
function M.start()
    current_radius = Balance.CIRCLE_INIT_RADIUS

    local map_area = clicli.area.get_map_area()
    local center   = map_area:get_center_point()

    current_area = clicli.area.create_circle_area(center, current_radius)
    current_area:add_tag('play_zone')

    next_shrink_timer = clicli.timer.wait(Balance.CIRCLE_FIRST_SHRINK, function()
        M.shrink()
    end)
end

-- ---------------------------------------------------------
-- 缩圈
-- ---------------------------------------------------------
function M.shrink()
    if not current_area then return end

    local new_radius = current_radius * Balance.CIRCLE_SHRINK_RATIO
    if new_radius < Balance.CIRCLE_MIN_RADIUS then
        new_radius = Balance.CIRCLE_MIN_RADIUS
    end

    local delta = current_radius - new_radius
    local steps = math.max(1, math.ceil(delta / 0.5))

    shrink_timer = clicli.timer.count_loop(1.0, steps, function(timer, count)
        current_radius = current_radius - 0.5
        if current_radius < new_radius then
            current_radius = new_radius
        end
        current_area:set_radius(current_radius)
    end)

    M.start_damage()

    if current_radius > Balance.CIRCLE_MIN_RADIUS then
        next_shrink_timer = clicli.timer.wait(Balance.CIRCLE_INTERVAL, function()
            M.shrink()
        end)
    end
end

-- ---------------------------------------------------------
-- 区域外持续伤害
-- ---------------------------------------------------------
function M.start_damage()
    if damage_timer then return end

    damage_timer = clicli.timer.loop(2.0, function()
        if not current_area then return end

        local PlayerMgr = require 'core.player_manager'
        for _, pd in ipairs(PlayerMgr.get_all_player_units()) do
            if pd.alive then
                local pos = pd.unit:get_point()
                if not current_area:is_point_in_area(pos) then
                    pd.unit:add_hp(-Balance.CIRCLE_DAMAGE_PER_TICK)
                end
            end
        end
    end, '圈外伤害')
end

-- ---------------------------------------------------------
-- 停止
-- ---------------------------------------------------------
function M.stop()
    if shrink_timer then shrink_timer:remove(); shrink_timer = nil end
    if damage_timer then damage_timer:remove(); damage_timer = nil end
    if next_shrink_timer then next_shrink_timer:remove(); next_shrink_timer = nil end
    if current_area then current_area:remove(); current_area = nil end
end

return M