Left 4 Dead 2

Left 4 Dead 2

54 ratings
Select Your Skins [SYS] (Modders Guide)
By Ellie
This Guide explains to L4D2 Modders how to add SYS and RNG to their mods.
   
Award
Favorite
Favorited
Unfavorite
Tl;dr
This Guide is the full length version that aims to (re)explain everything about SYS and RNG, answering as many questions as possible. You might not need most parts of it, but it's a good read if you ever were interested in making RNG mods. It has never been so simple.

Keep in mind that even if the read will probably take you 15-20 minutes, it's a one time read. Once you will have made your first mod with the system, and understood the concept, it takes just seconds to implement, provided that your textures are ready.

Although, since I know that most of the time, more is not always best, I also made a quick version of this Guide : SYS Made Simple, that you can look up here:
https://sp.zhabite.com/sharedfiles/filedetails/?id=2309371158&preview=true
❔ Also, if you have any problem, feel free to ask your question to me on my profile or in the Dead 4 Mods Discord Server[discord.gg] or said group.
General Information
Difficulty :
The difficulty can be higher for technical mods like Color randomization or ''Model'' randomization

Short description : Select Your Skins (SYS) is an extremely powerful and simple way to make RNG Mods for L4D2, in other words, mods that lets the user randomize and/or choose what skin he wants for a character, a gun, an item, an infected, or actually anything in the game.
This system is better than the RNG in every way, and includes the last generation RNG codes as well as powerful features for modders to toggle by just changing 0's into 1's.

https://sp.zhabite.com/sharedfiles/filedetails/?id=2325990437
🛠️ Important : This Guide assumes that you already know how to make a basic mod for L4D2, like a texture replacement mod. It will not explain again all the basics, but does explain again how to make a VTF file with multiple textures (in an [Appendix] at the end).

Needed skills :
  • Knowing how to edit a VMT file
  • Knowing how to import a VTF file
Special skills for certain variants of SYS/RNG:
  • Basic 2D Graphics Software knowledge for Color RNG
  • Basic 3D Tools Software knowledge for 'Model' RNG
What is "Select Your Skins" ?
Select Your Skins (or simply SYS) is a series of VMT scripts that are a complete new take on the infamous RNG system. It does almost everything that RNG was capable of, but also includes many new options and features, that can be toggled simply by changing a variable.
  • For the end user, it first of all does what RNG always did: randomize the textures, the models, or the colors of an entity in the game world. However, the SYS system can also let the user randomize again all the mods on the fly with a simple key press.
  • For the modder, it comes in the form of a code to copy and paste in VMTs to activate everything, with a lot of options to customize, and a slot system to use.
🚩 If you are reading this, and are a Modder that already made mods with RNG, you can sort of forget (almost) everything you knew about RNG or randomization. Everything in this Guide was coded from scratch using all what I learned in 5 years about VMTs. Everything is made as simple as possible for both the user and the modder.

New features brought by SYS compared to the old RNG
  • The user can randomize again, on the fly, all the items made with SYS
  • The user can select his own skin, live in game
  • The user can switch live between either his selected skins (SYS) or RNG
  • The user can lock the skin, live in game, forever
  • Skins locked with SYS can even apply between models (i.e. chopper and crashed chopper)
  • You do not need to input the amount of frames of your VTF file anymore
  • Options to make the skin in hand match the one the user picked
  • Options to make world objects have multiple skins per map
  • Extremely powerful and simple version of Color RNG with 999 colors
  • Extremely powerful and simple version of Model RNG (Loadout system)
  • Code optimized to the extreme, avoiding any load bearing operations (runs at 300fps)
  • Usage of a CORE Mod to automatically update all released mods with new tech
  • Availability of a HUD Mod to let the user know what he is doing with the keys

Questions and Answers (Q&A)
Q : On what does it work ?
On almost everything (notable exceptions are particles and gun lenses with the Refract shader).
Q : Does it work online ?
Yes, provided that the server allows mods (not in Versus).
Q : When does the skin selected by the user resets ?
It doesn't. It stays between maps, campaigns, and even when the user exits L4D2. The user can truly, once and for all, select the skin he wants, and lock it, forever.
Q : Is it only for textures or also for different models ?
SYS cannot randomize bodygroups, but it can make VMTs appear or disappear. For instance, if you have a gun with a silencer, a "skin" could consist of hiding the silencer VMT, therefore changing the ''model'' by making a VMT invisible. The limitation is that the glow outline and shadow will still take the silencer into account.
Q : If the user does not or cannot use the SYS options, will it still work ?
Even if the user does not or cannot use the SYS keybinds, everything (mainly the randomization) will still work, and better than the RNG ever did.
Q : Can I update a RNG mod so it will work with SYS ?
Yes, but beware that if you straight up follow the patch {} method, your users will need to CORE Mod. Therefore, you'll need the inline variants at the end of this Guide
Q : What is this ''slots'' system you talked about ?
There are 30 slots. 12 of them are for survivors mods (10 are assigned), and the other 18 (13 to 30) can be used for anything. However, two items that use the same slot will change together. Therefore, the end user can theoretically not have two mods that use the same slot. If he does, it doesn't break, but changing a skin will also change the other one.
Q : 30 is not much. Will there be more in the future ?
The slots are actually unused or rarely used game varaibles. The 30 I selected are the least intrusive, but it's hard to find other ones. It would be possible to bump the slots to 60, but that would disable the use of a gamepad. I might try to add slots in the future if too many mods are done with the SYS system.

How much time does it take to add this to a mod ?
This is a copy and paste level of difficulty. If you have the textures ready, it actually takes less time than RNG to implement because you do not even need to specify how many skins you have anymore (the code automatically checks how many frames are in your VTF).

Visual examples
All examples are captured in real time. Every skin change is controlled by the user.






RNG and L4D2 Crashes
Before heading to the main content of this Guide, I take the opportunity to give anyone that reads this hints about RNG mods and L4D2 crashing.

RNG mods trend to crash the game more often than other mods. Actually, if it's true that they do crash the game more often, it's also true for a lot of HD or 4K mods.

The reason is simple. L4D2, being an old game, cannot cache more than 4 Gb of textures when a map loads. However, for RNG mods, the game actually caches all the frames of the texture, and not only the one that end up being displayed.

This means that the more skins you have in a texture, and the bigger the texture is, the more cached memory it will use, and therefore, the faster you'll hit that 4 Gb mark where it will crash to the desktop (CTD) when a map loads.

For crashes that are not CTDs when the map loads or just after it loads, usually, RNG is not responsible. An infamous problem is the "Bill Corpse" problem, where mods that replace the Bill Corpse and use the same textures for it as for the "live" model cause a crash due to RNG, but that's really all there is to it.

As of now, I have no proof at all, not even evidence, that big VMT structures with a lot of Material Proxies (VMT coding) cause game crashes. The SYS Code itself runs without any frame drops at 300fps. Also, mods with very complex VMT coding that I released in 2016, like this one and this one, didn't cause notably more crashes than old ones.

Still, in the end, what you need to remember is that, as of today, if you want to diminish the risk of crashes in your RNG or SYS mods, you should:
  • Try to limit the amount of skins (VTF) you use, if possible, less than 10.
  • Try to limit the size of the textures the user can choose (2048x2048 should be the maximum limit if under 10 skins, and 1024x1024 the limit if over 10 skins).
  • Try to avoid also randomizing the $bumpmap.
  • Try to use Color Randomization whenever possible (it only uses one frame).
  • Try to randomize parts of the models (model RNG) instead of texture RNG (see SYS Loadout).
📋 Before starting
Before starting your first SYS/RNG mod, there are things you need to do and choose.
Keep in mind that this is actually the longest part.

Even if it is the longest, it's nontheless super easy and you will need practically no skills. I spent a lot of hours of my time so it can be the easiest possible for you, the end user. Are you ready ?

This section will be divided in 5 parts:
  • Select the SYS variant you want.
  • Prepare the stuff you need for this variant (VTF with multiple frames etc.).
  • Remove the incompatible parts of the VMT just before copying the code.
  • Select the slot you want to use (and if you want to use a Slot).
  • Check that you have everything and the double }} at the end of the VMT.
➊ Select the SYS variant
The SYS (and RNG) system comes in many variants. There are also variants of variants.
Therefore, once and for all, I made a list of what I think you should use.
For the actual descriptions of what every variant does, you'll need to scroll after this list.
📍 Note that the order in which the variants are listed is the order you should consider. If possible, use the first variant, if not, the second one, and so on. However, if you want the ''model'' (attachments) to be randomized with VMT hiding, use SYS Loadout (+Pure) in priority
🏳️ Note that it is possible to use two variants on different VMTs of a same mod. Although, if the VTFs that go with these VMTs do not have the same number of frames, it will cause them to not always be synchronized. This unsyncing can actually cleverly be used to let the user choose between more skins (more info at the end of the Guide).
⚠️SYS Color is not compatible with the use of transparancy ($translucent or $alphatest). Do not use it if the VMT that must have it must also be transparant/translucent.

Zoey
Francis
Louis
Bill
Rochelle
Coach
Nick
Ellis
Tank
🔴 SYS Entity + Realistic Damage
🔴 SYS Color + Realistic Damage
🔵 SYS Entity
🔵 SYS Color
⚫️ SYS Loadout

Charger
Boomer
Smoker
Hunter
Jockey
Spitter
Witch
🔵 SYS Entity
⚫️ SYS Loadout

Weapons/Guns
Medkit
Pain Pills
Adrenaline
Pipe Bomb
Molotov
Bile Jar
Fireworks
Jerrycans
Oxygen tanks
⚪️ SYS Entity Pure
⚪️ SYS Loadout Pure (use this if you want random attachments)
🔵 SYS Entity
⚫️ SYS Loadout (use this if you want random attachments)
⚪️ SYS Color Pure
🔵 SYS Color

Medkit
Tank Rock
Ammo piles
Laser Boxes
Chopper pilot (alive)
Gnome
Defibrillator
Machine Guns
Explosive Ammo
Fire Ammo
Soda
Medkit Cabinets
Computer screens
Escape vehicles
Doors that open
🔵 SYS Entity
⚫️ SYS Loadout
🔵 SYS Color

Vending Machines
Paintings
Trash
Radios
Books
Ads
Magazine Racks
Billboards
Posters
Cars
Trucks
Signs
And anything else that is static in a map.
🔶SYS Map
⍟ (Variants descriptions)
📌Note that for every variant, you can choose to not use the SYS (skin selection) features and only use the RNG (randomization) features (or the opposite).
📌Note that every variant also comes with the possibility for the user to randomize everything again when he presses on the corresponding key (you can toggle that off as the Modder).

🔵SYS Entity
sys/sys_entity.vmt
This is the basic and classic version. It corresponds to both True and Real RNG under the old names, and it offers all these features:
  • Randomizes all the frames of the $basetexture VTF (multiple textures)
  • Choose between One Design per map or Multiple Designs per map (but the one the user picks does not match the one he picked)
  • Possible to define that "invisible" is also a skin (useful to make attachments or clothes disappear, like a cheap model RNG)
  • Includes Boomer vomit effects module
  • Includes Melee weapon blood effects module

🔵SYS Color
sys/sys_color.vmt
This is the Color randomization variant, that corresponds to the old Color RNG. Its main usage is to allow the user to select between 999 different colors that will be applied to the VTF texture or (if the user has the shaders on medium or high), parts of said texture. It offers these features:
  • Randomizes the color of the $basetexture between 999 possibilities
  • Easy way to define what parts should share the same color
  • Possibility to randomize the $basetexture too (i.e. different clothes patterns)
  • Possibility to assign a different slot for the $basetexture
  • Choose between One Design per map or Multiple Designs per map (but the one the user picks does not match the one he picked)
  • Includes Boomer vomit effects module
  • Includes Melee weapon blood effects module

⚫️SYS Loadout
sys/sys_loadout.vmt
This version is a brand new version that does not work like nor corresponds to any prior RNG version. This is the main version to use for ''Model'' RNG (VMT hide/show).
This version lets the user define up to 9 "Loadouts". For each Loadout, the user can define what frame the texture should take, and/or if the texture should be invisible. The code then randomizes the loadouts. It was mainly developed for guns randomization, but it can also be used for anything else that allows for it.
  • Randomizes between the (maximum of) 9 loadouts the user defined.
  • The user can individually decide if the VMT must show for each loadout
  • The user can individually decide what frame (skin) must show for each loadout
  • Choose between One Design per map or Multiple Designs per map (but the one the user picks does not match the one he picked)
  • Includes Boomer vomit effects module
  • Includes Melee weapon blood effects module

⚪️SYS Pure (Entity / Color / Loadout)
sys/sys_entity_pure.vmt sys/sys_color_pure.vmt sys/sys_loadout_pure.vmt
This is a variation of the three previous versions. Even if it is experimental, it is the most powerful randomization available for weapons and items. It corresponds to the Pure RNG under the old names, but unlike what was previously the case, it does not require model edits anymore.

This version will actually let you have in hand the gun / item you picked up. Unlike 🔵SYS Entity, the skin in first person (in hand) can actually change to match what you picked.
  • Multiple designs per map, but ''clusters'' all share the same textures
  • The skin in hand matches the last skin the player approached
Originally posted by you:
If this stuff is so powerful, why ever use the other ones ?
There are scenarios where the other 🔵⚫️ SYS are still better than the ⚪️SYS Pure:
- If what you mod is the only one of its kind in the map (survivors / escape vehicles...)
- If you hate the fact that clusters of items share the same texture
- If you hate the fact that nearby objects will transfer their skin to the first person one

🔴SYS Realistic Damage (Entity / Color)
sys/sys_entity_dmg.vmt sys/sys_color_dmg.vmt rdmg/sys_v1.vmt
This is a variation of the SYS Entity and Color, that includes basic Realistic Damage options. This is only made to be used on Survivors and on the Tank. Here are the additional features it offers compared to SYS Entity and Color:
  • Activates Blood effects when the survivor has low health.
  • Possibility to choose the shape of the blood stains
  • Possibility to choose the scale of the blood stains
  • Possibility to choose if using a Medkit heals the blood or not (for each VMT)
  • Random blood position every map
https://sp.zhabite.com/sharedfiles/filedetails/?id=2235890807
🔶SYS Map
sys/sys_map.vmt
This version is the one you must use if you make a mod for something that is static on a map.
You can choose to have one design per map, like in the old True RNG version.
However, this 2020 version can for the first time provide multiple different designs per map (i.e. the vending machines at the start of the map have a specific skin, but the ones further in the map have another one). It uses the Player position to actually tweak the RNG. This means that sometimes, if you do not select the "One design per map", you might come across different skins within the same map, even though it is the same model.
  • Randomizes all the frames of the $basetexture VTF (multiple textures)
  • Choose between One Design per map or possibly Multiple Designs per map
  • Possibility to define the size of the 'grid' that triggers a skin change
  • Includes Boomer vomit effects module
  • Includes Melee weapon blood effects module
❷ Prepare the materials
After you choose your variant, you will need to prepare stuff depending on what variant you chose.
This stuff is the same as with the old RNG. It can be:
  • Make a VTF file with multiple frames (textures) to randomize the $basetexure
  • Make a VTF that has an alpha mask to tell the game what parts to color
  • Divide 1 material (VMT ≠VTF) in 2 VMTs if they need to randomize independently*
  • Making sure the world model and view model VMTs share the same VMT file*
* How to do this is not explained in this Guide. It requires a 3D Tool like Blender or Maya, but if you know how to use one of these tools, you probably know how to do this anyway. If the world model and view model do not share the same VMT, what happens is that they will be randomized independantly in RNG Mode, but they will however still match if SYS (Skin Selector) is used.

Making a VTF with multiple frames for the $basetexture is not the focus of this Guide, but you can find instructions on how to do it in an [Appendix] at the end of this Guide.
This is generally required for:
- 🔴 SYS Entity + Realistic Damage
- 🔵 SYS Entity
- ⚪️ SYS Entity Pure
- 🔶 SYS Map
This is optional for these, if you chose to only randomize the color / model (visibility).
- ⚫️ SYS Loadout
- ⚪️ SYS Loadout Pure
- 🔵 SYS Color
- ⚪️ SYS Color Pure
- 🔴 SYS Color + Realistic Damage

Making a VTF with an alpha mask for the parts to be colored for Color randomization is not the focus of this Guide either, but you can find instructions on how to do it in an [Appendix] at the end of this Guide.
This is generally required for the Color variants:
- 🔵 SYS Color
- ⚪️ SYS Color Pure
- 🔴 SYS Color + Realistic Damage

Once you have either a ☑ VTF with multiple frames, a ☑ VTF compatible with Color RNG, or ☑ VMTs that can be shown or hidden for separate attachments (SYS Loadout), you can continue.

➌ Clean up the VMT
In a few moments, to activate everything, you will just need to copy stuff in the VMT.
However, you need to prepare the VMT and remove a bunch of stuff that might be in the VMT and that is not compatible with the SYS System.
Note that not all of these things will be in your VMT file. But everything listed here must be removed.

VertexLitGeneric
At the beginning of your VMT, you might see something like this:
VertexLitGeneric {
Remove that (also remove the {)

patch
At the beginning of your VMT, you might see something like this (note that you might have a different file path after the include):
patch { include "materials/models/survivors/survivors_it_shared.vmt" insert {
Remove that (also remove the two {)

Proxies
In the middle of your VMT, you might see something like this (it can also say "Proxies" with "):
Proxies {
Remove that and also ❗️ remove absolutely everything that comes after it.

Note that at this point, you should only have lines that begin with parameters ($)

Custom variables
This one is more tricky. But you probably do not need to do it if you did not delete the Proxies stuff from the previous step. However, if you did delete a Proxies block, you might need to delete some more stuff. This is not always required, but if you get a waterfall or errors in the console, it's probably that you did not do this step right.

You need to also delete the custom variables that the Proxies block you just deleted might have used. The only way to know what is a custom variable is to know what actually isn't. For example, $basetexture is definitely something the game uses, so you should not delete that line.

To try and simplify the thing, I listed the commons "custom variables" the game and the former RNG codes use. If you see any of these things, remove the whole line:
$blueOscillation $check $corrtoapply $detailAmount $docorr $docorr $dostore $er $fh $framec $framecdo $framenumber $greenOscillation $inject $inval $ITAmount $itemid $itemtocheck $itemtocheckr $maxX $maxY $maxZ $minX $minY $minZ $mo $nn $numberoflastframeplus $objlimit $objnumber $one $pf $pos $poscheck $ramp $rand $randstop $randtwo $randtwostock $realrngtime $redOscillation $rngtime $rngtimecorr $rngtimeinvert $selected $stock $storeframe $timestop $two $weareinstoretime $wecanstore $zero
➍ Select the slot
The last preparatory step is to select the slot you will use.
❗️ If you are making a mod for something that the player has little to no interest of changing himself (like plants, trash, ads, the color of cars), it is better to skip this step and to not select any slot. Everything will still be randomized, but this way, you will not waste precious slots for other modders to use for mods that the user had more interest of changing.
You could select the slot at random, and you might actually do that if you were the only Modder left on this planet, but you need to think a bit about the other modders.
It is of common interest that all modders use the same ranges of slots for the same items or survivors. Imagine that: if all Zoey mods use the slot 1, then all mods are compatible with eachother. However, if a Shotgun and a Sniper from two different modders both use the slot 17, the user will have to choose between one of them if he wants to use the SYS options (even though he can still use the RNG options).
🔔 As a reminder, what happens when 2 mods use the same slot is that they will be linked when the user change skins. It will not break the SYS tech and will not cause crashes, but it will be impossible or tedious for the user to make sure both mods have the skin he wants. Moreover, the user that uses 2 mods with the same slot might not even be able to select any of those skins combinations.
Also, note that it's possible to release a "Slot Activation Mod" (or SYS activation mod) as a separate addon for your users. This way, you could, for example, not put the SYS options in your base mod, to avoid slots conflicts, but release a separate mod for your users just to bind your mod to a slot. More info about it can be found under the 🗂️ Make a slot change addon section at the end of this Guide.

This being said, please try to respect this list when you choose the slot you will use, or at least, choose a nearby slot if you cannot use the one normally dedicated to it:

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)
➎ The double } and last check
The last thing you need to make sure before copying the code at the top of your VMT is to make sure that at this point, it contains only variables (lines that start with $), and has a double } at the end.

For example, this is how the producer_body_it.vmt file should look just before copying the code.
$baseTexture "models\survivors\producer\p_white" $bumpmap "models\survivors\producer\producer_body_normal" $phong 1 $phongboost "2.5" $phongexponent 5 $phongtint "[.85 .85 1]" $halflambert 0 $phongfresnelranges "[.3 .65 30]" $ambientocclusion 1 $diffuseexp "1.5" } }
Note that there is this double } at the end of the VMT
Note that there is no line that begins with anything else than a $

Checklist
At this point, you must have:
✔️ A VTF with multiple frames or a VTF for color RNG or VMTs to hide/show
✔️ Chosen what version of the SYS you will use, depending on the above
✔️ Removed any line in your VMT that did not begin with $, as well as the custom variables
✔️ The double } at the end but nothing at the top of the VMT
✔️ Selected the slot to use or you chose to not use a slot (and not use the SYS options)
⚙️ Copy the code
Now has come the time to copy the code at the top of your VMT. All the codes are listed thereafter, and you just need to CTRL+C and CTRL+V the one you selected.

After you will have copied the code, there will be one more last step, that I will explain right now.

In the code you will copy and paste in a few seconds, you will see this:
$slotUsed "0"
  • If you chose a slot, change that value of 0 into the n° of the slot you decided to use.
  • If you chose to only activate the RNG (randomization), just let the default value of 0.

Note that all parameters ($) included in the code you will copy are explained in detail afterwards in the last part of this Guide. You do not need to modify them, but it offers new options you can discover to fully customize your mod.

➡️ If you are using ⚫️ SYS Loadout or ⚪️ SYS Loadout Pure, you will still need to change other things in the code, mainly $loadoutsInUse. Please refer yourself to the list of the parameters hereafter.

➡️ If you are using anything else, copying the code (and changing that $slotUsed) is the very last step and your mod will work right after, even if you can still customize some parameters.

✳️ ... but if you want the shader to be UnlitGeneric or LightmappedGeneric, you will need another 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"
🔵 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 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
🔵 SYS Color
//--------------------------------------------------------------------------------- patch { include "rng/sys_entity_color.vmt" insert { /////////////////////////////////////////////////////////////////////////////////////////////// $slotUsed "0" // Change this to your slot number if you want SYS $oneSkinPerMap "0" // Set to 1 to limit the RNG to 1 skin per map $VMTColorOffset "0" // VMT sharing the same value here will share colors $speedColorFactor "1" // Speed of color change in SYS Mode (minimum = 1) $activateEXTR "0" // Set to 1 to randomize the $basetexture frames $slotUsedFrame "0" // If you have multiple frames, it will use that slot $activateColorRNG "1" // Set to 0 to deactivate color RNG (but allow SYS) $originalColor "[1 1 1]" $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 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
⚫️ SYS Loadout
//--------------------------------------------------------------------------------- patch { include "rng/sys_entity_loadout.vmt" insert { /////////////////////////////////////////////////////////////////////////////////////////////// $slotUsed "0" // Change this to your slot number if you want SYS $loadoutsInUse "1" // How many loadouts you are using (1-9) $oneSkinPerMap "0" // Set to 1 to limit the RNG to 1 skin per map $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 $FRAMEloadout1 "0" // For each loadout, n° of the frame that must show $FRAMEloadout2 "0" $FRAMEloadout3 "0" $FRAMEloadout4 "0" $FRAMEloadout5 "0" $FRAMEloadout6 "0" $FRAMEloadout7 "0" $FRAMEloadout8 "0" $FRAMEloadout9 "0" $ALPHAloadout1 "1" // For each loadout, 1 = visible, 0 = invisible $ALPHAloadout2 "1" $ALPHAloadout3 "1" $ALPHAloadout4 "1" $ALPHAloadout5 "1" $ALPHAloadout6 "1" $ALPHAloadout7 "1" $ALPHAloadout8 "1" $ALPHAloadout9 "1" $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 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
⚪️ 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 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
⚪️ SYS Color Pure
//--------------------------------------------------------------------------------- patch { include "rng/sys_entity_color_pure.vmt" insert { /////////////////////////////////////////////////////////////////////////////////////////////// $slotUsed "0" // Change this to your slot number if you want SYS $oneSkinPerMap "0" // Set to 1 to limit the RNG to 1 skin per map $VMTColorOffset "0" // VMT sharing the same value here will share colors $speedColorFactor "1" // Speed of color change in SYS Mode (minimum = 1) $activateEXTR "0" // Set to 1 to randomize the $basetexture frames $slotUsedFrame "0" // If you have multiple frames, it will use that slot $activateColorRNG "1" // Set to 0 to deactivate color RNG (but allow SYS) $originalColor "[1 1 1]" $proxThreshold "500" // Increase this value if you see the texture change $toleranceThreshold "10" // Increase this value if you see the texture flicker $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 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
⚪️ SYS Loadout Pure
//--------------------------------------------------------------------------------- patch { include "rng/sys_entity_loadout_pure.vmt" insert { /////////////////////////////////////////////////////////////////////////////////////////////// $slotUsed "0" // Change this to your slot number if you want SYS $loadoutsInUse "1" // How many loadouts you are using (1-9) $oneSkinPerMap "0" // Set to 1 to limit the RNG to 1 skin per map $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 $FRAMEloadout1 "0" // For each loadout, n° of the frame that must show $FRAMEloadout2 "0" $FRAMEloadout3 "0" $FRAMEloadout4 "0" $FRAMEloadout5 "0" $FRAMEloadout6 "0" $FRAMEloadout7 "0" $FRAMEloadout8 "0" $FRAMEloadout9 "0" $ALPHAloadout1 "1" // For each loadout, 1 = visible, 0 = invisible $ALPHAloadout2 "1" $ALPHAloadout3 "1" $ALPHAloadout4 "1" $ALPHAloadout5 "1" $ALPHAloadout6 "1" $ALPHAloadout7 "1" $ALPHAloadout8 "1" $ALPHAloadout9 "1" $proxThreshold "500" // Increase this value if you see the texture change $toleranceThreshold "10" // Increase this value if you see the texture flicker $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 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
🔴 SYS Entity + Damage
//--------------------------------------------------------------------------------- patch { include "rng/sys_entity_dmg.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" $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 // ................................................................................. $ScaleBlood "0.5" // x2 to make the blood smaller, /2 to make it bigger $canOnlyGetWorse "0" // Set to 1 to stop Medkits from healing the blood $detail "models\infected\hunter\hunter_01_detail" // Better textures for the blood in the Realistic Damage Guide /////////////////////////////////////////////////////////////////////////////////////////////// // Code by Ellie, https://sp.zhabite.com/id/ellie_williams - 2020 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
🔴 SYS Color + Damage
//--------------------------------------------------------------------------------- patch { include "rng/sys_entity_color_dmg.vmt" insert { /////////////////////////////////////////////////////////////////////////////////////////////// $slotUsed "0" // Change this to your slot number if you want SYS $oneSkinPerMap "0" // Set to 1 to limit the RNG to 1 skin per map $VMTColorOffset "0" // VMT sharing the same value here will share colors $speedColorFactor "1" // Speed of color change in SYS Mode (minimum = 1) $activateEXTR "0" // Set to 1 to randomize the $basetexture frames $slotUsedFrame "0" // If you have multiple frames, it will use that slot $activateColorRNG "1" // Set to 0 to deactivate color RNG (but allow SYS) $originalColor "[1 1 1]" // ................................................................................. $ScaleBlood "0.5" // x2 to make the blood smaller, /2 to make it bigger $canOnlyGetWorse "0" // Set to 1 to stop Medkits from healing the blood $detail "models\infected\hunter\hunter_01_detail" // Better textures for the blood in the Realistic Damage Guide /////////////////////////////////////////////////////////////////////////////////////////////// // Code by Ellie, https://sp.zhabite.com/id/ellie_williams - 2020 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
🔴 Damage alone
This code the VMTs of your model that needs to have blood on them when the survivor takes damage, but that do not have any SYS or RNG options (like the bare skin of your character).
//--------------------------------------------------------------------------------- patch { include "rdmg/sys_v1.vmt" insert { /////////////////////////////////////////////////////////////////////////////////////////////// $ScaleBlood "0.5" // x2 to make the blood smaller, /2 to make it bigger $canOnlyGetWorse "0" // Set to 1 to stop Medkits from healing the blood $detail "models\infected\hunter\hunter_01_detail" // Better textures for the blood in the Realistic Damage Guide /////////////////////////////////////////////////////////////////////////////////////////////// // Code by Ellie, https://sp.zhabite.com/id/ellie_williams - 2020 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
🔶 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 /////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------
$activateEXTR
$activateEXTR "0"
This parameter is for SYS Color. If you set it to 1, it will randomize the $basetexture skins (frames).
For example, you could have a $basetexture with 3 frames for a bikini. One plain bikini, one bikini with white dots that stay white, and one bikini with stripes that (half) stays white. The code will then randomly select one bikini variant, and will assign a random color to it.

If you want the user to be able to change the $basetexture (here: bikini) with the SYS, you need to define $slotUsedFrame; usually, you can set the same value for it as for $slotUsed.

No matter what you choose, this only matters when RNG Mode is active.
🔎 Something interesting you can do with this is to actually allow one of your skins (only) to have a random color. If your $basetexture has, let's say, 4 skins, but the first 3 have an all black alpha channel in the VTF, the code will not color them, and the 4 one, with its white alpha channel, will be colored. Note though that everything will be colored with the user has his shaders on LOW or MEDIUM.
$activateRNG
$activateRNG "1"
You can change this value to 0 to disable the RNG options.

If you defined a slot with $slotUsed, the SYS options will still be avaliable.

If you disable the RNG options, the skin that will be used when RNG is active will always be the one in the first frame (n°0).
💡 This option might be useful if you want to offer non canon skins to your users, but do not want these non canon skins to appear if the user do not select them (i.e. flashy hair colors etc.)
$activateColorRNG
$activateColorRNG "1"
You can change this value to 0 to disable the Color RNG options.

If you defined a slot with $slotUsed, the SYS options will still be available.

If you disable the Color RNG options, the color that will be used when RNG is active will always be the one you specify in $originalColor.
💡 This option might be useful if you want to offer non canon colors to your users, but do not want these non canon colors to appear if the user do not select them (i.e. flashy hair colors etc.)
$ALPHAloadout[.]
$ALPHAloadout1 "1" $ALPHAloadout2 "1" $ALPHAloadout3 "1" $ALPHAloadout4 "1" $ALPHAloadout5 "1" $ALPHAloadout6 "1" $ALPHAloadout7 "1" $ALPHAloadout8 "1" $ALPHAloadout9 "1"
For each loadout in use (see $loadoutsInUse), you can specify manually if the VMT is visible (1) or invisible (0). By default, the VMT is visible for every loadout (hence the values of 1).
💡 Obviously, when a value, for example, $ALPHAloadout2, is equal to 0, it doesn't matter anymore what value $FRAMEloadout2 has, since it will be invisible anyway.
$boomerEffects
$boomerEffects "0" // $detail "models/survivors/survivor_it" // $detailscale 3 // $detailblendfactor ".001" // $detailblendmode "0"
You can change the value of $boomerEffects to 1 to activate the Boomer effects on your survivor (puke when the Boomer vomits). If you do this, you do not need to do any of the _it steps from other guides.

If you activate the Boomer effects, you also need to unquote (remove the //) that are here
$canOnlyGetWorse
$canOnlyGetWorse "0"
This variable is only useful for the Realistic Damage variants.
If you set the value to 1, a Medkit will not heal the blood anymore, until the next map.
💡 All VMT do not need to share the same value. You could set this to 1 only for the clothes VMT. This way, when the survivor uses a Medkit, it removes the blood on his skin, but not on his clothes.
$detail (blood)
$detail "models\infected\hunter\hunter_01_detail"
This variable is the path to the $detail texture to be used for the blood effects. By default, it uses a low resolution texture that is in the game files.

However, if you want crisp HD Blood, you can check the textures includes in this guide under the [Appendix] Blood textures on Ellie section (note that if you use the textures from this Guide, mod, you and your subscribers will also need to subscribe to this mod)
https://sp.zhabite.com/sharedfiles/filedetails/?id=2235890807
💡 Usually, I get the best results by using bloodmaps/Blooddrops_darker for the face&skin and bloodmaps/CartoonBlooddrops_darker for the clothes, with a value of $ScaleBlood between 0.25 and 1 (the scale can vary between VMTs. Usually, I use 0.25 for the face)
$distancePerFrame
$distancePerFrame "4000"
This parameter only exists in SYS Map. It defines the size of the "grid", and the skin changes if the player goes to another grid square.
In other words, this value is how many units the player will have to travel in order to see the next skin if he has just seen the skin change.

What you need to know is that you need to increase this value if you see the skins change too often, and you should lower it if you do not see them change at all in a same map. Any value below 1000 will result in a quasi guarantee you will visually see the skin change.

💡 Maps are rarely more than 10000 units long, so any value above 10000 will probably be the same as one skin per map or almost.
$FRAMEloadout[.]
$FRAMEloadout1 "0" $FRAMEloadout2 "0" $FRAMEloadout3 "0" $FRAMEloadout4 "0" $FRAMEloadout5 "0" $FRAMEloadout6 "0" $FRAMEloadout7 "0" $FRAMEloadout8 "0" $FRAMEloadout9 "0"
For each loadouts in use (see $loadoutsInUse), you can specify manually what is the n° of the frame that must show. The frames do not need to be in order, a frame can be used multiple times, and you do not need to use all the frames.
💡 There is a frame n°0. The n° of the frame corresponds to the one you can see in VTFEdit when you switch the frames (see [Appendix] VTF with multiple textures at the end of this Guide)
💡 The frame n° should never be higher than 8 (if you use a different frame for each loadout)
$frameOffset
$frameOffset "0"
Modifying this value will offset the frame for this specific VMT. This is useful to desynchronize multiple objects that otherwise use the same VTF file (i.e. different paintings). It's useless to change this value if your VTF file is only used by a single model that does not have multiple skinfamilies.
$injectInto[...]
$injectIntoFrame "1" $injectIntoDetail "0" $injectIntoBumpMap "0"
By default, the skin is injected into the $frame. You can set $injectIntoFrame to 0 so it's not injected into $frame anymore.

You can set $injectIntoBumpMap to 1 if you have different bumpmaps for every frame (however, this trends to make your mod even heavier for really few advantages, so I do not recommend to use multiple bumpmaps)

$injectIntoDetail will change the $detail frame. However, it will (still) use the $basetexture to count how many frames you have (unless you are using the Loadout variant). To fully use $detail instead of $basetexture, you need to set $injectIntoDetail to 1, $injectIntoFrame to 0, and...

...replace what's after the include near the beginning of your VMT by one of these depending on what you are currently using:
rng/detail/sys_entity.vmt rng/detail/sys_entity_pure.vmt rng/detail/sys_map.vmt
$invisible[...]
$invisibleIsAlsoASkin "0" $invisibleIsAlsoASkinHere "0" $invisibleNotInRNGPool "0"
These parameters let you add in a simple way an extra "invisible" skin for your whole VMT.
This means that in addition to all your skins (frames of your VTF), the code will automatically add one more invisible skin.

If you want to use this feature, you need to do the following:
  • In EVERY VMT of your model that has the SYS Code, set $invisibleIsAlsoASkin to 1
  • In the VMT(s) THAT CAN DISAPPEAR, also set $invisibleIsAlsoASkinHere to 1
Note that when the user reaches the "invisible skin", the skin of the other VMTs will be the skin of the last frame of your VTFs (they will just keep the previous skin just before looping).

$invisibleNotInRNGPool can be set to 1 so that the "invisible" skin does not show in the randomization pool but can only be selected by the user with the SYS options.
💡 Setting $invisibleNotInRNGPool to 1 can be a nice way to offer a nude skin (disappearing clothes) in SYS Mode without risking that this nude skin shows up randomly in RNG mod.
🔩 You could actually not have a single skin and this feature will still work. It would switch your VMT between visible and invisible, creating a very cheap Model RNG without the need of SYS Loadout.
🔎 If you want only specific parts of your VMT to disappear, the best way to do it is to make sure your textures have different alpha channels and use them for transparency (then set $translucent 1 or $alphatest 1). Even if the "skin" is the same (it doesn't need to be), the alpha channel will be different, and different parts of your texture will disappear as different 'skins'.
$loadoutsInUse
$loadoutsInUse "1"
This parameter is only for SYS Loadout. You need to tell the code how many loadouts you are using for your mod, because he cannot guess it alone.
The number must be between 1 and 9 since there is a maximum of 9 loadouts.
$oneSkinPerMap
$oneSkinPerMap "0"
You can change this value to 1 to force only one same skin per map (in other words, one skin will be selected at the beginning of the map, and all the objects in the map will share this same skin).
No matter what you choose, this only matters when RNG Mode is active.
💡 This option is recommended for survivors. Using it will ensure that the dead corpse of the survivor matches the skin of the alive one. However, it will therefore not allow for multiple skins on servers that allow more than 4 survivors.
💡 This option might be useful when you hate the fact that the skin in first person does not match the one you pick, and if you also hate the "Pure" variants that tries to fix this problem.
$proxThreshold
$proxThreshold "500" $toleranceThreshold "10"
These parameters are specific to the Pure variants of SYS.
The only thing you need to know is that you should:
  • Increase the value of $proxThreshold by +100 if you sometimes see the texture change
  • Decrease the value of $proxThreshold by -100 if you think the skin in hand change randomly
  • Increase the value of $toleranceThreshold by +10 if the skin flickers when you approach it
🔩 These two values define when the Pure RNG change the skin in hand and in the world. By default, the values of 500 and 10 mean that the code changes the skin (in hand and in the world) when the player is 500±10 units away from the item, provided that the item is loaded in memory. The effect is the same as if the player had pressed on the "Reroll RNG" key, except that it locks the skins.
$speedColorFactor
$speedColorFactor "7"
This parameter is only available for SYS Color.

The bigger the value, the faster the user can scroll through the color tones in SYS Mode.

However, beware that only a value of 1 can ensure that the user will see the 999 colors.

But more than just the speed of the color change, this value also determines how scrambled the colors are. A value of 7 guarantees a good balance between the scramble and the amount of colors.
⛔️ Do NOT use a value of 10/20/30/40..., or you will only have greens and blue tones.
If possible, use 2, 3, 7, 9, 11, 13 or 17.
💡 If 2 VMTs have different values for this parameter, they might begin to desynchronize colors, especially if the values are small prime numbers. See 📊 Desynchronise the VMTs at the end of this Guide for more information on that.
$originalColor
$originalColor "[1 1 1]"
This parameter is only useful when $activateColorRNG is set to 0 (color RNG disabled).

Since your VTF texture is white for Color RNG, you will need to manually tell the code what default color to display when RNG is active.

You will need to replace the three 1's by values from 0 to 1.
Using the Eye Dropper tool on Paint or Photoshop, determine what RGB values your texture has.

As an example, let's say your character has flashy pink hair (#ef569b).
The RGB values for this color are 239 (reds), 86 (greens) and 155 (blues).

You then need to divide these values by 255 :
  • 239 / 255 = 0.93 (Reds)
  • 86 / 255 = 0.33 (Greens)
  • 155 / 255 = 0.60 (Blues)
Then, remove the 0, and input them like this:
$originalColor "[.93 .33 .6]"
$ScaleBlood
$ScaleBlood "0.5"
This variable is only used by the "Realistic Damage" variants.
  • Multiply the value by 2 to make the blood stains smaller
  • Divide the value by 2 to make the blood stains bigger
💡 How the blood will look does not only depend on the value you input, but also of the size (resolution) of your texture. Therefore, on two different mods, a same value can give different results.
$slotUsed
$slotUsed "0"
This defines the slot the SYS System will use. Change the 0 into the n° of the slot you want to use.
Keep the default value of 0 to only activate the RNG options and not the SYS options.
DO NOT fully choose at random, look under "➍ Select the slot" to see what slot to use.
Two mods that share the same value will always change their skins together.
$slotUsedFrame
$slotUsedFrame "0"
This parameter is unique to SYS Color, and is required only if you have multiple frames for your $basetexture VTF. Therefore, it does nothing if $activateEXTR is set to 0.

If $activateEXTR is set to 1, you can define the slot that will make the $basetexture change without the change of color. Usually, it's safe to set this as the same slot as the $slotUsed.
$VMTColorOffset
$VMTColorOffset "0"
This is unique to SYS Color. You can change this by a value from 1 to 999, at random.
Each VMT on the same model that has the same value will share colors.
Therefore, let's say you have a VMT for a bikini top, and one for a bikini bottom. If you want them to have different colors when they randomize, just change the $VMTColorOffset for one of them.
💡 The closer the values of two VMTs are from eachother, the more often they should have similar colors, but note that it's actually a "loop" (1 is very close from 999).
🗃️ Inline upgrade from RNG
Since I know that some of you did old, cool mods with the old RNG system, maybe you are interested in upgrading these mods to this new RNG system.

Note though that a so called 'inline' upgrade will not allow your users to select their skins with the SYS Technology. It's not that it's technically not possible, it's just that right now, the technology is experimental, and the game data values used by the SYS System to store data will maybe change in the future. Therefore, it's too unsafe as of today to let you upgrade directly to the SYS.

Nonetheless, there are many cool features that are available in the new RNG system alone:
- The possibility for the player to randomize everything again with the "Reroll RNG" key.
- Items skins in hand that match the ones that were picked
- Multiple different skins per map for world objects

HOW TO UPGRADE
To upgrade from an existing RNG mod, you will need to replace everything you copied in the VMT the first time by a new code. There's no other change to do, unless you want to tweak the options (look above in that Guide for these options).

This means that you will first need to remove :
  • The "Proxies" block (everything from the line that say "Proxies" up until the last } at the very end (do not delete the last })
  • All the custom variables (the $) that came with the RNG when you copied it, mainly $rand.
You can look at examples below. Everything in red must be removed.



Once that stuff is removed, you just need to copy one of the below codes in your VMT (above the last }) and the RNG will be activated straight away with all the new features (your subscribers will not need the CORE Mod).

To this day, you can choose between:

🔵 Inline RNG Entity
🔵 Inline RNG Color
⚪️ Inline RNG Entity Pure
🔶 Inline RNG Map

To know which one you need, you need to go to ➊ Select the SYS variant.
🔵 Inline RNG Entity
//////////////////////////////////////////////////////////////////////////// $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" } }
⚪️ Inline RNG Entity 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" } }
🔵 Inline RNG Color
////////////////////////////////////////////////////////// $color "[1 1 1]" $blendtintbybasealpha "1" $oneSkinPerMap "0" // Set to 1 to limit to 1 color per map $VMTColorOffset "0" // VMT with same value here share colors $activateEXTR "0" // Activate frame randomization $boomerEffects "0" // Set to 1 and unquote for Boomer effects // $detail "models/survivors/survivor_it" // $detailscale 3 // $detailblendfactor ".001" // $detailblendmode "0" ////////////////////////////////////////////////////////// $checkMax "0.0" $maxFrame "0.0" $maxFramePlusOne "1.0" $countingFinished "0.0" $randEXTR "0.0" $randEXTRStored "0.0" $randEXTRInject "0.0" $randEXTROverflow "0.0" $injectEXTR "0.0" $RNGframeEXTR "0.0" $rerollRaw "0" $rerollRawStored "0" $rerollRNG "0" $randSYS "0.0" $randSYSTemp "0.0" $randSYSOverflow "0.0" $ramp "0" $prepareStore "1000.0" $randSYSStored "1000.0" $randSYSInject "0.0" $roundOffset "0.05" $randOffset "1000.0" $randOffsetDIV "100.0" $injectColor "0.0" $RNGInjectColor "0.0" $colorReds "0.0" $colorGreens "0.0" $colorBlues "0.0" $tempDIV "0.0" $tempMULT "0.0" $tempFRAC "0.0" $tempOFFSET "0.0" $CHOSENinjectColor "0" $boomerAmount "0.0" $bloodAmount "0.0" $mo "-1" $zero "0.0" $one "1.0" $two "2.0" $three "3" $four "4" $ten "10" $oh "100" $tff "255" $fh "500" $nnn "999" $ot "1000" Proxies { 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" } Add { srcVar1 "$maxFrame" srcVar2 "$one" resultVar "$maxFramePlusOne" } Divide { srcVar1 "$randOffset" srcVar2 "$ten" resultVar "$randOffsetDIV" } Divide { srcVar1 "$randOffsetDIV" srcVar2 "$maxFramePlusOne" resultVar "$tempDIV" } Frac { srcVar1 "$tempDIV" resultVar "$tempDIV" } Multiply { srcVar1 "$tempDIV" srcVar2 "$maxFramePlusOne" resultVar "$tempDIV" } Add { srcVar1 "$tempDIV" srcVar2 "$roundOffset" resultVar "$randOffsetDIV" } EntityRandom { scale "$maxFramePlusOne" resultVar "$randEXTR" } Add { srcVar1 "$randEXTR" srcVar2 "$randOffsetDIV" resultVar "$randEXTR" } Subtract { srcVar1 "$randEXTR" srcVar2 "$maxFramePlusOne" resultVar "$randEXTROverflow" } LessOrEqual { LessEqualVar "$randEXTR" greaterVar "$randEXTROverflow" srcVar1 "$randEXTR" srcVar2 "$maxFramePlusOne" resultVar "$randEXTR" } LessOrEqual { LessEqualVar "$prepareStore" greaterVar "$randEXTR" srcVar1 "$countingFinished" srcVar2 "$zero" resultVar "$prepareStore" } LessOrEqual { LessEqualVar "$randEXTRStored" greaterVar "$prepareStore" srcVar1 "$randEXTRStored" srcVar2 "$fh" resultVar "$randEXTRStored" } LessOrEqual { LessEqualVar "$randEXTR" greaterVar "$randEXTRStored" srcVar1 "$oneSkinPerMap" srcVar2 "$zero" resultVar "$randEXTRInject" } Multiply { srcVar1 "$countingFinished" srcVar2 "$randEXTRInject" resultVar "$injectEXTR" } Multiply { srcVar1 "$injectEXTR" srcVar2 "$activateEXTR" resultVar "$RNGframeEXTR" } 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 "$zero" srcVar1 "$rerollRNG" srcVar2 "$zero" resultVar "$randSYSStored" } LessOrEqual { LessEqualVar "$randEXTRStored" greaterVar "$ot" srcVar1 "$rerollRNG" srcVar2 "$zero" resultVar "$randEXTRStored" } LinearRamp { rate "10" resultVar "$ramp" } Int { srcVar1 "$ramp" resultVar "$ramp" } Divide { srcVar1 "$ramp" srcVar2 "$ot" resultVar "$tempDIV" } Frac { srcVar1 "$tempDIV" resultVar "$tempDIV" } Multiply { srcVar1 "$tempDIV" srcVar2 "$ot" resultVar "$tempDIV" } Add { srcVar1 "$tempDIV" srcVar2 "$roundOffset" resultVar "$tempDIV" } LessOrEqual { LessEqualVar "$randOffset" greaterVar "$tempDIV" srcVar1 "$randOffset" srcVar2 "$nnn" resultVar "$randOffset" } EntityRandom { scale "999" resultVar "$randSYSTemp" } Add { srcVar1 "$randSYSTemp" srcVar2 "$randOffset" resultVar "$randSYSTemp" } Subtract { srcVar1 "$randSYSTemp" srcVar2 "$ot" resultVar "$randSYSOverflow" } LessOrEqual { LessEqualVar "$randSYSTemp" greaterVar "$randSYSOverflow" srcVar1 "$randSYSTemp" srcVar2 "$ot" resultVar "$randSYS" } LessOrEqual { LessEqualVar "$randSYS" greaterVar "$randSYSStored" srcVar1 "$randSYSStored" srcVar2 "$zero" resultVar "$randSYSStored" } LessOrEqual { LessEqualVar "$randSYS" greaterVar "$randSYSStored" srcVar1 "$oneSkinPerMap" srcVar2 "$zero" resultVar "$randSYSInject" } LessOrEqual { LessEqualVar "$RNGinjectColor" greaterVar "$randSYSInject" srcVar1 "$randSYS" srcVar2 "$zero" resultVar "$RNGinjectColor" } Add { srcVar1 "$RNGinjectColor" srcVar2 "$VMTColorOffset" resultVar "$RNGinjectColor" } Equals { srcVar1 "$RNGinjectColor" resultVar "$CHOSENinjectColor" } Equals { srcVar1 "$RNGframeEXTR" resultVar "$frame" } LessOrEqual { LessEqualVar "$frame" greaterVar "$maxframe" srcVar1 "$frame" srcVar2 "$maxframe" resultVar "$frame" } Divide { srcVar1 "$CHOSENinjectColor" srcVar2 "$ten" resultVar "$colorReds" } Divide { srcVar1 "$CHOSENinjectColor" srcVar2 "$oh" resultVar "$colorGreens" } Divide { srcVar1 "$CHOSENinjectColor" srcVar2 "$ot" resultVar "$colorBlues" } Frac { srcVar1 "$colorReds" resultVar "$colorReds" } Frac { srcVar1 "$colorBlues" resultVar "$colorBlues" } Frac { srcVar1 "$colorGreens" resultVar "$colorGreens" } Multiply { srcVar1 "$colorReds" srcVar2 "$ten" resultVar "$colorReds" } Multiply { srcVar1 "$colorGreens" srcVar2 "$ten" resultVar "$colorGreens" } Multiply { srcVar1 "$colorBlues" srcVar2 "$ten" resultVar "$colorBlues" } Int { srcVar1 "$colorReds" resultVar "$colorReds" } Int { srcVar1 "$colorBlues" resultVar "$colorBlues" } Int { srcVar1 "$colorGreens" resultVar "$colorGreens" } Divide { srcVar1 "$colorReds" srcVar2 "$ten" resultVar "$color[0]" } Divide { srcVar1 "$colorGreens" srcVar2 "$ten" resultVar "$color[1]" } Divide { srcVar1 "$colorBlues" srcVar2 "$ten" resultVar "$color[2]" } LessOrEqual { LessEqualVar "$detailblendfactor" greaterVar "$boomerAmount" srcVar1 "$boomerEffects" srcVar2 "$zero" resultVar "$detailblendfactor" } }
🔶 Inline RNG Map
////////////////////////////////////////////////////////////////////////////////////////////////// $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" } }
🗂️ Make a slot change addon
It is possible to use the "Mod a Mod" architecture depicted in the Guide below to release a mod that changes the slot your mod is using. This can be useful for two reasons:
  • To allow your users to use your mod with another slot if they are already using the slot the mod was originally intended for
  • To release your base mod without the SYS options (Slot = 0), allowing your users to use the SYS options only if they want to.
https://sp.zhabite.com/sharedfiles/filedetails/?id=2232174067 You could read that Guide, but for the sake of being complete, I'll make a dumbed-down version of it right down below.

This assumes that you are the original modder, and that you know what a .qc file is.

STEP 1
Open the .qc file of what you want to be able to release a slot change addon for, and find the $cdmaterials lines, for example:
$cdmaterials "models\medkit_dbdl\" $cdmaterials "vgui\radars"

STEP 2
Add a new $cdmaterials line at the very top of them, with a new (yet) unused folder:
$cdmaterials "models\medkit_dbdl\slotchange\" $cdmaterials "models\medkit_dbdl\" $cdmaterials "vgui\radars"

STEP 3
(Re)compile your model, and release your mod as you would do it normally.
Now it's time to make the slot change addon.

STEP 4
Make a mod with only the VMT files, but instead of putting them in your original mod folder, put them in the folder you specified at step 2 (i.e. for me, the new same VMTs will be in materials\models\medkit_dbdl\slotchange instead of materials\models\medkit_dbdl).

STEP 5
Change the slot ($slotUsed) of these VMTs, save them, pack your mod with vpk.exe, and you are good to go. You just made a slot change addon.

(If you use both mods at the same time, the VMTs with the 'changed' slot will take priority over the original ones, because the new $cdmaterials of the new folder has a higher priority than the $cdmaterials of the old folder, because it's above in the QC.

🔎 This architecture does not only work for the change of slots. You could actually use it for everything, to release, for example, skin packs for your own mods, with new VTF files included. It's the best way to release tweak mods for your own mods, without a single conflict.

📊 Desynchronise the VMTs
You might have asked yourself one of these two questions at this point:
  • Is it possible to let the user choose his skins for 2 different parts of the model?
  • Is it possible to have more than 9 loadouts for SYS Loadout?
SYS has not been developped with the intend of answering yes to these questions (except for the 'extra' slots for survivors), but there's a nice little trick you can use to actually allow for this.

The trick is to actually use VTFs that do not have the same number of frames (skins).

You see, when all VTFs have the same amount of skins (frames), everything works well. However, when they do not have the same number of frames, it begins to desynchronise.

Here's what happens under normal conditions. With 2 VMTs that each have the same 4 skins (frames). You can see that everything syncs perfectly, and that there's only actually 4 different variants.

1
2
3
4
5
6
7
8
9
10
11
12
VMT 1
❤️
💙
💚
💛
❤️
💙
💚
💛
❤️
💙
💚
💛
VMT 2
📕
📘
📗
📙
📕
📘
📗
📙
📕
📘
📗
📙

Now this is what happens when you remove one skin from VMT 2:
You will note that by removing one skin, the VMTs now are desynchronised, and you actually get 12 different variants, by removing a skin.

1
2
3
4
5
6
7
8
9
10
11
12
VMT 1
❤️
💙
💚
💛
❤️
💙
💚
💛
❤️
💙
💚
💛
VMT 2
📕
📘
📗
📕
📘
📗
📕
📘
📗
📕
📘
📗

However, look at what happens if I remove one more skin from VMT 2:
Now, there are only 4 variants, and there are combinations that are now impossible (such as 💚📘 or 💛📕). It got worse.

1
2
3
4
5
6
7
8
9
10
11
12
VMT 1
❤️
💙
💚
💛
❤️
💙
💚
💛
❤️
💙
💚
💛
VMT 2
📕
📘
📕
📘
📕
📘
📕
📘
📕
📘
📕
📘

Now, the general rule is that all the combinations will show if the smallest number that is divisible by both the number of frames in the first VMT and the number of frames in the second VMT is also the multiple of these number of frames.

For example, if a VMT has 4 frames, and another VMT has 7 frames, their product is 28 (4 × 7 = 28), and 28 is the smallest number that can be divided by both 4 and 7. Therefore, with 4 and 7 frames, all the combinations will show up.

For example, if a VMT has 4 frames, and another VMT has 6 frames, their product is 24 (4 × 6 = 24). However, 24 is not the smallest number that can be divided by 4 and 6, because 12 is. Therefore, with 4 and 6, not all the combinations will show up.

From all of this, you should remember this: if you want to mix up the VMTs to allow the player to choose between a lot of combinations of clothes/parts, you just need to do 💡 two things:
  • Make it so VTFs that can desynchronise have different numbers of frames / loadouts.
  • Make it so that the number of frames of these VTFs are prime numbers.
For the math haters, the common first prime numbers are 2, 3, 5, 7, 11, 13, 17, 19, 23 and 29.
Note that 4 also works most of the time with any of these prime numbers except 2.
[Appendix] VTF with multiple textures
This section will explain you how to create a VTF File with multiple textures (frames) in it.
Any SYS Code will then automatically randomize these textures that your VTF file will contain.

You will need VTFEdit, that you can find here : https://gamebanana.com/tools/95

STEP 1
Save all your different textures (skins) as .tga files (or .png if you do not want transparancy) and put them in the same folder. Note that they will be sorted in alphabetical (or numerical) order once the VTF will be created.



STEP 2
Open VTFEdit. Press on CTRL+i. Select all the different .tga files (textures) at the same time, then press on the ENTER key on your keyboard or click on OPEN in the bottom-right corner. Press on OK when the VTF Options screen comes up.



STEP 3
Under the Image tab, check that you can increment the Frame by clicking on the two little arrows. If you can go above 0, it means you did everything right and you can now save the VTF file.



STEP 4
Export your VTF file like usual (CTRL+E) and replace the old VTF file that only contained one texture. Congratulations, that was the last step!
[Appendix] VTF for color modulation
This section will explain you how to create a VTF File that can be used for color modulation, so that only the chosen parts of the $basetexture gets colored.

You will need VTFEdit, that you can find here : https://gamebanana.com/tools/95
You will also need a 2D Graphics Software, like Abobe Photoshop® or Gimp.
This Appendix assumes that you have Abobe Photoshop®, but similar results can be achieved in Gimp or an equivalent.

STEP 1
Open the .tga texture into Photoshop (or equivalent).

STEP 2
Select all the parts that need to change color in the texture you're working on (use the Lasso, the Magic Wand, or the Select Color Range tools), and copy them as a new layer (but keep the original layer/texture under it).


In this example, I want Rochelle's shirt to change color, but not her other clothes.

STEP 3
Make the new layer black and white (CTRL+ALT+SHIFT+B in Photoshop).
Then, adjust the curves (CTRL+M in Photoshop) so that the layer becomes white and not grey or black.



STEP 4
Toggle back the visibility of the layer underneath (the one that still has the colored clothes).



STEP 5
Create a new channel[helpx.adobe.com] (≠ a new layer) for the texture you are editing and name it Alpha (do not do this if the texture already has an Alpha channel).

STEP 6
Make that new Alpha channel all black.

STEP 7
Copy the layer with the white clothes / parts to be colored into the alpha channel, and position it so it perfectly matches the original layer (to ensure that, you need to toggle the visibility of all four RGB+Alpha channels simultaneously, by clicking on the little checkboxes that make an eye icon appear). Note that the parts that are black in the alpha channel will have a red hue in Photoshop when all channels are visible).


The above image shows the alpha channel only.

STEP 8
Check that the final result looks like this when all channels are visible.
The parts that do not need to be colored must have a red hue due, and the parts to be colored must have show in white. When you get this result, you can save the file as .tga.



STEP 9
Import the .tga file you just saved in VTFEdit and press on CTRL+M to view the mask.
If you did everything right, you should see all the parts that needs to be colored, that will be white, on a checkered background.



STEP 10
Export the file as a VTF file and replace the original file with your new texture.
It is now ready to be colored by the SYS Script.
📌Note that if the user sets his shaders options to LOW or MEDIUM in the Graphics Options of L4D2, the game will not color the specific parts of the VTF but the whole texture instead, as if it did not have an alpha mask. There's currently no know way around that. If you know one, please contact me.
[Appendix] Reverse engineering
I know that some of you actually understand things better when they can reverse engineer mods. Therefore, this section lists example of mods that use different features of the SYS Technology, so you can see how they are built:

⚪️ SYS Entity Pure
https://sp.zhabite.com/sharedfiles/filedetails/?id=2326008875
⚪️ SYS Color Pure
https://sp.zhabite.com/sharedfiles/filedetails/?id=2326043777
⚪️ SYS Loadout Pure
https://sp.zhabite.com/sharedfiles/filedetails/?id=2326061140
🔴 SYS Entity + Damage
https://sp.zhabite.com/sharedfiles/filedetails/?id=2326072300
🔴 SYS Color + Damage
(Also showcases the double layer RNG (pattern ($basetexture) and color)
https://sp.zhabite.com/sharedfiles/filedetails/?id=2326078146
🔶 SYS Map
https://sp.zhabite.com/sharedfiles/filedetails/?id=2326084941
Slot Activation Mod (architecture with Mod a Mod)
https://sp.zhabite.com/sharedfiles/filedetails/?id=740516157 https://sp.zhabite.com/sharedfiles/filedetails/?id=2326046795
Invisible as a skin (clothes)
https://sp.zhabite.com/sharedfiles/filedetails/?id=2326092439
6 Comments
Drawing Pad 4 Dec, 2022 @ 4:18am 
Yep, I'm not gonna even bother. :dicewhat:
Yoimiya 26 Aug, 2021 @ 3:05am 
You are great, this is a groundbreaking guide.
TheZombieDon 13 Feb, 2021 @ 11:12am 
Alright - cuz CS:S does use a "custom" folder system, which does allow custom weapons to work both offline and online (on servers that have the right sv_pure values and what not). Not sure how it would come up as a menu in the game though, honestly.
Ellie  [author] 13 Feb, 2021 @ 10:46am 
@TheZombieDon : The basic concept should be able to work, but the module is not directly transposable because the core variables used would need to be changed. Also, for games that do not natively support mods (games that prevent mods in Online), it wouldn't work.
TheZombieDon 13 Feb, 2021 @ 10:20am 
Quick question - could this technically work on other Source engine games, like CS:S? (online as well)
john.starwars.1999 23 Dec, 2020 @ 12:50pm 
This looks really cool... maybe I'll get round to reading it one day ;)