Files
Endfield-Data/LuaScripts/Common/Utils/CharInfoUtils.lua
2026-01-31 21:42:01 +07:00

3353 lines
113 KiB
Lua

local CharInfoUtils = {}
local CharUtils = CS.Beyond.Gameplay.CharUtils
function CharInfoUtils.openCharInfoBestWay(arg)
if PhaseManager:IsOpen(PhaseId.CharInfo) then
PhaseManager:ExitPhaseFast(PhaseId.CharInfo)
PhaseManager:OpenPhase(PhaseId.CharInfo, arg)
else
PhaseManager:OpenPhase(PhaseId.CharInfo, arg)
end
end
function CharInfoUtils.openWeaponInfoBestWay(arg)
if PhaseManager:IsOpen(PhaseId.WeaponInfo) then
PhaseManager:ExitPhaseFast(PhaseId.WeaponInfo)
PhaseManager:OpenPhase(PhaseId.WeaponInfo, arg)
else
PhaseManager:OpenPhase(PhaseId.WeaponInfo, arg)
end
end
function CharInfoUtils.isEndmin(charTemplateId)
return string.find(charTemplateId, "endmin") ~= nil
end
function CharInfoUtils.isCharDevAvailable(instId)
if not Utils.isInMainScope() then
return false
end
return CharInfoUtils.checkIsCardInTrail(instId) == false
end
function CharInfoUtils.checkIsCardInTrail(instId)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(instId)
local isTrail = charInst ~= nil and charInst.charType == GEnums.CharType.Trial
return isTrail
end
function CharInfoUtils.checkIsWeaponInTrail(weaponInstId)
return GameUtil.IsClientSpawned(weaponInstId)
end
function CharInfoUtils.getDefExtraHint(charInstId)
local allAttribute = CharInfoUtils.getCharFinalAttributes(charInstId)
local finalDef = allAttribute[GEnums.AttributeType.Def]
local efficiencyOfDEF = Tables.battleConst.efficiencyOfDEF
local damagePrevent = (1 / (1 + efficiencyOfDEF * finalDef) )
local showInfo = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.PhysicalDamageTakenScalar, damagePrevent, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
})
if showInfo then
return string.format(Language.LUA_CHAR_INFO_DEF_EXTRA_HINT_FORMAT, showInfo.showValue)
end
end
local REACH_SHOW_VALUE = 100
function CharInfoUtils.getCharRelationShowValue(relation)
local reachCount = 0
for i = 2, #Tables.SpaceshipCharRelationLevelTable do
local relationCfg = Tables.SpaceshipCharRelationLevelTable:GetValue(i)
if relation >= relationCfg.favorability then
reachCount = reachCount + 1
else
local lastRelationCfg = Tables.SpaceshipCharRelationLevelTable:GetValue(i - 1)
local gap = relationCfg.favorability - lastRelationCfg.favorability
local rate = math.floor((relation - lastRelationCfg.favorability) / gap * REACH_SHOW_VALUE)
return reachCount * REACH_SHOW_VALUE + rate
end
end
return reachCount * REACH_SHOW_VALUE
end
function CharInfoUtils.generateCharInfoBasicAttrShowInfo(charInstId)
local allAttribute = CharInfoUtils.getCharFinalAttributes(charInstId)
local fcAttrInfoList = CharInfoUtils.generateFCAttrShowInfoList(allAttribute, false, UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR)
local scMainAttrInfoList = CharInfoUtils.generateSCMainAttrShowInfoList(allAttribute, false, UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR)
local scSubAttrInfoList = CharInfoUtils.generateSCSubAttrShowInfoList(allAttribute, false, UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR)
return fcAttrInfoList, scMainAttrInfoList, scSubAttrInfoList
end
function CharInfoUtils._innerGenerateAttrShowInfoListBlack(arg)
local allAttributes = arg.allAttributes
local blackMap = arg.blackMap
local isAttributeDiff = arg.isAttributeDiff == true
local fromSpecificSystem = arg.fromSpecificSystem
local showInfoList = {}
for attributeIndex = 1, GEnums.AttributeType.Enum:ToInt() - 1 do
local attributeType = GEnums.AttributeType.__CastFrom(attributeIndex)
if attributeType then
local attr = allAttributes[attributeType]
if not CharInfoUtils._checkIfAttributeInBlackMap(attributeType, attr, blackMap) then
local attributeShowInfo = CharInfoUtils._innerGenerateAttrShowInfo(attr, attributeType, isAttributeDiff, fromSpecificSystem)
if attributeShowInfo then
table.insert(showInfoList, attributeShowInfo)
end
end
end
end
table.sort(showInfoList, function(a, b)
return a.sortOrder < b.sortOrder
end)
return showInfoList
end
function CharInfoUtils._checkIfAttributeInBlackMap(attrType, attr, blackMap)
if not blackMap then
return false
end
local blackCfg = blackMap[attrType]
if not blackCfg then
return false
end
if blackCfg.forbidAllModifier then
return true
end
local _, attrModifier, _ = AttributeUtils.extractAttrData(attr)
if attrModifier ~= nil then
if blackCfg.forbidModifiers[attrModifier] then
return true
end
end
return false
end
function CharInfoUtils._innerGenerateAttrShowInfoList(allAttributes, showOrder, isAttributeDiff, noSort, fromSpecificSystem)
local showInfoList = {}
if not showOrder then
for attrType, attr in pairs(allAttributes) do
local attributeShowInfo = CharInfoUtils._innerGenerateAttrShowInfo(attr, attrType, isAttributeDiff, fromSpecificSystem)
if attributeShowInfo then
table.insert(showInfoList, attributeShowInfo)
end
end
elseif type(showOrder) == "table" then
for _, attributeType in ipairs(showOrder) do
local attr = allAttributes[attributeType]
local attributeShowInfo = CharInfoUtils._innerGenerateAttrShowInfo(attr, attributeType, isAttributeDiff, fromSpecificSystem)
if attributeShowInfo then
table.insert(showInfoList, attributeShowInfo)
end
end
elseif type(showOrder) == "userdata" then
for i = 1, showOrder.Count do
local attributeType = showOrder[CSIndex(i)]
local attr = allAttributes[attributeType]
local attributeShowInfo = CharInfoUtils._innerGenerateAttrShowInfo(attr, attributeType, isAttributeDiff, fromSpecificSystem)
if attributeShowInfo then
table.insert(showInfoList, attributeShowInfo)
end
end
end
if noSort ~= true then
table.sort(showInfoList, function(a, b)
return a.sortOrder < b.sortOrder
end)
end
return showInfoList
end
function CharInfoUtils._innerGenerateAttrShowInfo(attr, attrType, isAttributeDiff, fromSpecificSystem)
if not attr or not attrType then
return
end
local attrValue, attrModifier, enhancedAttrIndex, enhanceGuaranteeTimesRuleId = AttributeUtils.extractAttrData(attr)
if attrValue then
local attributeShowInfo = AttributeUtils.generateAttributeShowInfo(attrType, attrValue,{
isAttributeDiff = isAttributeDiff,
attrModifier = attrModifier,
enhancedAttrIndex = enhancedAttrIndex,
enhanceGuaranteeTimesRuleId = enhanceGuaranteeTimesRuleId,
fromSpecificSystem = fromSpecificSystem,
})
if attributeShowInfo then
return attributeShowInfo
end
end
end
function CharInfoUtils.generateCompositeAttributeShowInfoList(allAttributes, fromSpecificSystem)
return CharInfoUtils._innerGenerateAttrShowInfoList(allAttributes, nil, false, false, fromSpecificSystem)
end
function CharInfoUtils.generateFCAttrShowInfoList(allAttributes, isAttrDiff, fromSpecificSystem)
return CharInfoUtils._innerGenerateAttrShowInfoList(allAttributes, UIConst.CHAR_INFO_FIRST_CLASS_ATTRIBUTE_SHOW_ORDER, isAttrDiff, false, fromSpecificSystem)
end
function CharInfoUtils.generateSCMainAttrShowInfoList(allAttributes, isAttrDiff, fromSpecificSystem)
return CharInfoUtils._innerGenerateAttrShowInfoList(allAttributes, UIConst.CHAR_INFO_SECOND_CLASS_MAIN_ATTRIBUTE_SHOW_ORDER, isAttrDiff, true, fromSpecificSystem)
end
function CharInfoUtils.generateSCSubAttrShowInfoList(allAttributes, isAttrDiff, fromSpecificSystem)
return CharInfoUtils._innerGenerateAttrShowInfoListBlack({
allAttributes = allAttributes,
blackMap = UIConst.CHAR_INFO_FULL_ATTR_BLACK_MAP,
isAttrDiff = isAttrDiff,
fromSpecificSystem = fromSpecificSystem,
})
end
function CharInfoUtils.generateBasicAttributeShowInfoList(allAttributes, isAttributeDiff)
local showInfoList = {}
for _, attributeType in ipairs(UIConst.CHAR_INFO_BASIC_ATTRIBUTE_SHOW_ORDER) do
local attr = allAttributes[attributeType]
local attributeShowInfo = CharInfoUtils._innerGenerateAttrShowInfo({
attrValue = attr,
modifierType = GEnums.ModifierType.BaseAddition
}, attributeType, isAttributeDiff)
if attributeShowInfo then
table.insert(showInfoList, attributeShowInfo)
end
end
return showInfoList
end
function CharInfoUtils.generateUpgradeAttributeShowInfoList(allAttributes, isAttributeDiff)
local showInfoList = {}
for _, attributeType in ipairs(UIConst.CHAR_INFO_UPGRADE_ATTRIBUTE_SHOW_ORDER) do
local attr = allAttributes[attributeType]
local attributeShowInfo = CharInfoUtils._innerGenerateAttrShowInfo({
attrValue = attr,
modifierType = GEnums.ModifierType.BaseAddition
}, attributeType, isAttributeDiff)
if attributeShowInfo then
table.insert(showInfoList, attributeShowInfo)
end
end
return showInfoList
end
function CharInfoUtils.checkIsCardInSlot(instId)
local curSquadSlot = GameInstance.player.squadManager:GetSlotInCurSquad(instId)
return curSquadSlot ~= nil
end
function CharInfoUtils.getPlayerBreakInfoList()
local breakData = Tables.charBreakTable
local breakInfoList = {}
for i = 1, Tables.characterConst.maxBreak do
local breakCfg = breakData[i]
local breakStatus = breakCfg.breakStatus
table.insert(breakInfoList, {
isHide = breakStatus == 0,
isBigBreak = breakStatus == 1,
})
end
return breakInfoList
end
function CharInfoUtils.getPlayerCharInfoByTemplateId(templateId, charType)
local charBag = GameInstance.player.charBag
return charBag:GetCharInfoByTemplateId(templateId, charType)
end
function CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local charBag = GameInstance.player.charBag
return charBag:GetCharInfo(charInstId)
end
function CharInfoUtils.getPlayerCharInfoByPresetId(presetId)
local charBag = GameInstance.player.charBag
return charBag:GetCharInfoByPresetId(presetId)
end
CharInfoUtils.CHAR_INFO_PAGE_TYPE = {
OVERVIEW = 1,
WEAPON = 2,
EQUIP = 3,
TALENT = 5,
PROFILE = 6,
UPGRADE = 7,
PROFILE_SHOW = 10,
POTENTIAL = 11,
}
function CharInfoUtils.getCharInfoTitle(charTemplateId, pageType)
local charCfg = Tables.characterTable[charTemplateId]
if pageType == UIConst.CHAR_INFO_PAGE_TYPE.OVERVIEW then
return string.format(Language.LUA_CHAR_INFO_TITLE_FORMAT, charCfg.name, Language.LUA_CHAR_INFO_TITLE_OVERVIEW)
elseif pageType == UIConst.CHAR_INFO_PAGE_TYPE.EQUIP then
return string.format(Language.LUA_CHAR_INFO_TITLE_FORMAT, charCfg.name, Language.LUA_CHAR_INFO_TITLE_EQUIP)
elseif pageType == UIConst.CHAR_INFO_PAGE_TYPE.TALENT then
return string.format(Language.LUA_CHAR_INFO_TITLE_FORMAT, charCfg.name, Language.LUA_CHAR_INFO_TITLE_TALENT)
elseif pageType == UIConst.CHAR_INFO_PAGE_TYPE.PROFILE then
return string.format(Language.LUA_CHAR_INFO_TITLE_FORMAT, charCfg.name, Language.LUA_CHAR_INFO_TITLE_PROFILE)
elseif pageType == UIConst.CHAR_INFO_PAGE_TYPE.UPGRADE then
return string.format(Language.LUA_CHAR_INFO_TITLE_FORMAT, charCfg.name, Language.LUA_CHAR_INFO_TITLE_UPGRADE)
elseif pageType == UIConst.CHAR_INFO_PAGE_TYPE.PROFILE_SHOW then
elseif pageType == UIConst.CHAR_INFO_PAGE_TYPE.POTENTIAL then
return string.format(Language.LUA_CHAR_INFO_TITLE_FORMAT, charCfg.name, Language.LUA_CHAR_INFO_TITLE_POTENTIAL)
elseif pageType == UIConst.CHAR_INFO_PAGE_TYPE.WEAPON then
return string.format(Language.LUA_CHAR_INFO_TITLE_FORMAT, charCfg.name, Language.LUA_CHAR_INFO_TITLE_WEAPON)
end
return ""
end
function CharInfoUtils.checkIfCharMaxLv(charInstId)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
return charInst.level >= Tables.characterConst.maxLevel
end
function CharInfoUtils.getCharPassiveSkillCount(charTemplateId)
local charGrowthCfg = CharInfoUtils.getCharGrowthData(charTemplateId)
local talentNodeMap = charGrowthCfg.talentNodeMap
local skillIdDict = {}
for _, talentNode in pairs(talentNodeMap) do
if talentNode.nodeType == GEnums.TalentNodeType.PassiveSkill then
local skillId = talentNode.passiveSkillNodeInfo.skillId
if skillIdDict[skillId] == nil then
skillIdDict[skillId] = true
end
end
end
local passiveSkillCount = lume.count(skillIdDict)
return passiveSkillCount
end
function CharInfoUtils.getCharExpInfo(charInstId)
local charInfo = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local breakStage = charInfo.breakStage
local breakCfg = Tables.charBreakTable[breakStage]
local stageLv = breakCfg.maxLevel
local availableExpItems = breakCfg.availableExpItems
local curLevel = charInfo.level
local curExp = charInfo.exp
local levelUpExp = Tables.charLevelUpTable[curLevel].exp
return curExp, levelUpExp, curLevel, stageLv, availableExpItems
end
function CharInfoUtils.getSkillGroupSubDescList(charTemplateId, skillGroupId, skillGroupLv)
local skillGroupCfg = CharInfoUtils.getSkillGroupCfg(charTemplateId, skillGroupId)
local skillIdList = skillGroupCfg.skillIdList
local isEndmin = CharUtils.IsEndminTemplateId(charTemplateId)
local skillDescList = {}
local skillDescNameList = {}
for i = 1, #skillIdList do
local skillId = skillIdList[CSIndex(i)]
local skillCfg = CharInfoUtils.getSkillCfg(skillId, skillGroupLv)
local isValid = true
if isEndmin and not string.startWith(skillId, CharUtils.curEndminCharTemplateId) then
isValid = false
end
if skillCfg and isValid then
if i == 1 or isEndmin then
local skillExtraInfoList = CharInfoUtils.getSkillExtraInfoList(skillCfg.skillId, skillCfg.level)
for _, extraInfo in ipairs(skillExtraInfoList) do
table.insert(skillDescNameList, extraInfo.name)
table.insert(skillDescList, extraInfo.value)
end
end
for j = 1, #skillCfg.subDescNameList do
local descName = skillCfg.subDescNameList[CSIndex(j)]
if descName == nil or string.isEmpty(descName) then
break
end
table.insert(skillDescNameList, skillCfg.subDescNameList[CSIndex(j)])
end
for j = 1, #skillCfg.subDescList do
local desc = skillCfg.subDescList[CSIndex(j)]
if desc == nil or string.isEmpty(desc) then
break
end
table.insert(skillDescList, skillCfg.subDescList[CSIndex(j)])
end
end
end
return skillDescNameList, skillDescList
end
function CharInfoUtils.getEquipByInstId(equipInstId)
if not equipInstId then
return
end
local _, equipInst = GameInstance.player.inventory:TryGetEquipInst(Utils.getCurrentScope(), equipInstId)
if not equipInst then
return
end
local equipInstanceData = equipInst.instData
return equipInstanceData
end
function CharInfoUtils.getEquipMinWearLv(tierLv)
local hasTier, tierCfg = Tables.equipTierLevelTable:TryGetValue(tierLv)
if not hasTier then
return -1
end
return tierCfg.equiplevel
end
function CharInfoUtils.getCharAllEquipAttributeShowInfos(charInstId)
local mainAttrShowInfos = {}
local extraAttrShowInfos = {}
local defAttr, mainAttrs, extraAttrs = CharInfoUtils.getCharAllEquipAttributes(charInstId)
local defAttrShowInfo = AttributeUtils.generateAttributeShowInfo(defAttr.attrType, defAttr.attrValue, {
attrModifier = defAttr.attrModifier,
})
for _, attr in ipairs(mainAttrs) do
local attributeShowInfo = AttributeUtils.generateAttributeShowInfo(attr.attrType, attr.attrValue, {
attrModifier = attr.attrModifier,
})
table.insert(mainAttrShowInfos, attributeShowInfo)
end
table.sort(mainAttrShowInfos, function(a, b)
return a.sortOrder < b.sortOrder
end)
for _, attr in ipairs(extraAttrs) do
local attributeShowInfo = AttributeUtils.generateAttributeShowInfo(attr.attrType, attr.attrValue, {
attrModifier = attr.attrModifier,
})
table.insert(extraAttrShowInfos, attributeShowInfo)
end
table.sort(extraAttrShowInfos, function(a, b)
return a.sortOrder < b.sortOrder
end)
return defAttrShowInfo, mainAttrShowInfos, extraAttrShowInfos
end
local ATTR_MODIFIER_MERGE_RULE = {
ADD = 1,
MULTIPLY = 2,
}
local DEFAULT_MERGE_RULE = ATTR_MODIFIER_MERGE_RULE.ADD
local EQUIP_ATTR_MODIFIER_TYPE_MERGE_RULE = {
[GEnums.ModifierType.FinalMultiplier] = ATTR_MODIFIER_MERGE_RULE.MULTIPLY,
[GEnums.ModifierType.BaseFinalMultiplier] = ATTR_MODIFIER_MERGE_RULE.MULTIPLY,
}
function CharInfoUtils.getCharAllEquipAttributes(charInstId)
local defAttr = {
attrType = GEnums.AttributeType.Def,
attrValue = 0,
attrModifier = GEnums.ModifierType.BaseAddition,
}
local attrType2ModifierDict = {}
local attrModifierDataList = CharInfoUtils.getAllEquipInstAttributes(charInstId)
for _, attr in ipairs(attrModifierDataList) do
local keyAttrType = attr.keyAttrType
local modifierType = attr.modifierType
local attrValue = attr.attrValue
if modifierType == GEnums.ModifierType.BaseAddition and keyAttrType == GEnums.AttributeType.Def then
if defAttr == nil then
defAttr = {
attrValue = 0,
attrType = GEnums.AttributeType.Def,
attrModifier = modifierType,
}
end
defAttr.attrValue = defAttr.attrValue + attrValue
else
if attrType2ModifierDict[keyAttrType] == nil then
attrType2ModifierDict[keyAttrType] = {}
end
local modifierDict = attrType2ModifierDict[keyAttrType]
if modifierDict[modifierType] == nil then
modifierDict[modifierType] = attrValue
else
if EQUIP_ATTR_MODIFIER_TYPE_MERGE_RULE[modifierType] == ATTR_MODIFIER_MERGE_RULE.MULTIPLY then
modifierDict[modifierType] = modifierDict[modifierType] * attrValue
else
modifierDict[modifierType] = modifierDict[modifierType] + attrValue
end
end
end
end
local mainAttrs = {}
for attrType, modifierDict in pairs(attrType2ModifierDict) do
for modifierType, mergedAttrValue in pairs(modifierDict) do
table.insert(mainAttrs, {
attrValue = mergedAttrValue,
attrType = attrType,
attrModifier = modifierType,
})
end
end
return defAttr, mainAttrs, {}
end
function CharInfoUtils.getAllEquipInstAttributes(charInstId)
local attrTypeDataList = {}
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
for slotIndex, equipInstId in pairs(charInst.equipCol) do
local baseAttr, attrs = CharInfoUtils.getEquipInstAttributes(equipInstId)
table.insert(attrTypeDataList, baseAttr)
for _, attr in ipairs(attrs) do
table.insert(attrTypeDataList, attr)
end
end
return attrTypeDataList
end
function CharInfoUtils.getEquipShowAttributes(instId)
local equipInst = CharInfoUtils.getEquipByInstId(instId)
return CharInfoUtils._genEquipShowAttributes(equipInst.templateId, CharInfoUtils.getEquipInstAttributes(instId))
end
function CharInfoUtils.getEquipTemplateShowAttributes(equipTemplateId)
return CharInfoUtils._genEquipShowAttributes(equipTemplateId, CharInfoUtils.getEquipTemplateAttributes(equipTemplateId))
end
local EQUIP_MAIN_ATTR_INDEX = 2
function CharInfoUtils._genEquipShowAttributes(templateId, equipAttr, attrs)
local defAttrShowInfo = AttributeUtils.generateAttributeShowInfo(equipAttr.keyAttrType, equipAttr.attrValue, {
attrModifier = equipAttr.modifierType,
})
local mainAttrShowList = {}
local extraAttrShowList = {}
for index, attrDisplayInfo in ipairs(attrs) do
local attrShowInfo = AttributeUtils.generateAttributeShowInfo(attrDisplayInfo.keyAttrType, attrDisplayInfo.attrValue, {
attrModifier = attrDisplayInfo.modifierType,
enhancedAttrIndex = attrDisplayInfo.enhancedAttrIndex,
enhanceGuaranteeTimesRuleId = attrDisplayInfo.enhanceGuaranteeTimesRuleId,
})
if attrDisplayInfo.attrIndex <= EQUIP_MAIN_ATTR_INDEX then
table.insert(mainAttrShowList, attrShowInfo)
else
table.insert(extraAttrShowList, attrShowInfo)
end
end
mainAttrShowList = lume.sort(mainAttrShowList, function(a, b)
return a.enhancedAttrIndex < b.enhancedAttrIndex
end)
extraAttrShowList = lume.sort(extraAttrShowList, function(a, b)
return a.enhancedAttrIndex < b.enhancedAttrIndex
end)
return defAttrShowInfo, mainAttrShowList, extraAttrShowList
end
function CharInfoUtils.getEquipTemplateAttributes(templateId)
local _, equipData = Tables.equipTable:TryGetValue(templateId)
if not equipData then
return
end
local attrs = {}
for i = 1, equipData.displayAttrModifiers.Count do
local attrModifier = equipData.displayAttrModifiers[CSIndex(i)]
local attrInfo = {
attrType = attrModifier.attrType,
attrValue = attrModifier.attrValue,
modifierType = attrModifier.modifierType,
attrIndex = attrModifier.attrIndex,
enhancedAttrIndex = attrModifier.enhancedAttrIndex,
enhancedAttrValues = attrModifier.enhancedAttrValues,
enhanceGuaranteeTimesRuleId = attrModifier.enhanceGuaranteeTimesRuleId,
}
if string.isEmpty(attrModifier.compositeAttr) then
attrInfo.keyAttrType = attrModifier.attrType
else
attrInfo.keyAttrType = attrModifier.compositeAttr
end
table.insert(attrs, attrInfo)
end
local displayEquipAttrModifier = equipData.displayBaseAttrModifier
local baseAttr = {
keyAttrType = displayEquipAttrModifier.attrType,
attrType = displayEquipAttrModifier.attrType,
attrValue = displayEquipAttrModifier.attrValue,
modifierType = displayEquipAttrModifier.modifierType,
attrIndex = displayEquipAttrModifier.attrIndex,
enhancedAttrIndex = displayEquipAttrModifier.enhancedAttrIndex,
enhancedAttrValues = displayEquipAttrModifier.enhancedAttrValues,
}
return baseAttr, attrs
end
function CharInfoUtils.getEquipInstAttributes(instId)
local equipInstData = CharInfoUtils.getEquipByInstId(instId)
local baseAttr, attrs = CharInfoUtils.getEquipTemplateAttributes(equipInstData.templateId)
for _, attrInfo in ipairs(attrs) do
attrInfo.attrValue = EquipTechUtils.getEnhancedAttrValue(attrInfo, equipInstData)
end
return baseAttr, attrs
end
function CharInfoUtils.getCharSuitInfoList(instId, focusSuitId)
local suitInfoList = {}
local charEntityInfo = CharInfoUtils.getPlayerCharInfoByInstId(instId)
local equipCol = charEntityInfo.equipCol
local suitTable = {}
local suit2Slots = {}
for slotIndex, equipInstId in pairs(equipCol) do
local equipInstanceData = CharInfoUtils.getEquipByInstId(equipInstId)
local templateId = equipInstanceData.templateId
local _, equipData = Tables.equipTable:TryGetValue(templateId)
local suitId = equipData.suitID
if not suit2Slots[suitId] then
suit2Slots[suitId] = {}
end
if not focusSuitId or focusSuitId == suitId then
suitTable[suitId] = suitTable[suitId] and suitTable[suitId] + 1 or 1
suit2Slots[suitId][slotIndex] = true
end
end
for suitId, suitCount in pairs(suitTable) do
table.insert(suitInfoList, {
suitId = suitId,
suitCount = suitCount,
})
end
suitInfoList = lume.sort(suitInfoList, function(a, b)
return a.suitCount > b.suitCount
end)
return suitInfoList, suit2Slots
end
function CharInfoUtils.getCharTableData(charTemplateId)
local tableData = nil
local characterData = CharInfoUtils.getCharGrowthData(charTemplateId)
if characterData then
tableData = characterData
end
return tableData
end
function CharInfoUtils.getCharBaseAttributes(instId, baseTypeMask)
local charInfo = CharInfoUtils.getPlayerCharInfoByInstId(instId)
return CharInfoUtils._getSlotBaseAttributes(charInfo, baseTypeMask)
end
function CharInfoUtils.getCharArmedAttributes(instId, armedTypeMask, baseTypeMask)
local charInfo = CharInfoUtils.getPlayerCharInfoByInstId(instId)
return CharInfoUtils._getSlotArmedAttributes(charInfo, armedTypeMask, baseTypeMask)
end
function CharInfoUtils.getCharFinalAttributes(instId)
local charInfo = CharInfoUtils.getPlayerCharInfoByInstId(instId)
return CharInfoUtils.getCharFinalAttributesFromSpecificCache(charInfo.attributes)
end
function CharInfoUtils.getCharFinalAttributesFromSpecificCache(allAttributes)
local attributes = {}
for i = 1, GEnums.AttributeType.Enum:ToInt() - 1 do
local attributeType = GEnums.AttributeType.__CastFrom(i)
if attributeType then
attributes[attributeType] = allAttributes:GetValue(attributeType)
end
end
return attributes
end
function CharInfoUtils.getQualifiedEquipBreakNodeIdByEquipTierLimit(equipTierLimit)
for nodeId, nodeCfg in pairs(Tables.charBreakNodeTable) do
if nodeCfg.equipTierLimit == equipTierLimit and nodeCfg.talentNodeType == GEnums.TalentNodeType.EquipBreak then
return nodeId
end
end
end
function CharInfoUtils.checkCharInTeam(charInstId, teamIndex)
if not teamIndex or teamIndex <= 0 then
return -1
end
local teamInfo = GameInstance.player.charBag.teamList[CSIndex(teamIndex)]
local memberList = teamInfo.memberList
for index = 1, memberList.Count do
local instId = memberList[CSIndex(index)]
if instId == charInstId then
return index
end
end
return -1
end
function CharInfoUtils.getAllCharInfoList()
local charBag = GameInstance.player.charBag
local charInfoList = {}
local playerChars = charBag.charInfos
for _, charInfo in cs_pairs(playerChars) do
local isClientOnly = GameUtil.IsRuntimeClientId(charInfo.instId)
if not isClientOnly then
local templateId = charInfo.templateId
local charData = CharInfoUtils.getCharTableData(templateId)
local item = {
instId = charInfo.instId,
templateId = templateId,
ownTime = charInfo.ownTime,
level = charInfo.level,
rarity = charData.rarity,
slotIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM + 1,
slotReverseIndex = -1,
}
table.insert(charInfoList, item)
end
end
return charInfoList
end
function CharInfoUtils.getCurScopeCharInfoList(csTeamIndex)
local charBag = GameInstance.player.charBag
local charInfoList = {}
local playerChars = charBag.charInfos
local scopeCharList = charBag.charList
if csTeamIndex == nil then
csTeamIndex = charBag.curTeamIndex
end
local teamInfo = charBag.teamList[csTeamIndex]
local memberList = teamInfo.memberList
for i = 1, memberList.Count do
local instId = memberList[CSIndex(i)]
local charInfo = playerChars[instId]
local templateId = charInfo.templateId
local charCfg = Tables.characterTable:GetValue(templateId)
local item = {
instId = instId,
templateId = charInfo.templateId,
level = charInfo.level,
ownTime = charInfo.ownTime,
rarity = charCfg.rarity,
slotIndex = i,
slotReverseIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM - i,
sortOrder = charCfg.sortOrder,
singleSelect = true,
}
table.insert(charInfoList, item)
end
for i = 1, scopeCharList.Count do
local charInfo = scopeCharList[CSIndex(i)]
local instId = charInfo.instId
local isClientOnly = GameUtil.IsRuntimeClientId(instId)
if (not isClientOnly) and (CharInfoUtils.checkCharInTeam(instId, LuaIndex(csTeamIndex)) <= 0) then
local templateId = charInfo.templateId
local charCfg = Tables.characterTable:GetValue(templateId)
local item = {
instId = instId,
templateId = templateId,
ownTime = charInfo.ownTime,
level = charInfo.level,
rarity = charCfg.rarity,
slotIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM + 1,
slotReverseIndex = -1,
sortOrder = charCfg.sortOrder,
}
table.insert(charInfoList, item)
end
end
charInfoList = lume.sort(charInfoList, Utils.genSortFunction(UIConst.CHAR_FORMATION_LIST_SORT_OPTION[1].reverseKeys))
return charInfoList
end
function CharInfoUtils.getCharInfoList(csTeamIndex)
local charBag = GameInstance.player.charBag
local charInfoList = {}
local playerChars = charBag.charInfos
if csTeamIndex == nil then
csTeamIndex = charBag.curTeamIndex
end
local teamInfo = charBag.teamList[csTeamIndex]
local memberList = teamInfo.memberList
for i = 1, memberList.Count do
local instId = memberList[CSIndex(i)]
local charInfo = playerChars[instId]
local templateId = charInfo.templateId
local charCfg = Tables.characterTable:GetValue(templateId)
local item = {
instId = instId,
templateId = charInfo.templateId,
level = charInfo.level,
ownTime = charInfo.ownTime,
rarity = charCfg.rarity,
slotIndex = i,
slotReverseIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM - i,
sortOrder = charCfg.sortOrder,
singleSelect = true,
}
table.insert(charInfoList, item)
end
for instId, charInfo in pairs(playerChars) do
local isClientOnly = GameUtil.IsRuntimeClientId(instId)
if (not isClientOnly) and (CharInfoUtils.checkCharInTeam(instId, LuaIndex(csTeamIndex)) <= 0) then
local templateId = charInfo.templateId
local charCfg = Tables.characterTable:GetValue(templateId)
local item = {
instId = instId,
templateId = templateId,
ownTime = charInfo.ownTime,
level = charInfo.level,
rarity = charCfg.rarity,
slotIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM + 1,
slotReverseIndex = -1,
sortOrder = charCfg.sortOrder,
}
table.insert(charInfoList, item)
end
end
charInfoList = lume.sort(charInfoList, Utils.genSortFunction(UIConst.CHAR_FORMATION_LIST_SORT_OPTION[1].reverseKeys))
return charInfoList
end
function CharInfoUtils.getSingleCharInfoList(charInstId)
return CharInfoUtils.getCharInfoListByInstIdList({charInstId})
end
function CharInfoUtils.getCharInfoListByInstIdList(charInstIdList, isShowPreview)
local charInfoList = {}
for _, charInstId in pairs(charInstIdList) do
local charInfo = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local charData = CharInfoUtils.getCharTableData(charInfo.templateId)
local item = {
instId = charInstId,
templateId = charInfo.templateId,
level = charInfo.level,
ownTime = charInfo.ownTime,
rarity = charData.rarity,
slotIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM + 1,
slotReverseIndex = -1,
isShowPreview = isShowPreview or false,
}
table.insert(charInfoList, item)
end
return charInfoList
end
function CharInfoUtils.checkCharInLockedTeam(charInfo, lockedTeamData)
local isLocked = false
local isReplaceable = false
local isInLockedTeam = false
for _, char in ipairs(lockedTeamData.chars) do
if char.charInstId == charInfo.instId then
isInLockedTeam = true
break
end
if char.isReplaceable and char.charId == charInfo.templateId then
isLocked = true
isReplaceable = true
end
end
return isInLockedTeam, isLocked, isReplaceable
end
function CharInfoUtils.getCharInfoListWithLockedTeamData(lockedTeamData)
local charBag = GameInstance.player.charBag
local charInfoList = {}
local playerChars = charBag.charInfos
local allCount = 0
if lockedTeamData then
for i, char in ipairs(lockedTeamData.chars) do
local charInfo = CharInfoUtils.getPlayerCharInfoByInstId(char.charInstId)
local charData = CharInfoUtils.getCharTableData(char.charId)
local item = {
instId = char.charInstId,
templateId = char.charId,
level = charInfo.level,
ownTime = charInfo.ownTime,
rarity = charData.rarity,
slotIndex = i,
slotReverseIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM - i,
isLocked = char.isLocked,
isTrail = char.isTrail,
isReplaceable = char.isReplaceable,
}
table.insert(charInfoList, item)
allCount = allCount + 1
end
if lockedTeamData.lockedTeamMemberCount == lockedTeamData.maxTeamMemberCount and
not lockedTeamData.hasReplaceable then
return charInfoList, allCount
end
end
for instId, charInfo in pairs(playerChars) do
local isClientOnly = GameUtil.IsRuntimeClientId(instId)
local isInLockedTeam, isLock, isReplaceable = CharInfoUtils.checkCharInLockedTeam(charInfo, lockedTeamData)
if not isInLockedTeam and not isClientOnly then
local templateId = charInfo.templateId
local charData = CharInfoUtils.getCharTableData(templateId)
local item = {
instId = instId,
templateId = templateId,
ownTime = charInfo.ownTime,
level = charInfo.level,
rarity = charData.rarity,
slotIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM + 1,
slotReverseIndex = -1,
isLocked = isLock,
isReplaceable = isReplaceable,
}
table.insert(charInfoList, item)
if not isReplaceable and not charInfo.isDead then
allCount = allCount + 1
end
end
end
local hasValue
local charTeamData
hasValue, charTeamData = Tables.charTeamTable:TryGetValue(lockedTeamData.teamConfigId)
if hasValue then
for _, charPresetId in pairs(charTeamData.presetCharList) do
local charPresetData
hasValue, charPresetData = Tables.charPresetTable:TryGetValue(charPresetId)
if hasValue then
local charInfo = CharInfoUtils.getPlayerCharInfoByPresetId(charPresetId)
local isInLockedTeam, isLock, isReplaceable = CharInfoUtils.checkCharInLockedTeam(charInfo, lockedTeamData)
if not isInLockedTeam then
local charData = CharInfoUtils.getCharTableData(charInfo.templateId)
local item = {
instId = charInfo.instId,
templateId = charInfo.templateId,
level = charInfo.level,
ownTime = charInfo.ownTime,
rarity = charData.rarity,
slotIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM + 1,
slotReverseIndex = -1,
isTrail = true,
isLocked = isLock,
isReplaceable = isReplaceable,
}
table.insert(charInfoList, item)
if not isReplaceable then
allCount = allCount + 1
end
end
end
end
end
return charInfoList, allCount
end
function CharInfoUtils.getLeaderCharInfo()
local leaderIndex = GameInstance.player.squadManager.leaderIndex
local curSquad = GameInstance.player.squadManager.curSquad
local slot = curSquad.slots[leaderIndex]
local charInstId = slot.charInstId
local isClientOnly = GameUtil.IsRuntimeClientId(charInstId)
if isClientOnly then
local firstAvailableChar = CharInfoUtils.getServerEndmin()
return firstAvailableChar
end
local playerChar = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
if playerChar ~= nil then
local charInfo = {
instId = playerChar.instId,
templateId = playerChar.templateId,
}
return charInfo
else
return nil
end
end
function CharInfoUtils.getServerEndmin()
local charBag = GameInstance.player.charBag
local playerChars = charBag.charInfos
for instId, charInfo in pairs(playerChars) do
local isClientOnly = GameUtil.IsRuntimeClientId(instId)
if (not isClientOnly) and CharInfoUtils.isEndmin(charInfo.templateId) then
return{
instId = instId,
templateId = charInfo.templateId
}
end
end
end
function CharInfoUtils.getCharDisplayData(templateId)
local data
local res, displayData = DataManager.characterDisplayConfig.data:TryGetValue(templateId)
if res then
data = displayData
end
return data
end
function CharInfoUtils.getCharHeightData(charHeight)
local res, displayData = DataManager.characterHeightConfig.heightDataDict:TryGetValue(charHeight)
if not res then
return
end
return displayData
end
function CharInfoUtils.getCharHeadSpriteName(templateId)
return UIConst.UI_SPRITE_CHAR_HEAD, UIConst.UI_CHAR_HEAD_PREFIX .. templateId
end
function CharInfoUtils.getCharHeadSquareSpriteName(templateId)
return UIConst.UI_SPRITE_CHAR_HEAD_SQUARE, UIConst.UI_CHAR_HEAD_PREFIX .. templateId
end
function CharInfoUtils.getCharPaperAttributes(templateId, level, breakStage)
local attributes = {}
local _, attributesWithStringKey = DataManager.characterAttributeTable:TryGetData(templateId, level, breakStage)
return attributesWithStringKey
end
function CharInfoUtils._getSlotBaseAttributes(charInfo, typeMask)
if typeMask == nil then
typeMask = UIConst.CHAR_INFO_ATTRIBUTE_ALL_FILTER_MASK
end
local attributes = {}
for i = 1, GEnums.AttributeType.Enum:ToInt() - 1 do
local attributeType = GEnums.AttributeType.__CastFrom(i)
if attributeType then
attributes[attributeType] = charInfo.attributes:GetBaseValue(attributeType, typeMask)
end
end
return attributes
end
function CharInfoUtils._getSlotArmedAttributes(charInfo, armedTypeMask, baseTypeMask)
if armedTypeMask == nil then
armedTypeMask = UIConst.CHAR_INFO_ATTRIBUTE_ALL_FILTER_MASK
end
if baseTypeMask == nil then
baseTypeMask = UIConst.CHAR_INFO_ATTRIBUTE_ALL_FILTER_MASK
end
local attributes = {}
for i = 1, GEnums.AttributeType.Enum:ToInt() - 1 do
local attributeType = GEnums.AttributeType.__CastFrom(i)
if attributeType then
attributes[attributeType] = charInfo.attributes:GetArmedValue(attributeType, armedTypeMask, baseTypeMask)
end
end
return attributes
end
function CharInfoUtils._getSlotFinalAttributes(charInfo)
local attributes = {}
if charInfo.attributes == nil then
logger.error("CharInfoUtils->Can't get char attributes, charTemplateId:" .. charInfo.templateId)
return attributes
end
local attributes = {}
for i = 1, GEnums.AttributeType.Enum:ToInt() - 1 do
local attributeType = GEnums.AttributeType.__CastFrom(i)
if attributeType then
attributes[attributeType] = charInfo.attributes:GetValue(attributeType)
end
end
return attributes
end
function CharInfoUtils.getCharGrowthData(charTemplateId)
charTemplateId = CharUtils.GetVirtualCharTemplateId(charTemplateId)
local _, charGrowthData = Tables.charGrowthTable:TryGetValue(charTemplateId)
return charGrowthData
end
function CharInfoUtils.getCharProfessionIconName(profession, isSmall)
local iconName = ''
local _, professionData = Tables.charProfessionTable:TryGetValue(profession)
if professionData then
iconName = professionData.iconId
if isSmall then
iconName = iconName .. UIConst.UI_CHAR_PROFESSION_SMALL_SUFFIX
end
end
return iconName
end
function CharInfoUtils.getAllWeaponList(weaponType)
local weaponList = {}
local res, weaponInstDict = GameInstance.player.inventory:TryGetAllWeaponInstItems(Utils.getCurrentScope())
if res then
for weaponInstId, itemBundle in pairs(weaponInstDict) do
local instInfo = CharInfoUtils.getWeaponInstInfo(weaponInstId)
local weaponInfo = FilterUtils.processWeapon(instInfo.weaponTemplateId, instInfo.weaponInstId)
weaponInfo.instInfo = instInfo
if not weaponType or instInfo.weaponCfg.weaponType == weaponType then
table.insert(weaponList, weaponInfo)
end
end
end
return weaponList
end
function CharInfoUtils.getWeaponInstInfo(weaponInstId)
local res, itemBundle = GameInstance.player.inventory:TryGetWeaponInst(Utils.getCurrentScope(), weaponInstId)
if not res then
return
end
local weaponInst = itemBundle.instData
local weaponTemplateId = weaponInst.templateId
local _, itemCfg = Tables.itemTable:TryGetValue(weaponTemplateId)
local weaponExhibitInfo = CharInfoUtils.getWeaponExhibitBasicInfo(weaponTemplateId, weaponInstId)
local mainAttributeList, subAttributeList = CharInfoUtils.getWeaponShowAttributes(weaponInstId)
local _, weaponCfg = Tables.weaponBasicTable:TryGetValue(weaponTemplateId)
local data = {
weaponInst = weaponInst,
weaponInstId = weaponInst.instId,
weaponTemplateId = weaponTemplateId,
weaponExhibitInfo = weaponExhibitInfo,
mainAttributeList = mainAttributeList,
subAttributeList = subAttributeList,
itemCfg = itemCfg,
weaponCfg = weaponCfg,
}
return data
end
function CharInfoUtils.getCharCurWeapon(charInstId)
local charInfo = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local weaponInstId = charInfo.weaponInstId
return CharInfoUtils.getWeaponInstInfo(weaponInstId)
end
function CharInfoUtils.getWeaponByInstId(weaponInstId)
local _, weaponInst = GameInstance.player.inventory:TryGetWeaponInst(Utils.getCurrentScope(), weaponInstId)
if not weaponInst then
return
end
local equipInstanceData = weaponInst.instData
return equipInstanceData
end
function CharInfoUtils.getGemByInstId(gemInstId, logError)
local _, getInst = GameInstance.player.inventory:TryGetGemInst(Utils.getCurrentScope(), gemInstId)
if not getInst then
if logError then
logger.error("CharInfoUtils->Can't get gem inst from inventory, gemInstId: " .. tostring(gemInstId))
end
return
end
local gemInstData = getInst.instData
return gemInstData
end
function CharInfoUtils.isGemTermEnhanceMax(termId, level)
local _, termCfg = Tables.gemTable:TryGetValue(termId)
if not termCfg then
logger.error("CharInfoUtils->Can't get gem term config, termId: " .. termId)
return false
end
local isMax = true
local _, gemEnhanceDataList = Tables.gemEnhanceTable:TryGetValue(termCfg.termType)
if gemEnhanceDataList then
local maxEnhanceData = gemEnhanceDataList.list[#gemEnhanceDataList.list - 1]
if maxEnhanceData then
isMax = level >= maxEnhanceData.termCost
end
end
return isMax
end
function CharInfoUtils.getGemLeadSkillTermId(gemInstId)
local gemInst = CharInfoUtils.getGemByInstId(gemInstId)
if not gemInst then
return
end
local maxCost = -1
local maxCostTermId
for _, skillTerm in pairs(gemInst.termList) do
local challengerCfg = Tables.gemTable:GetValue(skillTerm.termId)
if challengerCfg.isSkillTerm then
if skillTerm.cost > maxCost then
maxCost = skillTerm.cost
maxCostTermId = skillTerm.termId
elseif skillTerm.cost == maxCost then
local curMaxTermCfg = Tables.gemTable:GetValue(maxCostTermId)
local challengerCfg = Tables.gemTable:GetValue(skillTerm.termId)
if challengerCfg and curMaxTermCfg then
if challengerCfg.sortOrder > curMaxTermCfg.sortOrder then
maxCost = skillTerm.cost
maxCostTermId = skillTerm.termId
end
end
end
end
end
return maxCostTermId
end
function CharInfoUtils.getWeaponBreakthroughInfo(weaponInstId, breakthroughLevel)
local _, weaponInst = GameInstance.player.inventory:TryGetWeaponInst(Utils.getCurrentScope(), weaponInstId)
local weaponInstData = weaponInst.instData
if not weaponInstData then
logger.error("CharInfoUtils->Can't get weapon inst from inventory, weaponInstId: " .. weaponInstId)
return
end
if not breakthroughLevel then
breakthroughLevel = weaponInstData.breakthroughLv
end
local weaponTemplateId = weaponInst.id
local _, weaponCfg = Tables.weaponBasicTable:TryGetValue(weaponTemplateId)
if not weaponCfg then
logger.error("CharInfoUtils->Can't get weapon basic info, templateId: " .. weaponTemplateId)
return
end
local breakthroughTemplateId = weaponCfg.breakthroughTemplateId
local _, breakthroughTemplateCfg = Tables.weaponBreakThroughTemplateTable:TryGetValue(breakthroughTemplateId)
if not breakthroughTemplateCfg then
logger.error("CharInfoUtils->Can't get weapon breakthrough info, breakthroughTemplateId: " .. breakthroughTemplateId)
return
end
for i, templateCfg in pairs(breakthroughTemplateCfg.list) do
if templateCfg.breakthroughShowLv == breakthroughLevel then
return templateCfg
end
end
end
function CharInfoUtils.getWeaponExhibitBasicInfo(weaponTemplateId, weaponInstId)
local _, weaponCfg = Tables.weaponBasicTable:TryGetValue(weaponTemplateId)
if not weaponCfg then
logger.error("CharInfoUtils->Can't get weapon basic info, templateId: " .. weaponTemplateId)
return
end
local _, weaponItemCfg = Tables.itemTable:TryGetValue(weaponTemplateId)
if not weaponItemCfg then
logger.error("CharInfoUtils->Can't get weapon item info, templateId: " .. weaponTemplateId)
return
end
local weaponInst = CharInfoUtils.getWeaponByInstId(weaponInstId)
local weaponExhibitInfo = {}
local gemItemCfg
local gemInst
if weaponInst.attachedGemInstId and weaponInst.attachedGemInstId > 0 then
gemInst = CharInfoUtils.getGemByInstId(weaponInst.attachedGemInstId)
local gemTemplateId = gemInst.templateId
gemItemCfg = Tables.itemTable:GetValue(gemTemplateId)
end
weaponExhibitInfo.weaponInst = weaponInst
weaponExhibitInfo.weaponCfg = weaponCfg
weaponExhibitInfo.itemCfg = weaponItemCfg
weaponExhibitInfo.gemItemCfg = gemItemCfg
weaponExhibitInfo.gemInst = gemInst
local expInfo = CharInfoUtils.getWeaponExpInfo(weaponInstId)
if not expInfo then
logger.error("CharInfoUtils->Can't get weapon exp info, weaponInstId: " .. weaponInstId)
return weaponExhibitInfo
end
weaponExhibitInfo.breakthroughGold = expInfo.breakthroughGold
weaponExhibitInfo.curBreakthroughLv = expInfo.curBreakthroughLv
weaponExhibitInfo.maxBreakthroughLv = expInfo.maxBreakthroughLv
weaponExhibitInfo.breakthroughTemplateCfg = expInfo.breakthroughTemplateCfg
weaponExhibitInfo.breakthroughInfoList = expInfo.breakthroughInfoList
weaponExhibitInfo.curLv = expInfo.curLv
weaponExhibitInfo.maxLv = expInfo.maxLv
weaponExhibitInfo.stageLv = expInfo.stageLv
weaponExhibitInfo.nextLvGold = expInfo.nextLvGold
weaponExhibitInfo.nextLvExp = expInfo.nextLvExp
weaponExhibitInfo.curExp = expInfo.curExp
return weaponExhibitInfo
end
function CharInfoUtils.getWeaponExpInfo(weaponInstId, targetBreakLv)
local expInfo = {}
local weaponInst = CharInfoUtils.getWeaponByInstId(weaponInstId)
local _, weaponCfg = Tables.weaponBasicTable:TryGetValue(weaponInst.templateId)
if not weaponCfg then
logger.error("CharInfoUtils->Can't get weapon basic info, templateId: " .. weaponInst.templateId)
return
end
local breakthroughTemplateId = weaponCfg.breakthroughTemplateId
local _, breakthroughTemplateCfg = Tables.weaponBreakThroughTemplateTable:TryGetValue(breakthroughTemplateId)
if not breakthroughTemplateCfg then
logger.error("CharInfoUtils->Can't get weapon breakthrough info, breakthroughTemplateId: " .. breakthroughTemplateId)
return
end
local weaponInst = CharInfoUtils.getWeaponByInstId(weaponInstId)
local levelUpTemplateId = weaponCfg.levelTemplateId
local hasLevelUpCfg, levelUpCfg = Tables.weaponUpgradeTemplateTable:TryGetValue(levelUpTemplateId)
if not hasLevelUpCfg then
logger.error("CharInfoUtils->Can't get weapon level up info, levelUpTemplateId: " .. levelUpTemplateId)
return
end
local nextLvExp = -1
local nextLvGold = -1
if levelUpCfg.list.Count >= CSIndex(weaponInst.weaponLv + 1) then
nextLvExp = levelUpCfg.list[CSIndex(weaponInst.weaponLv)].lvUpExp
nextLvGold = levelUpCfg.list[CSIndex(weaponInst.weaponLv)].lvUpGold
end
local maxLv = weaponCfg.maxLv
if targetBreakLv == nil then
targetBreakLv = weaponInst.breakthroughLv
end
local maxBreak, breakLv2StageLv = CharInfoUtils.getWeaponBreakLv2StageLv(weaponInst.templateId)
local stageLv = breakLv2StageLv[targetBreakLv]
expInfo.curBreakthroughLv = weaponInst.breakthroughLv
expInfo.maxBreakthroughLv = maxBreak
expInfo.breakthroughTemplateCfg = breakthroughTemplateCfg
expInfo.curLv = weaponInst.weaponLv
expInfo.maxLv = maxLv
expInfo.stageLv = stageLv
expInfo.nextLvGold = nextLvGold
expInfo.nextLvExp = nextLvExp
expInfo.curExp = weaponInst.exp
return expInfo
end
function CharInfoUtils.getWeaponBreakLv2StageLv(templateId)
local _, weaponCfg = Tables.weaponBasicTable:TryGetValue(templateId)
if not weaponCfg then
logger.error("CharInfoUtils->Can't get weapon basic info, templateId: " .. templateId)
return
end
local breakLv2StageLv = {}
local breakthroughTemplateId = weaponCfg.breakthroughTemplateId
local _, breakthroughTemplateCfg = Tables.weaponBreakThroughTemplateTable:TryGetValue(breakthroughTemplateId)
local maxLv = weaponCfg.maxLv
local maxStageLv = 1
local maxBreak = 0
for i = 1, breakthroughTemplateCfg.list.Count - 1 do
local breakCfg = breakthroughTemplateCfg.list[CSIndex(i)]
local nextBreakCfg = breakthroughTemplateCfg.list[CSIndex(i + 1)]
if maxLv > nextBreakCfg.breakthroughShowLv then
breakLv2StageLv[breakCfg.breakthroughShowLv] = nextBreakCfg.breakthroughLv
maxBreak = nextBreakCfg.breakthroughShowLv
maxStageLv = math.max(maxStageLv, nextBreakCfg.breakthroughShowLv)
end
end
if maxStageLv < maxLv then
breakLv2StageLv[maxBreak] = maxLv
end
return maxBreak, breakLv2StageLv
end
function CharInfoUtils.getWeaponShowAttributes(instanceId, level)
if level == nil then
local weaponInst = CharInfoUtils.getWeaponByInstId(instanceId)
level = weaponInst.weaponLv
end
local mainAttrDict, subAttrDict = CharInfoUtils.getWeaponShowAttributeDict(instanceId, level)
local mainAttrShowAttributes = AttributeUtils.generateAttributeShowInfoListByModifierGroup(mainAttrDict)
local subAttrShowAttributes = AttributeUtils.generateAttributeShowInfoListByModifierGroup(subAttrDict)
return mainAttrShowAttributes, subAttrShowAttributes
end
function CharInfoUtils.getWeaponShowAttributesByTemplateId(templateId, level)
local hasValue, mainAttributeTuple = CS.Beyond.Gameplay.WeaponUtil.TryGetWeaponAttrModifierData(templateId, level)
if hasValue then
local mainAttrShowAttributes = AttributeUtils.generateAttributeShowInfoListByModifierGroup(CharInfoUtils._generateWeaponAttrDict(mainAttributeTuple))
return mainAttrShowAttributes
end
end
function CharInfoUtils.getWeaponShowAttributesByTemplateIdWithBasicLevel(templateId)
return CharInfoUtils.getWeaponShowAttributesByTemplateId(templateId, 1)
end
function CharInfoUtils.getWeaponShowAttributesByTemplateIdWithMaxLevel(templateId)
local hasValue, basicData = Tables.weaponBasicTable:TryGetValue(templateId)
if hasValue then
return CharInfoUtils.getWeaponShowAttributesByTemplateId(templateId, basicData.maxLv)
end
end
function CharInfoUtils.getWeaponShowAttributeDict(instanceId, level)
local hasValue, attrTupleList = CS.Beyond.Gameplay.WeaponUtil.TryGetWeaponAttrModifierData(Utils.getCurrentScope(), instanceId, level)
if not hasValue then
logger.error("CharInfoUtils->Can't get weapon attributes, instanceId:" .. instanceId)
return
end
local mainAttrDict = {}
for i, attrTuple in pairs(attrTupleList) do
local attrShowInfo = CharInfoUtils._generateWeaponAttributeData(attrTuple)
mainAttrDict[attrShowInfo.attrType] = {
[attrShowInfo.modifierType] = attrShowInfo,
}
end
return mainAttrDict, {}
end
function CharInfoUtils._generateWeaponAttrDict(attrTupleList)
local attrDict = {}
for _, attrTuple in pairs(attrTupleList) do
local attrShowInfo = CharInfoUtils._generateWeaponAttributeData(attrTuple)
attrDict[attrShowInfo.attrType] = {
[attrShowInfo.modifierType] = attrShowInfo,
}
end
return attrDict
end
function CharInfoUtils._generateWeaponAttributeData(attrTuple)
local attrData = {}
local attrType, modifierType, attrValue = attrTuple.Item1, attrTuple.Item2, attrTuple.Item3
attrData.attrType = attrType
attrData.modifierType = modifierType
attrData.attrValue = attrValue
return attrData
end
function CharInfoUtils.getCharTalentInTable(templateId, breakStage)
local charData = CharInfoUtils.getCharTableData(templateId)
local talentDataBundle = charData.talentDataBundle
local talents = {}
for _, talentData in pairs(talentDataBundle) do
local talentBreakStage = talentData.breakStage
if talentBreakStage <= breakStage then
table.insert(talents, talentData)
end
end
return talents
end
function CharInfoUtils.getCharBreakStageTalents(templateId, breakStage, targetBreakStage, needCurrent)
local talents = CharInfoUtils.getCharActiveTalent(templateId, breakStage)
local targetTalents = CharInfoUtils.getCharTalentInTable(templateId, targetBreakStage)
local unlockTalents = {}
local enhancedTalents = {}
local tmpUnlockTalents = {}
local tmpEnhancedTalents = {}
for _, targetTalent in pairs(targetTalents) do
local tmpBreakStage = targetTalent.breakStage
local targetIndex = targetTalent.talentIndex
local tmpUnlockTalent = tmpUnlockTalents[targetIndex]
local tmpEnhancedTalent = tmpEnhancedTalents[targetIndex]
if not talents[targetIndex] ~= nil then
if not tmpUnlockTalent then
tmpUnlockTalents[targetIndex] = targetTalent
elseif tmpUnlockTalent.breakStage > tmpBreakStage then
tmpUnlockTalents[targetIndex] = targetTalent
end
elseif talents[targetIndex].breakStage < targetTalent.breakStage or needCurrent then
if not tmpEnhancedTalent then
tmpEnhancedTalents[targetIndex] = targetTalent
elseif tmpEnhancedTalent.breakStage == talents[targetIndex].breakStage then
tmpEnhancedTalents[targetIndex] = targetTalent
elseif targetTalent.breakStage ~= talents[targetIndex].breakStage and tmpEnhancedTalent.breakStage >
targetTalent.breakStage then
tmpEnhancedTalents[targetIndex] = targetTalent
end
end
end
for _, talent in pairs(tmpUnlockTalents) do
table.insert(unlockTalents, {
talentData = talent
})
end
for targetIndex, talent in pairs(tmpEnhancedTalents) do
table.insert(enhancedTalents, {
talentData = needCurrent and talents[targetIndex] or talent,
nextBreakStage = talent.breakStage,
})
end
local resTalents = {
unlockTalents = unlockTalents,
enhancedTalents = enhancedTalents,
}
return resTalents
end
function CharInfoUtils.getCharActiveTalent(templateId, breakStage)
local talents = {}
return talents
end
function CharInfoUtils.getTalentSkillData(talentData)
local skillDatas = {}
for _, talentEffect in pairs(talentData.talentEffects) do
if talentEffect.talentEffectType == GEnums.TalentEffectType.AddPassiveSkill then
local skillId = talentEffect.passiveSkillId
local level = talentEffect.passiveSkillLevel
local res, skillPatchData = DataManager:TryGetSkillPatchData(skillId, level)
if res then
table.insert(skillDatas, skillPatchData)
end
end
end
return skillDatas
end
function CharInfoUtils.getTalentMaxBreakStage(templateId, talentIndex)
local characterData = CharInfoUtils.getCharTableData(templateId)
local maxBreakStage = -1
local talentDataBundle = characterData.talentDataBundle
for luaIndex = 1, talentDataBundle.Count do
local talent = talentDataBundle[CSIndex(luaIndex)]
if talent.talentIndex == talentIndex then
maxBreakStage = math.max(maxBreakStage, talent.breakStage)
end
end
return maxBreakStage
end
function CharInfoUtils.checkIfSkillElite(skillId, skillLv)
end
function CharInfoUtils.getCharCurTalentNodes(charInstId)
local charInfo = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local templateId = charInfo.templateId
local potentialLevel = 0
local skillNodeList = CharInfoUtils._getCharSkillNodeList(templateId, potentialLevel)
local attributeNodeList = {}
local passiveNodeATable = {}
local passiveNodeBTable = {}
local breakNodeTable = {}
end
function CharInfoUtils._getCharSkillNodeList(templateId, potentialLevel)
local charGrowthData = CharInfoUtils.getCharGrowthData(templateId)
local skillId2LevelNode = {}
for _, skillLevelData in ipairs(charGrowthData.skillLevelUp) do
local skillId = skillLevelData.skillId
if not skillId2LevelNode[skillId] then
skillId2LevelNode[skillId] = {}
end
local skillLevelList = skillId2LevelNode[skillId]
table.insert(skillLevelList, skillLevelData)
end
return skillId2LevelNode
end
function CharInfoUtils.classifyMainSkillUpgradeNodes(instId, potentialLevel)
local mainSkills = {}
local showOrderList = {}
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(instId)
local charGrowthData = CharInfoUtils.getCharGrowthData(charInst.templateId)
local allSkillNode = charGrowthData.skillLevelUp
for i, skillNode in pairs(allSkillNode) do
local skillGroupId = skillNode.skillGroupId
local skillGroupCfg = CharInfoUtils.getSkillGroupCfg(charInst.templateId, skillGroupId)
if mainSkills[skillGroupId] == nil then
mainSkills[skillGroupId] = {}
for index, skillGroupType in ipairs(UIConst.CHAR_INFO_SKILL_SHOW_ORDER) do
if skillGroupCfg.skillGroupType == skillGroupType then
showOrderList[index] = skillGroupId
end
end
end
end
for i, skillUpgradeList in pairs(mainSkills) do
table.sort(skillUpgradeList, function(a, b)
return a.level < b.level
end)
end
return mainSkills, showOrderList
end
function CharInfoUtils.getCharSpaceshipSkillUpgradeList(templateId)
local shipSkills = {}
local charSpaceShipSkillList = Tables.spaceshipCharSkillTable[templateId].skillList
for _, charSkillCfg in pairs(charSpaceShipSkillList) do
local skillIndex = charSkillCfg.skillIndex
if shipSkills[skillIndex] == nil then
shipSkills[skillIndex] = {}
end
local skillCfg = Tables.spaceshipSkillTable[charSkillCfg.skillId]
table.insert(shipSkills[skillIndex], {
charSkillCfg = charSkillCfg,
skillCfg = skillCfg
})
end
for i, shipSkillList in pairs(shipSkills) do
table.sort(shipSkillList, function(a, b)
return a.skillCfg.level < b.skillCfg.level
end)
end
return shipSkills
end
function CharInfoUtils.classifyTalentNode(templateId, potentialLevel)
local attrNodeList = {}
local passiveSkillNodes = {}
local shipSkills = {}
local charGrowthData = CharInfoUtils.getCharGrowthData(templateId)
local allTalentNode = charGrowthData.talentNodeMap
for nodeId, nodeInfo in pairs(allTalentNode) do
local nodeType = nodeInfo.nodeType
if nodeType == GEnums.TalentNodeType.PassiveSkill then
local index = nodeInfo.passiveSkillNodeInfo.index
if passiveSkillNodes[index] == nil then
passiveSkillNodes[index] = {}
end
table.insert(passiveSkillNodes[index], nodeInfo)
elseif nodeType == GEnums.TalentNodeType.Attr then
table.insert(attrNodeList, nodeInfo)
elseif nodeType == GEnums.TalentNodeType.FactorySkill then
local shipSkillId = nodeInfo.nodeId
local skillIndex = nodeInfo.factorySkillNodeInfo.index
if shipSkills[skillIndex] == nil then
shipSkills[skillIndex] = {}
end
table.insert(shipSkills[skillIndex], nodeInfo)
end
end
table.sort(attrNodeList, function(a, b)
if a.attributeNodeInfo.breakStage ~= b.attributeNodeInfo.breakStage then
return a.attributeNodeInfo.breakStage < b.attributeNodeInfo.breakStage
else
local attrTypeA = a.attributeNodeInfo.attributeModifier.attrType
local attrTypeB = b.attributeNodeInfo.attributeModifier.attrType
return attrTypeA:ToInt() < attrTypeB:ToInt()
end
end)
for index, skillNodeList in pairs(passiveSkillNodes) do
table.sort(skillNodeList, function(a, b)
return a.passiveSkillNodeInfo.breakStage < b.passiveSkillNodeInfo.breakStage
end)
end
for i, shipSkillNodeList in pairs(shipSkills) do
table.sort(shipSkillNodeList, function(a, b)
return a.factorySkillNodeInfo.breakStage < b.factorySkillNodeInfo.breakStage
end)
end
local passiveSkillNodeList = {}
for index, nodeList in pairs(passiveSkillNodes) do
local nodeIndex = nodeList[1].passiveSkillNodeInfo.index
passiveSkillNodeList[nodeIndex] = nodeList
end
local facSkillNodeList = {}
for skillIndex, nodeList in pairs(shipSkills) do
table.insert(facSkillNodeList, {
skillIndex = skillIndex,
nodeList = nodeList,
})
end
return attrNodeList, passiveSkillNodeList, facSkillNodeList
end
function CharInfoUtils.getSkillType(templateId, skillId)
local res, skillTable = Tables.skillLockTable:TryGetValue(templateId)
if res then
local bundleData = skillTable.BundleData
for _, skillData in pairs(bundleData) do
if skillData.skillId == skillId then
return skillData.skillType
end
end
end
return nil
end
function CharInfoUtils.getPlayerCharSkillByTypeUnlock(charInstId, templateId, skillType, level, teamIndex)
return CharInfoUtils.getPlayerCharSkillByType(charInstId, templateId, skillType, level, true, teamIndex)
end
function CharInfoUtils.getSkillDataById(skillId, level)
local get, skillPatchData = DataManager:TryGetSkillPatchData(skillId, level)
if not get then
skillPatchData = nil
end
local skillData = {
patchData = skillPatchData,
level = level,
}
return skillData
end
function CharInfoUtils.getPlayerCharSkillByType(charInstId, templateId, skillGroupType, level, onlyUnlock)
local charInfo
if charInstId ~= nil and not templateId then
charInfo = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
templateId = charInfo.templateId
end
local charGrowthData = CharInfoUtils.getCharGrowthData(templateId)
local skillGroupData
if charGrowthData then
for _, data in pairs(charGrowthData.skillGroupMap) do
if data.skillGroupType == skillGroupType then
skillGroupData = data
end
end
end
local skills = {}
local skillLevelUpData = CharInfoUtils.getCharSkillLevelData(templateId)
if charGrowthData and skillGroupData then
local maxLevel
local inUse = true
local skillId = skillGroupData.skillId
local skillGroupId = skillGroupData.skillGroupId
local res, skillInfo = CS.Beyond.Gameplay.SkillUtil.TryGetCharSkillGroupInfo(charInstId, skillGroupId)
local unlock = true
if res then
if not level then
level = skillInfo.level
end
maxLevel = skillInfo.maxLevel
else
if not level then
level = 1
end
maxLevel = level
end
local realMaxLevel = skillLevelUpData[skillGroupId] and skillLevelUpData[skillGroupId].realMaxLevel or maxLevel
local find, skillData = Tables.skillPatchTable:TryGetValue(skillId)
if find and skillData then
local _, skillPatchData = DataManager:TryGetSkillPatchData(skillId, level)
local btnSkillInfo = {
skillId = skillId,
patchData = skillPatchData,
bundleData = skillGroupData,
level = level,
maxLevel = maxLevel,
inUse = inUse,
unlock = unlock,
realMaxLevel = realMaxLevel,
breakStage = 0,
}
if not onlyUnlock or (onlyUnlock and unlock) then
table.insert(skills, btnSkillInfo)
end
end
end
table.sort(skills, Utils.genSortFunction({ "breakStage" }, true))
return skills
end
function CharInfoUtils.getPlayerCharCurSkills(charInstId)
local skills = {}
for skillType, btnIndex in pairs(UIConst.SKILL_TYPE_2_BTN_INDEX) do
local skillList = CharInfoUtils.getPlayerCharSkillByType(charInstId, nil, skillType, nil, nil)
skills[btnIndex] = skillList
end
return skills
end
function CharInfoUtils.getCharInfoSkillGroupBgColor(skillGroupCfg, isBattle)
local firstSkillId = skillGroupCfg.skillIdList[0]
local firstSkillCfg = CharInfoUtils.getSkillCfg(firstSkillId, 1)
local iconBgType = firstSkillCfg.iconBgType
if iconBgType == CS.Beyond.GEnums.DamageType.Fire then
return Color(1, 0.384, 0.239)
elseif iconBgType == CS.Beyond.GEnums.DamageType.Pulse then
return Color(1, 0.753, 0)
elseif iconBgType == CS.Beyond.GEnums.DamageType.Cryst then
return Color(0.129, 0.776, 0.816)
elseif iconBgType == CS.Beyond.GEnums.DamageType.Natural then
return Color(0.671, 0.749, 0)
else
return isBattle and Color(0.647, 0.647, 0.647) or Color(0.373, 0.373, 0.373)
end
end
function CharInfoUtils.getCharSkillGroupCfgByType(templateId, skillGroupType)
local charGrowthData = CharInfoUtils.getCharGrowthData(templateId)
if not charGrowthData then
return nil
end
for _, data in pairs(charGrowthData.skillGroupMap) do
if data.skillGroupType == skillGroupType and #data.skillIdList > 0 then
return data
end
end
return nil
end
function CharInfoUtils.getCharFirstSkillIdByType(templateId, skillGroupType)
local charGrowthData = CharInfoUtils.getCharGrowthData(templateId)
if not charGrowthData then
return nil
end
for _, data in pairs(charGrowthData.skillGroupMap) do
if data.skillGroupType == skillGroupType and #data.skillIdList > 0 then
return data.skillIdList[0]
end
end
return nil
end
function CharInfoUtils.getCharSkillLevelData(templateId)
local data = {}
local charData = CharInfoUtils.getCharTableData(templateId)
local skillLevelUp = charData.skillLevelUp
for _, skillLevelData in pairs(skillLevelUp) do
local skillGroupId = skillLevelData.skillGroupId
local level = skillLevelData.level
if not data[skillGroupId] then
data[skillGroupId] = {
realMaxLevel = 1,
}
end
data[skillGroupId][level] = skillLevelData
data[skillGroupId].realMaxLevel = math.max(data[skillGroupId].realMaxLevel, level)
end
return data
end
function CharInfoUtils.getSkillTypeName(skillType)
local skillTypeText
if skillType == Const.SkillTypeEnum.NormalSkill then
skillTypeText = Language.LUA_NORMAL_SKILL
elseif skillType == Const.SkillTypeEnum.UltimateSkill then
skillTypeText = Language.LUA_ULTIMATE_SKILL
else
skillTypeText = Language.LUA_NORMAL_ATTACK
end
return skillTypeText
end
function CharInfoUtils.getBreakStageUnlockSkills(templateId, breakStage)
local charTable = CharInfoUtils.getCharTableData(templateId)
local skills = {}
local res, breakStageEffectData = charTable.breakStageEffect:TryGetValue(breakStage)
if res then
skills = breakStageEffectData.skillUnlock
end
return skills
end
function CharInfoUtils.getCharSkillUpgradeNextBreakStage(templateId, breakStage, skillType)
local targetBreakStage
local charTable = CharInfoUtils.getCharTableData(templateId)
local maxBreakStage = Tables.characterConst.maxBreak
if maxBreakStage == breakStage then
return targetBreakStage
end
for i = breakStage + 1, maxBreakStage do
local res, breakStageEffectData = charTable.breakStageEffect:TryGetValue(i)
if res then
for _, data in pairs(breakStageEffectData.skillEffect) do
if data.skillType == skillType then
targetBreakStage = i
break
end
end
end
if targetBreakStage then
break
end
end
return targetBreakStage
end
function CharInfoUtils.getCharSkillLevelInfo(charInfo, skillGroupId)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInfo.instId)
local skillGroupList = charInst.skillGroupLevelInfoList
for _, skillGroupInfo in pairs(skillGroupList) do
if skillGroupInfo.skillGroupId == skillGroupId then
return skillGroupInfo
end
end
logger.error(string.format("角色养成->角色templateId[%s]缺少技能组[%s]", charInst.templateId, skillGroupId))
return nil
end
function CharInfoUtils.getCharSkillLevelByType(templateId, skillGroupType)
local skillInfo = CharInfoUtils.getCharSkillLevelInfoByType(templateId, skillGroupType)
if skillInfo == nil then
return 1
end
return skillInfo.level
end
function CharInfoUtils.getCharSkillLevelInfoByType(charInfo, skillGroupType)
local templateId = charInfo.templateId
local charGrowthData = CharInfoUtils.getCharGrowthData(templateId)
if not charGrowthData then
return nil
end
local skillGroupId
for _, data in pairs(charGrowthData.skillGroupMap) do
if data.skillGroupType == skillGroupType then
skillGroupId = data.skillGroupId
break
end
end
if skillGroupId == nil then
return nil
end
local skillLevelInfo = CharInfoUtils.getCharSkillLevelInfo(charInfo, skillGroupId)
if skillLevelInfo == nil then
return nil
end
return skillLevelInfo
end
function CharInfoUtils.getSkillCfg(skillId, skillLv)
local get, talentSkillCfg = Tables.SkillPatchTable:TryGetValue(skillId)
if not get then
logger.error("CharInfoTalentCtrl->_RefreshPassiveSkillCell: skillId not found in SkillPatchTable, skillId = " .. tostring(skillId))
return
end
local exactSkillCfg
for i, skillCfg in pairs(talentSkillCfg.SkillPatchDataBundle) do
if skillCfg.level == skillLv then
exactSkillCfg = skillCfg
break
end
end
return exactSkillCfg
end
function CharInfoUtils.getShipSkillCfg(skillId)
local get, skillCfg = Tables.spaceshipSkillTable:TryGetValue(skillId)
if not get then
logger.error("CharInfoTalentCtrl->_RefreshPassiveSkillCell: skillId not found in spaceshipSkillTable, skillId = " .. tostring(skillId))
return
end
return skillCfg
end
function CharInfoUtils.getSkillGroupCfg(charId, skillGroupId)
local charGrowthData = CharInfoUtils.getCharGrowthData(charId)
local get, skillGroupData = charGrowthData.skillGroupMap:TryGetValue(skillGroupId)
return skillGroupData
end
function CharInfoUtils.getTalentNodeCfg(charTemplateId, nodeId)
local charGrowthCfg = CharInfoUtils.getCharGrowthData(charTemplateId)
local success, nodeCfg = charGrowthCfg.talentNodeMap:TryGetValue(nodeId)
if success then
return nodeCfg
end
end
function CharInfoUtils.getCharSpaceshipSkillIndex(templateId, skillId)
local charSpaceShipSkillList = Tables.spaceshipCharSkillTable[templateId].skillList
for _, skillCfg in pairs(charSpaceShipSkillList) do
if skillCfg.skillId == skillId then
return skillCfg.skillIndex
end
end
end
function CharInfoUtils.getSkillTalentNodeBySkillId(charTemplateId, skillGroupId, skillLv)
local charGrowthCfg = CharInfoUtils.getCharGrowthData(charTemplateId)
local skillUpgradeList = charGrowthCfg.skillLevelUp
for _, skillUpgradeCfg in pairs(skillUpgradeList) do
if skillUpgradeCfg.skillGroupId == skillGroupId and skillUpgradeCfg.level == skillLv then
return skillUpgradeCfg
end
end
end
function CharInfoUtils.getPassiveSkillTalentNodeByIndex(charTemplateId, nodeIndex, nodeLevel)
local foundNodeList = CharInfoUtils.getAllPassiveSkillTalentNodeByIndex(charTemplateId, nodeIndex)
if nodeLevel then
for i, talentNode in pairs(foundNodeList) do
if talentNode.passiveSkillNodeInfo.level == nodeLevel then
return talentNode
end
end
end
end
function CharInfoUtils.getShipSkillIdByTalentNodeId(charTemplateId, nodeId)
local charGrowthCfg = CharInfoUtils.getCharGrowthData(charTemplateId)
local talentNodeMap = charGrowthCfg.talentNodeMap
local talentNode = talentNodeMap[nodeId]
if talentNode.nodeType ~= GEnums.TalentNodeType.FactorySkill then
return
end
local index = talentNode.factorySkillNodeInfo.index
local level = talentNode.factorySkillNodeInfo.level
local shipSkillList = Tables.spaceshipCharSkillTable[charTemplateId].skillList
for _, shipSkill in pairs(shipSkillList) do
if shipSkill.skillIndex == index then
local shipSkillCfg = Tables.spaceshipSkillTable[shipSkill.skillId]
if shipSkillCfg.level == level then
return shipSkill.skillId
end
end
end
end
function CharInfoUtils.getAllPassiveSkillTalentNodeByIndex(charTemplateId, nodeIndex)
local charGrowthCfg = CharInfoUtils.getCharGrowthData(charTemplateId)
local talentNodeMap = charGrowthCfg.talentNodeMap
local foundNodeList = {}
for _, talentNode in pairs(talentNodeMap) do
local passiveSkillNodeInfo = talentNode.passiveSkillNodeInfo
if talentNode.nodeType == GEnums.TalentNodeType.PassiveSkill and passiveSkillNodeInfo.index == nodeIndex then
table.insert(foundNodeList, talentNode)
end
end
table.sort(foundNodeList, function(a, b)
return a.passiveSkillNodeInfo.breakStage < b.passiveSkillNodeInfo.breakStage
end)
return foundNodeList
end
function CharInfoUtils.getShipSkillTalentNodeBySkillId(charTemplateId, skillId)
local shipSkillCfg = Tables.spaceshipSkillTable[skillId]
local skillLevel = shipSkillCfg.level
local charShipSkillList = Tables.spaceshipCharSkillTable[charTemplateId].skillList
for _, shipSkill in pairs(charShipSkillList) do
if shipSkill.skillId == skillId then
local skillIndex = shipSkill.skillIndex
local charGrowthCfg = CharInfoUtils.getCharGrowthData(charTemplateId)
local talentNodeMap = charGrowthCfg.talentNodeMap
for _, talentNode in pairs(talentNodeMap) do
if talentNode.nodeType == GEnums.TalentNodeType.FactorySkill
and talentNode.factorySkillNodeInfo.index == skillIndex
and talentNode.factorySkillNodeInfo.level == skillLevel then
return talentNode
end
end
end
end
end
function CharInfoUtils.getAttributeNodeStatus(charInstId, attrNodeId)
local lockText
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local attrNodeCfg = CharInfoUtils.getTalentNodeCfg(charInst.templateId, attrNodeId)
local friendshipValue = CSPlayerDataUtil.GetCharFriendshipByInstId(charInst.instId)
local isBelowFriendshipValue = friendshipValue < attrNodeCfg.attributeNodeInfo.favorability
local isBelowBreakStage = attrNodeCfg.attributeNodeInfo.breakStage > charInst.breakStage
if isBelowFriendshipValue then
lockText = Language.LUA_CHAR_INFO_TALENT_BELOW_FRIENDSHIP_TOAST
end
if isBelowBreakStage then
lockText = string.format(Language.LUA_CHAR_INFO_TALENT_UPGRADE_BREAK_LOCK_HINT, attrNodeCfg.attributeNodeInfo.breakStage)
end
local isLock = isBelowBreakStage or (friendshipValue < attrNodeCfg.attributeNodeInfo.favorability)
local isActive = charInst.talentInfo.attributeNodes:Contains(attrNodeId)
return isActive, isLock, lockText
end
function CharInfoUtils.getCharBreakNodeFromStageAndEquipTier(breakStage, equipTierLimit)
for nodeId, nodeCfg in pairs(Tables.charBreakNodeTable) do
if nodeCfg.breakStage == breakStage and nodeCfg.equipTierLimit == equipTierLimit then
return nodeId
end
end
end
function CharInfoUtils.getExactSkillIdInSkillGroup(skillGroupData, skillLv)
for _, skillData in pairs(skillGroupData.skillIdList) do
if skillData.level == skillLv then
return skillData.skillId
end
end
end
function CharInfoUtils.getCharBreakNodeStatus(charInstId, nodeId)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local charBreakCostMap = CharInfoUtils.getCharGrowthData(charInst.templateId).charBreakCostMap
local breakCfg = charBreakCostMap[nodeId]
local isLockByLv = false
local isLockByEquipTier = breakCfg.equipTierLimit > charInst.equipTierLimit
local isLockByBreakStage = breakCfg.breakStage - 1 > charInst.breakStage
if charInst.breakStage == breakCfg.breakStage - 1 and (not isLockByEquipTier) then
local breakStageCfg = Tables.charBreakStageTable[breakCfg.breakStage - 1]
isLockByLv = breakStageCfg.maxCharLevel > charInst.level
end
local isLock = isLockByEquipTier or isLockByBreakStage or isLockByLv
local isActive = charInst.breakStage >= breakCfg.breakStage
return isActive, isLock, {
isLockByLv = isLockByLv,
}
end
function CharInfoUtils.getEquipBreakNodeStatus(charInstId, nodeId)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local charBreakCostMap = CharInfoUtils.getCharGrowthData(charInst.templateId).charBreakCostMap
local breakCfg = charBreakCostMap[nodeId]
local isActive = false
if breakCfg.breakStage < charInst.breakStage then
isActive = true
elseif breakCfg.breakStage == charInst.breakStage then
isActive = breakCfg.nodeId == charInst.talentInfo.latestBreakNode
end
local isLock = breakCfg.breakStage > charInst.breakStage
return isActive, isLock, {
}
end
function CharInfoUtils.getPassiveSkillNodeStatus(charInstId, nodeId)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local nodeCfg = CharInfoUtils.getTalentNodeCfg(charInst.templateId, nodeId)
local passiveSkillNodeInfo = nodeCfg.passiveSkillNodeInfo
local isActive, isLock, lockText = CharInfoUtils._innerGetPassiveSkillNodeStatus(charInstId, nodeId)
if isActive or isLock then
return isActive, isLock, lockText
end
local foundNodeList = CharInfoUtils.getAllPassiveSkillTalentNodeByIndex(charInst.templateId, passiveSkillNodeInfo.index)
table.sort(foundNodeList, function(a,b)
return a.passiveSkillNodeInfo.level < b.passiveSkillNodeInfo.level
end)
for i = passiveSkillNodeInfo.level + 1, #foundNodeList do
local nextNodeCfg = foundNodeList[i]
if nextNodeCfg then
local nextActive = CharInfoUtils._innerGetPassiveSkillNodeStatus(charInstId, nextNodeCfg.nodeId)
if nextActive then
return true, false
end
end
end
if passiveSkillNodeInfo.level > 1 then
local previousNodeCfg = foundNodeList[passiveSkillNodeInfo.level - 1]
if previousNodeCfg then
local lastActive, lastLock = CharInfoUtils._innerGetPassiveSkillNodeStatus(charInstId, previousNodeCfg.nodeId)
if not lastActive then
return false, true, Language.LUA_CHAR_INFO_TALENT_PREVIOUS_SKILL_INACTIVE
end
end
end
return false, false
end
function CharInfoUtils._innerGetPassiveSkillNodeStatus(charInstId, nodeId)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local nodeCfg = CharInfoUtils.getTalentNodeCfg(charInst.templateId, nodeId)
local passiveSkillNodeInfo = nodeCfg.passiveSkillNodeInfo
local isActive = charInst.talentInfo.latestPassiveSkillNodes:Contains(nodeId)
if isActive then
return true, false
end
local isLock = passiveSkillNodeInfo.breakStage > charInst.breakStage
if isLock then
local lockText = string.format(Language.LUA_CHAR_INFO_TALENT_UPGRADE_BREAK_LOCK_HINT, passiveSkillNodeInfo.breakStage)
return false, true, lockText
end
return false, false
end
function CharInfoUtils.getShipSkillTalentNodeByIndex(charTemplateId, index, level)
local charGrowthCfg = CharInfoUtils.getCharGrowthData(charTemplateId)
local talentNodeMap = charGrowthCfg.talentNodeMap
for nodeId, nodeCfg in pairs(talentNodeMap) do
if nodeCfg.nodeType == GEnums.TalentNodeType.FactorySkill then
local factorySkillNodeInfo = nodeCfg.factorySkillNodeInfo
if factorySkillNodeInfo.index == index and factorySkillNodeInfo.level == level then
return nodeCfg
end
end
end
end
function CharInfoUtils.getShipSkillNodeStatus(charInstId, nodeId)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local nodeCfg = CharInfoUtils.getTalentNodeCfg(charInst.templateId, nodeId)
local factorySkillNodeInfo = nodeCfg.factorySkillNodeInfo
local isActive, isLock, lockText = CharInfoUtils._innerGetFacSkillNodeStatus(charInstId, nodeId)
if isActive or isLock then
return isActive, isLock, lockText
end
local foundNodeList = CharInfoUtils.getAllFactorySkillTalentNodeByIndex(charInst.templateId, factorySkillNodeInfo.index)
table.sort(foundNodeList, function(a,b)
return a.factorySkillNodeInfo.level < b.factorySkillNodeInfo.level
end)
local nextNodeCfg = foundNodeList[factorySkillNodeInfo.level + 1]
if nextNodeCfg then
local nextActive = CharInfoUtils._innerGetFacSkillNodeStatus(charInstId, nextNodeCfg.nodeId)
if nextActive then
return true, false
end
end
if factorySkillNodeInfo.level > 1 then
local previousNodeCfg = foundNodeList[factorySkillNodeInfo.level - 1]
if previousNodeCfg then
local lastActive, lastLock = CharInfoUtils._innerGetFacSkillNodeStatus(charInstId, previousNodeCfg.nodeId)
if not lastActive then
return false, true, Language.LUA_CHAR_INFO_TALENT_PREVIOUS_SKILL_INACTIVE
end
end
end
return false, false
end
function CharInfoUtils.getAllFactorySkillTalentNodeByIndex(templateId, index)
local foundNodeList = {}
local charGrowthCfg = CharInfoUtils.getCharGrowthData(templateId)
local talentNodeMap = charGrowthCfg.talentNodeMap
for i, nodeCfg in pairs(talentNodeMap) do
if nodeCfg.nodeType == GEnums.TalentNodeType.FactorySkill then
local factorySkillNodeInfo = nodeCfg.factorySkillNodeInfo
if factorySkillNodeInfo.index == index then
table.insert(foundNodeList, nodeCfg)
end
end
end
return foundNodeList
end
function CharInfoUtils._innerGetFacSkillNodeStatus(charInstId, nodeId)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInstId)
local nodeCfg = CharInfoUtils.getTalentNodeCfg(charInst.templateId, nodeId)
local factorySkillNodeInfo = nodeCfg.factorySkillNodeInfo
local isActive = charInst.talentInfo.latestFactorySkillNodes:Contains(nodeId)
if isActive then
return true, false
end
local isLock = factorySkillNodeInfo.breakStage > charInst.breakStage
if isLock then
local lockText = string.format(Language.LUA_CHAR_INFO_TALENT_UPGRADE_BREAK_LOCK_HINT, factorySkillNodeInfo.breakStage)
return false, true, lockText
end
return false, false
end
function CharInfoUtils.getSkillCanUpgradeLv(skillGroupType, breakStage)
local stageCfg = Tables.charBreakStageTable[breakStage]
local canUpgradeLv = 0
if skillGroupType == GEnums.SkillGroupType.NormalAttack then
canUpgradeLv = stageCfg.normalAttackSkillLevel
elseif skillGroupType == GEnums.SkillGroupType.NormalSkill then
canUpgradeLv = stageCfg.normalSkillLevel
elseif skillGroupType == GEnums.SkillGroupType.UltimateSkill then
canUpgradeLv = stageCfg.ultimateSkillLevel
elseif skillGroupType == GEnums.SkillGroupType.ComboSkill then
canUpgradeLv = stageCfg.comboSkillLevel
else
logger.error("CharInfoTalentCtrl->getSkillCanUpgradeLv: skillType can't upgrade !!!!, skillType = " .. tostring(skillGroupType))
end
return canUpgradeLv
end
function CharInfoUtils.getSkillDesc(skillId, skillLv)
local skillDesc = Utils.SkillUtil.GetSkillDescription(skillId, skillLv)
return skillDesc
end
function CharInfoUtils.getGroupSkillExtraInfoList(skillGroupId, skillLv)
end
function CharInfoUtils.getSkillExtraInfoList(skillId, skillLv)
local skillExtraInfoList = {}
local _, skillPatchData = DataManager:TryGetSkillPatchData(skillId, skillLv)
local cooldownTime = skillPatchData.coolDown
local costType = skillPatchData.costType
local costValue = skillPatchData.costValue
local hasUspCost = false
if costType == GEnums.CostType.Atb then
if costValue > 0 and math.abs(costValue) > 0.01 then
local roundedValue = lume.round(costValue)
table.insert(skillExtraInfoList, {
name = Language.LUA_CHAR_INFO_SKILL_COST_ATB,
value = roundedValue,
})
end
end
if costType == GEnums.CostType.UltimateSp then
if costValue > 0 and math.abs(costValue) > 0.01 then
local roundedValue = lume.round(costValue)
table.insert(skillExtraInfoList, {
name = Language.LUA_CHAR_INFO_SKILL_COST_SP,
value = roundedValue,
})
hasUspCost = true
end
end
if cooldownTime and cooldownTime > 0 and math.abs(cooldownTime) > 0.01 then
local roundedValue = lume.round(cooldownTime * 10) / 10
if (roundedValue * 10) % 10 == 0 then
roundedValue = math.floor(roundedValue)
end
table.insert(skillExtraInfoList, {
name = Language.LUA_CHAR_INFO_SKILL_DURATION,
value = string.format(Language.LUA_CHAR_INFO_SKILL_DURATION_FORMAT, roundedValue),
})
end
return skillExtraInfoList
end
function CharInfoUtils.isCharBreakCostEnough(templateId, nodeId)
local charGrowthData = CharInfoUtils.getCharGrowthData(templateId)
if not charGrowthData then
return false
end
local _, charBreakDetailData = charGrowthData.charBreakCostMap:TryGetValue(nodeId)
if not charBreakDetailData then
return false
end
for _, itemBundle in pairs(charBreakDetailData.requiredItem) do
if Utils.getItemCount(itemBundle.id, true) < itemBundle.count then
return false
end
end
return true
end
function CharInfoUtils.isCharTalentCostEnough(templateId, nodeId)
local charGrowthData = CharInfoUtils.getCharGrowthData(templateId)
if not charGrowthData then
return false
end
local _, talentNode = charGrowthData.talentNodeMap:TryGetValue(nodeId)
if not talentNode then
return false
end
for _, itemBundle in pairs(talentNode.requiredItem) do
if Utils.getItemCount(itemBundle.id, true) < itemBundle.count then
return false
end
end
return true
end
function CharInfoUtils.isSkillGroupLevelUpCostEnough(templateId, skillGroupId, skillLv)
local skillLevelUpData = CharInfoUtils.getSkillTalentNodeBySkillId(templateId, skillGroupId, skillLv)
if not skillLevelUpData then
return false
end
if skillLevelUpData.goldCost > 0 then
if Utils.getItemCount(UIConst.INVENTORY_MONEY_IDS[1], true) < skillLevelUpData.goldCost then
return false
end
end
for _, itemBundle in pairs(skillLevelUpData.itemBundle) do
if Utils.getItemCount(itemBundle.id, true) < itemBundle.count then
return false
end
end
return true
end
function CharInfoUtils.getCharInfoProfile(templateId)
local profile = {}
local charData = Tables.characterTable[templateId]
if charData then
profile = {
profileVoice = charData.profileVoice,
profileRecord = charData.profileRecord,
}
end
return profile
end
function CharInfoUtils.IsFullLockedTeam()
local formationData
if FocusModeUtils.isInFocusMode then
local curFocusModeInstId = GameInstance.mode.instId
if string.isEmpty(curFocusModeInstId) then
return false
end
local _, focusModeData = GameInstance.dataManager.focusModeInstDataTable:TryGetValue(curFocusModeInstId)
if not focusModeData then
return false
end
local formulaData = CharInfoUtils.getLockedFormationData(focusModeData.presetTeamId, false)
if not formulaData then
return false
end
return true, formulaData
end
local curDungeonId = GameInstance.dungeonManager.curDungeonId
local _, subGameData = DataManager.subGameInstDataTable:TryGetValue(curDungeonId)
if subGameData and not string.isEmpty(subGameData.teamConfigId) then
formationData = CharInfoUtils.getLockedFormationData(subGameData.teamConfigId, false)
if formationData and formationData.lockedTeamMemberCount == formationData.maxTeamMemberCount and
not formationData.hasReplaceable then
return true, formationData
end
end
return false, formationData
end
function CharInfoUtils.IsFocusModeFullLockedTeam(focusModeInstId)
local curFocusModeInstId = focusModeInstId
if not curFocusModeInstId and FocusModeUtils.isInFocusMode then
curFocusModeInstId = GameInstance.mode.instId
end
if string.isEmpty(curFocusModeInstId) then
return false
end
local _, focusModeData = GameInstance.dataManager.focusModeInstDataTable:TryGetValue(curFocusModeInstId)
if not focusModeData then
return false
end
local formulaData = CharInfoUtils.getLockedFormationData(focusModeData.presetTeamId, false)
if not formulaData then
return false
end
return true, formulaData
end
function CharInfoUtils.getLockedFormationData(teamConfigId, createClientCharInfo)
if string.isEmpty(teamConfigId) then
return nil
end
local hasValue
local charTeamData
hasValue, charTeamData = Tables.charTeamTable:TryGetValue(teamConfigId)
if not hasValue then
return nil
end
local shouldShowTrailTips = #charTeamData.presetCharList > 0
if createClientCharInfo then
for _, charPresetId in pairs(charTeamData.presetCharList) do
GameInstance.player.charBag:CreateClientCharInfo(charPresetId, ScopeUtil.GetCurrentScope())
end
end
local lockedTeamData = {}
lockedTeamData.teamConfigId = teamConfigId
lockedTeamData.maxTeamMemberCount = charTeamData.maxMemberCount
local chars = {}
for _, charPresetId in pairs(charTeamData.presetTeam) do
local charPresetData
hasValue, charPresetData = Tables.charPresetTable:TryGetValue(charPresetId)
if hasValue then
local charInfo = {
charId = CharUtils.GetCharTemplateId(charPresetData.charId),
charPresetId = charPresetId,
isLocked = true,
isTrail = true,
isReplaceable = false,
}
if createClientCharInfo then
local csCharInfo = CharInfoUtils.getPlayerCharInfoByPresetId(charPresetId)
charInfo.charInstId = csCharInfo.instId
charInfo.charId = csCharInfo.templateId
end
table.insert(chars, charInfo)
end
shouldShowTrailTips = false
end
local hasReplaceable = false
for _, charId in pairs(charTeamData.requireCharTids) do
charId = CharUtils.GetCharTemplateId(charId)
local found = false
for _, charInfo in ipairs(chars) do
if charInfo.charId == charId then
charInfo.isReplaceable = true
found = true
hasReplaceable = true
break
end
end
if not found then
if createClientCharInfo then
local foundCharInfo
local trailCharInfos = GameInstance.player.charBag.clientCharInfos
for _, trailCharInfo in cs_pairs(trailCharInfos) do
if trailCharInfo.templateId == charId then
foundCharInfo = trailCharInfo
break
end
end
if not foundCharInfo then
foundCharInfo = CharInfoUtils.getPlayerCharInfoByTemplateId(charId, GEnums.CharType.Default)
end
local charInfo = {
charId = charId,
charInstId = foundCharInfo.instId,
isLocked = true,
isTrail = foundCharInfo.charType == GEnums.CharType.Trial,
isReplaceable = true,
}
table.insert(chars, charInfo)
else
local isTrail = false
local presetId
for _, charPresetId in pairs(charTeamData.presetCharList) do
local charPresetData
hasValue, charPresetData = Tables.charPresetTable:TryGetValue(charPresetId)
if hasValue and CharUtils.GetCharTemplateId(charPresetData.charId) == charId then
isTrail = true
presetId = charPresetId
break
end
end
local charInfo = {
charId = charId,
charPresetId = presetId,
isLocked = true,
isTrail = isTrail,
isReplaceable = true,
}
table.insert(chars, charInfo)
end
hasReplaceable = true
end
shouldShowTrailTips = false
end
lockedTeamData.chars = chars
lockedTeamData.lockedTeamMemberCount = #chars
lockedTeamData.hasReplaceable = hasReplaceable
lockedTeamData.shouldShowTrailTips = shouldShowTrailTips
return lockedTeamData
end
function CharInfoUtils.getLockedFormationCharTipsShow(charInfo)
local isShowFixed = charInfo.isLocked == true and not charInfo.isReplaceable
local isShowTrail = charInfo.isTrail and not isShowFixed
return isShowFixed, isShowTrail
end
function CharInfoUtils.getHpBase(charInfo)
return CharInfoUtils.getAttrBaseDefault(charInfo.instId, GEnums.AttributeType.MaxHp)
end
function CharInfoUtils.getAtkBase(charInfo)
return CharInfoUtils.getAttrBaseDefault(charInfo.instId, GEnums.AttributeType.Atk)
end
function CharInfoUtils.getAtkTotalBase(charInfo)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInfo.instId)
local atkValue = charInst.attributes:GetValue(GEnums.AttributeType.Atk)
local _, atkScalar = CharInfoUtils.getAtkScalar(charInfo)
local attrValue = atkValue / (1 + atkScalar)
local attrShowInfo = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, attrValue, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
})
return attrShowInfo.showValue, attrShowInfo.attributeValue
end
function CharInfoUtils.getAtkScalar(charInfo)
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInfo.instId)
local attributes = charInst.attributes
local strScalar = attributes:GetAtkFinalScalarFromStr()
local agiScalar = attributes:GetAtkFinalScalarFromAgi()
local wisdScalar = attributes:GetAtkFinalScalarFromWisd()
local willScalar = attributes:GetAtkFinalScalarFromWill()
local mainAttrScalarShowInfo = AttributeUtils.generateAttributeShowInfo(
GEnums.AttributeType.Atk,
strScalar + agiScalar + wisdScalar + willScalar,
{
forceShowPercent = UIConst.ATTRIBUTE_GENERATE_FORCE_PERCENT.HAS_PERCENT,
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR,
}
)
return "+" .. mainAttrScalarShowInfo.showValue, mainAttrScalarShowInfo.attributeValue
end
function CharInfoUtils.getDefBase(charInfo)
return CharInfoUtils.getAttrBaseDefault(charInfo.instId, GEnums.AttributeType.Def)
end
function CharInfoUtils.getAttrBaseDefault(charInstId, attrType)
local attrShowInfo = AttributeUtils.generateAttributeShowInfo(attrType, CharInfoUtils.getCharBaseAttributes(charInstId)[attrType], {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
})
return attrShowInfo.showValue, attrShowInfo.attributeValue
end
function CharInfoUtils.getHpDetailList(charInfo, finalValue)
local detailList = {}
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInfo.instId)
local attributes = charInst.attributes
local rawHp = attributes:GetRawValue(GEnums.AttributeType.MaxHp)
local rawHpShowValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.MaxHp, rawHp, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue
table.insert(detailList, {
showName = Language.LUA_CHAR_INFO_FULL_ATTRIBUTE_HP_RAW,
showValue = rawHpShowValue,
})
local hpByStr = attributes:GetHpBaseAddFromStrAttribute()
local hpByStrShowValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.MaxHp, hpByStr, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue
table.insert(detailList, {
showName = Language.LUA_CHAR_INFO_FULL_ATTRIBUTE_HP_BY_STR,
showValue = hpByStrShowValue,
})
local baseHp = attributes:GetBaseValue(GEnums.AttributeType.MaxHp, UIConst.CHAR_INFO_ATTRIBUTE_ALL_FILTER_MASK)
local otherBaseHp = baseHp - rawHp - hpByStr
if math.abs(otherBaseHp) < 0.001 then
return detailList
end
return detailList
end
function CharInfoUtils.getAtkBaseDetailList(charInfo, finalValue)
local detailList = {}
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInfo.instId)
local attributes = charInst.attributes
local baseAtkWeapon = 0
local weaponInstId = charInst.weaponInstId
local _, itemBundle = GameInstance.player.inventory:TryGetWeaponInst(Utils.getCurrentScope(), weaponInstId)
local weaponInst = itemBundle.instData
local weaponAttrDict = CharInfoUtils.getWeaponShowAttributeDict(weaponInst.instId, weaponInst.weaponLv)
if weaponAttrDict[GEnums.AttributeType.Atk] then
for modifierType, attrInfo in pairs(weaponAttrDict[GEnums.AttributeType.Atk]) do
if modifierType == GEnums.ModifierType.BaseAddition then
baseAtkWeapon = attrInfo.attrValue
end
end
end
table.insert(detailList, {
showName = Language.LUA_CHAR_INFO_FULL_ATTRIBUTE_ATK_WEAPON,
showValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, baseAtkWeapon, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue
})
local baseAtkChar = attributes:GetBaseValue(GEnums.AttributeType.Atk, UIConst.CHAR_INFO_ATTRIBUTE_NONE_FILTER_MASK)
table.insert(detailList, {
showName = Language.LUA_CHAR_INFO_FULL_ATTRIBUTE_ATK_CHAR,
showValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, baseAtkChar, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue
})
local baseAtk = attributes:GetBaseValue(GEnums.AttributeType.Atk, UIConst.CHAR_INFO_ATTRIBUTE_ALL_FILTER_MASK)
local baseAtkOther = baseAtk - baseAtkWeapon - baseAtkChar
if math.abs(baseAtkOther) < 0.001 then
return detailList
end
local baseAtkOtherShowValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, baseAtkOther, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue
table.insert(detailList, {
showName = Language.LUA_CHAR_INFO_FULL_ATTRIBUTE_OTHER,
showValue = baseAtkOtherShowValue,
})
return detailList
end
function CharInfoUtils.getAtkTotalBaseDetailList(charInfo, finalValue)
local detailList = {}
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInfo.instId)
local attributes = charInst.attributes
local atkBase = attributes:GetBaseValue(GEnums.AttributeType.Atk)
local atkBaseChar = attributes:GetBaseValue(GEnums.AttributeType.Atk, UIConst.CHAR_INFO_ATTRIBUTE_NONE_FILTER_MASK)
local subDetailList = {}
local atkBaseWeapon = atkBase - atkBaseChar
table.insert(subDetailList, {
showName = Language.LUA_CHAR_INFO_FULL_ATTRIBUTE_ATK_WEAPON,
showValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, atkBaseWeapon, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue,
})
table.insert(subDetailList, {
showName = Language.LUA_CHAR_INFO_FULL_ATTRIBUTE_ATK_CHAR,
showValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, atkBaseChar, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue,
})
table.insert(detailList, {
showName = Language.LUA_CHAR_INFO_ATTR_ATK_DETAIL_BASE,
showValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, atkBase, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue,
subDetailList = subDetailList,
})
local _, atkBaseMulValue, atkBaseAddValue = attributes:GetBaseFinalAdditionValueForLua(GEnums.AttributeType.Atk)
local atkAddition = atkBaseMulValue + atkBaseAddValue
local subDetailList = {}
if atkBaseAddValue > 0 then
table.insert(subDetailList, {
showName = Language.LUA_CHAR_INFO_ATTR_ATK_DETAIL_ADDITION_FIXED,
showValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, atkBaseAddValue, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue,
})
end
if atkBaseMulValue > 0 then
local atkBaseMulPercentText = string.format("%.1f%%", atkBaseMulValue / atkBase * 100)
table.insert(subDetailList, {
showName = Language.LUA_CHAR_INFO_ATTR_ATK_DETAIL_ADDITION_PERCENT,
showValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, atkBaseMulValue, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue,
hintInfo = {
title = Language.LUA_CHAR_INFO_ATTR_ATK_DETAIL_ADDITION_PERCENT,
mainHint = string.format(Language.LUA_CHAR_INFO_ATTR_ATK_DETAIL_ADDITION_PERCENT_HINT_FORMAT, atkBaseMulPercentText)
},
})
end
table.insert(detailList, {
showName = Language.LUA_CHAR_INFO_ATTR_ATK_DETAIL_ADDITION,
showValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, atkAddition, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue,
subDetailList = subDetailList,
})
local atkSpecialAddition = finalValue - atkBase - atkAddition
local atkSpecialAdditionShowInfo = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, atkSpecialAddition, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
})
if atkSpecialAdditionShowInfo.modifiedValue > 0 then
table.insert(detailList, {
showName = Language.LUA_CHAR_INFO_ATTR_ATK_DETAIL_SPECIAL_ADDITION,
showValue = atkSpecialAdditionShowInfo.showValue,
})
end
return detailList
end
function CharInfoUtils.getAtkScalarDetailList(charInfo, finalValue)
local detailList = {}
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInfo.instId)
local attributes = charInst.attributes
local function getDetail(attrType, attrValue)
local attrShowCfg, attrShowInfo
attrShowCfg = AttributeUtils.getAttributeShowCfg(attrType)
attrShowInfo = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Atk, attrValue, {
forceShowPercent = UIConst.ATTRIBUTE_GENERATE_FORCE_PERCENT.HAS_PERCENT,
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
})
return {
showName = string.format(Language.LUA_CHAR_INFO_FULL_ATTRIBUTE_ATK_SCALAR_FORMAT, attrShowCfg.name),
showValue = "+" .. attrShowInfo.showValue,
}
end
local attrValue
attrValue = attributes:GetAtkFinalScalarFromStr()
if attrValue > 0 then
table.insert(detailList, getDetail(GEnums.AttributeType.Str, attrValue))
end
attrValue = attributes:GetAtkFinalScalarFromAgi()
if attrValue > 0 then
table.insert(detailList, getDetail(GEnums.AttributeType.Agi, attrValue))
end
attrValue = attributes:GetAtkFinalScalarFromWisd()
if attrValue > 0 then
table.insert(detailList, getDetail(GEnums.AttributeType.Wisd, attrValue))
end
attrValue = attributes:GetAtkFinalScalarFromWill()
if attrValue > 0 then
table.insert(detailList, getDetail(GEnums.AttributeType.Will, attrValue))
end
return detailList
end
function CharInfoUtils.GetAllCharPotentialInfos()
local charPotentialIndex2Infos = {}
local charPotentialPicId2Index = {}
local charInfos = CharInfoUtils.getCharInfoList()
local index = 1
for i, info in pairs(charInfos) do
local charInfo = CharInfoUtils.getPlayerCharInfoByInstId(info.instId)
local level = charInfo.potentialLevel
local success, characterPotentialList = Tables.characterPotentialTable:TryGetValue(info.templateId)
if success then
local photoCount = 0
for j = CSIndex(1), CSIndex(characterPotentialList.potentialUnlockBundle.Count) do
if j >= level then
break
end
local potentialData = characterPotentialList.potentialUnlockBundle[j]
local hasPhoto = potentialData.unlockCharPictureItemList and potentialData.unlockCharPictureItemList.Count > 0
if hasPhoto then
photoCount = photoCount + 1
end
end
for j = CSIndex(1), CSIndex(characterPotentialList.potentialUnlockBundle.Count) do
if j >= level then
break
end
local potentialData = characterPotentialList.potentialUnlockBundle[j]
local hasPhoto = potentialData.unlockCharPictureItemList and potentialData.unlockCharPictureItemList.Count > 0
if hasPhoto then
for innerIndex, itemId in pairs(potentialData.unlockCharPictureItemList) do
local _, posterId = Tables.pictureItemTable:TryGetValue(itemId)
local _, posterData = Tables.pictureTable:TryGetValue(posterId)
local _, charCfg = Tables.characterTable:TryGetValue(charInfo.templateId)
local posterInfo = {
posterData = posterData,
charInfo = charInfo,
charSortOrder = charCfg.sortOrder,
charSortOrderReversal = math.maxinteger - charCfg.sortOrder,
charRarity = charCfg.rarity,
charRarityReversal = math.maxinteger - charCfg.rarity,
charPhotoCount = photoCount,
charPhotoCountReversal = math.maxinteger - photoCount,
photoLevel = LuaIndex(j),
photoLevelReversal = math.maxinteger - LuaIndex(j),
innerIndex = innerIndex,
innerIndexReversal = math.maxinteger - innerIndex,
}
table.insert(charPotentialIndex2Infos, posterInfo)
charPotentialPicId2Index[posterId] = index
index = index + 1
end
end
end
end
end
return charPotentialIndex2Infos, charPotentialPicId2Index
end
function CharInfoUtils.getDefDetailList(charInfo, finalAttr)
local detailList = {}
local charInst = CharInfoUtils.getPlayerCharInfoByInstId(charInfo.instId)
local attributes = charInst.attributes
local equipDef = attributes:GetBaseValue(GEnums.AttributeType.Def, UIConst.CHAR_INFO_ATTRIBUTE_EQUIP_FILTER_MASK)
local equipDefShowValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Def, equipDef, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue
table.insert(detailList, {
showName = Language.LUA_CHAR_INFO_FULL_ATTRIBUTE_DEF_BASE,
showValue = equipDefShowValue,
})
local baseDef = attributes:GetBaseValue(GEnums.AttributeType.Def, UIConst.CHAR_INFO_ATTRIBUTE_ALL_FILTER_MASK)
local extraBaseDef = baseDef - equipDef
if math.abs(extraBaseDef) < 0.001 then
return detailList
end
local extraBaseDefShowValue = AttributeUtils.generateAttributeShowInfo(GEnums.AttributeType.Def, extraBaseDef, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
}).showValue
table.insert(detailList, {
showName = Language.LUA_CHAR_INFO_FULL_ATTRIBUTE_DEF_OTHER,
showValue = extraBaseDefShowValue,
})
return detailList
end
function CharInfoUtils.getHpExtra(charInfo)
return CharInfoUtils.getAttrExtraDefault(charInfo.instId, GEnums.AttributeType.MaxHp)
end
function CharInfoUtils.getDefExtra(charInfo)
return CharInfoUtils.getAttrExtraDefault(charInfo.instId, GEnums.AttributeType.Def)
end
function CharInfoUtils.getAttrExtraDefault(charInstId, attrType)
local finalAttr = CharInfoUtils.getCharFinalAttributes(charInstId)[attrType]
local baseAttr = CharInfoUtils.getCharBaseAttributes(charInstId)[attrType]
local attrShowInfo = AttributeUtils.generateAttributeShowInfo(attrType, finalAttr - baseAttr, {
fromSpecificSystem = UIConst.CHAR_INFO_ATTRIBUTE_SPECIFIC_SYSTEM.CHAR_FULL_ATTR
})
return attrShowInfo.showValue, finalAttr - baseAttr
end
_G.CharInfoUtils = CharInfoUtils
return CharInfoUtils