UGCProjects/GZJ/Script/Global/GlobalFunctions.lua

670 lines
17 KiB
Lua
Raw Normal View History

2025-01-08 22:46:12 +08:00
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