I moved to a new URL! Check it out!

Doodle Post

Image


Some more notes from my Dev Days notebook.

Doodle Post

Image


Valve gave us a notebook at Dev Days so I drew some stuff in it.

Dev Log: Areas of Effect

Dev Log: Areas of Effect
My most recent development in my game's crazy system is implementing an area of effect. Right now areas of effect can keep track of any Entities that enter them with a "Combatant" component. I'm using the Combatant component to keep track of anything in the scene that can either deal or receive damage in some way. Here's an area of effect that increases the player's "TimeRate" stat:

Image


When the TimeRate stat is modified the player's weapons will fire faster, and anything else that depends on that stat is also changed. I think the way I have it set up right now any sort of regeneration status will be effected by the TimeRate, so if I had a health regeneration modifier then it would be applied faster than normal.

The way I have things set up right now is that all entities in the scene that are combatants have some sort of core stats table. These stats determine all kinds of things for each of those entities, and things like areas of effect can just apply modifiers to those stats and hopefully the entities will react accordingly. This is all totally new stuff to me and I'm learning a lot as I go, but progress is kinda slow as the more I learn about this stuff the more I know about what I could be doing better -- so I end up scrapping stuff and writing it better as I realize it.

Not quite as fast as a game jam scenario, but I don't want to code myself into a corner when it comes to making a system like this!

Dev Log: More Data Driving

Dev Log: More Data Driving
How far is too far when it comes to making data driven code? Right now I'm wrestling with this question. I have a bunch of stuff defined in my xml which is all well and good for some parts of this game, but then I came to think of spells and abilities and how to make them data driven... but I think to truly do that would require some sort of scripting!

I was looking into Lua or using some form of Python for scripting in my game, but ultimately I've decided to hold off on that sort of thing. It sounds really fun, especially when I start to consider the modding possibilities of a game that uses a lot of scripting and data driven stuff... but it feels like a large burden to take on very early on in a project (even though getting Lua set up in C# is incredibly easy!)

As I slowly pick away at these systems everything is becoming a little bit more clear with each day of work. I'm still learning the ins and outs of C# and the power of reflection. One thing I started looking into today is custom attributes. It seems like a powerful way to combine data driven and engine driven stuff into one. I think by using custom attributes I could define a lot of data right in a class itself, and I would be mostly doing this in instances where I wouldn't want this kind of data exposed to the end user.

For example right now I have my stat class set up with a Dictionary where the enum StatType is the key, and a float is the value. This is all fine, but it means that in the constructor of my stat manager class I have to define all of those stats by doing Add(StatType, value) a bunch of times. An alternative way to do this might be to define the stats as just floats in the class itself, and apply custom attributes to each one like [Stat] or [CoreStat] or [DerivedStat]. I'm going to spend a little time experimenting with this stuff and we'll see how it turns out!

Doodle Post

Image

Dev Log: Fun with Stats

Dev Log: Fun with Stats
I haven't made much progress on my system to set up triggers and actions for Enchantments, but I did make some progress on my player stats system. I coded up a pretty generic Stat class that allows StatMods to be applied. Check it out!
class Stat {

public float BaseValue;
public string Name;

public bool Capped;
public float Cap;

public List<StatMod> StatMods { get; private set; }

bool needsUpdate = false;
float cachedValue;

public Stat(string name, float basevalue = 0) {
Name = name;
BaseValue = basevalue;
Cap = BaseValue * 2;
StatMods = new List<StatMod>();
cachedValue = basevalue;
}

public Stat(float basevalue) : this("", basevalue) { }

public StatMod AddMod(StatMod mod) {
StatMods.Add(mod);
needsUpdate = true;
return mod;
}

public StatMod RemoveMod(StatMod mod) {
StatMods.Remove(mod);
needsUpdate = true;
return mod;
}

public void ClearMods() {
StatMods.Clear();
cachedValue = BaseValue;
}

public float FinalValue {
get {
if (needsUpdate) {
float v = BaseValue;
var m = 1;
foreach (var s in StatMods) {
v += s.Add;
}
foreach (var s in StatMods) {
v += BaseValue * s.Multiply;
}
cachedValue = v;
needsUpdate = false;
}
if (Capped && cachedValue > Cap) return Cap;
return cachedValue;
}
}

public static implicit operator float(Stat stat) {
return stat.FinalValue;
}


}

class StatMod {
public float Multiply = 1;
public float Add;

public StatMod(float add = 0, float multiply = 0) {
Multiply = multiply;
Add = add;
}
}
I'll probably add this into the Utility folder of Otter at some point. Basically you can make a stat, like new Stat(10), then apply modifiers and get the final modified value back. You can also treat it as a float and it will spit out the modified value as well.

Multiply might not work the way you think at first though. Setting Multiply to 1 in a StatMod actually means to Add 100% of the stat to itself. For example, a stat of 100 with a multiplier mod of 1 will calculate as 200. It's as if the mod is saying "BaseStat +100%" when you set it to 1. So 0.5f would be interpreted as +50%, -0.5f would be -50%, and so on.

Modifiers will always be applied with addition, then multiplication. For example if a stat had a base value of 100, and then you apply a modifier with Add set to 50, and then another modifier with Multiply set to 1, then the final result will be 300. It applies the +50, and then the +100%. It doesn't matter which order they're applied in.

Now I'll get back to work on my dumb trigger and action system that I have no idea how to implement right now, yahoo!