Skip to content

Instantly share code, notes, and snippets.

@Wintrrss1
Created December 16, 2022 17:16
Show Gist options
  • Save Wintrrss1/b5ed74fb8867e65bd4dd1a1c05bd55de to your computer and use it in GitHub Desktop.
Save Wintrrss1/b5ed74fb8867e65bd4dd1a1c05bd55de to your computer and use it in GitHub Desktop.
-- NOTE: Lua version is 5.3 or newer
setGlobalEnum("ShaderDrawOrder")
setGlobalEnum("ShaderDrawOrderSubOrder")
setGlobalEnum("ShaderDrawOrderUserSlot")
setGlobalEnum("RenderFormat")
-- TextureCompositeEnityData.ddf
setGlobalEnum("RuntimeGeneratedTexturesBlendMode")
setGlobalEnum("AlphaMode")
setGlobalEnum("RecolorMode")
setGlobalEnum("RasterizedTextureFormat")
-- alternate operation modes
mutCaptureMode = false
-- brts used by lua must be referenced by launch_sba
brts = {
armgear = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/playerArms_brt"),
base = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/base_brt"),
gear = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/playerGear_brt"),
head = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/playerHead_brt"),
headgear = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/playerHeadgear_brt"),
legs = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/playerLegs_brt"),
presets = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/playerShaderPresets_brt"),
shadow = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/playerShadow_brt"),
uniform = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/playerUniformTextures_brt"),
zonly = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/playerZOnly_MeshCombine_brt"),
vanityItems = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/vanityItems_brt"),
vanityGear = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/bundlereftables/playerVanityGear_brt"),
}
slots = {
arms = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerUpperArm_slot"),
elbowgearL = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerLeftElbowGear_slot"),
elbowgearR = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerRightElbowGear_slot"),
hair = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerHair_slot"),
strandHair = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerStrandHair_slot"),
headaccessory = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerHeadAccessory_slot"),
handgearL = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerHandgearL_slot"),
handgearR = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerHandgearR_slot"),
head = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerHead_slot"),
headgear = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerHeadgear_slot"),
haircap = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerHairCap_slot"),
pants = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerPants_slot"),
legs = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerLegs_slot"),
shoeL = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerShoeL_slot"),
shoeR = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerShoeR_slot"),
shadow = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/characterShadow_slot"),
torso = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerTorso_slot"),
wristgearL = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerLeftWristGear_slot"),
wristgearR = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerRightWristGear_slot"),
mouthpiece = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/playerMouthpiece_slot"),
zonly = lookupDataContainer(ResourceCompartment_Game, "content/common/logic/schematics/slots/PlayerZOnly_slot"),
}
-- -----------------------------------------------------------------------------------------------------------------------------------------------------------
muscleMaps_ArmNames = {
"",
"arm_normal",
"arm_soft_normal",
"arm_ripped_normal",
}
-- TODO: Enable muscle maps for torso and legs. Currently disabled for M21.
muscleMaps_torsoNames = {
"",
"",
"",
"",
}
muscleMaps_legNames = {
"",
"",
"",
"",
}
v_MuscleMaps_torsoNames = {
"",
"v_Torso_NORM_D",
"v_Torso_NORM_H",
"v_Torso_NORM_M",
}
v_MuscleMaps_legNames = {
"",
"v_Legs_NORM_D",
"v_Legs_NORM_H",
"v_Legs_NORM_M",
}
log("FootballRender.LUA Initialized") -- Debug
-- ===========================================================================================================================================================
-- SCRIPT CONFIG
local AllowMissing = true
local TestVanityHardcode = false
local SETTING_EnableStrandHair = true
-- ===========================================================================================================================================================
-- SCRIPT CONSTANTS
-- many geo's include lods as ports of fbx, no need to specify lods
local lod0 = 0
-- most meshes don't contribute to bounding box computations as it will be very expensive
-- but at least few have to, otherwise the model will be invisible
-- we have lod2 and shadow mesh contributing to bbox
local noBoundingBox = false
local updateBoundingBox = true
local playerDrawOrder = ShaderDrawOrder_OnField
local playerDrawOrder_Default = ShaderDrawOrder_Default
local playerDrawSubOrder = ShaderDrawOrderSubOrder_Invalid
local playerDrawUserSlot_High = ShaderDrawOrderUserSlot_High
local playerDrawUserSlot_Medium = ShaderDrawOrderUserSlot_Medium
local playerDrawUserSlot_AboveDefaultBelowMedium = ShaderDrawOrderUserSlot_MaddenAboveDefaultBelowMedium
local LeftSide = {
name = "Left",
prefix = "L"
}
local RightSide = {
name = "Right",
prefix = "R"
}
local fallbackhead_name = "meanhead_capture" -- Fallback hack until New Generics are in
-- note that directly input shader value may not match up perfectly to values used in photoshop due to pipeline color adjustments
local commonColor_Black = {0.015, 0.015, 0.015, 1.0} -- on the 0-255 scale, this is roughly 4
local commonColor_White = {0.92156, 0.92156, 0.92156, 1.0} -- on the 0-255 scale, this is 235
-- ===========================================================================================================================================================
-- HELPER FUNCTIONS
-- EA_TODO: Add support for a module lua file that contains these helper methods/classes
-----------------------------------------------------------------------------
local function isLeft(side)
return side == LeftSide
end
-----------------------------------------------------------------------------
local function isRight(side)
return side == RightSide
end
-----------------------------------------------------------------------------
-- Check to see if array has a value
local function has_value (tab, val)
for index, value in ipairs(tab) do
if value == val then
return true
end
end
return false
end
-----------------------------------------------------------------------------
-- Cull String (TA Determined) coming in from CulledRegion list in appearance object
local function DrawEnabled(cullString, initData)
if initData and initData.Vanity and initData.Vanity.ExtendedVanityData and initData.Vanity.ExtendedVanityData.CulledRegions then
return not has_value(initData.Vanity.ExtendedVanityData.CulledRegions, cullString)
else
return true
end
end
-----------------------------------------------------------------------------
local function stripchars(str, chars)
local s = str:gsub("["..chars:gsub("%W","%%%1").."]", '')
return s
end
-----------------------------------------------------------------------------
local function strStartsWith(inStr, searchStr)
return (string.sub(inStr, 1, #searchStr) == searchStr)
end
local function strEndsWith(inStr, searchStr)
return (searchStr == "" or str:sub(-#searchStr) == searchStr)
end
-----------------------------------------------------------------------------
-- Dump a table node to the log (FB Log and tool, see
-- https://confluence.ea.com/pages/viewpage.action?spaceKey=madden&title=Football+DB+Messaging+-+aka+Roster+and+Appearance+Tweaker)
function log_table(node)
local cache, stack, output = {},{},{}
local depth = 1
local output_str = "{\n"
while true do
local size = 0
if node then
for k,v in pairs(node) do
size = size + 1
end
local cur_index = 1
for k,v in pairs(node) do
if (cache[node] == nil) or (cur_index >= cache[node]) then
if (string.find(output_str,"}",output_str:len())) then
output_str = output_str .. ",\n"
elseif not (string.find(output_str,"\n",output_str:len())) then
output_str = output_str .. "\n"
end
table.insert(output,output_str)
output_str = ""
local key
if (type(k) == "number" or type(k) == "boolean") then
key = "["..tostring(k).."]"
else
key = "['"..tostring(k).."']"
end
if (type(v) == "number" or type(v) == "boolean") then
output_str = output_str .. string.rep('\t',depth) .. key .. " = "..tostring(v)
elseif (type(v) == "table") then
output_str = output_str .. string.rep('\t',depth) .. key .. " = {\n"
table.insert(stack,node)
table.insert(stack,v)
cache[node] = cur_index+1
break
else
output_str = output_str .. string.rep('\t',depth) .. key .. " = '"..tostring(v).."'"
end
if (cur_index == size) then
output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
else
output_str = output_str .. ","
end
else
-- close the table
if (cur_index == size) then
output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
end
end
cur_index = cur_index + 1
end
end
if (size == 0) then
output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
end
if (#stack > 0) then
node = stack[#stack]
stack[#stack] = nil
depth = cache[node] == nil and depth + 1 or depth - 1
else
break
end
end
table.insert(output,output_str)
output_str = table.concat(output)
log(output_str)
end
-----------------------------------------------------------------------------
function tableDeepCopy(obj, seen)
if type(obj) ~= 'table' then return obj end
if seen and seen[obj] then return seen[obj] end
local s = seen or {}
local res = setmetatable({}, getmetatable(obj))
s[obj] = res
for k, v in pairs(obj) do res[tableDeepCopy(k, s)] = tableDeepCopy(v, s) end
return res
end
-----------------------------------------------------------------------------
function setVec(targetField, sourceOverride)
fieldCount = 0
for k,v in pairs(targetField) do
fieldCount = fieldCount + 1
end
if fieldCount == 3 then
targetField[1] = sourceOverride.Vec3Value[1]
targetField[2] = sourceOverride.Vec3Value[2]
targetField[3] = sourceOverride.Vec3Value[3]
else
targetField[1] = sourceOverride.Vec4Value[1]
targetField[2] = sourceOverride.Vec4Value[2]
targetField[3] = sourceOverride.Vec4Value[3]
targetField[4] = sourceOverride.Vec4Value[4]
end
end
-----------------------------------------------------------------------------
local function overrideItem(targetItem, overrides)
if targetItem == nil then
log("targetItem Nil")
--dumpStack()
else
if overrides ~= nil then
count = 0
for k,v in pairs(overrides) do
local fieldName = v.FieldName
if targetItem[fieldName] ~= nil then
--log('Type of field: ' .. fieldName .. ' is ' .. type(targetItem[fieldName]))
if type(targetItem[fieldName]) == 'number' then
targetItem[fieldName] = v.IntValue
elseif type(targetItem[fieldName]) == 'table' then
setVec(targetItem[fieldName], v)
else
targetItem[fieldName] = v.StringValue
end
else
log("Overidden field " .. fieldName .. " does not exist on target item: " .. v.Name)
end
count = count + 1
end
--log("override count " .. count)
end
end
end
-----------------------------------------------------------------------------
function nonil(var)
if var == nil then
return "(nil)"
else
return var
end
end
function vanityLoadComplete(initData)
initData.vanityItemData.vanityTrackingEnabled = false
log("InitPlayer Futures Complete: " .. initData.vanityItemData.Info)
-- clear out the pendingResolves array so that lua can GC the data when finished
initData.vanityItemData.pendingResolves = {}
initPlayerComplete(initData.vanityItemData.RawInitData, initData)
end
function startTrackingVanity(initData)
initData.vanityItemData.vanityTrackingEnabled = true
if initData.vanityItemData.resolvedVanityItems == initData.vanityItemData.requestedVanityItems then
vanityLoadComplete(initData)
end
end
-----------------------------------------------------------------------------
-- forces True if an empty string or nil is given, otherwise passes through AllowMissing
function allowEmptyMissing(assetName)
local returnValue = AllowMissing
if not assetName or assetName =="" then
returnValue = true
end
return returnValue
end
-----------------------------------------------------------------------------
-- Called before load player, if supplied. initalize any vanity assets, must call initPlayerComplete at some point (within futures) for loadplayer to get called
function InitPlayer(incomingInitData, rawInitData)
local initData = tableDeepCopy(incomingInitData)
initData.vanityItemData = {}
local initVanityItemData = initData.vanityItemData
local avatarId = 'N/A'
if initData.Vanity and initData.Vanity.ExtendedVanityData and initData.Vanity.ExtendedVanityData.AvatarInstanceId and initData.Vanity.ExtendedVanityData.AvatarInstanceId ~= '' then
avatarId = initData.Vanity.ExtendedVanityData.AvatarInstanceId
end
initVanityItemData.Info = initData.JerseyName .. ' (index: ' .. initData.RosterIndex .. ' AVID: ' .. avatarId .. ')'
initVanityItemData.RosterIndex = initData.RosterIndex
initVanityItemData.RawInitData = rawInitData
log("Init Player: " .. initVanityItemData.Info )
initVanityItemData.pendingResolves = {}
local pendingResolvesCount = 0
initVanityItemData.vanityTrackingEnabled = false
initVanityItemData.requestedVanityItems = 0 -- Must be globally defined
initVanityItemData.resolvedVanityItems = 0 -- Must be globally defined
if initData.Vanity then
local loadout = initData.Vanity.VanityOnFieldLoadout
if loadout then
loadout = tableDeepCopy(initData.Vanity.VanityOnFieldLoadout)
PreloadVanity("UniformHelmet", loadout.UniformHelmetAssetName, "U_Helmet_Starter_B_BLK", loadout.UniformHelmetOverrides, initData)
PreloadVanity("UniformJersey", loadout.UniformJerseyAssetName, "U_Jersey_Starter_H_BLK", loadout.UniformJerseyOverrides, initData)
PreloadVanity("UniformPants", loadout.UniformPantsAssetName, "U_Pants_None", loadout.UniformPantsOverrides, initData)
PreloadVanity("UniformSocks", loadout.UniformSocksAssetName, "U_Socks_Starter_B_BLK", loadout.UniformSocksOverrides, initData)
PreloadVanity("HelmetFacemask", loadout.GearFacemaskAssetName, "G_Facemask_HyperShield_2Bar", loadout.GearFacemaskOverrides, initData)
PreloadVanity("HelmetVisor", loadout.GearVisorAssetName, "Visor_None", loadout.GearVisorOverrides, initData)
PreloadVanity("JerseyStyle", loadout.UniformJerseyStyleAssetName, "JerseyStyle_Tucked", loadout.UniformJerseyStyleOverrides, initData)
PreloadVanity("JerseySleeves", loadout.GearJeseySleeveAssetName, "JerseySleeve_Tight", loadout.GearJeseySleeveOverrides, initData)
PreloadVanity("Undershirt", loadout.GearUndershirtAssetName, "Body_UpperBody", loadout.GearUndershirtOverrides, initData)
PreloadVanity("Backplate", loadout.GearBackplateAssetName, "Backplate_None", loadout.GearBackplateOverrides, initData)
PreloadVanity("Flakjacket", loadout.GearFlakjacketAssetName, "Flakjacket_None", loadout.GearFlakjacketOverrides, initData)
PreloadVanity("LegsBase", loadout.GearLegsBaseAssetName, "G_CompShorts_Default", loadout.GearLegsBaseOverrides, initData)
PreloadVanity("Socks", loadout.GearSockStyleAssetName, "Socks_Layered", loadout.GearSockStyleOverrides, initData)
PreloadVanity("LeftSpat", loadout.GearLeftSpatAssetName, "Spats_None", loadout.GearLeftSpatOverrides, initData)
PreloadVanity("LeftShoe", loadout.GearLeftShoeAssetName, "U_MaddenSpeedLow_Starter_B_BLK", loadout.GearLeftShoeOverrides, initData)
PreloadVanity("LeftCalf", loadout.GearLeftCalfAssetName, "CalfGear_None", loadout.GearLeftCalfOverrides, initData)
PreloadVanity("RightSpat", loadout.GearRightSpatAssetName, "Spats_None", loadout.GearRightSpatOverrides, initData)
PreloadVanity("RightShoe", loadout.GearRightShoeAssetName, "U_MaddenSpeedLow_Starter_B_BLK", loadout.GearRightShoeOverrides, initData)
PreloadVanity("RightCalf", loadout.GearRightCalfAssetName, "CalfGear_None", loadout.GearRightCalfOverrides, initData)
PreloadVanity("LeftArmSleeve", loadout.GearLeftArmSleeveAssetName, "ArmSleeve_None", loadout.GearLeftArmSleeveOverrides, initData)
PreloadVanity("RightArmSleeve", loadout.GearRightArmSleeveAssetName, "ArmSleeve_None", loadout.GearRightArmSleeveOverrides, initData)
PreloadVanity("LeftElbow", loadout.GearLeftElbowAssetName, "ElbowGear_None", loadout.GearLeftElbowOverrides, initData)
PreloadVanity("RightElbow", loadout.GearRightElbowAssetName, "ElbowGear_None", loadout.GearRightElbowOverrides, initData)
PreloadVanity("LeftWrist", loadout.GearLeftWristAssetName, "WristGear_None", loadout.GearLeftWristOverrides, initData)
PreloadVanity("RightWrist", loadout.GearRightWristAssetName, "WristGear_None", loadout.GearRightWristOverrides, initData)
PreloadVanity("LeftHand", loadout.GearLeftGloveAssetName, "HandGear_None", loadout.GearLeftGloveOverrides, initData)
PreloadVanity("RightHand", loadout.GearRightGloveAssetName, "HandGear_None", loadout.GearRightGloveOverrides, initData)
PreloadVanity("Headband", loadout.GearHeadbandAssetName, "Headband_None", loadout.GearHeadbandOverrides, initData)
PreloadVanity("Mouthpiece", loadout.GearMouthpieceAssetName, "Mouthpiece_None", loadout.GearMouthpieceOverrides, initData)
PreloadVanity("Neckpad", loadout.GearNeckpadAssetName, "Neckpad_None", loadout.GearNeckpadOverrides, initData)
PreloadVanity("Towel", loadout.GearTowelAssetName , "Towel_None", loadout.GearTowelOverrides, initData)
PreloadVanity("Handwarmer", loadout.GearHandwarmerAssetName, "Handwarmer_None", loadout.GearHandwarmerOverrides, initData)
PreloadVanity("HandwarmerMod", loadout.GearHandwarmerModAssetName , "HandwarmerStyle_Front", loadout.GearHandwarmerModOverrides, initData )
PreloadVanity("FaceMarks", loadout.GearFacepaintAssetName, "FaceMarks_None", loadout.GearFacepaintOverrides, initData)
pendingResolvesCount = #initData.vanityItemData.pendingResolves -- need to get the count of the resolves as the array might get cleared
startTrackingVanity(initData) -- Called to tell futures to use this
end
else
log("NO VANITY")
end
log("End InitPlayer: " .. initVanityItemData.Info)
return pendingResolvesCount
end
-----------------------------------------------------------------------------
function PreloadVanity(fieldName, vanityName, fallbackNames, overrideData, initData)
local initVanityItemData = initData.vanityItemData
initVanityItemData.requestedVanityItems = initVanityItemData.requestedVanityItems + 1
--log("FIRST CHECK: " .. nonil(fieldName) .. " - " .. nonil(vanityName) .. "." .. fallbackNames)
if vanityName == nil or vanityName == '' then
vanityName = fallbackNames
fallbackNames = ''
end
local loadAssets = vanityName
if fallbackNames ~= nil then
loadAssets = loadAssets .. ';' .. fallbackNames
end
--log("Loading " .. fieldName .. ": " .. nonil(loadAssets) .. "!" .. initVanityItemData.Info )
initVanityItemData.pendingResolves[#initVanityItemData.pendingResolves + 1] = futureCall(function(resultItem)
initVanityItemData.resolvedVanityItems = initVanityItemData.resolvedVanityItems + 1
if(resultItem) then
local assetData = tableDeepCopy(assetToTable(resultItem))
if overrideData ~= nil and next(overrideData) ~= nil then
overrideItem(assetData, overrideData)
end
initVanityItemData[fieldName] = assetData
else
log('Note for vanity ' .. fieldName .. 'could not load any of ' .. loadAssets)
initVanityItemData[fieldName] = nil
end
if initVanityItemData.vanityTrackingEnabled and initVanityItemData.resolvedVanityItems == initVanityItemData.requestedVanityItems then
vanityLoadComplete(initData)
end
end, loadAsync(brts.vanityItems, loadAssets, true))
end
-----------------------------------------------------------------------------
local function loadCommonAssets(initData)
local commonAssets = {}
local logo_name = string.format("%sLogo01_TRAN;invisible_color", initData.TeamName)
commonAssets.logo_texture = loadAsync(brts.gear, logo_name)
local degmap_name = string.format("cloth_gear_deg_%s_tile_MASK", initData.DegradationType)
commonAssets.degMap = loadAsync(brts.gear, degmap_name)
local degmask_name = string.format("cloth_gear_deg_%s_reveal_MASK_array", initData.DegradationType)
commonAssets.degMask = loadAsync(brts.gear, degmask_name)
return commonAssets
end
-----------------------------------------------------------------------------
local function resolveVanityColors(initData, vanityTablePart)
local colorList = nil
if vanityTablePart and vanityTablePart.PaletteString then
if vanityTablePart.PaletteString == "Custom" then
colorList = {
primary = tableDeepCopy(vanityTablePart.CustomColor1),
secondary = tableDeepCopy(vanityTablePart.CustomColor2),
tertiary = tableDeepCopy(vanityTablePart.CustomColor3),
quaternary = tableDeepCopy(vanityTablePart.CustomColor4),
}
--[[
-- this is currently unused since team has no concept in vanity
elseif vanityTablePart.PaletteString == "TeamColor" then
colorList = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
]]--
elseif vanityTablePart.PaletteString == "White" then
colorList = {
primary = commonColor_White,
secondary = commonColor_White,
tertiary = commonColor_White,
quaternary = commonColor_White,
}
elseif vanityTablePart.PaletteString == "Black" then
colorList = {
primary = commonColor_Black,
secondary = commonColor_Black,
tertiary = commonColor_Black,
quaternary = commonColor_Black,
}
end
else
log("Entered vanityColoResolve with no table data or palette string")
end
return colorList
end
-----------------------------------------------------------------------------
local function convertLeftPartMaskToRight(leftMaskValue)
-- This function takes an arm culling mask value and converts it to the right side
-- Done by simply bumping the mask 6 slots
local rightMaskValue = 0
rightMaskValue = leftMaskValue<<6
return rightMaskValue
end
-----------------------------------------------------------------------------
local function combineCullingMasks(maskList)
-- takes a list of maks values and Bitwise ORs them all together
combinedMask = 0
for i,regionMaskValue in ipairs(maskList) do
combinedMask = combinedMask|regionMaskValue
end
return combinedMask
end
-----------------------------------------------------------------------------
local function addDegShaderParams(material, initData, degMap, degMask)
material:addTexture("deg_pattern_texture", degMap)
material:addTexture("deg_maskArrayTexture", degMask)
material:addVector("degOffset", initData.JerseyNumberSplit)
material:addVector("degColor1", initData.DegradationColor1)
material:addVector("degColor2", initData.DegradationColor2)
end
-- ===========================================================================================================================================================
-- LOAD AND BIND FUNCTIONS
local function bindArmsNfl(initData, arm_mesh, arm_preset, arm_normal, sleeve_texture, degMap, degMask)
local item = createItem("playerUpperArm", slots.arms, initData.laneId, 1)
item:addMeshLodPair(lod0, arm_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
local addShaderParams = function(material)
-- presets
if arm_preset then
material:addPreset(arm_preset)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
-- vectors
material:addVector("primaryColor", initData.UniformPrimaryColor)
material:addVector("secondaryColor", initData.UniformSecondaryColor)
material:addVector("regionMaskValue", initData.FullArmRegionMask)
material:addVector("armSleeveMaskValue", initData.ArmSleeveMask)
material:addVector("leftSleeveColor", initData.LeftArmSleeveColor)
material:addVector("rightSleeveColor", initData.RightArmSleeveColor)
-- texture
if sleeve_texture then
material:addTexture("sleeveTexture", sleeve_texture)
end
if arm_normal then
material:addTexture("normalClampTexture", arm_normal)
end
end
item:reserveMaterials(3)
addShaderParams(item:addMaterial("arm_lod0_mat"))
addShaderParams(item:addMaterial("arm_lod1_mat"))
addShaderParams(item:addMaterial("arm_lod2_mat"))
return item
end
local function bindArmsVanity(initData, arm_mesh, arm_preset, sleeveL_mesh, sleeveL_preset, sleeveR_mesh, sleeveR_preset, arm_normal, tapeL_normal, tapeR_normal, degMap, degMask,
armsleeveL_colors, armsleeveR_colors)
local item = createItem("playerUpperArm", slots.arms, initData.laneId, 3)
item:addMeshLodPair(lod0, arm_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
if sleeveL_mesh then
item:addMeshLodPair(lod0, sleeveL_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
end
if sleeveR_mesh then
item:addMeshLodPair(lod0, sleeveR_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
end
local addArmShaderParams = function(material)
-- presets
material:addPreset(arm_preset)
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
-- Arm Tape Logic ...........................................................................................................
local textureRef = nil
local combinedMask = 0
if initData.vanityItemData.LeftArmSleeve.isNormal > 0.5 or initData.vanityItemData.RightArmSleeve.isNormal > 0.5 then
if initData.vanityItemData.LeftArmSleeve.isNormal > 0.5 then
if tapeL_normal then
textureRef = tapeL_normal
end
combinedMask = initData.vanityItemData.LeftArmSleeve.PartMask
end
if initData.vanityItemData.RightArmSleeve.isNormal > 0.5 then
if not textureRef and tapeR_normal then
textureRef = tapeR_normal
end
-- first shift the mask by 5 (geometry culling for rest of the body uses 6 instead of 5) to get the value of the right side
-- mask and then bitwise OR with the left side mask
-- ToDO convert literal to constant
combinedMask = combinedMask|(initData.vanityItemData.RightArmSleeve.PartMask<<5)
end
if textureRef then
material:addTexture("sleeveTexture", textureRef)
end
material:addVector("armSleeveMaskValue", combinedMask)
if armsleeveL_colors then
material:addVector("leftSleeveColor", armsleeveL_colors.primary)
end
if armsleeveR_colors then
material:addVector("rightSleeveColor", armsleeveR_colors.primary)
end
end
--[[
--We don't want to do muscle map based swapping for vanity arms due to different topology
if arm_normal then
material:addTexture("normalClampTexture", arm_normal)
end
]]--
-- Arm Culling Logic .....................................................................................................
local maskList = {}
--left armsleeve
if initData.vanityItemData.LeftArmSleeve.isNormal < 0.1 then
maskList[#maskList+1] = initData.vanityItemData.LeftArmSleeve.PartMask
end
maskList[#maskList+1] = initData.vanityItemData.LeftElbow.PartMask
maskList[#maskList+1] = initData.vanityItemData.LeftWrist.PartMask
maskList[#maskList+1] = initData.vanityItemData.LeftHand.PartMask
--right armsleeve
if initData.vanityItemData.RightArmSleeve.isNormal < 0.1 then
maskList[#maskList+1] = convertLeftPartMaskToRight(initData.vanityItemData.RightArmSleeve.PartMask)
end
maskList[#maskList+1] = convertLeftPartMaskToRight(initData.vanityItemData.RightElbow.PartMask)
maskList[#maskList+1] = convertLeftPartMaskToRight(initData.vanityItemData.RightWrist.PartMask)
maskList[#maskList+1] = convertLeftPartMaskToRight(initData.vanityItemData.RightHand.PartMask)
--undershirt
maskList[#maskList+1] = initData.vanityItemData.Undershirt.PartMask
local fullMask = combineCullingMasks(maskList)
material:addVector("regionMaskValue", fullMask) --temporary disable
end
item:reserveMaterials(9)
addArmShaderParams(item:addMaterial("arm_lod0_mat"))
addArmShaderParams(item:addMaterial("arm_lod1_mat"))
addArmShaderParams(item:addMaterial("arm_lod2_mat"))
local addSleeveShaderParams = function(material, tgtPreset, colors)
-- presets
if tgtPreset then
material:addPreset(tgtPreset)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
if colors then
material:addVector("primaryColor", colors.primary)
material:addVector("secondaryColor", colors.secondary)
material:addVector("tertiaryColor", colors.tertiary)
material:addVector("quaternaryColor", colors.quaternary)
end
end
if initData.vanityItemData.LeftArmSleeve.isNormal < 0.1 then
addSleeveShaderParams(item:addMaterial("armSleeveL_lod0_mat"), sleeveL_preset, armsleeveL_colors)
addSleeveShaderParams(item:addMaterial("armSleeveL_lod1_mat"), sleeveL_preset, armsleeveL_colors)
addSleeveShaderParams(item:addMaterial("armSleeveL_lod2_mat"), sleeveL_preset, armsleeveL_colors)
addSleeveShaderParams(item:addMaterial("playerArmSleeveL_lod0_mat"), sleeveL_preset, armsleeveL_colors)
addSleeveShaderParams(item:addMaterial("playerArmSleeveL_lod1_mat"), sleeveL_preset, armsleeveL_colors)
addSleeveShaderParams(item:addMaterial("playerArmSleeveL_lod2_mat"), sleeveL_preset, armsleeveL_colors)
addSleeveShaderParams(item:addMaterial("playerArmSleeveL_lod3_mat"), sleeveL_preset, armsleeveL_colors)
addSleeveShaderParams(item:addMaterial("playerArmSleeveL_lod4_mat"), sleeveL_preset, armsleeveL_colors)
end
if initData.vanityItemData.RightArmSleeve.isNormal < 0.1 then
addSleeveShaderParams(item:addMaterial("armSleeveR_lod0_mat"), sleeveR_preset, armsleeveR_colors)
addSleeveShaderParams(item:addMaterial("armSleeveR_lod1_mat"), sleeveR_preset, armsleeveR_colors)
addSleeveShaderParams(item:addMaterial("armSleeveR_lod2_mat"), sleeveR_preset, armsleeveR_colors)
addSleeveShaderParams(item:addMaterial("playerArmSleeveR_lod0_mat"), sleeveR_preset, armsleeveR_colors)
addSleeveShaderParams(item:addMaterial("playerArmSleeveR_lod1_mat"), sleeveR_preset, armsleeveR_colors)
addSleeveShaderParams(item:addMaterial("playerArmSleeveR_lod2_mat"), sleeveR_preset, armsleeveR_colors)
addSleeveShaderParams(item:addMaterial("playerArmSleeveR_lod3_mat"), sleeveR_preset, armsleeveR_colors)
addSleeveShaderParams(item:addMaterial("playerArmSleeveR_lod4_mat"), sleeveR_preset, armsleeveR_colors)
end
return item
end
-----------------------------------------------------------------------------
local function loadArms(items, initData)
local chars_to_remove = "'- ."
-- Shaquem Griffin Arm Override
local arm_name = "arms"
if string.lower(initData.UniqueHeadName) == "griffinshaquem_13251" then
arm_name = "NoHandL"
elseif string.lower(initData.UniqueHeadName) == "hasselljt_20895" then
arm_name = "NoHandL_1"
end
local mesh_name = nil
local arm_mesh = nil
local preset_name = nil
local arm_preset = nil
local arm_normal_name = muscleMaps_ArmNames[initData.MuscleType+1] --lua indices start at 1 and not 0
local arm_normal = nil
if arm_normal_name == "" then
local arms_barycentric = initData.ArmsBarycentric
local arms_base = initData.ArmsBase
arm_normal_name = muscleMaps_ArmNames[2]
if arms_barycentric > 1.5 and arms_barycentric < 2.5 and arms_base > 0.5 then
arm_normal_name = muscleMaps_ArmNames[3]
elseif arms_barycentric > 0.5 and arms_barycentric < 1.5 and arms_base > 0.5 then
arm_normal_name = muscleMaps_ArmNames[4]
end
end
arm_normal = loadAsync(brts.armgear, arm_normal_name, true)
local armsleeveL_colors = nil
local armsleeveL_colors = nil
local armsleeveR_colors = nil
local armsleeve_mask = 0
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout) then
armsleeveL_colors = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
armsleeveR_colors = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
preset_name = string.format("%s_ST_preset;player_skin_ST%s_preset;player_skin_ST3_preset", stripchars(initData.UniqueHeadName, chars_to_remove), initData.SkinTone)
if mutCaptureMode then
preset_name = "player_skin_capture_preset"
end
arm_preset = loadAsync(brts.presets, preset_name)
mesh_name = string.format("%s_metamorph", arm_name)
arm_mesh = loadAsync(brts.armgear, mesh_name)
local sleeve_name = string.format("%s;%s",
initData.RightArmSleeve,
initData.LeftArmSleeve)
local sleeve_texture = loadAsync(brts.armgear, sleeve_name, AllowMissing)
items[#items + 1] = futureCall(bindArmsNfl, initData, arm_mesh, arm_preset, arm_normal, sleeve_texture,
initData.commonAssets.degMap, initData.commonAssets.degMask)
else
-- Vanity
-- If IsNormal is true for an ArmSleeve, then we use preset as a texture name on the arm
preset_name = string.format("v_%s_ST_preset;vanity_skin_ST%s_preset;vanity_skin_ST3_preset", stripchars(initData.UniqueHeadName, chars_to_remove), initData.SkinTone)
arm_preset = loadAsync(brts.vanityGear, preset_name)
mesh_name = string.format("%s_metamorph", "v_Arms")
arm_mesh = loadAsync(brts.vanityGear, mesh_name)
armsleeveL_colors = resolveVanityColors(initData, initData.vanityItemData.LeftArmSleeve)
armsleeveR_colors = resolveVanityColors(initData, initData.vanityItemData.RightArmSleeve)
local meshL_name = string.format("%s%s_metamorph", initData.vanityItemData.LeftArmSleeve.Model, "L")
local presetL_name = string.format("%s%s_preset;%s_preset;%s%s_preset", initData.vanityItemData.LeftArmSleeve.Material, "L", initData.vanityItemData.LeftArmSleeve.Material, initData.vanityItemData.LeftArmSleeve.Model, "L")
local tapeL_normal = nil
if initData.vanityItemData.LeftArmSleeve.isNormal > 0.5 then
tapeL_normal = loadAsync(brts.vanityGear, initData.vanityItemData.LeftArmSleeve.Material, AllowMissing) --this is a normal map in this case
end
local armsleeveL_mesh = loadAsync(brts.vanityGear, meshL_name, AllowMissing)
local armsleeveL_preset = loadAsync(brts.vanityGear, presetL_name, AllowMissing)
local meshR_name = string.format("%s%s_metamorph", initData.vanityItemData.RightArmSleeve.Model, "R")
local presetR_name = string.format("%s%s_preset;%s_preset;%s%s_preset", initData.vanityItemData.RightArmSleeve.Material, "R", initData.vanityItemData.RightArmSleeve.Material, initData.vanityItemData.RightArmSleeve.Model, "R")
local tapeR_normal = nil
if initData.vanityItemData.RightArmSleeve.isNormal > 0.5 then
tapeR_normal = loadAsync(brts.vanityGear, initData.vanityItemData.RightArmSleeve.Material, AllowMissing) --this is a normal map in this case
end
local armsleeveR_mesh = loadAsync(brts.vanityGear, meshR_name, AllowMissing)
local armsleeveR_preset = loadAsync(brts.vanityGear, presetR_name, AllowMissing)
items[#items + 1] = futureCall(bindArmsVanity, initData, arm_mesh, arm_preset, armsleeveL_mesh, armsleeveL_preset,
armsleeveR_mesh, armsleeveR_preset, arm_normal, tapeL_normal, tapeR_normal, initData.commonAssets.degMap, initData.commonAssets.degMask,
armsleeveL_colors, armsleeveR_colors)
end
end
-----------------------------------------------------------------------------
local function bindElbowGear(side, initData, elbowgear, elbowgear_mesh, elbowgear_preset, elbow_colors, degMap, degMask)
local item_name = string.format("playerElbowGear%s", side.prefix)
local item = createItem(item_name, elbowgear.slot, initData.laneId, 1)
if elbowgear_mesh then
item:addMeshLodPair(lod0, elbowgear_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
end
local addShaderParams = function(material)
-- presets
if elbowgear_preset then
material:addPreset(elbowgear_preset)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
if elbow_colors then
material:addVector("primaryColor", elbow_colors.primary)
material:addVector("secondaryColor", elbow_colors.secondary)
material:addVector("tertiaryColor", elbow_colors.tertiary)
material:addVector("quaternaryColor", elbow_colors.quaternary)
end
end
item:reserveMaterials(3)
addShaderParams(item:addMaterial(string.format("playerElbow%s_lod0_mat", side.prefix)))
addShaderParams(item:addMaterial(string.format("playerElbow%s_lod1_mat", side.prefix)))
addShaderParams(item:addMaterial(string.format("playerElbow%s_lod2_mat", side.prefix)))
return item
end
-----------------------------------------------------------------------------
local function loadElbowGear(side, items, initData)
local elbowgear_mesh = nil
local elbowgear_preset = nil
local elbowgear = {
slot = isLeft(side) and slots.elbowgearL or slots.elbowgearR,
model = isLeft(side) and initData.LeftElbowModel or initData.RightElbowModel,
material = isLeft(side) and initData.LeftElbowMaterial or initData.RightElbowMaterial,
palette = isLeft(side) and initData.LeftElbowPalette or initData.RightElbowPalette,
loadoutAsset = nil,
loadoutOverrides = nil,
}
local elbow_colors = nil
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout) then
elbow_colors = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
local mesh_name = string.format("%s%s_metamorph", elbowgear.model, side.prefix)
local preset_name = string.format("%s%s_%s_preset;%s_preset;player_missing_preset",
elbowgear.model, elbowgear.material, elbowgear.palette,
elbowgear.model)
elbowgear_mesh = loadAsync(brts.armgear, mesh_name, AllowMissing)
elbowgear_preset = loadAsync(brts.presets, preset_name)
else
local elbow_side = isLeft(side) and "LeftElbow" or "RightElbow"
elbow_colors = resolveVanityColors(initData, initData.vanityItemData[elbow_side])
local mesh_name = string.format("%s%s_metamorph", initData.vanityItemData[elbow_side].Model, side.prefix)
local preset_name = string.format("%s%s_preset;%s%s_preset", initData.vanityItemData[elbow_side].Material, side.prefix, initData.vanityItemData[elbow_side].Model, side.prefix)
elbowgear_mesh = loadAsync(brts.vanityGear, mesh_name, AllowMissing)
elbowgear_preset = loadAsync(brts.vanityGear, preset_name, AllowMissing)
end
items[#items + 1] = futureCall(bindElbowGear, side, initData, elbowgear, elbowgear_mesh, elbowgear_preset, elbow_colors,
initData.commonAssets.degMap, initData.commonAssets.degMask)
end
-----------------------------------------------------------------------------
local function bindHair(initData, hair_mesh, hair_helmetoff_mesh, hair_collider_mesh, logo_overlay_texture, headgear_color)
local item = createItem("playerHair", slots.hair, initData.laneId, 3)
item:setIncludeCullTagHashes("Hair")
item:setTagHashes("Hair")
if hair_mesh then
item:addMeshLodPair(lod0, hair_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
end
if hair_helmetoff_mesh then
item:addMeshLodPair(lod0, hair_helmetoff_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
end
item:addMeshLodPair(lod0, hair_collider_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
return item
end
-- hair cap item
local function bindHaircapItem(initData, haircap_mesh, logo_overlay_texture, headgear_color)
local item = createItem("haircap", slots.haircap, initData.laneId)
item:setIncludeCullTagHashes("hair_cap")
item:setTagHashes("hair_cap")
item:addMeshLodPair(lod0, haircap_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
local addShaderParams = function(material)
-- Headbands are in the haircap on G4
material:addVector("primaryColor", headgear_color.primary)
material:addVector("secondaryColor", headgear_color.secondary)
material:addVector("tertiaryColor", headgear_color.tertiary)
-- n.b, In at least CharacterTestLevel TeamName is empty... so we load invisible_color here. The defaults in FrostEd are correct, so lets just leave them.
-- logo_overlay_texture is loaded by a dynamic string name which uses TeamName.
if initData.TeamName and not (initData.TeamName == "") then
-- cover potentially two different types of shaders
material:addTexture("logoOverlayTexture", logo_overlay_texture)
material:addTexture("teamLogo", logo_overlay_texture)
end
end
item:reserveMaterials(1)
addShaderParams(item:addMaterial("headband_mat"))
return item
end
-- bind hair accessory item
local function bindHairAccessoryItem(initData, hairaccessory_mesh, logo_overlay_texture, headgear_color)
local item = createItem("hairaccessory", slots.headaccessory, initData.laneId)
item:setIncludeCullTagHashes("hair_accessory")
item:setTagHashes("hair_accessory")
item:addMeshLodPair(lod0, hairaccessory_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
local addShaderParams = function(material)
material:addVector("primaryColor", headgear_color.primary)
material:addVector("secondaryColor", headgear_color.secondary)
material:addVector("tertiaryColor", headgear_color.tertiary)
-- n.b, In at least CharacterTestLevel TeamName is empty... so we load invisible_color here. The defaults in FrostEd are correct, so lets just leave them.
-- logo_overlay_texture is loaded by a dynamic string name which uses TeamName.
if initData.TeamName and not (initData.TeamName == "") then
-- cover potentially two different types of shaders
material:addTexture("logoOverlayTexture", logo_overlay_texture)
material:addTexture("teamLogo", logo_overlay_texture)
end
end
item:reserveMaterials(1)
addShaderParams(item:addMaterial("headband_mat"))
return item
end
-----------------------------------------------------------------------------
local function loadHair(items, initData)
local chars_to_remove = "'- ."
local headgear_color = nil
headgear_color = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
local haircap_mesh_name = string.format("%s_haircap;gen_%s_haircap;%s;%s_haircap",
initData.UniqueHeadName,
initData.GenericHeadName,
initData.CustomHairCap,
fallbackhead_name)
local haircap_mesh = loadAsync(brts.head, stripchars(haircap_mesh_name, chars_to_remove), AllowMissing)
local hairaccessory_mesh_name = string.format("%s_headaccessory;%s%s_headaccessory;gen_%s_headaccessory",
initData.UniqueHeadName,
initData.LastName, initData.FirstName,
initData.GenericHeadName)
local hairaccessory_mesh = loadAsync(brts.head, stripchars(hairaccessory_mesh_name, chars_to_remove), AllowMissing)
local hair_mesh_name = string.format("%s_hair;gen_%s_hair;%s;%s_hair",
initData.UniqueHeadName,
initData.GenericHeadName,
initData.CustomHair,
fallbackhead_name)
local hair_mesh = loadAsync(brts.head, stripchars(hair_mesh_name, chars_to_remove), AllowMissing)
--Robby Anderson hair override
local hair_helmetoff_mesh_name = string.format("%s_hair_HelmetOff;%s_helmetOff",
initData.UniqueHeadName,
string.lower(initData.UniqueHeadName) == "andersonrobby_17960" and "None" or initData.HelmetOnHairSimType)
local hair_helmetoff_mesh = loadAsync(brts.head, stripchars(hair_helmetoff_mesh_name, chars_to_remove), AllowMissing)
local hair_collider_mesh_name = string.format("%s_HairCollider;HairCollider", initData.UniqueHeadName)
local hair_collider_mesh = loadAsync(brts.gear, stripchars(hair_collider_mesh_name, chars_to_remove))
items[#items + 1] = futureCall(bindHair, initData, hair_mesh, hair_helmetoff_mesh, hair_collider_mesh, initData.commonAssets.logo_texture, headgear_color)
if haircap_mesh then
items[#items + 1] = futureCall(bindHaircapItem, initData, haircap_mesh, initData.commonAssets.logo_texture, headgear_color)
end
if hairaccessory_mesh then
items[#items + 1] = futureCall(bindHairAccessoryItem, initData, hairaccessory_mesh, initData.commonAssets.logo_texture, headgear_color)
end
end
-----------------------------------------------------------------------------
local function bindStrandHairItem(initData, hair, beard, eye_brow)
local item = createItem("strandhair", slots.strandHair, initData.laneId)
item:setIncludeCullTagHashes("strand_hair")
item:setTagHashes("strand_hair")
if hair then item:addMeshLodPair(lod0, hair, updateBoundingBox, playerDrawOrder, playerDrawSubOrder) end
if beard then item:addMeshLodPair(lod0, beard, updateBoundingBox, playerDrawOrder, playerDrawSubOrder) end
if eye_brow then item:addMeshLodPair(lod0, eye_brow, updateBoundingBox, playerDrawOrder, playerDrawSubOrder) end
-- EA_TODO: Add materials here.
return item
end
-----------------------------------------------------------------------------
local function loadStrandHair(items, initData)
local chars_to_remove = "'- ."
-- EA_TODO: Move strand hair to its own BRT to prevent accidental loading of non-strand assets
local hair_mesh_name = string.format("%s_strandbind_hair;gen_%s_strandbind_hair;%s_strandbind_hair;%s_strandbind_hair",
initData.UniqueHeadName,
initData.GenericHeadName,
initData.CustomHair,
fallbackhead_name)
local beard_mesh_name = string.format("%s_strandbind_beard;gen_%s_strandbind_beard;%s_strandbind_hair;%s_strandbind_beard",
initData.UniqueHeadName,
initData.GenericHeadName,
initData.CustomHair,
fallbackhead_name)
local eyebrow_mesh_name = string.format("%s_strandbind_eyebrow;gen_%s_strandbind_eyebrow;%s_strandbind_hair;%s_strandbind_hair",
initData.UniqueHeadName,
initData.GenericHeadName,
initData.CustomHair,
fallbackhead_name )
local allow_missing = true
-- EA_TODO: M22 Hack to disable Strand Hair on SSKO players
-- SSKO heads contain "C_KO" in the name. Check if this one does so we can disable its strand hair.
local isSSKOHead = string.find(initData.UniqueHeadName, "C_KO") ~= nil
local shouldLoadStrandHair = (not isSSKOHead)
if not isSSKOHead then
local hair_mesh = loadAsync(brts.head, stripchars(hair_mesh_name, chars_to_remove), allow_missing)
local beard_mesh = loadAsync(brts.head, stripchars(beard_mesh_name, chars_to_remove), allow_missing)
local eye_brow_mesh = loadAsync(brts.head, stripchars(eyebrow_mesh_name, chars_to_remove), allow_missing)
shouldLoadStrandHair = hair_mesh or beard_mesh or eye_brow_mesh
if shouldLoadStrandHair then
items[#items + 1] = futureCall(bindStrandHairItem, initData, hair_mesh, beard_mesh, eye_brow_mesh)
end
end
return shouldLoadStrandHair
end
-----------------------------------------------------------------------------
local function bindHead(initData, head_mesh, headacc_mesh, eyepaint_texture, eyepaint_channels)
local item = createItem("playerHead", slots.head, initData.laneId, 2)
item:addMeshLodPair(lod0, head_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
item:setTagHashes("psd")
if headacc_mesh then
item:addMeshLodPair(lod0, headacc_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
end
local addShaderParams = function(material)
material:addVector("EBChannels", eyepaint_channels)
material:addVector("degOffset", initData.JerseyNumberSplit)
material:addTexture("EBTexture", eyepaint_texture)
end
item:reserveMaterials(3)
addShaderParams(item:addMaterial("head_lod0_mat"))
addShaderParams(item:addMaterial("head_lod1_mat"))
addShaderParams(item:addMaterial("head_lod2_mat"))
return item
end
-----------------------------------------------------------------------------
local function loadHead(items, initData)
local chars_to_remove = "'- ."
local head_mesh_name = string.format("%s;gen_%s;%s",
initData.UniqueHeadName,
initData.GenericHeadName,
fallbackhead_name) -- Fallback hack until New Generics are in
if initData.CharLogo and initData.CharLogo == "M21_NARRATIVE_HACK" then
head_mesh_name = string.format("%s_m21uniHack;%s;gen_%s;%s",
initData.UniqueHeadName,
initData.UniqueHeadName,
initData.GenericHeadName,
fallbackhead_name) -- Fallback hack until New Generics are in)
end
if mutCaptureMode then
head_mesh_name = "meanhead_capture"
end
local head_mesh = loadAsync(brts.head, stripchars(head_mesh_name, chars_to_remove))
local headacc_mesh_name = string.format("%s", initData.FaceAccessory)
local headacc_mesh = loadAsync(brts.head, stripchars(headacc_mesh_name, chars_to_remove), AllowMissing)
local eyepaint_texture_name = ""
local eyepaint_texture = nil
local eyepaint_channels = { 0.0, 0.0, 0.0, 0.0 }
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout or not initData.vanityItemData) then
eyepaint_texture_name = string.format("%s", initData.EyePaintTexture)
eyepaint_texture = loadAsync(brts.head, eyepaint_texture_name)
eyepaint_channels = initData.EyePaintChannels
if mutCaptureMode then
eyepaint_channels = { 0.0, 0.0, 0.0, 0.0 }
end
else
eyepaint_texture_name = string.format("%s", initData.vanityItemData.FaceMarks.Material)
if eyepaint_texture_name == "" then
eyepaint_texture_name = "eyeBlack"
end
--eyepaint_texture = loadAsync(brts.vanityGear, eyepaint_texture_name)
eyepaint_texture = loadAsync(brts.head, eyepaint_texture_name) --TODO switch this to vanity exclusive texutres once delivered
eyepaint_channels = initData.vanityItemData.FaceMarks.FacePaintChannels
end
items[#items + 1] = futureCall(bindHead, initData, head_mesh, headacc_mesh, eyepaint_texture, eyepaint_channels)
end
-----------------------------------------------------------------------------
local function bindHeadGear(initData, helmetshell_mesh, helmetacc_mesh, helmetfacemask_mesh, helmetvisor_mesh, helmethair_mesh,
helmetvisorclip_mesh, helmethaircollider_mesh, helmetshell_preset, helmetacc_preset, helmetfacemask_preset, helmetvisor_preset, greendot_texture,
helmAcc_colors, helmFacemask_colors, helmVisor_colors, helmChinstrap_colors)
local item = createItem("playerHeadGear", slots.headgear, initData.laneId, 8)
item:setIncludeCullTagHashes("Helmet")
item:setExcludeCullTagHashes("Hair")
item:setExcludeCullTagHashes("hair_cap")
item:setTagHashes("Helmet")
-- Meshes
if helmetshell_mesh then
item:addMeshLodPair(lod0, helmetshell_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_AboveDefaultBelowMedium)
end
if helmetacc_mesh then
item:addMeshLodPair(lod0, helmetacc_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_AboveDefaultBelowMedium)
end
if helmetfacemask_mesh then
item:addMeshLodPair(lod0, helmetfacemask_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_AboveDefaultBelowMedium)
end
if helmetvisor_mesh then
item:addMeshLodPair(lod0, helmetvisor_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_AboveDefaultBelowMedium)
end
if helmethair_mesh then
item:addMeshLodPair(lod0, helmethair_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_AboveDefaultBelowMedium)
end
if helmetvisorclip_mesh then
item:addMeshLodPair(lod0, helmetvisorclip_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_AboveDefaultBelowMedium)
end
if helmethaircollider_mesh then
item:addMeshLodPair(lod0, helmethaircollider_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_AboveDefaultBelowMedium)
end
-- Materials
item:reserveMaterials(18)
-- HelmetShell
local addHelmetShellShaderParams = function(material)
if helmetshell_preset then
material:addPreset(helmetshell_preset)
end
material:addVector("helmetBackNumber_selection", initData.JerseyNumberSplit)
material:addVector("helmetFrontNumber_selection", initData.JerseyNumberSplit)
material:addVector("degAwayTeamColor", initData.OppositeTeamColor)
material:addTexture("greendot", greendot_texture)
--check for composited uniform
if initData.PalletizedUniformData and initData.PalletizedUniformData.IsPalletizedUniform > 0.1 and initData.PalletizedUniformData.PalletizedHelmetColorTextureHandle ~= 0 then
--log("Apply Composited Helmet")
material:addGenTexture("colorTexture", initData.PalletizedUniformData.PalletizedHelmetColorTextureHandle)
end
end
addHelmetShellShaderParams(item:addMaterial("playerHelmetShell_lod0_mat"))
addHelmetShellShaderParams(item:addMaterial("playerHelmetShell_lod1_mat"))
addHelmetShellShaderParams(item:addMaterial("playerHelmetShell_lod2_mat"))
-- Accessories
local addHelmetAccShaderParams = function(material)
if helmetacc_preset then
material:addPreset(helmetacc_preset)
end
material:addVector("degOffset", initData.JerseyNumberSplit)
if helmAcc_colors then
material:addVector("primaryColor", helmAcc_colors.primary)
material:addVector("secondaryColor", helmAcc_colors.secondary)
material:addVector("tertiaryColor", helmAcc_colors.tertiary)
material:addVector("quaternaryColor", helmAcc_colors.quaternary)
end
end
addHelmetAccShaderParams(item:addMaterial("playerHelmetAccessories_lod0_mat"))
addHelmetAccShaderParams(item:addMaterial("playerHelmetAccessories_lod1_mat"))
addHelmetAccShaderParams(item:addMaterial("playerHelmetAccessories_lod2_mat"))
-- Chinstrap - uses the Accessory materials
addHelmetAccShaderParams(item:addMaterial("playerHelmetChinstrap_lod0_mat"))
addHelmetAccShaderParams(item:addMaterial("playerHelmetChinstrap_lod1_mat"))
addHelmetAccShaderParams(item:addMaterial("playerHelmetChinstrap_lod2_mat"))
-- Facemask
local addHelmetFacemaskShaderParams = function(material)
if helmetfacemask_preset then
material:addPreset(helmetfacemask_preset)
end
material:addVector("degOffset", initData.JerseyNumberSplit)
if helmFacemask_colors then
material:addVector("primaryColor", helmFacemask_colors.primary)
material:addVector("secondaryColor", helmFacemask_colors.secondary)
material:addVector("tertiaryColor", helmFacemask_colors.tertiary)
material:addVector("quaternaryColor", helmFacemask_colors.quaternary)
end
end
addHelmetFacemaskShaderParams(item:addMaterial("playerHelmetFacemask_lod0_mat"))
addHelmetFacemaskShaderParams(item:addMaterial("playerHelmetFacemask_lod1_mat"))
addHelmetFacemaskShaderParams(item:addMaterial("playerHelmetFacemask_lod2_mat"))
-- Visor
local addHelmetVisorShaderParams = function(material)
if helmetvisor_preset then
material:addPreset(helmetvisor_preset)
end
if helmVisor_colors then
if helmVisor_colors.primary then -- we don't always use these for nfl
--log("visor palettize main")
material:addVector("color1", helmVisor_colors.primary)
material:addVector("color2", helmVisor_colors.secondary)
material:addVector("color3", helmVisor_colors.tertiary)
end
if helmVisor_colors.tabPrimary then -- we don't use these for vanity in m21
--log("visor palettize tab")
--note the capitalization (first letter capitalized) on the parameters here is different than on the other parts
material:addVector("PrimaryColor", helmVisor_colors.tabPrimary)
material:addVector("SecondaryColor", helmVisor_colors.tabSecondary)
--material:addVector("TertiaryColor", helmVisor_colors.tabTertiary)
end
end
end
addHelmetVisorShaderParams(item:addMaterial("playerHelmetVisor_lod0_mat"))
addHelmetVisorShaderParams(item:addMaterial("playerHelmetVisor_lod1_mat"))
addHelmetVisorShaderParams(item:addMaterial("playerHelmetVisor_lod2_mat"))
-- VisorClips
local addHelmetVisorClipsShaderParams = function(material)
if helmetfacemask_preset then
material:addPreset(helmetfacemask_preset)
end
if helmFacemask_colors then
material:addVector("primaryColor", helmFacemask_colors.primary)
material:addVector("secondaryColor", helmFacemask_colors.secondary)
material:addVector("tertiaryColor", helmFacemask_colors.tertiary)
material:addVector("quaternaryColor", helmFacemask_colors.quaternary)
end
end
addHelmetVisorClipsShaderParams(item:addMaterial("playerHelmetVisorClips_lod0_mat"))
addHelmetVisorClipsShaderParams(item:addMaterial("playerHelmetVisorClips_lod1_mat"))
addHelmetVisorClipsShaderParams(item:addMaterial("playerHelmetVisorClips_lod2_mat"))
return item
end
-----------------------------------------------------------------------------
HelmetFacemaskToVisorClip = {
-- Facemasks
["revokicker"] = "kicker_revo",
["revo3barrb"] = "revo3BarRBClip",
["revofullcage3"] = "revoFullCage3Clip",
["revospeedcage"] = "RevospeedCageClip",
["revospeedrobot"] = "revoSpeedrobotClip",
["stdbulldog"] = "standardClip",
["revospeedkicker"] = nil,
["revospeedfullcage2"] = "revospeedCageClip",
["g3bn"] = "G3B_revo",
["g2b"] = "G3B_revo",
["g2bd"] = "G3B_revo",
["3barrb"] = "standard2Clip",
["3barrbjagged"] = "standard2Clip",
["opodw"] = "standard2Clip",
["bullrb"] = "standard2Clip",
["rkop"] = "standard2Clip",
["xenithpredator"] = "XenithPrismClip",
["xenithprism"] = "XenithPrismClip",
["xenithprowl"] = "XenithProwlClip",
["viciskicker"] = "VicisKickerClip",
["vengeancefullcagebulldog"] = "VengeanceFullCageBulldogClip",
["speedflexcage"] = "speedflexCageClip",
["speedflexhalfcage2"] = "speedflexCageClip",
["speedflex2barqb"] = "speedflexCageClip",
["speedflex2barsingle"] = "speedflexCageClip",
["speedflexrobotrbjagged"] = "speedflexCageClip",
["speedflex3barsingle"] = "speedflexCageClip",
["speedflex3barqb"] = "speedflexCageClip",
["speedflex3barrbjagged"] = "speedflexCageClip",
["vengeancez102bar"] = "SchuttVengeanceZ10Clip",
["vengeancez103barlb"] = "SchuttVengeanceZ10Clip",
["vengeancez10cage"] = "SchuttVengeanceZ10Clip",
["vengeancez10robot"] = "SchuttVengeanceZ10Clip",
["vengeancez10robotrb"] = "SchuttVengeanceZ10Clip",
["revospeed2barwr"] = "Revospeed2BarWRClip",
["vengeance3barrb"] = "VengeanceClip",
["vengeancekicker"] = "VengeanceClip",
["vengeanceqb"] = "VengeanceClip",
["vengeancerobot"] = "VengeanceClip",
["vengeancefullcage"] = "VengeanceClip",
["vengeancerobotrb"] = "VengeanceClip",
["f72bar"] = "SchuttF7Clip",
["f73bar"] = "SchuttF7Clip",
["f73barrb"] = "SchuttF7Clip",
["f7fullcage"] = "SchuttF7Clip",
["f7robotrb"] = "SchuttF7Clip",
["f7robot"] = "SchuttF7Clip",
-- Helmets
["riddell360"] = "riddell360Clip",
["speedflex"] = "speedflexClip",
["airxp"] = "standardClip",
["schutt"] = "standardClip",
["standard"] = "standardClip",
["revospeed"] = "revoSpeedClip",
["revo"] = "revoClip",
["xenith"] = "XenithClip",
["schuttvengeance"] = "VengeanceClip",
["viciszero1"] = "VicisZero1Clip",
["xenithepic"] = "XenithClip",
["xenithshadow"] = "XenithClip",
["v_madden_hypershield"] = "standardClip"
}
local function getVisorClip(facemaskIn, helmetIn)
local visor = HelmetFacemaskToVisorClip[string.lower(facemaskIn)]
if not visor then
visor = HelmetFacemaskToVisorClip[string.lower(helmetIn)] or ""
end
return visor
end
-----------------------------------------------------------------------------
local function loadHeadGear(items, initData)
local helmetshell_mesh = nil
local helmetacc_mesh = nil
local helmetfacemask_mesh = nil
local helmetvisor_mesh = nil
local helmetvisorclip_mesh_name = ""
local helmetvisorclip_mesh = nil
local helmetshell_preset = nil
local helmetacc_preset = nil
local helmetfacemask_preset = nil
local helmetvisor_preset = nil
local helmAcc_colors = nil
local helmFacemask_colors = nil
local helmVisor_colors = nil
local helmChinstrap_colors = nil --needs shader update to fully implement
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout or not initData.vanityItemData) then
-- set oakley visor tab colors. We don't do this for vanity since they should be using baked tab textures
helmVisor_colors = {
tabPrimary = initData.HelmetPrimaryColor,
tabSecondary = initData.HelmetSecondaryColor,
tabTertiary = initData.HelmetSecondaryColor, --we do not currently use tertiary though the shader supports it
}
local helmetshell_mesh_name = string.format("helmet_shell_%s", initData.PlayerHelmet)
helmetshell_mesh = loadAsync(brts.headgear, helmetshell_mesh_name, AllowMissing)
local helmetacc_mesh_name = string.format("helmet_accessories_%s", initData.PlayerHelmet)
helmetacc_mesh = loadAsync(brts.headgear, helmetacc_mesh_name, AllowMissing)
local helmetfacemask_mesh_name = string.format("helmet_facemask_%s", initData.Facemask)
helmetfacemask_mesh = loadAsync(brts.headgear, helmetfacemask_mesh_name, AllowMissing)
local visor = initData.Visor == "None" and "None" or "visor"
local helmetvisor_mesh_name = string.format("helmet_%s_%s", visor, initData.PlayerHelmet)
helmetvisor_mesh = loadAsync(brts.headgear, helmetvisor_mesh_name, AllowMissing)
if initData.Visor ~= "None" then
helmetvisorclip_mesh_name = string.format("helmet_visorclips_%s", getVisorClip(initData.Facemask, initData.PlayerHelmet))
end
helmetvisorclip_mesh = loadAsync(brts.headgear, helmetvisorclip_mesh_name, AllowMissing)
local helmetshell_preset_name = string.format("%s_preset;FALLBACK_Helmet_preset", initData.HelmetPreset)
-- NARRATIVE HACK
if initData.HatType then
if initData.HatType == 370 or initData.HatType == 400 or initData.HatType == 410 or initData.HatType == 520 then
helmetshell_preset_name = string.format("%s_CFP_preset;FALLBACK_Helmet_preset", initData.HelmetPreset)
end
end
helmetshell_preset = loadAsync(brts.presets, helmetshell_preset_name)
local helmetacc_preset_name = string.format("%s_Acc_preset;FALLBACK_Helmet_Acc_preset", initData.HelmetPreset)
helmetacc_preset = loadAsync(brts.presets, helmetacc_preset_name)
local helmetfacemask_preset_name = string.format("%s_facemask_preset;FALLBACK_Helmet_Facemask_preset", initData.HelmetPreset)
helmetfacemask_preset = loadAsync(brts.presets, helmetfacemask_preset_name)
local helmetvisor_preset_name = string.format("player_visor_%s_preset;player_visor_preset", initData.Visor)
if mutCaptureMode then
helmetvisor_preset_name = "player_visor_capture_preset"
end
helmetvisor_preset = loadAsync(brts.presets, helmetvisor_preset_name)
else
helmAcc_colors = nil --resolveVanityColors(initData, initData.vanityItemData.UniformHelmet)
helmChinstrap_colors = nil --initData.VanityItemData.UniformHelmet.ChinstrapColor
-- special visor setup
if initData.vanityItemData.HelmetVisor.PaletteString == "Custom" then
helmVisor_colors = {
primary = tableDeepCopy(initData.vanityItemData.HelmetVisor.CustomColor1),
secondary = tableDeepCopy(initData.vanityItemData.HelmetVisor.CustomColor2),
tertiary = tableDeepCopy(initData.vanityItemData.HelmetVisor.CustomColor3),
quaternary = tableDeepCopy(initData.vanityItemData.HelmetVisor.CustomColor4),
}
end
-- special facemask setup
if initData.vanityItemData.UniformHelmet.FacemaskPaletteString == "Custom" then
helmFacemask_colors = {
primary = tableDeepCopy(initData.vanityItemData.UniformHelmet.FacemaskCustomColor1),
secondary = tableDeepCopy(initData.vanityItemData.UniformHelmet.FacemaskCustomColor2),
tertiary = tableDeepCopy(initData.vanityItemData.UniformHelmet.FacemaskCustomColor3),
quaternary = tableDeepCopy(initData.vanityItemData.UniformHelmet.FacemaskCustomColor4),
}
elseif initData.vanityItemData.UniformHelmet.FacemaskPaletteString == "TeamColor" then
helmFacemask_colors = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
elseif initData.vanityItemData.UniformHelmet.FacemaskPaletteString == "White" then
helmFacemask_colors = {
primary = commonColor_White,
secondary = commonColor_White,
tertiary = commonColor_White,
quaternary = commonColor_White,
}
elseif initData.vanityItemData.UniformHelmet.FacemaskPaletteString == "Black" then
helmFacemask_colors = {
primary = commonColor_Black,
secondary = commonColor_Black,
tertiary = commonColor_Black,
quaternary = commonColor_Black,
}
end
local helmet_item_model = initData.vanityItemData.UniformHelmet.Model
local facemask_item_model = initData.vanityItemData.HelmetFacemask.Model
local visor_item_model = initData.vanityItemData.HelmetVisor.Model
local helmet_item_mat = initData.vanityItemData.UniformHelmet.Material
local facemask_item_mat = initData.vanityItemData.UniformHelmet.FacemaskMaterial
local visor_item_mat = initData.vanityItemData.HelmetVisor.Material
local helmetshell_mesh_name = string.format("%s_shell", helmet_item_model)
helmetshell_mesh = loadAsync(brts.vanityGear, helmetshell_mesh_name, AllowMissing)
local helmetacc_mesh_name = string.format("%s_accessories", helmet_item_model)
helmetacc_mesh = loadAsync(brts.vanityGear, helmetacc_mesh_name, AllowMissing)
local helmetfacemask_mesh_name = string.format("helmet_facemask_%s", facemask_item_model)
helmetfacemask_mesh = loadAsync(brts.headgear, helmetfacemask_mesh_name, AllowMissing)
local helmetvisor_mesh_name = string.format("%s_%s", helmet_item_model, visor_item_model)
helmetvisor_mesh = loadAsync(brts.vanityGear, helmetvisor_mesh_name, AllowMissing)
if visor_item_model ~= "" then
helmetvisorclip_mesh_name = string.format("helmet_visorclips_%s", getVisorClip(facemask_item_model, helmet_item_model))
end
local helmetshell_preset_name = string.format("%s_preset_pro;%s_preset;%s;FALLBACK_Helmet_preset", helmet_item_mat, helmet_item_mat, helmet_item_mat)
helmetshell_preset = loadAsync(brts.presets, helmetshell_preset_name)
local helmetacc_preset_name = string.format("%s_Acc_preset;FALLBACK_Helmet_Acc_preset", helmet_item_mat)
helmetacc_preset = loadAsync(brts.presets, helmetacc_preset_name)
local helmetfacemask_preset_name = string.format("%s_preset;FALLBACK_Helmet_Facemask_preset", facemask_item_mat)
helmetfacemask_preset = loadAsync(brts.presets, helmetfacemask_preset_name, true)
local helmetvisor_preset_name = string.format("%s_preset", visor_item_mat)
helmetvisorclip_mesh = loadAsync(brts.headgear, helmetvisorclip_mesh_name, true)
helmetvisor_preset = loadAsync(brts.vanityGear, helmetvisor_preset_name, true)
end
local greendot_texture_name = initData.GreenDot == "None" and "invisible_color" or "greenSticker_COL"
local greendot_texture = loadAsync(brts.headgear, greendot_texture_name)
local helmethair_mesh_name = string.format("%s_hair_helmetOn;%s_helmetOn",
initData.UniqueHeadName,
initData.HelmetOnHairSimType)
local helmethair_mesh = loadAsync(brts.headgear, helmethair_mesh_name, AllowMissing)
local helmethaircollider_mesh_name = string.format("%s_HairCollider;HairCollider", initData.UniqueHeadName)
local helmethaircollider_mesh = loadAsync(brts.headgear, helmethaircollider_mesh_name, AllowMissing)
items[#items + 1] = futureCall(bindHeadGear, initData, helmetshell_mesh, helmetacc_mesh, helmetfacemask_mesh, helmetvisor_mesh, helmethair_mesh,
helmetvisorclip_mesh, helmethaircollider_mesh, helmetshell_preset, helmetacc_preset, helmetfacemask_preset, helmetvisor_preset, greendot_texture,
helmAcc_colors, helmFacemask_colors, helmVisor_colors, helmChinstrap_colors)
end
-----------------------------------------------------------------------------
local function bindPants(initData, pants_mesh, pants_preset, logo_overlay_texture, degMap, degMask, pants_colors)
local item = createItem("playerPants", slots.pants, initData.laneId, 1)
-- Meshes
if pants_mesh then
item:addMeshLodPair(lod0, pants_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_Medium)
end
-- Materials
item:reserveMaterials(3)
-- Pants
local addPantsShaderParams = function(material)
if pants_preset then
material:addPreset(pants_preset)
end
material:addVector("thighNormalArrayTextureSlice", initData.ThighPadNormalSlice)
material:addVector("kneeNormalArrayTextureSlice", initData.KneePadNormalSlice)
addDegShaderParams(material, initData, degMap, degMask)
--check for composited uniform
if initData.PalletizedUniformData and initData.PalletizedUniformData.IsPalletizedUniform > 0.1 and initData.PalletizedUniformData.PalletizedPantsColorTextureHandle ~= 0 then
--log("Apply Composited Pants")
material:addGenTexture("colorTexture", initData.PalletizedUniformData.PalletizedPantsColorTextureHandle)
material:addGenTexture("RSMTexture", initData.PalletizedUniformData.PalletizedPantsRSMTextureHandle)
material:addGenTexture("normalClampTexture", initData.PalletizedUniformData.PalletizedPantsSeamNormalTextureHandle)
end
end
addPantsShaderParams(item:addMaterial("playerPants_lod0_mat"))
addPantsShaderParams(item:addMaterial("playerPants_lod1_mat"))
addPantsShaderParams(item:addMaterial("playerPants_lod2_mat"))
return item
end
-----------------------------------------------------------------------------
local function loadPants(items, initData)
local pants_mesh = nil
local pants_preset = nil
if not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout then
local pants_bottom_name = { "pants", "shorts_padless" }
local pants_mesh_name = string.format("%s_metamorph", pants_bottom_name[initData.PlayerBottom + 1])
pants_mesh = loadAsync(brts.legs, pants_mesh_name)
-- Presets
local pants_preset_name = string.format("%s_preset;FALLBACK_Pants_preset", initData.PantsPreset)
pants_preset = loadAsync(brts.presets, pants_preset_name)
else
-- Vanity Items ..................................................................................
pants_colors = nil --resolveVanityColors(initData, initData.vanityItemData.UniformPants)
local pants_item_model = initData.vanityItemData.UniformPants.Model
local pants_item_mat = initData.vanityItemData.UniformPants.Material
-- PANTS
local pants_mesh_name = string.format("%s_metamorph", pants_item_model)
pants_mesh = loadAsync(brts.vanityGear, pants_mesh_name, AllowMissing)
local pants_mat_name = ""
-- yeah this is a huge hack but it's the reality of the world we live in
if pants_item_model == "v_FootballPants_Standard" or pants_item_model == "v_FootballPantsCutoff_AboveKnee" or pants_item_model == "v_FootballPants_AboveKnee" then
--log("Pants Uniform Preset")
pants_mat_name = string.format("%s_preset_pro;%s_preset;%s", pants_item_mat, pants_item_mat, pants_item_mat)
pants_preset = loadAsync(brts.presets, pants_mat_name, AllowMissing)
else
--log("Pants Gear Preset")
pants_mat_name = string.format("s_preset_pro;%s_preset;%s", pants_item_mat, pants_item_mat, pants_item_mat)
pants_preset = loadAsync(brts.vanityGear, pants_mat_name, AllowMissing)
end
end
items[#items + 1] = futureCall(bindPants, initData, pants_mesh, pants_preset, initData.commonAssets.logo_texture,
initData.commonAssets.degMap, initData.commonAssets.degMask, pants_colors)
end
-----------------------------------------------------------------------------
local function bindLegs(initData, pants_mesh, socks_mesh, towel_mesh, handwarmer_mesh, leftcalf_mesh, rightcalf_mesh, socksunder_mesh, towelcollider_mesh, bottomlegs_mesh, bottomlegs_preset,
pants_preset, leftcalf_preset, rightcalf_preset, socks_preset, socks_adjustments, legs_preset, handwarmer_preset, legs_normal, logo_overlay_texture, degMap, degMask,
legsbase_mesh, legsbase_preset, pants_colors, legsbase_colors, leftcalf_colors, rightcalf_colors, socksunder_colors, socks_colors, handwarmer_colors)
local item = createItem("playerLegs", slots.legs, initData.laneId, 10)
if socks_mesh then
item:addMeshLodPair(lod0, socks_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_Medium)
end
if towel_mesh then
item:addMeshLodPair(lod0, towel_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_Medium)
if towelcollider_mesh then
item:addMeshLodPair(lod0, towelcollider_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_Medium)
end
end
if handwarmer_mesh then
item:addMeshLodPair(lod0, handwarmer_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_Medium)
end
if leftcalf_mesh then
item:addMeshLodPair(lod0, leftcalf_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_Medium)
end
if rightcalf_mesh then
item:addMeshLodPair(lod0, rightcalf_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_Medium)
end
if socksunder_mesh then
item:addMeshLodPair(lod0, socksunder_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_AboveDefaultBelowMedium)
end
if bottomlegs_mesh then
item:addMeshLodPair(lod0, bottomlegs_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_Medium)
end
if legsbase_mesh then
item:addMeshLodPair(lod0, legsbase_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_Medium)
end
-- Materials
item:reserveMaterials(21)
-- Calves
local addCalfShaderParams = function(material, input_preset, input_colors)
if input_preset then
material:addPreset(input_preset)
end
if input_colors then
material:addVector("primaryColor", input_colors.primary)
material:addVector("secondaryColor", input_colors.secondary)
material:addVector("tertiaryColor", input_colors.tertiary)
end
addDegShaderParams(material, initData, degMap, degMask)
end
addCalfShaderParams(item:addMaterial("playerCalfSleeveL_lod0_mat"), leftcalf_preset, leftcalf_colors)
addCalfShaderParams(item:addMaterial("playerCalfSleeveL_lod1_mat"), leftcalf_preset, leftcalf_colors)
addCalfShaderParams(item:addMaterial("playerCalfSleeveL_lod2_mat"), leftcalf_preset, leftcalf_colors)
addCalfShaderParams(item:addMaterial("playerCalfSleeveR_lod0_mat"), rightcalf_preset, rightcalf_colors)
addCalfShaderParams(item:addMaterial("playerCalfSleeveR_lod1_mat"), rightcalf_preset, rightcalf_colors)
addCalfShaderParams(item:addMaterial("playerCalfSleeveR_lod2_mat"), rightcalf_preset, rightcalf_colors)
-- Socks
local addSocksShaderParams = function(material)
if socks_preset then
material:addPreset(socks_preset)
end
addDegShaderParams(material, initData, degMap, degMask)
--apply uv adjustments
material:addVector("vOffset", socks_adjustments.offset)
material:addVector("vScale", socks_adjustments.scale)
--check for composited uniform
if initData.PalletizedUniformData and initData.PalletizedUniformData.IsPalletizedUniform > 0.1 and initData.PalletizedUniformData.PalletizedSocksColorTextureHandle ~= 0 then
--log("Apply Composited Socks")
material:addGenTexture("colorTexture", initData.PalletizedUniformData.PalletizedSocksColorTextureHandle)
end
end
if not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout then
addSocksShaderParams(item:addMaterial("playerSocksUnder_lod0_mat"))
addSocksShaderParams(item:addMaterial("playerSocksUnder_lod1_mat"))
addSocksShaderParams(item:addMaterial("playerSocksUnder_lod2_mat"))
else
addSocksShaderParams(item:addMaterial("playerSocks_lod0_mat"))
addSocksShaderParams(item:addMaterial("playerSocks_lod1_mat"))
addSocksShaderParams(item:addMaterial("playerSocks_lod2_mat"))
end
-- Handwarmer
local addHandWarmerShaderParams = function(material)
if handwarmer_preset then
material:addPreset(handwarmer_preset)
end
if handwarmer_colors then
material:addVector("primaryColor", handwarmer_colors.primary)
material:addVector("secondaryColor", handwarmer_colors.secondary)
material:addVector("tertiaryColor", handwarmer_colors.tertiary)
end
material:addTexture("logoOverlayTexture", logo_overlay_texture)
addDegShaderParams(material, initData, degMap, degMask)
end
addHandWarmerShaderParams(item:addMaterial("Handwarmer_lod0_mat"))
addHandWarmerShaderParams(item:addMaterial("Handwarmer_lod1_mat"))
addHandWarmerShaderParams(item:addMaterial("Handwarmer_lod2_mat"))
-- Towel
local addTowelShaderParams = function(material)
addDegShaderParams(material, initData, degMap, degMask)
end
addTowelShaderParams(item:addMaterial("towel_lod0_mat"))
addTowelShaderParams(item:addMaterial("towel_lod1_mat"))
addTowelShaderParams(item:addMaterial("towel_lod2_mat"))
-- Socks - uses same shader pararms as Towels
addTowelShaderParams(item:addMaterial("playerSocks_lod0_mat"))
addTowelShaderParams(item:addMaterial("playerSocks_lod1_mat"))
addTowelShaderParams(item:addMaterial("playerSocks_lod2_mat"))
local addLegsShaderParams = function(material)
material:addPreset(legs_preset)
if legs_normal then
material:addTexture("normalClampTexture", legs_normal)
end
end
if legs_preset then
addLegsShaderParams(item:addMaterial("playerLegs_lod0_mat"))
addLegsShaderParams(item:addMaterial("playerLegs_lod1_mat"))
addLegsShaderParams(item:addMaterial("playerLegs_lod2_mat"))
end
-- Vanity: Legs Base
local addLegsBaseShaderParams = function(material)
if legsbase_preset then
material:addPreset(legsbase_preset)
end
if legsbase_colors then
material:addVector("primaryColor", legsbase_colors.primary)
material:addVector("secondaryColor", legsbase_colors.secondary)
material:addVector("tertiaryColor", legsbase_colors.tertiary)
material:addVector("quaternaryColor", legsbase_colors.quaternary)
end
addDegShaderParams(material, initData, degMap, degMask)
-- Culling Logic
if initData.vanityItemData then
local maskList = {}
maskList[#maskList+1] = initData.vanityItemData.UniformPants.PartMask
maskList[#maskList+1] = initData.vanityItemData.Socks.PartMask
local fullMask = combineCullingMasks(maskList)
material:addVector("regionMaskValue", fullMask)
end
end
addLegsBaseShaderParams(item:addMaterial("playerLowerBodyUnder_lod0_mat"))
addLegsBaseShaderParams(item:addMaterial("playerLowerBodyUnder_lod1_mat"))
addLegsBaseShaderParams(item:addMaterial("playerLowerBodyUnder_lod2_mat"))
-- Bare Legs Skintone
local addBottomLegsShaderParams = function(material)
if bottomlegs_preset then
material:addPreset(bottomlegs_preset)
end
addDegShaderParams(material, initData, degMap, degMask)
-- Culling Logic
if initData.vanityItemData then
local maskList = {}
maskList[#maskList+1] = initData.vanityItemData.UniformPants.PartMask
maskList[#maskList+1] = initData.vanityItemData.LegsBase.PartMask
maskList[#maskList+1] = initData.vanityItemData.Socks.PartMask
local fullMask = combineCullingMasks(maskList)
material:addVector("regionMaskValue", fullMask)
end
end
if bottomlegs_mesh then
addBottomLegsShaderParams(item:addMaterial("legskin_lod0_mat"))
addBottomLegsShaderParams(item:addMaterial("legskin_lod1_mat"))
addBottomLegsShaderParams(item:addMaterial("legskin_lod2_mat"))
end
return item
end
-----------------------------------------------------------------------------
local function loadLegs(items, initData)
local pants_mesh = nil
local leftcalf_mesh = nil
local rightcalf_mesh = nil
local socksunder_mesh = nil
local socks_mesh = nil
local handwarmer_mesh = nil
local bottomlegs_mesh = nil
local bottomlegs_preset = nil
local towel_mesh = nil
local towelcollider_mesh = nil
local pants_preset = nil
local leftcalf_preset = nil
local rightcalf_preset = nil
local socks_preset = nil
local handwarmer_preset = nil
local legsbase_mesh = nil
local legsbase_preset = nil
local legsbase_colors = nil
local leftcalf_colors = nil
local rightcalf_colors = nil
local socksunder_colors = nil
local socks_colors = nil
local handwarmer_colors = nil
local legsbase_culling = nil
local socks_culling = nil
local legs_normal = nil
local socks_adjustments = {
offset = 0.0,
scale = 1.0,
}
-- TODO: Enable this block of code once leg normal maps exist. This code is currently untested.
-- TODO: Refactor indexing into muscleMaps_LegNames based on bitmasking.
--[[
local legs_normal_name = muscleMaps_LegNames[initData.MuscleType+1] --lua indices start at 1 and not 0
if legs_normal_name == "" then
local legs_barycentric = initData.LegsBarycentric
local legs_base = initData.LegsBase
legs_normal_name = muscleMaps_LegNames[2]
if legs_barycentric > 1.5 and legs_barycentric < 2.5 and legs_base > 0.5 then
legs_normal_name = muscleMaps_LegNames[3]
elseif legs_barycentric > 0.5 and legs_barycentric < 1.5 and legs_base > 0.5 then
legs_normal_name = muscleMaps_LegNames[4]
end
end
legs_normal = loadAsync(brts.legs, legs_normal_name, true)
]]
if not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout then
local pants_bottom_name = { "pants", "shorts_padless" }
local legs_bottom_name = { "", "legs" }
local socksunder_bottom_name = { "socks_under", "" }
handwarmer_colors = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
local pants_mesh_name = string.format("%s_metamorph", pants_bottom_name[initData.PlayerBottom + 1])
pants_mesh = loadAsync(brts.legs, pants_mesh_name)
local socksunder_mesh_name = string.format("%s_metamorph", socksunder_bottom_name[initData.PlayerBottom + 1])
socksunder_mesh = loadAsync(brts.legs, socksunder_mesh_name, AllowMissing)
local socks_mesh_name = string.format("socks_%s_metamorph", initData.SockHeight)
socks_mesh = loadAsync(brts.legs, socks_mesh_name, AllowMissing)
-- adjust sock stripes on undersock to oversock height
if initData.SockAdjust > 0.5 then
if initData.SockHeight == "Low" then
socks_adjustments.offset = -0.35
elseif initData.SockHeight == "High" then
socks_adjustments.offset = 0.05
socks_adjustments.scale = 2.0
end
end
local towel_mesh_name = string.format("%s_%s", initData.Towel, initData.ApproxBodyType)
if mutCaptureMode then
towel_mesh_name = ""
end
towel_mesh = loadAsync(brts.gear, towel_mesh_name, AllowMissing)
towelcollider_mesh = loadAsync(brts.gear, "TowelCollider", AllowMissing)
local handwarmer_mesh_name = string.format("%s_metamorph", initData.HandWarmer)
handwarmer_mesh = loadAsync(brts.gear, handwarmer_mesh_name, AllowMissing)
local bottomlegs_mesh_name = string.format("%s_metamorph", legs_bottom_name[initData.PlayerBottom + 1])
bottomlegs_mesh = loadAsync(brts.armgear, bottomlegs_mesh_name, AllowMissing) -- yeah it's kinda weird that legs are in the armgear brt but it's really because both arms and legs are in "bodies"
local bottomlegs_preset_name = string.format("vanity_legskin_ST%s_preset;vanity_legskin_ST3_preset", initData.SkinTone)
bottomlegs_preset = loadAsync(brts.presets, bottomlegs_preset_name, AllowMissing)
-- Presets
local pants_preset_name = string.format("%s_preset;FALLBACK_Pants_preset", initData.PantsPreset)
pants_preset = loadAsync(brts.presets, pants_preset_name)
local socks_preset_name = string.format("%s_preset;FALLBACK_Socks_preset", initData.SocksPreset)
socks_preset = loadAsync(brts.presets, socks_preset_name)
else
-- Vanity Items ..................................................................................
pants_colors = nil --resolveVanityColors(initData, initData.vanityItemData.UniformPants)
legsbase_colors = resolveVanityColors(initData, initData.vanityItemData.LegsBase)
leftcalf_colors = resolveVanityColors(initData, initData.vanityItemData.LeftCalf)
rightcalf_colors = resolveVanityColors(initData, initData.vanityItemData.RightCalf)
socks_colors = resolveVanityColors(initData, initData.vanityItemData.UniformSocks)
handwarmer_colors = resolveVanityColors(initData, initData.vanityItemData.Handwarmer)
local pants_item_model = initData.vanityItemData.UniformPants.Model
local legsbase_item_model = initData.vanityItemData.LegsBase.Model
local leftcalf_item_model = initData.vanityItemData.LeftCalf.Model
local rightcalf_item_model = initData.vanityItemData.RightCalf.Model
local socks_item_model = initData.vanityItemData.Socks.Model
local handwarmer_item_model = initData.vanityItemData.Handwarmer.Model
local pants_item_mat = initData.vanityItemData.UniformPants.Material
local legsbase_item_mat = initData.vanityItemData.LegsBase.Material
local leftcalf_item_mat = initData.vanityItemData.LeftCalf.Material
local rightcalf_item_mat = initData.vanityItemData.RightCalf.Material
local socks_item_mat = initData.vanityItemData.UniformSocks.Material
local handwarmer_item_mat = initData.vanityItemData.Handwarmer.Model
local handwarmer_style = initData.vanityItemData.HandwarmerMod.Model -- not a true model, used to modify handwarmer type
local towel_item_model = initData.vanityItemData.Towel.Model
local legs_bottom_name = ""
legs_normal = nil
-- RESOLVE CONFLICTING PARTS
-- CompressionPants Full should disable CalfSleeves
-- PANTS
local pants_mesh_name = string.format("%s_metamorph", pants_item_model)
pants_mesh = loadAsync(brts.vanityGear, pants_mesh_name, AllowMissing)
local pants_mat_name = ""
-- yeah this is a huge hack but it's the reality of the world we live in
if pants_item_model == "v_FootballPants_Standard" or pants_item_model == "v_FootballPantsCutoff_AboveKnee" or pants_item_model == "v_FootballPants_AboveKnee" then
--log("Pants Uniform Preset")
pants_mat_name = string.format("%s_preset_pro;%s_preset;%s", pants_item_mat, pants_item_mat, pants_item_mat)
pants_preset = loadAsync(brts.presets, pants_mat_name, AllowMissing)
else
--log("Pants Gear Preset")
pants_mat_name = string.format("s_preset_pro;%s_preset;%s", pants_item_mat, pants_item_mat, pants_item_mat)
pants_preset = loadAsync(brts.vanityGear, pants_mat_name, AllowMissing)
end
-- LEGS BASE
local legsbase_mesh_name = string.format("%s_metamorph", legsbase_item_model)
legsbase_mesh = loadAsync(brts.vanityGear, legsbase_mesh_name, true)
local legsbase_preset_name = string.format("%s_preset", legsbase_item_mat)
legsbase_preset = loadAsync(brts.vanityGear, legsbase_preset_name, true)
-- CALF SLEEVE/PADS
local leftcalf_mesh_name = string.format("%sL_metamorph", leftcalf_item_model)
leftcalf_mesh = loadAsync(brts.vanityGear, leftcalf_mesh_name, AllowMissing)
local rightcalf_mesh_name = string.format("%sR_metamorph", rightcalf_item_model)
rightcalf_mesh = loadAsync(brts.vanityGear, rightcalf_mesh_name, AllowMissing)
local leftcalf_preset_name = string.format("%s_preset", leftcalf_item_mat)
leftcalf_preset = loadAsync(brts.vanityGear, leftcalf_preset_name, AllowMissing)
local rightcalf_preset_name = string.format("%s_preset", rightcalf_item_mat)
rightcalf_preset = loadAsync(brts.vanityGear, rightcalf_preset_name, AllowMissing)
-- SOCKS
local socks_mesh_name = string.format("%s_metamorph", socks_item_model)
socks_mesh = loadAsync(brts.vanityGear, socks_mesh_name, AllowMissing)
local socks_preset_name = string.format("%s_preset_pro;%s_preset;%s", socks_item_mat, socks_item_mat, socks_item_mat)
socks_preset = loadAsync(brts.presets, socks_preset_name, AllowMissing)
-- HANDWARMER
local handwarmer_mesh_name = string.format("%s_%s_metamorph;%s_metamorph", handwarmer_item_model, handwarmer_style, handwarmer_item_model)
handwarmer_mesh = loadAsync(brts.vanityGear, handwarmer_mesh_name, AllowMissing)
local handwarmer_preset_name = string.format("%s_preset", handwarmer_item_mat)
handwarmer_preset = loadAsync(brts.vanityGear, handwarmer_preset_name, AllowMissing)
-- TOWEL
local towel_mesh_name = string.format("%s_%s", towel_item_model, initData.ApproxBodyType) -- TODO Temp body type?
towel_mesh = loadAsync(brts.vanityGear, towel_mesh_name, AllowMissing)
towelcollider_mesh = loadAsync(brts.gear, "TowelCollider", AllowMissing) --TODO does vanity need its own collider mesh?
-- BARE LEGS
legs_bottom_name = "v_Legs"
local bottomlegs_preset_name = ""
local legs_normal_name = v_MuscleMaps_legNames[initData.MuscleType+1]
legs_normal = loadAsync(brts.vanityGear, legs_normal_name, true)
bottomlegs_preset_name = string.format("vanity_legskin_ST%s_preset;vanity_legskin_ST3_preset", initData.SkinTone)
local bottomlegs_mesh_name = string.format("%s_metamorph", legs_bottom_name)
bottomlegs_mesh = loadAsync(brts.vanityGear, bottomlegs_mesh_name, AllowMissing)
bottomlegs_preset_name = string.format("vanity_legskin_ST%s_preset;vanity_legskin_ST3_preset", initData.SkinTone)
bottomlegs_preset = loadAsync(brts.vanityGear, bottomlegs_preset_name, AllowMissing)
end
local legs_preset_name = string.format("%s_legST_preset;player_leg_ST%s_preset;player_leg_ST4_preset", initData.UniqueHeadName, initData.SkinTone)
local legs_preset = loadAsync(brts.presets, legs_preset_name)
items[#items + 1] = futureCall(bindLegs, initData, pants_mesh, socks_mesh, towel_mesh, handwarmer_mesh, leftcalf_mesh, rightcalf_mesh, socksunder_mesh, towelcollider_mesh,
bottomlegs_mesh, bottomlegs_preset, pants_preset, leftcalf_preset, rightcalf_preset, socks_preset, socks_adjustments, legs_preset, handwarmer_preset, legs_normal,
initData.commonAssets.logo_texture, initData.commonAssets.degMap, initData.commonAssets.degMask,
legsbase_mesh, legsbase_preset, pants_colors, legsbase_colors, leftcalf_colors, rightcalf_colors, socksunder_colors, socks_colors, handwarmer_colors)
end
-----------------------------------------------------------------------------
local function compositeNamePlate(initData, fontAsset)
-- Will replace many prefabs/entites in SetupTeam_LP that deal with generating the jersey name. Hardcoding values for testing.
local width, height, mips = 3000, 4, 1
local fieldWidth, kerningGap = 1000, 4
local idealScale = 1.81
local texture_id = string.format("playername_%d_%s_%s_%s", initData.UniquePlayerId, initData.FirstName, initData.LastName, getAssetName(fontAsset))
local compositor = createTextureCompositor(texture_id, width, height, mips)
compositor:setIndirectText(fontAsset, initData.JerseyName, fieldWidth, kerningGap, initData.JerseyNameMinCoverage, initData.JerseyNameMaxCoverage, initData.JerseyNameScaleAtMin, idealScale)
return compositor:generateIndirectText()
end
-----------------------------------------------------------------------------
local function bindTorso(initData, shirt_mesh, backplate_mesh, sleeve_mesh, neckpad_mesh, jersey_preset, jersey_sleeve_preset, probowl_patch_normal, backplate_preset, neckpad_preset, backplate_colors, captain_patch, cpatch_colors,
second_patch, jersey_norm, jersey_anim, shoulderpad_preset, namePlateGeneratedMap, degMap, degMask, undershirt_mesh, undershirt_preset, undershirt_colors, torso_normal)
-- Questions: Are we binding materials to meshes that have no use for those materials?
-- How much is this costing in time/resources? Possible optimization?
-- Do all meshes need to update bounding box?
-- TODO: move calculation of JerseyIndirectTexturePlacement from Schematics to Lua
-- LaneId support
local item = createItem("playerTorso", slots.torso, initData.laneId, 5)
if shirt_mesh then
item:addMeshLodPair(lod0, shirt_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_High)
end
if sleeve_mesh then
item:addMeshLodPair(lod0, sleeve_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_High)
end
if backplate_mesh then
item:addMeshLodPair(lod0, backplate_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_High)
end
if neckpad_mesh then
item:addMeshLodPair(lod0, neckpad_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_High)
end
if initData.Vanity and initData.Vanity.UseExtendedVanityData and undershirt_mesh then
item:addMeshLodPair(lod0, undershirt_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder, playerDrawUserSlot_High)
end
--item:reserveMaterials(9)
-----------------------------------------------------------------------------
local addJerseyShaderParams = function(material, initData)
local captainsPatchPalettization = (initData.CaptainPatchPrefix == "CaptainsPatch") and {1, 1, 1, 1} or {0, 0, 0, 0}
local captainPatchLevelVec = {initData.CaptainPatchLevel, initData.CaptainPatchLevel, initData.CaptainPatchLevel, initData.CaptainPatchLevel}
-- presets
material:addPreset(jersey_preset)
--check for composited uniform
-- note Lua converts the bool to a float 0.0 or 1.0 which is why we check for > 0.1
-- need to add check for the handle itself as composited parts can now be mix and matched, this can be negative so we just check for nonzero
if initData.PalletizedUniformData and initData.PalletizedUniformData.IsPalletizedUniform > 0.1 and initData.PalletizedUniformData.PalletizedJerseyColorTextureHandle ~= 0 then
--log("Apply Composited Jersey")
material:addGenTexture("colorTexture", initData.PalletizedUniformData.PalletizedJerseyColorTextureHandle)
material:addGenTexture("RSMTexture", initData.PalletizedUniformData.PalletizedJerseyRSMTextureHandle)
material:addGenTexture("seamPatternNormTexture", initData.PalletizedUniformData.PalletizedJerseySeamNormalTextureHandle)
material:addGenTexture("chestNumbers", initData.PalletizedUniformData.PalletizedChestNumberColorArrayTextureHandle)
material:addGenTexture("backNumbers", initData.PalletizedUniformData.PalletizedBackNumberColorArrayTextureHandle)
material:addGenTexture("shoulderNumbers", initData.PalletizedUniformData.PalletizedShoulderNumberColorArrayTextureHandle)
material:addGenTexture("NameplateFontTexture", initData.PalletizedUniformData.PalletizedNameplateFontColorArrayTextureHandle)
material:addGenTexture("sleeveNumbers", initData.PalletizedUniformData.PalletizedSleeveNumberColorArrayTextureHandle)
end
-- textures
material:addTexture("wrinkleNormTexture", jersey_norm)
material:addTexture("wrinkleNormTextureAnim", jersey_anim)
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
-- vectors
material:addVector("chestNumber_selection", initData.JerseyNumberSplit)
material:addVector("backNumber_selection", initData.JerseyNumberSplit)
material:addVector("shoulderNumber_selection", initData.JerseyNumberSplit)
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout or not initData.vanityItemData) then
material:addVector("chestNumber_spacing", initData.JerseyNumberSpacing)
material:addVector("backNumber_spacing", initData.JerseyNumberSpacing)
material:addVector("shoulderNumber_spacing", initData.JerseyNumberSpacing)
end
if captain_patch then
material:addTexture("patchSampler", captain_patch)
material:addVector("cPatch_enablePalettization", captainsPatchPalettization)
material:addVector("cPatch_starLevel", captainPatchLevelVec)
if cpatch_colors then
material:addVector("cPatchColor1", cpatch_colors.primary)
material:addVector("cPatchColor2", cpatch_colors.secondary)
end
end
if second_patch then
material:addTexture("secondPatchSampler", second_patch)
end
-- swish
material:addVector("swishDynamicBlend", {1, 1, 1, 1} )
material:addVector("sleeveNumber_selection", initData.JerseyNumberSplit)
if probowl_patch_normal then
material:addTexture("ProBowlPatch_Normal", probowl_patch_normal)
end
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout or not initData.vanityItemData) then
material:addVector("sleeveNumber_spacing", initData.JerseyNumberSpacing)
end
end
addJerseyShaderParams(item:addMaterial("jersey_lod0_mat"), initData)
addJerseyShaderParams(item:addMaterial("jersey_lod1_mat"), initData)
addJerseyShaderParams(item:addMaterial("jersey_lod2_mat"), initData)
addJerseyShaderParams(item:addMaterial("jersey_lod3_mat"), initData)
addJerseyShaderParams(item:addMaterial("jersey_lod4_mat"), initData)
-----------------------------------------------------------------------------
local addSleevesShaderParams = function(material)
-- presets
if jersey_sleeve_preset then
material:addPreset(jersey_sleeve_preset)
end
--check for composited uniform
if initData.PalletizedUniformData and initData.PalletizedUniformData.IsPalletizedUniform > 0.1 and initData.PalletizedUniformData.PalletizedJerseyColorTextureHandle ~= 0 then
--log("Apply Composited Sleeves")
material:addGenTexture("colorTexture", initData.PalletizedUniformData.PalletizedJerseyColorTextureHandle)
material:addGenTexture("RSMTexture", initData.PalletizedUniformData.PalletizedJerseyRSMTextureHandle)
material:addGenTexture("seamPatternNormTexture", initData.PalletizedUniformData.PalletizedJerseySeamNormalTextureHandle)
material:addGenTexture("sleeveNumbers", initData.PalletizedUniformData.PalletizedSleeveNumberColorArrayTextureHandle)
end
-- textures
material:addTexture("wrinkleNormTexture", jersey_norm)
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
-- vectors
material:addVector("sleeveNumber_selection", initData.JerseyNumberSplit)
if probowl_patch_normal then
material:addTexture("ProBowlPatch_Normal", probowl_patch_normal)
end
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout or not initData.vanityItemData) then
material:addVector("sleeveNumber_spacing", initData.JerseyNumberSpacing)
end
end
addSleevesShaderParams(item:addMaterial("playerSleeves_lod0_mat"))
addSleevesShaderParams(item:addMaterial("playerSleeves_lod1_mat"))
addSleevesShaderParams(item:addMaterial("playerSleeves_lod2_mat"))
-----------------------------------------------------------------------------
local addBackplateShaderParams = function(material)
-- presets
if backplate_preset then
material:addPreset(backplate_preset)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
-- vectors
if backplate_colors then
material:addVector("primaryColor", backplate_colors.primary)
material:addVector("secondaryColor", backplate_colors.secondary)
material:addVector("tertiaryColor", backplate_colors.tertiary)
material:addVector("quaternaryColor", backplate_colors.quaternary)
end
end
addBackplateShaderParams(item:addMaterial("playerBackplate_lod0_mat"))
addBackplateShaderParams(item:addMaterial("playerBackplate_lod1_mat"))
addBackplateShaderParams(item:addMaterial("playerBackplate_lod2_mat"))
-----------------------------------------------------------------------------
local addNameplateShaderParams = function(material)
if namePlateGeneratedMap then
material:addGenTexture("NameplateIndirectTexture", namePlateGeneratedMap)
material:addGenVector("NameplateIndirectPlacement", namePlateGeneratedMap)
else
material:addGenTexture("NameplateIndirectTexture", initData.JerseyIndirectTextureHandle)
material:addVector("NameplateIndirectPlacement", initData.JerseyIndirectTexturePlacement)
end
end
addNameplateShaderParams(item:addMaterial("jersey_lod0_mat"))
addNameplateShaderParams(item:addMaterial("jersey_lod1_mat"))
addNameplateShaderParams(item:addMaterial("jersey_lod2_mat"))
-----------------------------------------------------------------------------
local addUndershirtShaderParams = function(material)
-- presets
if undershirt_preset then
material:addPreset(undershirt_preset)
end
if undershirt_colors then
material:addVector("primaryColor", undershirt_colors.primary)
material:addVector("secondaryColor", undershirt_colors.secondary)
material:addVector("tertiaryColor", undershirt_colors.tertiary)
material:addVector("quaternaryColor", undershirt_colors.quaternary)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
-- Culling Logic
if initData.vanityItemData then
local maskList = {}
--left armsleeve
if initData.vanityItemData.LeftArmSleeve.isNormal < 0.1 then
maskList[#maskList+1] = initData.vanityItemData.LeftArmSleeve.PartMask
end
maskList[#maskList+1] = initData.vanityItemData.LeftElbow.PartMask
maskList[#maskList+1] = initData.vanityItemData.LeftWrist.PartMask
maskList[#maskList+1] = initData.vanityItemData.LeftHand.PartMask
--right armsleeve
if initData.vanityItemData.RightArmSleeve.isNormal < 0.1 then
maskList[#maskList+1] = convertLeftPartMaskToRight(initData.vanityItemData.RightArmSleeve.PartMask)
end
maskList[#maskList+1] = convertLeftPartMaskToRight(initData.vanityItemData.RightElbow.PartMask)
maskList[#maskList+1] = convertLeftPartMaskToRight(initData.vanityItemData.RightWrist.PartMask)
maskList[#maskList+1] = convertLeftPartMaskToRight(initData.vanityItemData.RightHand.PartMask)
--jersey
maskList[#maskList+1] = initData.vanityItemData.JerseyStyle.PartMask
local fullMask = combineCullingMasks(maskList)
material:addVector("regionMaskValue", fullMask) --temporary disable
end
end
addUndershirtShaderParams(item:addMaterial("playerUpperBodyUnder_lod0_mat"))
addUndershirtShaderParams(item:addMaterial("playerUpperBodyUnder_lod1_mat"))
addUndershirtShaderParams(item:addMaterial("playerUpperBodyUnder_lod2_mat"))
-----------------------------------------------------------------------------
local addTorsoShaderParams = function(material)
-- presets
if undershirt_preset then
material:addPreset(undershirt_preset)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
if torso_normal then
material:addTexture("normalClampTexture", torso_normal)
end
-- Culling Logic
if initData.vanityItemData then
local maskList = {}
maskList[#maskList+1] = initData.vanityItemData.JerseyStyle.PartMask
maskList[#maskList+1] = initData.vanityItemData.Undershirt.PartMask
local fullMask = combineCullingMasks(maskList)
material:addVector("regionMaskValue", fullMask) --temporary disable
end
end
addTorsoShaderParams(item:addMaterial("torsoSkin_lod0_mat"))
addTorsoShaderParams(item:addMaterial("torsoSkin_lod1_mat"))
addTorsoShaderParams(item:addMaterial("torsoSkin_lod2_mat"))
-----------------------------------------------------------------------------
-- shoulderpads are a seperate material inside rolled_jersey and is not its own mesh
local addShoulderpadShaderParams = function(material)
-- presets
if shoulderpad_preset then
material:addPreset(shoulderpad_preset)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
end
addShoulderpadShaderParams(item:addMaterial("playerShoulderpads_lod0_mat"))
addShoulderpadShaderParams(item:addMaterial("playerShoulderpads_lod1_mat"))
addShoulderpadShaderParams(item:addMaterial("playerShoulderpads_lod2_mat"))
return item
end
-----------------------------------------------------------------------------
local function loadTorso(items, generatedTextures, initData)
-- Meshes
local playerTops = {"jersey", "padlessJersey", "practiceJersey"}
local shirt_mesh = nil
local sleeve_mesh = nil
local jersey_preset_name_data = ""
local jersey_preset = nil
local jersey_sleeve_preset = nil
local shoulderpad_preset = nil
local probowl_patch_normal = nil
local captain_patch = ""
local second_patch = ""
local neckpad_mesh = nil
local neckpad_preset = nil
local undershirt_mesh = nil
local undershirt_preset = nil
local torso_normal = nil
local namePlateGeneratedMap = nil
local fontAsset = nil
-- seperated backplate only used in vanity with rolled jersey
local backplate_mesh = nil
local backplate_preset = nil
local backplate_colors = nil
-- we use captain patch colors through the jersey preset and not at all in vanity
local cpatch_colors = nil
local undershirt_colors = nil
-- TODO: Enable this block of code once torso normal maps exist. This code is currently untested.
-- TODO: Refactor indexing into muscleMaps_TorsoNames based on bitmasking.
--[[
local torso_normal_name = muscleMaps_TorsoNames[initData.MuscleType+1] --lua indices start at 1 and not 0
if torso_normal_name == "" then
local gut_barycentric = initData.GutBarycentric
local gut_base = initData.GutBase
torso_normal_name = muscleMaps_TorsoNames[2]
if gut_barycentric > 1.5 and gut_barycentric < 2.5 and gut_base > 0.5 then
torso_normal_name = muscleMaps_TorsoNames[3]
elseif gut_barycentric > 0.5 and gut_barycentric < 1.5 and gut_base > 0.5 then
torso_normal_name = muscleMaps_TorsoNames[4]
end
end
torso_normal = loadAsync(brts.legs, torso_normal_name, true)
]]
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout) then
-- Jersey ........................................................................................
-- this fallback setup iss used for gen5 merged jersey sleeves. If the merged model isn't found we fall back to g4. We are making this change universally to prevent needing to diverge this script
-- for example, jersey_metamorph + sleeve_long_metamorph in g4 would load as jersey_sleeve_long_metamorph
local shirt_mesh_name = string.format("%s_%s_metamorph;%s_metamorph", playerTops[initData.PlayerTop + 1], initData.JerseySleeve, playerTops[initData.PlayerTop + 1])
shirt_mesh = loadAsync(brts.gear, shirt_mesh_name)
-- for the same reason as stated above, this is allowed to be missing for g5
local sleeve_mesh_name = string.format("%s_metamorph", initData.JerseySleeve)
sleeve_mesh = loadAsync(brts.gear, sleeve_mesh_name, true)
-- Presets
-- Override for QB Practice jerseys
jersey_preset_name_data = (initData.BreathRite == "QB" and initData.PlayerTop == 2) and
initData.JerseyPreset .. "_QB" or initData.JerseyPreset
local jersey_preset_name = string.format("%s_swish_preset;%s_preset;FALLBACK_jersey_preset", jersey_preset_name_data, jersey_preset_name_data)
jersey_preset = loadAsync(brts.presets, jersey_preset_name)
local jersey_sleeve_preset_name = string.format("%s_Sleeves_preset;FALLBACK_jersey_Sleeves_preset", jersey_preset_name_data)
jersey_sleeve_preset = loadAsync(brts.presets, jersey_sleeve_preset_name)
local captain_patch_name = string.format("%s%s%s;invisible_color", initData.CaptainPatchPrefix, initData.CaptainPatchMiddle, initData.CaptainPatchSuffix)
captain_patch = loadAsync(brts.gear, captain_patch_name)
local second_patch_name = string.format("%s;invisible_color", initData.SecondaryPatch)
-- NARRATIVE HACK
if initData.HatType then
if initData.HatType == 370 or initData.HatType == 400 or initData.HatType == 410 then
second_patch_name = "NCAA_Decal_2019_BLACK"
elseif initData.HatType == 520 then
second_patch_name = "NCAA_Decal_2020_BLACK"
end
end
second_patch = loadAsync(brts.gear, second_patch_name)
local neckpad_mesh_name = string.format("%s_%s", initData.Neckpad, initData.ApproxBodyType)
neckpad_mesh = loadAsync(brts.gear, neckpad_mesh_name, true)
if not (initData.SecondaryPatch == "") then
local probowl_patch_normal_name = string.format("%s_normal;invisible_color", initData.SecondaryPatch)
probowl_patch_normal = loadAsync(brts.uniform, probowl_patch_normal_name, false)
end
--nameplate texture
if initData.JerseyIndirectTextureHandle == 0 then
-- Composite the nameplate
local font_name = string.format("%s;EAG_Jersey_2012_GRE_Name_COL", initData.JerseyFontName)
fontAsset = loadAsync(brts.uniform, font_name)
namePlateGeneratedMap = futureCall(compositeNamePlate, initData, fontAsset)
generatedTextures[#generatedTextures + 1] = namePlateGeneratedMap
end
else
-- Vanity Items ..................................................................................
local shirt_item_model = initData.vanityItemData.JerseyStyle.Model
local shirt_item_mat = initData.vanityItemData.UniformJersey.Material
local sleeve_item_model = initData.vanityItemData.JerseySleeves.Model
local undershirt_item_model = initData.vanityItemData.Undershirt.Model
local undershirt_item_mat = initData.vanityItemData.Undershirt.Material
local shoulderpad_item_mat = "" --initData.vanityItemData.UniformJersey.Material
local neckpad_item_model = initData.vanityItemData.Neckpad.Model
local neckpad_item_mat = initData.vanityItemData.Neckpad.Material
undershirt_colors = resolveVanityColors(initData, initData.vanityItemData.Undershirt)
-- Jersey ........................................................................................
local shirt_mesh_name = string.format("%s_metamorph", shirt_item_model)
shirt_mesh = loadAsync(brts.vanityGear, shirt_mesh_name)
local sleeve_mesh_name = string.format("%s_metamorph", sleeve_item_model)
sleeve_mesh = loadAsync(brts.vanityGear, sleeve_mesh_name, true)
-- Presets
local jersey_preset_name = string.format("%s_preset_pro;%s_preset;%s;FALLBACK_jersey_preset", shirt_item_mat, shirt_item_mat, shirt_item_mat)
jersey_preset = loadAsync(brts.vanityGear, jersey_preset_name)
local jersey_sleeve_preset_name = string.format("%s_Sleeves_preset_pro;%s_Sleeves_preset;FALLBACK_jersey_Sleeves_preset", shirt_item_mat, shirt_item_mat)
jersey_sleeve_preset = loadAsync(brts.vanityGear, jersey_sleeve_preset_name)
local captain_patch_name = "" --string.format("%s%s%s;invisible_color", initData.CaptainPatchPrefix, initData.CaptainPatchMiddle, initData.CaptainPatchSuffix)
captain_patch = loadAsync(brts.vanityGear, captain_patch_name, true)
local second_patch_name = "" --string.format("%s;invisible_color", initData.SecondaryPatch)
second_patch = loadAsync(brts.vanityGear, second_patch_name, true)
local shoulderpad_preset_name = string.format("%s_preset;v_Jersey_Rolled_jerseyGear_preset", shoulderpad_item_mat)
shoulderpad_preset = loadAsync(brts.vanityGear, shoulderpad_preset_name, true)
-- Undershirt / Upper Base Layer .....................................................................
local undershirt_preset_name = string.format("%s_preset;FALLBACK_jersey_preset", undershirt_item_mat)
if undershirt_item_model == "v_Torso" then
-- this shouldn't be necessary and i cannot actually repro the issue in the bug but there are some bugs
-- claiming belly clipping still occuring, so disabling torso with certain jersey styles
if shirt_item_model == "v_Jersey_Tucked" or shirt_item_model == "v_Jersey_Untucked" then
undershirt_item_model = "None"
end
local torso_normal_name = v_MuscleMaps_torsoNames[initData.MuscleType+1]
torso_normal = loadAsync(brts.vanityGear, torso_normal_name, true)
undershirt_preset_name = string.format("vanity_torsoskin_ST%s_preset;vanity_torsoskin_ST3_preset", initData.SkinTone)
end
local undershirt_mesh_name = string.format("%s_metamorph", undershirt_item_model)
log(undershirt_mesh_name)
undershirt_mesh = loadAsync(brts.vanityGear, undershirt_mesh_name, true)
undershirt_preset = loadAsync(brts.vanityGear, undershirt_preset_name, true)
local neckpad_mesh_name = string.format("%s_%s", neckpad_item_model, initData.ApproxBodyType)
neckpad_mesh = loadAsync(brts.vanityGear, neckpad_mesh_name, true)
local backplate_mesh_name = ""
local backplate_preset_name = ""
-- Exposed Backplate .................................................................................
-- TODO add field to jersey style for exposed backplate so we don't have to match based on model name
if shirt_item_model == "v_Jersey_Rolled" and initData.vanityItemData.Backplate and initData.vanityItemData.Backplate.Model ~= "" then
backplate_colors = resolveVanityColors(initData, initData.vanityItemData.Backplate)
backplate_mesh_name = string.format("%s_metamorph", initData.vanityItemData.Backplate.Model)
backplate_mesh = loadAsync(brts.vanityGear, backplate_mesh_name, true)
backplate_preset_name = string.format("%s_preset", initData.vanityItemData.Backplate.Material)
backplate_preset = loadAsync(brts.vanityGear, backplate_preset_name, true)
end
--nameplate texture
if initData.JerseyIndirectTextureHandle == 0 then
-- Composite the nameplate
local font_name = string.format("%s;EAG_Jersey_2012_GRE_Name_COL", initData.vanityItemData.UniformJersey.NameplateTexture)
fontAsset = loadAsync(brts.uniform, font_name)
namePlateGeneratedMap = futureCall(compositeNamePlate, initData, fontAsset)
generatedTextures[#generatedTextures + 1] = namePlateGeneratedMap
end
end
-- Common Textures ...............................................................................
local jerseyWrinkleTypes = {"JerseyWrinkles", "PadlessJersey_Wrinkles", "JerseyWrinkles"}
local jerseyWrinkleType = jerseyWrinkleTypes[initData.PlayerTop + 1]
local jersey_norm_name = string.format("%s_%s;%s_%s;%s_%s;%s_D",
jerseyWrinkleType, initData.FlakJacket,
jerseyWrinkleType, initData.Backplate,
jerseyWrinkleType, initData.ApproxBodyType,
jerseyWrinkleType)
local jersey_norm = loadAsync(brts.gear, jersey_norm_name)
local jersey_anim_name = string.format("%s_%s_anim;%s_%s_anim;%s_%s_anim;%s_D_anim",
jerseyWrinkleType, initData.FlakJacket,
jerseyWrinkleType, initData.Backplate,
jerseyWrinkleType, initData.ApproxBodyType,
jerseyWrinkleType)
local jersey_anim = loadAsync(brts.gear, jersey_anim_name)
items[#items + 1] = futureCall(bindTorso, initData, shirt_mesh, backplate_mesh, sleeve_mesh, neckpad_mesh, jersey_preset, jersey_sleeve_preset, probowl_patch_normal,
backplate_preset, neckpad_preset, backplate_colors, captain_patch, cpatch_colors, second_patch, jersey_norm, jersey_anim,
shoulderpad_preset, namePlateGeneratedMap, initData.commonAssets.degMap, initData.commonAssets.degMask, undershirt_mesh, undershirt_preset,
undershirt_colors, torso_normal)
end
-----------------------------------------------------------------------------
local function bindHandGear(side, initData, handgear, handgear_mesh, handgear_preset, hand_colors, degMap, degMask)
local item_name = string.format("playerHandGear%s", side.prefix)
local item = createItem(item_name, handgear.slot, initData.laneId, 1)
if handgear_mesh then
item:addMeshLodPair(lod0, handgear_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
end
local addShaderParams = function(material)
-- presets
if handgear_preset then
material:addPreset(handgear_preset)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
-- vectors
if hand_colors then
material:addVector("primaryColor", hand_colors.primary)
material:addVector("secondaryColor", hand_colors.secondary)
material:addVector("tertiaryColor", hand_colors.tertiary)
material:addVector("quaternaryColor", hand_colors.quaternary)
end
end
item:reserveMaterials(3)
addShaderParams(item:addMaterial(string.format("playerGlove%s_lod0_mat", side.prefix)))
addShaderParams(item:addMaterial(string.format("playerGlove%s_lod1_mat", side.prefix)))
addShaderParams(item:addMaterial(string.format("playerGlove%s_lod2_mat", side.prefix)))
return item
end
-----------------------------------------------------------------------------
local function loadHandGear(side, items, initData)
local handgear_mesh = nil
local handgear_preset = nil
local handgear = {
slot = isLeft(side) and slots.handgearL or slots.handgearR,
model = isLeft(side) and initData.LeftHandModel or initData.RightHandModel,
material = isLeft(side) and initData.LeftHandMaterial or initData.RightHandMaterial,
palette = isLeft(side) and initData.LeftHandPalette or initData.RightHandPalette,
loadoutAsset = nil,
loadoutOverrides = nil,
}
local hand_colors = nil
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout) then
hand_colors = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
local mesh_name = string.format("%s%s_metamorph", handgear.model, side.prefix)
local preset_name = string.format("%s%s_%s_preset;%s%s_preset;%s_preset;player_missing_preset",
handgear.model, handgear.material, handgear.palette,
handgear.model, handgear.material,
handgear.model)
handgear_mesh = loadAsync(brts.armgear, mesh_name, AllowMissing)
handgear_preset = loadAsync(brts.presets, preset_name)
else
local hand_side = isLeft(side) and "LeftHand" or "RightHand"
hand_colors = resolveVanityColors(initData, initData.vanityItemData[hand_side])
local mesh_name = string.format("%s%s_metamorph", initData.vanityItemData[hand_side].Model, side.prefix)
local preset_name = string.format("%s_preset;%s_preset", initData.vanityItemData[hand_side].Material, initData.vanityItemData[hand_side].Model)
handgear_mesh = loadAsync(brts.vanityGear, mesh_name, allowEmptyMissing(mesh_name))
handgear_preset = loadAsync(brts.vanityGear, preset_name, allowEmptyMissing(preset_name))
end
items[#items + 1] = futureCall(bindHandGear, side, initData, handgear, handgear_mesh, handgear_preset, hand_colors,
initData.commonAssets.degMap, initData.commonAssets.degMask)
end
-----------------------------------------------------------------------------
local function bindShoe(side, initData, shoe, shoe_mesh, shoe_preset, spats_preset, shoe_colors, spats_colors, degMap, degMask)
local item_name = string.format("playerShoe%s", side.prefix)
local item = createItem(item_name, shoe.slot, initData.laneId, 1)
if shoe_mesh then
item:addMeshLodPair(lod0, shoe_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
end
local addShaderParams = function(material)
-- presets
if shoe_preset then
material:addPreset(shoe_preset)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
-- vectors
if shoe_colors then
material:addVector("primaryColor", shoe_colors.primary)
material:addVector("secondaryColor", shoe_colors.secondary)
material:addVector("tertiaryColor", shoe_colors.tertiary)
material:addVector("quaternaryColor", shoe_colors.quaternary)
end
end
local spat_materials = {
["Black"] = {0.015, 0.015, 0.015, 1.0}, -- on the 0-255 scale, this is roughly 4
["White"] = {0.92156, 0.92156, 0.92156, 1.0}, -- on the 0-255 scale, this is 235
["TeamColor"] = initData.UniformPrimaryColor,
["SecondaryColor"] = initData.UniformSecondaryColor
}
local addSpatShaderParams = function(material)
--reuse preset logic for spats since the whole model uses one material
addShaderParams(material)
if not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout then
-- NFL
material:addVector("comboColor", spat_materials[shoe.spatmaterial] or spat_materials["White"])
elseif spats_color then
-- Vanity
material:addVector("comboColor", spats_colors.primary)
else
--Vanity Fallback
material:addVector("comboColor", spat_materials["White"])
end
end
item:reserveMaterials(6)
addShaderParams(item:addMaterial(string.format("playerShoe%s_lod0_mat", side.prefix)))
addShaderParams(item:addMaterial(string.format("playerShoe%s_lod1_mat", side.prefix)))
addShaderParams(item:addMaterial(string.format("playerShoe%s_lod2_mat", side.prefix)))
addSpatShaderParams(item:addMaterial(string.format("playerSpat%s_lod0_mat", side.prefix)))
addSpatShaderParams(item:addMaterial(string.format("playerSpat%s_lod1_mat", side.prefix)))
addSpatShaderParams(item:addMaterial(string.format("playerSpat%s_lod2_mat", side.prefix)))
-- vanity thin spats using incorrect material name, just going to accept
addSpatShaderParams(item:addMaterial(string.format("playerSpats%s_lod0_mat", side.prefix)))
addSpatShaderParams(item:addMaterial(string.format("playerSpats%s_lod1_mat", side.prefix)))
addSpatShaderParams(item:addMaterial(string.format("playerSpats%s_lod2_mat", side.prefix)))
return item
end
-----------------------------------------------------------------------------
local function loadShoe(side, items, initData)
local shoe_mesh = nil
local shoe_preset = nil
local spats_preset = nil -- currently unused as material is not seperated for shoes but in the future custom spat shaders might be supported
local shoe_colors = nil
local spats_colors = nil
local shoe = {
slot = isLeft(side) and slots.shoeL or slots.shoeR,
model = isLeft(side) and initData.LeftShoeModel or initData.RightShoeModel,
material = isLeft(side) and initData.LeftShoeMaterial or initData.RightShoeMaterial,
spatmaterial = isLeft(side) and initData.LeftSpatMaterial or initData.RightSpatMaterial,
palette = isLeft(side) and initData.LeftShoePalette or initData.RightShoePalette,
loadoutAsset = nil,
loadoutOverrides = nil,
}
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout) then
shoe_colors = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
local shoeModelTemp = shoe.model
local shoePresetTemp = shoe.material
if string.lower(initData.UniqueHeadName) == "kaepernickcolin_10578" then
shoeModelTemp = "shoe_low_NikeVaporEdge99Club"
end
local mesh_name = string.format("%s%s_metamorph;shoe_Mid_NikeLunarBeast%s_metamorph",
shoe.model, side.prefix,
side.prefix)
local material_var = ""
if initData.ShoesPreset then
material_var = initData.ShoesPreset:match("_[A-Za-z]*$"):lower()
end
if string.lower(initData.UniqueHeadName) == "kaepernickcolin_10578" then
shoeModelTemp = "shoe_low_NikeVaporEdge_BLMKaepernick"
shoePresetTemp = ""
end
local preset_name = string.format("%s%s%s_preset;%s%s_preset",
shoe.model, shoe.material, material_var,
shoe.model, shoe.material)
shoe_mesh = loadAsync(brts.gear, mesh_name, AllowMissing)
shoe_preset = loadAsync(brts.presets, preset_name, AllowMissing)
else
local shoe_side = isLeft(side) and "LeftShoe" or "RightShoe"
local spats_side = "LeftSpat"
--spats_side = isLeft(side) and "LeftSpat" or "RightSpat" --only use Left side for spats as we do not support indepedendent spat selection, uncomment this to enable per-side behavior
shoe_colors = resolveVanityColors(initData, initData.vanityItemData[shoe_side])
spats_colors = resolveVanityColors(initData, initData.vanityItemData[spats_side])
local spats_model = initData.vanityItemData[spats_side].Model
local mesh_name = string.format("%s%s%s_metamorph", initData.vanityItemData[shoe_side].Model, spats_model, side.prefix)
local preset_name = string.format("%s%s%s_preset;%s%s_preset;%s_preset", initData.vanityItemData[shoe_side].Material, spats_model, side.prefix, initData.vanityItemData[shoe_side].Model, side.prefix, initData.vanityItemData[shoe_side].Material)
shoe_mesh = loadAsync(brts.vanityGear, mesh_name, AllowMissing)
shoe_preset = loadAsync(brts.vanityGear, preset_name, AllowMissing)
--spats_preset = loadAsync(brts.vanityGear, spats_preset_name, true)
end
items[#items + 1] = futureCall(bindShoe, side, initData, shoe, shoe_mesh, shoe_preset, spats_preset, shoe_colors, spats_colors,
initData.commonAssets.degMap, initData.commonAssets.degMask)
end
-----------------------------------------------------------------------------
local function bindWristGear(side, initData, wristgear, wristgear_mesh, wristgear_preset, wrist_colors, degMap, degMask)
local item_name = string.format("playerWristGear%s", side.prefix)
local item = createItem(item_name, wristgear.slot, initData.laneId, 1)
if wristgear_mesh then
item:addMeshLodPair(lod0, wristgear_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
end
local addShaderParams = function(material)
-- presets
if wristgear_preset then
material:addPreset(wristgear_preset)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
-- vectors
if wrist_colors then
material:addVector("primaryColor", wrist_colors.primary)
material:addVector("secondaryColor", wrist_colors.secondary)
material:addVector("tertiaryColor", wrist_colors.tertiary)
material:addVector("quaternaryColor", wrist_colors.quaternary)
end
end
item:reserveMaterials(3)
addShaderParams(item:addMaterial(string.format("playerWrist%s_lod0_mat", side.prefix)))
addShaderParams(item:addMaterial(string.format("playerWrist%s_lod1_mat", side.prefix)))
addShaderParams(item:addMaterial(string.format("playerWrist%s_lod2_mat", side.prefix)))
return item
end
-----------------------------------------------------------------------------
local function loadWristGear(side, items, initData)
local wristgear_mesh = nil
local wristgear_preset = nil
local wristgear = {
slot = isLeft(side) and slots.wristgearL or slots.wristgearR,
model = isLeft(side) and initData.LeftWristModel or initData.RightWristModel,
material = isLeft(side) and initData.LeftWristMaterial or initData.RightWristMaterial,
loadoutAsset = nil,
loadoutOverrides = nil,
}
local wrist_colors = nil
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout) then
wrist_colors = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
local mesh_name = string.format("%s%s_metamorph;wrist%s_metamorph", wristgear.model, side.prefix, side.prefix)
local preset_name = string.format("%s_%s_preset;%s_preset;player_missing_preset",
wristgear.model, wristgear.material,
wristgear.model)
wristgear_mesh = loadAsync(brts.armgear, mesh_name, AllowMissing)
wristgear_preset = loadAsync(brts.presets, preset_name)
else
local wrist_side = isLeft(side) and "LeftWrist" or "RightWrist"
wrist_colors = resolveVanityColors(initData, initData.vanityItemData[wrist_side])
local mesh_name = string.format("%s%s_metamorph", initData.vanityItemData[wrist_side].Model, side.prefix)
local preset_name = string.format("%s%s_preset;%s%s_preset", initData.vanityItemData[wrist_side].Material, side.prefix, initData.vanityItemData[wrist_side].Model, side.prefix)
wristgear_mesh = loadAsync(brts.vanityGear, mesh_name, AllowMissing)
wristgear_preset = loadAsync(brts.vanityGear, preset_name, AllowMissing)
end
items[#items + 1] = futureCall(bindWristGear, side, initData, wristgear, wristgear_mesh, wristgear_preset, wrist_colors,
initData.commonAssets.degMap, initData.commonAssets.degMask)
end
-----------------------------------------------------------------------------
local function bindMouthpiece(initData, mouthpiece_mesh, mouthpiece_preset, mouthpiece_colors, degMap, degMask)
local item = createItem("playerMouthpiece", slots.mouthpiece, initData.laneId, 1)
item:setIncludeCullTagHashes("Mouthpiece")
local addShaderParams = function(material)
-- presets
if mouthpiece_preset then
material:addPreset(mouthpiece_preset)
end
-- degradation
addDegShaderParams(material, initData, degMap, degMask)
-- palettization
if mouthpiece_colors then
material:addVector("primaryColor", mouthpiece_colors.primary)
material:addVector("secondaryColor", mouthpiece_colors.secondary)
material:addVector("tertiaryColor", mouthpiece_colors.tertiary)
material:addVector("quaternaryColor", mouthpiece_colors.quaternary)
end
end
--Mesh
if mouthpiece_mesh then
item:addMeshLodPair(lod0, mouthpiece_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
item:reserveMaterials(3)
addShaderParams(item:addMaterial("mouthpiece_lod0_mat"))
addShaderParams(item:addMaterial("mouthpiece_lod1_mat"))
addShaderParams(item:addMaterial("mouthpiece_lod2_mat"))
end
return item
end
-----------------------------------------------------------------------------
local function loadMouthpiece(items, initData)
local mouthpiece_mesh = nil
local mouthpiece_preset = nil
local mouthpiece_colors = nil
if (not initData.Vanity or not initData.Vanity.VanityOnFieldLoadout) then
mouthpiece_colors = {
primary = initData.UniformPrimaryColor,
secondary = initData.UniformSecondaryColor,
tertiary = initData.UniformTertiaryColor,
quaternary = initData.UniformSecondaryColor,
}
local mesh_name = string.format("mouthpiece_%s", initData.MouthpieceModel)
local preset_name = string.format("mouthpiece_%s%s_preset", initData.MouthpieceModel, initData.MouthpieceMaterial)
mouthpiece_mesh = loadAsync(brts.headgear, mesh_name, true) --block mouthpieces in NFL on request
mouthpiece_preset = loadAsync(brts.headgear, preset_name, true)
else
mouthpiece_colors = resolveVanityColors(initData, initData.vanityItemData.Mouthpiece)
local mouthpiece_model = initData.vanityItemData.Mouthpiece.Model
local mouthpiece_material = initData.vanityItemData.Mouthpiece.Material
local mesh_name = string.format("%s", mouthpiece_model)
local preset_name = string.format("%s_preset; mouthpiece_preset", mouthpiece_material)
mouthpiece_mesh = loadAsync(brts.vanityGear, mesh_name, true)
mouthpiece_preset = loadAsync(brts.vanityGear, preset_name, true)
end
items[#items + 1] = futureCall(bindMouthpiece, initData, mouthpiece_mesh, mouthpiece_preset, mouthpiece_colors,
initData.commonAssets.degMap, initData.commonAssets.degMask)
end
-----------------------------------------------------------------------------
local function bindShadow(shadow_mesh, shadowRtw_mesh, laneId)
local item = createItem("playerShadow", slots.shadow, laneId, 2)
item:addMeshLodPair(lod0, shadow_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
if shadowRtw_mesh then
item:addMeshLodPair(lod0, shadowRtw_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
end
return item
end
-----------------------------------------------------------------------------
local function loadShadow(items, initData)
local shadow_mesh = loadAsync(brts.shadow, "playerShadow")
local shadowRtw_mesh = loadAsync(brts.shadow, "playerShadow_rtwImportance", true)
items[#items + 1] = futureCall(bindShadow, shadow_mesh, shadowRtw_mesh, initData.laneId)
end
-----------------------------------------------------------------------------
local function bindZOnly(zonly_mesh, laneId)
local item = createItem("PlayerZOnly", slots.zonly, laneId, 1)
item:addMeshLodPair(lod0, zonly_mesh, updateBoundingBox, playerDrawOrder, playerDrawSubOrder)
return item
end
-----------------------------------------------------------------------------
local function loadZOnly(items, initData)
local zonly_mesh = loadAsync(brts.zonly, "MeshCombineZOnly")
items[#items + 1] = futureCall(bindZOnly, zonly_mesh, initData.laneId)
end
-- ===========================================================================================================================================================
-- BODY LOGIC
function LoadPlayer(initData, laneId)
local items = {}
local generatedTextures = {}
local assets = {}
log("Start LoadPlayer: " .. initData.JerseyName .. " (index: " .. initData.RosterIndex .. ", lane: " .. laneId .. ")")
-- Debug use, see
-- https://confluence.ea.com/pages/viewpage.action?spaceKey=madden&title=Football+DB+Messaging+-+aka+Roster+and+Appearance+Tweaker
if initData.vanityItemData and initData.vanityItemData.Info then
log('Vanity requests: ' .. initData.vanityItemData.requestedVanityItems .. ' # Resolved: ' .. initData.vanityItemData.resolvedVanityItems .. " for " .. initData.vanityItemData.Info)
else
log("No Vanity Found for " .. initData.JerseyName .. " (index: " .. initData.RosterIndex .. ")")
end
--log_table(initData.vanityItemData)
initData.laneId = laneId
initData.commonAssets = loadCommonAssets(initData)
--log("VANITY DEBUG TABLE")
--log_table(initData)
if DrawEnabled("Hair", initData) then
-- EA_TODO: This is placeholder logic. We actually want to eventually load both assets. For now, just load the strand hair if it exists and is enabled.
if SETTING_EnableStrandHair then
loadStrandHair(items, initData)
end
loadHair(items, initData)
end
if DrawEnabled("Head", initData) then
loadHead(items, initData)
end
if DrawEnabled("HeadGear", initData) then
loadHeadGear(items, initData)
end
if DrawEnabled("Pants", initData) then
loadPants(items, initData)
end
if DrawEnabled("Legs", initData) then
loadLegs(items, initData)
end
if DrawEnabled("Torso", initData) then
loadTorso(items, generatedTextures, initData)
end
if DrawEnabled("Arms", initData) then
loadArms(items, initData)
end
if DrawEnabled("LeftElbow", initData) then
loadElbowGear(LeftSide, items, initData)
end
if DrawEnabled("RightElbow", initData) then
loadElbowGear(RightSide, items, initData)
end
if DrawEnabled("LeftHandGear", initData) then
loadHandGear(LeftSide, items, initData)
end
if DrawEnabled("RightHandGear", initData) then
loadHandGear(RightSide, items, initData)
end
if DrawEnabled("LeftShoe", initData) then
loadShoe(LeftSide, items, initData)
end
if DrawEnabled("RightShoe", initData) then
loadShoe(RightSide, items, initData)
end
if DrawEnabled("LeftWrist", initData) then
loadWristGear(LeftSide, items, initData)
end
if DrawEnabled("RightWrist", initData) then
loadWristGear(RightSide, items, initData)
end
if DrawEnabled("Mouthpiece", initData) then
loadMouthpiece(items, initData)
end
if DrawEnabled("Shadow", initData) then
loadShadow(items, initData)
end
if DrawEnabled("ZOnly", initData) then
loadZOnly(items, initData)
end
log("End LoadPlayer: " .. initData.JerseyName .. " (index: " .. initData.RosterIndex .. ")")
return items, generatedTextures, assets
end
function PrintGlobal()
log("Lua _G contents start:")
for n in pairs(_G) do log(n) end
log("Lua _G contents end")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment