Friday, June 16, 2006
And here are the power ups (at least for now). From left to right we have:
- Health Pack - Restores player health, to a maximum of 100%. Shiny, slowly rotating sphere.
- Berserker Pack - Makes the player "berserk" for a brief period. When berserk, a player is invulnerable, and delivers a mighty one-two punch to any monster he touches (doing as much damage as 10 bullets). Notably, the player cannot damage insubstantial creatures (such as Wraiths and Poltergeists) with a berserker punch. Could be a problem, as the player could be left with a concentration of fast, hard to kill monsters after he comes down from his berserker rage. Translucent black sphere with red-black particle effect.
- Grenade Pack - Gives the player a Holy Hand Grenade. When used (via chat command), it acts as a smart bomb that destroys all monsters within range (about 10 meters) without damaging players. Modeled after the Holy Hand Grenade of Antioch from Monty Python's Search for the Holy Grail by Will Webb (who is also acting as beta tester, brainstormer, and general sounding board for the project). Thanks, Will!
All told, the power up system came together surprisingly quickly. The chat damage system used by the monsters proved to be very easy to expand to include power ups. Currently, monsters deliver damage by saying the damage and the key of the intended recipient. If a player HUD hears the key of the player, it knows to apply the indicated damage to the life total.
Given that system, making health packs was a snap. The packs simply deliver negative damage, effectively increasing the life total of the target. The other two required a couple of extra if-thens. If the damage total is a specific amount (512 for the Berserker Pack, 513 for the Grenade Pack), the HUD knows to bypass the damage system and trigger a specialty power up routine instead. It should be easy enough to add other power ups as they occur to me.
A few different people have suggested that I make an invisibility pack. The way to do this would be to broadcast a false key to the central server when it calls for a roll call. The monsters will only seek players whose keys are listed on the active roll call list (which is broadcast every 6 seconds, currently). The power up could trigger a roll call immediately, then tell the HUD to broadcast a nonsense key. This would have the result of keeping all the monsters active (the server kills them off if there are no keys on the roll call list), but unable to find any players to hunt. For a single player game, that's fine. The player would just have a bunch of stationary targets to shoot at. But for a multiplayer game, the power up would effectively be a "screw your fellow players" button. All of the monsters currently seeking the invisible player would suddenly go after the nearest visible players, instead. Given that this is nominally a cooperative game (players vs. the monsters), this is a sub-optimal result. I'll keep it in mind, but I'm thinking invisibility won't be an option any time soon.
I forgot to detail how the power ups are dispensed. As mentioned before, they have a small, random chance of being released every time a monster is rezzed. As such, more power ups are dispensed when more players are in game. Seems fair, given that the monster rate is also increased.
The power ups are rezzed from the same dispensers as the monsters. They are initially invisible. Each dispenser is turned such that its positive-X direction points toward the center of the arena. The dispenser knows to rez monsters to match this direction. This gives the best chance of rezzing the monster facing (at least generally) towards the players. (Mostly because it looks a bit silly to have the monster appear with its back to you, only to laboriously turn around as it bumbles toward you.) Now, on rez, the invisible power up checks its current X direction, and moves a random distance (from 2 to 12 meters, in one meter increments) along that same vector.
Then it parks itself and waits for the next player roll call. Once a player list is received, it reveals itself (turning visible, turning on particles, etc.) and waits for an avatar collision. If 60 seconds pass, it disappears. But if an avatar whose key is on the active player list collides with it before that time, it fires off its code string, plays a little power up sound effect, and vanishes. And, voila, we have randomly appearing power ups.
My next task is to finalize the HUD itself. Right now, it has functionality to change player status: dead/out-of-play or alive/in-play. It can also track health, and arm/disarm the gun when entering or leaving play. Ultimately, my plan is to tie the HUD into the teleport system that brings players in and out of the garage. The HUD will automatically switch to "live" mode when the player enters. This will signal the HUD to arm the gun, start the play timer (there is no score, only an elapsed survival time), and begin to call for monsters. When the player dies, the HUD will deactivate and summon a teleporter device to leave the arena. (He can also use the exit door to teleport out without dying.) In either case, the play timer will be stopped, and the timer will broadcast the elapsed time to a scorecard device somewhere. Honestly, the high score system is my lowest priority right now.
I'm still tinkering with the design, but I know the HUD will need three different readouts: Health (percentage), Elapsed Time (in minutes and seconds), and Grenade Count. As easy as it would be to work in llSetText, I think I'm going to have to use a prim numbering system. I've found that llSetText in a HUD can be unpredictable and hard to format, since it changes sizes based on the screen resolution (or, rather, doesn't change size, but the HUD and client changes size around it). It might be possible to come up with a scheme that allows for differing sizes of floating text, but it would be difficult. At the moment, I'm leaning towards a retro-styled rolling number scheme, with lots of brass and copper toned fittings around it. I guess we'll see if my artistic skills are up to the task.