UGCProjects/GZJ/Script/Global/GlobalFunctions.lua
2025-01-08 22:46:12 +08:00

670 lines
17 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

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

GlobalFunctions = GlobalFunctions or {}
GlobalFunctions.IsServer = nil
GlobalFunctions.IsShipping = nil
function UE.LogTag()
if GlobalFunctions.IsServer == nil then
GlobalFunctions.IsServer = UGCGameSystem.IsServer()
end
local LogStr = "[UGCLog]"
if GlobalFunctions.IsServer == true then
LogStr = LogStr .. "[Server]"
else
LogStr = LogStr .. "[Client]"
end
if GameDataManager and UE.IsValid(GameDataManager.GetLocalPlayerState()) then
LogStr = LogStr .. "[" .. GameDataManager.GetLocalPlayerState().PlayerKey .. "]"
end
return LogStr
end
function UE.Print(Log)
print(Log)
end
function UE.Log(Fmt, ...)
local LogStr = UE.LogTag()..string.format(Fmt, ...)
UE.Print(LogStr)
end
function UE.LogError(Fmt, ...)
local LogStr = UE.LogTag().."[Error]"..string.format(Fmt, ...)
UE.Print(LogStr)
end
function UE.LogUGC(Fmt, ...)
local LogStr = UE.LogTag()..string.format(Fmt, ...)
ugcprint(LogStr)
end
function GlobalFunctions.GetAttributeDisplayType(InAttributeName)
for Name, Config in pairs(GlobalConfigs.Attributes) do
if Name == InAttributeName then
return Config.Type
end
end
return EAttributeDisplayType.Int
end
---获取武器蓝图路径
---@return WeaponClassPath string @蓝图路径
---@param ID int
function GlobalFunctions.GetWeaponClassPath(ID)
local WeaponData = Tables.Weapon[ID]
if WeaponData ~= nil then
return WeaponData.ClassPath
end
return nil
end
---获取武器名称
---@return WeaponName string @武器名称
---@param ID int
function GlobalFunctions.GetWeaponName(ID)
local WeaponData = Tables.Weapon[ID]
if WeaponData ~= nil then
return WeaponData.WeaponName
end
return nil
end
---发送自定义Action
---生效范围S
---@param EventName string @事件名称
---@param EventWaitTime int @事件等待时间
function GlobalFunctions.SendEventNextSecond(EventName, EventWaitTime)
if EventName == "" then
UE.Log("[GlobalFunctions.SendEventNextSecond] Not SendEvent")
return
end
local GameState = UGCGameSystem.GameState
if not GameState then
return
end
if GameState.ActionHandles == nil then
GameState.ActionHandles = {}
GameState.ActionHandleIndex = 0
end
GameState.ActionHandleIndex = GameState.ActionHandleIndex + 1
local HandleIndex = GameState.ActionHandleIndex
UE.Log("[GlobalFunctions.SendEventNextSecond] SendEvent: %s, WaitTime: %s", EventName, tostring(EventWaitTime))
local ActionHandle = {
Delegate = nil,
Timer = nil,
}
ActionHandle.Delegate = ObjectExtend.CreateDelegate(GameState,
function()
if type(EventWaitTime) == "number" and EventWaitTime > 0 then
UGCGameSystem.SendModeCustomEvent(EventName, EventWaitTime)
else
UGCGameSystem.SendModeCustomEvent(EventName)
end
if GameState.ActionHandles[HandleIndex] and GameState.ActionHandles[HandleIndex].Delegate then
ObjectExtend.DestroyDelegate(GameState.ActionHandles[HandleIndex].Delegate)
GameState.ActionHandles[HandleIndex].Delegate = nil
end
if GameState.ActionHandles[HandleIndex] and GameState.ActionHandles[HandleIndex].Timer then
KismetSystemLibrary.K2_ClearTimerHandle(GameState, GameState.ActionHandles[HandleIndex].Timer)
GameState.ActionHandles[HandleIndex].Timer = nil
end
GameState.ActionHandles[HandleIndex] = nil
end)
ActionHandle.Timer = KismetSystemLibrary.K2_SetTimerDelegateForLua(ActionHandle.Delegate, GameState, 1, false)
GameState.ActionHandles[HandleIndex] = ActionHandle
end
------------------------------------------------------------------------------------
local RootPackagePath = UGCMapInfoLib.GetRootLongPackagePath()
function GetFullPath(InPath)
if type(InPath) ~= "string" then
return ""
end
if #RootPackagePath > #InPath or string.sub(InPath, 1, #RootPackagePath) ~= RootPackagePath then
InPath = RootPackagePath..InPath
end
return InPath
end
------------------------------------------------------------------------------------
---获取表元素个数
function table.getCount(t)
if type(t) ~= "table" then
return -1
end
local Length = 0
for i, v in pairs(t) do
Length = Length + 1
end
return Length
end
---获取表中所有的Key
function table.getKeys(t)
if type(t) ~= "table" then
return {}
end
local keys = {}
for k,v in pairs(t) do
keys[#keys + 1] = k
end
return keys
end
---获取对应元素的Index
function table.getIndex(t, v)
if type(t) ~= "table" then
return nil
end
for index, value in pairs(t) do
if value == v then
return index
end
end
return nil
end
---获取表中是否有对应Key
function table.hasKey(t, k)
if type(t) ~= "table" then
return false
end
for key, value in pairs(t) do
if k == key then
return true
end
end
return false
end
---按Key删除表中元素
function table.removeKey(t, k)
if t == nil then
return nil
end
local v = t[k]
t[k] = nil
return v
end
---获取表中是否有对应的Value
function table.hasValue(t, value)
if t == nil then return false end
for k, v in pairs(t) do
if v == value then
return true
end
end
return false
end
---按Value删除表中元素
function table.removeValue(t, value, removeAll)
local deleteNum = 0
local i = 1
local max = table.getCount(t)
while i <= max do
if t[i] == value then
table.remove(t,i)
deleteNum = deleteNum + 1
i = i - 1
max = max - 1
if not removeAll then break end
end
i = i + 1
end
return deleteNum
end
---返回是否是空表
function table.isEmpty(t)
if type(t) ~= "table" then
return true
end
return next(t) == nil
end
function table.Swap(t, i, j)
if type(t) ~= "table" then
return
end
local temp = t[i]
t[i] = t[j]
t[j] = temp
end
-- 针对 t1, t2 做插值注意t1 是 t2 的子集
function table.Diff(t1, t2)
local val = {}
for i, v in pairs(t2) do
if t1[i] == nil then
val[i] = v
end
end
return val
end
--- table随机(洗牌算法)
function table.Rand(t)
if type(t) ~= "table" then
return false
end
for i = 1, #t - 1 do
local SwapIndex = math.random(i + 1, #t)
table.Swap(t, i, SwapIndex)
end
end
---@param header string
---@param tbl table
---@param maxIndent integer
---❉ 递归打印table默认并且最多支持打印5层Table嵌套
function table.print(header, tbl, maxIndent)
local logFunc = UE.Log
local maxIndent = maxIndent or 5
maxIndent = math.max(1,maxIndent)
maxIndent = math.min(5,maxIndent)
if tbl == nil or type(tbl) ~= 'table' then
logFunc("table.print input arg is not a table type!")
return
end
logFunc(header)
logFunc("========= content of table(\"" .. tostring(tbl) .."\") ===========")
local function printInternal(t, prevKey, indent)
local indent = indent
if indent > maxIndent then
logFunc(prevKey .. "Over " .. maxIndent .." indents,omit print...")
return
end
for key, value in pairs(t) do
local printKey = prevKey .. "." .. tostring(key)
logFunc(printKey .. " = " .. tostring(value))
if key ~= "_outer" and type(value) == 'table' then
if next(value) == nil then
logFunc(printKey .. " = " .. "{ }")
else
printInternal(value, printKey, indent + 1)
end
end
end
end
printInternal(tbl, "", 0)
end
---clamp
---@param v number @number
---@param Min number @min
---@param Max number @max
---@return number @clamp v between Min and Max
function math.clamp(v, Min, Max)
Min = math.min(Min, Max)
Max = math.max(Min, Max)
if v < Min then
return Min
end
if v > Max then
return Max
end
return v
end
---clamp
---@param a number @First number to compare
---@param b number @Second number to compare
---@param Tolerance number @Maximum allowed difference for considering them as 'nearly equal'
---@return boolean @true if a and b are nearly equal
function math.isNearlyEqual(a, b, Tolerance)
if Tolerance == nil then
Tolerance = 0.01
end
return math.abs(a - b) <= Tolerance
end
--- @param n integer 正整数
function math.pow(x, n)
local val = x
for i = 1, n do
val = val * val
end
return val
end
---字符串分割
function string.split(InStr, sep)
local sep, fields = sep or "\t",{}
local pattern = string.format("([^%s]+)", sep)
InStr:gsub(pattern, function(c) fields[#fields+1] = c end)
return fields
end
---字符串直接转Number
function string.splitToNumber(InStr, sep)
local sep, fields = sep or "\t",{}
local pattern = string.format("([^%s]+)", sep)
InStr:gsub(pattern, function(c) fields[#fields+1] = tonumber(c) end)
return fields
end
---------------------------------For Items---------------------------------
---11111
---对于武器配件来说
---第一位:大类 1
---第二位:物品类型 1~5
---第三位:所属武器类型 1~6
---第四位:物品品质 1~4
---第五位:物品伤害类型 0
---
---对于技能书来说
---第一位:大类 2
---第二、三位:技能类型 01~99
---第四位:品质 1~4
---第五位:伤害类型 0
---
---对于石头来说
---第一位:大类 3
---第二位:具体分类 1~2
---第三四五位:保留字段 000
---
---以下是武器配件的方法
---获取品质,对应 Tables.QualityInfo
function GetItemQualityLevel(InItemId)
return (InItemId // 10) % 10 - 1
end
---获取物品所属武器类型,注意第一个是手枪,因此不需要 - 1
function GetItemWeaponTypeByItemId(InItemId)
return (InItemId // 100) % 10
end
---获取物品类型,此处返回的是 1-5如果要对应 Enum需要再 - 1
function GetItemTypeByItemId(InItemId)
local val = InItemId // 10000 -- 对应的是 EItemType
if val == 1 then
return (InItemId // 1000) % 10 - 1
elseif val == 2 then
return EItemType.SkillBook
elseif val == 3 then
if InItemId // 1000 == 31 then
return EItemType.ScouringStone
elseif InItemId // 1000 == 32 then
return EItemType.SubstituteStone
end
end
print(string.format("[GetItemTypeByItemId] 此时 ItemId 有问题ItemId = %d", InItemId))
end
function GetSkillIdByItemId(InItemId)
if InItemId < 20000 or InItemId > 29999 then
return nil
end
return InItemId % 10000 // 100
end
---获取物品大类,都是对应 Enum: EDropItemSet
function GetItemGrantTypeById(InItemId)
return (InItemId // 10000) - 1
end
function GetItemDamageTypeByItemId(InItemId)
return (InItemId % 10)
end
function IsWeaponPartItem(InItemId)
if InItemId == nil then
return false
end
local Id = InItemId // 10000
return Id == EDropItemSet.WeaponParts + 1
end
function IsSkillBookItem(InItemData)
local Id = InItemData.ItemID // 10000
return Id == EDropItemSet.SkillBooks + 1
end
function IsStoneItem(InItemData)
local Id = InItemData.ItemID // 10000
return Id == EDropItemSet.Stones + 1
end
function GenerateSkillBookData(SkillType)
local RateTable = {
[1] = {Min = 1, Max = 85},
[2] = {Min = 86, Max = 98},
[3] = {Min = 99, Max = 100},
}
local Rand = math.random(1, 100)
local ResultQuality = -1
for Quality, Rates in pairs(RateTable) do
if Rand >= Rates.Min and Rand <= Rates.Max then
ResultQuality = Quality
break
end
end
local StartSkillName = ESkillName.Counter
local EndSkillName = ESkillName.Bombing
if SkillType ~= nil then --刷出制定类型的技能(主动/被动)
if SkillType == ESkillType.Passive then
EndSkillName = ESkillName.Scabbing
elseif SkillType == ESkillType.Active then
StartSkillName = ESkillName.DeathStrike
end
end
local SkillNamePool = {}
for i = StartSkillName, EndSkillName do
table.insert(SkillNamePool, i)
end
local ResultSkillName = SkillNamePool[math.random(1, #SkillNamePool)]
local ItemData = {
-- 此处需要修改,中间两位是具体生成的
ItemID = 20000 + ResultQuality * 10 + ResultSkillName * 100,
ItemType = EItemType.SkillBook,
Quality = ResultQuality,
Count = 1,
}
UE.Log("DropItem: ItemType = %d, ItemType = %d, Quality = %d", ItemData.ItemID, ItemData.ItemType, ItemData.Quality)
return ItemData
end
function GenerateWeaponPartData()
local WeaponPartTypeRateTable = {
[EItemType.Muzzle] = {Min = 1, Max = 20},
[EItemType.Grip] = {Min = 21, Max = 40},
[EItemType.Mag] = {Min = 41, Max = 60},
[EItemType.Stock] = {Min = 61, Max = 80},
[EItemType.Scope] = {Min = 81, Max = 100},
}
local Rand1 = math.random(1, 100)
local ResultItemType = -1
for ItemType, Rates in pairs(WeaponPartTypeRateTable) do
if Rand1 >= Rates.Min and Rand1 <= Rates.Max then
ResultItemType = ItemType
break
end
end
local QualityRateTable = {
[1] = {Min = 1, Max = 95},
[2] = {Min = 96, Max = 99},
[3] = {Min = 100, Max = 100},
}
local Rand2 = math.random(1, 100)
local ResultQuality = -1
for Quality, Rates in pairs(QualityRateTable) do
if Rand2 >= Rates.Min and Rand2 <= Rates.Max then
ResultQuality = Quality
break
end
end
local WeaponClassTypeRateTable = {
[EWeaponClassType.WT_ShotGun] = {Min = 1, Max = 4},
[EWeaponClassType.WT_MachineGun] = {Min = 5, Max = 8},
[EWeaponClassType.WT_SubmachineGun] = {Min = 9, Max = 12},
[EWeaponClassType.WT_ShooterRifle] = {Min = 13, Max = 16},
[EWeaponClassType.WT_AssaultRifle] = {Min = 17, Max = 20},
[EWeaponClassType.WT_Sniper] = {Min = 21, Max = 24},
}
local Rand3 = math.random(1, 24)
local ResultWeaponClassType = -1
for WeaponClassType, Rates in pairs(WeaponClassTypeRateTable) do
if Rand3 >= Rates.Min and Rand3 <= Rates.Max then
ResultWeaponClassType = WeaponClassType
break
end
end
local ItemData = {
ItemID = 10000 + (ResultItemType + 1) * 1000 + ResultWeaponClassType * 100 + ResultQuality * 10,
ItemType = ResultItemType,
Quality = ResultQuality,
Count = 1,
WeaponClassType = ResultWeaponClassType
}
UE.Log("DropItem: ItemType = %d, ItemType = %d, Quality = %d, WeaponClassType = %d", ItemData.ItemID, ItemData.ItemType, ItemData.Quality, ItemData.WeaponClassType)
return ItemData
end
function GenerateStoneData()
local RateTable = {
[EItemType.SubstituteStone] = {Min = 1, Max = 100},
[EItemType.ScouringStone] = {Min = -1, Max = -100},
}
local Rand = math.random(1, 100)
local ResultItemType = -1
for ItemType, Rates in pairs(RateTable) do
if Rand >= Rates.Min and Rand <= Rates.Max then
ResultItemType = ItemType
break
end
end
local ItemData = {
ItemID = ResultItemType == EItemType.ScouringStone and 31000 or 32000,
ItemType = ResultItemType,
Quality = 1,
Count = 1,
}
UE.Log("DropItem: ItemType = %d, ItemType = %d, Quality = %d", ItemData.ItemID, ItemData.ItemType, ItemData.Quality)
return ItemData
end
function GenerateDropItemData()
local RateTable = {
[EDropItemSet.SkillBooks] = {Min = 1, Max = 95},
-- 默认不需要这个
--[EDropItemSet.WeaponParts] = {Min = -100, Max = -10},
[EDropItemSet.Stones] = {Min = 96, Max = 100},
}
local Rand = math.random(1, 100)
local ResultItemSet = -1
for ItemSet, Rates in pairs(RateTable) do
if Rand >= Rates.Min and Rand <= Rates.Max then
ResultItemSet = ItemSet
break
end
end
if ResultItemSet == EDropItemSet.WeaponParts then
return GenerateWeaponPartData()
elseif ResultItemSet == EDropItemSet.SkillBooks then
return GenerateSkillBookData()
else
return GenerateStoneData()
end
--return GenerateSkillBookData()
end
--创建随机词条
function RandomWeaponProperty(InVal)
-- 从200 中进行随机
math.randomseed(KismetSystemLibrary.GetGameTimeInSeconds(InVal) + math.random())
--这是计算 200
local Val = math.random(1,200)
local WeaponMainPropIndex = 0
for i = 1, 16 do
if Val > Tables.WeaponPropertyConfig[i].ProbabilityMin and Val <= Tables.WeaponPropertyConfig[i].ProbabilityMax then
WeaponMainPropIndex = i
break
end
end
local MinVal = Tables.WeaponPropertyConfig[WeaponMainPropIndex].RandomMin
local MaxVal = Tables.WeaponPropertyConfig[WeaponMainPropIndex].RandomMax
math.randomseed(KismetSystemLibrary.GetGameTimeInSeconds(InVal))
--返回属性的具体值
local c = math.random() * (MaxVal - MinVal) + MinVal
return WeaponMainPropIndex, c
end
--- @return boolean 是否可以随机到
function math.RandomValue(InPercent)
if InPercent > 1 then
InPercent = InPercent * 0.01
end
local RandomNum = math.random()
if RandomNum < InPercent then
return true
end
return false
end
function table.logTree(InTable, Addtions)
-- 首先检测一下是否是table
if Addtions == nil then
Addtions = ''
end
local RetStr = Addtions
if type(InTable) == 'table' then
for i, v in pairs(InTable) do
RetStr = RetStr .. "k: " .. tostring(i) .. '\t';
RetStr = RetStr .. "v: "
if type(v) == 'table' then
RetStr = RetStr .. '\ttype:table\n'
RetStr = RetStr .. table.logTree(v, "\t" .. Addtions)
RetStr = RetStr .. '\n'
else
RetStr = RetStr .. tostring(v) .. '\t';
end
-- RetStr = RetStr ..'\n'
end
else
RetStr = tostring(InTable)
end
return RetStr .. '\n';
end