Left 4 Dead 2

Left 4 Dead 2

35 ratings
Select Your Skins made simple (Modders Guide)
By Ellie
This is the abbreviated version of the Select Your Skins (for Modders) Guide. Contrary to the other Guide, it's written with the focus to make you achieve a result as fast as possible, without detailing all the options.
   
Award
Favorite
Favorited
Unfavorite
General Information
Difficulty :

Short description: Select Your Skins (SYS) is the new way of doing RNG (randomization) mods. This Guide is the dumbed-down version of the full guide that you can. It does not explain all the features that SYS Offers, and focuses on the main stuff that might be enough for you.
❗ This Guide covers both the "Whole New Mod" and "Update your mod to the new RNG" situations, but if you want to update an existing mod, you will only be able to add the new RNG (≠SYS) features, mainly the key that lets the user randomize again everything
This Guide teaches the classic version of RNG/SYS and does not explain:
  • 'Model' Randomization (SYS Loadout)
  • 'Color' Randomization (SYS Color)
To learn about these, read the full guide.
https://sp.zhabite.com/sharedfiles/filedetails/?id=2303221834&preview=true
Features
What does the RNG/SYS system offers (and that's explained in this Guide) ?:
(Stroked features are features the SYS system offers but only explained in the full Guide)
  • RNG (Randomization) of multiple skins for your character/gun/item/object
  • It's not required anymore to specify the number of skins (VTF frames) you have ⁽ᴺᴱᵂ⁾
  • The item you pick matches the one you have in hand ⁽ᴺᴱᵂ⁾
  • More than 1 skin per map for static objects that are in a map ⁽ᴺᴱᵂ⁾
  • Possibility to tell that invisible is also a skin ⁽ᴺᴱᵂ⁾
  • Lets the user randomize everything again live in the middle of a game ⁽ᴺᴱᵂ⁾
  • Easy way to do 'model' RNG (Loadout system) ⁽ᴺᴱᵂ⁾
  • Easy way to do Color RNG ⁽ᴺᴱᵂ⁾

    (Not available if you update an old mod)
  • Select Your Skins (SYS) System that lets the user choose his/her skins ⁽ᴺᴱᵂ⁾
  • Slots system (30 Slots) for the user to store skins (each mod has a defined slot) ⁽ᴺᴱᵂ⁾
  • Possibility to lock a slot (skin), forever, even when the game is exited ⁽ᴺᴱᵂ⁾

  • New keyboards shortcuts to randomize again, or to switch between RNG/SYS Mode ⁽ᴺᴱᵂ⁾
  • Optional HUD options with new animated icons to help the user ⁽ᴺᴱᵂ⁾
① VTF with multiple frames
To randomize the textures, you will need to make a VTF with multiple frames.
  • If you already made a RNG mod in the past, you know how this works, and you can jump to the next step ②.
  • If you never made a RNG mod in the past, you can go read the [Appendix] VTF with multiple textures in the full guide.
If you do not want to read the full Guide, here's a dumbed-down explanation:
⒈ Save all your different skins (textures) as .tga file and put them in a same folder
⒉ In VTFEdit, import all the textures (.tga) at once by selecting them all and pressing ENTER
⒊ You should now be able to increment the frame with the little arrows under the 'Image' tab
⒋ Export your texture as a VTF file with VTFEdit as usual and put it in your mod
② Clean the VMT
You will now need to clean up your VMT and remove some parts of it so it will be compatible with the code you will copy and paste.

If you are updating an old RNG mod, you need to delete from the VMT everything that you added when you implemented RNG for the first time, this means:
  • The "Proxies" line and everything that comes after it up until the very last } at the end of your VMT (do not delete that last })
  • All the new variables (things that start with $) that you added when you implemented the RNG. In other words, all the variables ($) that did not come with the original VMT.
If you are making a new mod, you need to delete from the VMT, if they are here:
  • The VertexLitGeneric line and the { that comes just after it.
  • The patch line and everything that comes after up until you reach the first $ (variable)
  • The "Proxies" line and everything that comes after it up until the very last } at the end of your VMT (do not delete that last })
  • The $detailAmout variable if you see it, and any other custom variable.
Is this too complicated to understand ? Okay, let's try with pictures:
- If you are updating an old RNG mod, delete all the stuff that looks like what's in red in the pictures below.
- If you are making a new mod, delete all the stuff that looks like what's in red/orange/yellow in the pictures below.



③ Find what version you need
Find what you are making a mod for in the tables below and remember the version you will need to use.

Zoey
Francis
Louis
Bill
Rochelle
Coach
Nick
Ellis
Charger
Boomer
Smoker
Hunter
Jockey
Spitter
Witch
Tank
→ If you make a new mod: 🔵 SYS Entity
→ If you update an existing mod: 🔵 Inline RNG Entity

Guns/Weapons
Pain Pills
Adrenaline
Medkit
Pipe Bomb
Molotov
Bile Jar
Fireworks
Jerrycans
Oxygen tanks
→ If you make a new mod: ⚪️ SYS Pure
→ If you update an existing mod: ⚪️ Inline RNG Pure

Soda
Tank Rock
Ammo piles
Laser Boxes
Chopper pilot (alive)
Gnome
Defibrilator
Machine Guns
Explosive Ammo
Fire Ammo
Fireworks
Medkit Cabinets
Computer screens
Escape vehicles
Doors that open
→ If you make a new mod: 🔵 SYS Entity
→ If you update an existing mod: 🔵 Inline RNG Entity

Vending Machines
Paintings
Trash
Radios
Books
Ads
Magazine Racks
Bilboards
Posters
Cars
Trucks
Signs
And anything else that is static in a map (incl. Bill's corpse).
→ If you make a new mod: 🔶SYS Map
→ If you update an existing mod: 🔶 Inline SYS Map
④ Copy the code
You will now need to copy the code you just determined at the last step in your VMT. You will find all the (6) codes just after this section.
Although, where you need to copy is different if you are updating an old mod or making a new mod.

If you are updating an old mod, you need to copy the (inline) code above the last }.


If you are making a new mod, you need to copy the code at the top of the VMT, where VertexLitGeneric used to be just before you deleted it.

🔵 SYS Entity
//--------------------------------------------------------------------------------- patch { include "rng/sys_entity.vmt" insert { /////////////////////////////////////////////////////////////////////////////////////////////// $slotUsed "0" // Change this to your slot number if you want SYS $activateRNG "1" // Set to 0 to deactivate randomization (RNG) $oneSkinPerMap "0" // Set to 1 to limit the RNG to 1 skin per map $injectIntoFrame "1" $injectIntoDetail "0" $injectIntoBumpMap "0" // Set to 1 if you have one bumpmap for each frame $invisibleIsAlsoASkin "0" // Set to 1 if ANY VMT has the next value set to 1 $invisibleIsAlsoASkinHere "0" // If set to 1, THIS VMT can also disappear as a skin $invisibleNotInRNGPool "0" // Set to 1 if invisible is only an option for SYS $boomerEffects "0" // Set to 1 and unquote below for Boomer effects // $detail "models/survivors/survivor_it" // $detailscale 3 // $detailblendfactor ".001" // $detailblendmode "0" $meleeBloodEffects "0" // Set to 1 and unquote below for Melee blood effects // $detail "models/infected/hunter/hunter_01_detail" // $detailscale "1.75" // $detailblendfactor .001 // $detailblendmode "0" /////////////////////////////////////////////////////////////////////////////////////////////// // Code by Ellie, https://sp.zhabite.com/id/ellie_williams - 2020 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
🔵 Inline RNG Entity
////////////////////////////////////////////////////////////////////////////////////////////////// // RNG Entity 2020 (inline) - by Ellie ////////////////////////////////////////////////////////////////////////////////////////////////// $oneSkinPerMap "0" // Set to 1 to limit the skin at 1 per map $invisibleIsAlsoASkin "0" // 1 if any skin in the MOD has invisible skin $invisibleIsAlsoASkinHere "0" // 1 for invisible to be a skin for this VMT $boomerEffects "0" // Set to 1 and unquote for Boomer effects // $detail "models/survivors/survivor_it" // $detailscale 3 // $detailblendfactor ".001" // $detailblendmode "0" $meleeBloodEffects "0" // Set to 1 and unquote for Melee blood // $detail "models/infected/hunter/hunter_01_detail" // $detailscale "1.75" // $detailblendfactor .001 // $detailblendmode "0" /////////////////////////////////////////////////////////////////////////////// $randSYS "0.0" $randSYSTemp "0.0" $randSYSOverflow "0.0" $prepareStore "1000.0" $randSYSStored "1000.0" $randSYSInject "0.0" $randOffset "1000.0" $roundOffset ".05" $time "0" $isEntity "0" $rerollRaw "0" $rerollRawStored "0" $rerollRNG "0" $checkMax "0.0" $maxFrame "0.0" $maxFramePlusOne "1.0" $maxFramePlusInvisible "1.0" $countingFinished "0.0" $injectFrame "0.0" $RNGInjectFrame "0.0" $clampLimit "0.0" $tempDIV "0.0" $tempMULT "0.0" $tempFRAC "0.0" $tempOFFSET "0.25" $boomerAmount "0.0" $bloodAmount "0.0" $mo "-1" $zero "0.0" $one "1.0" $two "2.0" $three "3" $four "4" $oh "100" $fh "500" $ot "1000" Proxies { Add { srcVar1 "$maxFrame" srcVar2 "$one" resultVar "$maxFramePlusOne" } Add { srcVar1 "$invisibleIsAlsoASkin" srcVar2 "$maxFramePlusOne" resultVar "$maxFramePlusInvisible" } AnimatedTexture { animatedtexturevar "$basetexture" animatedtextureframenumvar "$checkMax" animatedtextureframerate "25" } LessOrEqual { LessEqualVar "$maxFrame" greaterVar "$checkMax" srcVar1 "$checkMax" srcVar2 "$maxFrame" resultVar "$maxFrame" } LessOrEqual { LessEqualVar "$one" greaterVar "$countingFinished" srcVar1 "$checkMax" srcVar2 "$zero" resultVar "$countingFinished" } LessOrEqual { LessEqualVar "$zero" greaterVar "$countingFinished" srcVar1 "$maxFrame" srcVar2 "$zero" resultVar "$countingFinished" } ConVar { convar "cl_buy_favorite_nowarn" resultVar "$rerollRaw" } Int { srcVar1 "$rerollRaw" resultVar "$rerollRaw" } Subtract { srcVar1 "$rerollRaw" srcVar2 "$rerollRawStored" resultVar "$rerollRNG" } Abs { srcVar1 "$rerollRNG" resultVar "$rerollRNG" } Equals { srcVar1 "$rerollRaw" resultVar "$rerollRawStored" } LessOrEqual { LessEqualVar "$randOffset" greaterVar "$ot" srcVar1 "$rerollRNG" srcVar2 "$zero" resultVar "$randOffset" } LessOrEqual { LessEqualVar "$randSYSStored" greaterVar "$ot" srcVar1 "$rerollRNG" srcVar2 "$zero" resultVar "$randSYSStored" } CurrentTime { resultVar "$time" } Divide { srcVar1 "$time" srcVar2 "$maxFramePlusInvisible" resultVar "$tempDIV" } Frac { srcVar1 "$tempDIV" resultVar "$tempDIV" } Multiply { srcVar1 "$tempDIV" srcVar2 "$maxFramePlusInvisible" resultVar "$tempDIV" } Add { srcVar1 "$tempDIV" srcVar2 "$roundOffset" resultVar "$tempDIV" } LessOrEqual { LessEqualVar "$randOffset" greaterVar "$tempDIV" srcVar1 "$randOffset" srcVar2 "$fh" resultVar "$randOffset" } EntityRandom { scale "$maxFramePlusInvisible" resultVar "$randSYSTemp" } Add { srcVar1 "$randSYSTemp" srcVar2 "$randOffset" resultVar "$randSYSTemp" } Subtract { srcVar1 "$randSYSTemp" srcVar2 "$maxFramePlusInvisible" resultVar "$randSYSOverflow" } LessOrEqual { LessEqualVar "$randSYSTemp" greaterVar "$randSYSOverflow" srcVar1 "$randSYSTemp" srcVar2 "$maxFramePlusInvisible" resultVar "$randSYS" } LessOrEqual { LessEqualVar "$prepareStore" greaterVar "$randSYS" srcVar1 "$countingFinished" srcVar2 "$zero" resultVar "$prepareStore" } LessOrEqual { LessEqualVar "$randSYSStored" greaterVar "$prepareStore" srcVar1 "$randSYSStored" srcVar2 "$fh" resultVar "$randSYSStored" } LessOrEqual { LessEqualVar "$randSYS" greaterVar "$randSYSStored" srcVar1 "$oneSkinPerMap" srcVar2 "$zero" resultVar "$randSYSInject" } Multiply { srcVar1 "$countingFinished" srcVar2 "$randSYSInject" resultVar "$injectFrame" } EntityRandom { scale "1" resultVar "$isEntity" } LessOrEqual { LessEqualVar "$RNGinjectFrame" greaterVar "$injectFrame" srcVar1 "$isEntity" srcVar2 "$zero" resultVar "$injectFrame" } LessOrEqual { LessEqualVar "$maxFrame" greaterVar "$maxFramePlusOne" srcVar1 "$invisibleIsAlsoASkinHere" srcVar2 "$zero" resultVar "$clampLimit" } LessOrEqual { LessEqualVar "$injectFrame" greaterVar "$clampLimit" srcVar1 "$injectFrame" srcVar2 "$clampLimit" resultVar "$RNGinjectFrame" } Equals { srcVar1 "$RNGinjectFrame" resultVar "$frame" } Int { srcVar1 "$frame" resultVar "$frame" } LessOrEqual { LessEqualVar "$one" greaterVar "$zero" srcVar1 "$frame" srcVar2 "$maxframe" resultVar "$alpha" } IT { resultVar "$boomerAmount" } LessOrEqual { LessEqualVar "$detailblendfactor" greaterVar "$boomerAmount" srcVar1 "$boomerEffects" srcVar2 "$zero" resultVar "$detailblendfactor" } BloodyHands { resultVar "$bloodAmount" } LessOrEqual { LessEqualVar "$detailblendfactor" greaterVar "$bloodAmount" srcVar1 "$meleeBloodEffects" srcVar2 "$zero" resultVar "$detailblendfactor" } }
⚪️ SYS Entity Pure
//--------------------------------------------------------------------------------- patch { include "rng/sys_entity_pure.vmt" insert { /////////////////////////////////////////////////////////////////////////////////////////////// $slotUsed "0" // Change this to your slot number if you want SYS $activateRNG "1" // Set to 0 to deactivate randomization (RNG) $proxThreshold "500" // Increase this value if you see the texture change $toleranceThreshold "10" // Increase this value if you see the texture flicker $oneSkinPerMap "0" // Set to 1 to limit the RNG to 1 skin per map $injectIntoFrame "1" $injectIntoDetail "0" $injectIntoBumpMap "0" // Set to 1 if you have one bumpmap for each frame $invisibleIsAlsoASkin "0" // Set to 1 if ANY VMT has the next value set to 1 $invisibleIsAlsoASkinHere "0" // If set to 1, THIS VMT can also disappear as a skin $invisibleNotInRNGPool "0" // Set to 1 if invisible is only an option for SYS $boomerEffects "0" // Set to 1 and unquote below for Boomer effects // $detail "models/survivors/survivor_it" // $detailscale 3 // $detailblendfactor ".001" // $detailblendmode "0" $meleeBloodEffects "0" // Set to 1 and unquote below for Melee blood effects // $detail "models/infected/hunter/hunter_01_detail" // $detailscale "1.75" // $detailblendfactor .001 // $detailblendmode "0" /////////////////////////////////////////////////////////////////////////////////////////////// // Code by Ellie, https://sp.zhabite.com/id/ellie_williams - 2020 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
⚪️ Inline RNG Pure
////////////////////////////////////////////////////////////////////////////////////////////////// // RNG Pure 2020 (inline) - by Ellie ////////////////////////////////////////////////////////////////////////////////////////////////// $oneSkinPerMap "0" // Set to 1 to limit the skin at 1 per map $proxThreshold "500" // Add +100 if you can see the skin change $toleranceThreshold "10" $invisibleIsAlsoASkin "0" // 1 if any skin in the MOD has invisible skin $invisibleIsAlsoASkinHere "0" // 1 for invisible to be a skin for this VMT $boomerEffects "0" // Set to 1 and unquote for Boomer effects // $detail "models/survivors/survivor_it" // $detailscale 3 // $detailblendfactor ".001" // $detailblendmode "0" $meleeBloodEffects "0" // Set to 1 and unquote for Melee blood // $detail "models/infected/hunter/hunter_01_detail" // $detailscale "1.75" // $detailblendfactor .001 // $detailblendmode "0" /////////////////////////////////////////////////////////////////////////////// $randSYS "0.0" $randSYSTemp "0.0" $randSYSOverflow "0.0" $prepareStore "1000.0" $randSYSStored "1000.0" $randSYSInject "0.0" $randOffset "1000.0" $roundOffset ".05" $time "0" $hasBeenFar "0" $isEntity "0" $rerollRaw "0" $rerollRawStored "0" $rerollRNG "0" $checkMax "0.0" $maxFrame "0.0" $maxFramePlusOne "1.0" $maxFramePlusInvisible "1.0" $countingFinished "0.0" $injectFrame "0.0" $RNGInjectFrame "0.0" $prox "0" $proxCheck "0" $triggerPureRNG "0" $clampLimit "0.0" $tempDIV "0.0" $tempMULT "0.0" $tempFRAC "0.0" $tempOFFSET "0.0" $boomerAmount "0.0" $bloodAmount "0.0" $mo "-1" $zero "0.0" $one "1.0" $two "2.0" $three "3" $twentyfour "24" $oh "100" $fh "500" $ot "1000" Proxies { Add { srcVar1 "$maxFrame" srcVar2 "$one" resultVar "$maxFramePlusOne" } Add { srcVar1 "$invisibleIsAlsoASkin" srcVar2 "$maxFramePlusOne" resultVar "$maxFramePlusInvisible" } AnimatedTexture { animatedtexturevar "$basetexture" animatedtextureframenumvar "$checkMax" animatedtextureframerate "25" } LessOrEqual { LessEqualVar "$maxFrame" greaterVar "$checkMax" srcVar1 "$checkMax" srcVar2 "$maxFrame" resultVar "$maxFrame" } LessOrEqual { LessEqualVar "$one" greaterVar "$countingFinished" srcVar1 "$checkMax" srcVar2 "$zero" resultVar "$countingFinished" } LessOrEqual { LessEqualVar "$zero" greaterVar "$countingFinished" srcVar1 "$maxFrame" srcVar2 "$zero" resultVar "$countingFinished" } ConVar { convar "cl_buy_favorite_nowarn" resultVar "$rerollRaw" } Int { srcVar1 "$rerollRaw" resultVar "$rerollRaw" } Subtract { srcVar1 "$rerollRaw" srcVar2 "$rerollRawStored" resultVar "$rerollRNG" } Abs { srcVar1 "$rerollRNG" resultVar "$rerollRNG" } Equals { srcVar1 "$rerollRaw" resultVar "$rerollRawStored" } LessOrEqual { LessEqualVar "$randOffset" greaterVar "$ot" srcVar1 "$rerollRNG" srcVar2 "$zero" resultVar "$randOffset" } LessOrEqual { LessEqualVar "$randSYSStored" greaterVar "$ot" srcVar1 "$rerollRNG" srcVar2 "$zero" resultVar "$randSYSStored" } CurrentTime { resultVar "$time" } Divide { srcVar1 "$time" srcVar2 "$maxFramePlusInvisible" resultVar "$tempDIV" } Frac { srcVar1 "$tempDIV" resultVar "$tempDIV" } Multiply { srcVar1 "$tempDIV" srcVar2 "$maxFramePlusInvisible" resultVar "$tempDIV" } Add { srcVar1 "$tempDIV" srcVar2 "$roundOffset" resultVar "$tempDIV" } LessOrEqual { LessEqualVar "$randOffset" greaterVar "$tempDIV" srcVar1 "$randOffset" srcVar2 "$fh" resultVar "$randOffset" } EntityRandom { scale "$maxFramePlusInvisible" resultVar "$randSYSTemp" } Add { srcVar1 "$randSYSTemp" srcVar2 "$randOffset" resultVar "$randSYSTemp" } Subtract { srcVar1 "$randSYSTemp" srcVar2 "$maxFramePlusInvisible" resultVar "$randSYSOverflow" } LessOrEqual { LessEqualVar "$randSYSTemp" greaterVar "$randSYSOverflow" srcVar1 "$randSYSTemp" srcVar2 "$maxFramePlusInvisible" resultVar "$randSYS" } LessOrEqual { LessEqualVar "$prepareStore" greaterVar "$randSYS" srcVar1 "$countingFinished" srcVar2 "$zero" resultVar "$prepareStore" } LessOrEqual { LessEqualVar "$randSYSStored" greaterVar "$prepareStore" srcVar1 "$randSYSStored" srcVar2 "$fh" resultVar "$randSYSStored" } LessOrEqual { LessEqualVar "$randSYS" greaterVar "$randSYSStored" srcVar1 "$oneSkinPerMap" srcVar2 "$zero" resultVar "$randSYSInject" } Multiply { srcVar1 "$countingFinished" srcVar2 "$randSYSInject" resultVar "$injectFrame" } EntityRandom { scale "1" resultVar "$isEntity" } PlayerProximity { scale "1" resultVar "$prox" } Subtract { srcVar1 "$prox" srcVar2 "$proxThreshold" resultVar "$proxCheck" } Abs { srcVar1 "$proxCheck" resultVar "$proxCheck" } LessOrEqual { LessEqualVar "$one" greaterVar "$zero" srcVar1 "$proxCheck" srcVar2 "$toleranceThreshold" resultVar "$triggerPureRNG" } Add { srcVar1 "$triggerPureRNG" srcVar2 "$rerollRNG" resultVar "$triggerPureRNG" } LessOrEqual { LessEqualVar "$zero" greaterVar "$isEntity" srcVar1 "$triggerPureRNG" srcVar2 "$zero" resultVar "$isEntity" } LessOrEqual { LessEqualVar "$hasBeenFar" greaterVar "$one" srcVar1 "$RNGinjectFrame" srcVar2 "$zero" resultVar "$hasBeenFar" } LessOrEqual { LessEqualVar "$one" greaterVar "$isEntity" srcVar1 "$hasBeenFar" srcVar2 "$zero" resultVar "$isEntity" } LessOrEqual { LessEqualVar "$RNGinjectFrame" greaterVar "$injectFrame" srcVar1 "$isEntity" srcVar2 "$zero" resultVar "$injectFrame" } LessOrEqual { LessEqualVar "$RNGinjectFrame" greaterVar "$injectFrame" srcVar1 "$isEntity" srcVar2 "$zero" resultVar "$injectFrame" } LessOrEqual { LessEqualVar "$maxFrame" greaterVar "$maxFramePlusOne" srcVar1 "$invisibleIsAlsoASkinHere" srcVar2 "$zero" resultVar "$clampLimit" } LessOrEqual { LessEqualVar "$injectFrame" greaterVar "$clampLimit" srcVar1 "$injectFrame" srcVar2 "$clampLimit" resultVar "$RNGinjectFrame" } Equals { srcVar1 "$RNGinjectFrame" resultVar "$frame" } Int { srcVar1 "$frame" resultVar "$frame" } LessOrEqual { LessEqualVar "$one" greaterVar "$zero" srcVar1 "$frame" srcVar2 "$maxframe" resultVar "$alpha" } IT { resultVar "$boomerAmount" } LessOrEqual { LessEqualVar "$detailblendfactor" greaterVar "$boomerAmount" srcVar1 "$boomerEffects" srcVar2 "$zero" resultVar "$detailblendfactor" } BloodyHands { resultVar "$bloodAmount" } LessOrEqual { LessEqualVar "$detailblendfactor" greaterVar "$bloodAmount" srcVar1 "$meleeBloodEffects" srcVar2 "$zero" resultVar "$detailblendfactor" } }
🔶 SYS Map
//--------------------------------------------------------------------------------- patch { include "rng/sys_map.vmt" insert { /////////////////////////////////////////////////////////////////////////////////////////////// $slotUsed "0" // Change this to your slot number if you want SYS $activateRNG "1" // Set to 0 to deactivate randomization (RNG) $distancePerFrame "2000" // Distance to move for the skin to change $oneSkinPerMap "0" // Set to 1 to limit the RNG to 1 skin per map $frameOffset "0" // Frame offset for SYS (useful do desync objects) $injectIntoFrame "1" $injectIntoDetail "0" $injectIntoBumpMap "0" // Set to 1 if you have one bumpmap for each frame /////////////////////////////////////////////////////////////////////////////////////////////// // Code by Ellie, https://sp.zhabite.com/id/ellie_williams - 2020 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
🔶 Inline RNG Map
////////////////////////////////////////////////////////////////////////////////////////////////// // RNG Map 2020 (inline) - by Ellie ////////////////////////////////////////////////////////////////////////////////////////////////// $distancePerFrame "4000" $oneSkinPerMap "0" // Set to 1 to limit to 1 skin per map $frameOffset "0" // Offset for the frame if skinfamilies ////////////////////////////////////////////////////////////////////////////////////////////////// $pos "[0 0 0]" $posX "0.0" $posY "0.0" $time "0" $timeOffset "0" $rerollRaw "0" $rerollRawStored "0" $rerollRNG "0" $randSYS "0.0" $prepareStore "1000.0" $randSYSStored "1000.0" $randSYSInject "0.0" $randSYSOffset "0.0" $randSYSOverflow "0.0" $checkMax "0.0" $maxFrame "0.0" $maxFramePlusOne "1.0" $countingFinished "0.0" $injectFrame "0.0" $RNGInjectFrame "0.0" $distanceRollback "0.0" $tempDIV "0.0" $tempMULT "0.0" $tempOFFSET "0.25" $tempFRAC "0.0" $mo "-1" $zero "0.0" $one "1.0" $two "2.0" $oh "100" $fh "500" $ot "1000" $tt "10000" Proxies { AnimatedTexture { animatedtexturevar "$basetexture" animatedtextureframenumvar "$checkMax" animatedtextureframerate "25" } LessOrEqual { LessEqualVar "$maxFrame" greaterVar "$checkMax" srcVar1 "$checkMax" srcVar2 "$maxFrame" resultVar "$maxFrame" } Add { srcVar1 "$maxFrame" srcVar2 "$one" resultVar "$maxFramePlusOne" } LessOrEqual { LessEqualVar "$one" greaterVar "$countingFinished" srcVar1 "$checkMax" srcVar2 "$zero" resultVar "$countingFinished" } LessOrEqual { LessEqualVar "$zero" greaterVar "$countingFinished" srcVar1 "$maxFrame" srcVar2 "$zero" resultVar "$countingFinished" } Multiply { srcVar1 "$distancePerFrame" srcVar2 "$maxFramePlusOne" resultVar "$distanceRollback" } PlayerPosition { scale 1 resultVar "$pos" } Clamp { srcVar1 "$zero" min "$pos[0]" max "$pos[0]" resultVar "$posX" } Abs { srcVar1 "$posX" resultVar "$posX" } LessOrEqual { LessEqualVar "$posX" greaterVar "$timeOffset" srcVar1 "$timeOffset" srcVar2 "$zero" resultVar "$timeOffset" } Clamp { srcVar1 "$zero" min "$pos[1]" max "$pos[1]" resultVar "$posY" } Abs { srcVar1 "$posY" resultVar "$posY" } Add { srcVar1 "$posY" srcVar2 "$posX" resultVar "$posY" } Divide { srcVar1 "$posY" srcVar2 "$distanceRollback" resultVar "$posY" } Frac { srcVar1 "$posY" resultVar "$posY" } Multiply { srcVar1 "$posY" srcVar2 "$maxFramePlusOne" resultVar "$randSYS" } CurrentTime { resultVar "$time" } Add { srcVar1 "$time" srcVar2 "$timeOffset" resultVar "$tempMULT" } Divide { srcVar1 "$tempMULT" srcVar2 "$maxFramePlusOne" resultVar "$tempDIV" } Frac { srcVar1 "$tempDIV" resultVar "$tempDIV" } Multiply { srcVar1 "$tempDIV" srcVar2 "$maxFramePlusOne" resultVar "$tempDIV" } LessOrEqual { LessEqualVar "$tempDIV" greaterVar "$randSYSOffset" srcVar1 "$randSYSOffset" srcVar2 "$zero" resultVar "$randSYSOffset" } Add { srcVar1 "$randSYSOffset" srcVar2 "$randSYS" resultVar "$randSYS" } Subtract { srcVar1 "$randSYS" srcVar2 "$maxFramePlusOne" resultVar "$randSYSOverflow" } LessOrEqual { LessEqualVar "$randSYS" greaterVar "$randSYSOverflow" srcVar1 "$randSYS" srcVar2 "$maxFramePlusOne" resultVar "$randSYS" } Add { srcVar1 "$randSYS" srcVar2 "$frameOffset" resultVar "$randSYS" } Subtract { srcVar1 "$randSYS" srcVar2 "$maxFramePlusOne" resultVar "$randSYSOverflow" } LessOrEqual { LessEqualVar "$randSYS" greaterVar "$randSYSOverflow" srcVar1 "$randSYS" srcVar2 "$maxFramePlusOne" resultVar "$randSYS" } ConVar { convar "cl_buy_favorite_nowarn" resultVar "$rerollRaw" } Int { srcVar1 "$rerollRaw" resultVar "$rerollRaw" } Subtract { srcVar1 "$rerollRaw" srcVar2 "$rerollRawStored" resultVar "$rerollRNG" } Abs { srcVar1 "$rerollRNG" resultVar "$rerollRNG" } Equals { srcVar1 "$rerollRaw" resultVar "$rerollRawStored" } LessOrEqual { LessEqualVar "$randSYSOffset" greaterVar "$zero" srcVar1 "$rerollRNG" srcVar2 "$zero" resultVar "$randSYSOffset" } LessOrEqual { LessEqualVar "$randSYSStored" greaterVar "$ot" srcVar1 "$rerollRNG" srcVar2 "$zero" resultVar "$randSYSStored" } LessOrEqual { LessEqualVar "$prepareStore" greaterVar "$randSYS" srcVar1 "$countingFinished" srcVar2 "$zero" resultVar "$prepareStore" } LessOrEqual { LessEqualVar "$randSYSStored" greaterVar "$prepareStore" srcVar1 "$randSYSStored" srcVar2 "$fh" resultVar "$randSYSStored" } LessOrEqual { LessEqualVar "$randSYS" greaterVar "$randSYSStored" srcVar1 "$oneSkinPerMap" srcVar2 "$zero" resultVar "$randSYSInject" } Multiply { srcVar1 "$countingFinished" srcVar2 "$randSYSInject" resultVar "$injectFrame" } LessOrEqual { LessEqualVar "$frame" greaterVar "$randSYSInject" srcVar1 "$injectFrame" srcVar2 "$zero" resultVar "$frame" } LessOrEqual { LessEqualVar "$frame" greaterVar "$maxframe" srcVar1 "$frame" srcVar2 "$maxframe" resultVar "$frame" } }
⑤ Define the slot
Now that the code is copied, you might need to define the slot, however:
- Do not do this (you can't) if you updated an old RNG mod (using the inline variant).
- Do not do this if it's a bit stupid that the user could choose his own skin for what you mod (i.e. for trashcans, water stains on the walls, warning signs etc. (mostly map objects).

If you are not in one of the two above mentionned cases where you should not define the slot, what you need to do now is to change this value of 0 in your VMT(s)...:
$slotUsed "0"
... by a number that you will find below (if you have more than 1 possibility in the table below, you can choose at random among them).

SLOT
USAGE
1
Zoey
2
Zoey Extras
3
Rochelle
4
Rochelle Extras
5
Bill
6
Francis
7
Louis
8
Coach
9
Nick
10
Ellis
11
Survivors Extras
12
Survivors Extras
13
Special Infected / Guns
14
Guns (low tiers) / Items / Melee Weapons
15
Guns (low tiers) / Items / Melee Weapons
16
Guns (low tiers) / Items / Melee Weapons
18
Guns (high tiers) / Items / Melee Weapons
19
Guns (high tiers) / Items / Melee Weapons
20
Guns (high tiers) / Items / Melee Weapons
21
Guns (high tiers) / Items / Melee Weapons
22
Guns (high tiers) / Items / Melee Weapons
23
Map Items (Vending Machines / Paintings / Posters)
24
Map Items (Vending Machines / Paintings / Posters)
25
Map Items (Vending Machines / Paintings / Posters)
26
Anything (No restriction)
27
Anything (No restriction)
28
Anything (No restriction)
29
Anything (No restriction)
30
Anything (No restriction)

💡 If you are making a mod for a survivor (especially Zoey and Rochelle), you can actually use the slot Zoey Extras (2) or Rochelle Extras (4) for certain VMTs to allow the user to change these VMTs independantly from the other ones. For example, if you have multiple shirts and hair colors for Rochelle, you can set $slotUsed to 3 for the shirts VMT(s), and $slotUsed 4 for the hair VMT(s). The user will then select the shirts with Slot 3 and the Hair with Slot 4.
⑥ Mark the SYS Core Mod as required
Only if you are making a new mod (if you used the SYS and not the inline RNG), you will need to tell your subscribers that they need to download the SYS Core Mod that you can find here:
https://sp.zhabite.com/sharedfiles/filedetails/?id=2325990437
If you do not know how to do this, you can read the [Appendix] Set a Mod as required in this guide.

If you only updated an old RNG mod with the inline variants, your users do not need to download the SYS Core Mod for the RNG to work. That's normal, because if they needed it, you would just have broken the mod for all the ones that are not (yet) subscribed to the Code Mod and that would have no way to know that they need it now.

⑦ (Change the Shader)
If you are making a new mod (not using the inline variants), and if you want the shader to be UnlitGeneric or LightmappedGeneric, you will need to do this extra step: at the top of your VMT after you copy the code, you will see something like this
include "rng/sys_entity_pure.vmt"
If you want UnlitGeneric, modify this line like this:
include "rng/UnlitGeneric/sys_entity_pure.vmt"
If you want LightmappedGeneric, modify this line like this:
include "rng/LightmappedGeneric/sys_entity_pure.vmt"
If you want VertexLitGeneric, as told above, you do not need this step.

If you want anything else (notably UnlitTwoTexture), please contact me. Note that Refract is incompatible with the code. If you make a scope lens, you will therefore need to make it the old way with an envmap, or use _rt_FullFrameFB.
⑧ Optional tweaks
Congratulations! If you reached that step, it means your new or updated RNG/SYS mod now works. You might need to redo the previous steps for all others VMTs (you can copy&paste).
📌 If you ever do a mod with the Full Guide, just know that the steps are the same. You can actually just swap the code you copied with one that's only featured in the Full Guide and it will also work. You just have more parameters to play with.

Now though, you probably noticed that there are other variables ($) than this $slotUsed that you might have modified. You can also modify these to trigger cool features.
Here's the list of what they do (alphabetical order):

$activateRNG
If you set this to 0, the user will only be able to change the skins with the Select Your Skins (SYS) and the randomization (RNG) will not randomize them. Useful if you want to offer non canon skins to only the users that want them (mainly hair colors)

$boomerEffects
If you set this to 1, and unquote (remove the // below), if will automatically activate the Boomer vomit effects, without the need to do the _it steps for this VMT.

$distancePerFrame
Increase this value by +1000 if you can visually see the skins change too often (if you do not want them to change within the map at all, just set $oneSkinPerMap to 1).

$frameOffset
If your VTF is used by multiple VMTs (or skinfamilies) that need to randomize independently, set this to 0 in the first VTF, then 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, and 78 in the next ones (in that order).

$injectIntoBumpMap
If you set this to 1, the $bumpmap frame will follow the $frame. Otherwise, the bumpmap will be the same for every skin.

$invisibleIsAlsoASkin
Set this to 1 in all VMTs of your mod if you set $invisibleIsAlsoASkinHere to 1 in any VMT of your mod

$invisibleIsAlsoASkinHere
Set this to 1 if you want that in addition to all your skins, your VMT can also turn invisible as a skin (useful to hide clothes or gun attachments). If you set this to 1 for any VMT, you need to set $invisibleIsAlsoASkin to 1 in all VMTs (including the one with $invisibleIsAlsoASkinHere set to 1)

$invisibleNotInRNGPool
Set this to 1 if you want that the 'invisible' skin you activated with $invisibleIsAlsoASkinHere can only be selected by the user in SYS Mode (useful if you want to add R18 options with clothes hiding that only the user can choose).

$meleeBloodEffects
If you set this to 1, and unquote (remove the // below), if will automatically activate the Melee Blood effects, without the need to do the steps for this VMT.

$oneSkinPerMap
If you set this to 1, the skin selected will be the same on all the objects on the map. It is recommended to set this value to 1 for survivors mods because that's the only way to make their dead corpse match the skin they had while alive. (This is like the old 'True RNG')

$proxThreshold
Increase this value by +100 if you can visually see the skin of your item change when you approach it (maximum recommended of 1000).