The older CandleLight Sims DigiDec unit was, in essense, an alarm clock with a hacked init BHAV (so that it
would hang on the wall) and a graphics-swapping routine built in. This time, I started with a basic
painting, stripped all of the BHAVs and built the object from the ground up. The goal was to create an
object that could be set to ring at any specific time of day or relative to the sim's work schedule
(being from one to five hours before the start time of the sim's job). It can also have its display color set between
blue, red and green.
To begin, here's a brief explanation of the Stack Obj's Attribute values at play:
This Attribute is in charge of keeping up with the DigiDec's display color. 0=Blue, 1=Red and 2=Green.
The Attribute is set by the "Change Color To" BHAVs and is read by the "Update Graphic" BHAV.|
When the alarm is set, this Attribute is assigned the proper value. If the alarm is set for 11:00 PM, then
Stack Obj's Attribute 1 will be set to "23."|
Though the user needn't be aware, the DigiDec alarm has three different "modes." One of the modes is
"off," and that is the default mode set at purchase time when Stack Obj's Attribute 2 is set at "0."
When a specific time is chosen for the alarm setting, the value is set to "6," which indicates that the
alarm is in "manual" mode. However, if the alarm is set to ring a certain number of hours before work
time, then Stack Obj's Attribute 2 is set for a value between "1" and "5," all of which indicate
"automatic" mode. An explanation will follow in the BHAV section.|
Don't be intimidated by the number of BHAVs! It may look like a long list, but it's mostly comprised
of Interaction BHAVs and their Test BHAVs, all of which are so similar and simple that they need very
|Once Per Hour|
True to its name, this BHAV works once per hour. Actually, it works every loop, but returns
"True" immediately if the "minute" value of the game clock is not "zero." Otherwise, the BHAV
first checks to make sure that the alarm isn't supposed to start ringing (by checking Stack
Obj's Attribute 1 against the "hour" value of the game clock), and then runs the "Update
Graphics" BHAV if the alarm isn't supposed to ring yet.
The basic function of this BHAV is to make sure that the clock displays the correct hour in
the correct color. To this end, it first collects the game clock's "hour" value in Local
Variable 0. Next, it checks to see whether or not the time is past noon. If so, we'll need
to subtract "12" from Local Variable 0 because the DigiDec is a twelve-hour clock, not a
military clock; it doesn't display 13:00, for instance. If, on the other hand, the time is
0:00, we go ahead and change Local Variable 0 to "12."
We would almost be finished
at this point, but the design is slightly complicated by the fact that the DigiDec has two
more optional colors. While the drawgroups were being created, care was taken to ensure that
the graphics for the time display would be consistent. The graphic for "12:00" blue is exactly
twelve drawgroups behind "12:00" red, which is exactly 12 drawgroups behind "12:00" green.
Therefore, all we have to do is test the value of Stack Obj's Attribute 0, and if it is "1"
or "2" we simply add "12" or "24" to the value of Local Variable 0 accordingly.
we're almost finished. We can go ahead and tell the BHAV to assign the value of "stack object's
graphic" to Local Variable 0, but keep in mind that the drawgroup for "1:00" blue is actually at
index 0, (and all of the other drawgroups are one index below the time represented by their graphic),
so we simply subtract "1" from the value now stored in "stack object's graphic" before refreshing
the graphic and moving on.
|Update Alarm Time|
This BHAV will immediately return "True" unless the alarm is in "automatic" mode, which (you'll recall from the
"Attributes" table above) means that Stack Obj's Attribute 2 is set to a value from "1" to "5."
The reason for separating a "manual" mode from an "automatic" mode in the first place is that
if the alarm is set to go off a certain amount of time before the carpool arrives, then the actual
alarm hour is not set in stone; it's relative and must be updated regularly in case the sim gets
a promotion and his or her work schedule changes. That's where this BHAV comes into play. Using
a method which was largely stolen from the Maxis alarm clock, it gathers the "job type" in Temporary
Storage 0 and the "job promotion" in Temporary Storage 1. Then, it uses those two values to store
the sim's job start time into a variable of our choosing. Since we first have to set Stack Obj ID
to "Next Person" before grabbing any info from the sim, we can't directly adjust the DigiDec's Stack
Obj's Attributes until setting Stack Obj ID back to "my obj id." For that reason, I just used Local
Variable 1 and Local Variable 2 as proxies for Stack Obj's Attribute 1 and Stack Obj's Attribute 2
As for the math, that starts out with the act of setting Local Variable 1 to
the sim's start job. Since the goal is to eventually set Stack Obj's Attribute 1 a certain number
of hours before the sim's job starts, we need to subtract. Back in the Interaction BHAVs
used to set the alarm for work, Stack Obj's Attribute 2 was set to the appropriate number, and since
Local Variable 2 is now set to Stack Obj's Attribute 2, all we have to do is subtract Local Variable 2
from Local Variable 1.
However, we still have to account for the possibility that our sim's
job starts in the wee hours of the morning, which would cause Local Variable 1 to end up being negative
if we subracted a large enough number. There's an easy fix for this; all we need to do is check to see
whether Local Variable 1 is less than "0" and then add "24" if it is.
Now we can be confident
that Local Variable 1 is currently the value that we want Stack Obj's Attribute 1 to be, so it's time
to return the Stack Obj ID to "my obj id" and assign Stack Obj's Attribute 1 to Local Variable 1's value.
|Set For Work -1|
This is merely the first of the five "Set For Work" BHAVs. It simply uses a standard "Go To" function
and then sets Stack Obj's Attribute 2 to "1." The other four "Set For Work" BHAVs set Stack Obj's
Attribute 1 to "2," "3," "4" and "5" accordingly.
|Set For 0:00|
This particular BHAV sets Stack Obj's Attribute 1 to "0," which means that it sets the alarm
to go off at midnight. It also sets Stack Obj's Attribute 2 to "6" because we want the clock
to be in neither "off" mode nor "automatic" mode, and "6" is the number chosen specifically for
"manual" mode. This BHAV has twenty-three near-identical copies, but each of them sets Stack
Obj's Attribute 1 to a different value from "1" to "23" accordingly.
|Change to Blue|
This BHAV runs "Go To" and then changes Stack Obj's Attribute 0 to "0." "Change to Red" and
"Change to Green" change Stack Obj's Attribute 0 to "1" and "2," of course. After setting
the attritube, there's also a call to the "Update Graphics" BHAV because it's normally only
run from the "init tree" or "Once Per Hour" BHAVs, but we don't want to wait until the time
changes to see the color update.
It doesn't get much simpler than this one. All it does is "Go To" the unit and set Stack Obj's
Attribute 2 to "0," which is the "off" state. It doesn't even make a change to Stack Obj's
Attribute 1 because no matter what time the alarm is technically still set for, it won't
ring if the clock is in "off" mode.
Not surprisingly, this BHAV calls for the alarm clock's "ringing" sound. When it
is first called, it handles a few preliminary steps before trapping the object in
a loop; the most important of these steps is setting Local Variable 3 to "10." This
is important because after the object has entered the loop, each iteration will decrease
Local Variable 3 until it reaches zero, at which point the object will escape the loop.
During the loop in question, the object switches between the two "ringing" drawgroups,
refreshes itself and idles for a moment. Idling is important because the object can't
get back to its "main" BHAV and idle from there, and if the object isn't allowed to
idle at all, it will cause everything in the game, including the sims, to freeze.
Even though the DigiDec appears to have four rotations, please note that it actually only uses
"front" and "back." I was able to keep the numbers in the display from appearing backwards in
the "flipped" rotation because I kept them as seperate sprites. When the DigiDec's frame is
flipped, the sprite index used for the display is actually the "back" graphic. When the frame's
back is showing, the display isn't visible, so it's not even referenced in those drawgroups.
The complexity might have been overkill, but it did manage to save a great deal of unnecessary SPR2
bloat, which can quickly increase file sizes. It's a good technique to keep in mind for larger objects
that would accumulate a lot of bloat quickly.
Thanks for reading!