Monday, June 21, 2010

A generic system for implementing skills, traits, and item bonuses...

I know the title is a mouthful, but if beyond it is an idea I'm excited about. Like most ideas, it came to me when I was doing something other than programming.

This iteration I'm planning on implementing varying difficulty monsters and hopefully items of varying strengths. In my previous post, I suggested using a "trait" system to implement some of the monster characteristics. For example, one wolf might be "fast"-er or "strong"-er than another, trading that off against some additional base attributes. In my head I hoped to sneak in items with enchantments; a sword that could make you tougher or a staff that made you case spells better.

It came to me that both of these use cases are very similar to the skill tree attributes I implemented last iteration. Those skills could increase base stats or allow new skills. As a programmer, when I hear of three different implementations of an idea, I get an itch to make a generic framework or factor out the pattern or something.

The crux of the idea is that all of these ideas can be implemented as a system of tags and values. For example, a skill that increases the characters base hitpoints by 5 could be:

m_player["HPBonus"] = 5;

Then to calculate the number of hitpoints in this simple example one can do something like:

// Player
int GetSkillTags(string tagName)
{
    int total = 0;
    foreach(ISkill s in Skills)
    {
         if(s.attributes.Contains(tagName))
             total += s.attributes[tagName];
    }

    foreach(IItem i in Equipment)
    {
         if(i.attributes.Contains(tagName))
             total += s.attributes[tagName];
    }
    return total;
}

// Monster
int GetSkillTags(string tagName)
{
    int total = 0;
    foreach(Dictionary<string, int> d in Traits)
    {
         if(d.Contains(tagName))
             total += d[tagName];
    }
    return total;
} 

Once I implement a given skill or trait checking in one section of the game engine using this API, creating a new skill, item attribute, or monster trait to do the same thing is trivial. Also, since checking if a dictionary contains a key is fast, it should be efficient as well.

Thoughts?

Sunday, June 20, 2010

MEF is now cross platform friendly, kinda

So in February I noted some attempts at using MEF and the disappointment that it was Windows only at the time. MEF in short is a way to break up your C# application into smaller pieces that are loosely connected.

Since multiple of the tasks I have for iteration 9 involve refactoring, I figured I'd take a look at MEF again and see if it is in better shape. The short answer answer is that it works with mono, but only in their development branch. A kind fellow in the mono IRC channel pointed me to a copy he built of System.ComponentModel.Composition.dll that I could use. It works under Windows, Mac, and Linux.

In the next release of Mono it seems likely that this will be built into the .NET 4 client profile, but packaging a single assembly along with your application seems to be an easy solution for now.

Once I break up magecrawl into smaller components, I'm planning on making another post describing MEF and showing how I used it.

Saturday, June 19, 2010

Iteration 9 - "Levels" and polish

So, I haven't had the time I wanted to work on magecrawl this week, but the ideas keep coming. I have over 50 major/minor/bug fixes I wish I could get into this iteration. Before an iteration, I try to come up with a "theme" tying together what I hope to accomplish in the next few months. This iteration (9), the theme is "Levels and polish". It also may be the last iteration before I move onto the next stage of my development plan.

The "levels" in the theme refer to varying levels of difficulty in challenges, not different floors connected by stairs (which I already have). For example, the wolf that attacks you at the very beginning of the game should be different than the wolf pack that hounds you a few levels later when you have better equipment and skills. The quality of treasure should also vary based on depth.

My current idea is to create an engine that creates these monsters and items on the fly. For example, asking for a level 3 monster could create a fast (+1 lv, 25% faster), strong (+1 lv 25% dmg) base kobold (base creature). Or it could create a experience goblin (+2 stat levels). A combination of traits (such as fast, strong, special abilities) and stat levels (more hp, etc). A similar system would exist for items, so creating a level 5 sword could return a masterwork wooden sword or a crude iron sword. Each quality grade and material would contribute to the effective level of the item, along with any enchantments.

I think this system should help me balance magecrawl's difficult curve. Manually creating monster and item stats based on paper calculations is difficult and time consuming.

In addition to "levels", I have a huge number of polish issues that I'd like to implement. They range from the status effect ideas I listed here to internal refactoring to improving monster AI.

As I mentioned, this might be the last "iteration" of magecrawl. I think I laid this out on some other post, but finding it escaped me. The idea of iterations are to fill out functionality needed in the game engine and GUI needed for a "real" game. After I feel like I have enough functionality, I'm planning on moving to "slices". Slice would be a portion of the full planned game, from top to bottom. For example, the first slice could be implementing the entire fire skill tree and all its spells, and flushing out sections of the dungeon. The game itself would be a full (albeit shallow) game. After releasing that, I'd take another slice of say the water tree and more dungeon sections.

Well I should get off to coding...

Saturday, June 12, 2010

Status Effects 2.0

The initial implementation of status effects, the one you may have seen in the first three tech demos of magecrawl, was almost an exact reimplementation of the model used in crawl. Effects when cast have a length (in turns or ticks or whatever) at which time they disappear. Some effects are positive, some are negative. If you have a positive effect (say haste) that you want to have on you permanently, you need to recast it was it expires. Some games automate this step, but in the end it is the same model.

While simple and easy, I don't really like this model for magecrawl. Mages in books and legend sometimes were wrapped in layers of magical protection, and the idea that you need to stop walking every five minutes to recast all your buffs seems silly. I'm stealing a page from dragon age, and separating effects into two orthogonal categories: length and type.

Sustained effects (long term) are ones that persist until canceled, however have a continuing cost. My current implementation reduces the player's maximum MP by an amount for each effect that persists. This provides a nice trade off; keep no effects up and have access to your entire mana pool, keep some up and have only part, or keep a bunch up and be able to maybe only cast one spell.

Temporary effects are effects that use the traditional effect model of a deadline time and no additional cost while in effect. Unlike sustained effects, where having a sustained negative effect doesn't make sense, temporary effects can be positive or negative in nature. Positive effects that are too powerful or come from items could be temporary. 

Another status effect idea I had, which I haven't implemented yet, are school specific debufs for common attack spells. An simple example would be the school of fire. Fire attack spells could have a chance to apply a "burning" negative status effect upon targets. Some spells (like sticky flames) might have a higher chance to apply effects than others. In the case of burning, it would do damage over time to the target. If attacked by any water or ice damage damage, the effect would end early. 

Some effects I have in mind would reduce damage taken by some schools and increase others (e.g. being frozen reduces fire damage but a good earth spell would shatter the target nicely).

Effects might be a trait added on by skills in the skill tree, so the initiates fireblast might do damage but not be powerful enough to set things on fire. It also brings up the possibility of branches in the skill tree, where some could specialize in damage over time or status effects while others specialize in raw power.

I think status effects will be on the areas I focus on for this iteration. I think it can be used to bring out a lot of flavor and interesting choices in magecrawl.

Wednesday, June 9, 2010

What I've been up to the last few weeks...


In the age of please rob me and other such sites that make it easy to find people's home location, stating online that I was going to take a 10 day trip out of the country didn't seem like a good idea. Hence the "things are going to be crazy" excuse. My trip to Russia was wonderful if your are curious.

Given the 12 hour flight both ways, I did get some hacking on magecrawl done. I refactored and redesigned how status effects work. I'll get around to writing it up as a long post hopefully this week.

Now that I am back, and mostly recovered from jet lag, more forward progress on magecrawl seems likely. I have an idea list a mile long I need to enter into fogbugz, and I need to come up with a high level plan of what I'm going to accomplish this iteration.