Left 4 Dead 2

Left 4 Dead 2

92 ratings
[Obsolete] Material Proxies for Modders : Part 2 : RNG
By Ellie
This is the Part 2 of the Huge Planned Guide that aims to provide the Source Modding community everything I've learned about Proxies and stuff. This part focuses on the Random Number Generation (RNG) that allows to make random textures and random "stuff". It also aims to serve as a base for further more complex programms with proxies.
   
Award
Favorite
Favorited
Unfavorite
READ THIS GUIDE INSTEAD
Different kinds of RNG
True RNG : It means that the random generated number is random per map. (Example : Every Molotov Cocktail has the same skin while you play the finale map of Mercy Hospital, but this skin is different than the one you had in the previous map (Hospital Interior)

Real RNG : It means that the random generated number is random per entity. (Example : Every Molotov Cocktail in the world has a different skin, because each one is a different entity)

Model (Real/True) RNG : It means that it gives the illusion that a same object can be different within or between maps (Example : The Pipebomb looks like a firework in map 1, and like a party bomb in map 2)

Color RNG : It means that some part of the material will recieve a totally random color. (Example : The body of a guitar can take any color, randomly)
Different kinds of Entities
It if absolutely essential to understand that there are differend kind of "Entities" within the Source Entine
-----------------------------------------------------------------------------------------------------------------------
Entity : In-game thing that has the ability to draw random numbers with the EntityRandom proxy
These entities are mainly the server-side elements that are constitued at 99% of "elements that have collisions and can move"
Examples : Guns (FP and World Model) / Infected / Survivors / Rescue Vehicles / Items / Pickables items / Doors / Movable Cars
-----------------------------------------------------------------------------------------------------------------------
Semi-entity : In-game thing that has not the ability to draw random numbers using the EntityRandom proxy but doesn't crash the game with used on it
These entities are mainly the client-side movable elements that are constitued at 99% of "elements that have no collisions and can move"
Examples : HUD / Items held by or on the survivors / Small Trash (Pizza boxes / cans...) / Dead Corpses
-----------------------------------------------------------------------------------------------------------------------
Non-entity : In-game thing that has not the ability to draw random numbers using the EntityRandom proxy and crash the game with used on it
These entities are mainly the client-side maps elements that are constitued at 99% of "elements that have no collisions and can't move"
Examples : Soda Machines / Walls / Plants / Ads / Non-movable Cars
-----------------------------------------------------------------------------------------------------------------------

Knowing what kind of entity you are working with is crucial, since it will decide if you have to use the EntityRandom or UniformNoise proxy. :

- If you have an "Entity" → EntityRandom proxy
- If you have a "Semi-Entity" → UniformNoise proxy (otherwise won't work)
- If you have a "Non-Entity" → UniformNoise proxy (otherwise will crash the game ⛔)

Please note that the kind of Entity is not determined by the MDL file but by its use in the game. For example, the world model of and item is an Entity when "in the world" but a "Semi-entity" when "on a survivor"

A same VMT can even be used on all 3 kinds of Entities. For example, the charger VMT is used on an Entity (the alive charger), a Semi-entity (the dead charger) and a Non-entity (the dead displayed charger between poles)
The 2 proxies for RNG
The main thing to understand is that there are TWO different ways to create RNG with Proxies, there are actually TWO different proxies that give different results :

EntityRandom
This proxy generates a random number directly from the Entity the material is applied to.
(Example : You spawn a bottle of pills, the game will give this bottle the random object N°350231, then, the EntityRandom proxy will use this number to generate a random number associated with the Entity)
  • HUGE Advantage : The model will always return the same random number as EntityRandom, therefore, if your skin is in multiple VMT, they will all get the same EntityRandom result, so you do not have to worry if your model has multiple VMT, they will all match.
  • HUGE Advantage : This method doesn't cause any flickering issues and takes less processing ressources, resulting in less crashes
  • HUGE Advantage : It allows "Real RNG" : you can make every item in the world be different, because they depend on the Entity N°, that is different for every spawned thing
  • HUGE Advantage : You don't need to "stop" the proxy, the number it returns is always the same.
  • HUGE Disadvantage : It forces the first Advantage. If you want the different VMT to have independant random textures, it's way more complicated or even impossible to code.
  • HUGE Disadvantage : Crashes the game if used on anything that is static on a map

UniformNoise
This proxy keeps generating random numbers every frame. You can set the min and max values they can have.
  • HUGE Advantage : Works on every-single-thing.
  • HUGE Advantage : Allows different parts of a same model to be randomized independantly
  • Disadvantage : Can sometimes cause short object flickering and takes more processing ressources
--------------------------------------------------------------------------------------------------------------

In the rest of this guide, I'll take all different kinds of RNG one by one, starting by the easiest to understand then moving on to the hardest. I'll then add some remarks at the end.
RNG Cheat Sheet ✌
Entity Random : Real RNG



Q : What effects does this do ? :
➞ This makes every object have a different texture, even within the same map

Q : What can I use it on ? :
➞ Guns / Items / Ammo / Escape Vehicles / Survivors / Infected (besides Charger)

Q : What should I use it on ? :
➞ Ammo / Escape Vehicles

Q : What can I NOT ⛔ use it on ? :
➞ Any item that is static on a map (vending machines / carpet / furniture...) : Will result in not working or crashing the game

Q : What are the pros and cons ? :
✔ No Flickering Textures
✔ Different textures within the same map
✔ No need to worry if your model has multiple VMT and you want them to match their $frame
✘ Will CRASH the game if used on the wrong thing
✘ Impossible to make each VMT be random on its own
✘ Not that much realistic if used on something else than Ammo or Escape Vehicles (See Below)

Why it's not realistic if used on most stuff :
The problem is that is causes a lot of problems because most of the stuff is not considered as an Entity :
- If used on Survivors, their skin will change upon death (and will always be the same)
- If used on Infected, their skin will change upon death (and will always be the same)
- If used on Items or Guns, the skin in the world won't match the skin in hand AND the skin carried by the survivors will always have the very first frame

So normally, you can FORGET about this kind of RNG since it's useful only for Ammo Packs and Escape Vehicles (the rest is either unrealistic, cf. above, or will crash the game).

Below is an example of the code that you have to put in your VMT. Just modify 5.99 to the number you need. Here, there are 6 frames, so it's 5.99. 12 frames is 11.99, 2 frames is 1.99 etc.
The code directly injects the value of the EntityRandom in the $frame, so there's nothing you have to worry about. It's also a great way to test the RNG for the first time ;), so you see if it works.

"Proxies" { "EntityRandom" { "scale" "5.99" "resultVar" "$frame" } }

Example of mod that use this kind of RNG :
Click here to access it.
Entity Random : True RNG


Q : What effects does this do ? :
➞ This randomizes the texture "per map". Every object will have the same texture within the map. It's the most "realistic" one up to date but it doesn't allow to make textures random on their own.

Q : What can I use it on ? :
➞ Guns / Items / Ammo / Escape Vehicles / Survivors / Infected (besides Charger)

Q : What should I use it on ? :
➞ Guns* / Items*/ Ammo / Escape Vehicles / Survivors/ Infected (besides Charger)
* as long as they have the same VMT for World and First person.

Q : What can I NOT ⛔ use it on ? :
➞ Any item that is static on a map (vending machines / carpet / furniture...) : Will result in not working or crashing the game

Q : What are the pros and cons ? :
✔ No Flickering Textures
✔ No need to worry if your model has multiple VMT and you want them to match their $frame
✔ All textures (world / hand) will match as long as they use the same VMT
✘ Will CRASH the game if used on the wrong thing
✘ Impossible to make each VMT be random on its own

Why is this the "best" RNG :
This kind of RNG is the only one that's truly "realistic", you won't get frame flickering problems and the object you pick will match the object in your hands, or the corpse will match its "living" body texture.
Therefore, I'd suggest you to ALWAYS use this (if possible) UNLESS the thing you want to use it for is most of the time in multiple locations at the same place.
I personnally only use the other kind - Real RNG + True RNG - for Molotovs, Pills and Pipebombs because they are often in multiple locations and it's therefore nice to see different skins.
So if you really want the RNG to bring only advantages and 0 disadvantages, use THIS :D

The code for that is a little bit more complicated, but you do not need to understand it.
To use is, just change the "9.99" to the number of different skins you have -0.01
If you have 12 skins, put 11.99. If you have 3 skins, put 2.99 etc.

$frame 1000 $rand 0 $zero 0 $fh 500 "Proxies" { "EntityRandom" { "scale" "9.99" "resultVar" "$rand" } "LessOrEqual" { "LessEqualVar" "$frame" "greaterVar" "$rand" "srcVar1" "$frame" "srcVar2" "$fh" "resultVar" "$frame" } }
Basically, the difference with "Real RNG" is that the result of the EntityRandom is stored only once into $frame. $frame starts at 1000, the "LessOrEqual" proxy stores $rand (random number) into $frame when $frame is over 500 ($fh), so this happens only once since $rand never be over 9.99 ; therefore, it's the first item you see that will determine the frame of every subsequent item in the map.
Since a same VMT can't have 2 different textures within the same map unless it directly depends on EntityRandom, the textures will match no matter if this thing is applied to a Real-Entity or a False-Entity, but it will CRASH if applied to a Non-Entity


In other words, the code does this :
1 : Compares $frame to $fh (500)
2 : If $frame > $fh* (500), then copy the $rand value into $frame...
3 : ...else copy $frame into $frame (= do nothing)
* this is only the case at the very beginning, since $frame has 1000 as default value.

Example of mod that use this kind of RNG :
Click here to access it.
Uniform Noise : True RNG


Q : What effects does this do ? :
➞ This randomizes the texture "per map". Every object will have the same texture within the map. This one can be used without any risk of CTD.

Q : What can I use it on ? :
➞ Anything

Q : What should I use it on ? :
➞ Anything that is static on a map / Any item or gun or survivor when you want the VMTs to be random on their own (See below for why)

Q : What are the pros and cons ? :
✔ Works on everything
✔ Every generated number is independant
✘ Flickering Textures can happen when you see the object for the first time
✘ RNG per map is the only one avaliable

Why do I need to use this when I want the VMT's to be random on their own ? :
Let's say you have a bottle of pills with 2 VMT, one for the cap and one for the body. You have 2 caps (black / white) and 4 body skins.
EntityRandom actually works this way : it generates a number from 0 to 1 depending on the object ID, then multiples this by the "scale". Since your cap and your body are on the same object, this will result in the 2 VMT to be dependant, even though they do not have the same numbers of frames. That means that you will always get the black cap with the 2 first body skins and the white cap with the 2 remaining body skins ($frame 0 cap with $frame 0-1 bottle and $frame 1 cap with $frame 2-3 cap).

As you can see in the example on the right, if EntityRandom return 0.89, this will always be converted into 1.77 (multiplied by 1.99) for the cap and into 3.55 for the body (multiplied by 3.99). Therefore, since no matter what the (red) line will always be horitzontal (due to the fact EntityRandom "links" the VMT of a same object), you can see that it will be impossible to get a White cap with Body 3 or 4 in this configuration.
This is why you should use the Uniform Noise one if you really want the different VMTs of your object to roll numbers in an independant way.

NOTE : It is though still possible to make independant RNG with EntityRandom. This would require (in the example above) to roll EntityRandom on 8 (because there is total 2 * 4 different skins combinations) and then set the cap to white if it's over 4, else to black, and remove 4 to $rand if it's over 4 when it's to insert into $frame.
The only mods that currently use this are the 180 Molotov Cocktails and Honoka, but this is very complicated because they are coupled with Model RNG and there are not 2 but 4 parameters.

The code is almost the same as for "True RNG" with EntityRandom.
The only thing you need to modify is the "4.99", again, you need to set that to the number of different skins you have - 0.01. If you have 23 skins, put 22.99, if you have 2, put 1.99 etc.

$frame 1000 $fh 500 $rand 0 "Proxies" { "UniformNoise" { "minVal" "0" "maxVal" "4.99" "resultVar" "$rand" } "LessOrEqual" { "LessEqualVar" "$frame" "greaterVar" "$rand" "srcVar1" "$frame" "srcVar2" "$fh" "resultVar" "$frame" } }

The code does this :
1 : Compares $frame to $fh (500)
2 : If $frame > $fh* (500), then copy the $rand value into $frame...
3 : ...else copy $frame into $frame (= do nothing)
* this is only the case at the very beginning, since $frame has 1000 as default value.

The "UniformNoise" proxy keeps generating random numbers. $rand changes every fraction of second, this explains the need to "stop" the generation with the LessOrEqual proxy.

Example of mod that use this kind of RNG :

Click here to access it.
Entity Random : Model RNG


Q : What effects does this do ? :
➞ This gives the illusion for different objects to be randomly generated by the game

Q : What can I use it on ? :
➞ Guns / Items / Ammo / Escape Vehicles / Survivors / Infected (besides Charger)

Q : What should I use it on ? :
➞ Anything listed above that does NEVER have a Glow Outline except if the shape change are very, very subtle

Q : What can I NOT ⛔ use it on ? :
➞ Any item that is static on a map (vending machines / carpet / furniture...) : Will result in not working or crashing the game

Q : What are the pros and cons ? :
✔ Provides different shapes for a same object within the same mod
✔ Different shapes avaliable through the same map
✔ No need to worry if your model has multiple VMT and you want them to match their $frame
✘ Requires to know how to use a 3D Editing Tool
✘ Will CRASH the game if used on the wrong thing
✘ Looks bad on anything that has a Glow Outline (practically everthing in L4D2)[/i][/b])

How does this work ? :
The main idea is to "stack" different shapes that use different VMT's in a same MDL/SMD and display only one VMT at a time, the others being invisible. Every shape will still be here but only one will be randomly opaque, giving the illusion of random shapes.

What is the HUGE problem with that ?

The HUGE problem is that the Glow Outline, that you have on almost EVERYTHING in L4D2 (Guns / Survivors / Infected / Items...) STILL takes the global shape into account, meaning that it will look bad and unrealistic. So this "Model RNG" has in fact very limited use.
You can see with the Katana here : it has a RNG Sleeve and the Glow Outline takes the Sleeve into account. It doesn't look really good even though the 2 "models" have almost the same shape. With 2 very different shapes, it can look horrible

Basically, there are mutiple ways to code that RNG, but the best one not to become "silly" is the one that I used in the "Tank Rock RNG" mod. I will explain some of it here in case you really want to give it a go, but it's really complicated :D.

FIRST, as I said, each different thing to display should have a separate VMT, here, the rocks each have a VMT : rock1.vmt, rock2.vmt, rock3.vmt etc...

Let's look at "rock1.vmt" :

"patch" { include "materials\models\rngtr\rng.vmt" insert { "$basetexture" "models\rngtr\rock1_d" "$bumpmap" "models\rngtr\rock1_n" "$phongexponenttexture" "models\rngtr\rock1_s" "$itemid" "4" } }

To make the code better, I used the "patch" system. The patch system allows you to copy the content of a VMT into another (cf. "include") and then insert more stuff that will (case needed) replace what is in the VMT you included.

In this VMT, you have the $basetexture etc. (the things you know) and this $itemid.
$itemid is a custom variable that is used to know what the "rock ID" is. The code that is in rng.vmt will know if the rock is to display depending on what number the code will have rolled.

So what you need to do if you want to implement that is to copy the content of this into each VMT you want to randomize the display and set an $itemid for each one, starting at 0. "rock1" doesn't need to have the id 1, but the id's need to be chonological and start at 0.

Then, the "rng.vmt".

"VertexLitGeneric" { "$halflambert" "1" "$nocull" 1 "$model" 1 "$alpha" 0 "$phong" "1" $phongboost "0" $phongfresnelranges "[0.1 0.1 0.1]" "$phongalbedotint" "1" $envmap env_cubemap $normalmapalphaenvmapmask 1 $envmapfresnel 1 $envmapFresnelMinMaxExp "[.05 .1 .1]" $envmaptint "[0.01 0.01 0.01]" $color2 "[0.9 0.9 0.9]" //////////////////////////////////////////////////////////////////////////////////////////////// // REAL RNG : MODEL (2016) //////////////////////////////////////////////////////////////////////////////////////////////// $objnumber 4.99 // MODIFY ONLY THIS IN THIS VMT $objlimit 4.49 // MODIFY ONLY THIS IN THIS VMT $selected 1000 $rand 1000 $one 1 $zero 0 $pf "0.5" $itemtocheck 0 $itemtocheckr 0 $inject 0 "Proxies" { "EntityRandom" { "scale" "$objnumber" "resultVar" "$rand" } "LessOrEqual" { "LessEqualVar" "$rand" "greaterVar" "$zero" "srcVar1" "$rand" "srcVar2" "$objlimit" "resultVar" "$selected" } "Subtract" { "srcVar1" "$selected" "srcVar2" "$itemid" "resultVar" "$itemtocheck" } "Abs" { "srcVar1" "$itemtocheck" "resultVar" "$itemtocheckr" } "LessOrEqual" { "LessEqualVar" "$one" "greaterVar" "$zero" "srcVar1" "$itemtocheckr" "srcVar2" "$pf" "resultVar" "$inject" } "LessOrEqual" { "LessEqualVar" "$alpha" "greaterVar" "$inject" "srcVar1" "$rand" "srcVar2" "$zero" "resultVar" "$alpha" } } }

This VMT contains the RNG, the patch method allows you not to have to edit every single VMT if you want to change something in the RNG (because not using patch, you'd have to copy this stuff in every VMT, that would do exactly the same).

If you want to use this, as it's said, you just need to change the 2 values that yell "change me".
If you have 5 objects (like in my case), you need 4.99 and 4.49. If you have 23 objects, you need 22.99 and 22.49. If you have 4, 3.99 and 3.49 etc.

Now, if you really want to understand how this works, let me try :D (you don't need to understand, but it's good if you want to become a Material Proxies master).

STEP 1 : EntityRandom generates a random number for the whole entity (so this number will be shared between rock1.vmt, rock2.vmt, rock3.vmt etc. since they are on the same Entity : the rock thrown by the Tank) ; this number is from 0 to the max object number.
STEP 2 : LessOrEqual proxy makes the number return to 4.49 if it's past 4.49, this is due to the way we control what item is selected, further in the code
STEP 3* : Subtract does a substraction : is substracts $selected (value selected by EntityRandom) and $itemid.
STEP 4* : Abs (absoluve value proxy) turns $itemid to it's positive countrepart if $itemid is below 0. Doing that after substracting $selected and $itemid returns the delta between $selected and $itemid.
STEP 5* : We compare the delta between $selected and $itemid and if it's less than 0.5, it means that it's this item that has to be displayed, we therefore turn $alpha to 1 (= visibile) ; otherwise we keep it to 0 (invisible)

* For example, let's say we have $itemid = 5 and $selected = 3. We make 3-5 = -2 and then abs(-2) = 2. It means that the difference between 5 and 3 is 2.
Now let's say we have $itemid = 5 and $selected = 5. We make 5-5 = 0 and then abs(0) = 0.
With this operation, we'll get 0 if the numbers match and anything above if they don't, that's the way to write "Is equal to" with proxies and that's what we need.
"Is equal to" can't be written in programming language, but "Has a difference of 0 with it" can be (and that's equal to ==). In the code therefore, we use 0.49 and not 0.

Linear Ramp : True RNG


⛔ WARNING :
Do NOT use this if you can use Entity Random : True RNG

Q : What effects does this do ? :
➞ This allows the different VMT's of an items to share the same $frame. It's therefore useful if you can't use EntityRandom : True RNG (that does the same thing), especially if what you're replacing is a map item

Q : What can I use it on ? :
➞ Anything

Q : What should I use it on ? :
➞ Anything that is static on a map and that has more than 2 VMT that have the share the same $frame (i.e. models that contain multiple VTF)

Q : What are the pros and cons ? :
✔ Works on everything
✔ Allows to "link" the different VMT's without using EntityRandom
✘ The textures can sometimes be full-black for the first few seconds you came across the material, especilally late in the map
✘ The RNG doesn't seem even on Localhost games

$numberoflastframe 5 // <== [[MODIFY ONLY THIS BY THE N° OF YOUR LAST FRAME]] $framec 0 $numberoflastframeplus 0 $ramp 0 $inval 0 $frame 300 $zero 0 $nn .74 $one 1 $two 2 $docorr 0 $framecdo 0 "Proxies" { "Add" { "srcVar1" "$numberoflastframe" "srcVar2" "$nn" "resultVar" "$framec" } "Divide" { "srcVar1" "$framec" "srcVar2" "$two" "resultVar" "$numberoflastframeplus" } "LinearRamp" { "rate" "$numberoflastframeplus" "initialValue" "$inval" "resultVar" "$ramp" } "LessOrEqual" { "LessEqualVar" "$zero" "greaterVar" "$one" "srcVar1" "$ramp" "srcVar2" "$framec" "resultVar" "$docorr" } "Multiply" { "srcVar1" "$framec" "srcVar2" "$docorr" "resultVar" "$framecdo" } "Subtract" { "srcVar1" "$inval" "srcVar2" "$framecdo" "resultVar" "$inval" } "LessOrEqual" { "LessEqualVar" "$frame" "greaterVar" "$ramp" "srcVar1" "$frame" "srcVar2" "$framec" "resultVar" "$frame" } }

The code is complicated ; basically, it generated a looping number using a LinearRamp proxy, this number "loops" by reducing the offset of the LinearRamp when the LinearRamp reaches the maximal frame of the VTF (reducing the result of the Proxy doesn't work).
What determines the RNG is actually the time it takes for the game to load (kinda), and more precisely the difference between the loading time of the different players.
Entity + Uniform : Mixed RNG


Q : What effects does this do ? :
➞ This is a "fix" for Real RNG when it's used on certain items, that always display the first frame (frame 0) on the items carried and help by the teammates

Q : What can I use it on ? :
➞ Anything that you can use "Real RNG" on

Q : What should I use it on ? :
➞ Items carried or held by the survivors that always display the same frame (frame 0).

Q : What can I NOT ⛔ use it on ? :
➞ Any item that is static on a map (vending machines / carpet / furniture...) : Will result in not working or crashing the game

Q : What are the pros and cons ? :
✔ This is a fix for "Real RNG", use it instead of it if items carried by the survivors keep displaying frame 0 on Real RNG

As it says in the code, copy the whole bunch of ♥♥♥♥ and modify on the the said line by the N° of your last frame (in the example, it's N°49, meaning we have 50 frames)

$lastframenumber 49 // <== [[MODIFY ONLY THIS BY YOUR LAST FRAME NUMBER]] /// DO NOT TOUCH ANYTHING BELOW THAT POINT without knowing what you're doing $framenumber 0 $frame 1000 $zero 0 $sf "0.99" $one 1 $rand 0 $randtwo 0 $randtwostock 0 $docorr 0 $corrtoapply 0 "Proxies" { "Add" { "srcVar1" "$lastframenumber" "srcVar2" "$sf" "resultVar" "$framenumber" } "EntityRandom" { "scale" "$framenumber" "resultVar" "$rand" } "UniformNoise" { "minVal" "0" "maxVal" "$framenumber" "resultVar" "$randtwo" } "LessOrEqual" { "LessEqualVar" "$randtwo" "greaterVar" "$randtwostock" "srcVar1" "$randtwostock" "srcVar2" "$zero" "resultVar" "$randtwostock" } "Add" { "srcVar1" "$rand" "srcVar2" "$randtwostock" "resultVar" "$frame" } "LessOrEqual" { "LessEqualVar" "$zero" "greaterVar" "$one" "srcVar1" "$frame" "srcVar2" "$framenumber" "resultVar" "$docorr" } "Multiply" { "srcVar1" "$framenumber" "srcVar2" "$docorr" "resultVar" "$corrtoapply" } "Subtract" { "srcVar1" "$frame" "srcVar2" "$corrtoapply" "resultVar" "$frame" } }
Basically, the code draws a random number with both Entityrandom and Uniformnoise, then inject the UniformNoise one if the Entityrandom one display 0. This results in the carried item to be under Uniform Noise True RNG and the world ones under Real RNG

Example of mod that use this kind of RNG :

Click here to access it.
Extra : Bumpmap Support
Adding support for Bumpmap RNG is really easy, take any RNG code and just add this Proxy at the end of the Proxies block :

"Equals" { "srcVar1" "$frame" "resultVar" "$bumpframe" }

It will make the frame of your diffuse match the frame of your bumpmap.

Please be aware that this "technique" is impossible with selfillummasks and other masks, it also doesn't work with anything else than bumpmap (and detail) ; therefore, it's not possible to RNG a specular mask, even if it's internal to a texture.

You can although RNG a selfillum if that selfillum is part of
Extra : Add a "secret texture"
There's a very simple way to include ONE "secret" texture in any of the formerly presented RNG. That "secret" texture will be displayed at a very lower rate than the other ones. It's really easy to do so.

STEP 1 : Put that secret texture as the VERY LAST FRAME of your diffuse texture
STEP 2 : In any RNG code, modify the
"scale" "5.99"
or the
"maxVal" "5.99"
into something that does not end with .99, to lower the chance of the last frame to be displayed.

Example : Let's say we have 12 different textures, meaning the N° of our last frame is 11, we want the 12th texture (11th frame) to be displayed way fewer than it originally is (originally 1/12th of the time).
Our code contains :
"scale" "11.99"
If we change that to 11.1 instead of 11.99, it means that the frame N°11 will be displayed only 0.1 / 11.1 times = 1/111 times instead of 1/11.99, making it approximately 10 times more rare than usual, therefore creating a "secret" texture.

Examples of mods that use this technique :

Click here to access it.


Click here to access it. (Used with Model RNG)
Debbuging ⛨
This sections provides some help for debugging the RNG in case it doesn't work or gives ♥♥♥♥. Try to search for your issue and see the probable cause :

❎ The game crashes when I come close to the object I applied the RNG on
➞ You used an EntityRandom based RNG on something non supported, try Uniform Noise

❎ The object is full black and does not display any texture
➞ Try to reload the map multiple times or spawn multiples items if it's on Real RNG, if it does it only sometimes or on some objets, the issue is that you entered a wrong number of frame in the code (for example, you have 12 frames and you entered 12.99 when you should have entered 11.99, because the N° of your last frame is 11)

If it always shows a full-black object no matter what, it's probably a syntax error in the code. Try to check your copy-paste and that the 3 last characters in your code are }

Example for the 3 } (end of a full VMT) :
"srcVar2" "$framec" "resultVar" "$frame" } } }

❎ The frame is always the frame 0 (first design/frame)
➞ You maybe forgot to copy all the variables before the Proxies block, check you copy-paste. If, in this situation, you have a $frame 1000 line in your code and you always get frame 0, the code is working though. So you're either unlucky or maybe, use the Linear Ramp RNG on a Localhost server.
If you always get frame 0 on an item carried on the teammates, check the "Uniform + EntityRandom Mixed RNG"

❎ When I pick an item, I don't end up with the item I picked
➞ That's probably because you've used Entity Random : Real RNG. There's yet no way to make the item you pick match the item in your hand, sadly, this is unfixable. Use Entity Random : True RNG if you want them to match, but the design will be the same along the map.

If however, you've used Entity Random : True RNG or Uniform Noise : True RNG and end up with this problem, that means that your view model probably has a different VMT than the world model (that's the case for the base game Molotov / Pain Pills and Medkit) ; in this case, use Real RNG since even True RNG can't make the items match.
The solution to this problem would be to set the world and the first person model to the same VMT, that's done using a 3D software like Blender, but if you know that, it's probably not a secret to you ;)

❎ Textures seem to change very fast when I first see the model then stop
➞ This is a recurent problem in Uniform Noise RNG, I couldn't modify it, even by creating a sort of "buffer", yet, there's no fix for it unless using the EntityRandom RNG ; if you can't however (because the object doesn't support it and makes the game crash), there's unfortunately no solution

❎ Textures doesn't match, on the same model (VMT frames do not match)
➞ You used a wrong kind of RNG, probably an Uniform Noise based one when you should have used an Entity Random based one. If however you need to use an Uniform Noise based one (because the thing you try to RNG is in the "world"), then you need to use the "Linear Ramp : True RNG LINK" instead.
46 Comments
Ellie  [author] Oct 24, 2020 @ 8:43am 
@Mark Zer0 (YourBroLonk) : So like the Animated Textures except the "starting" position is random ? Yes it is, but this is featured here. It's easy to code.
Mark Zer0 (YourBroLonk) Oct 24, 2020 @ 8:36am 
Would it be possible to make a random frame of the animated texture be picked at random and change every, let's say 5 seconds?
JI06CT3P Aug 29, 2020 @ 2:02am 
OMG, Elliiiiiieeeeeeeeeeeeeee, it's genius!!!! Perfecto!!! Bellisimmo!!!! Fantastish!!!!! Awesome:templars:
Thank you very much <3
MSF Oct 28, 2018 @ 1:29pm 
Well, I tried with the other True RNGs and they didn't work. I used the Entity Random Real RNG and it works like a charm. I never like using Real RNG on Survivors or Infected, but it works really well with the Spy. He could be blue, dies, and he changes to red like he was disguised as a blue Spy. It's perfect! Thanks for responding and helping out!
MSF Oct 28, 2018 @ 12:57pm 
I ported the Spy into L4D2. I've also been experimenting with resolution. I made the head textures the same as the body textures, but by doing so it would never change the Spy's body to red, just the mask. I'm starting to think that it's an ordering thing, where because the head the 'main' texture, it can't move the horizontal line for the suit past the blue color or something. I'm gonna try to do a few more experiments before I use Real RNG, cause I think True RNG is right, it's just acting wonky.
Ellie  [author] Oct 28, 2018 @ 12:39pm 
@MSF : This is very strange. Did you port that Spy in L4D2 or are you trying to RNG it in TF2 ? An explanation would be that the Spy model is actually 2 stacked models or 2 different entities, which would be strange (and definitely not the case in L4D2).
Nonetheless, try Entity Rnadom : Real RNG or the other "RNG Made Simple" Guide I made.
MSF Oct 28, 2018 @ 11:52am 
I'm trying to add RNG to the TF2 Spy model so that he can be either Blue or Red, & he has two VMT files; one for his body, and one for his head. I used the Entity Random True RNG because of how the horizontal line explained in the Uniform Noise section will always have other VMTs match. I only have two frames for both of the VMTs and they are both in order, Blue frame 0, Red frame 1. The value for both VMT's "scale" is 1.99.

When testing, the Spy can have the proper colors, but the Spy can also have the wrong mask color. Am I using the wrong RNG? Are the different Resolutions of the two textures (body and head) causing this?
Ellie  [author] Jan 19, 2018 @ 11:02am 
@Pleasant Peasant : This is possible but required 3D Tools and some practice. You basically need to combine all textures into one by making a new UV-Mapping of it.
Short answer : if you have never used a 3D Tool, you can't do that, sorry :P (blame Valve)
Pleasant Peasant Jan 19, 2018 @ 1:05am 
I'm trying to apply color RNG to a survivor, however the model I'm using uses 4 textures... so 4 vmts to put the color RNG code into which means its now multicolored is there a way I can group the vmts together and then put the code into one?
Ellie  [author] Nov 5, 2017 @ 1:03am 
@Tiny King Trashmouth : Yes. Texture RNG works independantly of Model RNG. Since the "object" (and by object, it's thing you hold, so "all the weapons at the same time) always have the same value, the RNG, drawn on this value, will always be the same.
You do not even have to worry the slightest about that except that you'll have to merge the proxies block into one (order doesn't matter) because you can't have 2 "Proxies" block in a VMT.
And by "merge", you won't even need to merge if you take texture RNG and add Model RNG to that.
Feel free to add me so I can help you :), but as I already said, the first part is to put the different "parts" to RNG in separate VMT by 3D Model editing (define new material names for these parts)