LarryG on 7/8/2015 at 23:05
Before I go ahead and implement the following, I want to check that there isn't a simpler approach to having a working cuckoo clock, complete with cuckoo calling out the hours. Please read and comment with suggested improvements / simplifications. If there is already some obscure CuckooClock script out there which does all this, please let me know.
I have a cuckoo clock model which is designed for use with the Clock script.
The Clock script advances the clock's hour hand to the next hour and minute hand to point up when the clock is frobbed. This script moves the hands of the clock independent from any joint setup, with the initial position of the hands set using the Script/Timing property and not the Shape > Joint Positions and you might expect. The value of the Script/Timing property is interpreted as the number of minutes past 12. So 60 = 1:00, 75 = 1:15, 360 = 6:00, and so on.
As the clock runs, the script timing property is updated by the Clock script with the current time, however I have found no means to trigger events based on its value (I suppose a custom script could be written to read that property and react like TrigQVar when it reaches desired values, but you would have to take modulo 12 before checking ... anyhow that option isn't open to me), so I have had to plan a QVar system and an NVRelay timer system (see below) to keep track of the time in parallel.
The Clock script expects the pendulum to be joint 3, the hour hand joint 4, and the minute hand joint 5, which is how I have built my cuckoo clock object, with the addition of joint 1 for the door and joint 2 the cuckoo.
The weights are on a separate object and are used to turn the clock on. Once turned on the clock can not be stopped.
The clock's hands are preset to 3:00 and a QHour QVar is initiated to 2 and then incremented at clock TurnOn via HourRelay (see below) to correspond with the hands' initial positioning. This also starts the timer so the cuckoo will appear to call again at the next hour.
In addition to the Clock script, the cuckoo clock has NVJointControl to control the opening of the door, the advance of the cuckoo, the retreat of the cuckoo, and the closing of the door. Each action has it's own TurnOn (though the exact specifications for joint speeds will need experimentation to get right):
[INDENT]NVJointControlOn1="OpenClockDoor"; NVJointControlOn1Joint1=90; NVJointControlOn1Joint1Speed=30; NVJointControlOn2="CloseClockDoor"; NVJointControlOn2Joint1=-90; NVJointControlOn1Joint1Speed=30; NVJointControlOn3="AdvanceCuckoo"; NVJointControlOn3Joint2=0.125; NVJointControlOn3Joint2Speed=5; NVJointControlOn4="RetractCuckoo"; NVJointControlOn4Joint2=-0.125; NVJointControlOn4Joint2Speed=5;[/INDENT]
It also has the TweqOnOff script in order to start/stop the pendulum in response to a TurnOn from frobbing the weights (actually from putting the weights onto the clock's chains, so it really is a tool frob on the chains which sends the TurnOn, but let's not quibble).
Finally, the cuckoo clock also has NVRelayTrap in order to advance QHour and to reset the timer via HourRelay (see below) every time that the clock is frobbed.
HourSetQVar is a marker with NVTrapSetQVar on it. This increments QHour modulo 12. I think the following will accomplish that, if I correctly understand the explanation NV gives for how to write QVar setting equations:
[INDENT]Trap->Quest Var: =(QHour%12)+1:QHour[/INDENT]
HourRelay is a marker with NVRelayTrap and NVRelayTrap2 on it. NVRelayTrap will repeatedly relay the TurnOn every hour and NVRelayTrap2 will relay the TurnOn immediately. Each TurnOn received will reset the timer.
[INDENT]NVRelayTrapOnDelay=3600000; NVRelayTrapExclusiveDelay=1; NVRelayTrapRepeat=-1; NVRelayTrapRepeatOnly=1; NVRelayTrapTDest=HourSetQVar; NVRelayTrap2TDest=HourSetQVar[/INDENT]
There are 12 HourTrigQVar markers, one for each hour. HourTrigQVar1 is typical, using NVTrigQVar to look for QHour = 1. (HourTrigQVar12 looks for QHour= 0.) Each hooks up to the HourActionRelay.
The HourActionRelay marker initiates an hour's events as outlined. Each step completes its job before relaying a TurnOn to the marker responsible for the next step.
* Make the clock frobinert
* Play the clock door opens schema and open the clock door ("OpenClockDoor" message to the CuckooClock)
* Advance the cuckoo ("AdvanceCuckoo" message to the CuckooClock)
* Play the cockoo call schema, repeating the call the appropriate number of times by using an NVRelayTrap to a marker that plays the sound and NVRelayTrapRepeat=$QHour with NVRelayTrapDelay set equal to a little bit longer that the length of the sound (say, 2.1 seconds). This will play the sound the number of times of the value in QHour
* Retract the cuckoo ("RetractCuckoo" message to the CuckooClock)
* Close the clock door ("CloseClockDoor" message to the CuckooClock) and play the clock door closes schema
* Make the clock frobable again.
Is there an easier way? Do you see any glaring logic errors? I appreciate any advice you have to offer. I'm pretty sure my approach will work (in theory) but if there is something simpler that takes advantage of other capabilities, I'm all ears. Thanks.
Yandros on 7/8/2015 at 23:20
There's no glaring errors that I see. I have a grandfather clock in one DCE mission which chimes the quarter hours and keeps accurate time, but it's all done with the joints tweq and NVRelayTraps with appropriate delays set for the chimes.
LarryG on 8/8/2015 at 00:57
I'm thinking now that I re-read this that I may be able to get away with just one of the HourTrigQVars. Since the QVar is read directly by the NVRelayTrapRepeat parameter, there is nothing unique to do for any given hour ... All I need to do is detect when the QVar changes. I don't need to know what it changes to at that point.
ZylonBane on 8/8/2015 at 02:46
My what large text you have.
LarryG on 8/8/2015 at 05:02
Big fonts for old eyes.
Niborius on 8/8/2015 at 10:07
[video=youtube;nmaWsFdbYx0]https://www.youtube.com/watch?v=nmaWsFdbYx0[/video]
On Topic: Nice script though. I like how some FM creators often try harder to get a desired effect than official game creators. All clocks I ever saw in games were just static objects.
LarryG on 8/8/2015 at 22:27
It turns out that NVJointControl respects Tweq > Joints > Halt: Continue. I had thought that it would just move to the specified joint position and quit. But no, it seems that it checks the Halt parameter and does what that says to do. Why is this not good in this case? Because if it is set to Continue (needed to keep the pendulum joint swinging) the clock door also keeps swinging once started by NVJointControl. Bummer.
But all is not lost. I'll simply put the pendulum on another object so that it can have different joint settings from the cuckoo door and bird. Fortunately NewDark allows us more objects than OldDark did.
Edit: I had the oddest experience putting the pendulum on it's own. When I used joint 3 for the pendulum on the clock object, that worked just fine. But when I put it on its own object it would not activate with joint 3. I had to switch the joint to joint 1 in the model, and then the joint worked. The only difference between the two cases is that on the clock joints 1, 2, 3, 4, and 5 were all present. With the pendulum object only one joint was there, joint 3. And that didn't work. The only difference between the model that worked and the one that didn't was which joint was defined in the model and which joint the tweq was set to. Everything else was the same. I sure I must've used joint 3 by itself before, but I can't recall for certain. Maybe it never works on its own, but only with other joints defined? Odd. Anyhow I'm past that minor roadblock and back traveling on down the cuckoo highway,
LarryG on 11/8/2015 at 04:34
[video=youtube;rmg1CkGrDKk]https://www.youtube.com/watch?v=rmg1CkGrDKk&feature=youtu.be[/video]
And here it is. Features are
1. Does not start and is not frobable until the mechanism weight is put on the clock by tool frobbing the chains with the weight
2. Pendulum works
3. Door opens
4. Bird comes out
5. Bird calls out the hours
6. Bird goes back inside
7. Door shuts
8. Clock becomes frobable
9. Frobbing the clock advances the hour hand one hour, the minute hand goes to 12, and the clock becomes unfrobable until the cuckoo completes its cycle.
Oh, and it keeps accurate time too ... in theory ... I still need to test that bit by starting it up and going away for an hour.
Whew! I ended up needing all 10 NVRelayTraps on the cuckoo clock object plus a few more to get it to work!! So I created a grandparent archetype, a parent archetype, and the concrete child so as to have 12 script slots.
This really was a task for a custom script, but me no speakee C++.
Le MAlin 76 on 11/8/2015 at 16:43
This technic can apply chime of fifteen minutes and hours for big clock with bells ?
LarryG on 11/8/2015 at 18:07
Chiming on the quarter, half, three quarter, and full hours is easy. The hard part was the coordination of the cuckoo. All of the difficulties were with the clockwork mechanics and not with the sounds. To do the sounds all you need are NVRelayTrap timers for when you want the sounds to play and appropriate qvars for how many times you want the chimes to sound. If you want a distinct bells for the quarter hour and half hour, then I would have one qvar that went from 0 to 3 and three traps (for 1, 2, and 3, but none for 0) which would then initiate the chime when the qvar changed. So that qvar would need to be incremented every 15 minutes by its timer [using =(qvar+1)%4=qvar]. Another qvar would count the hours [using =(qvar%12)+1=qvar] and one trap would trigger the hourly chimes using NVRelayTrapRepeat=qvar to get the right number of the chimes. If you want the quarter hour to be 1 chime, the half 2, and 45 minutes to be 3 of that special bell, then you would need a similar use of NVRelayTrapRepeat=qvar for those. That's the broad brush strokes. The details are left to you.