The programming language used within the Sims 2 to define the behaviour of sims and objects in the game. Within a Package, SimAntics is defined in BHAV files.
The structure of a SimAntics procedure owes a great deal to flow charts and decision trees. Each procedure is made up of one or more 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.
This produces an execution structure very similar to a flow chart. Execution always begins at the first line (or node), and chooses its path based on the results.
For example, the following segment of code:
0x0001: Expression (My motive Fun >= Literal 0x0000), True Target: 0x0001, False Target: 0x0002 0x0002: Expression (My motive Fun += Literal 0x0010), True Target: Return True, False Target: Error 0x0003: Expression (My motive Fun += Literal 0x0020), True Target: Return True, False Target: Error
Checks to see if the current sim's "fun" motive is greater than or equal to 0. If this condition is true, then line 0x0001 is run, otherwise line 0x0002 is run. In the first instance, the sim's fun level is boosted by 0x10 points, but in the second instance the fun level is boosted by 0x20 points.
Both lines 0x2 and 0x3 have a True Target or "Return True". If this procedure were to be called by a different Procedure (this process is described below,) then in both of these cases the command would be evaluated to true, and the command's True Target would be followed.
If a target that points to "Error" is run, it generally means that something very unexpected has happened. If a user is playing with Testing Cheats enabled, they will receive a pop-up error message, and a stack trace will be generated in their error logs directory. If Testing Cheats are not enabled, then the object will generally reset.
Every command in SimAntics is identified by an OpCode. These opcodes are numerical, and fall within one of four regions:
- Primitives, within the range 0x0000 - 0x00FF
- Globals, within the range 0x0100 - 0x0FFF
- SemiGlobals, within the range 0x2000 - 0x2FFF
- Locals, within the range 0x1000 - 0x1FFF
The region an OpCode falls into affects the contexts in which it may be called.
Primitives may be called by any procedure in any object. The behaviour of primitives is defined within the sims game engine, and so cannot be easily modified.
Globals may also be accessed by any procedure, but unlike primitives they are not defined within the engine. Globals are procedures made up of calls to primitives and other globals, and are stored in BHAV files distributed with the game. The OpCode of a Global is its instance number.
SemiGlobals are procedures that are specific to a particular class of objects. An object defined as a chair will only be able to run chair SemiGlobals, where a table will only run table SemiGlobals. Because of this SemiGlobals for different classes of objects may have the same instance number, and consequently the same OpCode. They are differentiated by their group numbers. SemiGlobals are generally made up of calls to other SemiGlobals, Globals, and Primitives.
Locals are procedures that are limited to a single object or package. They are able to call other locals, SemiGlobals, Globals and Primitives, but can generally only be called by other locals within the same object. SemiGlobal bhavs can call local (object-based) bhavs; it seems that Globals can as well, but it has not been observed. The exception to this is when using the "Run Tree By Name" primitive, which allows objects to call other objects' local procedures, SemiGlobals procedures or Global procedures. Locals also use their instance number as their OpCode.
Every command has either 8 or 16 bytes of space in which to store operands which are received by the caller as parameters. The nature and purpose of these operands is dependent on the procedure or primitive being run. Operands are stored and passed as little-endian values, so sequence is important when passing values that require more than one byte of space.
- Making Your First Custom BHAV
- Introduction to BHAV Files
- Welcome to Adventures in Simantics...
- TTAB’s Explained: How to Edit Menu Options
- Basic Hacked Object Modding Tutorial
- Modding Infocenter - Simantics and BHAVs
- Programmer's Guide to BHAVs
- Fixing self-referencing objects