Tuesday, May 26, 2009

Sixteen Candles

After our group meeting yesterday, I worked hard on the alignment & PK system for Evidyon and churned out a bunch of new code.  The only things left to do before I can release this update are (1) implement the "Evil Town" where players who go evil and are killed spawn, and (2) do a bunch of testing to make sure everything works.

Eleven
Evil spawn point is implemented.  Rebuilding the editor and going to get started testing.

Whoops, forgot that actor templates need to have an alignment parameter.

Noon
After much testing, the system works great!  The hour counter was more difficult than I anticipated but using GetSystemTime, SystemTimeToFileTime and some hints from RtlTimeToSecondsSince1970, I managed to make it work.  I can use this same system for handling account time, too!

One more thing to do before I release:  put alignment on the player's stats screen.

Four
Back from a long lunch.  Alignment is on the stats screen.  I'd like to add race/class display to the screen also (temporary hack for now, this screen is going to be redone anyway).  Fixed a small bug I found in the server code that caused evil players to register as PKs.

Another cool idea for PKers I wanted to write down:  after a PK, you get a glowing red effect around you for a few minutes (so you're easily identified as a killer!)

3 comments:

Joe M. said...

Karl, you said once that DOTs were messy to code. Why is that, and would this system of time-governed effects solve it? (i.e., we're already updating a character's hp/mp every second with regens, wouldn't it be easy to have DOTs as an enchantment that negatively effects regen?)

Karl said...

DOTs are messy because they are a timed effect as opposed to an immediate one. To make matters worse, they often have multiple targets.

Consider the difference: a "burn" spell with no casting delay has an immediate effect. In pseudocode,

if (playerIsNotBusy()) {
createSFX(spell.sfx);
doSpellEffect(spell.target, spell.effect);
}

As soon as you add in a time delay, you need lists, timers, and validators (what if the target logs off before the spell lands?) to handle the fringe cases. That's not so bad, but consider the following:

I cast a level 5 poison spell on an enemy. Someone else then casts a level 1 poison spell on them as well. Logically, the lower-powered one shouldn't overwrite the higher-powered one, but this leads to further complication: every DOT must have both a type (2 types of poison can't overwrite each other) and power grade, and all of this logic must be hard-coded since there is no parsimonious way to express them in a config file other than to write a script, which isn't particularly well suited to something that can happen dozens of times per second on a well-populated server.

If you go the other route and say no poisons should ever overwrite each other, any decent DOT spell could kill the strongest player in the game without any challenge. Just cast it a bunch of times and stack the effects.


That said, a different way of handling DOTs might work but they won't really feel much like a classic DOT: assign a DOT a "negative regen value" like you were proposing, but have the character simply regenerate his or her regen rate. When the DOT is cast, if the regen rate is higher than the spell's negative regen rate, set the regen rate to be the negative one--otherwise, leave it alone. You'd have to continuously cast a DOT to keep it at full power (makes sense to me...) and wouldn't be able to use other spells, but using one at the start of combat could be helpful.

What do you think?

Joe M. said...

I don't think I understood most (if any!) of that first part, so I'm just going to explain what I had in mind and hope that you haven't already explained why it wouldn't work. :D What I'm thinking is similar to that last bit of yours. This also relies on some assumptions about the enchantment system that may well not hold true. I'd love to work this issue out, though, as I think DOTs are one of the most interesting types of spell that can be had in a game.

My discussion will be HP-only, the same structure could be applied to MP.

(1) Every Character has a regen value that the game applies to his HP every second.

(2) Make a Regen "slot" in the array of possible enchantments that a player can have concurrently. This is simply an enchantment that modifies a player's regen value, either positively or negatively. Let's call these enchantments ROTs (regen over time).
(2a) Since there's only 1 slot, only one ROT at a time could be operative, and we wouldn't have a problem with stacking.
(2a.1) Unless, of course, we want to be able to stack ROTS of the same type up to, say, 3, or stack ROTs of different types, in which case we just need a slot for each type or for the number we wish to stack.(3) Every ROT has a count-down value, which decrements every second (every time regen kicks in, every time the ROT "hits" the player).
(3a) I can see how this step might cause problems, but I might be imagining things. If this would cause problems, let me know: I have some ideas about how they might be worked around.

(4) Every ROT has a "priority" value; if an ROT is cast on a player who is already under the effect of a higher-priority ROT, the lower-priority ROT does not take hold.