|
Search:
Advanced search
|
Browse by category:
|
Glossary | Contact Us |
Programmer's Guide to BHAV's by ECHO |
|||||
A Programmer’s Guide to Behaviour Editing Contents Contents .................................................................................2 Introduction.............................................................................3 What is this document about? .................................................3 Who is this document for? ......................................................3 Why not just make "BHAVs for Dummies"? ...............................3 Getting Started ........................................................................4 Tools....................................................................................4 Tutorials and Walk-throughs ...................................................4 SimAntics ................................................................................5 What is SimAntics? ................................................................5 The SimAntics paradigm.........................................................5 BHAVs = SimAntics? ..............................................................6 Calling a function in a BHAV ....................................................6 Changing the contents of an existing BHAV ...............................7 Importing Semi-globals.............................................................9 The nature of semi-globals .....................................................9 Adding semi-globals from your object’s semi-global library .........9 Adding semi-globals from a foreign semi-global library.............10 Getting your function called .....................................................10 Calling from an existing function............................................11 Pie Menu Functions ..............................................................11 Object Functions..................................................................12 Overriding default functions ..................................................12 Constant values and BCONS ....................................................13 Expressions and Primitive 0x0002 ............................................13 Where to now?.......................................................................13 Introduction What is this document about? This document aims to provide an intermediate level description of the known background theory behind behaviour editing for The Sims 2. It is not a guide to any one tool, nor is it an explanation of how to make new objects. Instead, this document exists to allow people to come to grips with some of the important fundamentals to changing the behaviours in The Sims 2. Who is this document for? This document is not a "BHAVs for Dummies" guide. It is targeted at those who have had a play around with the internals of Sim Packages, tried a few of the tutorials, and want to try something a little more complicated. It also assumes some degree of programming understanding. You don’t need to be a computer genius, but some knowledge about basic programming theory (selection, function calling, etc) is extremely helpful. This is a "Programmer’s Guide" after all! That does not mean that if you can’t program you won’t get anything out of this, but you will likely come across terminology and ideas that are strange or unfamiliar to you. There are many resources online that are excellent at explaining these concepts. Additionally, there are tutorials available that walk you through the process of modding The Sims step by step if you find that method of learning more useful Why not just make "BHAVs for Dummies"? Why not indeed? Well the obvious reason for that is that dummies are probably not the best people to be doing BHAV editing! BHAV editing isn’t extremely hard, but it is certainly not something you can pick up after ten minutes and a two-page tutorial. More seriously speaking, there are a lot of concepts familiar to programmers that occur in BHAV editing. If this understanding can be assumed, it saves a lot of explanation on my end. Getting Started Tools As stated earlier, this is not a guide to any specific tool. However, one or two tools are of particular use while trying to understand behaviour editing. SimPE A package editor for the Sims. At present, this is the predominant tool used in the modding community. It will let you get in and modify most parts of Sims packages, and is reasonably accessible for users. DatGen DatGen promises to provide a great many tools to aid in behaviour modding, particularly for objects, through their "Lilith" plug-in. This tool does not currently have the same number of experienced users, but has a lot of potential as a user friendly package editing tool. DisaSim2 While I have not used this program myself, it comes very highly recommended as a tool for examining the contents of BHAVs in objects. Tutorials and Walk-throughs The best way to get a feel for your tools before diving into the theory is to have a go at a few of the available tutorials and walkthroughs that already exist for your tool. If you have not done so already, make yourself an expert on the process of recolouring and remeshing objects using your chosen editor (not just wizards!). It does not matter if this isn’t where your interest truly lies, these are just areas where you have a lot of support available while you learn. Even more importantly, it will give you a feel for manipulating the internals of a Sim Package. Finally, as an introductory tutorial to changing behaviours in SimPE, I highly recommend Carrigon’s tutorials, listed on the SimPE web site. SimAntics What is SimAntics? SimAntics is the programming language used in The Sims 2 to define the behaviour of the Sims. Coding in SimAntics is a bit like coding in a language half way between assembly and a simple procedural language, but the language has plenty of little idiosyncrasies. The SimAntics paradigm The structure of a SimAntics function owes a great deal to flow charts and decision trees. Each function is made up of one or more discrete lines of code. Every line of code, when run, is evaluated to return either true or false. If the outcome of the line is true, control passes to a particular line of code. If the outcome of the line is false, control passes to a different line of code. Thinking in terms of selection constructs, it is as though each line is translated into an "if" statement. That is; if(line_1 == true) goto line_3; else goto line_4; These paths make more sense if they are displayed graphically, using flow charts or directed graphs. For example, given the following calls: Line True Target False Target 1 3 2 2 4 Fail 3 Success Success 4 Success Fail It is possible draw this as a flow chart: When a function you have written is called by another function, the success or failure values the function produces are returned as the true or false values for your function as a whole. BHAVs = SimAntics? BHAV files are the files within a package that record the sequences of SimAntics calls for a particular function. Every BHAV file has its own start point, and returns a true or false value based on the success or failure of its code. Calling a function in a BHAV Every line in a BHAV represents a function call. Each function call must include: The opcode of the function you are calling The line to jump to if the function returns true The line to jump to if the function returns false As well as this, the function may take either eight or sixteen parameters. The opcode of a function is the unique identifier for that function. For any given BHAV , its opcode is the same as its instance id. There is an important convention in the numbering of opcodes: Opcodes in the range 0000 – 00FF are primitives Opcodes in the range 0100 – 0FFF are globals Opcodes in the range 1000 – 1FFF are locals Opcodes in the range 2000 – 2FFF are semi-globals Primitive functions are exactly that: primitive. They are the building blocks of all other functions and are hard coded into the Sims game engine. Primitives are available to all functions in all packages. Global functions are one step up from primitives. They are not hard coded into the Sims engine, and it is possible to look at their BHAV code. They use primitives to perform actions that are used across a wide variety of different areas, and are thus also available to all functions in all packages. Local functions are the ones that are most easily accessible and, initially, the ones you are most likely to be editing. They can call primitives, globals, and certain semi-globals, but are only really visible to the object they belong to and to function calls within that object. Semi-globals are a little more complicated. They are functions which have been abstracted for a particular set of objects. They are common between a particular family of objects, but are only accessible by objects in that family. For example, the semi-globals library for chairs includes functions for sitting down and standing up. Only objects that have been defined within the game as "chairs" can call these functions. Semi-globals can see both primitives and globals (and under some very strict circumstances locals). Each object is able to choose one set of semi-globals that it will access, generally based on the sort of object it is. Thus a chair would normally choose to see the "chair semi-globals". Only objects that have selected a particular semi-global library can call the semiglobal functions. Probably the simplest of the function calls you could make would be the following: Opcode True Target False Target Parameters Sleep (0x0000) Success Failure Sleep is a very simple primitive that takes no parameters, does nothing and always returns true. Parameters vary on a per-function basis. They provide the function with specific details about what you want the function to do. For example, in the primitive 0x0001 (Generic Sims Call) the first and only parameter is a number specifying which of the generic Sims calls it was that you wanted to run. Changing the contents of an existing BHAV The specifics to changing the contents of an existing BHAV are highly dependent on the program you are using to do it, but there are several elements that are the same regardless. If you wish to add a new function call, it will generally be added after all the existing function calls. This is rather like adding a node to your flowchart that isn’t connected to anything. The node will never be run, because nothing is directing the function to run it. Let’s say you have added a new function called ‘b’. You must look at the existing contents of the BHAV to find the function you want function ‘b’ to follow on from. Let’s call this function ‘a’. You should first note down where ‘a’ was pointing, then make at least one of its true or false targets point to the line containing function call ‘b’. You must then make sure that ‘b’ does not simply quit the BHAV (unless you want it to of course!) but rather continues the execution of the BHAV . Graphically represented, you must essentially do this: When bypassing a node (disconnecting it so that it is no longer used), the process is essentially done in reverse. You must find all the places that call the node and redirect them so that execution skips the node in question. Deleting a node entirely is not really recommended, because it is very hard to undo. Instead you should bypass nodes you no longer want. Once you are completely sure that your change is working with no ill effects then it is safe to delete the node. Importing Semi-globals The nature of semi-globals As described earlier, semi-globals are libraries of common behaviour for particular types of objects. You can find which semi-global library your object is using by looking at your package’s GLOB (aka "Global Data") file. This file will tell you the name of the library your object is using, as well as the library’s group ID. All the functions in semi-global libraries have instance IDs between 0x2000 and 0x2FFF, and each semi-global library has a specific Group ID. You can find the BHAVs for these libraries by looking though the Objects.package file for BHAV files with the same Group ID. Specific functions can be found by filtering these results on instance ID. Adding semi-globals from your object’s semiglobal library When cloned, many simple objects do not come with all the behaviours associated with them in the package. That is because most of the behaviours are located in semi-global functions. If you want to change one of these behaviours in your clone but leave the semi-global behaviours intact for all the other objects, then it is necessary to make a new local copy of the BHAV from the semi-global library. Once you have found the semi-global in question, you need to export it and import it into your own file. Once this is done, it is vitally important that you change the BHAV ’s Group ID to #FFFFFFFF and the Instance ID to an unused number between 0x1000 and 0x1FFF. If you do not do this, then your imported BHAV will override the one in the semi-global library. It is at this point that your detective skills come in to play. You must now track down all places in your object where the semiglobal you imported could have been called from. If the pie menu originally called the semi-global, then you must edit the pie menu functions so they now call the new local BHAV . Any time the semiglobal in question was called by a function, that function must be updated. It is important to note that some Sims tools can perform this task automatically for you on request (to varying degrees of success), so investigate your program for this capability. In some cases, this is all you have to do. Unfortunately, with many functions (especially the lower level functions), there may actually be unimported semi-globals that are still referencing the original semi-global. If this is the case, then you need to import those offending semi-globals, update the calls in their BHAV files, and repeat the entire process for each of these. In some cases, the number of imported BHAVs can grow exponentially. Not all semi-globals require the same degree of backtracking. A function that is called from a pie menu is generally only referred to in a few places, but a function that is only ever called by another function could be referred to in significantly more places. Adding semi-globals from a foreign semiglobal library The process of importing semi-globals from a foreign semi-global library (that is, a library that is not the one your object normally accesses,) is similar to the process of importing from your own library. However, there is an added complexity involved. Say, for example, you have a painting (which can only see the "Paintings" semi-globals) and you import a semi-global BHAV from the "Stereo" semi-global library. Any function calls that exist in the imported function are expecting to be called from a Stereo type object, not a Painting type object. Thus, when the BHAV makes a call to opcode 0x2009, it thinks it will be getting the Stereo semiglobal (Stereo – Turn Off/On), but what it will actually get is the Painting semi-global (Interaction – Critique – Test). This means that when you are importing semi-globals from a foreign library, you must also import all the semi-globals that are called by the function and repeat the same process. Getting your function called As is the case with most functions in most languages, code will never be run unless the function is called by something. If you have created a new function or imported one from some other object, it is important to make sure that the object is calling your function at some point. There are four main ways your function can be called. Calling from an existing function The obvious way to get your function to run is to call it from an existing BHAV function that is already being called. This is done in the same way as function calls in general which was described earlier. The function’s opcode is simply the instance ID of the BHAV you added. Pie Menu Functions From the user’s point of view, this is the normal way of getting an object to do something. Click an object, select an option from the menu, then the object does something. The link between the pie menu and an object’s BHAVs can be found in the TTAB (aka "Pie Menu Functions") file in your object’s package. There are a great many things that can be tweaked in this area for different effects, but there are two sections which are vital to getting your function called. The first and most obvious is the Action field. This must be set to the opcode (instance ID) of the BHAV function you want to call. The second field that is important is the Guardian. This function also takes an opcode to a BHAV , but serves a different purpose. The guardian should be a function that evaluates whether a particular menu item should be shown should the currently selected sim try to use it. For example, the "Make Breakfast - Pancakes" menu item is only available early in the morning, to sims with high enough cooking skill. To check if this is the case, there is a BHAV which returns true if the currently selected Sim is permitted to run that menu option, and false if not. If the BHAV returns false, the menu option will not be displayed. It is important to note here that Guardian functions are run every time the mouse even hovers over an object. You don’t even have to click on the object for the Guardian code to be run! That is why it is extremely important that a Guardian function does not change anything in the game, rather it just looks at game settings to determine if the option should be available. If you do not want a guardian function for your behaviour, you can set this field to opcode 0x0000 (Sleep) and it is assumed that your function can always be run. There are a few things that Guardians are not responsible for checking when it comes to opening menus. The game engine itself is responsible for checking some things, like the age group of the Sim. The TTAB files have flags specifying what age groups the function is available to, as well as if it is accessible to visitors and whether it can be used autonomously. These tweaks are currently beyond the scope of this document, but should be fairly simple to change depending your particular editing program. Adding new pie menu items is relatively simple, but it requires additional changes in the related TTAs files (aka "Pie Menu Strings"). Every line in your TTAB should generally have an accompanying line in the TTAs giving it a name for the menu item. Object Functions Where Pie menu items allow users to make an object perform an action on command, object functions allow the system to call certain functions automatically. The most common of these is the "init" function, which is run automatically when an object is created. There are several engine events that you can assign functions to in the game, all of which you can find in your object’s OBJf (aka "Object Functions") file. You will generally have one OBJf to start off with, and one additional OBJf for every tile your object takes up. Each event listed in the OBJf file has a pair of corresponding Guardian and Action calls. In most cases, only an action is needed for object functions, as they are run automatically by the game. If you want to remove either or both of these function calls, simply set them to opcode 0x0000 and they will essentially be ignored. Overriding default functions It is possible to write your own functions which replace existing functions. When you do this, then your function will be called in all the same places that the default version was called. This style of hacking is a little more risky than modifying new objects, and is generally reserved for game-wide hacks. In user made objects, all the BHAVs should have their Group IDs set to 0xFFFFFFFF, and have Instance IDs between 0x1000 and 0x1FFF. These values mean that the changes you make will only affect the object they are placed in. However, in the case of hacking the game play or fixing game bugs, you will want the change you make to override the game’s default behaviour. To do this, simply leave the Group ID and Instance ID with the same values as the function you are trying to override. When the game is loaded, it will use your function rather than the default one. I will repeat now that this is risky. Changing default behaviours can have wide ranging and unexpected side effects. If you choose to distribute a package with elements that override default functions, it is important that you mention the nature of your changes to your downloaders. Constant values and BCONS It is possible in Sims packages to store constant values for use in your BHAV functions. For example, if you are creating an object that increases fun you may want to create a constant value that represents the speed of the fun increase. If, after testing your object, you determine that the fun increase is too slow, then you can change the value of the constant in the package without hunting down all the relevant lines in your BHAV and modifying them individually. Constant values are stored in files called BCONs. Each constant value is stored in its own line, and can be accessed using a combination of the BCON’s instance ID and the specific line number of your value. Many existing Maxis objects can be tweaked quite easily using the BCONs, without the need to change the BHAV files at all. Expressions and Primitive 0x0002 Probably the most important function you will ever come across is "Expression", with opcode 0x0002. Expression allows you to evaluate mathematical and Boolean expressions, as well as assign values to properties in the system and set various system flags, amongst other things. Details on primitive 0x0002 and its use can be found in numerous locations, in particular on the MTS2 Wiki. I strongly recommend you become familiar with it, as it is a well understood and extremely useful primitive. Where to now? Clearly this is not a complete guide to BHAV modding. There is a lot of known information about BHAV programming that is not covered here. There is also a fair amount of information about BHAV modding that is not known yet. An excellent resource for modders is the ModTheSims2 forums and its various sub-forums. Get yourself involved in discussions, and read everything informative that you can find! Above all, try things out! Play around with BHAVs and other parts of your packages just to see what happens. You never know what great new discovery you might make. And if you discover anything interesting, then be sure to share it with the rest of the community. Good luck, we can’t wait to see what exciting new mods you come up with! Version 0 5 June 2005 Corrections to echo_eternity84@yahoo.com
|
|||||