MGSV Modding Wiki

View My GitHub Profile

Custom Outfits


Contents Contents:
  1. Functions
  2. RegisterOutfit
    1. Branch fields
    2. Head options
    3. Iris colour
    4. Colours
    5. Variants
    6. Camo bonus
    7. Abilities
    8. Outfit motion
    9. Outfit voice
    10. Outfit R&D row
  3. RegisterHeadOption
    1. Head fields
    2. Branches
    3. Head motion
    4. Head abilities
    5. Face layers (DD soldiers)
    6. Face stages (Snake only)
    7. Head R&D row
  4. ExtendVanillaOutfit
    1. Select the vanilla suit
    2. Vanilla-outfit branch fields
    3. Vanilla-outfit variant fields
  5. Minimal complete example
  6. See also

A custom outfit is a body model (.parts) and package (.fpk), with optional camo, voice, face, head, and variant assets.

Place all calls inside this.LoadLibraries().

Functions

Function Description
V_Player.RegisterOutfit Create a new uniform.
V_Player.RegisterHeadOption Create a new custom head.
V_Player.ExtendVanillaOutfit Add variants or heads to an existing vanilla outfit.
V_TppMotherBaseManagement.AddToEquipDevelopTable R&D name, icon, grade, cost, and unlock state.
V_Player.GetOutfitInfo Read back the ids assigned to an outfit you registered.
V_Player.GetHeadOptionSlot Read back the vars.playerFaceEquipId value a custom head wears under.

IDs are assigned automatically and saved under each registration key.

Most *Fpk and *Fv2 fields take a path, true for vanilla, or false to disable the asset.

RegisterOutfit needs an AddToEquipDevelopTable row with the same key.


RegisterOutfit

V_Player.RegisterOutfit({
  key = "MyMod:MySuit",

  ddFemale = {
    partsPath = "/Assets/.../body.parts",
    fpkPath   = "/Assets/.../body.fpk",
  },
})

Returns partsType, developId, flowIndex, or false.

Field Required Purpose
key Yes Registration key.
snake, avatar, ddMale, ddFemale, ocelot, quiet At least one Per-character branch.

Branch fields

Field Required Purpose
partsPath Yes Body model.
fpkPath Yes Its package. Not installed: the vanilla suit is worn.
camoFpk, camoFv2 No (none) Camo. camoFpk not installed: no camo.
diamondFpk, diamondFv2 No (none) Diamond Dogs emblem or overlay. diamondFpk not installed: neither is used.
voiceFpk, voiceType No (vanilla) Outfit voice.
faceFpk, skinFv2 No (vanilla) Face and skin.
iconFtexPath No (R&D icon) Suit-list icon.
displayName No (R&D name) Outfit-cell label.
enableArm No (true) Keep Snake or Avatar’s bionic arm. Always off on ddMale and ddFemale.
enableHead No (true) Keep the character head.
eyeFv2, eyeColor No (none) Iris colour on the outfit’s body.
headOptions No (none) Selectable heads. Max 120.
colors No (none) Colours for the Sortie Prep colour palette.
variants No (none) Alternative looks you cycle through. Max 254.
camoBonusType No (none) Use a vanilla camo’s concealment.
camoBonusValues No (none) Own concealment per material.
abilities No (none) Abilities while worn.
motionMtars No (vanilla) Replacement player motion archives.

Head options

Each headOptions entry is a raw equip ID, a custom head key, or one of these vanilla heads:

none, bandana, infinitebandana, balaclava, spheadgear, hpheadgear
headOptions = { "balaclava", "MyMod:MyHead" },

Iris colour

eyeFv2 is an fv2 with an iris group (id 110, one unit per iris), packed with the outfit. DD staff then keep their own iris colour on the outfit; eyeColor = n (0-31) shows unit n instead, for every character, and false turns the iris off.

ddMale = {
  -- partsPath, fpkPath ...
  eyeFv2 = "/Assets/tpp/fova/chara/sna/sna4_plym0_def_v00.fv2",
},

eyeFv2 may hold only the iris group, plus the skin group (id 100) on DD soldiers, who get their own skin tone. The body needs the eye material of the DD player bodies. Vanilla’s sna4_plym0_def_v00.fv2 works as eyeFv2.

Colours

In Sortie Prep, press Triangle (Y) on the uniform to open the colour palette. The picked colour’s fv2 is applied over the outfit and saved per outfit, character and channel. The second channel goes on top of the first, so give the channels different materials. A variant’s colors replace the branch’s.

colors = {
  primary = {
    { fv2 = "/Assets/tpp/fova/mymod/olive.fv2", icon = "/Assets/tpp/ui/texture/mymod/olive.ftex" },
  },
  secondary = { count = 12, fv2 = "/Assets/tpp/fova/mymod/trim_%02d.fv2" },
},
Field Required Purpose
primary, secondary At least one Colour channels, one palette tab each. Max 1024 colours.
fv2 Yes Applied when picked. Must be in a loaded package: the outfit’s, camoFpk or the colour’s fpk.
fpk No (none) Package with the fv2 and its textures, loaded as the camo package. Not installed: the colour isn’t applied.
icon No (empty swatch) Swatch picture.
count No (none) Builds count colours from fields with one %d (or %02d), numbered from 0.

Read or pick colours from Lua: outfit colours.

Variants

variants = {
  {
    partsPath   = "/Assets/tpp/parts/chara/mymod/body_alt.parts",
    fpkPath     = "/Assets/tpp/pack/mymod/body_alt.fpk",
    displayName = "staff_name_99_052",
    default     = true,
  },
},

All variant fields are optional.

Field Default Purpose
partsPath, fpkPath base model Variant model and package.
camoFpk, camoFv2, diamondFpk, diamondFv2 none Variant camo and emblem. An *Fpk not installed: its pair is not used.
voiceFpk, voiceType branch’s Variant voice.
displayName none Variant label on the cycle button.
iconFtexPath branch’s Suit-list icon.
default false true makes this the initial variant.
enableArm, enableHead branch’s Override the branch values.
eyeFv2, eyeColor branch’s This variant’s iris.
headOptions none This variant’s heads.
colors branch’s This variant’s colours.
motionMtars branch’s Motion while this variant is worn.

Camo bonus

camoBonusType takes a vanilla camo name (playerCamoTypes in player2_camouf_param.lua) or a number 0-116:

camoBonusType = "TIGERSTRIPE",

camoBonusValues takes one value per material. Keys are MTR_* names (materialTypes in player2_camouf_param.lua) or 1-82. Materials left out are 0:

camoBonusValues = {
  MTR_LEAF   = 90,
  MTR_SOIL_A = 60,
  MTR_CONC_A = 15,
},

Use one or the other. With both, camoBonusType wins.

Abilities

abilities = {
  quietMovement = true,
  defense       = 4,
  rattleSuit    = "snk",
},

All ability fields are optional.

Field Type (default) Effect
quietMovement boolean (false) Move like Quiet.
silentFootsteps boolean (false) Footsteps one level quieter.
sprintSpeed number (suit’s own) Sprint speed, 0.1-10. Ninja suit 1.3, Raiden suit 1.5.
raidenRun boolean (false) Raiden’s sprint animation.
dashAttack boolean or TppDamage.ATK_* (false) Sprinting into an enemy knocks them down, as with the Ninja and Raiden suits. An ATK_ id hits with that attack instead.
sprintSound boolean (false) The Ninja and Raiden sprint sound.
sprintSpark string (none) .vfx at each sprinting footstep, packed with the outfit. Raiden’s: /Assets/tpp/effect/vfx_data/chara/fx_tpp_chrfotspk01_s5.vfx.
defense number 0-9 (0, off) Damage reduction.
lifeRecovery number 0-9 (0, off) Health regeneration rate.
rattleSuit string or number ("nom") Cloth-rustle sound: "nom", "bony", "snk", "amr".
damageSe string (vanilla) Sound when hit: "battledress" (Battle Dress) or "default".

Outfit motion

Name a player motion archive in motionMtars to replace it while the outfit is worn. Archives you leave out stay vanilla.

motionMtars = {
  cqc  = "/Assets/tpp/motion/mtar/mymod/mysuit_cqc.mtar",
  jump = "/Assets/tpp/motion/mtar/mymod/mysuit_jump.mtar",
},

Keys are the archive filenames in /Assets/tpp/motion/mtar/player2/, without the player2_ prefix and .mtar:

avatar_edit, behind, camera, carry, cbox, cqc, cure, cypr,
ddf_facial, ddm_facial, elude, facial_ddf_helispace,
facial_ddm_helispace, facial_snake_helispace, gimmick, heli, horse,
jump, ladder, liquid, ocelot_facial, okb_zero, online, paz, pipe,
quiet_facial, resident, timecigarette, trashbox, vehicle,
vram_resident, TppPlayer2Facial

The replacement must hold every clip of the vanilla archive, or those animations break. Build it from the vanilla .mtar.

Outfit voice

voiceFpk is one package path, or a table with one package per voice type. voiceType forces the voice the player speaks with.

ddMale = {
  partsPath = "/Assets/tpp/parts/chara/mymod/body.parts",
  fpkPath   = "/Assets/tpp/pack/mymod/body.fpk",

  voiceFpk = {
    ddmsoldiera = "/Assets/tpp/pack/mymod/voice_a.fpk",
    ddmsoldierb = "/Assets/tpp/pack/mymod/voice_b.fpk",
  },
  voiceType = "ddmsoldiera",
},

Voice types

Player type Voice Number
snake/avatar snak 0x3CF677C6
ddMale ddmsoldiera 0x2EED93D9
ddMale ddmsoldierb 0x2EED93DA
ddMale ddmsoldierc 0x2EED93DB
ddMale ddmsoldierd 0x2EED93DC
ddFemale ddfsoldiera 0x80400AFA
ddFemale ddfsoldierb 0x80400AF9
ddFemale ddfsoldierc 0x80400AF8
ddFemale ddfsoldierd 0x80400AFF
ocelot ocelot 0x1BF9CBC1
quiet quiet 0x5D5262DF

Outfit R&D row

V_TppMotherBaseManagement.AddToEquipDevelopTable("MyMod:MySuit", {
  const = {
    equipID             = TppEquip.EQP_SUIT,
    equipDevelopTypeID  = TppMbDev.EQP_DEV_TYPE_Suit,
    langEquipName       = "staff_name_99_051",
    iconFtexPath        = "/Assets/.../ui_suit_icon",
    equipDevelopGroupID = V_TppMbDev.EQP_OUTFIT_VARIANT_NAME,
  },
  flow = {
    grade            = 5,
    developGmpCost   = 50000,
    initialAvailable = 0,
  },
})

Other fields: AddToEquipDevelopTable.


RegisterHeadOption

V_Player.RegisterHeadOption({
  key = "MyMod:MyHead",

  snake = {
    fv2 = "/Assets/.../myhead.fv2",
    fpk = "/Assets/.../myhead.fpk",
  },
})

Head fields

Field Required Purpose
key Yes Registration key, shared with its R&D row. Max 63 characters; no line break, double quote or backslash.
snake, avatar, ddMale, ddFemale At least one Per-character branches.
showInDevelopMenu No (false) true lists the head in R&D.
abilities No (none) Abilities while the head is worn.

Branches

Field Branch Required Purpose
fv2, fpk snake, avatar Yes Head model.
TppEnemyFaceId ddMale, ddFemale No (balaclava) Soldier face worn as the head.
fv2, fpk ddMale, ddFemale No (none) Own head model. Wins over TppEnemyFaceId.
colors any No (none) Head colours (Triangle (Y) in the HEAD list). Their fv2s and textures go in the head’s own fpk; needs the branch’s fv2 and fpk.
ddMale = {
  TppEnemyFaceId = TppEnemyFaceId.svs_balaclava,
},

ddFemale = {
  fv2 = "/Assets/tpp/fova/chara/mymod/head_ddf.fv2",
  fpk = "/Assets/tpp/pack/mymod/head_ddf.fpk",
},

Head motion

A branch can animate the head and attach effects; play them with PlayHeadMotion, PlayHeadEffect and PlayHeadSound.

snake = {
  -- fv2, fpk ...
  motion = {
    mtar    = "/Assets/tpp/motion/mymod/head_motion.mtar",
    clips   = { blink = "/Assets/tpp/motion/mymod/blink.gani" },
    effects = {
      sparks = { vfx = "/Assets/tpp/effect/mymod/sparks.vfx", point = "CNP_HEAD", clip = "blink" },
    },
    rest    = "blink",
  },
},
Field Required Purpose
mtar Yes, for clips Head animation archive, packed in the head’s fpk.
clips Yes, for clips Clip name = clip id (path, MtarTool id or 0x id).
effects No (none) Effects by name.
rest No (none) Clip whose effects run while no other clip plays.

Each effect:

Field Required Purpose
vfx Yes Effect file.
point No (none) Connect point to attach to.
clip No (none) Starts with this clip.

Head abilities

abilities goes at the top level, next to key. Inside a branch it is ignored.

V_Player.RegisterHeadOption({
  key       = "MyMod:MyHead",
  snake     = { fv2 = "/Assets/.../myhead.fv2", fpk = "/Assets/.../myhead.fpk" },
  abilities = { infiniteAmmo = true },
})

All optional.

Field Type (default) Effect
infiniteAmmo boolean (false) Infinite ammo.

Face layers (DD soldiers)

Optional, ddMale/ddFemale only. true keeps the soldier’s own layer, false hides it under the head. Omitted: vanilla behaviour.

Layer Contents Toggle
face Face model. enableFaceFova
face deco Beard, stubble or face paint on the face. enableFaceDecoFova
hair Hair model. enableHairFova
hair deco Hair colour or style. enableHairDecoFova
ddMale = {
  TppEnemyFaceId     = TppEnemyFaceId.dds_balaclava2,
  enableFaceFova     = false,
  enableFaceDecoFova = false,
},

Layer path overrides

Optional. Force specific layer assets, such as a hair, for a head:

V_Player.RegisterHeadOption({
  key = "MyMod:CapWithPixieHair",

  ddFemale = {
    fv2 = "/Assets/tpp/fova/chara/mymod/cap_ddf.fv2",
    fpk = "/Assets/tpp/pack/mymod/cap_ddf.fpk",

    faceFovaPath        = "",
    faceFovaFpkPath     = "",
    faceDecoFovaPath    = "",
    faceDecoFovaFpkPath = "",
    hairFovaPath        = "/Assets/tpp/fova/common_source/chara/cm_head/hair/cm_hair_c101.fv2",
    hairFovaFpkPath     = "/Assets/tpp/pack/fova/common_source/chara/cm_head/hair/cm_hair_c101.fpk",
    hairDecoFovaPath    = "/Assets/tpp/fova/common_source/chara/cm_head/hair_deco/cm_hair_c101_c000.fv2",
    hairDecoFovaFpkPath = "/Assets/tpp/pack/fova/common_source/chara/cm_head/hair_deco/cm_hair_c101_c000.fpk",
  },
})

Face stages (Snake only)

Optional. faceStages gives a Snake head its own face per Demon Point stage. Missing stages use the branch’s fv2 and fpk.

snake = {
  fv2 = "/Assets/.../myhead.fv2",
  fpk = "/Assets/.../myhead.fpk",

  faceStages = {
    [1] = { fv2 = "/Assets/.../myhead_normal.fv2", fpk = "/Assets/.../myhead_normal.fpk" }, -- Normal
    [2] = { fv2 = "/Assets/.../myhead_horn.fv2",   fpk = "/Assets/.../myhead_horn.fpk" },   -- Grown horn
    [3] = { fv2 = "/Assets/.../myhead_demon.fv2",  fpk = "/Assets/.../myhead_demon.fpk" },  -- Demon Snake
  },
}

Head R&D row

Gives the head its name and icon.

V_TppMotherBaseManagement.AddToEquipDevelopTable("MyMod:MyHead", {
  const = {
    equipID            = TppEquip.EQP_None,
    equipDevelopTypeID = TppMbDev.EQP_DEV_TYPE_Suit,
    langEquipName      = "staff_name_99_050",
    iconFtexPath       = "/Assets/.../ui_head_icon",
  },
  flow = {
    grade            = 1,
    developGmpCost   = 1000,
    initialAvailable = 0,
  },
})

ExtendVanillaOutfit

Adds to a vanilla suit; no new suit cell or R&D row.

V_Player.ExtendVanillaOutfit({
  outfit = "TIGERSTRIPE",

  snake = {
    headOptions = { "bandana", "MyMod:MyHead" },
    variants = {
      {
        partsPath = "/Assets/.../variant.parts",
        fpkPath   = "/Assets/.../variant.fpk",
      },
    },
  },
})

Select the vanilla suit

Use one of these:

Field Required Purpose
outfit One of the two Vanilla camo name, such as "TIGERSTRIPE", or a number 0-116.
partsType One of the two Raw parts type. variants do not work with it.
V_Player.ExtendVanillaOutfit({
  partsType = 3,
  snake     = { headOptions = { "bandana", "MyMod:MyHead" } },
})

Vanilla-outfit branch fields

All optional; only fields you set change the suit. headOptions and the voice fields apply only to the named camo.

Field Required Purpose
variants No (none) Extra looks. A vanilla parts type holds 29 in total.
headOptions No (none) Heads added to the suit. Max 120.
voiceFpk, voiceType No (vanilla voice) Voice for the suit on this player type.
enableArm No (true) false hides the bionic arm, also in FOB. Snake and Avatar only.
enableHead No (true) false hides the head (face and hair on DD); the vanilla head shows online. A head built into the suit stays.
abilities No (none) Suit abilities for this branch.

Vanilla-outfit variant fields

These mirror the variant fields, with these differences:

Field Required Purpose
partsPath, fpkPath Yes If fpkPath is not installed, the vanilla suit is used.
camoFpk, camoFv2 No (vanilla camo) If camoFpk is not installed, the vanilla camo is used.
diamondFpk, diamondFv2 No (vanilla overlay) Wet, mud or emblem overlay; false removes it. If diamondFpk is not installed, the vanilla overlay is used.
voiceFpk, voiceType No (branch voice) Not applied in FOB.
V_Player.ExtendVanillaOutfit({
  outfit = "TIGERSTRIPE",

  ddFemale = {
    variants = {
      {
        partsPath   = "/Assets/tpp/parts/chara/sna/sna4_plyf0_def_v00.parts",
        fpkPath     = "/Assets/tpp/pack/mymod/plparts_female_6.fpk",
        diamondFpk  = false,
        displayName = "staff_name_99_117",
      },
    },
  },
})

Minimal complete example

local this = {}

function this.LoadLibraries()

  V_Player.RegisterHeadOption({
    key = "MyMod:OgreHorn",

    ddFemale = {
      fv2 = "/Assets/tpp/fova/chara/mymod/ogrehorn.fv2",
      fpk = "/Assets/tpp/pack/mymod/ogrehorn.fpk",
    },
  })

  V_TppMotherBaseManagement.AddToEquipDevelopTable("MyMod:OgreHorn", {
    const = {
      equipID            = TppEquip.EQP_None,
      equipDevelopTypeID = TppMbDev.EQP_DEV_TYPE_Suit,
      langEquipName      = "staff_name_99_050",
      iconFtexPath       = "/Assets/.../ui_head_ogre",
    },
    flow = {
      grade            = 1,
      developGmpCost   = 1000,
      initialAvailable = 0,
    },
  })

  V_Player.RegisterOutfit({
    key = "MyMod:OgreSuit",

    ddFemale = {
      partsPath   = "/Assets/tpp/parts/chara/mymod/ogre.parts",
      fpkPath     = "/Assets/tpp/pack/mymod/ogre.fpk",
      headOptions = { "MyMod:OgreHorn", "balaclava" },
    },
  })

  V_TppMotherBaseManagement.AddToEquipDevelopTable("MyMod:OgreSuit", {
    const = {
      equipID             = TppEquip.EQP_SUIT,
      equipDevelopTypeID  = TppMbDev.EQP_DEV_TYPE_Suit,
      langEquipName       = "staff_name_99_051",
      iconFtexPath        = "/Assets/.../ui_ogre_suit",
      equipDevelopGroupID = V_TppMbDev.EQP_OUTFIT_VARIANT_NAME,
    },
    flow = {
      grade            = 5,
      developGmpCost   = 50000,
      initialAvailable = 1,
    },
  })
end

return this

See also