X-From_: ivan@solaris.kala.com Tue Apr 14 03:18:09 1998 From: ivan@solaris.kala.com Date: Tue, 14 Apr 1998 06:28:23 -0400 To: b l a d e s@ spiderwebsoftware . com (Note spaces added to thwart spammers. Remove spaces for valid email address.) Subject: animation approaches that don't work - warnings for the unwary Cc: ivan@solaris.kala.com X-Sun-Charset: US-ASCII I wanted to have an animation sequence at the beginning of a scenario, giving the appearance of a storm on shipboard with lightning and thunder. Easy, I thought. Use a special sequence on the start town, which would contain one area of solid Pits (the black square) for the night, and another with a slice of ship deck and adjacent water. For a lightning flash, just move the party from the night to the ship and back, followed by some boom sounds (sound 5 seems best) for the thunder. Stick in some delays to space out the flashes, and slightly alter the ship deck in different flashes (e.g. have a sailor figure move around, rocks go past in the water, etc.) to give a strobe effect. Stick in a few dialogs to extend the narrative and presto, a nice impressive opening. Oops. BoE doen't do this sort of thing. I've spent quite a bit of time finding approaches that don't work for effects of this kind, and this note is to help others avoid repeating the waste. First, getting into the sequence. In Advanced Town Details you can set a special node which is called whenever the party enters the town. I wrote a few specials of my anination, put the first special in the ADT slot, and tried it out. No animation. Tried entering the town the usual way, and the animation ran. Conclusion: BoE does not call the Town Enter special on scenario startup. I call this a bug, but there you have it. As a workaround, I set the startup location on the night pits and put the animation start special in a ring surrounding the party. Changed the startup text dialog so that it suggested that the ship was heaving enough to stagger the party, and left the player to make the first move into the blackness and thus trigger my animation sequence. Had to create a new terrain (with the Pit graphic but unblocked) so the party could step on the special, but this workaround works. It might even be better for the player than simply dumping him into the animation. Now about the sequence itself. The move from night to ship and back does give a nice flash. And it is easy to have crew and rocks move in consecutive flashes as described. But continuous flash/bang/flash/bang... looks like a disco gone berserk. A real storm has delays between flash and bang, and the flashes come at random intervals. I needed a real-time delay special. A 'Delay N milliseconds' sort of thing. There ain't one. The first workaround idea was simply a counting delay loop. Set a SDF to a large value, and loop decrementing it until zero. BoE would take some real time to do the loop, and there's my delay. If I needed longer than the 255 size of a SDF, then a nested loop where the outer loop is decremented once for each 255 times around the inner loop would do. This loop would need to be executed quite a few time in my sequence, with different values in the SDF being decremented. Aha! an obvious subroutine. Have the mainline sequence stick the value corresponding to the desired delay in a defined SDF, and subroutine-call the counting loop. This would eliminate having to repeat the looping code literally in the sequence at each point where I wanted a delay. Guess what: despite the documentation always talking about 'calling' a special, in reality BoE only _jumps_ to the special, and the 'return address' is discarded. To do any complicated effects at all (not just animations) BoE badly needs a true subroutine: "Call Special (and Return Here When Finished)". Yes, this means that the engine would need to maintain a stack, but that's no big deal. Got your ears on, Jeff? So the sequences would have to have the delay loops in line longhand. Code up the first couple of delays, and try it out. And get a nice error message, "A Special may have at most 50 nodes". Mine had only 14 at that point, so what it means is that a special may only _execute_ 50 nodes, including those it executes several times as in my loop. 50 is much too few for a useful delay, much less an entire sequence of them, so delay loops are out. This error message is actually a Good Thing, because it catches erroneous specials that jump to themselves in an infinite loop. But 50 is a little restrictive - 5000 might be better. But best of all would be a 'Reset Node Counter' special node, which would let the writer tell BoE that he knows that a particular special is intentionally longer than the safety limit. Er - Jeff? However, before I discovered the 50 limit, I had spent a little time dealing with the variations in machine speeds. A particular delay loop will run much more quickly on a fast machine. If I put in delay values that give a nice storm on my machine, the result would be intolerably boring on a slower machine and silent-movie jerky on a faster one. So the actual counter values would have to depend on the player's machine speed. How to calibrate this? I wrote a dialog which ran before the storm started, telling the user that the animations need calibration and for him to measure the time (in seconds) between that message and the following one. By putting a standard (uncalibrated) delay between the two messages, I could measure how long in seconds (as reported by the user) corresponded to what value in the counter. Then a little arithmetic would let me scale all the counters to adjust for the host machine speed as calibrated. Nifty. Not quite. To begin with, while there is a Text Response node (which accepts a string and compares it with a desired response), there is no Numeric Response node which accepts a number and sticks the value in a designated SDF. Shouldn't be too hard, because there are built-in numeric dialogs throughout BoE (e.g. Give How Many when passing arrows between members). Jeff? So to get the value back from the user, I actually have to enter a binary tree of dialogs: Did it take less than 32 seconds? Less than 16 seconds? Less than 8 seconds? Less than 12 seconds? Less than 10 seconds? Aha, 9 seconds. This is a pain for all concerned, but does get me a value. Now I have to scale all my delay counter values to normalize them for the host machine. Yes, arithmetic. BoE doesn't do arithmetic either. But it _is_ a Turing machine (albeit with a non-infinite tape), so arithmetic _can_ be coded. (For those unfamiliar with it, a Turing Machine is any computing process which can perform all the computations which can be performed with two bricks and a _very_ long roll of toilet paper. No, really.) Addition and subtraction are relatively easy. Sit in a loop, decrementing one SDF and incrementing another. When the decremented reaches zero, the incremented holds the sum of the two. But scaling needs multiplication and division. I had just begun considering the pain of doing multiplication by repeated addition (and division by repeated subtraction) in the absence of subroutines when I discovered the 50-node limit and abandoned the whole delay-loop idea. Whew! If Jeff ever does put an arithmetic capability in BoE, I suggest that he define a limited number (255?) 32-bit registers rather than SDFs. Leave the SDFs for the Boolean usage they are obviously intended for, and define the arithmetic operations (and the necessary if-thens etc) on the registers instead. And lest you think that all this is quite specialized and would add little to scenarios, consider the following encounter: you have been captured by brigands and for ransom they demand half your gold, however much that is. Writing the special that does that is left as an exercise (remember the 50-node limit, and the 30kGP wealth limit). Email solutions (in the form of trivial scenarios) to me at ig@kala.com. Meanwhile, back at the thunderstorm, I still needed a delay. The documentation makes a big to-do about how it takes a long time to switch between towns. So I thought that I could put in a delay by switching back and forth between apparently identical (all black in my case) towns a few times. So we need a stairway node. The first stairway out is no problem - Generic Stairway type 8 to a scratch town. Of course, that's a one-way trip, whereas I wanted my sequence to continue through the transfer. No problem - set a Town Enter special on the scratch town, and it gets control as soon as the stairway finishes. Put a Sound node on the enter, and try it out: Boom, as expected. Replace the Sound with a Stairway back to my ship town. Have to keep the sequence going through my return too, so added a Town Enter special on the Ship/Night town, with a test sequence on an incremented SDF so I could tell where in my sequence I was supposed to return to. This last was painful, and could probably have been improved by having a large number of duplicate Ship/Night towns and using Variable Town Entry and the incremented SDF, at the expense of making the save file bigger. Try it out. The sequence got to the scratch town OK, but the stairway back gives an error "Cannot change level now". Seems you can't leave town during the Town Enter special. This precludes not only my intended usage, but also such things as the effect of a Variable Town Enter based on party characteristics, i.e. enter this version of a town if the party is flying, and this other one if entered by land. There seems no good reason for the restriction in the likely implementation, so I call this a bug too. Whatever. So what else is there in BoE that takes a noticable amount of time? The only thing I can think of is a sound. Whip out Inside Mac and read up on snd resources, pull up ResEdit, and add a 99th sound to the BoE sound file. The new sound is nothing but a 4-second delay. If it works, I'd need a 1-, 2-, 8-, and 16-second delay too, but later. And unlike all the town-switch kludges, this delay is true wall clock time and would not need to be calibrated. Set up a test with a Play Sound of my new sound, bracketed by a couple of booms. Try it. Boom Boom. No delay in between. Must have screwed up the snd format. Re-read. Looks OK. Try the new sound out in ResEdit, get a nice 'Playing' message that stays on the screen for 4 seconds. Now what? Get sneaky. Open the sound file again, and rather than _add_ the new sound, _replace_ one of the existing sounds. Change the sound numbers in my test case and try again. Boom Boom. Bingo. BoE simply ignores sounds with numbers greater than 98. I've got my delay, at the expense of eliminating an available sound and requiring that my scenario be distributed with a substitute sound file. Now (before Jeff jumps in and explains why I shouldn't do this), the sound file solution is a bad one. Yes, it does give me a delay. But users who install my modified sound file will no doubt forget to put the original one back when they finish my scenario, and will then try to play other scenarios with the modified sound file. And wonder why the game seems to stop for 32 seconds when a particular monster poops or whatever and the scenario tries to use the standard sound I replaced. The solution is to let users supply a custom sound file with each scenario (augmenting rather then replacing the standard one), just as they now can supply a custom graphics file. I can't imagine why Jeff didn't do this in the original BoE - letting the authors define custom noises seems so obviously in keeping with the rest of the editor and game. _And_, I could get my delay. BoE1.1 maybe? And by the way, I'd really like to see a 'Delay N Milliseconds' special node. RESPONSE FROM JEFF VOGEL: I found this to be a fascinating article to read. You see, when I starting writing the editor, I had a very clear, straightforward, well defined idea of what I wanted it to do, and what I wanted to be possible. Then I went out and wrote the thing. As I wrote, some things went over the side (like black and white Exile III type graphics) and some things were added. However, I pretty much stuck with the basic ideas I started with. Yet, had I worked on the editor for a million years, I don't think it ever would have occured to me that someone would have tried to do what you did. It really, honestly amazes me that you made any progress at all. Yes, the editor does have limitations. The lack of the ability to add more sounds, for example. The sad truth is that the whole thing is very compilcated as it is, both as a program and as a system for people to learn. At some point, I felt I had to say "OK. This is enough. People can create a good adventure with this, and, at the same time, it's simple enough for one person's brain to contain it." And, at that point, I rested. Given the editor's limitations, I'm amazed to see the tricks people work with it, and I can't wait to see your scenario (or what you finish of it). By the way, yes, 50 nodes is too little. And no, the special node for town entry is not supposed to be called when the scenario starts. However, there should be a way to have a special encounter happen when the scenario starts. As for queueing special encoutners and having subroutines, I dunno. It seems like a good idea, but the simple way its set up had an appeal as being something a normal person would have a better chance of learning. - Jeff Vogel