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