local BATTLE_PASS_CONSTANTS = { ACTIVATE_COST_YB = 500, -- Цена активации пропуска в юаньбао BUY_EXP_COST_YB = 50, -- Цена покупки опыта в юаньбао EXP_PER_ITEM = 1240, -- Опыт за одну покупку EXP_PER_LEVEL = 2480, -- Опыт для повышения уровня MAX_LEVEL = 100, -- Максимальный уровень пропуска STATUS_NOT_ACTIVE = 0, -- Пропуск не активирован STATUS_ACTIVE = 1 -- Пропуск активирован } -- Имя в комментариях — атрибут name у в data/local/zhCN/attdata/item_name.xml local BATTLE_PASS_REWARDS_CONFIG = { [1] = {0, 0}, [2] = {4530242, 5}, -- Сосредоточение стихий [3] = {3070056, 15}, -- Заказ [перс.] [4] = {3500048, 10}, -- Чудесный кремень темноты [5] = {4810137, 10}, -- Камень сброса [6] = {3030127, 1}, -- Морозный камень [7] = {3070018, 10}, -- Свиток воскрешения [8] = {4400024, 1}, -- Камень истины [9] = {6600466, 1}, -- Проклятая кирка [10] = {4820180, 1}, -- Плейона [11] = {6600979, 3}, -- Кровь дракона [12] = {4820084, 1}, -- Руна Кристалла [13] = {4820047, 3}, -- Черная дыра [14] = {6600412, 1}, -- Печать Артемиды [15] = {3030127, 1}, -- Морозный камень [16] = {4400024, 2}, -- Камень истины [17] = {3050085, 20}, -- Драгоценная пыль [18] = {3500061, 1}, -- Древний кремень темноты [19] = {3500040, 1}, -- Сила поглощений [перс.] [20] = {4820254, 1}, -- Идеальная гравировка [21] = {4820257, 1}, -- Руна тройной награды [перс.] [22] = {3070056, 30}, -- Заказ [перс.] [23] = {6601283, 1}, -- Медальон крови [24] = {4810137, 25}, -- Камень сброса [25] = {3030127, 1}, -- Морозный камень [26] = {4810136, 15}, -- Таинственный камень сброса [27] = {4820256, 1}, -- Книга Астролога [28] = {4820180, 2}, -- Плейона [29] = {4530242, 5}, -- Сосредоточение стихий [30] = {6602498, 1}, -- Куб власти [31] = {6600626, 1}, -- Шкатулка душ эльфов [10 ур.] [32] = {5802632, 1}, -- Священное сияние [9 ур.] [33] = {3500061, 2}, -- Древний кремень темноты [34] = {5802667, 1}, -- Священный свет [9 ур.] [35] = {3030127, 1}, -- Морозный камень [36] = {3500023, 1}, -- Особая руна способностей [37] = {6600412, 2}, -- Печать Артемиды [38] = {4820229, 1}, -- Руна тройной награды [39] = {3010029, 10}, -- Большой эликсир ОЗ [40] = {6602498, 2}, -- Куб власти [41] = {4530242, 10}, -- Сосредоточение стихий [42] = {3500061, 5}, -- Древний кремень темноты [43] = {6600836, 1}, -- Модификатор узора [44] = {3020013, 1}, -- Божественная руна удачи [45] = {4800133, 1}, -- Вход в Храм Аскез [12ч.] [46] = {4400024, 3}, -- Камень истины [47] = {3060060, 2}, -- Эликсир великих способностей [48] = {3030127, 2}, -- Морозный камень [49] = {3030168, 1}, -- Удаление камней [Ур. 9] [50] = {4820254, 1}, -- Идеальная гравировка [51] = {4651101, 1}, -- Верная цель [52] = {5802632, 2}, -- Священное сияние [9 ур.] [53] = {5802667, 2}, -- Священный свет [9 ур.] [54] = {6600979, 10}, -- Кровь дракона [55] = {3030127, 3}, -- Морозный камень [56] = {3010034, 50}, -- Сильное зелье бодрости [57] = {4530242, 25}, -- Сосредоточение стихий [58] = {4820229, 2}, -- Руна тройной награды [59] = {3060058, 1}, -- Крепкий эликсир [60] = {6602498, 5}, -- Куб власти [61] = {3500023, 2}, -- Особая руна способностей [62] = {3030168, 2}, -- Удаление камней [Ур. 9] [63] = {3500208, 1}, -- Ядро души эльфа [110] [64] = {3561001, 1}, -- Клеймо Духа [65] = {4800133, 2}, -- Вход в Храм Аскез [12ч.] [66] = {3020140, 5}, -- Руна стража [+30] [67] = {6600980, 2}, -- Коготь дракона [68] = {3020013, 5}, -- Божественная руна удачи [69] = {4820035, 1}, -- Древние книги [70] = {3020102, 1}, -- Магическое ожерелье +30 [71] = {3500061, 10}, -- Древний кремень темноты [72] = {6602130, 2}, -- Книга астромагии [73] = {3030168, 1}, -- Удаление камней [Ур. 9] [74] = {4820180, 3}, -- Плейона [75] = {5802632, 3}, -- Священное сияние [9 ур.] [76] = {5802667, 3}, -- Священный свет [9 ур.] [77] = {3500208, 2}, -- Ядро души эльфа [110] [78] = {3020017, 1}, -- Мистический ловец душ [79] = {3020102, 1}, -- Магическое ожерелье +30 [80] = {6602498, 10}, -- Куб власти [81] = {6600573, 1}, -- Компас надежды [30 дн.] [82] = {3500023, 3}, -- Особая руна способностей [83] = {3060061, 1}, -- Святой эликсир [84] = {3500209, 1}, -- Ядро души эльфа [120] [85] = {4820049, 1}, -- Печать Ориона [86] = {3050110, 1}, -- Магическая гардеробная [87] = {3030127, 10}, -- Морозный камень [88] = {4400024, 10}, -- Камень истины [89] = {3020126, 1}, -- Камень души +20 [перс.] [90] = {3020102, 1}, -- Магическое ожерелье +30 [91] = {4820254, 1}, -- Идеальная гравировка [92] = {6602498, 3}, -- Куб власти [93] = {3020131, 1}, -- Камень души +25 [перс.] [94] = {4820179, 1}, -- Сила Ориона [95] = {3051616, 3}, -- Вечное сверло [96] = {4810109, 1}, -- Золотая плейона [97] = {4820281, 2}, -- Древняя гравировка [98] = {3020136, 1}, -- Камень души +30 [перс.] [99] = {3500209, 3}, -- Ядро души эльфа [120] [100] = {6602498, 30} -- Куб Власти } function BattlePass_GetConstants() return 0, 0, BATTLE_PASS_CONSTANTS.EXP_PER_ITEM, BATTLE_PASS_CONSTANTS.EXP_PER_LEVEL, BATTLE_PASS_CONSTANTS.MAX_LEVEL, BATTLE_PASS_CONSTANTS.ACTIVATE_COST_YB, BATTLE_PASS_CONSTANTS.BUY_EXP_COST_YB end function BattlePass_GetReward(level) local lv = tonumber(level) or 0 local cfg = BATTLE_PASS_REWARDS_CONFIG[lv] if cfg == nil then return 0, 0 end return tonumber(cfg[1]) or 0, tonumber(cfg[2]) or 0 end function BattlePass_GetState(roleId) local RoleID = tonumber(roleId) or 0 if RoleID <= 0 then return 0, 0, 0, 0, 0, 0 end local exp = role.GetRoleScriptData(RoleID, 1, RoleDataType["Bo_EXP"]) or 0 local hasPass = role.GetRoleScriptData(RoleID, 1, RoleDataType["Bo_Have"]) or 0 local rewardIndex = role.GetRoleScriptData(RoleID, 1, RoleDataType["Bo_Rew"]) or 0 local level = role.GetRoleScriptData(RoleID, 1, RoleDataType["Bo_Level"]) or 0 return hasPass, level, exp, rewardIndex, 0, 0 end local function BattlePass_LevelUp(exp, level) local e = tonumber(exp) or 0 local lv = tonumber(level) or 0 local maxLv = BATTLE_PASS_CONSTANTS.MAX_LEVEL local perLv = BATTLE_PASS_CONSTANTS.EXP_PER_LEVEL if perLv <= 0 then return e, lv end while lv < maxLv and e >= perLv do lv = lv + 1 e = e - perLv end return e, lv end function BattlePass_DoAction(MapID, InstanceID, roleId, action, param) local E_OK = 0 local E_SCRIPT_FAIL = 1 local E_INVALID_PARAM = 2 local E_NOT_ACTIVE = 3 local E_ALREADY_ACTIVE = 4 local E_NO_PASS_ITEM = 5 local E_NO_EXP_ITEM = 6 local E_LEVEL_MAX = 7 local E_REWARD_LOCKED = 8 local EBPA_ACTIVATE = 1 local EBPA_BUY_EXP = 2 local EBPA_CLAIM = 4 local EBPA_BUY_100_LEVELS = 8 local EBPA_CLAIM_ALL_REWARDS = 16 local E_NOT_ENOUGH_YB = 9 local E_INVALID_ROLE_ID = 10 local E_INVALID_REWARD_INDEX = 11 local E_REWARD_INDEX_MISMATCH = 12 local E_UNKNOWN_ACTION = 13 local E_ADD_ITEM_EXCEPTION = 14 local E_ADD_ITEM_FAILED = 15 local map = tonumber(MapID) or 0 local inst = tonumber(InstanceID) or 0 local RoleID = tonumber(roleId) or 0 local act = tonumber(action) or 0 local prm = tonumber(param) or 0 if RoleID <= 0 then return E_INVALID_ROLE_ID, 0, 0, 0, 0, 0, 0 end local hasPass, level, exp, rewardIndex, passItemCount, expItemCount = BattlePass_GetState(RoleID) local err = E_OK if act == EBPA_ACTIVATE then if hasPass ~= BATTLE_PASS_CONSTANTS.STATUS_NOT_ACTIVE then err = E_ALREADY_ACTIVE else local curYB = role.GetRoleYuanbao(map, inst, RoleID) or 0 local cost = BATTLE_PASS_CONSTANTS.ACTIVATE_COST_YB if curYB < cost then err = E_NOT_ENOUGH_YB else role.DecRoleYuanBao(map, inst, RoleID, cost) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_Rew"], 2) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_Level"], 1) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_Have"], BATTLE_PASS_CONSTANTS.STATUS_ACTIVE) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_EXP"], 0) local activateItems = { { 4300003, 1 }, { 3070113, 1 }, { 6600899, 1 }, } local granted = {} for _, pair in ipairs(activateItems) do local itemId, itemCnt = pair[1], pair[2] local ok, addRet = pcall(role.AddRoleItem, map, inst, RoleID, itemId, itemCnt, 6, 1, 420) if not ok then err = E_ADD_ITEM_EXCEPTION break end local addRetNum = (addRet == true) and 1 or ((addRet == false) and 0 or (tonumber(addRet) or 0)) if addRetNum <= 0 then err = E_ADD_ITEM_FAILED break end table.insert(granted, { itemId, itemCnt }) end if err ~= E_OK then for _, g in ipairs(granted) do pcall(role.RemoveFromRole, map, inst, RoleID, g[1], g[2], 420) end role.AddRoleYuanBao(map, inst, RoleID, cost) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_Rew"], 0) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_Level"], 0) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_EXP"], 0) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_Have"], BATTLE_PASS_CONSTANTS.STATUS_NOT_ACTIVE) end end end elseif act == EBPA_BUY_EXP then if hasPass ~= BATTLE_PASS_CONSTANTS.STATUS_ACTIVE then err = E_NOT_ACTIVE elseif level >= BATTLE_PASS_CONSTANTS.MAX_LEVEL then err = E_LEVEL_MAX else local curYB = role.GetRoleYuanbao(map, inst, RoleID) or 0 local cost = BATTLE_PASS_CONSTANTS.BUY_EXP_COST_YB if curYB < cost then err = E_NOT_ENOUGH_YB else role.DecRoleYuanBao(map, inst, RoleID, cost) exp = exp + BATTLE_PASS_CONSTANTS.EXP_PER_ITEM role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_EXP"], exp) exp, level = BattlePass_LevelUp(exp, level) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_Level"], level) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_EXP"], exp) end end elseif act == EBPA_CLAIM then if hasPass ~= BATTLE_PASS_CONSTANTS.STATUS_ACTIVE then err = E_NOT_ACTIVE elseif rewardIndex < 1 or rewardIndex > BATTLE_PASS_CONSTANTS.MAX_LEVEL then err = E_INVALID_REWARD_INDEX elseif prm > 0 and prm ~= rewardIndex then err = E_REWARD_INDEX_MISMATCH elseif level < rewardIndex then err = E_REWARD_LOCKED else local itemData = BATTLE_PASS_REWARDS_CONFIG[rewardIndex] local itemId = 0 local itemCount = 0 if itemData then itemId = tonumber(itemData[1]) or 0 itemCount = tonumber(itemData[2]) or 0 end local addOk = true if itemId > 0 and itemCount > 0 then local ok, addRet = pcall(role.AddRoleItem, map, inst, RoleID, itemId, itemCount, -1, 8, 420) if not ok then err = E_ADD_ITEM_EXCEPTION addOk = false end if addOk then local addRetNum = (addRet == true) and 1 or ((addRet == false) and 0 or (tonumber(addRet) or 0)) if addRetNum <= 0 then err = E_ADD_ITEM_FAILED addOk = false end end end if err == E_OK and addOk then rewardIndex = rewardIndex + 1 role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_Rew"], rewardIndex) end end elseif act == EBPA_BUY_100_LEVELS then if hasPass ~= BATTLE_PASS_CONSTANTS.STATUS_ACTIVE then err = E_NOT_ACTIVE elseif level >= BATTLE_PASS_CONSTANTS.MAX_LEVEL then err = E_LEVEL_MAX else local targetLevel = math.min(level + 100, BATTLE_PASS_CONSTANTS.MAX_LEVEL) local levelsToBuy = targetLevel - level local totalExpNeeded = levelsToBuy * BATTLE_PASS_CONSTANTS.EXP_PER_LEVEL local expItemsNeeded = math.ceil(totalExpNeeded / BATTLE_PASS_CONSTANTS.EXP_PER_ITEM) local totalCost = expItemsNeeded * BATTLE_PASS_CONSTANTS.BUY_EXP_COST_YB local curYB = role.GetRoleYuanbao(map, inst, RoleID) or 0 if curYB < totalCost then err = E_NOT_ENOUGH_YB else role.DecRoleYuanBao(map, inst, RoleID, totalCost) exp = exp + (expItemsNeeded * BATTLE_PASS_CONSTANTS.EXP_PER_ITEM) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_EXP"], exp) exp, level = BattlePass_LevelUp(exp, level) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_Level"], level) role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_EXP"], exp) end end elseif act == EBPA_CLAIM_ALL_REWARDS then if hasPass ~= BATTLE_PASS_CONSTANTS.STATUS_ACTIVE then err = E_NOT_ACTIVE elseif rewardIndex < 1 or rewardIndex > BATTLE_PASS_CONSTANTS.MAX_LEVEL then err = E_INVALID_REWARD_INDEX elseif level < rewardIndex then err = E_REWARD_LOCKED else -- Зачисляем все доступные награды от rewardIndex до level включительно local newRewardIndex = rewardIndex for claimLevel = rewardIndex, level do if claimLevel > BATTLE_PASS_CONSTANTS.MAX_LEVEL then break end local itemData = BATTLE_PASS_REWARDS_CONFIG[claimLevel] local itemId = 0 local itemCount = 0 if itemData then itemId = tonumber(itemData[1]) or 0 itemCount = tonumber(itemData[2]) or 0 end if itemId > 0 and itemCount > 0 then local ok, addRet = pcall(role.AddRoleItem, map, inst, RoleID, itemId, itemCount, -1, 8, 420) if not ok then err = E_ADD_ITEM_EXCEPTION break end local addRetNum = (addRet == true) and 1 or ((addRet == false) and 0 or (tonumber(addRet) or 0)) if addRetNum <= 0 then err = E_ADD_ITEM_FAILED break end newRewardIndex = claimLevel + 1 else newRewardIndex = claimLevel + 1 end end -- Частичная выдача: при полном инвентаре уже выданное должно засчитаться, иначе -- Bo_Rew не сдвигается — UI врёт и «Получить награды» выдаёт дубликаты. if newRewardIndex > rewardIndex or err == E_OK then if newRewardIndex > BATTLE_PASS_CONSTANTS.MAX_LEVEL then newRewardIndex = BATTLE_PASS_CONSTANTS.MAX_LEVEL + 1 end role.SetRoleScriptData(RoleID, 1, RoleDataType["Bo_Rew"], newRewardIndex) end end else err = E_UNKNOWN_ACTION end hasPass, level, exp, rewardIndex, passItemCount, expItemCount = BattlePass_GetState(RoleID) return err, hasPass, level, exp, rewardIndex, passItemCount, expItemCount end