local LuaEventListener = LuaEventListener local LuaClickListener = LuaClickListener local LuaDragListener = LuaDragListener local LuaDragExtendListener = LuaDragExtendListener local Application = Application local GameObject = GameObject local Util = Util local table_insert = table.insert local unpack = unpack local is_50_version = EnglineVersion and AppConst_EnglineVer >= 50 local is_52_version = EnglineVersion and AppConst_EnglineVer >= 52 local is_61_version = EnglineVersion and AppConst_EnglineVer >= 61 --判断游戏对象是否已经被销毁为 null function IsNull(obj) if obj == nil or obj == false then return true end return Util.Equals(obj, nil) end function GetChildTransforms(transform, names) if transform then local childs = {} if is_52_version then local objs = Util.GetChildTransforms(transform, names) for i = 0,objs.Length - 1 do table_insert(childs, objs[i]) end else for i = 1, #names do table_insert(childs, transform:FindChild(names[i])) end end return unpack(childs) end end function GetChildGameObjects(transform, names) if transform then local childs = {} if is_52_version then local objs = Util.GetChildGameObjects(transform, names) for i = 0,objs.Length - 1 do table_insert(childs, objs[i]) end else for i = 1, #names do table_insert(childs, transform:FindChild(names[i]).gameObject) end end return unpack(childs) end end function GetChildImages(transform, names) if transform then local childs = {} if is_52_version then local objs = Util.GetChildImages(transform, names) for i = 0,objs.Length - 1 do table_insert(childs, objs[i]) end else for i = 1, #names do table_insert(childs, transform:FindChild(names[i]):GetComponent("Image")) end end return unpack(childs) end end function GetChildTexts(transform, names) if transform then local childs = {} if is_52_version then local objs = Util.GetChildTexts(transform, names) for i = 0,objs.Length - 1 do table_insert(childs, objs[i]) end else for i = 1, #names do table_insert(childs, transform:FindChild(names[i]):GetComponent("Text")) end end return unpack(childs) end end --打印方法的调用位置 function PrintFunctionCallPos(function_name, stack_layer) if RuntimePlatform and (SystemRuntimePlatform.IsAndroid() or SystemRuntimePlatform.IsIphone()) then return end local create_info = debug.getinfo(stack_layer or 3, "Sl") local print_msg = "" if create_info then function_name = function_name or "" print_msg = string.format("%s calledPos = %s[%d]",function_name, create_info.source,create_info.currentline) print(print_msg) end return print_msg end function NewTable() PrintFunctionCallPos("NewTable") return {} end --输出报错栈 function TraceBack(str) if RuntimePlatform and (SystemRuntimePlatform.IsAndroid() or SystemRuntimePlatform.IsIphone()) then return end if str then LogError("error_reason is: ".. str .. debug.traceback("", 2)) else LogError(debug.traceback("", 2)) end end function tracebackex() local ret = "" local level = 3 ret = ret .. "stack traceback:\n" -- while true do --get stack info local info = debug.getinfo(level, "Sln") if not info then return end if info.what == "C" then -- C function ret = ret .. tostring(level) .. "\tC function\n" else -- Lua function ret = ret .. string.format("\t[%s]:%d in function `%s`\n", info.short_src, info.currentline, info.name or "") end --get local vars local i = 1 while true do local name, value = debug.getlocal(level, i) if not name then break end ret = ret .. "\t\t" .. name .. " =\t" .. tostringex(value, 3) .. "\n" i = i + 1 end level = level + 1 -- end return ret end function tostringex(v, len) if len == nil then len = 0 end local pre = string.rep('\t', len) local ret = "" if type(v) == "table" then if len > 5 then return "\t{ ... }" end local t = "" for k, v1 in pairs(v) do t = t .. "\n\t" .. pre .. tostring(k) .. ":" t = t .. tostringex(v1, len + 1) end if t == "" then ret = ret .. pre .. "{ }\t(" .. tostring(v) .. ")" else if len > 0 then ret = ret .. "\t(" .. tostring(v) .. ")\n" end ret = ret .. pre .. "{" .. t .. "\n" .. pre .. "}" end else ret = ret .. pre .. tostring(v) .. "\t(" .. type(v) .. ")" end return ret end --捕获报错 is_safe = false 表示有异常 可以在else里用替换方法 function TryCatch(func, ...) local args = { ... } local paramCount = select('#', ...) args = {xpcall(func, TraceBack, unpack(args, 1, paramCount))} local is_safe = table.remove(args, 1) return is_safe, args end function ShowBlackGround(alpha, show_type, sky_res, parent) if not lua_viewM.main_cancas_last_visible or lua_viewM.is_lock_screen then return end if show_type and show_type == 2 then MainCamera:getInstance():ShowBlackSky(sky_res) else if global_black_ground_go == nil then global_black_ground_go = UiFactory.createChild(parent or MainCamera.Instance.camera_gameObject.transform, UIType.SpriteRenderer, "global_black_ground_go") lua_resM:loadSprite(UiFactory, "uiComponent_asset", "com_black", function(objs) if objs[0] then global_black_ground_go:GetComponent("SpriteRenderer").sprite = objs[0] global_black_ground_go.transform.localPosition = Vector3(0, 0, 1) global_black_ground_go.transform.localScale = Vector3.one * 10 SetLocalRotation(global_black_ground_go.transform, 0) global_black_ground_go:GetComponent("SpriteRenderer").color = Color(1 ,1 ,1 ,alpha or 0.8) end end) else if parent then global_black_ground_go.transform:SetParent(parent) end end global_black_ground_go:SetActive(true) local main_role = Scene.Instance:GetMainRole() if main_role then main_role:AddSceneObject() end end end function HideBlackGround(show_type, sky_res) if show_type and show_type == 2 then MainCamera:getInstance():HideBlackSky(sky_res) else if global_black_ground_go then global_black_ground_go:SetActive(false) local main_role = Scene.Instance:GetMainRole() if main_role then main_role:RemoveScreenObj() end end end end function SetAlphaBlackGround() if global_black_ground_go then local compoent = global_black_ground_go:GetComponent("Image") if compoent then compoent.alpha = 0 end local main_role = Scene.Instance:GetMainRole() if main_role then main_role:RemoveScreenObj() end end end function FindBone(transform, bone_name) if transform then --先从一级子节点找起 local obj = transform.Find(transform, bone_name) if obj then return obj end --[[ -- gameObject.name对比有GCAlloc local objs = transform:GetComponentsInChildren(typeof(UnityEngine.Transform)) for i=1,objs.Length do if objs[i-1].name == bone_name then return objs[i-1] end end ]] local count = transform.childCount for i=1,count do local child_trans = transform:GetChild(i-1) local child_obj = FindBone(child_trans, bone_name) if child_obj then return child_obj end end end return nil end function SetChildRenderQueue(game_object,ignore_bone,render_queue, ignore_mat) if game_object then local objs = game_object:GetComponentsInChildren(typeof(UnityEngine.Renderer)) for i=1,objs.Length do if objs[i-1].name ~= ignore_bone then local mats = objs[i-1].sharedMaterials for i=0, mats.Length - 1 do if ignore_mat and mats[i].name ~= ignore_mat then mats[i].renderQueue = render_queue end end end end end end --输出日志-- function log( ... ) lua_logM:Log( ... ) end --错误日志-- function LogError( ... ) lua_logM:LogError( ... ) end --警告日志-- function logWarn( ... ) lua_logM:LogWarn( ... ) end --查找对象-- function find(str) return GameObject.Find(str); end function destroy(obj,immediate) if not obj then return end if immediate then GameObject.DestroyImmediate(obj) else GameObject.Destroy(obj); end end function newObject(prefab) --print("-----newObject------",prefab) return Util.newObject(prefab) end function Trim(str) --去除字符串str两端空格 -- @param str 需要去除空格的字符串 --[[ local p1, p2, s = string.find(str, "^%s*(.-)%s*$") if p1 then return s else return str end]] if str == nil or type(str) == "table" then return "" end str = string.gsub(str, "^[ \t\n\r]+", "") return string.gsub(str, "[ \t\n\r]+$", "") -- return (string.gsub(str, "^%s*(.-)%s*$", "%1")) end function Join(join_table, joiner) -- 以某个连接符为标准,返回一个table所有字段连接结果 -- @param join_table 连接table -- @param joiner 连接符 -- @param return 用连接符连接后的字符串 if #join_table == 0 then return "" end local fmt = "%s" for i = 2, #join_table do fmt = fmt .. joiner .. "%s" end return string.format(fmt, unpack(join_table)) end function Printf(fmt, ...) -- 格式化输出字符串,类似c函数printf风格 print(string.format(fmt, ...)) end function DeepCopy(object) -- @param object 需要深拷贝的对象 -- @return 深拷贝完成的对象 local lookup_table = {} local function _copy(object) if type(object) ~= "table" then return object elseif lookup_table[object] then return lookup_table[object] end local new_table = {} lookup_table[object] = new_table for index, value in pairs(object) do new_table[_copy(index)] = _copy(value) end return setmetatable(new_table, getmetatable(object)) end return _copy(object) end function RemoveRepeat(list, equal_func) local new_list = {} local have = false for k,v in pairs(list or {}) do have = false for kk,vv in pairs(new_list) do if equal_func(v, vv) then have = true break end end if not have then table.insert( new_list, v ) end end return new_list end function ToBoolean(s) -- 将字符串转换为boolean值 local transform_map = { ["true"] = true, ["false"] = false, } return transform_map[s] end --[[ 性别转换 ]] function GetSexByCareer(career_id) for index,data in pairs(Config.Career) do if data.career_id == career_id then return data.sex end end return 1 end --将 szFullString 对象拆分为一个子字符串表 function Split(szFullString, szSeparator, start_pos) if not szFullString or not szSeparator then return {} end local nFindStartIndex = start_pos or 1 local nSplitIndex = 1 local nSplitArray = {} while true do local nFindLastIndex = string.find(szFullString, szSeparator, nFindStartIndex) if not nFindLastIndex then nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, string.len(szFullString)) break end table.insert(nSplitArray, string.sub(szFullString, nFindStartIndex, nFindLastIndex - 1)) nFindStartIndex = nFindLastIndex + string.len(szSeparator) nSplitIndex = nSplitIndex + 1 end return nSplitArray end -- 通过一个指定的字符串切割另一个字符串 function SplitByStr(str, delimeter) local res = {} if not str or not delimeter then return res end local find, sub, insert = string.find, string.sub, table.insert local start, start_pos, end_pos = 1, 1, 1 while true do start_pos, end_pos = find(str, delimeter, start, true) if not start_pos then break end insert(res, sub(str, start, start_pos - 1)) start = end_pos + 1 end insert(res, sub(str, start)) return res end -- 根据国家获得不同的html文本 function GetHtmlColorStringByCountry(realm,label) return ""..label.."" -- return ""..label.."" --旧的 end --访问common目录的资源 function toURL(url) return "common/"..url -- return url end --[[ * 得到进阶前缀 * @param id * @return * --]] function getJinjiePreFix(id, type) local arr={"", "[1阶]", "[2阶]", "[3阶]", "[4阶]", "[5阶]", "[6阶]", "[7阶]", "[8阶]", "[9阶]", "[10阶]", "[11阶]", "[12阶]", "[13阶]", "[14阶]", "[15阶]", "[16阶]", "[17阶]", "[18阶]"} local str = arr[id + 1] if str == nil then return "" end if type ~= nil then str = string.gsub(str, "%[", "") str = string.gsub(str, "%]", "") end return str end --连接两个tab function TableConcat(tab1,tab2) local tab = {} for i=1,#tab1 do table.insert(tab,tab1[i]) end for j=1,#tab2 do table.insert(tab,tab2[j]) end return tab end function TableContains(tb,item) if table == nil or item == nil then return false end for key, value in pairs(tb) do if item == value then return true end end return false end function TableRemove(tb,item) if tb == nil or item == nil then return end for key, value in pairs(tb) do if item == value then table.remove(tb,key) return end end end function GetMaxLenString(str,max) local data = {} local charlen = 0 local len = 0 local string = "" --[[ UTF8的编码规则: 1. 字符的第一个字节范围: 0x00—0x7F(0-127),或者 0xC2—0xF4(194-244); UTF8 是兼容 ascii 的,所以 0~127 就和 ascii 完全一致 2. 0xC0, 0xC1,0xF5—0xFF(192, 193 和 245-255)不会出现在UTF8编码中 3. 0x80—0xBF(128-191)只会出现在第二个及随后的编码中(针对多字节编码,如汉字) ]] for v in string.gmatch(str,"[%z\1-\127\194-\244][\128-\191]*") do table.insert(data,v) end for i,v in ipairs(data) do if string.len(v) > 1 then charlen = 1 -- 汉字的长度重置为1 else charlen = 1 end len = len + charlen string = string .. v if len >= max then break end end return string,len end --[[ @四舍五入 --]] function round(number) return math.floor(number + 0.5) end --[[ @延迟执行 @func 延迟回调函数 @time 延迟时间(秒) @arg 延迟回调参数 --]] function setTimeout(func,time,...) local arg = {...} if func == nil or type(func) == "number" then return end local timeOutId = nil local timeFunc = function() func(unpack(arg)) GlobalTimerQuest:CancelQuest(timeOutId) func = nil end timeOutId = GlobalTimerQuest:AddDelayQuest(timeFunc,time) return timeOutId end function ChineseNumber(num) if num == nil then return end local chinese_num = {"零","一", "二", "三", "四", "五", "六", "七", "八", "九"} local tem_name_list = {"","十","百","千","万",""} local num_str = tostring(num) local num_len = string.len(num_str) local final_content = {} local cell_content = "" for i = 1, num_len do if string.sub(num_str,i,i) == "0" then if num_len > 1 and (i == num_len or tonumber(string.sub(num_str,i+1,num_len)) == 0) then --尾数的零不显示 cell_content = "" else cell_content = chinese_num[1] end else if (string.sub(num_str,i,i) + 1) == 2 and (num_len - i + 1) == num_len and num_len > 1 then --防止两位数以上第一个数字出现 一 比如 一十 cell_content = tem_name_list[num_len - i + 1] else cell_content = chinese_num[string.sub(num_str,i,i) + 1] .. tem_name_list[num_len - i + 1] end end if i == 1 or cell_content ~= chinese_num[1] or final_content[i-1] ~= chinese_num[1] then --避免中间出现重复的零 table.insert(final_content,cell_content) end end return table.concat(final_content) end --罗马数字转换Ⅰ、Ⅱ、Ⅲ、Ⅳ、Ⅴ、Ⅵ、Ⅶ、Ⅷ、Ⅸ function RomeNumber(num) if num == nil then return end local chinese_num = {"N","Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ", "Ⅴ", "Ⅵ", "Ⅶ", "Ⅷ", "Ⅸ"} local tem_name_list = {"","X","C","M"} local num_str = tostring(num) local num_len = string.len(num_str) local final_content = {} local cell_content = "" for i = 1, num_len do if string.sub(num_str,i,i) == "0" then if num_len > 1 and (i == num_len or tonumber(string.sub(num_str,i+1,num_len)) == 0) then --尾数的零不显示 cell_content = "" else cell_content = chinese_num[1] end else if (string.sub(num_str,i,i) + 1) == 2 and (num_len - i + 1) == num_len and num_len > 1 then --防止两位数以上第一个数字出现 一 比如 一十 cell_content = tem_name_list[num_len - i + 1] else cell_content = chinese_num[string.sub(num_str,i,i) + 1] .. tem_name_list[num_len - i + 1] end end if i == 1 or cell_content ~= chinese_num[1] or final_content[i-1] ~= chinese_num[1] then --避免中间出现重复的零 table.insert(final_content,cell_content) end end return table.concat(final_content) end -- function GetMoneyTypeRes( money_type )--1绑钱,2绑金,3金币 -- local res = "" -- if money_type == 1 then -- res = "comp:xx_btongIcon" -- elseif money_type == 2 then -- res = "comp:xx_bgoldIcon" -- elseif money_type == 3 then -- res = "comp:xx_goldIcon" -- end -- print("xxxxxxxxxxxxxxxxxxxxxx",money_type,res) -- return res -- end --0:物品, 1:彩钻, 2:红钻, 3:金币, 5:经验 --解析类似 [[ [{0,100100,100},{3,0,1000}] ]]}, function GetServerConfigReward( config_str) local good_list={} local lua=ErlangParser:GetInstance():Parse(config_str) for i,v in ipairs(lua) do local vo={} if v[1] == "0" then vo.typeId=tonumber(v[2]) elseif v[1] == "1" then vo.typeId=36010001 elseif v[1] == "2" then vo.typeId=36020001 elseif v[1] == "3" then vo.typeId=36030001 elseif v[1] == "4" then vo.typeId=36050001 elseif v[1] == "5" then vo.typeId=36060001 end vo.itemType = tonumber(v[1]) vo.count = tonumber(v[3]) table.insert(good_list,vo) end return good_list end --0:物品, 1:彩钻, 2:红钻, 3:金币, 5:经验 8社团资金 17社团成长值 --解析服务端发来的奖励列表 function GetServerRewardList( list, key1, key2, key3) local good_list={} for i,v in ipairs(list) do local vo={} if v[key1] == 0 then vo.typeId=v[key2] elseif v[key1] == 1 then vo.typeId=36010001 elseif v[key1] == 2 then vo.typeId=36020001 elseif v[key1] == 3 then vo.typeId=36030001 elseif v[key1] == 4 then vo.typeId=36050001 elseif v[key1] == 5 then vo.typeId=36060001 elseif v[key1] == 8 then vo.typeId=36050002 elseif v[key1] == 17 then vo.typeId=36050003 else vo.typeId=v[key2] end vo.itemType = v[key1] vo.count = v[key3] table.insert(good_list,vo) end return good_list end --解析类似 {aircraft_stage, Stage} function ConvertServerConfigTable(tbl) local ret = {} for k,v in ipairs(tbl) do if v[1] then ret[v[1]] = {} for i,vv in ipairs(v) do if tonumber(i) > 1 then table.insert(ret[v[1]],tonumber(vv)) end end end end return ret end --[[ @describtion:目前设备的分辨率和ipad的分辨率对比 @return:bool, ture 代表比大于等于ipad的分辨率 ,false代表小于ipad的分辨率 ]] function NowScreenCompareIpadScreen() local view_size = Game.UI:GetScreenView() local is_ipad_screen = false local view_ratio = view_size.y / view_size.x local ipad_ratio = 768 / 1024 if view_ratio < ipad_ratio then is_ipad_screen = false elseif view_ratio >= ipad_ratio then is_ipad_screen = true end return is_ipad_screen end -- 检查table是否为空 function IsTableEmpty(tbl) return not tbl or _G.next( tbl ) == nil end -- 获取table长度,当数据不连续时不能用# function TableSize(tbl) if IsTableEmpty(tbl) then return 0 end local len = 0 for _ in pairs(tbl) do len = len + 1 end return len end --无符号的32位转换成有符号的32位 function UnsignToSigned(number) if number >= 4000000000 then --无符号的数大于这个数默认为负数了 return -1 * bit.bnot(number - 1) else return number end end function insertElement(arr, obj) local flag = true; for i=1,#arr do if arr[i] == obj then flag = false; break ; end end if flag then table.insert(arr, obj); end end function deleteElement(arr, obj) for i=#arr,1,-1 do if arr[i] and arr[i] == obj then table.remove(arr, i); end end end function utf8_to_unicode(str) if not str or str == "" then return nil end local res, seq, val = {}, 0, nil for i = 1, #str do local c = string.byte(str, i) if seq == 0 then if val then res[#res + 1] = string.format("%04x", val) end seq = c < 0x80 and 1 or c < 0xE0 and 2 or c < 0xF0 and 3 or c < 0xF8 and 4 or --c < 0xFC and 5 or c < 0xFE and 6 or 0 if seq == 0 then return str end val = bit.band(c, 2 ^ (8 - seq) - 1) else val = bit.bor(bit.lshift(val, 6), bit.band(c, 0x3F)) end seq = seq - 1 end if val then res[#res + 1] = string.format("%04x", val) end if #res == 0 then return str end return "\\u" .. table.concat(res, " \\u") end function HasLimitChar(str) --[[local function hex2bin( hexstr ) local s = string.gsub(hexstr, "(.)(.)%s", function ( h, l ) return string.char(h2b[h]*16+h2b[l]) end) return s end]] local unicode_str = utf8_to_unicode(str) if not unicode_str or type(unicode_str) ~= "string" or unicode_str == "" then return false end local str = string.gsub(unicode_str,"\\u","0x") str = Split(str," ") for k,v in pairs(str) do local value = tonumber(v) --放过一批创角名字的特殊字符 --のミ★、灬о+メ丶◎ζξ if value == 0x306E or value == 0x30DF or value == 0x2605 or value == 0x3001 or value == 0x706C or value == 0x043E or value == 0xFF0B or value == 0x30E1 or value == 0x4E36 or value == 0x25CE or value == 0x03B6 or value == 0x03BE then return false end --中文 if not ((value >= 0x4E00 and value <= 0x9FA5) or (value >= 0x0021 and value <= 0x007F)) and --韩文 not ((value >= 0xAC00 and value <= 0xD7AF) or (value >= 0x0021 and value <= 0x007F)) and --日文 not ((value >= 0x3040 and value <= 0x31FF) or (value >= 0x0021 and value <= 0x007F)) then return true end end return false end --[[@ 功能: 生成角色唯一ID 参数: plat_name 平台名 string server_id 服ID int16 role_id 角色ID int32 返回值: 唯一角色ID int32 其它: 无 作者: deadline ]] function GenerateRoleId( plat_name, server_id, role_id) plat_name = plat_name or "" server_id = server_id or 0 role_id = role_id or 0 local tmp_val = server_id if string.len(plat_name) <= 0 then plat_name = "0" end tmp_val = tmp_val + tonumber(string.byte(plat_name , 1)) tmp_val = math.modf(tmp_val, 19) tmp_val = tmp_val + 1 tmp_val = bit.lshift(tmp_val, 24) --tmp_val = bit.toint(bit.bor(tmp_val, role_id)) tmp_val = bit.bor(tmp_val, role_id) tmp_val = bit.band(tmp_val, 0x0fffffff) return tmp_val end function GenerateSuperMemberData() local config = Config.SuperMemberQQSpecial[ClientConfig.plat_name] local use_remote = false if ClientConfig.super_member_qq_special then config = Game.System:ReadJsonStr( ClientConfig.super_member_qq_special ) if config and config.first == 1 then use_remote = true end end if not use_remote and MallModel.Instance.kaifuTime > Config.CloseBetaActivity.SuperMemberForNewServerTime then local server_info = LoginController.Instance:GetPlatUserInfo() -- 混服和应用宝专服 if ClientConfig.plat_belong ~= "1" or ( tonumber(server_info.belongid) == 7 and string.find(ClientConfig.plat_name, "yyb")) then config = Config.CloseBetaActivity.SuperMemberForNewServerConfig end end return config end function PrintTable( tbl , level) if RuntimePlatform and (SystemRuntimePlatform.IsAndroid() or SystemRuntimePlatform.IsIphone()) then return end if tbl == nil or type(tbl) ~= "table" then return end level = level or 1 local indent_str = "" for i = 1, level do indent_str = indent_str.." " end print(indent_str .. "{") for k,v in pairs(tbl) do local item_str = string.format("%s%s = %s", indent_str .. " ",tostring(k), tostring(v)) print(item_str) if type(v) == "table" then PrintTable(v, level + 1) end end print(indent_str .. "}") end --把整个table的内容拼接成一个字符串 function GetTableContentStr( tbl, level, return_counter ) if tbl == nil or type(tbl) ~= "table" then return "" end return_counter = return_counter or 3 --剩下多少层就返回,防止无限打印 if return_counter <= 0 then return "" end return_counter = return_counter - 1 level = level or 1 local indent_str = "" for i = 1, level do indent_str = indent_str.." " end indent_str = indent_str .. "{\n" -- print(indent_str .. "{") for k,v in pairs(tbl) do local item_str = string.format("%s%s = %s", indent_str .. " ",tostring(k), tostring(v)) indent_str = item_str.."\n" -- print(item_str) if type(v) == "table" then indent_str = indent_str .. GetTableContentStr(v, level + 1, return_counter) end end -- print(indent_str .. "}") indent_str = indent_str .. "}\n" return indent_str end function GetCallStackStr() local level = 1 local str = "" while true do local info = debug.getinfo(level, "Sl") if not info then break end if info.what == "C" then str = str..level.."\tC function\n" else str = str..string.format("[%s]:%d\n",info.short_src, info.currentline) end level = level + 1 end return str end function PrintCallStack( ) if RuntimePlatform and (SystemRuntimePlatform.IsAndroid() or SystemRuntimePlatform.IsIphone()) then return end local level = 1 while true do local info = debug.getinfo(level, "Sl") if not info then break end if info.what == "C" then print(level, "C function") else print(string.format("[%s]:%d", info.short_src, info.currentline)) end level = level + 1 end end --屏幕坐标转视口坐标 function ScreenToViewportPoint(x,y) return x / ScreenConvertRatio, y / ScreenConvertRatio end --视口坐标转换屏幕坐标 function ViewportToScreenPoint(x,y) return x * ScreenConvertRatio, y * ScreenConvertRatio end --统一错误码提示,Config.Errorcode function ErrorCodeShow(code, strParam) local tmp = Config.Errorcode[code] or GlobalErrorCode[code] local str = "未知返回码" .. code if tmp then str = tmp.about or tmp if strParam then local args = Split(strParam, ",") for i, v in ipairs(args) do str = string.gsub(str, "{"..i.."}", v) end end end print("HWR:utilManager [983]error_code: ",code) Message.show(str,"fault") end --删除标签 function DeleteColorTag(text) if text == nil or Trim(text) =="" then return text end --text = Trim(text) local function replaceLeft(str) return "" end local text = string.gsub(text, "%^/]+%>", replaceLeft) local function replaceRight(str) return "" end local text = string.gsub(text, "%", replaceRight) return text end --获取跨服长名称 function GetCSLongName( role_name, server_name, no_dot, server_color ) if not server_name then return role_name end local tb = {} if string.find(server_name, "-") then tb = Split(server_name, "-") elseif string.find(server_name, "_") then tb = Split(server_name, "_") else tb[1] = server_name end local server_id = tonumber(tb[1]) if server_id == 0 then server_id = 1 end server_id = server_id%1000 if server_id == 0 then server_id = 1000 end local ser_str = "" if no_dot then ser_str = "S" .. server_id else ser_str = "S" .. server_id .. ". " end if server_color then ser_str = "" .. ser_str .. "" end return ser_str .. role_name end --解析链接点击标签,适用于这种格式XXX, 例如强化石 function FormatHyperLinkParam(txt, cache_text) local final_list = {} --如果文本为空 或者没有需要解释的下划线或者点击事件 则过滤掉 if txt == nil or Trim(txt) == "" or (not string.find(txt, "") and not string.find(txt, "")) then return final_list end --txt = Trim(txt) local a_list = {} --保存a标签的所有数据 local p1, p2, param_str = string.find(txt, "%^/.]-)%>") local count = 1 while p1 do a_list[count] = {} a_list[count].param = param_str a_list[count].has_link = true a_list[count].start_pos = p1 local _, _, text = string.find(txt,"(.-)%<%/a%>", p2 + 1) text = text or "" text = string.gsub(text, "", "") a_list[count].text = string.gsub(text, "", "") p1, p2, param_str = string.find(txt, "%^/.]-)%>", p1 + 1) count = count + 1 end local u_list = {}--保存u标签的所有数据 p1, p2, param_str = string.find(txt, "%(.-)%<%/u%>") count = 1 while p1 do u_list[count] = {} u_list[count].start_pos = p1 param_str = string.gsub(param_str, "^/.]->", "") u_list[count].text = string.gsub(param_str, "", "") u_list[count].has_under_line = true p1, p2, param_str = string.find(txt, "%(.-)%<%/u%>", p1 + 1) count = count + 1 end local n_list = {}--保存后面没有标签的所有数据 p1, p2, param_str = string.find(txt, "%([^]+)%<") count = 1 while p1 do n_list[count] = {} n_list[count].text = param_str n_list[count].start_pos = p1 p1, p2, param_str = string.find(txt, "%([^]+)%<%a", p1 + 1) count = count + 1 end local n2_list = {}--保存后面没有标签的所有数据 p1, p2, param_str = string.find(txt, "%([^]+)%<") count = 1 while p1 do n2_list[count] = {} n2_list[count].text = param_str n2_list[count].start_pos = p1 p1, p2, param_str = string.find(txt, "%([^]+)%<", p1 + 1) count = count + 1 end local c_list = {}--保存color标签的所有数据 if cache_text then p1, p2, color_str, content_str = string.find(cache_text, "%^/.]-)%>([^%>^/.]-)%<%/color") count = 1 while p1 do c_list[count] = {} c_list[count].color = color_str c_list[count].text = content_str c_list[count].start_pos = p1 p1, p2, color_str, content_str = string.find(cache_text, "%^/.]-)%>([^%>^/.]-)%<%/color", p1 + 1) count = count + 1 end end p1, p2, param_str = string.find(txt, "([^]+)") local p3, p4, param_str2 = string.find(txt, "%") if p1 and param_str and not p3 and not param_str2 then param_str = param_str elseif not p1 and not param_str and p3 and param_str2 then param_str = param_str2 elseif p1 and param_str and p3 and param_str2 then param_str = p1 < p3 and param_str or param_str2 end if param_str and string.len(param_str) > 0 then table.insert(final_list, 1, {text = param_str, start_pos = 0})--开头没有标签的内容插入队列里作为第一个元素 end --------------------------把以上所有列表存入总表------------------------ for i, vo in ipairs(a_list) do table.insert(final_list, vo) end local function getFinalVoByText(text) for i, vo in ipairs(final_list) do if text == vo.text then return vo end end end local have = false for i, vo in ipairs(u_list) do have = getFinalVoByText(vo.text) if not have then table.insert(final_list, vo) end end local final_vo = nil for i, vo in ipairs(u_list) do final_vo = getFinalVoByText(vo.text) if final_vo then final_vo.has_under_line = true else table.insert(final_list, vo) end if final_vo then for j, c_vo in ipairs(c_list) do if c_vo.text == vo.text then vo.color = c_vo.color final_vo.color = c_vo.color break end end end end for i, vo in ipairs(n_list) do table.insert(final_list, vo) end for i, vo in ipairs(n2_list) do table.insert(final_list, vo) end ---------------------------------对总表做排序--------------------- local function sort_func(v1, v2) return v1.start_pos < v2.start_pos end table.sort(final_list, sort_func) return final_list end --判断一段文本是否添加了超链接 function HasLink(txt) if txt and string.find(txt, "") then return true end return false end --封装一些比较特殊的标签数据 function PackageSpecialTab(txt) txt = IsContainsUrlTab(txt) if txt == nil or Trim(txt) == "" or not string.find(txt, "") then return txt end --txt = Trim(txt) local function replaceFunc(str) local txt = string.sub(str, 2, -2) local arr = Split(txt,"@") PrintTable(arr) local name = "" if tostring(arr[2]) == "goods" or tostring(arr[2]) == "goods2" or tostring(arr[2]) == "goods5" or tostring(arr[2]) == "goods7" or tostring(arr[2]) == "goods9" then --物品 local basic = GoodsModel:getInstance():GetGoodsBasicByTypeId(tonumber(arr[3])) or GoodsModel:getInstance():GetGoodsBasicByTypeId(tonumber(arr[5])) local empower_lv = tonumber(arr[6]) or 0 if basic then local color = WordManager.GetGoodsColor(basic.color + empower_lv) if tonumber(basic.color) == 0 then -- 对主界面的提示框的绿色物品特殊处理 color = ColorUtil.SHALLOW_GREEN end if empower_lv == 3 then name = SetSevenColorStr("[" .. Trim(basic.goods_name) .. "]") else name = "" .. "[" .. Trim(basic.goods_name) .. "]" .. "" end if basic.type == 11 and (basic.subtype == 10 or basic.subtype == 11)then --装备鉴定物, 碎片,显示鉴定物对应的装备图标 local type_id, _name, icon = EquipModel:getInstance():GetIdentifyGoodsNameAndIcon(basic.type_id, RoleManager.Instance.mainRoleInfo.career, basic.color) goods_icon = icon name = _name end end elseif tostring(arr[2]) == "goods6" or tostring(arr[2]) == "goods3" or tostring(arr[2]) == "goods4" or tostring(arr[2]) == "goods6" then --物品 加括号 local basic = GoodsModel:getInstance():GetGoodsBasicByTypeId(tonumber(arr[3])) if basic then local color = WordManager.GetGoodsColor(basic.color) if tonumber(basic.color) == 0 then -- 对主界面的提示框的绿色物品特殊处理 color = ColorUtil.SHALLOW_GREEN end name = "" .. "[" .. Trim(basic.goods_name) .. "]" .. "" if basic.type == 11 and (basic.subtype == 10 or basic.subtype == 11) then --装备鉴定物, 碎片,显示鉴定物对应的装备图标 local type_id, _name, icon = EquipModel:getInstance():GetIdentifyGoodsNameAndIcon(basic.type_id, RoleManager.Instance.mainRoleInfo.career, basic.color) goods_icon = icon name = "<" .. Trim(_name) .. ">" end end elseif tostring(arr[2]) == "goods8" then --消耗物品 local basic = GoodsModel:getInstance():GetGoodsBasicByTypeId(tonumber(arr[3])) if basic then local have_num = GoodsModel:getInstance():GetCountWithType(0, tonumber(arr[3])) if tonumber(arr[4]) > have_num then name = ""..Trim(basic.goods_name).."("..have_num.."/"..tonumber(arr[4])..")" else name = ""..Trim(basic.goods_name).."("..have_num.."/"..tonumber(arr[4])..")" end --[[if basic.type == 11 and (basic.subtype == 10 or basic.subtype == 11)then --装备鉴定物, 碎片,显示鉴定物对应的装备图标 local type_id, _name, icon = EquipModel:getInstance():GetIdentifyGoodsNameAndIcon(basic.type_id, RoleManager.Instance.mainRoleInfo.career, basic.color) goods_icon = icon name = "<" .. Trim(_name) .. ">" end--]] end elseif tostring(arr[2]) == "scene" then --场景 local scene_info = SceneManager.Instance:GetSceneInfo(tonumber(arr[3])) if scene_info then name = Trim(scene_info.name) end elseif tostring(arr[2]) == "scene2" or tostring(arr[2]) == "treasure3" or tostring(arr[2]) == "valhallapk" then local scene_info = SceneManager.Instance:GetSceneInfo(tonumber(arr[3])) if scene_info then name = "<" .. Trim(scene_info.name) .. "(".. arr[4] ..",".. arr[5] ..")".. ">" end -- elseif tostring(arr[2]) == "partner" or arr[2] == "partner2" then --伙伴 -- local color, name_str = PartnerModel:getInstance():GetPartnerQualityAndName(tonumber(arr[3])) -- if color and name_str then -- logWarn(color,name_str) -- name = "" .. name_str .. "" -- end -- elseif tostring(arr[2]) == "partner3" then --伙伴 加括号 -- local color, name_str = PartnerModel:getInstance():GetPartnerQualityAndName(tonumber(arr[3])) -- if color and name_str then -- logWarn(color,name_str) -- name = "" .. "<" .. name_str .. ">" .. "" -- end -- elseif tostring(arr[2]) == "treasure" then --藏宝图地点 -- local event_type = tonumber(arr[3]) -- if event_type == 1 then -- 打开宝图介绍界面 -- name = string.format("[查看详情]", WordManager.GetChuanwenColor(0)) -- elseif event_type == 2 then -- 跳转到藏宝图boss位置 -- name = string.format("[立即前往]", WordManager.GetChuanwenColor(0)) -- end elseif tostring(arr[2]) == "scene3" then --点击前往 -- name = string.format("点击前往", ColorUtil.GREEN) name = string.format("点击前往", WordManager.GetChuanwenColor(0)) elseif tostring(arr[2]) == "player" then name = arr[3] elseif tostring(arr[2]) == "player2" then name = arr[3] elseif tostring(arr[2]) == "angel" then -- name = string.format("点击前往", ColorUtil.GREEN) name = string.format("点击前往", WordManager.GetChuanwenColor(0)) elseif tostring(arr[2]) == "skill" then local cfg = ConfigItemMgr.Instance:GetSkillItem(tonumber(arr[3])) if cfg then name = string.format("%s",Trim(cfg.name))..","..Trim(cfg.lvs[1].desc) end elseif tostring(arr[2]) == "mate_show" then name = MateConst.ShowMateText elseif tostring(arr[2]) == "beachcallgift" then name = "[给我投票]" elseif tostring(arr[2]) == "dunManyTeam" then name = string.format("[前往组队]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "dunManyGuardianTeam" then name = string.format("[我要进组]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "firstrecharge" then name = string.format("[我也要首充]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "fortuneCat" then -- 招财猫 name = string.format("[我也要翻倍]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "racerank" then -- 竞榜活动 name = string.format("[我也要冲榜]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "kfGroupBuying"then -- 开服团购活动 name = string.format("[前往砍价拼团]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "mobilizationGroupBuying" then name = string.format("[前往砍价拼团]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "attr_id_val" then -- 属性id和数值 local _, name1, _, val1 = WordManager:GetPropertyInfo(tonumber(arr[3]), tonumber(arr[4])) name = name1 .. ":" .. val1 elseif tostring(arr[2]) == "mon" then -- 怪物id,表现为读取配置显示怪物名称 local monster_cfg = ConfigItemMgr.Instance:GetMonsterDataItem(tonumber(arr[3])) name = monster_cfg and Trim(monster_cfg.name) or "" elseif tostring(arr[2]) == "marble" then -- 弹珠机 name = string.format("[我也要弹]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "mono" then -- 大富翁 name = string.format("[前往超级富豪]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "contract" then -- 万物宝典 name = string.format("[我也要解锁]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "contractLv" then -- 万物宝典 name = string.format("[我也要升级]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "escortHelp" then -- 护送协助 name = string.format("[立即前往]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "guild_csgr_enter" then -- 本国团战 name = string.format("[立即前往]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "bosspass" then -- 幻魔宝典 name = string.format("[我也要解锁]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "bosspassLv" then -- 幻魔宝典 name = string.format("[立即前往]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "hopegift" then--明日之礼 name = string.format("[我也要抽]", WordManager.GetChuanwenColor(1)) elseif tostring(arr[2]) == "playername" then -- 聊天@别人 name = HtmlColorTxt( "@" .. arr[3], ColorUtil.BLUE_DARK) elseif tostring(arr[2]) == "mobilize" then -- 全民动员 name = string.format("[我也要达成]", WordManager.GetChuanwenColor(1)) end return "<" .. txt..">" .. name end txt = string.gsub(txt, "%^/]+%>", replaceFunc) return txt end --是否包含Url标签 function IsContainsUrlTab( content ) if string.find(content, "[[]/url[]]") then local function replaceFunc( str ) local arr local new_str arr = Split(str,"]") new_str = string.format(" %s",arr[1],WordManager.GetChuanwenColor(4),arr[2]) return new_str end content = string.gsub(content, "%[url%s(.-)%[%/url%]",replaceFunc) end return content end --封装带url的特殊标签 function PackageSpecialUrlTab( content,url ) if string.find(url, "[[]/url[]]") then local function replaceFunc( str ) local arr local new_str arr = Split(str,"]") PrintTable(arr) if tostring(arr[2]) and tostring(arr[2]) ~= "" then new_str = string.format(" %s",arr[1],WordManager.GetChuanwenColor(4),arr[2]) elseif tostring(arr[2]) == "" then new_str = string.format(" 点击前往",arr[1],WordManager.GetChuanwenColor(4)) end return new_str end url = string.gsub(url, "%[url%s(.-)%[%/url%]",replaceFunc) end return PackageSpecialTab(content) .. url end --设置inlinetext的文本(no_chat_general在聊天栏部分颜色需要进行一次转换) function SetInlineText(inline_text, content, url, no_chat_general) if inline_text == nil then return end content = content or "" if url then content = PackageSpecialUrlTab(content, url) else content = PackageSpecialTab(content) end if no_chat_general then content = string.gsub(content, ColorUtil.GREEN_DARK, ColorUtil.GREEN_DARK_CH) end inlineSpriteMgr:PackageInlineText(inline_text, content) end --给inlinetext添加点击事件 可支持多行换行以及各种图文混排 function AddInlineLickEvent(inline_text, call_back) if inline_text then local function lua_callback(param, x, y) local param_list = Split(param, "@", 2) GlobalEventSystem:Fire(EventName.UNDER_LINE_CLICK_EVENT, param_list, x, y) if call_back then call_back(param_list,x,y) end end inline_text:AddLinkEvent(lua_callback) end end --[[ 这个东西改成了支持下划线的方法 --下划线,标识 --超链接,标识XXX, 例如强化石 参数用@开始分隔 @param : ref_tar必须是继承baseclass的对象 parent_transform:父控件 call_back:回调 hide_click:是否取消点击事件 hide_line:是否隐藏下滑线 ]] function AddUnderLineAndClick(ref_tar, parent_transform, call_back, hide_click, hide_line) if parent_transform == nil then return end local txt = parent_transform:GetComponent("Text").text local cache_label_list = ref_tar[parent_transform] if cache_label_list == nil then cache_label_list = {} ref_tar[parent_transform] = cache_label_list else for i, item in ipairs(cache_label_list) do item:SetActive(false) end end txt = PackageSpecialTab(txt) local txt_cache = txt --保存一份文本 txt_cache = string.gsub(txt_cache, "%^/]+%>", "") txt_cache = string.gsub(txt_cache, "", "") txt_cache = string.gsub(txt_cache, "", "") txt_cache = string.gsub(txt_cache, "%<%/u>", "") --先去掉颜色标签,不然颜色标签会影响下划线的位置运算 txt = DeleteColorTag(txt) --解析超链接 local final_list= FormatHyperLinkParam(txt, txt_cache) parent_text = parent_transform:GetComponent("Text") parent_text.text = txt_cache local inlie if not hide_click then inlie = parent_transform:GetComponent("InlieText") if inlie then --inlieText监听超链接点击 AddInlineLickEvent(parent_text, call_back) end end local label_cache_list = {} local current_width = 0 local label_count = 0 if not IsTableEmpty(final_list) then for i, vo in ipairs(final_list) do if vo.has_under_line or vo.has_link then label_count = label_count + 1 --创建下划线的label local child_label = cache_label_list[label_count] if child_label == nil then child_label = UiFactory.createChild(parent_transform, UIType.Label2,"child_label") child_label.transform.pivot = Vector2(0, 1) cache_label_list[label_count] = child_label child_label.transform.anchorMin = Vector2(0, 1) child_label.transform.anchorMax = Vector2(0, 1) child_label.transform:GetComponent("Text").fontSize = parent_text.fontSize child_label.transform:GetComponent("Text").raycastTarget = true child_label.transform:GetComponent("Text").alignment = UnityEngine.TextAnchor.LowerCenter else child_label:SetActive(true) end parent_text.text = vo.text .. " "--这里先临时加两个空格,否则会出现最后一个下划线符号不显示 local curr_text_width = parent_text.preferredWidth parent_text.text = vo.text local curr_text_height = parent_text.preferredHeight + 5 --暂时加增大文本高度 为了避免下划线渲染不出来,+1不够 改成5 child_label.transform.sizeDelta = Vector2(curr_text_width, curr_text_height) child_label.transform.localPosition = Vector3(current_width - parent_transform.pivot.x * parent_transform.sizeDelta.x, 0, 0) --设置"___"下划线文本 local str = "" for i = 1, string.len(vo.text) do if vo.has_under_line == false or hide_line then str = str .. " " else str = str .. "_" end end local color_str = vo.color or "#31ee4a" child_label:GetComponent("Text").text = ""..str.."" if not hide_click and not inlie then --每一个下划线都有点击事件 如果是inlieText就不要监听,inlieText有超链接的监听 local function onBtnClickHandler(target, x, y) local param_list = {} if vo.param then param_list = Split(vo.param, "@", 2) GlobalEventSystem:Fire(EventName.UNDER_LINE_CLICK_EVENT, param_list, x, y) end if call_back then call_back(param_list, x, y) end end AddClickEvent(child_label, onBtnClickHandler) end end parent_text.text = vo.text current_width = current_width + parent_text.preferredWidth end end parent_text.text = txt_cache end -- left 靠左或者居中 调用此方法前必须先赋值text!!! -- 目标,头衔,头衔Img,名字,是否靠左,vip,vipImg function SetTitlePos(target,title,t_img,text,left,vip,v_img) -- print(target,title,t_img,text,left,vip,v_img) local delta_x = 6 local width = text.preferredWidth t_img.gameObject:SetActive(title ~= 0) if title ~= 0 then RoleTitleModel:getInstance():SetTitleImageByTouxian(target, t_img, title) -- lua_resM:setImageSprite(target,t_img,"common_asset","title_icon_"..title) t_img.rectTransform.anchoredPosition = Vector2.zero text.rectTransform.anchoredPosition = Vector2(t_img.transform.sizeDelta.x + delta_x,0) width = width + t_img.transform.sizeDelta.x + delta_x t_img.gameObject:SetActive(true) else t_img.gameObject:SetActive(false) t_img.rectTransform.anchoredPosition = Vector2(-t_img.transform.sizeDelta.x,0) end if vip then VipModel:GetInstance():GetVipIcon(target,v_img,vip) width = vip ~= 0 and width + v_img.transform.sizeDelta.x + delta_x or width end if not left then --217是整个父物体的宽度 t_img.rectTransform.anchoredPosition = Vector2(217/2 - width/2, 0) end --无论居中还是靠左,text和vip都是在它左边组件的右边 text.rectTransform.anchoredPosition = Vector2(t_img.rectTransform.anchoredPosition.x + t_img.transform.sizeDelta.x + delta_x, 0) v_img.rectTransform.anchoredPosition = Vector2(text.rectTransform.anchoredPosition.x + text.preferredWidth + delta_x, 0) end function utf8_to_unicode(str) if not str or str == "" then return nil end local res, seq, val = {}, 0, nil for i = 1, #str do local c = string.byte(str, i) if seq == 0 then if val then res[#res + 1] = string.format("%04x", val) end seq = c < 0x80 and 1 or c < 0xE0 and 2 or c < 0xF0 and 3 or c < 0xF8 and 4 or --c < 0xFC and 5 or c < 0xFE and 6 or 0 if seq == 0 then return str end val = bit.band(c, 2 ^ (8 - seq) - 1) else val = bit.bor(bit.lshift(val, 6), bit.band(c, 0x3F)) end seq = seq - 1 end if val then res[#res + 1] = string.format("%04x", val) end if #res == 0 then return str end return "\\u" .. table.concat(res, " \\u") end -- function HasLimitChar(str) -- -- if not ClientConfig.is_chinese_verison then -- -- return str -- -- end -- local unicode_str = utf8_to_unicode(str) -- if not unicode_str or type(unicode_str) ~= "string" or unicode_str == "" then -- return false -- end -- local str = string.gsub(unicode_str,"\\u","0x") -- str = Split(str," ") -- for k,v in pairs(str) do -- local value = tonumber(v) -- --中文 -- if not ((value >= 0x4E00 and value <= 0x9FA5) or (value >= 0x0021 and value <= 0x007F)) and -- --韩文 -- not ((value >= 0xAC00 and value <= 0xD7AF) or (value >= 0x0021 and value <= 0x007F)) and -- --日文 -- not ((value >= 0x3040 and value <= 0x31FF) or (value >= 0x0021 and value <= 0x007F)) then -- return true -- end -- end -- return false -- end --计算单位,保证数字最多只有4个(军衔进阶界面战力显示用) function CalUnitNumWithMaxNum(num,max_num) local max_num = max_num and max_num or 4 local str = "" if num < 10000 then --小于1万 str = num elseif num < 100000000 then --小于1亿 -- local a,b = math.modf(num/10000) -- local left_num = 1--整数部分位数 -- for i=1,max_num + 1 do -- if a~=0 then -- a = math.floor(a/10) -- else -- left_num = i - 1 -- break -- end -- end -- if b == 0 then -- str = string.format("%d万", num/10000) -- else -- local cal_str = "%0."..(max_num-left_num).."f" -- str = string.format(cal_str.."万", num/10000) -- end --万单位的不显示小数点 str = string.format("%d万", math.floor(num/10000)) elseif num < 1000000000000 then --小于1万亿 local a,b = math.modf(num/100000000) local left_num = 1--整数部分位数 for i=1,max_num + 1 do if a~=0 then a = math.floor(a/10) else left_num = i - 1 break end end if b == 0 then str = string.format("%d亿", num/100000000) else local cal_str = "%0."..(max_num-left_num).."f" str = string.format(cal_str.."亿", num/100000000) end else --超过1万亿 str = string.format("%0.2f万亿", num/1000000000000) end return str end --计算单位 function CalUnitNum( num ) local str = "" if num < 10000 then --小于1万 str = num elseif num < 100000000 then --小于1亿 str = string.format("%0.2f万", num/10000) elseif num < 1000000000000 then --小于1万亿 str = string.format("%0.2f亿", num/100000000) else --超过1万亿 str = string.format("%0.2f万亿", num/1000000000000) end return str end --计算单位,不留小数和万字 function CalUnitNum1(num) local str = "" if num < 10000 then --小于1万 str = num elseif num < 100000000 then --小于1亿 str = string.format("%d", num/10000) elseif num < 1000000000000 then --小于1万亿 str = string.format("%d", num/100000000) else --超过1万亿 str = string.format("%d", num/100000000) end return str end --计算单位,不留小数版本 function CalUnitNum2( num ) local str = "" if num < 10000 then --小于1万 str = num elseif num < 100000000 then --小于1亿 str = string.format("%d万", num/10000) elseif num < 1000000000000 then --小于1万亿 str = string.format("%d亿", num/100000000) else --超过1万亿 str = string.format("%d亿", num/100000000) end return str end --计算单位 function CalUnitNum3( num ) local str = "" if num < 100000000 then --小于1亿 str = num elseif num < 1000000000000 then --小于1万亿 str = string.format("%0.2f亿", num/100000000) else --超过1万亿 str = string.format("%0.2f亿", num/100000000) end return str end --计算单位 保留一位小数 function CalUnitNum4( num ) local str = "" if num < 10000 then --小于1万 str = num elseif num < 100000000 then --小于1亿 str = string.format("%0.1f万", num/10000) elseif num < 1000000000000 then --小于1万亿 str = string.format("%0.1f亿", num/100000000) else --超过1万亿 str = string.format("%0.1f亿", num/100000000) end return str end --万以上的数转为万单位 function ChangeNumByTenThousand(num) local str = num if str and tonumber(str) >= 10000 then --万 str = string.format("%.1f万", str / 10000) str = string.gsub(str,"%.0","") end return str end local function chsize(char) if not char then print("not char") return 0 elseif char > 240 then return 4 elseif char > 225 then return 3 elseif char > 192 then return 2 else return 1 end end -- 计算utf8字符串字符数, 各种字符都按一个字符计算 -- 例如utf8len("1你好") => 3 function utf8len(str) local len = 0 local currentIndex = 1 while currentIndex <= #str do local char = string.byte(str, currentIndex) currentIndex = currentIndex + chsize(char) len = len +1 end return len end --计算战力,适用于配置表的属性格式 function CalAttrPowerByBaseAttr( pro_list ) local coe_arr = { [1] = 0.25, --生命 [3] = 2.5, --攻击 [4] = 2.5, --防御 [5] = 7.5, --命中 [6] = 7.5, --闪避 [7] = 7.5, --暴击 [8] = 7.5, --坚韧 [29] = 100, --暴击伤害 [30] = 100, --暴伤减免 [35] = 160, --伤害加成 [36] = 160, --伤害减免 } local power = 0 local coe_arr_val = 0 for k, v in ipairs(pro_list) do coe_arr_val = coe_arr[tonumber(v[1])] and coe_arr[tonumber(v[1])] or 0 power = power + coe_arr_val*tonumber(v[2]) end return round(power) end function HtmlColorTxt(content, color, sizeScale) local ncolor = color or "#ffffff" if sizeScale then return "" .. content .. "" else return "" .. content .. "" end end function PairsByKeysInvert(t) local temp = {} for k in pairs(t) do temp[#temp+1] = k end table.sort(temp) local i = #temp+1 return function() i = i-1 return temp[i], t[temp[i]] end end --根据pairs修改而来,保证遍历的顺序是从小到大 function pairsByKeys(t) local temp = {} for k in pairs(t) do temp[#temp+1] = k end table.sort(temp) local i = 0 return function() i = i+1 return temp[i], t[temp[i]] end end function UtilGetRolePicPath(role_id,out_server,head_ver) head_ver = head_ver or 0 local playerInfo = LoginController.Instance:GetPlatUserInfo() local server_id = out_server or playerInfo.server_id local file_path = Util.DataPath .. "/rolehead/" local file_name = role_id .. "_" .. head_ver .. ".jpg" return file_path,file_name end local rechange_tab = { ['['] = "{", [']'] = "}", ['<'] = "", ['>'] = "", key = "[%[%]<>]" } function stringtotable(str,is_check_chinese) if str == "" then return nil end local tab = {} if str == nil or str == "nil" then return nil elseif type(str) ~= "string" then tab = {} return tab elseif #str == 0 then tab = {} return tab end local _s = "" local number = 0 str = string.gsub(str , rechange_tab.key,function(s,...) return rechange_tab[s] or s end) local index,_ = string.find(str , "%b{}") if not index then str = string.format("{%s}",str) end string.gsub(str , "%b{}",function(s) -- print(s) number = number + 1 if number >= 2 then _s = _s .. "," end _s = _s .. s end) if number > 1 then _s = "{" .. _s .. "}" end if is_check_chinese then _s = string.gsub(_s , "([%z\1-\31\33-\43\45-\122\124\126\127\194-\244].-)([,}].-)",function(s,f) if tonumber(s) == nil then s = "'"..s.."'" end return s..f end) else _s = string.gsub(_s , "([%w%d].-)([,}].-)",function(s,f) if tonumber(s) == nil then s = "'"..s.."'" end return s..f end) end local code, ret = pcall(loadstring(string.format("do local _=%s return _ end", _s))) if code then return ret else tab = {} return tab end end function GetSkillPowerAttrList(skill_power_info) local result = {} local data = stringtotable(skill_power_info.attr) local coe_arr = { [1] = true, --生命 [3] = true, --攻击 [4] = true, --防御 [5] = true, --命中 [6] = true, --闪避 [7] = true, --暴击 [8] = true, --坚韧 [29] = true, --暴击伤害 [30] = true, --暴伤减免 [35] = true, --伤害加成 [36] = true, --伤害减免 } local function get_coe(key) for k,v in pairs(coe_arr) do if tonumber(key) == k then local arr = coe_arr[k] coe_arr[k] = nil return arr end end end --目前暂不判断 --被动技能 对象(自己):v[4] == 1 --被动技能 概率:v[3] == 1000 for i,v in pairs(data) do if get_coe(v[1]) and v[5] > 0 then local item = {v[1], v[5]} table.insert(result, item) end end return result end function GetSkillPower( skill_power_info ) return CalAttrPowerByBaseAttr(GetSkillPowerAttrList(skill_power_info)) end function GetSkillAttrBySkill( skill_id, skill_lv, need_power ,is_have) local new_atr_tb = {} ------------------------- skill_lv = skill_lv or 1 local power_conf = 0 local skill_conf = SkillManager:getInstance():getSkillFromConfig(skill_id) if skill_conf and skill_conf.lvs and skill_conf.lvs[skill_lv] then local temp_tb = stringtotable(skill_conf.lvs[skill_lv].base_attr) power_conf = tonumber(skill_conf.lvs[skill_lv].power) or 0 for k,v in pairs(temp_tb) do table.insert( new_atr_tb, {v[2],v[3]} ) end end if need_power then return new_atr_tb,GetFighting(new_atr_tb, is_have) + power_conf else return new_atr_tb end end function GetSkillConfPowerBySkill( skill_id, skill_lv) local new_atr_tb = {} ------------------------- skill_lv = skill_lv or 1 local power_conf = 0 local skill_conf = SkillManager:getInstance():getSkillFromConfig(skill_id) if skill_conf and skill_conf.lvs and skill_conf.lvs[skill_lv] then local temp_tb = stringtotable(skill_conf.lvs[skill_lv].base_attr) power_conf = tonumber(skill_conf.lvs[skill_lv].power) or 0 end return power_conf end function SetGameFrameRate( value ) if not FINAL_FRAMERATE then if SystemMemoryLevel.Cur == SystemMemoryLevel.Low then FINAL_FRAMERATE = GameSettingManager.PerformanceList[1].val_list[1] elseif SystemMemoryLevel.Cur == SystemMemoryLevel.Middle then FINAL_FRAMERATE = GameSettingManager.PerformanceList[1].val_list[2] else FINAL_FRAMERATE = GameSettingManager.PerformanceList[1].val_list[3] end end local value = value or FINAL_FRAMERATE Application.targetFrameRate = value end --千万以上的数转为亿单位 function ChangeNum(num) local str = num if str and tonumber(str) >= 100000000 then --千万 str = string.format("%.2f亿", str / 1000000000) end return str end --模拟器设置 function InitSimulatorSetting( ) if SystemMemoryLevel.Cur == SystemMemoryLevel.Low then SystemMemoryLevel.Cur = SystemMemoryLevel.Middle lua_settingM:SetPostEffectLevel(2) end --Optimizer.SetShaderLodValue(300) lua_settingM.sysSet.quality = 3 lua_settingM.sysSet.fps = 50 lua_settingM:ApplySetting() end function InitResLoadSpeed( scale_speed ) if SystemRuntimePlatform.IsWindows() then return end local scale = scale_speed or 1 local load_count = 6 local download = 3 if SystemMemoryLevel.Cur == SystemMemoryLevel.Low then load_count = 4 download = 2 elseif SystemMemoryLevel.Cur == SystemMemoryLevel.Middle then load_count = 5 download = 2 end resMgr:SetLoadAssetsMaxCount( load_count * scale ) resMgr:SetDownloadMaxCount( download * scale ) end function SetAsyncUpLoadLevel( level ) if SystemRuntimePlatform.IsWindows() then return end local time_slice = 4 local buff_size = 16 if SystemMemoryLevel.Cur == SystemMemoryLevel.Low then time_slice = 4 buff_size = 8 end time_slice = time_slice * level buff_size = buff_size * level QualitySettings.asyncUploadTimeSlice = time_slice QualitySettings.asyncUploadBufferSize = buff_size end function InitEngineData() if tonumber(AppConst.EnglineVer) >= 77 then resMgr:SetCacheDownloadMode(false) resMgr:SetNewDownloadMode(true) resMgr.m_download_timeout = 20 end -- if SystemRuntimePlatform.IsAndroid() then -- if tonumber(AppConst.EnglineVer) >= 91 then -- networkMgr.socket.mUseThread = true --是否开启多线程收发协议模式 -- if SystemMemoryLevel.Cur == SystemMemoryLevel.Hight and SystemRuntimePlatform.IsAndroid() then -- networkMgr.socket.mUseThread = false -- networkMgr.socket.writeFunc = 1 -- networkMgr.socket.use_read_cache_state = false -- networkMgr.socket.use_sent_cache_state = false -- end -- end -- else networkMgr.socket.mUseThread = true -- end end function GameDontDestroyOnLoad() local obj = GameObject.Find("root").transform while obj.parent ~= nil do obj = obj.parent end UnityEngine.Object.DontDestroyOnLoad(obj.gameObject) end function CheckIphoneXState() local iphonex_offset = 55 --像素 local mode_func = function() ClientConfig.iphone_x_offset_left = iphonex_offset local orientation = SDKUtil.CallIntFunc( "IosSystem", "GetIosOrientation", "") if tonumber(orientation) ~= 0 then ClientConfig.orientation_did_change = tonumber(orientation) end if ClientConfig.orientation_did_change == 3 then --默认 ClientConfig.iphone_x_offset_left = iphonex_offset ClientConfig.iphone_x_offset_right = 0 elseif ClientConfig.orientation_did_change == 4 then --反转 ClientConfig.iphone_x_offset_right = iphonex_offset ClientConfig.iphone_x_offset_left = 0 end end if ClientConfig.iphone_x_model then mode_func() end local device_list = {} if SystemRuntimePlatform.IsIphone() then device_list = { ["iPhone10,3"] = true, ["iPhone10,6"] = true, ["iPhone11,2"] = true, ["iPhone11,4"] = true, ["iPhone11,6"] = true, ["iPhone11,8"] = true, } elseif SystemRuntimePlatform.IsAndroid() and OriginalResolutionWidth == 2280 then device_list = { ["OPPOPACM00"] = true, ["OPPOPACT00"] = true, ["OPPOPAAT00"] = true, ["OPPOPAAM00"] = true, ["OPPOPADT00"] = true, ["OPPOPADM00"] = true, ["VIVOVIVOY85"] = true, ["VIVOVIVOY85A"] = true, ["VIVOVIVOX21"] = true, ["VIVOVIVOX21A"] = true, } elseif SystemRuntimePlatform.IsAndroid() and OriginalResolutionWidth == 1520 then device_list = { ["VIVOV1732A"] = true, ["VIVOV1732T"] = true, ["OPPOPBAM00"] = true, } elseif SystemRuntimePlatform.IsAndroid() and OriginalResolutionWidth == 2340 then device_list = { ["SAMSUNGSM-G8870"] = true, ["VIVOV1824A"] = true, } else return end local device = string.gsub(SystemInfo.deviceModel," ","") if SystemRuntimePlatform.IsAndroid() then device = string.upper(device) end if device_list[device] then ClientConfig.iphone_x_model = true if SystemRuntimePlatform.IsAndroid() then CheckAndroidHairAndOrientation(iphonex_offset) else mode_func() end else if SystemRuntimePlatform.IsIphone() then local hair_size = SDKUtil.CallIntFunc( "IosSystem", "GetIosHairSystemSize", "") if tonumber(hair_size) > 0 then ClientConfig.iphone_x_model = true iphonex_offset = tonumber(hair_size) mode_func() end end end end function CheckAndroidHairAndOrientation(size) if tonumber(AppConst.EnglineVer) >= 85 then --local orientation = SDKUtil.CallIntFunc( "SystemData", "OrientationChanged", "") if orientation and tonumber(orientation) > 0 then ClientConfig.orientation_did_change = tonumber(orientation) end if ClientConfig.orientation_did_change == 3 then ClientConfig.iphone_x_offset_left = size ClientConfig.iphone_x_offset_right = size else ClientConfig.iphone_x_offset_left = size ClientConfig.iphone_x_offset_right = size end else ClientConfig.iphone_x_offset_left = size ClientConfig.iphone_x_offset_right = size end end function CheckAndroid9SystemHair() if SystemRuntimePlatform.IsAndroid() and not ClientConfig.iphone_x_model then local size = SDKUtil.CallIntFunc( "SystemData", "GetSafeTop", "") local size_num = tonumber(size) -- local temp_str = "GetSafeTop = " .. tostring(size_num) -- GameError.Instance:SendErrorMsg(temp_str) if size_num then local temp_size = size_num > 55 and 55 or size_num temp_size = temp_size <= 0 and 10 or temp_size ClientConfig.iphone_x_model = true CheckAndroidHairAndOrientation(temp_size) end end end --设置材质贴图 function SetMaterialTexture(material, texture) if material:HasProperty("_MainTex") then material:SetTexture("_MainTex", texture) elseif material:HasProperty("_AmitTex") then material:SetTexture("_AmitTex", texture) end end --获取材质贴图 function GetMaterialTexture(material) local texture if material:HasProperty("_MainTex") then texture = material:GetTexture("_MainTex") elseif material:HasProperty("_AmitTex") then texture = material:GetTexture("_AmitTex") elseif material:HasProperty("_Amitex") then texture = material:GetTexture("_Amitex") end return texture end --取等级模型id列表的衣服id function GetRoleClotheId(level_model_list) local model_res_list = level_model_list if model_res_list then for k,v in ipairs(model_res_list) do if v.part_pos == FashionPartPos.Clothe then return v.level_model_id end end end end --取时装衣服贴图id --is_only_have_fashion_id:fashion_model_id如果是表示时装id而不是资源id,则要去FashionModel转化一下 function GetRoleClotheTextureId(vo, is_only_have_fashion_id) local model_res_list = vo.fashion_model_list if model_res_list then for k,v in ipairs(model_res_list) do if v.part_pos == FashionModel.FashionType.CLOTHES then --需要折算id返回 local id = v.fashion_model_id if is_only_have_fashion_id and v.fashion_model_id ~= 0 then id = FashionModel:GetInstance():GetFashionModelId(v.fashion_model_id, vo.career, v.fashion_color) end if id < 1000 then id = id + vo.career * 1000 end if v.fashion_chartlet_id > 1 then--配色大于1要多连接一个配色 id = id .. v.fashion_chartlet_id end return tonumber(id), 0 end end end end --取坐骑id function GetHorseTextureId(foster_list) local model_res_list = foster_list if model_res_list then for k,v in ipairs(model_res_list) do if v.type_id == FosterConst.ModuleId.FHorse then local cfg = FosterModel.Instance:GetBaseConfOne(v.type_id, v.stage_id, 0) if cfg then return cfg.resource end end end end return 1000 end --上面取坐骑id的先不删,新建一个方法,先取珍宝再取进阶 function GetHorseClotheId( vo ) if vo then local function get_foster_skin( type_id ) for k,v in pairs(vo.foster_skin_list) do if not v.skin_id then --数据结构改了,写法要修正,补全一个skin_id if v.type_id == FosterConst.ModuleId.FHorse then --武器的珍宝需要手动折算2次成资源名 v.skin_id = ShapeModel:GetInstance():GetModelRes( v.type_id, v.sub_id, v.star ) --你的数据要有职业哦,不然我没法完全正确地补全skin_id -- v.skin_id = GameResPath:GetFWeaponResName( vo.career or 1,v.skin_id)--写错了,等祖荣哥回来改 -- else -- v.skin_id = ShapeModel:GetInstance():GetModelRes( v.type_id, v.sub_id, v.star ) end end if v.type_id == type_id and v.skin_id > 0 then return v.skin_id end end end for k,v in pairs(vo.foster_skin_list) do if v.type_id == FosterConst.ModuleId.FHorse then return get_foster_skin(v.type_id) end end for k,v in pairs(vo.foster_list) do if v.type_id == FosterConst.ModuleId.FHorse then return FosterModel:GetInstance():GetModuleResIdByStage(v.type_id,v.stage_id) end end end return 1000 end --取时装头发id --is_only_have_fashion_id:fashion_model_id如果是表示时装id而不是资源id,则要去FashionModel转化一下 function GetRoleHeadId(vo, is_only_have_fashion_id) local model_res_list = vo.fashion_model_list if model_res_list then for k,v in ipairs(model_res_list) do if v.part_pos == FashionModel.FashionType.HEAD then --需要折算id返回 local id = v.fashion_model_id if is_only_have_fashion_id and v.fashion_model_id ~= 0 then id = FashionModel:GetInstance():GetFashionModelId(v.fashion_model_id, vo.career, v.fashion_color) end if id < 1000 then id = id + vo.career * 1000 end if v.fashion_chartlet_id > 1 then id = id .. v.fashion_chartlet_id end return tonumber(id) end end end model_res_list = vo.level_model_list if model_res_list then for k,v in ipairs(model_res_list) do if v.part_pos == FashionPartPos.Head then return v.level_model_id end end end end --取时装发饰id function GetRoleHatId(vo) local model_res_list = vo.fashion_model_list if model_res_list then for k,v in ipairs(model_res_list) do if v.part_pos == FashionModel.FashionType.HAT then return v.fashion_model_id end end end end --明日之星直接取发饰的资源id function GetRoleHatTextureId(vo) local model_res_list = vo.fashion_model_list if model_res_list then for k,v in ipairs(model_res_list) do if v.part_pos == FashionModel.FashionType.HAT then return FashionModel:GetInstance():GetFashionModelId(v.fashion_model_id, 0, v.fashion_color) end end end end --is_only_have_fashion_id:fashion_model_id如果是表示时装id而不是资源id,则要去FashionModel转化一下 function GetWingClotheId( vo ,is_only_have_fashion_id) if vo then --珍宝 local function get_foster_skin( type_id ) for k,v in pairs(vo.foster_skin_list) do if not v.skin_id then --数据结构改了,写法要修正,补全一个skin_id if v.type_id == FosterConst.ModuleId.FWing then --武器的珍宝需要手动折算2次成资源名 v.skin_id = ShapeModel:GetInstance():GetModelRes( v.type_id, v.sub_id, v.star ) --你的数据要有职业哦,不然我没法完全正确地补全skin_id -- v.skin_id = GameResPath:GetFWeaponResName( vo.career or 1,v.skin_id)--写错了,等祖荣哥回来改 -- else -- v.skin_id = ShapeModel:GetInstance():GetModelRes( v.type_id, v.sub_id, v.star ) end end if v.type_id == type_id and v.skin_id > 0 then return v.skin_id end end end for k,v in pairs(vo.foster_skin_list) do if v.type_id == FosterConst.ModuleId.FWing then local foster_skin_id = get_foster_skin(v.type_id) if foster_skin_id and foster_skin_id > 0 then return get_foster_skin(v.type_id) end end end for k,v in pairs(vo.foster_list) do if v.type_id == FosterConst.ModuleId.FWing then return FosterModel:GetInstance():GetModuleResIdByStage(v.type_id,v.stage_id) end end --时装 local model_res_list = vo.fashion_model_list if model_res_list then for k,v in ipairs(model_res_list) do if v.part_pos == FashionModel.FashionType.WING then if v.fashion_model_id ~= 0 then--明日之星可能会出现modelid为0的情况,这里要跳过 if is_only_have_fashion_id then return FashionModel:GetInstance():GetFashionModelId(v.fashion_model_id, vo.career, v.fashion_color),v.fashion_chartlet_id else return v.fashion_model_id end end end end end --进阶 model_res_list = vo.level_model_list if model_res_list then for k,v in ipairs(model_res_list) do if v.part_pos == FashionPartPos.wing then return v.level_model_id end end end end end --取宝具id function GetTalismanClotheId( vo ) if vo then local function get_foster_skin( type_id ) for k,v in pairs(vo.foster_skin_list) do if not v.skin_id then --数据结构改了,写法要修正,补全一个skin_id if v.type_id == FosterConst.ModuleId.FPearl then --武器的珍宝需要手动折算2次成资源名 v.skin_id = ShapeModel:GetInstance():GetModelRes( v.type_id, v.sub_id, v.star ) --你的数据要有职业哦,不然我没法完全正确地补全skin_id -- v.skin_id = GameResPath:GetFWeaponResName( vo.career or 1,v.skin_id)--写错了,等祖荣哥回来改 -- else -- v.skin_id = ShapeModel:GetInstance():GetModelRes( v.type_id, v.sub_id, v.star ) end end if v.type_id == type_id and v.skin_id > 0 then return v.skin_id end end end for k,v in pairs(vo.foster_skin_list) do if v.type_id == FosterConst.ModuleId.FPearl then local foster_id = get_foster_skin(v.type_id) if foster_id and foster_id > 0 then return foster_id end end end for k,v in pairs(vo.foster_list) do if v.type_id == FosterConst.ModuleId.FPearl then return FosterModel:GetInstance():GetModuleResIdByStage(v.type_id,v.stage_id) end end end end --先去时装模型列表的 再取等级模型id列表的武器id --is_only_have_fashion_model_id:fashion_model_id如果是表示资源id(居然和翅膀不一样,再特殊处理一下吧) function GetWeaponClotheId(vo,is_only_have_fashion_model_id) if vo then --珍宝 if vo.foster_skin_list then for k,v in pairs(vo.foster_skin_list) do if not v.skin_id then --数据结构改了,写法要修正,补全一个skin_id if v.type_id == FosterConst.ModuleId.FWeapon then --武器的珍宝需要手动折算2次成资源名 v.skin_id = ShapeModel:GetInstance():GetModelRes( v.type_id, v.sub_id, v.star ) --你的数据要有职业哦,不然我没法完全正确地补全skin_id if v.skin_id and v.skin_id > 0 then v.skin_id = GameResPath:GetFWeaponResName( vo.career or 1,v.skin_id) end -- else -- v.skin_id = ShapeModel:GetInstance():GetModelRes( v.type_id, v.sub_id, v.star ) end end if v.type_id == FosterConst.ModuleId.FWeapon and v.skin_id > 0 then return v.skin_id end end end for k,v in pairs(vo.foster_list) do if v.type_id == FosterConst.ModuleId.FWeapon then --防止stage_id等于0 local stage_id = v.stage_id == 0 and 1 or v.stage_id local res_id = FosterModel:GetInstance():GetModuleResIdByStage(v.type_id, stage_id) return GameResPath:GetFWeaponResName(vo.career,res_id) end end --时装 local model_res_list = vo.fashion_model_list if model_res_list then for k,v in ipairs(model_res_list) do if v.part_pos == FashionModel.FashionType.WEAPON then local figure_id = v.fashion_model_id if is_only_have_fashion_model_id then local figure_id = FashionModel:GetInstance():GetFashionModelId(v.fashion_model_id, vo.career, v.fashion_color) --需要折算id返回 if figure_id < 1000 then figure_id = figure_id + vo.career * 1000 end return figure_id else --需要折算id返回 if figure_id < 1000 then figure_id = figure_id + vo.career * 1000 end return figure_id end end end end --进阶 model_res_list = vo.level_model_list if model_res_list then for k,v in ipairs(model_res_list) do if v.part_pos == FashionPartPos.Weapon then return v.level_model_id end end end end end function GetRoleHeadPath(career,sex,turn) career = career or 1 sex = sex or 1 turn = turn or 1 local cfg = Config.Transfercareer[career.."@"..turn] if cfg then return "head_circle_" .. cfg.icon end return "" end --[[ local test = {1, 2, 3, 4} _G.next(test) = nil for i, v in pairs(test) do print(v) end]] --中文字符串的截取 function SubStringUTF8(str, startIndex, endIndex) if startIndex < 0 then startIndex = SubStringGetTotalIndex(str) + startIndex + 1; end if endIndex ~= nil and endIndex < 0 then endIndex = SubStringGetTotalIndex(str) + endIndex + 1; end if endIndex == nil then return string.sub(str, SubStringGetTrueIndex(str, startIndex)); else return string.sub(str, SubStringGetTrueIndex(str, startIndex), SubStringGetTrueIndex(str, endIndex + 1) - 1); end end --获取中英混合UTF8字符串的真实字符数量 function SubStringGetTotalIndex(str) local curIndex = 0; local i = 1; local lastCount = 1; repeat lastCount = SubStringGetByteCount(str, i) i = i + lastCount; curIndex = curIndex + 1; until(lastCount == 0); return curIndex - 1; end --[[ 获取一个字符串在unity里面实际占位大小(有误差,英文每个字母占的像素大多不一样) 取一个中文字符为标准占位(16号字体一个中文宽高都是16像素) 不同字体不同又不一样,很坑爹,于是大致认定为数字和英文都算半个中文。 ]]-- function CalStringTrueLength( str ) if not str then return 0 end str = DeleteColorTag(str) local length = 0; local i = 1; local lastCount = 1; repeat lastCount = SubStringGetByteCount(str, i) i = i + lastCount; if lastCount >= 2 then length = length + 1; else length = length + 0.5; end until(lastCount == 0); return length - 1; end function SubStringGetTrueIndex(str, index) local curIndex = 0; local i = 1; local lastCount = 1; repeat lastCount = SubStringGetByteCount(str, i) i = i + lastCount; curIndex = curIndex + 1; until(curIndex >= index); return i - lastCount; end --返回当前字符实际占用的字符数 function SubStringGetByteCount(str, index) local curByte = string.byte(str, index) local byteCount = 1; if curByte == nil then byteCount = 0 elseif 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 return byteCount; end --[[ 删除表中数据 @param list:数据列表 deleteKey:判断条件的key deleteValue:等于判断条件的value ]] function DeleteTable( list, deleteKey, deleteValue ) local delete_index={} for i,v in ipairs(list) do if v[deleteKey]==deleteValue then table.insert(delete_index,i) end end local del_num=0 for i,v in ipairs(delete_index) do local index = v - del_num table.remove(list, index) del_num = del_num + 1 end end --删除表中数据 判断不相等版本 function DeleteTableUnEqual( list, deleteKey, deleteValue ) local delete_index={} for i,v in ipairs(list) do if v[deleteKey]~=deleteValue then table.insert(delete_index,i) end end local del_num=0 for i,v in ipairs(delete_index) do local index = v - del_num table.remove(list, index) del_num = del_num + 1 end end function ToStringEx(value) if type(value)=='table' then return TableToStr(value) elseif type(value)=='string' then return "\'"..value.."\'" else return tostring(value) end end function TableToStr(t) if t == nil then return "" end local retstr= "{" local i = 1 for key,value in pairs(t) do local signal = "," if i==1 then signal = "" end if key == i then retstr = retstr..signal..ToStringEx(value) else if type(key)=='number' or type(key) == 'string' then retstr = retstr..signal..'['..ToStringEx(key).."]="..ToStringEx(value) else if type(key)=='userdata' then retstr = retstr..signal.."*s"..TableToStr(getmetatable(key)).."*e".."="..ToStringEx(value) else retstr = retstr..signal..key.."="..ToStringEx(value) end end end i = i+1 end retstr = retstr.."}" return retstr end function FindInTable( tbl, key, value ) for k,v in pairs(tbl) do if (key and v[key] or v) == value then return v end end return nil end function StrToTable(str) if str == nil or type(str) ~= "string" or str=="[]" then return end return loadstring("return " .. str)() end --获取进度的最大值(返回空表示不显示进度) function GetMaxProgress(list) if list[1] and list[1][1] then if list[1][1] == "attr" then return list[1][#list[1]] elseif list[1][1] == "boss" then return #list[1][2] elseif list[1][1] == "suit_type" then return list[#list][2] elseif list[1][1] == "vip" then return 1 elseif list[1][1] == "equip_ids" then return 1 elseif list[1][1] == "equip" then return 1 elseif list[1][1] == "equip_suit" then return 1 elseif list[1][1] == "equipment" then if list[1][2] == "0" then return 10 else return list[1][3] end elseif list[1][1] == "equipment_sumstren_lv" then return list[1][2] else return list[1][2] or 1 end end end --删除字符串中的所有空格 function NoBlankStr(str) local str = Trim(str) str = string.gsub(str, "%s", "") return str end --出现严重问题时触发后台报警流程 function UtilSentServerError( error_msg ) local server_name = "未知" if LoginController and LoginController.Instance then local playerInfo = LoginController.Instance:GetPlatUserInfo() if playerInfo then server_name = playerInfo.server_name or "" end end local plat_name = ClientConfig.plat_name local ticket = "e04201e54b49a941434c48d971b59af5" local now_method = "send_voice" local cur_time = tostring(os.time()) local post_param = { time = cur_time, method = now_method, sign = string.lower(Util.md5( ticket .. cur_time .. now_method )), server = server_name, platform = plat_name, game = "qhbgd", issue = error_msg or "出问题了", } local call_func = function(ret,error_msg,data) print("-- SentServerError result --",ret,error_msg,data) end local url = string.gsub(ClientConfig.php_website_error,"api.php","api_admin.php") HttpUtil.HttpPostRequest(url, post_param, call_func) end --把数组的顺序打乱[只支持连续的自然数key值] function DisruptListSequence(list) if not list or type(list) ~= "table" or not next(list) then return end local len = TableSize(list) local end_list = {} for i = 1, len do local index = len - i + 1 if index > 0 then local random_key = math.random(1, index) table.insert(end_list, list[random_key]) table.remove(list, random_key) end end for i,v in ipairs(end_list) do table.insert(list, v) end end function PrintResList() local func = function(load_count,load_list,request_count,request_list,loading_count,loading_list,hight_count,hight_list,mid_count,mid_list,low_count,low_list) local msg = string.format("res count:%d@%d@%d@%d@%d@%d",load_count,request_count,loading_count or 0,hight_count or 0,mid_count or 0,low_count or 0) if request_count > 0 then for i=1,request_count do msg = msg .. "\n" .. "request:" .. request_list[i-1] end end if load_count > 0 then for i=1,load_count do msg = msg .. "\n" .. "load:" .. load_list[i-1] end end if loading_count and loading_count > 0 then for i=1,loading_count do msg = msg .. "\n" .. "loading_list:" .. loading_list[i-1] end end if hight_count and hight_count > 0 then for i=1,hight_count do msg = msg .. "\n" .. "hight_list:" .. hight_list[i-1] end end if mid_count and mid_count > 0 then for i=1,mid_count do msg = msg .. "\n" .. "mid_list:" .. mid_list[i-1] end end if low_count and low_count > 0 then for i=1,low_count do msg = msg .. "\n" .. "low_list:" .. low_list[i-1] end end GameError.Instance:SendErrorToPHP(msg,LogType.Warning) print(msg) end resMgr:PrintResourceLog(func) end --- nNum 源数字 --- n 小数位数 function GetPreciseDecimal(nNum, n) if type(nNum) ~= "number" then return nNum end n = n or 0; n = math.floor(n) if n < 0 then n = 0 end local nDecimal = 10 ^ n local nTemp = math.floor(nNum * nDecimal); local nRet = nTemp / nDecimal; return nRet end function AttachGameRoot( transform ) if not G_GAMEROOT_TRANSFORM then G_GAMEROOT_TRANSFORM = GameObject.Find("root").transform end transform:SetParent(G_GAMEROOT_TRANSFORM) end --传入{ vector3,vector3,...} function ToVector3Array( table ) if AppConst.EnglineVer >= 74 then return Util.ToVector3Array( table ) else return nil end end --传入{ vector2,vector2,...} function ToVector2Array( table ) if AppConst.EnglineVer >= 74 then return Util.ToVector2Array( table ) else return nil end end function GetPathFiles(path,pre, match_str) if EnglineVersion and AppConst_EnglineVer >= 70 then return FileTools.GetPathFiles(path,pre, match_str) end return {} end function OutPutValue(file_name, str) if EnglineVersion and AppConst_EnglineVer >= 70 then return FileTools.OutPutValue(file_name, str) end end function CheckPathExists(path) if EnglineVersion and AppConst.EnglineVer >= 70 then return FileTools.CheckPathExists(path) end return false end function MatchCfg(path, pre, match_str, config) if EnglineVersion and AppConst.EnglineVer >= 70 then return FileTools.MatchCfg(path, pre, match_str, config) end return false end function ClearTrailRenderer(game_object) if TrailRenderer and game_object and not IsNull(game_object) then local com = game_object:GetComponentsInChildren(typeof(TrailRenderer),true) if com.Length > 0 then for i=1,com.Length do com[i-1]:Clear() end end end end function GetAssetBundleDependList(ab_name, callback) if tonumber(AppConst.EnglineVer) < 81 then Message.show("低版本引擎不支持该功能") return end local func = function(state,objs) if state and objs then callback(objs) else callback(nil) end end resMgr:GetDependResList(ab_name,func) end function ExportTerrainPreloadConfig() local preload_res = {} local function search_Dependencies(res,scene_id) local function callback(objs) if objs then local len = objs.Length for i = 1, len do local str = objs[i-1] local a,b = string.find(str, "/.*%.") local name = string.sub(str,a+1,b-1) if not preload_res[name] and not string.find(name,"shader") then preload_res[name] = scene_id end end end end GetAssetBundleDependList(res, callback) end local scene_list = Split(StepPackModule.PRELOAD_MAP_RES,",") for _,scene_id in ipairs(scene_list) do local name = "model"..scene_id local config = Config[name] if config then for _, item in ipairs(config) do local res = "terrain_prefab_"..item[1] if not preload_res[res] then preload_res[res] = scene_id search_Dependencies(res,scene_id) end end local data = ConfigItemMgr.Instance:GetSceneItem(scene_id) if data then local obj_cfg = nil local res = nil if data.Npcs then for id, _ in pairs(data.Npcs) do obj_cfg = ConfigItemMgr.Instance:GetNpcItem(id) if obj_cfg and obj_cfg.icon > 0 then res = "model_clothe_"..obj_cfg.icon if not preload_res[res] then preload_res[res] = scene_id end end end end if data.mon then for _, id in ipairs(data.mon) do obj_cfg = ConfigItemMgr.Instance:GetMonsterDataItem(id) if obj_cfg and obj_cfg.icon > 0 then res = "model_clothe_"..obj_cfg.icon if not preload_res[res] then preload_res[res] = scene_id end end end end else LogError("场景DB文件缺失数据,id = " .. scene_id) end end end local preload_res_map = {} local list_temp for res, scene_id in pairs(preload_res) do preload_res_map[scene_id] = preload_res_map[scene_id] or {} list_temp = preload_res_map[scene_id] list_temp[#list_temp+1] = res end local function sort_func(a,b) return a < b end for scene_id, list in pairs(preload_res_map) do table.sort(list, sort_func) end for _,scene_id in ipairs(scene_list) do list_temp = preload_res_map[scene_id] if list_temp then table.insert(list_temp, 1, "terrain_scene_"..scene_id) else preload_res_map[scene_id] = {[1] = "terrain_scene_"..scene_id} list_temp = preload_res_map[scene_id] end if Config.ConfigSceneEffect.EffectInfo[tonumber(scene_id)] then local particle_name = scene_id .. "effect" local file_path = AppConst.AppDataPath.."/StreamingAssets/rdata/" .. particle_name .. ".syrd" local file = io.open(file_path, "rb") if file then table.insert(list_temp,particle_name) else print(file_path .. " is not exist") end end end local str = [[ --预加载的场景由策划配置,为新手200级使用的地图资源的顺序 --每个场景预加载配置承接上个场景,即上个场景出现的资源配置不需要在之后的场景配置中(上个场景配置了,就已经预加载了,不需要重复配置) ]] str = str.."Config.ConfigTerrainPreload = \n{\n" for _, scene_id in ipairs(scene_list) do local list = preload_res_map[scene_id] if list then str = str.." ["..scene_id.."] =\n {\n" for i, res in ipairs(list) do res = Util.GetBase64String(string.lower(res)) str = str.." ["..i.."] = "..[["]]..res..[["]]..",\n" end str = str.." },\n" end end str = str.."}\n" local fileName = AppConst.AppDataPath.."/Lua/config/client/ConfigTerrainPreload.lua" local f = assert(io.open(fileName,'w')) f:write(str) f:close() end function SortTerrainShaderResUse() local map_list = {1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,2001,2081,2102,2400,2500,3001,3100,3200,4001,4063,4064,4100,4200,4300,6100,7001,7100,7200} local str local shader_list = {} local cache = {} for index,map in pairs(map_list) do local name = "model"..map local config = Config[name] if config then for _, item in ipairs(config) do local obj = item[1] .." " .. map local shader = item[19] if shader then if not shader_list[shader] then shader_list[shader] = {} end if not cache[obj] then cache[obj] = true table.insert(shader_list[shader],obj) end else print("----------------shader is empty--------------",map,obj) end end end end local str = "Config.ConfigTerrainShaderUse = \n{\n" for shader, data in pairs(shader_list) do str = str.." ["..[["]] .. shader .. [["]] .."] =\n {\n" for i, res in ipairs(data) do str = str.." ["..i.."] = "..[["]]..res..[["]]..",\n" end str = str.." },\n" end str = str.."}\n" local fileName = AppConst.AppDataPath .."/Lua/config/client/ConfigTerrainShaderUse.lua" local f = assert(io.open(fileName,'w')) f:write(str) f:close() end function SetSystemClipboard(value) SDKUtil.CallSDKFunc("SystemData","Clipboard",{ data = tostring(value) }) end function GetNoNewPlayerSmallMonster() local mon = {} for i=1000,9999 do local data = ConfigItemMgr.Instance:GetSceneItem(i) if data then for _, id in ipairs(data.mon) do local mon_cfg = ConfigItemMgr.Instance:GetMonsterDataItem(id) if mon_cfg then mon[mon_cfg.icon] = true end end end end local data = ConfigItemMgr.Instance:GetSceneItem(1000) if data then for _, id in ipairs(data.mon) do local mon_cfg = ConfigItemMgr.Instance:GetMonsterDataItem(id) if mon_cfg then mon[mon_cfg.icon] = nil end end end local sort_mon = {} for i in pairs(mon) do if i ~= nil then table.insert(sort_mon, i) end end table.sort(sort_mon, function(a,b) return (a < b) end) for k,v in ipairs(sort_mon) do print("------monster---------",v) end end --输出定时器 function PrintTimerQuest() local timer = GlobalTimerQuest local str = "" str = str.."timer_list:\n" for i,vo in pairs(timer.timer_list) do if vo.loop ~= 0 then str = str.."TimerQuest:"..tostring(vo.source).."\n" end end str = str.."\n\n" str = str.."timer_list2:\n" for i,vo in pairs(timer.timer_list2) do if vo.loop ~= 0 then str = str.."TimerQuest:"..tostring(vo.source).."\n" end end str = str.."\n\n" str = str.."timer_list3:\n" for i,vo in pairs(timer.timer_list3) do if vo.loop ~= 0 then str = str.."TimerQuest:"..tostring(vo.source).."\n" end end print(str) local fileName = AppConst.AppDataPath.."/StreamingAssets/log/timer_quest.txt" local f = assert(io.open(fileName,'w')) f:write(str) f:close() end --注册分帧执行器 function RegisterFraming(ref_tar,func_list,need_framing_load,interval,end_callback) local func_len = #func_list if not ref_tar or ref_tar._use_delete_method or func_len < 1 then return end if ref_tar.framing_timer_id then GlobalTimerQuest:CancelQuest(ref_tar.framing_timer_id) ref_tar.framing_timer_id = nil end if need_framing_load == nil then need_framing_load = true end if need_framing_load then interval = interval or 0.01 local frame = 0 local function frame_func() frame = frame + 1 local args = func_list[frame] if type(args) == "function" then args(ref_tar) elseif type(args) == "table" then if type(args[1]) == "function" then args[1](ref_tar, unpack(args,2)) end end if func_len == frame then if end_callback then end_callback() end if ref_tar.framing_timer_id then GlobalTimerQuest:CancelQuest(ref_tar.framing_timer_id) ref_tar.framing_timer_id = nil end end end ref_tar.framing_timer_id = GlobalTimerQuest:AddPeriodQuest(frame_func, interval) else for _, args in ipairs(func_list) do if type(args) == "function" then args(ref_tar) elseif type(args) == "table" then if type(args[1]) == "function" then args[1](ref_tar, unpack(args,2)) end end end end end --界面销毁时取消分帧执行器 function UnregisterFraming(ref_tar) if ref_tar.framing_timer_id then GlobalTimerQuest:CancelQuest(ref_tar.framing_timer_id) ref_tar.framing_timer_id = nil end end function SetGoodsIcon(ref_tar, icon_img, type_id, setNativeSize, width, height, x, y) local basic = GoodsModel:getInstance():GetGoodsBasicByTypeId(type_id) lua_resM:setOutsideImageSprite(ref_tar,icon_img,GameResPath.GetGoodsIcon(basic.goods_icon),setNativeSize) if width and height then SetSizeDelta(icon_img.transform, width, height) end if x and y then SetAnchoredPosition(icon_img.transform, x, y) end end function FindInScene(str) local args = Split(str, "/") if #args < 2 then return GameObject.Find(str) else local root = GameObject.Find(args[1]) if root then local len = string.len(args[1])+2 str = string.sub(str,len) local child = root.transform:Find(str) if child then return child.gameObject end end end end function SetFogStartDistance( value ) local render = UnityEngine.RenderSettings if render then render.fogStartDistance = value end end function SetFogEndDistance( value ) local render = UnityEngine.RenderSettings if render then render.fogEndDistance = value end end function SetGreenScreen(target) local GreenImage = UiFactory.createChild(target,UIType.Image,"GreenImage") local Image = GreenImage:GetComponent("Image") Image.raycastTarget = false Image.color = Color(0,1,0.13,1) Image.sprite = nil GreenImage:GetComponent("RectTransform").sizeDelta = Vector2(2000,1500) end ------------------------- --获取是否为百分比属性 function GetPropIsPercent( id ) id = id or 0 return (Config.ConfigItemAttr.Normal[id] and Config.ConfigItemAttr.Normal[id].is_percent) and id or false end function GetPropIsBasePercent( id ) id = id or 0 local tab = { base_att = 1, base_maxHp = 2, base_def = 4, base_hit = 5, base_dodge = 6, base_crit = 7, base_ten = 8, base_abs_att = 15, base_abs_def = 16, } if (Config.ConfigItemAttr.Normal[id] and Config.ConfigItemAttr.Normal[id].base_per_add) then return Config.ConfigItemAttr.Normal[id].base_per_add,tab[Config.ConfigItemAttr.Normal[id].base_per_add] else return false end end --获取角色属性列表 function GetRolePropList( ) local mainVo = RoleManager.Instance.mainRoleInfo return { [1] = mainVo.att or 0, [2] = mainVo.maxHp or 0, [4] = mainVo.def or 0, [5] = mainVo.hit or 0, [6] = mainVo.dodge or 0, [7] = mainVo.crit or 0, [8] = mainVo.ten or 0, [9] = mainVo.hurt_add_ratio or 0, [10] = mainVo.hurt_del_ratio or 0, [11] = mainVo.hit_ratio or 0, [12] = mainVo.dodge_ratio or 0, [13] = mainVo.crit_ratio or 0, [14] = mainVo.uncrit_ratio or 0, [15] = mainVo.abs_att or 0, [16] = mainVo.abs_def or 0, [19] = mainVo.att_add_ratio or 0, [20] = mainVo.hp_add_ratio or 0, [22] = mainVo.def_add_ratio or 0, [23] = mainVo.hit_add_ratio or 0, [24] = mainVo.dodge_add_ratio or 0, [25] = mainVo.crit_add_ratio or 0, [26] = mainVo.ten_add_ratio or 0, [27] = mainVo.skill_hurt_add_ratio or 0, [28] = mainVo.skill_hurt_del_ratio or 0, [29] = mainVo.final_hurt_add_ratio or 0, [30] = mainVo.final_hurt_del_ratio or 0, [48] = mainVo.parry_ratio or 0, [49] = mainVo.stab_ratio or 0, [50] = mainVo.pvp_hurt_del_ratio or 0, [51] = mainVo.pvp_hurt_add_ratio or 0, [52] = mainVo.crit_hurt_add_ratio or 0, [53] = mainVo.crit_hurt_del_ratio or 0, [54] = mainVo.heart_ratio or 0, [55] = mainVo.heart_add_hurt or 0, [56] = mainVo.heart_resist_ratio or 0, [57] = mainVo.heart_del_hurt or 0, [95] = mainVo.suck_blood or 0, [96] = mainVo.suck_blood_add or 0, [97] = mainVo.suck_blood_minus or 0, [98] = mainVo.boss_hurt_add_ratio or 0, [99] = mainVo.boss_hurt_del_ratio or 0, [100] = mainVo.mon_hurt_add_ratio or 0, [101] = mainVo.mon_hurt_del_ratio or 0, } end --获取百分比属性的实际使用加成 function GetPropPercentAdd( attr_id,attr_num ) attr_id = attr_id or 0 attr_num = attr_num or 0 if not GetPropIsPercent(attr_id) then return 0 end attr_num = attr_num or 0 return (1 + (5 * attr_num - 10000) / (2 * attr_num + 10000) ) * GetPropOneAddNum(attr_id) * 0.0002 end --获得属性的加成系数 function GetPropOneAddNum( attr_id ) attr_id = attr_id or 0 local num = 0 if Config.ConfigItemAttr.Normal[attr_id] and Config.ConfigItemAttr.Normal[attr_id].add_num then num = Config.ConfigItemAttr.Normal[attr_id].add_num end return num end --[[ 注意:is_have计算已有的属性战力,预览战力别传! Author:LZR Description:战力计算公式,做法就是计算出当前真实属性的战力,同时计算加上需要计算的属性之后,两者相减获得战力差值返回 parameters list = { [id] = { [1] = attr_id, [2] = attr_num }, } list = { [id] = { [1] = FuncId ,[2] = attr_id, [3] = attr_num }, 功能id } ]] function GetFighting( list,is_have ) list = list or {} list = ComposeAttr(list)--合并属性 local cur_power = 0 local final_power = 0 ------------------------- --更改数据格式便于计算 local base_list = {} for k,v in pairs(list) do if #v == 3 then base_list[tonumber(v[2])] = tonumber(v[3]) else base_list[v[1]] = v[2] end end ------------------------- local main_role = RoleManager.Instance.mainRoleInfo if main_role then ------------------------- --如果当前检查未获得的属性,包含了基础属性,那还要把那几个百分比基础加成加上去的参数补上 if not is_have then local base_per_list = {[19] = true,[20] = true,[22] = true,[23] = true,[24] = true,[25] = true,26,[29] = true,[30] = true} local base_add_id,match_id = 0, 0 local add_temp_num = 0 for k,v in pairs(base_per_list) do base_add_id,match_id = GetPropIsBasePercent(k) if base_add_id and base_list[match_id] then --加成的这波属性,要算进基础属性百分比里面 add_temp_num = main_role[Config.ConfigItemAttr.Normal[k].tag] + (base_list[k] or 0) base_list[match_id] = base_list[match_id] + math.floor( base_list[match_id] * add_temp_num/10000 ) end end end ------------------------- --生成新旧属性表 local cur_prop_list = GetRolePropList() local new_prop_list = DeepCopy(cur_prop_list) for k,v in pairs(base_list) do if new_prop_list[k] then if is_have then new_prop_list[k] = new_prop_list[k] - v else new_prop_list[k] = new_prop_list[k] + v end end end ------------------------- --百分比基础加成 for k,v in pairs(base_list) do local base_add_id,match_id = GetPropIsBasePercent(k) if base_add_id then main_role[base_add_id] = main_role[base_add_id] or 1000 if is_have then new_prop_list[match_id] = new_prop_list[match_id] - main_role[base_add_id]*(v / 10000) else new_prop_list[match_id] = new_prop_list[match_id] + main_role[base_add_id]*(v / 10000) end end end ------------------------- --罗列需要计算的属性id local id_list = { 1,2,4,5,6,7,8,15,16,9,10,11,12,13,14,27,28,48,49,50,51,52,53,54,55,56,57, 95,96,97,98,99,100,101 } ------------------------- --计算新旧战力 local PowerFactor_cur = 0 local PowerFactor_final = 0 for k,v in pairs(id_list) do if GetPropIsPercent(v) then PowerFactor_cur = PowerFactor_cur + GetPropPercentAdd(v,cur_prop_list[v]) PowerFactor_final = PowerFactor_final + GetPropPercentAdd(v,new_prop_list[v]) else cur_power = cur_power + cur_prop_list[v] * GetPropOneAddNum( v ) final_power = final_power + new_prop_list[v] * GetPropOneAddNum( v ) end end cur_power = cur_power * (1 + PowerFactor_cur) final_power = final_power * (1 + PowerFactor_final) ------------------------- end if is_have then return math.floor(cur_power - final_power) else return math.floor(final_power - cur_power) end end --判断模块是否开启 function GetModuleIsOpen( main_id,child_id,is_fade_show ) local _,conf = GetModuleOpenLevel(main_id,child_id) if not conf or not RoleManager.Instance.mainRoleInfo then return end ------------------------- local op_day,op_lv,op_task = 0,0,0 if is_fade_show and conf.icon_lv > 0 then op_day = conf.icon_day op_lv = conf.icon_lv op_task = conf.icon_task or 0 else op_day = conf.open_day op_lv = conf.open_lv op_task = conf.task_id or 0 end ------------------------- local is_open = op_day == 0 or op_day <= ServerTimeModel:getInstance():GetOpenServerDay()--开服天数 is_open = is_open and MainUIModel:getInstance():GetFunOpenState(op_lv, op_task)--任务和等级 return is_open , conf end --获取开放等级, is_fade_show代表使用客户端的展示等级 function GetModuleOpenLevel( main_id,child_id,is_fade_show) if not main_id then return end child_id = child_id or 0 local base_conf = child_id == 0 and Config.Moduleid[main_id] or Config.Modulesub[main_id .. "@" .. child_id] local open_lv = base_conf and base_conf.open_lv or 0 if is_fade_show and base_conf and base_conf.icon_lv > 0 then return base_conf.icon_lv, base_conf else return open_lv, base_conf end end --传入两属性,获得格式一样的属性 function GetAttrMatch( list_1,list_2,need_sort ) local data_1,data_2 = {},{} list_1 = list_1 or {} list_2 = list_2 or {} for k,v in pairs(list_1) do data_1[v[1]] = v[2] end for k,v in pairs(list_2) do data_2[v[1]] = v[2] end ------------------------- for k,v in pairs(data_1) do if not data_2[k] then data_2[k] = 0 end end for k,v in pairs(data_2) do if not data_1[k] then data_1[k] = 0 end end ------------------------- local result_1,result_2 = {},{} local index = 1 for k,v in pairs(data_1) do result_1[index] = {k,v} result_2[index] = {k,data_2[k]} index = index + 1 end ------------------------- if need_sort then result_1 = SortAttrList(result_1) result_2 = SortAttrList(result_2) end return result_1,result_2 end --给属性列表排序,高级属性在前 function SortAttrList( list ) if not list then return {} end local list_1 = {} local list_2 = {} for k,v in pairs(list) do if WordManager:GetAttrIsSpecial(v[1]) then table.insert( list_1, v ) else table.insert( list_2, v ) end end local function sort_call( a,b ) return tonumber(a[1]) < tonumber(b[1]) end if list_1[2] then table.sort( list_1, sort_call ) end if list_2[2] then table.sort( list_2, sort_call ) end for i,v in ipairs(list_2) do table.insert( list_1, v ) end return list_1 end --通过condition获得关键值 function GetKeyValue( condition,key ) local value = nil if condition then for i,v in ipairs(condition) do if v[1] and v[1] == key then return v[2] end end end return value end --顺序表排序翻转 function StartToEnd(list) if type(list) == "table" then local len = #list local new_list = {} for i=1,len do new_list[i] = list[len-i+1] end return new_list end end -- 计算utf8字符串字符数, 各种中文算俩字符其他按一个字符计算 -- 为什么这么算呢 因为字号20的文本 在u3d里面 -- 例如utf8len("1你好") => 5 width = 5 *(20/2) function utf8lenU3D(str) local len = 0 local currentIndex = 1 while currentIndex <= #str do local char = string.byte(str, currentIndex) currentIndex = currentIndex + chsize(char) if chsize(char) == 3 then len = len + 2 else len = len + 1 end end return len end --10进制数值转2进制 以table形式返回 --从左往右读 function TenbyteToTwobyte(num) local num_table = {}; while num ~= 0 do table.insert(num_table, math.fmod(num, 2)); num = math.floor(num/2) end return num_table end -- 属性图标根据颜色类型 function SetAttrIconByColorType(ref_tar, img_component, attr_id, force, color_type) if not ref_tar or not img_component then return end local color_list = { [1] = "7d91ac",--暗淡的蓝色 [2] = "fdfdc9",--黄色 [3] = "ffffff",--白色 [4] = "a9c1e1",--浅蓝 } img_component.color = ColorUtil:ConvertHexToRGBColor(color_list[color_type]) local a_name,b_name = GameResPath.GetAttrIcon(attr_id, force, 1) lua_resM:setImageSprite(ref_tar, img_component, a_name, b_name, true) end function UrlEncode(s) s = string.gsub(s, "([^%w%.%- ])", function(c) return string.format("%%%02X", string.byte(c)) end) return string.gsub(s, " ", "+") end function UrlDecode(s) s = string.gsub(s, '%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end) return s end --货币单位 function GetPriceCompany( ) return "¥" end --合并两属性列表,结果会写入list_a function CombineAttrList( list_a, list_b ) if not list_a or not list_b then return {} end for kk,vv in pairs(list_b) do local has_attr = false for k,v in pairs(list_a) do if v[1] == vv[1] then v[2] = v[2]+vv[2] has_attr = true break end end if not has_attr then table.insert(list_a, vv) end end return list_a end --获取属性差值,以attr_list2减去attr_list1的每个属性值,write_to_witch_list为1或2或nil,指定要把差值写入attr_list1还是attr_list2 function GetAttributeOffset( attr_list1, attr_list2, write_to_witch_list ) local result = {} for k,v in pairs(attr_list2) do local has_attr = false for kk,vv in pairs(attr_list1) do if v.index and v.index == vv.index then result[v.index] = v.attr_value-vv.attr_value has_attr = true if write_to_witch_list then if write_to_witch_list == 1 then vv.add_attr = result[vv.index] vv.add_attr_for_show = WordManager:GetPropertyValue(vv.index, vv.add_attr) else v.add_attr = result[v.index] v.add_attr_for_show = WordManager:GetPropertyValue(v.index, v.add_attr) end end break elseif v[1] and v[1] == vv[1] then --有些是用数组的,这里兼容下 result[v[1]] = v[2]-vv[2] has_attr = true if write_to_witch_list then if write_to_witch_list == 1 then vv.add_attr = result[vv[1]] vv.add_attr_for_show = WordManager:GetPropertyValue(vv[1], vv.add_attr) elseif write_to_witch_list == 2 then v.add_attr = result[v[1]] v.add_attr_for_show = WordManager:GetPropertyValue(v[1], v.add_attr) end end break end end if not has_attr then --如果在列表1里没找到 if v.attr_value then result[v.index] = v.attr_value if write_to_witch_list then if write_to_witch_list == 1 then vv.add_attr = vv.attr_value vv.add_attr_for_show = WordManager:GetPropertyValue(vv.index, vv.add_attr) else v.add_attr = v.attr_value v.add_attr_for_show = WordManager:GetPropertyValue(v.index, v.add_attr) end end elseif v[2] then result[v[1]] = v[2] if write_to_witch_list then if write_to_witch_list == 1 then vv.add_attr = vv[2] vv.add_attr_for_show = WordManager:GetPropertyValue(vv[1], vv.add_attr) else v.add_attr = v[2] v.add_attr_for_show = WordManager:GetPropertyValue(v[1], v.add_attr) end end end end end local new_attr_list = {} for k,v in pairs(result) do table.insert(new_attr_list, {k,v}) end return new_attr_list end --上面那个放大有毒算不对 太菜了 计算两属性的差值attr_list2 - attr_list1 function GetAttributeOffset2( attr_list1, attr_list2 ) attr_list1 = ComposeAttr(attr_list1) attr_list2 = ComposeAttr(attr_list2) local new_list = {} local is_find = false for i,v in ipairs(attr_list2) do is_find = false for ii,vv in ipairs(attr_list1) do if v[1] == vv[1] then is_find = true new_list[#new_list + 1] = {v[1],v[2]-vv[2] > 0 and v[2]-vv[2] or 0} break end end if not is_find then new_list[#new_list + 1] = {v[1],v[2]} end end return new_list end --合并相同属性值 function ComposeAttr( attr_list ) local com_list = {}--合并同样属性的战力值 for i,v in ipairs(attr_list) do if not com_list[v[1]] then com_list[v[1]] = {v[1],v[2]} else com_list[v[1]] = {v[1],v[2]+com_list[v[1]][2]} end end local fight_attr_list = {} for i,v in pairs(com_list) do fight_attr_list[#fight_attr_list + 1] = v end return fight_attr_list end -- 根据字符长度限制文本展示内容,超过字符限制的内容就用...或addition_str代替 -- 例如: LimitTextByCharNum(玩家名称): 玩家名称 -- LimitTextByCharNum(玩家名称称): 玩家名称... function LimitTextByCharNum(txt_str, len, sub_len, addition_str) if not txt_str then return "" end len = len or 4 -- 默认四个字符 sub_len = sub_len or len -- 截断位置,默认跟长度字符数相等 addition_str = addition_str or "..." if utf8len(txt_str) > len then -- txt_str = SubStringUTF8(txt_str, 1, sub_len) .. addition_str end return txt_str end -- 转化角度 -- 类型1 将角度转化为 -180~180之间 function ClampAngleType1(angle) if angle > 180 then angle = angle - 360 elseif angle < -180 then angle = angle + 360 end return angle end -- 类型2 将角度转化为 0~360之间 function ClampAngleType2(angle) if angle > 360 then angle = angle - math.floor(angle / 360) * 360 elseif angle < 0 then angle = angle + math.ceil(math.abs(angle) / 360) * 360 end return angle end --设置七彩颜色字符串 function SetSevenColorStr( str ) str = str or "" local new_str = "" local len = #(string.gsub(str, "[\128-\191]", "")) -- 计算字符数(不是字节数) if len > 0 then local s = {} local i = 1 for c in string.gmatch(str, ".[\128-\191]*" ) do -- 21.2 Pattern-Matching Functions s[i]=c -- 21.7 Unicode i=i+1 end local color_index = 1 local max_color_list_len = #EquipModel.ColorList for i,v in ipairs(s) do new_str = new_str..HtmlColorTxt(v, EquipModel.ColorList[color_index]) color_index = color_index + 1 if color_index > max_color_list_len then color_index = 1 end end end return new_str end -- 随机打乱一个序列表的元素顺序 function RandomizeSequenceTableData(tb) if not tb then return nil end local ram_tb = {} local len = #tb for k = 1, len do ram_tb[#ram_tb+1] = table.remove(tb, math.random(1, len - k + 1)) end return ram_tb end -- 当有输入框然后又有字数限制的时候,要获取限制内的字符串就用这个方法,例: -- new_str1 = abc啊啊啊 => abc啊啊啊 -- new_str2 = efgd啊啊啊 => efgd啊啊 -- new_str3 = ed啊啊aa啊啊 => ed啊啊aa(都是默认限制6位) function GetInputLimitResultStr(str, limit) limit = limit or 6 local len = #(string.gsub(str, "[\128-\191]", "")) -- 计算字符数(不是字节数) local new_str = "" local i = 0 if len > 0 then for c in string.gmatch(str, ".[\128-\191]*" ) do -- 21.2 Pattern-Matching Functions i = i + 1 new_str = new_str .. c if i >= limit then break end end return new_str end return "" end function UrlEncode(s) s = string.gsub(s, "([^%w%.%- ])", function(c) return string.format("%%%02X", string.byte(c)) end) return string.gsub(s, " ", "+") end function UrlDecode(s) s = string.gsub(s, '%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end) return s end function ScreenShot( ) local name = "screenshot"..TimeUtil:getServerTime( ) local png_path = "phone/"..name..".png" local save_path = Util.DataPath..png_path if SystemRuntimePlatform.IsAndroid() then local game_path = "luaFramework/" save_path = game_path..png_path end if UnityEngine and UnityEngine.ScreenCapture then UnityEngine.ScreenCapture.CaptureScreenshot(save_path) end local function on_delay( ) Message.show("截图成功:"..save_path) end setTimeout(on_delay, 1) end