TTLG|Thief|Bioshock|System Shock|Deus Ex|Mobile
Results 1 to 2 of 2

Thread: Auto Texture Replacement Script - Let's create a Database

  1. #1
    Registered: Jan 2012
    Location: Gèrmany

    Auto Texture Replacement Script - Let's create a Database

    With the coming DScript1.0 there will be 3 major CreatorScripts, which main goal is to help you in DromEd instead of doing in game stuff. One if it is the AutoTxtRepl or AutoTexRepl or AutoTexRep or AutoTex .... can't decide. Suggestions what name you like more?

    Texture Replacement Objects are great as you can add variety to the same shape but at the same time it could be kinda a hassle.
    CoSaS beds with over 100 varieties. Many Replacement Picture Frames and Doors but what Textures to use? The Tree pack with X Tress Y Leaves and Z Barks. The Vegetation Pack 5 Bushes x 20 Textures. The Book Collection with 29 covers (Off Topic non commercial advertising) and and and...

    But jahh checking which textures are available then edit object, add shape TexRepl write obj\txt16\ for the 100th time... that becomes annoying and maybe we just fall back to standard types.


    The Auto Texture Replacement Script automatically chooses textures based on the model.

    But for this a database is required. And that database needs your help! You also can and should add your own custom stuff. So CLICK ME
    (or first read about it

    So how does it work and look like.
    The script works with two table sets {Category=Models} and {Category=Textures} with categories as key-lock system. When it found the model in a category it will add a random texture from the same category from the texture table.
    Models: Pictures=["NVPictureFrame","AnotherPicture"]
    Textures: Pictures=["Paint1","Paint2","picnic"]
    So for example if you create a model with the Shape->Model Name: NVPictureFrame it will add one of the textures ""Paint1","Paint2","picnic" to the TxtRepl r0 property of that object.

    Slot Definition
    By default the Field 0 is used. By inserting a number (1-3) behind the model name this can be changed.
    Models: Barks=["1aTree"]
    This will add a Barks texture to Field 0 and a Leaves texture to Field 1 and as you see the same model can be used in more than one category.

    If your model uses more slots a sub texture table can be defined for example:
    Models: Book=["DBook"]
    Textures: Book=
    This will add to Field 0 one of the textures from "0" to Field 1 one from "1" ....
    Additionally with the KeepIndex variable it tells the script that the Field 0 and 1 should use textures with the same index so when Book2-0 gets randomed Book2-1 is chosen automatically.

    The numbers should be enclosed by "" and : used instead of = !

    Replacement Syntax
    Textures&Models can be added in four different ways, as seen above as single texture
    Textures: Key=["TextureName"]
    or also added automatically if they are in a numeric order ( so you don't have to write tex1, tex2,....)

    Textures: Painting=["RipOff#",11,"RipOff#",13.16]
    The # will be replaced by the row defined by the number added after the texture name. (The # can also be in the middle like: Book#-1 but not more than one # may be added)
    For integer numbers it will add 1->n and for float/decimal numbers the integer part->decimal part so for above RipOff1,RipOff2,...RipOff11 will be created and RipOff13,...,RipOff16. Obviously the decimal part must be higher.

    By default obj\txt16\ is the pre-added path. Other paths can be chosen but their full path needs to be written. NOTE that TWO \ are required!
    Textures: Windows=["fam\\church\\glas1"]
    A $ will be replaced by the entrys in an array in the slot directly behind the model or texture name:
    "Model$",["A","B"] -> "ModelA" , "ModelB"
    All optional Variants can be combined but must be in the order Array,Float,integer
    Models: "#$Worstcase",["a","b"] , 1.2 , 3 -> a1Worstcase,3, a2Worstcase,3 ,b1Worstcase,3 ,b2Worstcase, 3


    The script is designed to work automatically without parameters but there are also some options beside the standard DBaseTrap Parameters.
    DAutoTxtReplType=Category will add a random texture from the chooses Category into the TexRepl Field defined by DAutoTxtReplField (Default=0)
    (Not yet implemented) DAutoTxtReplLock (similar to DAutoTxtReplCount=1) if a Field is already filled with a value it will not be rerandomed again and skipped. This allows for example the manual adjustments of objects.
    DAutoTxtReplMode (Default=1)
    	// 0 will only work when TurnedOn (standard Trap behavior) Default: TurnOn and test via script_test ObjID
    	// 1 (Default) Not automatically in game.exe
    	// 2 Everytime when loaded. PRO: Works on in game.exe created objects CONTRA: Also executes after save game loads. Consider DAutoTxtReplCount=1 or Lock=1
    NOTE: Mode=2 will for example change pictures or your bedsheets;) in the game.exe after every reload, could be kinda interesting.

    What can you do?

    This database has two purposes.

    a)Collecting Models and Textures(*) which fit into generic categories for example Picture Frames, Rocks, DoorFrames...
    While models can be added without limitations. Textures which are not present for the user will be blank and DromEd will throw a warning. (Squirrel Question:Is there a way to test if a texture is present? FindFileInPath looked promising but fails - I think it doesn't check subfolders :/ . Can you somehow grab the resname_base add \obj\txt16 to the contents and then save that as path variable to be used again?)

    As this is a script for creators they(you) will realize when a texture is missing but I think we shouldn't hide good textures maybe move them to another commented array with information where to find them.
    Even just creating fitting texture categories would be helpful with the use of Yandros' generic reskinnable objects. or similar. You got a table model and want some Wood (frame) Textures....

    b1)Adding your own Models and fitting Textures
    Models: MyCategory=["MyModel"]
    Textures: MyCategory=["MyTexture"]
    This will help others who also use your model and this script to automatically texture it. Take my DBook as an example.
    Also here you can assume if the model is present the textures will be too as they come from the same source.

    b2)Creating Replacement Versions of existing sets.

    Kinda the same problematic: You have a few non replacement models, do you want to add them all to your gamesys or manually edit the shape numerous times just to change the texture?
    We could create Larry'sTarrotPictures->[1..30], CoSaS Books+Lamps+->[1...], Firemage' Dishes, Otto's Art Collection, Random Street Sign, Metal Decals and again and and and...

    In the end just one hierarchy slot but the whole set variety without extra adjustments.

    So where can I begin?

    Link to the Database

    I just took simple online editor.
    If you think GoogleDocs would be better and can set it up. I think we can happily migrate.

    Want to test it?

    The following code snip is working beta. Needs DScript.nut to run.

    ##############     DAutoTxtRepl 	###########################
    // We define this stuff globally here so not every script instance uses a copy. Modify to your liking.
    	{	//Standard is TexRep0, insert a number behind a model name to change it to TexRep#
    		//a $ will be replaced by the entrys in an array in the slot directly behind the model name: "Model$",["A","B"] -> "ModelA","ModelB"
    		//a # will be replaced by the numbers x->y specified a slot behind the model name "Model_#",1.3 -> Model_1,Model_2,Model_3
    		//All three optional variants can be combined but must be in the order Array,Float,integer
    				//"#$Worstcase",["a","b"],1.2,3 ->a1Worstcase,3,a2Worstcase,3,b1Worstcase,3,b2Worstcase,3
    	DLeaves=["1aTree",1,"1aLeaves","1bLeaves","2aTree",1,"2bLeaves","2bTree",1,"3aLeaves","3aTree",1,1,"3bLeaves","3bTree",1,"3bTreelod2",1,"3cTree",1,"4aLeaves","4aTree",1,"4bLeaves","4bLeavesLod2","4bTree",1], //removed some models
    	Book31=["DBook","DBookB"]		//Bind Cover ratio id 3:1
    		//If the Textures are in a SubTable the behind number indicates the max field that should be filled. So for example BookWithSide=[..,"MyBook(.bin)",1,..] would only get TexRepr0 and TexRepr1
    		//TODO: Does not work for 0
    //A number behind a Texture will replace the # with 1->i for integer and for example 18->32 for float numbers.
    //While it doesn't matter if a user doesn't have the models in ModTable you should make sure that the ones here in TexTable are provided or standard.
    	Pictures=["Paint1","Paint#",18.32,"picnic","RipOff",11,"RipOff",13.16]	//These require EPv2
    		KeepIndex="01",		//string with #field names which should share the same randomed index both arrays must have the same size.
    class DAutoTxtRepl extends DBaseTrap
    //	["NVPictureFrame","DBushR","DBushR2","DBushR3","DBushR4","DBushR5"]
    function DChangeTxtRepl(texarray,field=0,i=-1,obj=false,path="obj\\txt16\\")
    	if (!obj)
    	if (i==-1)			 //If same index is desired
    	local tex = texarray[i]					
    	if (startswith(tex,"fam\\"))
    	if (!(DGetParam(GetClassName()+"Lock",false)&&Property.Get(obj,"OTxtRepr"+field)!=""))	//Should work without !=, Archetype definitions will be kept.
    		Property.SetSimple(obj,"OTxtRepr"+field, path+tex)
    	return i
    function DParseTexArray(texarray)
    	local rem=[]
    		foreach (i,tv in texarray)
    			if (this=="ModTable"&&typeof(tv)=="string")
    			if (typeof(tv)=="array")
    				local tname=split(texarray[i-1],"$")
    				foreach (idx,char in tv)
    					if (tname.len()>1)
    					if (typeof(texarray[i+1])=="integer"||typeof(texarray[i+1])=="float")	//Will parse numbers separetly later
    						if (typeof(texarray[i+2])=="integer")	//Will parse numbers separetly later	"#$Worstcase",["a","b","c"],2.4,2
    							if (idx==tv.len()-1)
    								rem.append(i+2)		//trash 1st generation
    						if (idx==0)								//float XOR int trash
    				rem.append(i)									//trash array and original
    			local j=1
    			local ModInt=false
    			local noarbefore = (i==0||typeof(texarray[i-1])!="array")
    			if (typeof(tv)=="float"&&noarbefore)
    			if (typeof(tv)=="integer"&&(this=="TexTable"||ModInt)) //don't want to Parse for example Model-Leaves[1aTree,1]
    				local x=1
    				if (!noarbefore)
    				local tname=split(texarray[i-x],"#")
    				for (j;j<=tv;j++)
    					if (tname.len()>1)
    					if (typeof(texarray[i+1])=="integer")	//ModTable Beds=["Bed#",1.12,2]  Parsing and a Field specified
    						if (j==tv)							//trash 2nd generation
    		//Trash preparsed entrys
    		for (local r=rem.len()-1;r>=0;r--)
    		// Print result for control
    		foreach (i,tv in texarray)	
    	return texarray
    function DoOn(DN)						//TexTable={k=v[index i=tv] }
    	//Parse TexTablefor easier random use
    	if (!::ParseDone)		//needs only be done once per Session
    	foreach (k,v in TexTable)
    			if (typeof(v)=="array")
    			else //another table TexTable={	k= v={	k2=v2[index i=tv]	} }
    				foreach (v2 in v)
    					if (typeof(v2)!="array")	//KeepIndex. THIS IS THE PARSER
    	foreach (k,v in ModTable)"ModTable",v)
    ########### Actual Selection
    	if (!type)
    		local m = Property.Get(self,"ModelName").tolower()
    		foreach (k,v in ModTable)
    			local idx=v.find(m)
    			if (idx!=null)
    				//Check if custom tex field is specified.
    				local f = 0
    				if (!(idx==v.len()-1)&&typeof(v[idx+1])=="integer")	 //if its the last entry v[idx+1] would throw an error.
    					f = v[idx+1]
    				//Get Texture from a Array[]	
    				if (typeof(TexTable[k])=="array")
    				else //Get Textures from sub table like BookWithSide 
    					local KeepIndex=[""]
    					if ("KeepIndex" in TexTable[k])
    					foreach (field, tv in TexTable[k])	//TexTable={	k=TexTbl[k]={	field=tv[...]	} }	
    						//TODO: Does not work for 0
    						if (typeof(tv)!="array"||f>0&&field.tointeger()>f)	// KeepIndex case OR not all Fields should be used
    						if (KeepIndex[0].find(field)!=null)
    				//That's wrong here print("DAutoTxtRepl ERROR: Didn't find a match for Shape ModelName "+m+". On Object "+self+. "Specify DAutoTxtReplType")
    /*For demo video
    	if (IsEditor()==2)
    function OnTimer()
    function constructor()
    	local DN=userparams()
    	local Mode = DGetParam("DAutoTxtReplMode",1,DN)
    	local Exe = IsEditor()
    	// 0 will only work when TurnedOn (standard Trap behavior) Default: TurnOn and script_test ObjID
    	// 1 (Default) Not automatically in game.exe
    	// 2 Everytime. PRO: Works on in game.exe created objects CONTRA: Also executes after save game loads. Consider DAutoTxtReplCount=1 (TODO: Check if compatible with BaseTrapConstructor) or (TODO:) No Overwrite option.
    	if (Mode!=0&&!(Exe+Mode==1))
    Last edited by Daraan; 7th Dec 2017 at 15:54.

  2. #2
    Registered: Aug 2007
    Location: LosAngeles: Between Amusements
    This may be of use to you.

    New Art package

    > NewArt <

    > Overview <

    This package includes 128 painting objects based on images downloaded from
    Olga's Gallery ( and raw frame textures downloaded
    from CG Textures ( and then edited and adapted to
    work within T2. The picture objects are based on the original T2 picture
    objects with new art and frame textures applied.

    Olga's Terms of use are simple and to the point:
    Images from Olga's Gallery are made available for limited non-commercial,
    educational, and personal use only, or for fair use as defined in the United
    States copyright laws. Users must, however, cite the source of the image as
    they would material from any printed work, and the citations should include
    the URL ""

    CG Textures provides the following statement of restricted use:
    Use of the Textures is only allowed under one or more of the following conditions:
    - Private or commercial use
    - Use in 2D or 3D computer graphics, movies and printed media
    - Incorporation in computer games, 3D models
    - Selling 3D models bundled with modified versions of the textures, when the
    texture is customized for the 3D model

    It is NOT permitted to:
    - Sell or distribute any of these textures in an unmodified form, or where the
    derived product you are selling or distributing is a Texture or a collection
    of Textures. In other words: Do not sell or distribute any of these textures
    (modified or not) by itself or in a texture pack!
    - Interfere with the security or otherwise abuse, disrupt, place excessive loads
    on, or attempt to gain unauthorized access to the CGTextures website or any
    system resources or networks connected to this website.
    - Stockpile images with the goal of making a local copy of all textures on the site.
    - Using a special program (spider, leecher) or script to automatically download
    all Textures on the CGTextures website. Users who try to mass download will be
    banned from the website automatically.

    This package is provided with these restrictions intact.

    > Contents <

    NewArt Readme.txt : This file
    Index.pdf : A description of each painting included in this package.
    Note that the T2 object used as the model for a new
    painting is indicated by ">" in the list of compatible
    T2 models.
    PaintingArchetypes.pdf : Identification of achetype to object to texture in T2

    ..\NewArtSource : A sub-directory of .3ds files and individual palette
    .gif files (higher quality color, but increases palette

    ..\Obj : The sub-directory of the 128 picture .bin files
    ..\obj\Txt16 : The sub-directory with the 128 picture .gif files repaletized
    to use only 10 palettes, together with 44 .gif frame textures

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts