c1_lua/lua/app/global/global_func.lua
2025-10-30 16:38:48 +08:00

2120 lines
56 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local GFunc = {}
local EMPTY_TABLE = {}
local TEMP_LIST = {}
local TEMP_MAP = {}
local HASH_SEED = 31
local UINT_RANGE = 4294967296
local byte = string.byte
local DESIGN_RESOLUTION_WIDTH = CS.BF.GameConst.DESIGN_RESOLUTION_WIDTH
local DESIGN_RESOLUTION_HEIGHT = CS.BF.GameConst.DESIGN_RESOLUTION_HEIGHT
local UnityTime = CS.UnityEngine.Time
--获取unicode 字符串长度 和utf-8长度
function GFunc.getTextLen(str)
local byteLen = #str
local strLen = 0
local i = 1
local curByte
local byteCount = 1
while i <= byteLen do
curByte = byte(str, i)
byteCount = 1
if curByte > 0 and curByte <= 127 then
byteCount = 1
elseif curByte >= 192 and curByte < 223 then
byteCount = 2
elseif curByte >= 224 and curByte < 239 then
byteCount = 3
elseif curByte >= 240 and curByte <= 247 then
byteCount = 4
end
i = i + byteCount
strLen = strLen + 1
end
return strLen, i - 1
end
function GFunc.getTextLen2(str)
local byteLen = #str
local strLen = 0
local i = 1
local curByte
local byteCount = 1
while i <= byteLen do
curByte = byte(str, i)
byteCount = 1
if curByte > 0 and curByte <= 127 then
byteCount = 1
strLen = strLen + 1
elseif curByte >= 192 and curByte < 223 then
-- 中文算2个字节
byteCount = 2
strLen = strLen + 1
elseif curByte >= 224 and curByte < 239 then
byteCount = 3
strLen = strLen + 2
elseif curByte >= 240 and curByte <= 247 then
byteCount = 4
strLen = strLen + 1
end
i = i + byteCount
end
return strLen, i - 1
end
-- 判断字符串是不是全部都是空格,32是半角空格227是全角空格
function GFunc.getIsAllSpaceStr(str)
local result = true
local byteLen = #str
local i = 1
local curByte
local byteCount = 1
while i <= byteLen do
curByte = byte(str, i)
byteCount = 1
if curByte > 0 and curByte <= 127 then
byteCount = 1
if curByte ~= 32 then
result = false
break
end
elseif curByte >= 192 and curByte < 223 then
byteCount = 2
result = false
break
elseif curByte >= 224 and curByte < 239 then
byteCount = 3
if curByte ~= 227 then
result = false
break
end
elseif curByte >= 240 and curByte <= 247 then
byteCount = 4
result = false
break
else
result = false
break
end
i = i + byteCount
end
return result
end
function GFunc.num2Str(count, dec)
if count >= 99999999999 then -- 前端限制最大显示99999M
if dec then
return "99999.99M"
else
return "99999M"
end
elseif count >= 10000000 then
if dec then
count = math.floor((count*10^dec)/1000000)/(10^dec)
return count .. "M"
else
count = count // 1000000
return count .. "M"
end
elseif count >= 100000 then
if dec then
count = math.floor((count*10^dec)/1000)/(10^dec)
return count .. "K"
else
count = count // 1000
return count .. "K"
end
else
return GFunc.parseDedundantNumber(count)
end
end
-- 超过千位就缩写,目前只有公会奖励用到 1K-5K
function GFunc.num2Str2(count, dec)
if count >= 99999999999 then -- 前端限制最大显示99999M
if dec then
return "99999.99M"
else
return "99999M"
end
elseif count >= 1000000 then
if dec then
count = math.floor((count*10^dec)/1000000)/(10^dec)
return count .. "M"
else
count = count // 1000000
return count .. "M"
end
elseif count >= 1000 then
if dec then
count = math.floor((count*10^dec)/1000)/(10^dec)
return count .. "K"
else
count = count // 1000
return count .. "K"
end
else
return GFunc.parseDedundantNumber(count)
end
end
-- 与num2Str类似 但是上限扩大3位至99999B
function GFunc.num2Str3(count, dec)
if count >= 99999999999999 then -- 前端限制最大显示99999B
if dec then
return "99999.99B"
else
return "99999B"
end
elseif count >= 10000000000 then
if dec then
count = math.floor((count*10^dec)/1000000000)/(10^dec)
return count .. "B"
else
count = count // 1000000000
return count .. "B"
end
elseif count >= 10000000 then
if dec then
count = math.floor((count*10^dec)/1000000)/(10^dec)
return count .. "M"
else
count = count // 1000000
return count .. "M"
end
elseif count >= 100000 then
if dec then
count = math.floor((count*10^dec)/1000)/(10^dec)
return count .. "K"
else
count = count // 1000
return count .. "K"
end
else
return GFunc.parseDedundantNumber(count)
end
end
function GFunc.killDOTween(id, complete)
if complete == nil then
return CS.BF.Utils.KillDOTween(id)
else
return CS.BF.Utils.KillDOTween(id, complete)
end
end
function GFunc.setDOTweenTimeScale(id, timeScale)
CS.BF.Utils.SetDOTweenTimeScale(id, timeScale)
end
function GFunc.nameToLayer(name)
return CS.BF.Utils.NameToLayer(name)
end
-- BKDRHash
function GFunc.hash(str)
local h = 0
for i = 1, #str do
h = h * HASH_SEED + byte(str, i)
end
return h%UINT_RANGE
end
function GFunc.getScreenSize()
return CS.UnityEngine.Screen.width, CS.UnityEngine.Screen.height
end
function GFunc.parseDedundantNumber(num)
if num % 1 == 0 then
return math.ceil(num)
else
return num
end
end
function GFunc.openUrl(web)
CS.UnityEngine.Application.OpenURL(web)
end
function GFunc.getShader(shaderName)
return CS.UnityEngine.Shader.Find(shaderName)
end
function GFunc.subStringGetByteCount(str, index)
local curByte = byte(str, index)
local byteCount = 1
if curByte == nil then
byteCount = 0
elseif curByte > 240 then
byteCount = 4
elseif curByte > 225 then
byteCount = 3
elseif curByte > 192 then
byteCount = 2
end
return byteCount
end
function GFunc.subStringByCharCount(str, needCount)
local index = 1
local lastIndex = 1
local num = 0
while num < needCount and lastIndex ~= 0 do
lastIndex = GFunc.subStringGetByteCount(str, index)
index = index + lastIndex
num = num + 1
end
return string.sub(str,1, index - 1)
end
function GFunc.setLayer(gameObject, layerName)
local trans = gameObject.transform:GetComponentsInChildren(typeof(CS.UnityEngine.Transform))
local layer = GFunc.nameToLayer(layerName)
if trans then
local len = trans.Length
for i = 0, len - 1 do
trans[i].gameObject.layer = layer
end
end
end
-- 根据当前屏幕分辨率 计算偏差值
function GFunc.calculateFitSizeY()
local width, height = GFunc.getScreenSize()
local dif = 0
if width / height < DESIGN_RESOLUTION_WIDTH / DESIGN_RESOLUTION_HEIGHT then
dif = height / (width / DESIGN_RESOLUTION_WIDTH) - DESIGN_RESOLUTION_HEIGHT
end
return dif
end
-- 获得Expand模式下UI分辨率
function GFunc.getUIExpandScreenSize()
local width, height = GFunc.getScreenSize()
if width / height <= DESIGN_RESOLUTION_WIDTH / DESIGN_RESOLUTION_HEIGHT then
height = height * (DESIGN_RESOLUTION_WIDTH / width)
width = DESIGN_RESOLUTION_WIDTH
else
width = width * (DESIGN_RESOLUTION_HEIGHT / height)
height = DESIGN_RESOLUTION_HEIGHT
end
return width, height
end
function GFunc.checkNameValid(str, min, max)
local result = nil
if str == nil or str == "" then
--输入不能为空
return false
else
result = string.match(str, "/u{0020}") or string.match(str, "/u{3000}") or string.match(str, "/u{00A0}")
end
if result then
--非法字符
return false
end
local k, length = GFunc.getTextLen(str)
if length < min then
return false
elseif length > max then
return false
end
return true
end
function GFunc.showMessageBox(params)
local MessageBox = require "app/ui/common/message_box"
MessageBox:showMessageBox(params)
end
function GFunc.showAdMesssageBox(params)
UIManager:showUI("app/ui/common/common_ad_ui", params)
end
function GFunc.showToast(params)
ModuleManager.ToastManager:showToast(params)
end
function GFunc.UiRectTransformScreenPointToLocalPointInRectangle(go, x, y)
local uiCamera = UIManager:getUICameraComponent()
local anchoredPosition = CS.BF.Utils.RectTransformScreenPointToLocalPointInRectangle(go:getTransform(),
x, y, uiCamera)
return anchoredPosition
end
function GFunc.UiRectangleContainsScreenPoint(go, x, y)
local uiCamera = UIManager:getUICameraComponent()
return CS.BF.Utils.RectangleContainsScreenPoint(go:getTransform(), x, y, uiCamera)
end
-- 获取任务icon
function GFunc.getTaskIcon(taskType, taskTarget)
if taskType == GConst.TaskConst.TASK_TYPE.X_ARENA_GRADING then
local name = DataManager.ArenaData:getGradingIconName(DataManager.ArenaData:getGradingIdFromScore(taskTarget))
if name == "arena_dan_1" then
return "13"
elseif name == "arena_dan_2" then
return "14"
elseif name == "arena_dan_3" then
return "12"
end
else
return ConfigManager:getConfig("task_type")[taskType].icon
end
end
-- 获取任务描述
function GFunc.getTaskDesc(taskType, taskTarget)
if taskType == GConst.TaskConst.TASK_TYPE.X_ARENA_GRADING then
-- 段位显示文本
-- local grading = DataManager.ArenaData:getGradingName(DataManager.ArenaData:getGradingIdFromScore(taskTarget))
-- return I18N:getText("task_type", taskType, "desc", grading)
-- local curScore = DataManager.ArenaData:getGradingScore(taskTarget)
return I18N:getText("task_type", taskType, "desc", taskTarget)
elseif taskType == GConst.TaskConst.TASK_TYPE.X_PASS_CHAPTER then
local str = DataManager.ChapterData:getChapterNameXYMode(taskTarget)
return I18N:getText("task_type", taskType, "desc", str)
elseif taskType == GConst.TaskConst.TASK_TYPE.X_DUNGEON_ARMOR then
-- 防具副本显示章节和关卡
local cfg = DataManager.DungeonData:getDungeonDataByType(ModuleManager.MODULE_KEY.DUNGEON_ARMOR):getConfig(taskTarget)
return I18N:getText("task_type", taskType, "desc", cfg.chapter, cfg.stage)
else
return I18N:getText("task_type", taskType, "desc", taskTarget)
end
end
function GFunc.getTimeStrWithMS(time)
local m = math.floor(time/60)
local s = time%60
return I18N:getGlobalText(I18N.GlobalConst.TIME_MS, string.format("%02d", m), string.format("%02d", s))
end
function GFunc.getTimeStrWithMS2(time)
local m = math.floor(time/60)
local s = time%60
return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_MS, string.format("%02d", m), string.format("%02d", s))
end
function GFunc.getTimeStrWithHMS(time)
local h = math.floor(time/3600)
local m = math.floor((time%3600)/60)
local s = time%60
return I18N:getGlobalText(I18N.GlobalConst.TIME_HMS, string.format("%02d", h), string.format("%02d", m), string.format("%02d", s))
end
function GFunc.getTimeWithHMS(time)
local h = math.floor(time/3600)
local m = math.floor((time%3600)/60)
local s = time%60
return string.format("%02d", h), string.format("%02d", m), string.format("%02d", s)
end
function GFunc.getTimeStrWithM2(time)
local m = time // 60
return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_M, m)
end
function GFunc.getTimeStrWithHMS2(time)
local h = math.floor(time/3600)
local m = math.floor((time%3600)/60)
local s = time%60
return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_HMS, h, m, s)
end
function GFunc.getTimeStrWithDHM(time)
local d = math.floor(time/86400)
local h = math.floor((time%86400)/3600)
local m = math.floor((time%3600)/60)
return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_DHM, d, h, m)
end
function GFunc.getTimeStrWithDH2(time)
local d = math.floor(time/86400)
local h = math.floor((time%86400)/3600)
return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_DH, d, h)
end
function GFunc.getTimeStrWithD2(time)
local d = math.floor(time/86400)
return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_D, d)
end
function GFunc.getTimeStrWithHM(time)
local h = math.floor(time/3600)
local m = math.floor((time%3600)/60)
return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_HM, string.format("%02d", h), string.format("%02d", m))
end
function GFunc.getTimeStrWithHM2(time)
local h = math.floor(time/3600)
local m = math.floor((time%3600)/60)
return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_HM, h, m)
end
function GFunc.getTimeStr(time)
if time > 86400 then
return GFunc.getTimeStrWithDH2(time)
else
return GFunc.getTimeStrWithHMS2(time)
end
end
function GFunc.getTimeStr2(time)
if time > 86400 then
return GFunc.getTimeStrWithD2(time)
else
return GFunc.getTimeStrWithHM2(time)
end
end
function GFunc.getTimeStr3(time)
if time >= 3600 then
return GFunc.getTimeStrWithHM(time)
else
return GFunc.getTimeStrWithMS2(time)
end
end
function GFunc.getAdaptScale(basePixel)
basePixel = basePixel or 0
local DESIGN_WIDTH = 720
local DESIGN_HEIGHT = 1280
local safeHeight = SafeAreaManager:getNotchScreenHeight()
local winSizeWidth, winSizeHeight = GFunc.getScreenSize()
local maxScale = math.max(DESIGN_WIDTH/winSizeWidth, DESIGN_HEIGHT/winSizeHeight)
local height = maxScale*winSizeHeight - basePixel - safeHeight
local scale = height/(DESIGN_HEIGHT - basePixel)
return scale
end
function GFunc.getConstIntValue(key)
local ConstCfg = ConfigManager:getConfig("const")
if EDITOR_MODE then
if not ConstCfg[key] then
Logger.logHighlight("================ key = %s", key)
end
end
return math.floor(ConstCfg[key].value)
end
function GFunc.getConstValue(key)
local ConstCfg = ConfigManager:getConfig("const")
return ConstCfg[key] and ConstCfg[key].value or 0
end
function GFunc.getConstValueList(key)
local ConstCfg = ConfigManager:getConfig("const")
return ConstCfg[key] and ConstCfg[key].value_2 or {}
end
function GFunc.getConstReward(key)
local ConstCfg = ConfigManager:getConfig("const")
if not ConstCfg[key] or not ConstCfg[key].reward then
return
end
return ConstCfg[key].reward[1]
end
--isGetList 为true时返回列表反之返回第一个元素
function GFunc.getConstCost(key, isGetList)
local ConstCfg = ConfigManager:getConfig("const")
if ConstCfg[key] == nil or ConstCfg[key].reward == nil or #ConstCfg[key].reward <= 0 then
return nil
end
return isGetList and ConstCfg[key].reward or ConstCfg[key].reward[1]
end
function GFunc.getTargetAnchoredPosition(targetGo, parent)
local rectTransform = targetGo:getComponent(GConst.TYPEOF_UNITY_CLASS.RECTTRANSFORM)
local rect = rectTransform.rect
local localToWorldMatrix = rectTransform.localToWorldMatrix
local tarCornerMid = localToWorldMatrix:MultiplyPoint3x4(BF.Vector3((rect.xMax + rect.x) / 2, (rect.yMax + rect.y) / 2, 0))
local screenPos = UIManager:getUICameraComponent():WorldToScreenPoint(tarCornerMid)
local anchoredPosition = CS.BF.Utils.RectTransformScreenPointToLocalPointInRectangle(parent:getTransform(), screenPos.x, screenPos.y, UIManager:getUICameraComponent())
return anchoredPosition
end
function GFunc.getFormatPrice(rechargeId)
local cfg = ConfigManager:getConfig("recharge")[rechargeId]
if cfg == nil then
return GConst.EMPTY_STRING
end
-- 优先读取通过sdk获取的商品价格
local price = SDKManager:getProductPrice(cfg.payId)
if price and price ~= "" then
return price
end
-- sdk里查不到就读表
return cfg.price_str
end
function GFunc.setGrey(component, isGrey)
if isGrey then
component.color = GConst.COMPONENT_GREY_COLOR
else
component.color = GConst.COLOR.WHITE
end
end
function GFunc.checkBit(value, nbit)
if not value then
return false
end
local ret = value >> (nbit - 1)
if ret %2 == 1 then
return true
else
return false
end
end
function GFunc.showItemNotEnough(itemId)
local gemTextInfo = I18N:getConfig("item")[itemId]
if gemTextInfo then
GFunc.showToast(I18N:getGlobalText(I18N.GlobalConst.ITEM_NOT_ENOUGH, gemTextInfo.name))
end
if itemId == GConst.ItemConst.ITEM_ID_GOLD then
local params = {
content = I18N:getGlobalText(I18N.GlobalConst.GOTO_COIN_STORE_DESC),
boxType = GConst.MESSAGE_BOX_TYPE.MB_OK_CANCEL,
okText = I18N:getGlobalText(I18N.GlobalConst.BTN_TEXT_OK),
okFunc = function()
UIManager:closeAllUIExceptMainUI()
EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.GO_SHOP, {page = GConst.MainCityConst.BOTTOM_PAGE.SHOP, subType = GConst.ShopConst.MAIN_PAGE_TYPE.GOLD_STORE})
end
}
GFunc.showMessageBox(params)
end
end
function GFunc.checkCost(id, num, showToast)
if num <= 0 then
return true
end
local count = DataManager.BagData.ItemData:getItemNumById(id)
if count < num then
if showToast then
GFunc.showItemNotEnough(id)
end
return false
else
return true
end
end
---- 获得奖励的统一接口
function GFunc.addRewards(rewards, itemGetType)
if rewards == nil then
return
end
if EDITOR_MODE then
if not itemGetType then
local params = {
content = "GFunc addRewards has no itemGetType",
boxType = GConst.MESSAGE_BOX_TYPE.MB_OK,
okText = I18N:getGlobalText(I18N.GlobalConst.BTN_TEXT_OK),
}
GFunc.showMessageBox(params)
Logger.log("GFunc addRewards has no itemGetType")
end
end
-- 用元表来判断此奖励是否领过了,避免重复领取
if getmetatable(rewards) then
return
end
setmetatable(rewards, EMPTY_TABLE)
-- 合并奖励
local newRewards = {}
GFunc.mergeRewards2(rewards, newRewards)
-- 根据类型type来添加奖励
for k, v in ipairs(newRewards) do
if v.type == GConst.REWARD_TYPE.ITEM then
DataManager.BagData.ItemData:addItem(v.item, itemGetType)
elseif v.type == GConst.REWARD_TYPE.EQUIP then
DataManager.EquipData:addEquip(v.equip, itemGetType, true)
end
end
EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.GETED_REWARD_SUCCESS, newRewards)
end
function GFunc.addCosts(costs, itemGetType)
if costs == nil then
return
end
-- 用元表来判断此消耗是否领过了,避免重复扣除
if getmetatable(costs) then
return
end
setmetatable(costs, EMPTY_TABLE)
for _, unitCost in ipairs(costs) do
if unitCost.type == GConst.REWARD_TYPE.ITEM then
DataManager.BagData.ItemData:addItemCost(unitCost.item, itemGetType)
end
end
end
-- 奖励排序 结构为后端结构
function GFunc.sortRewards(rewards)
rewards = rewards or {}
local maxType = 10
for i,v in ipairs(rewards) do
if v.type == GConst.REWARD_TYPE.ITEM then
rewards[i].sort = (maxType - v.type) * 1000000000 + v.item.id
elseif v.type == GConst.REWARD_TYPE.EQUIP then
local cfg = ConfigManager:getConfig("equip")[v.equip.id]
rewards[i].sort = (maxType - v.type) * 1000000000 + cfg.qlt*100000000 + v.equip.id
end
end
table.sort(rewards, function (a, b)
return a.sort > b.sort
end)
end
---- 奖励展示接口
function GFunc.showRewardBox(rewards, extParams, callback)
rewards = rewards or {}
local params = extParams or {}
local newRewards = {}
if not params.noMerge then
GFunc.mergeRewards2(rewards, newRewards, true)
else
newRewards = rewards
end
params.rewards = newRewards
params.callback = callback
ModuleManager.TipsManager:showRewardsBox(params)
AudioManager:playEffect(AudioManager.EFFECT_ID.REWARD)
end
function GFunc.mergeRewards2(rewards, newRewards, needSort)
local items = {}
for i,v in ipairs(rewards) do
if v.type == GConst.REWARD_TYPE.ITEM then
items[v.item.id] = (items[v.item.id] or 0) + v.item.count
elseif v.type == GConst.REWARD_TYPE.EQUIP then
table.insert(newRewards, v)
end
end
for k,v in pairs(items) do
table.insert(newRewards, {type = GConst.REWARD_TYPE.ITEM, item = {id = k, count = v}})
end
if needSort then
GFunc.sortRewards(newRewards)
end
end
-- reward 结构为 type id num 配置中结构
function GFunc.mergeRewards(rewards)
local items = {}
local newRewards = {}
for i,v in ipairs(rewards) do
if v.type == GConst.REWARD_TYPE.ITEM then
items[v.id] = (items[v.id] or 0) + v.num
elseif v.type == GConst.REWARD_TYPE.EQUIP then
table.insert(newRewards, v)
elseif v.type == GConst.REWARD_TYPE.LEGACY then
table.insert(newRewards, v)
end
end
for k,v in pairs(items) do
table.insert(newRewards, {type = GConst.REWARD_TYPE.ITEM, id = k, num = v})
end
return newRewards
end
function GFunc.getRandomIndex(weightArr)
if #weightArr <= 0 then
return
end
local maxWeight = 0
for i, v in ipairs(weightArr) do
maxWeight = maxWeight + v
end
local randomWeight = math.random(1, maxWeight)
local idx
for i, v in ipairs(weightArr) do
if randomWeight <= v then
idx = i
break
else
randomWeight = randomWeight - v
end
end
return idx
end
---- 线性随机数算法
function GFunc.getRandomIndexBySeed(seed, min, max)
seed = (seed * 9301 + 49297)%233280
return min + seed*(max - min + 1)//233280
end
function GFunc.getRewardsStr(rewards)
if rewards == nil then
return
end
local itemStr = ""
for k, v in ipairs(rewards) do
if v.type == GConst.REWARD_TYPE.ITEM then
itemStr = itemStr .. v.type .. "." .. v.item.id .. "." .. v.item.count
end
if k ~= #rewards then
itemStr = itemStr.. "|"
end
end
return itemStr
end
function GFunc.getItemRewardsStr(rewards)
if rewards == nil then
return
end
local itemStr = ""
for k, v in ipairs(rewards) do
if v.type == GConst.REWARD_TYPE.ITEM then
itemStr = itemStr .. v.item.id .. ":" .. v.item.count
end
if k ~= #rewards then
itemStr = itemStr.. "|"
end
end
return itemStr
end
function GFunc.copyStr(str)
CS.UnityEngine.GUIUtility.systemCopyBuffer = str
end
function GFunc.getShakeSeq(obj, onlyKill, originScale, notForcerefresh)
originScale = originScale or 1
if obj.shakeSeq then
if notForcerefresh then
return obj.shakeSeq
end
obj.shakeSeq:Kill()
obj.shakeSeq = nil
end
obj:setLocalScale(originScale, originScale, originScale)
if onlyKill then
return
end
obj.shakeSeq = obj:createBindTweenSequence()
obj.shakeSeq:AppendInterval(2)
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 1.12, 0.1))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 0.9, 0.11))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 1.1, 0.15))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 0.9, 0.2))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 1.05, 0.25))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 0.9, 0.3))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 1, 0.3))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale, 0.3))
obj.shakeSeq:SetLoops(-1)
return obj.shakeSeq
end
function GFunc.getShakeSeq2(obj, onlyKill, originScale, notForcerefresh)
originScale = originScale or 1
if obj.shakeSeq then
if not notForcerefresh then
return obj.shakeSeq
end
obj.shakeSeq:Kill()
obj.shakeSeq = nil
end
obj:setLocalScale(originScale, originScale, originScale)
if onlyKill then
return
end
obj.shakeSeq = obj:createBindTweenSequence()
obj.shakeSeq:AppendInterval(1)
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 1.12, 0.1))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 0.9, 0.11))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 1.1, 0.15))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 0.9, 0.2))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 1.05, 0.25))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 0.9, 0.3))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale * 1, 0.3))
obj.shakeSeq:Append(obj:getTransform():DOScale(originScale, 0.3))
obj.shakeSeq:SetLoops(-1)
return obj.shakeSeq
end
function GFunc.getShakeSeqRotate(obj, onlyKill, notForcerefresh)
if obj.shakeSeq then
if notForcerefresh then
return obj.shakeSeq
end
obj.shakeSeq:Kill()
obj.shakeSeq = nil
obj:setLocalEulerAngles(0,0,0)
end
if onlyKill then
return
end
local objTrans = obj:getTransform()
obj.shakeSeq = obj:createBindTweenSequence()
obj.shakeSeq:AppendInterval(2)
local angle = 12
obj.shakeSeq:Append(objTrans:DORotate({x=0,y=0,z=angle},0.2))
obj.shakeSeq:Append(objTrans:DORotate({x=0,y=0,z=-angle},0.1))
obj.shakeSeq:Append(objTrans:DORotate({x=0,y=0,z=angle},0.1))
obj.shakeSeq:Append(objTrans:DORotate({x=0,y=0,z=-angle},0.07))
obj.shakeSeq:Append(objTrans:DORotate({x=0,y=0,z=angle},0.07))
obj.shakeSeq:Append(objTrans:DORotate({x=0,y=0,z=-angle},0.05))
obj.shakeSeq:SetLoops(-1)
return obj.shakeSeq
end
function GFunc.getScaleQueueAni(root, rewardList, listCell, callBack)
if root.aniSeq then
root.aniSeq:Kill()
root.aniSeq = nil
end
root.aniSeq = root:createBindTweenSequence()
local seq = root.aniSeq
local groupCell = {}
local index = 1
table.foreach(listCell, function(k, cell)
if groupCell[index] and #groupCell[index] >= 5 then
index = index + 1
end
if not groupCell[index] then
groupCell[index] = {}
end
table.insert(groupCell[index], cell)
end)
local rewardListTrans = rewardList:getTransform()
-- ani
table.foreach(groupCell, function(row, cells)
table.foreach(cells, function(k, cell)
local summonRewardCell = cell
local rewardType, id = summonRewardCell:getReward()
summonRewardCell:showMask()
local isNew = summonRewardCell:getIsFirstGet()
local rewardQlt = GFunc.getQuality(rewardType, id)
if rewardQlt and rewardQlt >= 4 and isNew then -- 紫色以上
seq:AppendInterval(0.4)
seq:AppendCallback(function() summonRewardCell:showReward() end)
--seq:Append(rewardListTrans:DOShakePosition(0.4, 14, 18, 90,true)) -- 轻幅度震动
seq:Append(rewardListTrans:DOShakePosition(1, 20, 18, 90,true)) -- 大力震动
else
seq:AppendCallback(function()
summonRewardCell:showReward()
end)
end
end)
seq:AppendInterval(0.1)
end)
seq:AppendCallback(function()
if callBack then
callBack()
end
end)
return seq
end
function GFunc.miningTipsMovePosY(obj, delay,callBack)
if obj.seq then
obj.seq:Kill()
obj.seq = nil
end
obj.seq = obj:createBindTweenSequence()
local trans = obj:getTransform()
local localPosY = trans.localPosition.y
local seq = obj.seq
seq:AppendInterval(delay)
seq:Append(trans:DOLocalMoveY(localPosY + 200, 1.2))
seq:AppendCallback(function()
obj:setActive(false)
if callBack then
callBack()
end
end)
end
function GFunc.dataEncrypt(data)
local numStr = CS.Security.XXTEA.Encrypt(tostring(data), GConst.SECRET_KEY)
return numStr
end
function GFunc.dataDecrypt(data)
local numStr = CS.Security.XXTEA.Decrypt(data, GConst.SECRET_KEY)
return tonumber(numStr)
end
function GFunc.getTickCount()
return math.floor(UnityTime.realtimeSinceStartup)
end
function GFunc.getTickCount2()
return math.floor(UnityTime.realtimeSinceStartup * 1000)
end
---得到展示奖励的图集名称,图片资源id
function GFunc.getFrameRes(type, id)
if type == GConst.REWARD_TYPE.REWARD_NONE then
return
end
local qlt = 1
local atlasPath = ""
if type == GConst.REWARD_TYPE.ITEM then
local ItemCfg = ConfigManager:getConfig("item")
local config = ItemCfg[id]
if not config then
return
end
qlt = config.qlt
atlasPath = GConst.ATLAS_PATH.ICON_EQUIP
end
if type == GConst.REWARD_TYPE.EQUIP then
local equipCfg = ConfigManager:getConfig("equip")
local config = equipCfg[id]
if not config then
return
end
qlt = config.qlt
atlasPath = GConst.ATLAS_PATH.ICON_EQUIP
end
if type == GConst.REWARD_TYPE.RUNES then
local runeCfg = ConfigManager:getConfig("runes")
local config = runeCfg[id]
if not config then
return
end
qlt = config.qlt
atlasPath = GConst.ATLAS_PATH.ICON_RUNE
end
return atlasPath, GConst.HERO_FRAME[ GConst.QUALITY[qlt] ] or "frame_1", qlt
end
---得到展示奖励的图集名称,图片资源id
function GFunc.getQuality(type, id)
if type == GConst.REWARD_TYPE.REWARD_NONE then
return
end
local qlt = 1
if type == GConst.REWARD_TYPE.ITEM then
local ItemCfg = ConfigManager:getConfig("item")
local config = ItemCfg[id]
if not config then
return
end
qlt = config.qlt
end
if type == GConst.REWARD_TYPE.EQUIP then
local equipCfg = ConfigManager:getConfig("equip")
local config = equipCfg[id]
if not config then
return
end
qlt = config.qlt
end
if type == GConst.REWARD_TYPE.LEGACY then
local equipCfg = ConfigManager:getConfig("legacy")
local config = equipCfg[id]
if not config then
return
end
qlt = config.qlt
end
if type == GConst.REWARD_TYPE.RUNES then
local runeCfg = ConfigManager:getConfig("runes")
local config = runeCfg[id]
if not config then
return
end
qlt = config.qlt
end
return qlt
end
function GFunc.getIconResByReward(reward)
if reward.type == GConst.REWARD_TYPE_NUM.ITEM then
return GFunc.getIconRes(reward.id)
elseif reward.type == GConst.REWARD_TYPE_NUM.EQUIP then
return GFunc.getEquipIconRes(reward.id)
end
end
---得到展示奖励的图集名称,图片资源id
function GFunc.getRewardIconRes(type, id)
if type == GConst.REWARD_TYPE.REWARD_NONE then
return
end
if type == GConst.REWARD_TYPE.ITEM then
return GFunc.getIconRes(id)
end
if type == GConst.REWARD_TYPE.EQUIP then
return GFunc.getEquipIconRes(id)
end
if type == GConst.REWARD_TYPE.RUNES then
return GFunc.getRuneIconRes(id)
end
if type == GConst.REWARD_TYPE.LEGACY then
return GFunc.getLegacyIconRes(id)
end
end
function GFunc.getIconRes(itemId)
local ItemCfg = ConfigManager:getConfig("item")
local config = ItemCfg[itemId]
if not config then
return
end
return GConst.ATLAS_PATH.ICON_ITEM, tostring(config.icon)
end
function GFunc.getEquipIconRes(equipId)
local EquipCfg = ConfigManager:getConfig("equip")
local config = EquipCfg[equipId]
if not config then
return
end
return GConst.ATLAS_PATH.ICON_EQUIP, tostring(config.icon)
end
function GFunc.getRuneIconRes(runeId)
local runeCfg = ConfigManager:getConfig("runes")
local config = runeCfg[runeId]
if not config then
return
end
return GConst.ATLAS_PATH.ICON_RUNE, tostring(config.icon)
end
function GFunc.getLegacyIconRes(legacyId)
local legacyCfg = ConfigManager:getConfig("legacy")
local config = legacyCfg[legacyId]
if not config then
return
end
return GConst.ATLAS_PATH.ICON_LEGACY, tostring(config.icon)
end
---得到展示奖励的图集名称,图片资源id
function GFunc.getRewardName(type, id)
if type == GConst.REWARD_TYPE.REWARD_NONE then
return
end
if type == GConst.REWARD_TYPE.ITEM then
return I18N:getText("item", id, "name")
end
if type == GConst.REWARD_TYPE.EQUIP then
return I18N:getText("equip", id, "desc")
end
if type == GConst.REWARD_TYPE.RUNES then
return I18N:getText("rune", id, "desc")
end
end
function GFunc.compareVersionThan(version1, version2, include)
if not version1 or not version2 then
return false
end
local versionStrs = string.split(version1, ".")
local versionNum1 = tonumber(versionStrs[1])
local versionNum2 = tonumber(versionStrs[2])
local versionNum3 = tonumber(versionStrs[3])
local versionStrs2 = string.split(version2, ".")
local versionNum21 = tonumber(versionStrs2[1])
local versionNum22 = tonumber(versionStrs2[2])
local versionNum23 = tonumber(versionStrs2[3])
if not versionNum1 or not versionNum2 or not versionNum3 or not versionNum21 or not versionNum22 or not versionNum23 then
return false
end
if versionNum1 > versionNum21 then
return true, true
elseif versionNum1 < versionNum21 then
return false
end
if versionNum2 > versionNum22 then
return true, true
elseif versionNum2 < versionNum22 then
return false
end
if versionNum3 > versionNum23 then
return true
elseif versionNum3 < versionNum23 then
return false
end
if include then
return true
end
return false
end
function GFunc.getFormatCfgRewards(rewards, onlyOne)
local cfgRewards = GFunc.getArray()
for _, reward in ipairs(rewards) do
local cfgReward = {
type = reward.type,
id = reward.id,
count = {
value = reward.count.value,
unit = reward.count.unit,
},
}
if onlyOne then
return cfgReward
else
table.insert(cfgRewards, reward)
end
end
return cfgRewards
end
function GFunc.getUpdateDataMap(fnName, dataName, dataMap, costs, rewards, fnArgs)
local params = {
fnName = fnName,
dataType = dataName,
data = dataMap,
costs = costs or GFunc.getArray(),
rewards = rewards or GFunc.getArray(),
fnArgs = fnArgs
}
return params
end
function GFunc.isShenhe()
return CS.BF.BFMain.IsShenhe
end
function GFunc.isInWhitelist()
return CS.BF.BFMain.IsWhite
end
function GFunc.getArray()
local array = {}
setmetatable(array, {__jsontype = "array"})
return array
end
function GFunc.getTable(struct)
local t = {}
if struct then
for k, v in pairs(struct) do
if type(v) == "table" then
t[k] = GFunc.getTable(v)
else
t[k] = v
end
end
end
return t
end
function GFunc.formatTimeStep(timestep)
if timestep and timestep > 10000000000 then
timestep = timestep // 1000
end
return timestep
end
function GFunc.randomPos(idx, pos)
local posX, posY
if idx == 1 then
posX = math.random(-50, 0)
posY = math.random(0, 50)
elseif idx == 2 then
posX = math.random(0, 50)
posY = math.random(0, 50)
elseif idx == 3 then
posX = math.random(-50, 0)
posY = math.random(-50, 0)
elseif idx == 4 then
posX = math.random(0, 50)
posY = math.random(-50, 0)
else
posX = math.random(-50, 50)
posY = math.random(-50, 50)
end
return posX + pos.x, posY + pos.y
end
function GFunc.imgFly(flyImg, beginPos, endPos, callback)
if flyImg.aniSeq then
flyImg.aniSeq:Kill()
end
local scale = 0.5
flyImg:setAnchoredPosition(beginPos.x, beginPos.y)
flyImg:setVisible(true, 0.1)
local maxDis = 2000
local dis = BF.Vector2Distance(beginPos, endPos)
local time = dis/maxDis
local aniSeq = flyImg:createBindTweenSequence()
-- aniSeq:Append(flyImg:getTransform():DOScale(BF.Vector3(scale + 0.2, scale + 0.2, scale + 0.2), 0.1):SetEase(CS.DG.Tweening.Ease.InCubic))
aniSeq:Append(flyImg:getTransform():DOScale(BF.Vector3(scale, scale, scale), 0.04):SetEase(CS.DG.Tweening.Ease.InCubic))
-- aniSeq:AppendInterval(0.3)
aniSeq:Append(flyImg:getTransform():DOAnchorPos(endPos, time):SetEase(CS.DG.Tweening.Ease.InCubic))
aniSeq:Join(flyImg:getTransform():DOScale(BF.Vector3(0.1, 0.1, 0.1), time):SetEase(CS.DG.Tweening.Ease.InCubic))
aniSeq:AppendCallback(function()
flyImg:setVisible(false)
if callback then
callback()
end
end)
flyImg.aniSeq = aniSeq
end
function GFunc.doScaleFlyImg(img, callback)
if img.aniSeq then
img.aniSeq:Kill()
img:setLocalScale(1, 1, 1)
end
local transform = img:getTransform()
local localScale = transform.localScale
local scale = localScale.x
local aniSeq = img:createBindTweenSequence()
aniSeq:Append(img:getTransform():DOScale(BF.Vector3(scale + 0.1, scale + 0.1, scale + 0.1), 0.08):SetEase(CS.DG.Tweening.Ease.InCubic))
aniSeq:Append(img:getTransform():DOScale(BF.Vector3(scale - 0.08, scale - 0.08, scale - 0.08), 0.08):SetEase(CS.DG.Tweening.Ease.InCubic))
aniSeq:Append(img:getTransform():DOScale(BF.Vector3(scale, scale, scale), 0.08):SetEase(CS.DG.Tweening.Ease.InCubic))
aniSeq:AppendCallback(function()
if callback then
callback()
end
end)
img.aniSeq = aniSeq
end
function GFunc.doScaleQuickZoom(img,callback)
if img.aniSeq then
img.aniSeq:Kill()
end
local transform = img:getTransform()
local aniSeq = img:createBindTweenSequence()
aniSeq:Append(transform:DOScale(1.4, 0.1))
aniSeq:Append(transform:DOScale(1, 0.06))
aniSeq:AppendCallback(function()
if callback then
callback()
end
end)
img.aniSeq = aniSeq
end
-- colorType 1 白色, 2 黑色
function GFunc.setAdsSprite(img, isGrey)
if not img then
return
end
local skip = DataManager.PrivilegeCardData:getIsSkipAd()
local icon = nil
-- if isGrey then
-- icon = skip and "common_ad_6" or "common_ad_5"
-- else
-- icon = skip and "common_ad_2" or "common_ad_1"
-- end
icon = skip and "common_ad_2" or "common_ad_1"
img:setSprite(GConst.ATLAS_PATH.COMMON, icon)
end
function GFunc.getAdSprite()
local skip = DataManager.PrivilegeCardData:getIsSkipAd()
return skip and "common_ad_2" or "common_ad_1"
end
function GFunc.centerImgAndTx(imgObj, txObj, spacing, iconOffectY, addX)
spacing = spacing or 0
addX = addX or 0
local imgW = imgObj:getSizeDelta().x
local posx, posy = imgObj:fastGetAnchoredPosition()
local txW = txObj:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO).preferredWidth
txObj:setSizeDeltaX(txW)
local w = (imgW + txW + spacing) / 2
imgObj:setAnchoredPosition(imgW / 2 - w + addX, iconOffectY or posy)
txObj:setAnchoredPositionX(w - txW / 2 + addX)
end
-- centerImgAndTx的位置反向版本
function GFunc.centerTxAndImg(txObj, imgObj, spacing, offset)
spacing = spacing or 0
offset = offset or 0
local imgW = imgObj:getSizeDelta().x
local txW = txObj:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO).preferredWidth
txObj:setSizeDeltaX(txW)
local w = (imgW + txW + spacing) / 2
txObj:setAnchoredPositionX(txW / 2 - w + offset)
imgObj:setAnchoredPositionX(w - imgW / 2 + offset)
end
function GFunc.centerTxAndTx(txObj1, txObj2, spacing)
spacing = spacing or 0
local txW = txObj1:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO).preferredWidth
txObj1:setSizeDeltaX(txW)
local txW2 = txObj2:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO).preferredWidth
txObj2:setSizeDeltaX(txW2)
local w = (txW2 + txW + spacing) / 2
txObj1:setAnchoredPositionX(txW / 2 - w)
txObj2:setAnchoredPositionX(w - txW2 / 2)
end
function GFunc.centerTxAndImgAndTx(txObj1, spacing1, imgObj, spacing2, txObj2)
local txW = txObj1:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO).preferredWidth
txObj1:setSizeDeltaX(txW)
local txW2 = txObj2:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO).preferredWidth
txObj2:setSizeDeltaX(txW2)
local imgW = imgObj:getSizeDelta().x
local w = (txW + spacing1 + imgW + spacing2 + txW2) / 2
txObj1:setAnchoredPositionX(txW / 2 - w)
imgObj:setAnchoredPositionX(txW - w + spacing1 + imgW / 2)
txObj2:setAnchoredPositionX(txW - w + spacing1 + imgW + spacing2 + txW2 / 2)
end
function GFunc.expandImgToFitTx(imgObj, txObj, spacing)
spacing = spacing or 0
local txW = txObj:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO).preferredWidth
txObj:setSizeDeltaX(txW)
imgObj:setSizeDeltaX(txW + spacing * 2)
end
function GFunc.formatAdImg(adImg)
if DataManager.PrivilegeCardData:getIsSkipAd() then
adImg:setSprite(GConst.ATLAS_PATH.COMMON, "common_ad_1")
else
adImg:setSprite(GConst.ATLAS_PATH.COMMON, "common_ad")
end
end
function GFunc.organizeCfg(cfgId, cfg)
local result = {}
result.cfgId = cfgId
result.cfg = cfg
return result
end
function GFunc.gemEnough(needNum,showToast) -- 钻石是否足够
return GFunc.checkCost(GConst.ItemConst.ITEM_ID_GEM, needNum, showToast) --判断不提示,点击才提示
end
---设置图片和文本居中, 文本需要左右居中对齐
function GFunc.setMiddlePosX(txtObj, icon, bgImg)
local txtRectWidth = txtObj:getTransform().rect.width
local iconRectWidth = icon:getTransform().rect.width
local bgImgRectWidth = bgImg:getTransform().rect.width
local halfBgWidth = bgImgRectWidth * 0.5
-- 文本的宽度
local meshPro = txtObj:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO)
local width = meshPro.preferredWidth
local txtMinWidth = math.max(width, txtRectWidth)
-- 以bg中心点为锚点时
-- 文本距离边界的距离
local txtPadding = halfBgWidth - txtMinWidth
txtPadding = txtPadding > 0 and txtPadding or 0
-- 图片距离边界距离
local iconPadding = halfBgWidth - iconRectWidth
iconPadding = iconPadding > 0 and iconPadding or 0
local maxPadding = math.max(txtPadding, iconPadding)
local minPadding = math.min(txtPadding, iconPadding)
local offset = (maxPadding - minPadding) * 0.5
if txtPadding > iconPadding then
txtObj:setAnchoredPositionX(txtMinWidth * 0.5 + offset)
icon:setAnchoredPositionX(-iconRectWidth * 0.5 + offset)
else
txtObj:setAnchoredPositionX(txtMinWidth * 0.5 - offset)
icon:setAnchoredPositionX(-iconRectWidth * 0.5 - offset)
end
end
---计算最小值
function GFunc.getCalcMinVal(arr)
local min = arr[1]
for i, v in ipairs(arr) do
if min > v then
min = v
end
end
return min
end
---计算最大值
function GFunc.getCalcMaxVal(arr)
local max = arr[1] or 0
for i, v in ipairs(arr) do
if max < v then
max = v
end
end
return max
end
function GFunc.getRewardTableByRewardList(rewardList)
local newRewards = {}
for _, reward in ipairs(rewardList) do
table.insert(newRewards, reward)
end
return newRewards
end
function GFunc.getRewardTableByReward(reward)
return GFunc.getRewardTable(reward.type, reward.id, reward.count)
end
function GFunc.getRewardTable(type, id, count)
if type == GConst.REWARD_TYPE.EQUIP then
return GFunc.getServerEquipRewardTable(id, count)
end
return {
type = type,
id = id,
count = count
}
end
function GFunc.formatRewardsToServerStruct(rewardList)
local rewards = {}
for _, reward in ipairs(rewardList) do
local serverReward = GFunc.getServerRewardTable(reward.type, reward.id, reward.count)
table.insert(rewards, serverReward)
end
return rewards
end
function GFunc.getServerRewardTable(type, id, count)
if type == GConst.REWARD_TYPE.ITEM then
return GFunc.getServerItemRewardTable(id, count)
end
end
function GFunc.getServerItemRewardTable(id, count)
local reward = {
type = GConst.REWARD_TYPE.ITEM,
item = {
id = id,
count = count
},
}
return reward
end
function GFunc.getServerRuneRewardTable(id, level)
return {
type = GConst.REWARD_TYPE.RUNES,
rune = {
id = id,
level = level,
},
}
end
function GFunc.getServerEquipRewardTable(id, level, count)
local reward = {
type = GConst.REWARD_TYPE.EQUIP,
equip = {
id = id,
level = level,
count = count
},
}
return reward
end
function GFunc.checkTableValueSame(standardTable, compareTable, debug)
if type(standardTable) ~= "table" or type(compareTable) ~= "table" then
if debug and standardTable ~= compareTable then
Logger.logHighlight(standardTable)
end
return standardTable == compareTable
end
for k, v in pairs(standardTable) do
local v2 = compareTable[k]
if v2 == nil then
if debug then
Logger.logHighlight(k)
end
return false
end
if not GFunc.checkTableValueSame(v, v2, debug) then
return false
end
end
return true
end
function GFunc.showCurrencyFlyAction(rewards, pos)
local flyPos = {}
if not pos then
pos = {x = 0, y = 0}
else
local sPoint = UIManager:getUICameraComponent():WorldToScreenPoint(pos)
pos = CS.BF.Utils.RectTransformScreenPointToLocalPointInRectangle(UIManager:getMainCanvasTransform(), sPoint.x, sPoint.y, UIManager:getUICameraComponent())
end
for i, reward in ipairs(rewards) do
if reward.type == GConst.REWARD_TYPE.ITEM then
local allPos = {}
for i = 1, 4 do
local posX, posY = GFunc.randomPos(i, pos)
allPos[i] = {x = posX, y = posY}
end
flyPos[reward.item.id] = allPos
end
end
UIManager:showCurrencyAction(flyPos)
end
function GFunc.getSkillEffectStr(id, lv)
local str = I18N:getText("skill", id, "desc")
local cfg = ConfigManager:getConfig("skill")[id]
local baseNum = cfg.string_num_base
local growNum = cfg.string_num_grow
local tab = {}
for i,v in ipairs(baseNum) do
table.insert(tab, baseNum[i] + (lv - 1)*growNum[i])
end
local idx = 0
str = string.gsub(str, '{%d+}', function (s)
idx = idx + 1
return tostring(tab[idx])
end)
return str
end
function GFunc.goTargetElasticityY(obj, onlyKill, offset, punchY, callBack)
if obj.shakeSeq then
obj.shakeSeq:Kill()
obj.shakeSeq = nil
end
if onlyKill then
return
end
local curPosY = obj:getAnchoredPositionY()
local objTrans = obj:getTransform()
obj.shakeSeq = obj:createBindTweenSequence()
obj.shakeSeq:Append(objTrans:DOLocalMoveY(curPosY - offset / 2,0.1))
obj.shakeSeq:Append(objTrans:DOLocalMoveY(curPosY + offset * 2 ,0.1))
obj.shakeSeq:Join(objTrans:DOPunchScale({x=0,y=punchY,z = 0},0.2, 6))
obj.shakeSeq:AppendCallback(function()
if callBack then
callBack()
end
end)
return obj.shakeSeq
end
function GFunc.goTargetPosXShake(obj, onlyKill, targetX, offset, callBack)
if obj.shakeSeq then
obj.shakeSeq:Kill()
obj.shakeSeq = nil
end
if onlyKill then
return
end
obj.shakeSeq = obj:createBindTweenSequence()
local objTrans = obj:getTransform()
local seq = obj.shakeSeq
seq:Append(objTrans:DOLocalMoveX(targetX,0.12))
seq:Append(objTrans:DOLocalMoveX(targetX + offset,0.1))
seq:Append(objTrans:DOLocalMoveX(targetX - offset / 3,0.05))
seq:Append(objTrans:DOLocalMoveX(targetX, 0.1))
seq:AppendCallback(function()
if callBack then
callBack()
end
end)
return obj.shakeSeq
end
function GFunc.getRewardId(reward)
if reward.id_for_nothing then
return CS.BF.Utils.GetRewardNumber(reward.id_for_nothing)
else
return reward.id
end
end
function GFunc.getRewardNum(reward)
if reward.num_for_nothing then
return CS.BF.Utils.GetRewardNumber(reward.num_for_nothing)
else
return reward.num or reward.count
end
end
function GFunc.getRewardType(reward)
if reward.type_for_nothing then
return CS.BF.Utils.GetRewardNumber(reward.type_for_nothing)
else
return reward.type
end
end
function GFunc.DOBFSliderValue(slider, endValue, duration, snapping)
return CS.BF.Utils.DOBFSliderValue(slider, endValue, duration, snapping)
end
function GFunc.intToString(int)
return GConst.INT_TO_STRING[int] or tostring(int)
end
function GFunc.getTempList()
for i = 1, #TEMP_LIST do
table.remove(TEMP_LIST)
end
return TEMP_LIST
end
function GFunc.recycleTempList()
for i = 1, #TEMP_LIST do
table.remove(TEMP_LIST)
end
end
function GFunc.getTempMap()
for k, v in pairs(TEMP_MAP) do
TEMP_MAP[k] = nil
end
return TEMP_MAP
end
function GFunc.recycleTempMap()
for k, v in pairs(TEMP_MAP) do
TEMP_MAP[k] = nil
end
end
-- 设置tabLe只速 出现改写会抛出Lua error
-- 用法locaL readOnlyCfg = GFunc.readOnlyTab(cfg) return readOnlyCfg
-- 增加了防重置设置read_onLy的机制
-- Lua5.3支持 1) table库支持调用元方法所以table.remove table.insert也会抛出错误,
-- 2)不用定义_ipairs 5.3 ipairs迭代器支持访问元方法__indexpairs迭代器next不支持故需要元方法_pairs
-- 低版本Lua此网数不能完全按照预期工作
function GFunc.readOnlyTab(inputTable)
local travelled_tables = {}
local function _read_only(tbl)
if not travelled_tables[tbl] then
local tbl_mt = getmetatable(tbl)
if not tbl_mt then
tbl_mt = {}
setmetatable(tbl, tbl_mt)
end
local proxy = tbl_mt._read_only__proxy
if not proxy then
proxy = {}
tbl_mt.__read_only_proxy = proxy
local proxy_mt = {
__index = tbl,
__newindex = function (t, k, v) error( "error write to a read-only table with key = " .. tostring(k)) end,
__pairs = function (t) return pairs(tbl) end,
-- __ipairs = function (t) return ipairs(tbl) end, 5.3版本不需要此方法
_len = function (t) return #tbl end,
__read_only_proxy = proxy
}
setmetatable(proxy, proxy_mt)
end
travelled_tables[tbl] = proxy
for k, v in pairs(tbl) do
if type(v) == "table" then
tbl[k] = _read_only(v)
end
end
end
return travelled_tables[tbl]
end
return _read_only(inputTable)
end
function GFunc.encryptNumber(value)
-- return value + GConst.NUMBER_ENCRYPTION_CONSTANT
return value
end
function GFunc.decryptNumber(value)
-- return value - GConst.NUMBER_ENCRYPTION_CONSTANT
return value
end
function GFunc.formatPlayerName(name)
if name == nil or #name == 0 then
name = I18N:getGlobalText(I18N.GlobalConst.NEW_PLAYER)
end
return name
end
-- info = {array_heroes, heroes_equips, skins, heroes_runes} -- 服务器返回的数据
function GFunc.formatPlayerFormationInfo(info)
local formation = {}
if not info.heroes then
return formation
end
-- 天赋
if info.talent then
local TalentCfg = ConfigManager:getConfig("talent")
local allAttr = {}
for id = 1, #TalentCfg do
local cfg = TalentCfg[id]
local lv = info.talent[id] or 0
if lv and lv > 0 and cfg.attr then
for _, v in ipairs(cfg.attr) do
allAttr[v.type] = (allAttr[v.type] or 0) + v.num * lv
end
end
end
-- 处理全局属性
local attr = {}
for _, v in pairs(GConst.ATTR_ALL) do
attr[v] = allAttr[v]
end
DataManager.HeroDataOther:setTalentAttr(attr)
end
for index, info in ipairs(info.heroes) do
-- 只是配置检测
if DataManager.HeroData:isExistHeroById(info.id) then
local heroEntity = DataManager.HeroDataOther:getEntity(info)
formation[heroEntity:getMatchType()] = heroEntity
end
end
info.equips = info.equips or {}
info.skins = info.skins or {}
info.heroes_runes = info.heroes_runes or {}
-- 有全局的属性 需要在最后重新计算
for _, entity in pairs(formation) do
entity:setAttrDirty()
end
-- for matchType, heroEntity in pairs(formation) do
-- local heroId = heroEntity:getCfgId()
-- -- 处理装备
-- local equipInfo = info.heroes_equips[heroId]
-- if not equipInfo then
-- equipInfo = {equips = {}}
-- end
-- for partName, partType in pairs(GConst.EquipConst.PART_TYPE) do
-- local level = equipInfo.equips[partType] or 0
-- local equipEntity = DataManager.EquipData:createEntity(heroId, partType, level)
-- equipEntity:setHeroEntity(heroEntity)
-- heroEntity:setEquips(partType, equipEntity)
-- end
-- -- 处理皮肤
-- local skinIds = {}
-- for idx, skinId in pairs(info.skins) do
-- if DataManager.SkinData:getOriginSkinId(heroId) ~= skinId and DataManager.SkinData:getHeroIdBySkinId(skinId) == heroId then
-- table.insert(skinIds, skinId)
-- end
-- end
-- if #skinIds > 0 then
-- heroEntity:setSkins(skinIds)
-- end
-- -- 处理符文
-- if info.heroes_runes[heroId] == nil then
-- info.heroes_runes[heroId] = {grids = {}}
-- end
-- local runesEntity = DataManager.RunesData:createEntity(heroId, info.heroes_runes[heroId].grids)
-- heroEntity:setRunes(runesEntity)
-- end
return formation
end
function GFunc.randomDrop(dropList)
local weightArr = {}
for i, v in ipairs(dropList) do
weightArr[i] = v.weight
end
local idx = GFunc.getRandomIndex(weightArr)
return dropList[idx]
end
-- 获取属性描述和数值
function GFunc.getStarImg(starType, currStar)
if currStar and currStar == 0 then
return GConst.ATLAS_PATH.COMMON, "common_star_0"
elseif starType == GConst.HeroConst.STAR_TYPE.LV_1 then
return GConst.ATLAS_PATH.COMMON, "common_star_1"
elseif starType == GConst.HeroConst.STAR_TYPE.LV_2 then
return GConst.ATLAS_PATH.COMMON, "common_star_2"
else
return GConst.ATLAS_PATH.COMMON, "common_star_3"
end
end
function GFunc.getHeroQltImg(qlt)
return GConst.ATLAS_PATH.HERO, "hero_quality_" .. qlt
end
function GFunc.getHeroIcon(icon)
return GConst.ATLAS_PATH.ICON_HERO, tostring(icon)
end
function GFunc.getHeroQltStr(qlt)
return I18N:getGlobalText("QLT_DESC_" .. qlt)
end
-- 通用
function GFunc.getQltColor(qlt)
qlt = qlt or GConst.QLT_TYPE.NORMAL
return GConst.QUALITY_TYPE[qlt]
end
-- 无描边用
function GFunc.getQltColorNoOutline(qlt)
qlt = qlt or GConst.QLT_TYPE.NORMAL
return GConst.QLT_COLOR_NO_OUTLINE[qlt]
end
---- 返回一个显示等间距但是数值不等间距的sliderValue
-- defaultValue 值代表第一段少了平均每段的值
function GFunc.getUnevenSliderValue(list, value, defaultValue)
local count = #list
if count <= 0 then
return 0
end
local pervalue = 1 / (count - (defaultValue or 0))
local firstValue = 1 / (defaultValue or 1)
local per = 0
local pervalue2 = 0
for index, v in ipairs(list) do
if index == 1 then
pervalue2 = pervalue / firstValue
else
pervalue2 = pervalue
end
if v <= value then
per = per + pervalue2
else
local before = list[index - 1]
if not before then
before = 0
end
per = per + (value - before) / math.max((v - before), 1) * pervalue2
break
end
end
return per
end
function GFunc.getAttrNameCfg()
local AttrNameCfg = ConfigManager:getConfigWithOtherKey("attr", "name")
return AttrNameCfg
end
function GFunc.showCommonBoxUI(id, showTips)
ModuleManager.CommonManager:showCommonBoxUI(id, showTips)
end
function GFunc.colorText(color, str)
local backStr = ""
backStr = string.format("<color=".. color.. ">%s</color>", str)
return backStr
end
--@region 战斗力
function GFunc.hidePowerToast()
ModuleManager.PowerToastManager:hideToast()
end
function GFunc.showPowerToast(before, after, posY)
if not before or not after then
return
end
ModuleManager.PowerToastManager:showToast(before, after, posY)
end
--@endregion
--@region 属性相关
function GFunc.getFinalAttrValue(attrName, attrNum, decimal)
local cfg = ConfigManager:getConfigWithOtherKey("attr", "name")[attrName]
if cfg and cfg.is_percent then
return GFunc.num2Str(attrNum / 100, decimal) .. "%"
else
return attrNum // GConst.DEFAULT_FACTOR
end
end
--@TODO 2025-09-11 11:54:20
function GFunc.getPerStr(key, str, ispercent)
if ispercent or key == GConst.BattleConst.BUFF_NAME.ATKP_ADD or
key == GConst.BattleConst.BUFF_NAME.ATKP_COLOR_ADD or
key == GConst.BattleConst.BUFF_NAME.ATKP_RED_ADD or
key == GConst.BattleConst.BUFF_NAME.ATKP_YELLOW_ADD or
key == GConst.BattleConst.BUFF_NAME.ATKP_GREEN_ADD or
key == GConst.BattleConst.BUFF_NAME.ATKP_BLUE_ADD or
key == GConst.BattleConst.BUFF_NAME.ATKP_PURPLE_ADD or
key == GConst.BattleConst.BUFF_NAME.DEC_DMG_RED_ADD or
key == GConst.BattleConst.BUFF_NAME.DEC_DMG_YELLOW_ADD or
key == GConst.BattleConst.BUFF_NAME.DEC_DMG_GREEN_ADD or
key == GConst.BattleConst.BUFF_NAME.DEC_DMG_BLUE_ADD or
key == GConst.BattleConst.BUFF_NAME.DEC_DMG_PURPLE_ADD or
key == GConst.BattleConst.BUFF_NAME.DEC_DMG_ALL_ADD or
key == GConst.BattleConst.BUFF_NAME.WEAKNESS_RED_ADD or
key == GConst.BattleConst.BUFF_NAME.WEAKNESS_YELLOW_ADD or
key == GConst.BattleConst.BUFF_NAME.WEAKNESS_GREEN_ADD or
key == GConst.BattleConst.BUFF_NAME.WEAKNESS_BLUE_ADD or
key == GConst.BattleConst.BUFF_NAME.WEAKNESS_PURPLE_ADD or
key == GConst.BattleConst.BUFF_NAME.WEAKNESS_ALL_ADD or
key == GConst.BattleConst.BUFF_NAME.DMG_ADDITION_RED_ADD or
key == GConst.BattleConst.BUFF_NAME.DMG_ADDITION_YELLOW_ADD or
key == GConst.BattleConst.BUFF_NAME.DMG_ADDITION_GREEN_ADD or
key == GConst.BattleConst.BUFF_NAME.DMG_ADDITION_BLUE_ADD or
key == GConst.BattleConst.BUFF_NAME.DMG_ADDITION_PURPLE_ADD or
key == GConst.BattleConst.BUFF_NAME.DMG_ADDITION_ALL_ADD or
key == GConst.BattleConst.BUFF_NAME.HPP_ADD or
key == GConst.BattleConst.BUFF_NAME.CRIT_TIME_ADD or
key == GConst.BattleConst.BUFF_NAME.EXP_TIME_ADD or
key == GConst.BattleConst.BUFF_NAME.CURED_ADD or
key == GConst.BattleConst.BUFF_NAME.POISON or
key == GConst.BattleConst.BUFF_NAME.SHIELD or
key == GConst.BattleConst.BUFF_NAME.SHIELD_REBOUND_200 or
key == GConst.BattleConst.BUFF_NAME.VULNERABLE or
key == GConst.BattleConst.BUFF_NAME.CORRUPT or
key == GConst.BattleConst.BUFF_NAME.BLEED or
key == GConst.BattleConst.BUFF_NAME.WEAKEN or
key == GConst.BattleConst.BUFF_NAME.COUNTER_ATTACK or
key == GConst.BattleConst.BUFF_NAME.THORNS or
key == GConst.BattleConst.BUFF_NAME.SHIELD_REBOUND_400 or
key == GConst.BattleConst.BUFF_NAME.SHIELD_ICE_REBOUND_400 or
key == GConst.BattleConst.BUFF_NAME.BURN or
key == GConst.BattleConst.BUFF_NAME.SHIELD_ICE or
key == GConst.BattleConst.BUFF_NAME.SHIELD_ICE_02 or
key == GConst.BattleConst.BUFF_NAME.BLOCK or
key == GConst.BattleConst.BUFF_NAME.CRIT_ADD or
key == GConst.BattleConst.COUNTER_ATTACK or
key == GConst.BattleConst.BUFF_NAME.SHIELD_ICE_REBOUND_200 or
key == GConst.BattleConst.BUFF_NAME.SHIELD_REBOUND_100 or
key == GConst.BattleConst.BUFF_NAME.SKILL_HURT_ADD_SHOW
then
str = str // 100 .. "%"
end
return str
end
function GFunc.getFinalBuffValue(buffName, attrNum, decimal)
local cfg = ConfigManager:getConfigWithOtherKey("buff", "name")[buffName]
if cfg and cfg.is_percent then
return GFunc.num2Str(attrNum / 100, decimal) .. "%"
else
return attrNum // GConst.DEFAULT_FACTOR
end
end
function GFunc.getBuffDesc(buffName, effectNum)
effectNum = GFunc.getFinalBuffValue(buffName, effectNum)
return I18N:getTextWithOtherKey("buff", "name", buffName, "desc", effectNum)
end
function GFunc.getAttrDesc(attrName, attrNum)
return I18N:getTextWithOtherKey("attr", "name", attrName, "desc", GFunc.getFinalAttrValue(attrName, attrNum))
end
-- 属性id转属性名
function GFunc.getAttrNameById(id)
local cfg = ConfigManager:getConfig("attr")[id]
if cfg then
return cfg.name
end
if EDITOR_MODE then
Logger.logError("没有找到属性id:" .. tostring(id))
end
return nil
end
-- 属性名转属性id
function GFunc.getAttrIdByName(type)
for id, info in pairs(ConfigManager:getConfig("attr")) do
if info.name == type then
return id
end
end
if EDITOR_MODE then
Logger.logError("没有找到属性名:" .. tostring(type))
end
return nil
end
function GFunc.getAttrNameByType(type)
local key = GFunc.getAttrIdByName(type)
return I18N:getText("attr", key, "name")
end
--@endregion
-- 设置文本长度
function GFunc.setTextLength(textObj)
local meshProComp = textObj:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO)
local contentWidth = meshProComp.preferredWidth
textObj:setSizeDeltaX(contentWidth)
end
return GFunc