Portal Clock Timer
After mucking around with logic_timers and env_texturetoggles for hours, I was finally able to figure out how to make this clock work, and boy is it a pain. This intermediate level tutorial will show anyone how to get it working, hopefully in less time than it took me.
1. Create a room or open up the room you want to put the clock in in hammer. A simple room with a button to trigger the timer will do for this tutorial.
2. First let's build the body of the clock. Create a prop_dynamic, and set the model to props/clock.mdl. Place it on the wall where you want it. Next, create the LCD screen. The screen consists of seven blocks: four 10h x 10w x 2deep blocks separated by three 10h x 2w x 2deep blocks, arranged in a row. Texture the blocks in nodraw.
Next, open up the texture browser and find the clock textures (search "signage"). Apply them to the front faces of the blocks, from left to right, in the following order: clock_minutes, clock_dots, clock_seconds, clock_dots, clock_centiseconds, clock_dots, clock_milliseconds. The texture scale for the numbers is X: .08, Y: .08, and the scale for the dots is X: .10, Y: .10.
Finally, move the LCD screen into place in the clock frame.
3. Now come the entities. There are sixteen (!) of them in total. First, select each of the blocks on the LCD screen bearing numbers and make them into func_brushes (the blocks bearing dots should remain world brushes). With this many entities, you're going to do yourself a huge favor by naming them according to a common naming scheme. I named mine, from left to right: clock_minute_brush, clock_second_brush, clock_centisecond_brush, clock_millisecond_brush.
Next, create the following entities: two env_texturtoggle, two material_modify_control, four logic_timer, two math_counter, one logic_relay, and one logic_auto. Name them according to the scheme:
env_texturtoggle 1: clock_minute_toggle
env_texturtoggle 2: clock_second_toggle
material_modify_control 1: clock_centisecond_mmc
material_modify_control 2: clock_millisecond_mmc
logic_timer 1: clock_minute_timer
logic_timer 2: clock_second_timer
logic_timer 3: clock_centisecond_timer
logic_timer 4: clock_millisecond_timer
math_counter 1: clock_counter
math_counter 2: clock_counter_2
(logic_autos cannot be named)
Arrange them in a visually appealing display. (Not a necessary step.)
4. Now for the fun part. First, open the logic_auto, go to the outputs tab, and create the following outputs:
This sets the clock to 01:00:00:00 when the map starts.
Now open clock_relay. Make sure Start Disabled is set to No or 0, then enter the following outputs:
Once the rest of the IO setup is complete, triggering this logic_relay will start the countdown.
Next, we'll tackle the timers. Set each one up the same way: Start Disabled - yes; Use Random Time - No; Refire Interval - 1. The only odd man out is clock_millisecond_timer, whose Refire Interval should be set to .1. Each timer is linked to its respective env_texturetoggle or material_modify_control:
This timer shuts itself off after changing 01:xx:xx:xx to 00:xx:xx:xx.
This timer also adds to each of the math_counters, allowing Source to keep track of the timer's progress.
Neither the centisecond nor millisecond panels can be controlled by env_texturetoggle; they must instead be controlled by material_modify_control entities. This had me hung up for a long time when I was trying to build this clock. Each number in the "parameters" column is separated by a space.
The parameters column here reads "0[space]9[space].1[space]1".
Now for the math_counters. These are responsible for halting the countdown when it reaches 00:00:00:00.
clock_counter: set Start Disabled to No and Maximum Legal Value to 60, then enter the following outputs.
clock_counter_2: set Start Disabled to No and Maximum Legal Value to 59, then enter the following outputs.
Finally we come to the env_texturetoggles and material_modify_controls. No IO work is necessary for these, but their settings do need to be adjusted.
clock_minute_toggle: set Target Brush(es) to clock_minute_brush.
clock_second_toggle: set Target Brush(es) to clock_second_brush.
clock_centisecond_mmc: set Parent to clock_centisecond_brush, Material to modify to signage/clock/clock_centiseconds, and Material variable to modify to $frame.
clock_millisecond_mmc: set Parent to clock_millisecond_brush, Material to modify to signage/clock/clock_milliseconds, and Material variable to modify to $frame.
That should be it! To start the countdown, just input "Trigger" to clock_relay. In my example map, I've chosen to do that by means of a button.
Linking Two or More Clocks Together
In portal, these clocks are seen in a pair at the beginning of the game: one over each autoportal frame, inside and outside of your cell, counting down in unison. Unfortunately, achieving this isn't as easy as copy/pasting the "body" of the clock to another part of the map, but it's a sight easier to create the second clock than it is the first clock.
1. Copy/paste the body of the clock to another part of the map (I know what I just said... just keep reading).
2. The env_texturetoggles on the first clock are capable of handling the minutes and seconds on clock #2, but the material_modify_controls on the first clock are not capable of controlling clock #2's centiseconds and milliseconds displays (unless the two clocks are in very near proximity to each other, in which case they sometimes can). To remedy this, select clock_centisecond_brush and clock_millisecond_brush on clock #2 and change their names to clock2_centisecond_brush and clock2_millisecond_brush. Create two more material_modify_controls, and name them clock2_centisecond_mmc and clock2_millisecond_mmc.
clock2_centisecond_mmc: set Parent to clock2_centisecond_brush, Material to modify to signage/clock/clock_centiseconds, and Material variable to modify to $frame.
clock2_millisecond_mmc: set Parent to clock2_millisecond_brush, Material to modify to signage/clock/clock_milliseconds, and Material variable to modify to $frame.
Now go back to clock_centisecond_timer and clock_millisecond_timer and a new output to each.
Done! When clock_relay is triggered, both clocks will count down in unison. I haven't added more than two clocks, but you could conceivably add as many as you want with this method.