-- ==============================脚本内全局变量======================================== local scriptConst = { -- 一级属等级配置 FIRST_LEVEL_ATTR_CONFIG = 1, -- 一级属性最大值配置id FIRST_LEVEL_ATTR_MAX_VALUE_CONFIG = 3001, -- 重置果实配置 RESET_FIRST_LEVEL_ATTR_CONDITION = 3002, -- 使用成功提示 FRUIT_SUCCESS = 200, -- 使用失败提示 FRUIT_FAIL = 201, } ---玩家累计使用果实数量 local USE_FRUIT_COUNT = "T$use_fruit_count" -- =====================================存储上次的果实使用信息实体=================================== local LastUsageInfo = {} LastUsageInfo.__index = LastUsageInfo function LastUsageInfo:new() local obj = { lastUsageTime = 0, usageCount = 0 } setmetatable(obj, LastUsageInfo) return obj end -- ====================================使用cd检验工具====================================== local ItemCanUseTool = {} ItemCanUseTool.__index = ItemCanUseTool function ItemCanUseTool:new(maxUsageCount, cooldownSeconds, useageInfos) local self = setmetatable({ maxUsageCount = maxUsageCount, cooldownMilSeconds = cooldownSeconds * 1000, usageInfos = useageInfos or {} }, ItemCanUseTool) return self end function ItemCanUseTool:canUseItem(actor, itemId) if self.maxUsageCount == -1 or self.cooldownMilSeconds == -1 then -- 不限制 return true end local oneInfo = self.usageInfos[itemId] if not oneInfo then return true end local lastTime = oneInfo.lastUsageTime local curTime = getbaseinfo(actor, "now") local timeSinceLastUse = curTime - lastTime if timeSinceLastUse >= self.cooldownMilSeconds then oneInfo.usageCount = 0 return true end return oneInfo.usageCount < self.maxUsageCount end function ItemCanUseTool:useItem(actor, itemId, count) local oneInfo = self.usageInfos[itemId] or LastUsageInfo:new() self.usageInfos[itemId] = oneInfo local curTime = getbaseinfo(actor, "now") oneInfo.lastUsageTime = curTime oneInfo.usageCount = oneInfo.usageCount + count end -- ================================================果实逻辑脚本模板========================================================== FruitScript = {} FruitScript.__index = FruitScript function FruitScript:new() local obj = setmetatable({}, FruitScript) return obj end local fruitScript = FruitScript:new() function FruitScript.handleUseFruit(actor, cfgId, count) local useCfgId = cfgId local useCount = count local realUseCount, currAttrAddValue = fruitScript:useFruit(actor, useCfgId, useCount); local recoveryCount = 0 local msg local fruitAttrId = ConfigDataManager.getTableValue("cfg_fruit", "attribute", "id", cfgId) local attrTipName = ConfigDataManager.getTableValue("cfg_att_info", "name", "id", fruitAttrId) if realUseCount == 0 then recoveryCount = count msg = false -- noticeTip.noticeinfo(actor, scriptConst.FRUIT_FAIL) end if realUseCount == count then msg = true -- if currAttrAddValue > 0 then -- noticeTip.noticeinfo(actor, scriptConst.FRUIT_SUCCESS, attrTipName, currAttrAddValue) -- else -- noticeTip.noticeinfo(actor, scriptConst.FRUIT_FAIL) -- end end if realUseCount ~= count and realUseCount > 0 then msg = true recoveryCount = count - realUseCount -- if currAttrAddValue > 0 then -- noticeTip.noticeinfo(actor, scriptConst.FRUIT_SUCCESS, attrTipName, currAttrAddValue) -- else -- noticeTip.noticeinfo(actor, scriptConst.FRUIT_FAIL) -- end end -- lg("恢复果实数量:", recoveryCount, "回包消息:", msg) local config = ConfigDataManager.getById("cfg_fruit", cfgId) if config ~= nil and next(config) ~= nil then if recoveryCount ~= 0 then additemtobag(actor, cfgId, recoveryCount, 0, 9999, '果实') else sendluamsg(actor, LuaMessageIdToClient.USE_FRUIT_RESULT, msg) end end if realUseCount~= nil and realUseCount > 0 then --记录使用数量 local oldCount = FruitScript.GetUseFruitCount(actor) setplaydef(actor, USE_FRUIT_COUNT, oldCount + realUseCount) ---使用果实任务 TaskHandler.TriggerTaskGoal(actor, TaskTargetType.USE_FRUIT_ITEM) end end ---获取玩家累计使用果实数量 function FruitScript.GetUseFruitCount(actor) local totalCount = getplaydef(actor, USE_FRUIT_COUNT) if totalCount == nil then totalCount = 0 end return totalCount end function FruitScript.toGetAlreadyUsePoints(actor) fruitScript:getAlreadyUsePoints(actor) end function FruitScript.resetFruit(actor, msgData) fruitScript:resetFruitAttr(actor, msgData) end function FruitScript.toGetResetCount(actor) fruitScript:getResetCount(actor) end -- ===================================使用果实============================================ function FruitScript:useFruit(actor, cfgId, count) if count <= 0 then return 0, 0 end local config = ConfigDataManager.getById("cfg_fruit", cfgId) if config == nil or next(config) == nil then -- lg('果实表中没有找到主键', cfgId) return 0, 0 end -- lg(cfgId, count) local hasCount = getbagitemcountbyid(actor, cfgId) -- lg('拥有道具' .. cfgId .. '数量' .. hasCount) -- 这里加上count是因为判断的逻辑在消耗了果实之后,要判断消耗之前的 if hasCount == nil or tonumber(hasCount) + count <= 0 then -- lg('道具数量不足') return 0, 0 end if count > tonumber(hasCount) + count then -- lg('道具数量不足') return 0, 0 end local canUse = self:canUseFruit(actor, cfgId) if not canUse then return 0, 0 end local fruitData = getplaydef(actor, "T$fruit_data") or {} local lastUsageInfos = fruitData["lastUsageInfo"] or {} fruitData["lastUsageInfo"] = lastUsageInfos -- 单个使用cd检查 local coolingTime = ConfigDataManager.getTableValue("cfg_item", "coolingTime", "id", cfgId) if coolingTime ~= nil and coolingTime ~= "" then local curTime = getbaseinfo(actor, "now") local lastUsageInfo = lastUsageInfos[cfgId] or LastUsageInfo:new() -- lg(lastUsageInfo) local lastUsageTime = lastUsageInfo["lastUsageTime"] or 0 if lastUsageTime ~= 0 then local timeSinceLastUse = curTime - lastUsageTime if timeSinceLastUse < tonumber(coolingTime) then -- lg('使用cd未冷却') return 0, 0 end end end -- 使用多个后cd检查 local canUseManager = nil local countAndTimeLimit = ConfigDataManager.getTableValue("cfg_item", "useLimit", "id", cfgId) if countAndTimeLimit ~= nil and countAndTimeLimit ~= "" then local splits = string.split(countAndTimeLimit, "#") local countLimit = tonumber(splits[1]) if count > countLimit then -- lg('使用数量超过限制') return 0, 0 end local timeLimit = tonumber(splits[2]) canUseManager = ItemCanUseTool:new(countLimit, timeLimit, lastUsageInfos) -- lg("canUseManager:", canUseManager) local canUseItem = canUseManager:canUseItem(actor, cfgId) if not canUseItem then local tipTime = timeLimit / 60 -- lg('使用数量达到上限' .. countLimit .. ',请等待' .. tipTime .. '分钟再使用!') return 0, 0 end end local realUseCount, currAttrAddValue = self:addFruitAttrPoint(actor, count, cfgId, fruitData) -- lg("实际使用果实数量:", realUseCount, "本次实际增加值", currAttrAddValue) if realUseCount == 0 then -- 使用失败或者添加值为零 return 0, 0 end if canUseManager == nil then -- 不限制使用,在这里初始化 canUseManager = ItemCanUseTool:new(-1, -1, lastUsageInfos) end canUseManager:useItem(actor, cfgId, realUseCount) -- 更新果实的使用信息 local updatedUseageInfo = canUseManager["usageInfos"] -- lg("果实使用信息", updatedUseageInfo) setplaydef(actor, "T$fruit_data", fruitData) self:getAlreadyUsePoints(actor) return realUseCount, currAttrAddValue end -- 添加属性点 function FruitScript:addFruitAttrPoint(actor, count, cfgId, fruitData) local fruitAttrId = ConfigDataManager.getTableValue("cfg_fruit", "attribute", "id", cfgId) -- lg("果实id", fruitAttrId) if fruitAttrId == "" or tonumber(fruitAttrId) <= 0 then return 0, 0 end local attributeGroup = ConfigDataManager.getTableValue("cfg_fruit", "group", "id", cfgId) -- lg("属性组", attributeGroup) if attributeGroup == "" or tonumber(attributeGroup) <= 0 then return 0, 0 end local realUseFruitCount = 0 local currAttrAddValue = 0 if self:isFirstLevelAttribute(fruitAttrId) then realUseFruitCount, currAttrAddValue = self:firstLevelAttrLogic(actor, cfgId, fruitAttrId, count, attributeGroup, fruitData) else realUseFruitCount, currAttrAddValue = self:notFirstLevelAttrLogic(actor, cfgId, fruitAttrId, count, attributeGroup, fruitData) end -- lg("使用果实后的当前对应属性值", currAttrAddValue) if realUseFruitCount == 0 then return 0, 0 end if realUseFruitCount > 0 and currAttrAddValue > 0 then local attrName = ConfigDataManager.getTableValue("cfg_att_info", "attribute", "id", fruitAttrId) if attrName == nil or attrName == nil then return false end -- lg("attrName", attrName) local newFruitData = getplaydef(actor, "T$fruit_data") or {} local newFruitAttrPoints = newFruitData["fruitAttrPoints"] or {} -- local newValue = newFruitAttrPoints[tonumber(fruitAttrId)] or 0 -- 更新属性值 -- updateattrgroup(actor, "fruitAttrs", attrName, newValue) addrolekmlattributes(actor, "fruitAttrs", newFruitAttrPoints) end return realUseFruitCount, currAttrAddValue end -- 第一级属性点添加逻辑 function FruitScript:firstLevelAttrLogic(actor, cfgId, fruitAttrId, count, attributeGroup, fruitData) -- lg("第一级属性点添加逻辑") local realUseFruitCount = 0 local maxFirstLevelAttrSum = ConfigDataManager.getTableValue("cfg_global", "value", "id", scriptConst .FIRST_LEVEL_ATTR_MAX_VALUE_CONFIG) if maxFirstLevelAttrSum == "" or maxFirstLevelAttrSum == nil then -- lg("获取最大属性点失败") return 0, 0 end maxFirstLevelAttrSum = tonumber(maxFirstLevelAttrSum) local fruitAttrPoints = fruitData["fruitAttrPoints"] or {} fruitData["fruitAttrPoints"] = fruitAttrPoints local totalAddValue = 0 while count > 0 do local oldFruitAttr = fruitAttrPoints[tonumber(fruitAttrId)] or 0 -- lg("当前已经有的属性值:", fruitAttrId, oldFruitAttr) local probability = ConfigDataManager.getTableValue("cfg_fruitgroup", "probability", "acquired", oldFruitAttr, "group", attributeGroup) -- lg("概率字符:", probability) local probabilityArr = string.splitByAll(probability, "#") local index = self:selectIndexByWeight(probabilityArr) -- lg("本次选中的索引:", index) local values = ConfigDataManager.getTableValue("cfg_fruitgroup", "number", "acquired", oldFruitAttr, "group", attributeGroup) local realAddAttrValue = tonumber(string.splitByAll(values, "#")[index]) -- lg("本次实际增加值:", realAddAttrValue) local numberType = ConfigDataManager.getTableValue("cfg_att_info", "remarks", "id", fruitAttrId) -- lg("数值类型:", numberType) if tonumber(numberType) == 2 then realAddAttrValue = realAddAttrValue * 0.0001 end local currentFirstLevelAttrSum = self:gainCurrentFirstLevelAttrSum(actor) -- lg("当前一级属性总和 : ", currentFirstLevelAttrSum) if currentFirstLevelAttrSum >= maxFirstLevelAttrSum then -- lg("当前属性点已达到上限") break end if currentFirstLevelAttrSum + realAddAttrValue >= maxFirstLevelAttrSum then -- lg("大于等于最大值") realUseFruitCount = realUseFruitCount + 1 local realAddThisTime = maxFirstLevelAttrSum - currentFirstLevelAttrSum totalAddValue = totalAddValue + realAddThisTime fruitAttrPoints[tonumber(fruitAttrId)] = oldFruitAttr + realAddThisTime break end if currentFirstLevelAttrSum + realAddAttrValue < maxFirstLevelAttrSum then -- lg("小于最大值") realUseFruitCount = realUseFruitCount + 1 totalAddValue = totalAddValue + realAddAttrValue fruitAttrPoints[tonumber(fruitAttrId)] = oldFruitAttr + realAddAttrValue end count = count - 1 if realAddAttrValue > 0 then local attrTipName = ConfigDataManager.getTableValue("cfg_att_info", "name", "id", fruitAttrId) local tipInfo = realAddAttrValue if tonumber(numberType) == 2 then tipInfo = realAddAttrValue * 100 .. "%" end noticeTip.noticeinfo(actor, scriptConst.FRUIT_SUCCESS, attrTipName, tipInfo) else noticeTip.noticeinfo(actor, scriptConst.FRUIT_FAIL) end -- 更新果实属性值 setplaydef(actor, "T$fruit_data", fruitData) end return realUseFruitCount, totalAddValue end -- 非属性点第一级添加逻辑 function FruitScript:notFirstLevelAttrLogic(actor, cfgId, fruitAttrId, count, attributeGroup, fruitData) -- lg("非属性点第一级添加逻辑") local realUseFruitCount = 0 local fruitAttrPoints = fruitData["fruitAttrPoints"] or {} fruitData["fruitAttrPoints"] = fruitAttrPoints -- 一级属性之外的属性不设上限 local totalAddValue = 0 while count > 0 do local oldFruitAttr = fruitAttrPoints[tonumber(fruitAttrId)] or 0 local numberType = ConfigDataManager.getTableValue("cfg_att_info", "remarks", "id", fruitAttrId) -- lg("数值类型:", numberType) local acquired = oldFruitAttr if tonumber(numberType) == 2 then acquired = math.round(oldFruitAttr * 10000) end -- lg("当前已经有的属性值:", fruitAttrId, oldFruitAttr, acquired) local probability = ConfigDataManager.getTableValue("cfg_fruitgroup", "probability", "acquired", acquired, "group", attributeGroup) local probabilityArr = string.splitByAll(probability, "#") local index = self:selectIndexByWeight(probabilityArr) -- lg("本次选中的索引:", index) local values = ConfigDataManager.getTableValue("cfg_fruitgroup", "number", "acquired", acquired, "group", attributeGroup) local realAddAttrValue = tonumber(string.splitByAll(values, "#")[index]) if tonumber(numberType) == 2 then realAddAttrValue = realAddAttrValue * 0.0001 end -- lg("本次实际增加值:", realAddAttrValue) totalAddValue = totalAddValue + realAddAttrValue fruitAttrPoints[tonumber(fruitAttrId)] = oldFruitAttr + realAddAttrValue realUseFruitCount = realUseFruitCount + 1 count = count - 1 if realAddAttrValue > 0 then local attrTipName = ConfigDataManager.getTableValue("cfg_att_info", "name", "id", fruitAttrId) local tipInfo = realAddAttrValue if tonumber(numberType) == 2 then tipInfo = realAddAttrValue * 100 .. "%" end noticeTip.noticeinfo(actor, scriptConst.FRUIT_SUCCESS, attrTipName, tipInfo) else noticeTip.noticeinfo(actor, scriptConst.FRUIT_FAIL) end end setplaydef(actor, "T$fruit_data", fruitData) return realUseFruitCount, totalAddValue end -- 获取属性点第一级属性点总和 function FruitScript:gainCurrentFirstLevelAttrSum(actor) local currentFirstLevelAttrSum = 0 local firstLevelAttributeEnum = self:getFirstAttrConfig() local fruitData = getplaydef(actor, "T$fruit_data") or {} local fruitAttrPoints = fruitData["fruitAttrPoints"] or {} for i, attrId in ipairs(firstLevelAttributeEnum) do local currFruitAttrPoint = fruitAttrPoints[tonumber(attrId)] or 0 currentFirstLevelAttrSum = currentFirstLevelAttrSum + currFruitAttrPoint end -- lg("一级属性值总和", currentFirstLevelAttrSum) return currentFirstLevelAttrSum end -- 校验是否可以使用 function FruitScript:canUseFruit(actor, cfgId) local itemConfig = ConfigDataManager.getById("cfg_item", cfgId) local fruitConfig = ConfigDataManager.getById("cfg_fruit", cfgId) if itemConfig == nil or fruitConfig == nil then -- lg('要使用的果实道具不存在,请检查配置') return false end local fruitAttrIdStr = ConfigDataManager.getTableValue("cfg_fruit", "attribute", "id", cfgId) if fruitAttrIdStr == nil or fruitAttrIdStr == "" then return false end local fruitAttrId = tonumber(fruitAttrIdStr) if fruitAttrId <= 0 then -- lg('配置属性id不合法') return false end local attInfoConfig = ConfigDataManager.getById("cfg_att_info", fruitAttrId) -- -- lg("属性信息", attInfoConfig) if attInfoConfig == nil or next(attInfoConfig) == nil then -- lg('未找到属性信息') return false end if self:isFirstLevelAttribute(fruitAttrId) then local currentFirstLevelAttrSum = self:gainCurrentFirstLevelAttrSum(actor) local maxFirstLevelAttrSum = ConfigDataManager.getTableValue("cfg_global", "value", "id", scriptConst.FIRST_LEVEL_ATTR_MAX_VALUE_CONFIG) maxFirstLevelAttrSum = tonumber(maxFirstLevelAttrSum) if currentFirstLevelAttrSum >= maxFirstLevelAttrSum then -- lg('当前一级果实属性加成已经达到最大值,无法使用果实继续加成!') return false end end return true end -- 判断是否是属性点第一级 function FruitScript:isFirstLevelAttribute(fruitAttrId) local firstLevelAttributeEnum = self:getFirstAttrConfig() -- lg("判断是否是属性点第一级属性", fruitAttrId, array.simpleContains(firstLevelAttributeEnum, fruitAttrId)) return array.simpleContains(firstLevelAttributeEnum, fruitAttrId) end -- 将字符串转换成map function FruitScript:convertStringToMap(source) if source == nil then return nil end local strValue = tostring(source) local map = {} if strValue ~= '' then map = string.toStringStringMap(strValue, "#", "|") end return map end -- ===========================================重置果实属性请求========================================== -- 重置果实属性请求 function FruitScript:resetFruitAttr(actor, attrIdAndValue) local fruitData = getplaydef(actor, "T$fruit_data") or {} local resetFruitAttrCount = fruitData["resetFruitAttrCount"] or 0 local resetCondition = ConfigDataManager.getTableValue("cfg_global", "value", "id", scriptConst.RESET_FIRST_LEVEL_ATTR_CONDITION) -- 根据重置条件,扣除道具 local tobeResetCount = resetFruitAttrCount + 1 local index = tobeResetCount if tobeResetCount > 4 then index = 4 end local resetConditions = string.splitByAll(resetCondition, "|") local resetCost = string.splitByAll(resetConditions[index], "#") local itemCount = getbagitemcountbyid(actor, tonumber(resetCost[2])) -- lg("重置果实属性请求,已有道具%d,数量%d", resetCost[2], itemCount) if tonumber(itemCount) < tonumber(resetCost[3]) then noticeTip.noticeinfo(actor, StringIdConst.TEXT348) return end -- 校验一级属性值总数是否一致 local totalAttrPoints = self:gainCurrentFirstLevelAttrSum(actor) local receivePoints = 0 for k, v in pairs(attrIdAndValue) do receivePoints = receivePoints + v end -- lg("重置果实属性请求,一级属性值总和%d,已获得属性值总和%d", totalAttrPoints, receivePoints) if tonumber(totalAttrPoints) ~= tonumber(receivePoints) then -- lg("重置果实属性请求失败,一级属性值总和不一致") return end local firstLevelAttributeEnum = self:getFirstAttrConfig() -- lg(firstLevelAttributeEnum) -- 客户端清除一级果实属性 (非一级属性不清除) local fruitAttrPoints = fruitData["fruitAttrPoints"] or {} for _, attrId in ipairs(firstLevelAttributeEnum) do local newValue = attrIdAndValue[attrId] fruitAttrPoints[tonumber(attrId)] = newValue end addrolekmlattributes(actor, "fruitAttrs", fruitAttrPoints) removeitemfrombag(actor, tonumber(resetCost[2]), tonumber(resetCost[3]),0,9999,'果实') fruitData["resetFruitAttrCount"] = tobeResetCount fruitData["fruitAttrPoints"] = fruitAttrPoints setplaydef(actor, "T$fruit_data", fruitData) self:getAlreadyUsePoints(actor) end -- 获取果实属性重置次数 function FruitScript:getResetCount(actor) local fruitData = getplaydef(actor, "T$fruit_data") or {} local resetFruitAttrCount = fruitData["resetFruitAttrCount"] or 0 -- lg("已经重置次数", resetFruitAttrCount) sendluamsg(actor, LuaMessageIdToClient.C_RESET_FRUIT_COUNT, resetFruitAttrCount) end -- 获取果实当前已经使用的点数 function FruitScript:getAlreadyUsePoints(actor) local data = getplaydef(actor, "T$fruit_data") or {} local attrPoints = data["fruitAttrPoints"] if attrPoints == nil then -- lg("没有属性点数据") sendluamsg(actor, LuaMessageIdToClient.C_USE_FRUIT_RESULT, { totalFirstLevelAttrs = 0, attrPoints = {} }) return end local totalFirstLevelAttrs = self:gainCurrentFirstLevelAttrSum(actor) for k, v in pairs(attrPoints) do attrPoints[k] = tostring(v) end -- lg("已分配属性点", attrPoints) sendluamsg(actor, LuaMessageIdToClient.C_USE_FRUIT_RESULT, { totalFirstLevelAttrs = totalFirstLevelAttrs, attrPoints = attrPoints }) end function FruitScript:getFirstAttrConfig() local firstLevelAttrConfigs = ConfigDataManager.getTable("cfg_att_info", "base", scriptConst.FIRST_LEVEL_ATTR_CONFIG) if table.isNullOrEmpty(firstLevelAttrConfigs) then return end local firstLevelAttributeEnum = {} for i, attInfoConfig in ipairs(firstLevelAttrConfigs) do local attrId = attInfoConfig["id"] table.insert(firstLevelAttributeEnum, attrId) end return firstLevelAttributeEnum end -- 根据权重随机选位置索引 function FruitScript:selectIndexByWeight(weights) local totalWeight = 0 for _, weight in ipairs(weights) do weight = tonumber(weight) totalWeight = totalWeight + weight end local randomValue = math.random(1, totalWeight) -- 遍历权重数组,找到对应的下标 local accumulatedWeight = 0 for i, weight in ipairs(weights) do accumulatedWeight = accumulatedWeight + weight if randomValue <= accumulatedWeight then return i end end -- 如果没有找到合适的下标(理论上不会发生),返回最后一个下标 return #weights end function clearfruit(actor) setplaydef(actor, "T$fruit_data", {}) end