BigTruck's Fan Page

BOD Python Scripting

20 - A Painless Way to Install New Objects

I think I have finally found a good way to install new models (objects or characters). Previously, in demo maps I have made, it was necessary to manually copy .BOD files to the correct directory. The new method makes the map completely plug'n'play. The maps must be made as a 'Mod' and installed from the BODLoader 'Mods' directory.

Step1
Make a folder in your map named 'To3DObjs'. Put all your new .BOD files for Objects in here. For new Characters, put the .BOD files in another folder named To3DChars.

Step2
At the end of the file 'BLModInfo.py', add this code:
			inststuff=0

			if inststuff==0:
				execfile("../../BODLoader/Mods/MyMapName/Installnewstuff.py")
					instuff=1
			else:
				print "Install stuff already done"
Step3
Create a file 'Installnewstuff.py' in your map folder. The content of the file goes like this:
			import os
			import shutil
			import stat

			def getmtime(filename):
					st = os.stat(filename)
					return st[stat.ST_MTIME]

			Odst= ('../../3DObjs')

			ObjFiles=os.listdir('../../BODLoader/Mods/WizardsDomain/To3DObjs')
			for file in ObjFiles:
				newfile = os.path.basename (file)
				Osrc=  ('../../BODLoader/Mods/WizardsDomain/To3DObjs/'+newfile)

				if os.path.exists('../../3DObjs/'+newfile):
					print "Exists file: ",newfile
					# if file already exists in dest dir, check for for mod time
					if getmtime('../../3DObjs/'+newfile) < getmtime(Osrc):
						shutil.copy(Osrc,Odst)
						print "overwriting : ",newfile
				else:
					print "NOT exists: ",newfile
					#if file does not already exist at dest dir, copy it straight to dest dir
					shutil.copy(Osrc,Odst)
					print "copying: ",newfile
When the game starts, all the contents of the To3DObjs folder are copied to the main BOD/3Dobjs folder. BUT only of a file of the same name does not exist there. However, if you update your model at any time and put the updated .BOD file in the To3DObjs folder, the pre-existing file in the main 3DObjs folder will be overwritten by the new modified version. To install to other directories, simply edit this code, e.g:
Cdst= ('../../3DChars')
and replace Odst with Cdst in the following block of code.

Step4
After this code, add blocks of code for each object installed.
			if os.path.exists ("../../3dObjs/mynewobject.BOD"):
				if not os.path.exists ("../../Config/mynewobject.cfg"):
						listapp = open("../../BodLink.list", "a")                     
						listapp.write("..\\..\\3dObjs\\mynewobject.BOD\n")
						listapp.write("MyNewObject\n")
						listapp.close()
						cfgfile = open("../../Config/mynewobject.cfg","w")
						cfgfile.write("The presense of this file ensures that the BodLink.list is not repeatedly appended.\n")
						cfgfile.close()
Add a version of this block of code for each new Object

The name in Yellow is the internal name of your object (Name used to create it)

The name in Pink is the name of the .BOD file. These can be the same.

Once this routine is set up within the map the new object is permanently installed. This allows the object to be created in any other map even if the map from where it was installed is uninstalled.
So every time you wish to install a new object, just put the .BOD file
in the relevant folder, copy/paste/edit the block of code that writes to the BodLink.list and thats it. If you modify the .BOD file at any time, the copy in the main directory will be updated.

Note. This code installs to basic model and allows it to be created in a map. The texture (.mmp) file is also needed. This can be installed in the main 3DObjs folder simply by putting it in the To3DObjs folder. (Load it from the .lvl file in the usual manner.)
Or it can be kept local to the map by including it in the file list in the BLModInfo file.

Physical objects need extra code to make them solid. Weapons and pickupable objects need extra code (See Lib/Reference.py) to define their data and onscreen name. This is usualy done within the map from
DefFuncs.py e.g:
			import Reference

			Reference.DefaultObjectData['MyNewSword']= [Reference.OBJ_WEAPON, 2, 0, 2.0,  Reference.THR_SPINNING, [Reference.W_FLAG_1H,]]
			Reference.DefaultSelectionData['MyNewSword']=(8.0,4000.0, "My New Sword")
For savegame integrity, add the same code to a file 'ActorsInit.py'
This is not strictly necessary, but the save will crash on load if the Player happens to have a new object in his inventory when you saved.
New Characters need a lot more data. (See eariler tuts)

I have been using this routine for a while now and it seems fairly idiotproof. It's as well to us this method even if you are just testing/experimenting. Avoid manually editing the BodLink.list if at all possible. Certain text editors seem to confuse Python as to where the end of a file is and after manually editing the BodLink.list can become corrupted. It's easily fixed but still annoying.